diff options
author | Marek Gradzki <mgradzki@cisco.com> | 2016-05-30 14:51:14 +0200 |
---|---|---|
committer | Marek Gradzki <mgradzki@cisco.com> | 2016-06-06 12:52:18 +0000 |
commit | 815f6da443f7032704908aa21f232bd05e89acb6 (patch) | |
tree | ff2c8b79cbd8d8baa35a9aeb893513f0ebec4a1f /v3po/v3po2vpp/src/main/java/io | |
parent | dffb11e30ee1bf6bbfdd1ba1a5ce9d0cb636586a (diff) |
Implementation of the new vlan model.
Missing features that will be added in subsequent commits:
- initializers update
- unit test update
- postman collection update
Change-Id: Iff01f6f9b4347261a504fe1a1d7840060cae367f
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
Diffstat (limited to 'v3po/v3po2vpp/src/main/java/io')
16 files changed, 1145 insertions, 576 deletions
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/initializers/InterfacesInitializer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/initializers/InterfacesInitializer.java index db3d540c7..a41a6e87b 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/initializers/InterfacesInitializer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/initializers/InterfacesInitializer.java @@ -34,20 +34,20 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanGpeVni; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.EthernetBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2Builder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.SubInterfaceBuilder; +// import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.SubInterfaceBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.TapBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VhostUserBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VxlanBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VxlanGpeBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.VlanTagRewriteBuilder; +// import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.VlanTagRewriteBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Ethernet; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.L2; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.SubInterface; +// import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.SubInterface; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Tap; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VhostUser; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Vxlan; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VxlanGpe; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.l2.VlanTagRewrite; +// import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.l2.VlanTagRewrite; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.Interconnection; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBased; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBasedBuilder; @@ -122,10 +122,11 @@ public class InterfacesInitializer extends AbstractDataTreeConverter<InterfacesS setL2(augmentBuilder, l2); } - final SubInterface subInterface = vppIfcAugmentation.getSubInterface(); - if(subInterface != null) { - setSubinterface(augmentBuilder, subInterface); - } + // FIXME new vlan model +// final SubInterface subInterface = vppIfcAugmentation.getSubInterface(); +// if(subInterface != null) { +// setSubinterface(augmentBuilder, subInterface); +// } final Ethernet ethernet = vppIfcAugmentation.getEthernet(); if(ethernet != null) { @@ -140,32 +141,33 @@ public class InterfacesInitializer extends AbstractDataTreeConverter<InterfacesS return builder.build(); } - private static void setSubinterface(final VppInterfaceAugmentationBuilder augmentBuilder, - final SubInterface subInterface) { - final SubInterfaceBuilder subIfcBuilder = new SubInterfaceBuilder(); - - if(subInterface.isDefaultSubif() != null) { - subIfcBuilder.setDefaultSubif(subInterface.isDefaultSubif()); - } - if(subInterface.isExactMatch() != null) { - subIfcBuilder.setExactMatch(subInterface.isExactMatch()); - } - if(subInterface.isMatchAnyInnerId() != null) { - subIfcBuilder.setMatchAnyInnerId(subInterface.isMatchAnyInnerId()); - } - if(subInterface.isMatchAnyOuterId() != null) { - subIfcBuilder.setMatchAnyOuterId(subInterface.isMatchAnyOuterId()); - } - - subIfcBuilder.setIdentifier(subInterface.getIdentifier()); - subIfcBuilder.setInnerId(subInterface.getInnerId()); - subIfcBuilder.setNumberOfTags(subInterface.getNumberOfTags()); - subIfcBuilder.setOuterId(subInterface.getOuterId()); - subIfcBuilder.setSuperInterface(subInterface.getSuperInterface()); - subIfcBuilder.setVlanType(subInterface.getVlanType()); - - augmentBuilder.setSubInterface(subIfcBuilder.build()); - } + // FIXME vlan new modele +// private static void setSubinterface(final VppInterfaceAugmentationBuilder augmentBuilder, +// final SubInterface subInterface) { +// final SubInterfaceBuilder subIfcBuilder = new SubInterfaceBuilder(); +// +// if(subInterface.isDefaultSubif() != null) { +// subIfcBuilder.setDefaultSubif(subInterface.isDefaultSubif()); +// } +// if(subInterface.isExactMatch() != null) { +// subIfcBuilder.setExactMatch(subInterface.isExactMatch()); +// } +// if(subInterface.isMatchAnyInnerId() != null) { +// subIfcBuilder.setMatchAnyInnerId(subInterface.isMatchAnyInnerId()); +// } +// if(subInterface.isMatchAnyOuterId() != null) { +// subIfcBuilder.setMatchAnyOuterId(subInterface.isMatchAnyOuterId()); +// } +// +// subIfcBuilder.setIdentifier(subInterface.getIdentifier()); +// subIfcBuilder.setInnerId(subInterface.getInnerId()); +// subIfcBuilder.setNumberOfTags(subInterface.getNumberOfTags()); +// subIfcBuilder.setOuterId(subInterface.getOuterId()); +// subIfcBuilder.setSuperInterface(subInterface.getSuperInterface()); +// subIfcBuilder.setVlanType(subInterface.getVlanType()); +// +// augmentBuilder.setSubInterface(subIfcBuilder.build()); +// } private static void setEthernet(final VppInterfaceAugmentationBuilder augmentBuilder, final Ethernet ethernet) { final EthernetBuilder ethernetBuilder = new EthernetBuilder(); @@ -193,15 +195,16 @@ public class InterfacesInitializer extends AbstractDataTreeConverter<InterfacesS } } - final VlanTagRewrite vlanTagRewrite = l2.getVlanTagRewrite(); - if(vlanTagRewrite != null) { - final VlanTagRewriteBuilder vlanTagRewriteBuilder = new VlanTagRewriteBuilder(); - vlanTagRewriteBuilder.setFirstPushed(vlanTagRewrite.getFirstPushed()); - vlanTagRewriteBuilder.setRewriteOperation(vlanTagRewrite.getRewriteOperation()); - vlanTagRewriteBuilder.setTag1(vlanTagRewrite.getTag1()); - vlanTagRewriteBuilder.setTag2(vlanTagRewrite.getTag2()); - l2Builder.setVlanTagRewrite(vlanTagRewriteBuilder.build()); - } + // FIXME new vlan model +// final VlanTagRewrite vlanTagRewrite = l2.getVlanTagRewrite(); +// if(vlanTagRewrite != null) { +// final VlanTagRewriteBuilder vlanTagRewriteBuilder = new VlanTagRewriteBuilder(); +// vlanTagRewriteBuilder.setFirstPushed(vlanTagRewrite.getFirstPushed()); +// vlanTagRewriteBuilder.setRewriteOperation(vlanTagRewrite.getRewriteOperation()); +// vlanTagRewriteBuilder.setTag1(vlanTagRewrite.getTag1()); +// vlanTagRewriteBuilder.setTag2(vlanTagRewrite.getTag2()); +// l2Builder.setVlanTagRewrite(vlanTagRewriteBuilder.build()); +// } augmentBuilder.setL2(l2Builder.build()); } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterconnectionWriteUtils.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterconnectionWriteUtils.java new file mode 100644 index 000000000..1463ca9e5 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterconnectionWriteUtils.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.interfaces; + +import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Objects.requireNonNull; + +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; +import io.fd.honeycomb.v3po.translate.write.WriteContext; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import java.util.concurrent.CompletionStage; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.Interconnection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBased; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.XconnectBased; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.SwInterfaceSetL2Bridge; +import org.openvpp.jvpp.dto.SwInterfaceSetL2BridgeReply; +import org.openvpp.jvpp.dto.SwInterfaceSetL2Xconnect; +import org.openvpp.jvpp.dto.SwInterfaceSetL2XconnectReply; +import org.openvpp.jvpp.future.FutureJVpp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility class providing Interconnection CUD support. + */ +final class InterconnectionWriteUtils { + + private static final Logger LOG = LoggerFactory.getLogger(InterconnectionWriteUtils.class); + + private final FutureJVpp futureJvpp; + private final NamingContext interfaceContext; + private final NamingContext bridgeDomainContext; + + InterconnectionWriteUtils(@Nonnull final FutureJVpp futureJvpp, + @Nonnull final NamingContext interfaceContext, + @Nonnull final NamingContext bridgeDomainContext) { + this.futureJvpp = requireNonNull(futureJvpp, "futureJvpp should not be null"); + this.interfaceContext = requireNonNull(interfaceContext, "interfaceContext should not be null"); + this.bridgeDomainContext = requireNonNull(bridgeDomainContext, "bridgeDomainContext should not be null"); + } + + void setInterconnection(final InstanceIdentifier<? extends DataObject> id, final int swIfIndex, + final String ifcName, + final Interconnection ic, final WriteContext writeContext) + throws VppApiInvocationException, WriteFailedException { + if (ic == null) { // TODO in case of update we should delete interconnection + LOG.trace("Interconnection is not set. Skipping"); + } else if (ic instanceof XconnectBased) { + setXconnectBasedL2(swIfIndex, ifcName, (XconnectBased) ic, writeContext); + } else if (ic instanceof BridgeBased) { + setBridgeBasedL2(swIfIndex, ifcName, (BridgeBased) ic, writeContext); + } else { + // FIXME how does choice extensibility work + // FIXME it is not even possible to create a dedicated customizer for Interconnection, since it's not a DataObject + // FIXME we might need a choice customizer + // THis choice is already from augment, so its probably not possible to augment augmented choice + LOG.error("Unable to handle Interconnection of type {}", ic.getClass()); + throw new WriteFailedException(id, "Unable to handle Interconnection of type " + ic.getClass()); + } + } + + private void setBridgeBasedL2(final int swIfIndex, final String ifcName, final BridgeBased bb, + final WriteContext writeContext) + throws VppApiInvocationException { + + LOG.debug("Setting bridge based interconnection(bridge-domain={}) for interface: {}", bb.getBridgeDomain(), + ifcName); + + String bdName = bb.getBridgeDomain(); + + int bdId = bridgeDomainContext.getIndex(bdName, writeContext.getMappingContext()); + checkArgument(bdId > 0, "Unable to set Interconnection for Interface: %s, bridge domain: %s does not exist", + ifcName, bdName); + + byte bvi = bb.isBridgedVirtualInterface() + ? (byte) 1 + : (byte) 0; + byte shg = bb.getSplitHorizonGroup().byteValue(); + + final CompletionStage<SwInterfaceSetL2BridgeReply> swInterfaceSetL2BridgeReplyCompletionStage = futureJvpp + .swInterfaceSetL2Bridge(getL2BridgeRequest(swIfIndex, bdId, shg, bvi, (byte) 1 /* enable */)); + final SwInterfaceSetL2BridgeReply reply = + TranslateUtils.getReply(swInterfaceSetL2BridgeReplyCompletionStage.toCompletableFuture()); + + if (reply.retval < 0) { + LOG.warn("Failed to update bridge based interconnection flags for: {}, interconnection: {}", ifcName, bb); + throw new VppApiInvocationException("swInterfaceSetL2Bridge", reply.context, reply.retval); + } else { + LOG.debug("Bridge based interconnection updated successfully for: {}, interconnection: {}", ifcName, bb); + } + } + + private SwInterfaceSetL2Bridge getL2BridgeRequest(final int swIfIndex, final int bdId, final byte shg, + final byte bvi, final byte enabled) { + final SwInterfaceSetL2Bridge swInterfaceSetL2Bridge = new SwInterfaceSetL2Bridge(); + swInterfaceSetL2Bridge.rxSwIfIndex = swIfIndex; + swInterfaceSetL2Bridge.bdId = bdId; + swInterfaceSetL2Bridge.shg = shg; + swInterfaceSetL2Bridge.bvi = bvi; + swInterfaceSetL2Bridge.enable = enabled; + return swInterfaceSetL2Bridge; + } + + private void setXconnectBasedL2(final int swIfIndex, final String ifcName, final XconnectBased ic, + final WriteContext writeContext) + throws VppApiInvocationException { + String outSwIfName = ic.getXconnectOutgoingInterface(); + LOG.debug("Setting xconnect based interconnection(outgoing ifc={}) for interface: {}", outSwIfName, ifcName); + + int outSwIfIndex = interfaceContext.getIndex(outSwIfName, writeContext.getMappingContext()); + checkArgument(outSwIfIndex > 0, + "Unable to set Interconnection for Interface: %s, outgoing interface: %s does not exist", + ifcName, outSwIfIndex); + + final CompletionStage<SwInterfaceSetL2XconnectReply> swInterfaceSetL2XconnectReplyCompletionStage = + futureJvpp + .swInterfaceSetL2Xconnect(getL2XConnectRequest(swIfIndex, outSwIfIndex, (byte) 1 /* enable */)); + final SwInterfaceSetL2XconnectReply reply = + TranslateUtils.getReply(swInterfaceSetL2XconnectReplyCompletionStage.toCompletableFuture()); + + if (reply.retval < 0) { + LOG.warn("Failed to update xconnect based interconnection flags for: {}, interconnection: {}", ifcName, ic); + throw new VppApiInvocationException("swInterfaceSetL2Xconnect", reply.context, reply.retval); + } else { + LOG.debug("Xconnect based interconnection updated successfully for: {}, interconnection: {}", ifcName, ic); + } + } + + private SwInterfaceSetL2Xconnect getL2XConnectRequest(final int rxIfc, final int txIfc, + final byte enabled) { + + final SwInterfaceSetL2Xconnect swInterfaceSetL2Xconnect = new SwInterfaceSetL2Xconnect(); + swInterfaceSetL2Xconnect.enable = enabled; + swInterfaceSetL2Xconnect.rxSwIfIndex = rxIfc; + swInterfaceSetL2Xconnect.txSwIfIndex = txIfc; + return swInterfaceSetL2Xconnect; + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/L2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/L2Customizer.java index ccb54b3c4..c4c6ecc0a 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/L2Customizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/L2Customizer.java @@ -16,30 +16,19 @@ package io.fd.honeycomb.v3po.translate.v3po.interfaces; -import static com.google.common.base.Preconditions.checkArgument; - import com.google.common.base.Optional; import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; -import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils; import io.fd.honeycomb.v3po.translate.write.WriteContext; import io.fd.honeycomb.v3po.translate.write.WriteFailedException; -import java.util.concurrent.CompletionStage; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.Interconnection; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBased; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.XconnectBased; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.jvpp.dto.SwInterfaceSetL2Bridge; -import org.openvpp.jvpp.dto.SwInterfaceSetL2BridgeReply; -import org.openvpp.jvpp.dto.SwInterfaceSetL2Xconnect; -import org.openvpp.jvpp.dto.SwInterfaceSetL2XconnectReply; import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,13 +37,13 @@ public class L2Customizer extends FutureJVppCustomizer implements ChildWriterCus private static final Logger LOG = LoggerFactory.getLogger(L2Customizer.class); private final NamingContext interfaceContext; - private final NamingContext bridgeDomainContext; + private final InterconnectionWriteUtils icWriteUtils; public L2Customizer(final FutureJVpp vppApi, final NamingContext interfaceContext, final NamingContext bridgeDomainContext) { super(vppApi); this.interfaceContext = interfaceContext; - this.bridgeDomainContext = bridgeDomainContext; + this.icWriteUtils = new InterconnectionWriteUtils(vppApi, interfaceContext, bridgeDomainContext); } @Nonnull @@ -100,112 +89,11 @@ public class L2Customizer extends FutureJVppCustomizer implements ChildWriterCus // TODO implement delete (if possible) } - private void setL2(final InstanceIdentifier<L2> id, final int swIfIndex, final String ifcName, final L2 vppL2, + private void setL2(final InstanceIdentifier<L2> id, final int swIfIndex, final String ifcName, final L2 l2, final WriteContext writeContext) throws VppApiInvocationException, WriteFailedException { LOG.debug("Setting L2 for interface: {}", ifcName); // Nothing besides interconnection here - setInterconnection(id, swIfIndex, ifcName, vppL2, writeContext); - } - - private void setInterconnection(final InstanceIdentifier<L2> id, final int swIfIndex, final String ifcName, - final L2 vppL2, final WriteContext writeContext) - throws VppApiInvocationException, WriteFailedException { - Interconnection ic = vppL2.getInterconnection(); - if (ic instanceof XconnectBased) { - setXconnectBasedL2(swIfIndex, ifcName, (XconnectBased) ic, writeContext); - } else if (ic instanceof BridgeBased) { - setBridgeBasedL2(swIfIndex, ifcName, (BridgeBased) ic, writeContext); - } else { - // FIXME how does choice extensibility work - // FIXME it is not even possible to create a dedicated customizer for Interconnection, since it's not a DataObject - // FIXME we might need a choice customizer - // THis choice is already from augment, so its probably not possible to augment augmented choice - LOG.error("Unable to handle Interconnection of type {}", ic.getClass()); - throw new WriteFailedException(id, "Unable to handle Interconnection of type " + ic.getClass()); - } - } - - private void setBridgeBasedL2(final int swIfIndex, final String ifcName, final BridgeBased bb, - final WriteContext writeContext) - throws VppApiInvocationException { - - LOG.debug("Setting bridge based interconnection(bridge-domain={}) for interface: {}", - bb.getBridgeDomain(), ifcName); - - String bdName = bb.getBridgeDomain(); - - int bdId = bridgeDomainContext.getIndex(bdName, writeContext.getMappingContext()); - checkArgument(bdId > 0, "Unable to set Interconnection for Interface: %s, bridge domain: %s does not exist", - ifcName, bdName); - - byte bvi = bb.isBridgedVirtualInterface() - ? (byte) 1 - : (byte) 0; - byte shg = bb.getSplitHorizonGroup().byteValue(); - - final CompletionStage<SwInterfaceSetL2BridgeReply> swInterfaceSetL2BridgeReplyCompletionStage = getFutureJVpp() - .swInterfaceSetL2Bridge(getL2BridgeRequest(swIfIndex, bdId, shg, bvi, (byte) 1 /* enable */)); - final SwInterfaceSetL2BridgeReply reply = - TranslateUtils.getReply(swInterfaceSetL2BridgeReplyCompletionStage.toCompletableFuture()); - - if (reply.retval < 0) { - LOG.warn("Failed to update bridge based interconnection flags for: {}, interconnection: {}", ifcName, - bb); - throw new VppApiInvocationException("swInterfaceSetL2Bridge", reply.context, reply.retval); - } else { - LOG.debug("Bridge based interconnection updated successfully for: {}, interconnection: {}", ifcName, - bb); - } - } - - private SwInterfaceSetL2Bridge getL2BridgeRequest(final int swIfIndex, final int bdId, final byte shg, - final byte bvi, final byte enabled) { - final SwInterfaceSetL2Bridge swInterfaceSetL2Bridge = new SwInterfaceSetL2Bridge(); - swInterfaceSetL2Bridge.rxSwIfIndex = swIfIndex; - swInterfaceSetL2Bridge.bdId = bdId; - swInterfaceSetL2Bridge.shg = shg; - swInterfaceSetL2Bridge.bvi = bvi; - swInterfaceSetL2Bridge.enable = enabled; - return swInterfaceSetL2Bridge; - } - - private void setXconnectBasedL2(final int swIfIndex, final String ifcName, final XconnectBased ic, - final WriteContext writeContext) - throws VppApiInvocationException { - - String outSwIfName = ic.getXconnectOutgoingInterface(); - LOG.debug("Setting xconnect based interconnection(outgoing ifc={}) for interface: {}", outSwIfName, - ifcName); - - int outSwIfIndex = interfaceContext.getIndex(outSwIfName, writeContext.getMappingContext()); - checkArgument(outSwIfIndex > 0, - "Unable to set Interconnection for Interface: %s, outgoing interface: %s does not exist", - ifcName, outSwIfIndex); - - final CompletionStage<SwInterfaceSetL2XconnectReply> swInterfaceSetL2XconnectReplyCompletionStage = - getFutureJVpp() - .swInterfaceSetL2Xconnect(getL2XConnectRequest(swIfIndex, outSwIfIndex, (byte) 1 /* enable */)); - final SwInterfaceSetL2XconnectReply reply = - TranslateUtils.getReply(swInterfaceSetL2XconnectReplyCompletionStage.toCompletableFuture()); - - if (reply.retval < 0) { - LOG.warn("Failed to update xconnect based interconnection flags for: {}, interconnection: {}", - ifcName, ic); - throw new VppApiInvocationException("swInterfaceSetL2Xconnect", reply.context, reply.retval); - } else { - LOG.debug("Xconnect based interconnection updated successfully for: {}, interconnection: {}", ifcName, - ic); - } - } - - private SwInterfaceSetL2Xconnect getL2XConnectRequest(final int rxIfc, final int txIfc, - final byte enabled) { - - final SwInterfaceSetL2Xconnect swInterfaceSetL2Xconnect = new SwInterfaceSetL2Xconnect(); - swInterfaceSetL2Xconnect.enable = enabled; - swInterfaceSetL2Xconnect.rxSwIfIndex = rxIfc; - swInterfaceSetL2Xconnect.txSwIfIndex = txIfc; - return swInterfaceSetL2Xconnect; + icWriteUtils.setInterconnection(id, swIfIndex, ifcName, l2.getInterconnection(), writeContext); } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/RewriteCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/RewriteCustomizer.java new file mode 100644 index 000000000..2309344c8 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/RewriteCustomizer.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.interfaces; + +import static io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils.booleanToByte; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.util.SubInterfaceUtils; +import io.fd.honeycomb.v3po.translate.v3po.util.TagRewriteOperation; +import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; +import io.fd.honeycomb.v3po.translate.write.WriteContext; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import java.util.List; +import java.util.concurrent.CompletionStage; +import javax.annotation.Nonnull; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527._802dot1q; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.L2; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.l2.Rewrite; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.l2.RewriteBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.tag.rewrite.PushTags; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.L2InterfaceVlanTagRewrite; +import org.openvpp.jvpp.dto.L2InterfaceVlanTagRewriteReply; +import org.openvpp.jvpp.future.FutureJVpp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Writer Customizer responsible for vlan tag rewrite.<br> Sends {@code l2_interface_vlan_tag_rewrite} message to + * VPP.<br> Equivalent of invoking {@code vppctl set interface l2 tag-rewrite} command. + */ +public class RewriteCustomizer extends FutureJVppCustomizer implements ChildWriterCustomizer<Rewrite> { + + private static final Logger LOG = LoggerFactory.getLogger( + io.fd.honeycomb.v3po.translate.v3po.interfacesstate.RewriteCustomizer.class); + private final NamingContext interfaceContext; + + public RewriteCustomizer(@Nonnull final FutureJVpp futureJvpp, + @Nonnull final NamingContext interfaceContext) { + super(futureJvpp); + this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null"); + } + + @Nonnull + @Override + public Optional<Rewrite> extract(@Nonnull final InstanceIdentifier<Rewrite> currentId, + @Nonnull final DataObject parentData) { + return Optional.fromNullable(((L2) parentData).getRewrite()); + } + + @Override + public void writeCurrentAttributes(final InstanceIdentifier<Rewrite> id, final Rewrite dataAfter, + final WriteContext writeContext) + throws WriteFailedException.CreateFailedException { + + try { + setTagRewrite(getSubInterfaceName(id), dataAfter, writeContext); + } catch (VppApiInvocationException e) { + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + private static String getSubInterfaceName(final InstanceIdentifier<Rewrite> id) { + return SubInterfaceUtils.getSubInterfaceName(id.firstKeyOf(Interface.class).getName(), + Math.toIntExact(id.firstKeyOf(SubInterface.class).getIdentifier())); + } + + private void setTagRewrite(final String ifname, final Rewrite rewrite, final WriteContext writeContext) + throws VppApiInvocationException { + final int swIfIndex = interfaceContext.getIndex(ifname, writeContext.getMappingContext()); + LOG.debug("Setting tag rewrite for interface {}(id=): {}", ifname, swIfIndex, rewrite); + + final CompletionStage<L2InterfaceVlanTagRewriteReply> replyCompletionStage = + getFutureJVpp().l2InterfaceVlanTagRewrite(getTagRewriteRequest(swIfIndex, rewrite)); + + final L2InterfaceVlanTagRewriteReply reply = + TranslateUtils.getReply(replyCompletionStage.toCompletableFuture()); + if (reply.retval < 0) { + LOG.debug("Failed to set tag rewrite for interface {}(id=): {}", ifname, swIfIndex, rewrite); + throw new VppApiInvocationException("l2InterfaceVlanTagRewrite", reply.context, reply.retval); + } else { + LOG.debug("Tag rewrite for interface {}(id=) set successfully: {}", ifname, swIfIndex, rewrite); + } + } + + private L2InterfaceVlanTagRewrite getTagRewriteRequest(final int swIfIndex, final Rewrite rewrite) { + final L2InterfaceVlanTagRewrite request = new L2InterfaceVlanTagRewrite(); + request.swIfIndex = swIfIndex; + request.pushDot1Q = booleanToByte(_802dot1q.class == rewrite.getVlanType()); + + final List<PushTags> pushTags = rewrite.getPushTags(); + final Short popTags = rewrite.getPopTags(); + + final int numberOfTagsToPop = popTags == null + ? 0 + : popTags.intValue(); + final int numberOfTagsToPush = pushTags == null + ? 0 + : pushTags.size(); + + request.vtrOp = TagRewriteOperation.get(numberOfTagsToPop, numberOfTagsToPush).ordinal(); + + if (numberOfTagsToPush > 0) { + for (final PushTags tag : pushTags) { + if (tag.getIndex() == 0) { + request.tag1 = tag.getDot1qTag().getVlanId().getValue(); + } else { + request.tag2 = tag.getDot1qTag().getVlanId().getValue(); + } + } + } + + LOG.debug("Generated tag rewrite request: {}", ReflectionToStringBuilder.toString(request)); + return request; + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Rewrite> id, + @Nonnull final Rewrite dataBefore, + @Nonnull final Rewrite dataAfter, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + try { + setTagRewrite(getSubInterfaceName(id), dataAfter, writeContext); + } catch (VppApiInvocationException e) { + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Rewrite> id, + @Nonnull final Rewrite dataBefore, @Nonnull final WriteContext writeContext) + throws WriteFailedException.DeleteFailedException { + try { + final String subifName = getSubInterfaceName(id); + LOG.debug("Disabling tag rewrite for interface {}", subifName); + final Rewrite rewrite = new RewriteBuilder().build(); // rewrite without push and pops will cause delete + setTagRewrite(subifName, rewrite, writeContext); + } catch (VppApiInvocationException e) { + throw new WriteFailedException.DeleteFailedException(id, e); + } + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceCustomizer.java index 499d98048..b6c8d9a59 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceCustomizer.java @@ -16,39 +16,53 @@ package io.fd.honeycomb.v3po.translate.v3po.interfaces; +import static com.google.common.base.Preconditions.checkState; +import static io.fd.honeycomb.v3po.translate.v3po.util.SubInterfaceUtils.getSubInterfaceName; import static io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils.booleanToByte; -import com.google.common.base.Optional; import com.google.common.base.Preconditions; -import io.fd.honeycomb.v3po.translate.v3po.util.AbstractInterfaceTypeCustomizer; +import io.fd.honeycomb.v3po.translate.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; -import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; import io.fd.honeycomb.v3po.translate.write.WriteContext; import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import java.util.List; +import java.util.Objects; import java.util.concurrent.CompletionStage; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.CVlan; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.Dot1qVlanId; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.SVlan; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.or.any.Dot1qTag; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VlanTag; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VlanType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.SubInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527._802dot1ad; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.SubInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.match.attributes.MatchType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.match.attributes.match.type.Default; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.match.attributes.match.type.vlan.tagged.VlanTagged; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Tags; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.tags.Tag; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.openvpp.jvpp.dto.CreateSubif; import org.openvpp.jvpp.dto.CreateSubifReply; +import org.openvpp.jvpp.dto.SwInterfaceSetFlags; +import org.openvpp.jvpp.dto.SwInterfaceSetFlagsReply; import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Writer Customizer responsible for sub interface creation.<br> - * Sends {@code create_subif} message to VPP.<br> + * Writer Customizer responsible for sub interface creation.<br> Sends {@code create_subif} message to VPP.<br> * Equivalent of invoking {@code vppclt create subif} command. */ -public class SubInterfaceCustomizer extends AbstractInterfaceTypeCustomizer<SubInterface> { +public class SubInterfaceCustomizer extends FutureJVppCustomizer + implements ListWriterCustomizer<SubInterface, SubInterfaceKey> { private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceCustomizer.class); private final NamingContext interfaceContext; @@ -60,18 +74,14 @@ public class SubInterfaceCustomizer extends AbstractInterfaceTypeCustomizer<SubI @Nonnull @Override - public Optional<SubInterface> extract(@Nonnull final InstanceIdentifier<SubInterface> currentId, - @Nonnull final DataObject parentData) { - return Optional.fromNullable(((VppInterfaceAugmentation) parentData).getSubInterface()); + public List<SubInterface> extract(@Nonnull final InstanceIdentifier<SubInterface> currentId, + @Nonnull final DataObject parentData) { + return ((SubInterfaces) parentData).getSubInterface(); } - @Override - protected Class<? extends InterfaceType> getExpectedInterfaceType() { - return org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.SubInterface.class; - } @Override - public void writeInterface(@Nonnull final InstanceIdentifier<SubInterface> id, + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<SubInterface> id, @Nonnull final SubInterface dataAfter, @Nonnull final WriteContext writeContext) throws WriteFailedException.CreateFailedException { try { @@ -81,31 +91,36 @@ public class SubInterfaceCustomizer extends AbstractInterfaceTypeCustomizer<SubI } } - private void createSubInterface(final String swIfName, final SubInterface subInterface, - final WriteContext writeContext) throws VppApiInvocationException { - final String superIfName = subInterface.getSuperInterface(); - final int swIfIndex = interfaceContext.getIndex(superIfName, writeContext.getMappingContext()); - LOG.debug("Creating sub interface of {}(id={}): name={}, subInterface={}", superIfName, swIfIndex, swIfName, subInterface); + private void createSubInterface(@Nonnull final String superIfName, + @Nonnull final SubInterface subInterface, final WriteContext writeContext) + throws VppApiInvocationException { + final int superIfIndex = interfaceContext.getIndex(superIfName, writeContext.getMappingContext()); + LOG.debug("Creating sub interface of {}(id={}): subInterface={}", superIfName, superIfIndex, subInterface); final CompletionStage<CreateSubifReply> createSubifReplyCompletionStage = - getFutureJVpp().createSubif(getCreateSubifRequest(subInterface, swIfIndex)); + getFutureJVpp().createSubif(getCreateSubifRequest(subInterface, superIfIndex)); final CreateSubifReply reply = TranslateUtils.getReply(createSubifReplyCompletionStage.toCompletableFuture()); if (reply.retval < 0) { - LOG.debug("Failed to create sub interface for: {}, subInterface: {}", swIfName, subInterface); + LOG.debug("Failed to create sub interface for: {}, subInterface: {}", superIfName, subInterface); throw new VppApiInvocationException("createSubif", reply.context, reply.retval); } else { - LOG.debug("Sub interface created successfully for: {}, subInterface: {}", swIfName, subInterface); - // Add new interface to our interface context - interfaceContext.addName(reply.swIfIndex, swIfName, writeContext.getMappingContext()); + setInterfaceState(reply.swIfIndex, booleanToByte(subInterface.isEnabled())); + interfaceContext.addName(reply.swIfIndex, + getSubInterfaceName(superIfName, Math.toIntExact(subInterface.getIdentifier())), + writeContext.getMappingContext()); + LOG.debug("Sub interface created successfully for: {}, subInterface: {}", superIfName, subInterface); } } - private CreateSubif getCreateSubifRequest(final SubInterface subInterface, final int swIfIndex) { + private CreateSubif getCreateSubifRequest(@Nonnull final SubInterface subInterface, final int swIfIndex) { + // TODO add validation CreateSubif request = new CreateSubif(); request.subId = Math.toIntExact(subInterface.getIdentifier().intValue()); request.swIfIndex = swIfIndex; - switch (subInterface.getNumberOfTags()) { + + final int numberOfTags = getNumberOfTags(subInterface); + switch (numberOfTags) { case 0: request.noTags = 1; break; @@ -116,38 +131,104 @@ public class SubInterfaceCustomizer extends AbstractInterfaceTypeCustomizer<SubI request.twoTags = 1; break; } - request.dot1Ad = booleanToByte(VlanType._802dot1ad.equals(subInterface.getVlanType())); - request.exactMatch = booleanToByte(subInterface.isExactMatch()); - request.defaultSub = booleanToByte(subInterface.isDefaultSubif()); - request.outerVlanIdAny = booleanToByte(subInterface.isMatchAnyInnerId()); - request.innerVlanIdAny = booleanToByte(subInterface.isMatchAnyInnerId()); - request.outerVlanId = vlanTagToChar(subInterface.getOuterId()); - request.innerVlanId = vlanTagToChar(subInterface.getInnerId()); + request.dot1Ad = booleanToByte(_802dot1ad.class == subInterface.getVlanType()); + + final MatchType matchType = subInterface.getMatch().getMatchType(); // todo match should be mandatory + request.exactMatch = + booleanToByte(matchType instanceof VlanTagged && ((VlanTagged) matchType).isMatchExactTags()); + request.defaultSub = booleanToByte(matchType instanceof Default); + + if (numberOfTags > 0) { + for (final Tag tag : subInterface.getTags().getTag()) { + if (tag.getIndex() == 0) { + setOuterTag(request, tag); + } else if (tag.getIndex() == 1) { + setInnerTag(request, tag); + } + } + } return request; } - private static char vlanTagToChar(@Nullable VlanTag tag) { - if (tag == null) { + private void setOuterTag(final CreateSubif request, final Tag outerTag) { + checkState(SVlan.class == outerTag.getDot1qTag().getTagType(), "Service Tag expected at index 0"); + final Dot1qTag.VlanId vlanId = outerTag.getDot1qTag().getVlanId(); + + request.outerVlanId = dot1qVlanIdToChar(vlanId.getDot1qVlanId()); + request.outerVlanIdAny = booleanToByte(Dot1qTag.VlanId.Enumeration.Any.equals(vlanId.getEnumeration())); + } + + private void setInnerTag(final CreateSubif request, final Tag innerTag) { + checkState(CVlan.class == innerTag.getDot1qTag().getTagType(), "Customer Tag expected at index 1"); + final Dot1qTag.VlanId vlanId = innerTag.getDot1qTag().getVlanId(); + + request.innerVlanId = dot1qVlanIdToChar(vlanId.getDot1qVlanId()); + request.innerVlanIdAny = booleanToByte(Dot1qTag.VlanId.Enumeration.Any.equals(vlanId.getEnumeration())); + } + + private static int getNumberOfTags(@Nonnull final SubInterface subInterface) { + final Tags tags = subInterface.getTags(); + if (tags == null) { + return 0; + } + final List<Tag> tagList = tags.getTag(); + if (tagList == null) { + return 0; + } + return tagList.size(); + } + + private static char dot1qVlanIdToChar(@Nullable Dot1qVlanId dot1qVlanId) { + if (dot1qVlanId == null) { return 0; // tell VPP that optional argument is missing } else { - return (char)tag.getValue().intValue(); + return (char) dot1qVlanId.getValue().intValue(); } } @Override public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<SubInterface> id, @Nonnull final SubInterface dataBefore, @Nonnull final SubInterface dataAfter, - @Nonnull final WriteContext writeContext) throws WriteFailedException.UpdateFailedException { - if (dataBefore.equals(dataAfter)) { - LOG.debug("dataBefore equals dataAfter, update will not be performed"); - return; + @Nonnull final WriteContext writeContext) + throws WriteFailedException.UpdateFailedException { + if (Objects.equals(dataBefore.isEnabled(), dataAfter.isEnabled())) { + LOG.debug("No state update will be performed. Ignoring config"); + return; // TODO shouldn't we throw exception here (if there will be dedicated L2 customizer)? + } + try { + final String subIfaceName = getSubInterfaceName(id.firstKeyOf(Interface.class).getName(), + Math.toIntExact(dataAfter.getIdentifier())); + setInterfaceState(interfaceContext.getIndex(subIfaceName, writeContext.getMappingContext()), + booleanToByte(dataAfter.isEnabled())); + } catch (VppApiInvocationException e) { + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } + } + + private void setInterfaceState(final int swIfIndex, final byte enabled) throws VppApiInvocationException { + final SwInterfaceSetFlags swInterfaceSetFlags = new SwInterfaceSetFlags(); + swInterfaceSetFlags.swIfIndex = swIfIndex; + swInterfaceSetFlags.adminUpDown = enabled; + + final CompletionStage<SwInterfaceSetFlagsReply> swInterfaceSetFlagsReplyFuture = + getFutureJVpp().swInterfaceSetFlags(swInterfaceSetFlags); + + LOG.debug("Updating interface state for: interface if={}, enabled: {}", swIfIndex, enabled); + + SwInterfaceSetFlagsReply reply = TranslateUtils.getReply(swInterfaceSetFlagsReplyFuture.toCompletableFuture()); + if (reply.retval < 0) { + LOG.warn("Failed to update interface state for: interface if={}, enabled: {}", swIfIndex, enabled); + throw new VppApiInvocationException("swInterfaceSetFlags", reply.context, reply.retval); + } else { + LOG.debug("Interface state updated successfully for: {}, index: {}, enabled: {}, ctxId: {}", + swIfIndex, enabled, reply.context); } - throw new UnsupportedOperationException("Sub interface update is not supported"); } @Override public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<SubInterface> id, - @Nonnull final SubInterface dataBefore, @Nonnull final WriteContext writeContext) + @Nonnull final SubInterface dataBefore, + @Nonnull final WriteContext writeContext) throws WriteFailedException.DeleteFailedException { throw new UnsupportedOperationException("Sub interface delete is not supported"); } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceL2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceL2Customizer.java new file mode 100644 index 000000000..a1957f5a0 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/SubInterfaceL2Customizer.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.interfaces; + +import com.google.common.base.Optional; +import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.util.SubInterfaceUtils; +import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; +import io.fd.honeycomb.v3po.translate.write.WriteContext; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.L2; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.future.FutureJVpp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Customizer for writing vlan sub interface l2 configuration + */ +public class SubInterfaceL2Customizer extends FutureJVppCustomizer implements ChildWriterCustomizer<L2> { + + private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceL2Customizer.class); + private final NamingContext interfaceContext; + private final InterconnectionWriteUtils icWriterUtils; + + public SubInterfaceL2Customizer(final FutureJVpp vppApi, final NamingContext interfaceContext, + final NamingContext bridgeDomainContext) { + super(vppApi); + this.interfaceContext = interfaceContext; + this.icWriterUtils = new InterconnectionWriteUtils(vppApi, interfaceContext, bridgeDomainContext); + } + + @Nonnull + @Override + public Optional<L2> extract(@Nonnull final InstanceIdentifier<L2> currentId, @Nonnull final DataObject parentData) { + return Optional.fromNullable(((SubInterface) parentData).getL2()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataAfter, + @Nonnull final WriteContext writeContext) + throws WriteFailedException { + final String subInterfaceName = getSubInterfaceName(id); + final int subInterfaceIndex = interfaceContext.getIndex(subInterfaceName, writeContext.getMappingContext()); + try { + setL2(id, subInterfaceIndex, subInterfaceName, dataAfter, writeContext); + } catch (VppApiInvocationException e) { + LOG.warn("Write of L2 failed", e); + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + private String getSubInterfaceName(@Nonnull final InstanceIdentifier<L2> id) { + final InterfaceKey parentInterfacekey = id.firstKeyOf(Interface.class); + final SubInterfaceKey subInterfacekey = id.firstKeyOf(SubInterface.class); + return SubInterfaceUtils + .getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue()); + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore, + @Nonnull final L2 dataAfter, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + + final String subInterfaceName = getSubInterfaceName(id); + final int subInterfaceIndex = interfaceContext.getIndex(subInterfaceName, writeContext.getMappingContext()); + // TODO handle update properly (if possible) + try { + setL2(id, subInterfaceIndex, subInterfaceName, dataAfter, writeContext); + } catch (VppApiInvocationException e) { + LOG.warn("Update of L2 failed", e); + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore, + @Nonnull final WriteContext writeContext) { + // TODO implement delete (if possible) + } + + private void setL2(final InstanceIdentifier<L2> id, final int swIfIndex, final String ifcName, final L2 l2, + final WriteContext writeContext) + throws VppApiInvocationException, WriteFailedException { + LOG.debug("Setting L2 for sub-interface: {}", ifcName); + icWriterUtils.setInterconnection(id, swIfIndex, ifcName, l2.getInterconnection(), writeContext); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizer.java deleted file mode 100644 index 721d15530..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VlanTagRewriteCustomizer.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.v3po.translate.v3po.interfaces; - -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import io.fd.honeycomb.v3po.translate.v3po.util.AbstractInterfaceTypeCustomizer; -import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; -import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; -import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils; -import io.fd.honeycomb.v3po.translate.write.WriteContext; -import io.fd.honeycomb.v3po.translate.write.WriteFailedException; -import java.util.concurrent.CompletionStage; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.SubInterface; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.TagRewriteOperation; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VlanTag; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VlanType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.VlanTagRewrite; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.VlanTagRewriteBuilder; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.jvpp.dto.L2InterfaceVlanTagRewrite; -import org.openvpp.jvpp.dto.L2InterfaceVlanTagRewriteReply; -import org.openvpp.jvpp.future.FutureJVpp; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Writer Customizer responsible for vlan tag rewrite.<br> - * Sends {@code l2_interface_vlan_tag_rewrite} message to VPP.<br> - * Equivalent of invoking {@code vppctl set interface l2 tag-rewrite} command. - */ -public class VlanTagRewriteCustomizer extends AbstractInterfaceTypeCustomizer<VlanTagRewrite> { - - private static final Logger LOG = LoggerFactory.getLogger(VlanTagRewriteCustomizer.class); - private final NamingContext interfaceContext; - - public VlanTagRewriteCustomizer(@Nonnull final FutureJVpp futureJvpp, - @Nonnull final NamingContext interfaceContext) { - super(futureJvpp); - this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null"); - } - - @Nonnull - @Override - public Optional<VlanTagRewrite> extract(@Nonnull final InstanceIdentifier<VlanTagRewrite> currentId, - @Nonnull final DataObject parentData) { - return Optional.fromNullable(((L2) parentData).getVlanTagRewrite()); - } - - @Override - protected Class<? extends InterfaceType> getExpectedInterfaceType() { - return SubInterface.class; - } - - @Override - protected void writeInterface(final InstanceIdentifier<VlanTagRewrite> id, final VlanTagRewrite dataAfter, - final WriteContext writeContext) throws WriteFailedException.CreateFailedException { - try { - setTagRewrite(id.firstKeyOf(Interface.class).getName(), dataAfter, writeContext); - } catch (VppApiInvocationException e) { - throw new WriteFailedException.CreateFailedException(id, dataAfter, e); - } - } - - private void setTagRewrite(final String ifname, final VlanTagRewrite cfg, final WriteContext writeContext) - throws VppApiInvocationException { - final int swIfIndex = interfaceContext.getIndex(ifname, writeContext.getMappingContext()); - LOG.debug("Setting tag rewrite for interface {}(id=): {}", ifname, swIfIndex, cfg); - - final CompletionStage<L2InterfaceVlanTagRewriteReply> replyCompletionStage = - getFutureJVpp().l2InterfaceVlanTagRewrite(getTagRewriteRequest(swIfIndex, cfg)); - - final L2InterfaceVlanTagRewriteReply reply = TranslateUtils.getReply(replyCompletionStage.toCompletableFuture()); - if (reply.retval < 0) { - LOG.debug("Failed to set tag rewrite for interface {}(id=): {}", ifname, swIfIndex, cfg); - throw new VppApiInvocationException("l2InterfaceVlanTagRewrite", reply.context, reply.retval); - } else { - LOG.debug("Tag rewrite for interface {}(id=) set successfully: {}", ifname, swIfIndex, cfg); - } - } - - private L2InterfaceVlanTagRewrite getTagRewriteRequest(final int swIfIndex, final VlanTagRewrite cfg) { - final L2InterfaceVlanTagRewrite request = new L2InterfaceVlanTagRewrite(); - request.swIfIndex = swIfIndex; - - request.vtrOp = cfg.getRewriteOperation().getIntValue(); // TODO make mandatory - request.pushDot1Q = (byte) (VlanType._802dot1q.equals(cfg.getFirstPushed()) - ? 1 - : 0); - final VlanTag tag1 = cfg.getTag1(); - if (tag1 != null) { - request.tag1 = tag1.getValue(); - } - final VlanTag tag2 = cfg.getTag2(); - if (tag2 != null) { - request.tag2 = tag2.getValue(); - } - return request; - } - - @Override - public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<VlanTagRewrite> id, - @Nonnull final VlanTagRewrite dataBefore, - @Nonnull final VlanTagRewrite dataAfter, @Nonnull final WriteContext writeContext) - throws WriteFailedException { - try { - setTagRewrite(id.firstKeyOf(Interface.class).getName(), dataAfter, writeContext); - } catch (VppApiInvocationException e) { - throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); - } - } - - @Override - public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<VlanTagRewrite> id, - @Nonnull final VlanTagRewrite dataBefore, @Nonnull final WriteContext writeContext) - throws WriteFailedException.DeleteFailedException { - try { - // disable tag rewrite - final VlanTagRewriteBuilder builder = new VlanTagRewriteBuilder(); - builder.setRewriteOperation(TagRewriteOperation.Disabled); - setTagRewrite(id.firstKeyOf(Interface.class).getName(), builder.build(), writeContext); - } catch (VppApiInvocationException e) { - throw new WriteFailedException.DeleteFailedException(id, e); - } - } -} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java index 49a6fd630..e1c3e2df6 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/EthernetCustomizer.java @@ -66,7 +66,7 @@ public class EthernetCustomizer extends FutureJVppCustomizer @Nonnull final ReadContext ctx) throws ReadFailedException { final InterfaceKey key = id.firstKeyOf(Interface.class); - final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, + final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key.getName(), interfaceContext.getIndex(key.getName(), ctx.getMappingContext()), ctx.getModificationCache()); if(iface.linkMtu != 0) { diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterconnectionReadUtils.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterconnectionReadUtils.java new file mode 100644 index 000000000..886549ac3 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterconnectionReadUtils.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; + +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; + +import io.fd.honeycomb.v3po.translate.read.ReadContext; +import io.fd.honeycomb.v3po.translate.read.ReadFailedException; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.Interconnection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBasedBuilder; +import org.openvpp.jvpp.dto.BridgeDomainDetails; +import org.openvpp.jvpp.dto.BridgeDomainDetailsReplyDump; +import org.openvpp.jvpp.dto.BridgeDomainDump; +import org.openvpp.jvpp.dto.BridgeDomainSwIfDetails; +import org.openvpp.jvpp.dto.SwInterfaceDetails; +import org.openvpp.jvpp.future.FutureJVpp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility class providing Interconnection read support. + */ +// FIXME this should be customizer, but it is not possible because Interconnection is not a DataObject +final class InterconnectionReadUtils { + + private static final Logger LOG = LoggerFactory.getLogger(InterconnectionReadUtils.class); + + private final FutureJVpp futureJvpp; + private final NamingContext interfaceContext; + private final NamingContext bridgeDomainContext; + + InterconnectionReadUtils(@Nonnull final FutureJVpp futureJvpp, + @Nonnull final NamingContext interfaceContext, + @Nonnull final NamingContext bridgeDomainContext) { + this.futureJvpp = requireNonNull(futureJvpp, "futureJvpp should not be null"); + this.interfaceContext = requireNonNull(interfaceContext, "interfaceContext should not be null"); + this.bridgeDomainContext = requireNonNull(bridgeDomainContext, "bridgeDomainContext should not be null"); + } + + @Nullable + Interconnection readInterconnection(@Nonnull final String ifaceName, @Nonnull final ReadContext ctx) + throws ReadFailedException { + final int ifaceId = interfaceContext.getIndex(ifaceName, ctx.getMappingContext()); + + final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(futureJvpp, ifaceName, + ifaceId, ctx.getModificationCache()); + LOG.debug("Interface details for interface: {}, details: {}", ifaceName, iface); + + final BridgeDomainDetailsReplyDump dumpReply = getDumpReply(); + final Optional<BridgeDomainSwIfDetails> bdForInterface = getBridgeDomainForInterface(ifaceId, dumpReply); + if (bdForInterface.isPresent()) { + final BridgeDomainSwIfDetails bdSwIfDetails = bdForInterface.get(); + final BridgeBasedBuilder bbBuilder = new BridgeBasedBuilder(); + bbBuilder.setBridgeDomain(bridgeDomainContext.getName(bdSwIfDetails.bdId, ctx.getMappingContext())); + + // Set BVI if the bridgeDomainDetails.bviSwIfIndex == current sw if index + final Optional<BridgeDomainDetails> bridgeDomainForInterface = + getBridgeDomainForInterface(dumpReply, bdForInterface.get().bdId); + // Since we already found an interface assigned to a bridge domain, the details for BD must be present + checkState(bridgeDomainForInterface.isPresent()); + if (bridgeDomainForInterface.get().bviSwIfIndex == ifaceId) { + bbBuilder.setBridgedVirtualInterface(true); + } + + if (bdSwIfDetails.shg != 0) { + bbBuilder.setSplitHorizonGroup((short) bdSwIfDetails.shg); + } + return bbBuilder.build(); + } + // TODO is there a way to check if interconnection is XconnectBased? + + return null; + } + + private Optional<BridgeDomainSwIfDetails> getBridgeDomainForInterface(final int ifaceId, + final BridgeDomainDetailsReplyDump reply) { + if (null == reply || null == reply.bridgeDomainSwIfDetails || reply.bridgeDomainSwIfDetails.isEmpty()) { + return Optional.empty(); + } + // interface can be added to only one BD only + return reply.bridgeDomainSwIfDetails.stream().filter(a -> a.swIfIndex == ifaceId).findFirst(); + } + + private Optional<BridgeDomainDetails> getBridgeDomainForInterface(final BridgeDomainDetailsReplyDump reply, + int bdId) { + return reply.bridgeDomainDetails.stream().filter(a -> a.bdId == bdId).findFirst(); + } + + private BridgeDomainDetailsReplyDump getDumpReply() { + // We need to perform full bd dump, because there is no way + // to ask VPP for BD details given interface id/name (TODO add it to vpp.api?) + // TODO cache dump result + final BridgeDomainDump request = new BridgeDomainDump(); + request.bdId = -1; + + final CompletableFuture<BridgeDomainDetailsReplyDump> bdCompletableFuture = + futureJvpp.bridgeDomainSwIfDump(request).toCompletableFuture(); + return TranslateUtils.getReply(bdCompletableFuture); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizer.java index 4027941eb..d54929ea1 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceCustomizer.java @@ -75,7 +75,7 @@ public class InterfaceCustomizer extends FutureJVppCustomizer final InterfaceKey key = id.firstKeyOf(id.getTargetType()); // Pass cached details from getAllIds to getDetails to avoid additional dumps - final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, + final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key.getName(), interfaceContext.getIndex(key.getName(), ctx.getMappingContext()), ctx.getModificationCache()); LOG.debug("Interface details for interface: {}, details: {}", key.getName(), iface); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java index b031523d6..e0bae975f 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/InterfaceUtils.java @@ -18,20 +18,19 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; import static com.google.common.base.Preconditions.checkNotNull; import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceCustomizer.getCachedInterfaceDump; +import static java.util.Objects.requireNonNull; +import static java.util.stream.Collectors.toList; import com.google.common.base.Preconditions; -import com.google.common.collect.Iterables; import io.fd.honeycomb.v3po.translate.ModificationCache; import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils; import java.math.BigInteger; import java.util.Map; -import java.util.Objects; import java.util.concurrent.CompletionStage; import java.util.stream.Collectors; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.EthernetCsmacd; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Gauge64; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.SubInterface; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.Tap; @@ -108,7 +107,7 @@ public final class InterfaceUtils { * @throws IllegalArgumentException if vppPhysAddress.length < 6 */ public static String vppPhysAddrToYang(@Nonnull final byte[] vppPhysAddress) { - Objects.requireNonNull(vppPhysAddress, "Empty physical address bytes"); + requireNonNull(vppPhysAddress, "Empty physical address bytes"); Preconditions.checkArgument(PHYSICAL_ADDRESS_LENGTH <= vppPhysAddress.length, "Invalid physical address size %s, expected >= 6", vppPhysAddress.length); StringBuilder physAddr = new StringBuilder(); @@ -149,7 +148,7 @@ public final class InterfaceUtils { * Queries VPP for interface description given interface key. * * @param futureJvpp VPP Java Future API - * @param key interface key + * @param name interface name * @param index VPP index of the interface * @param ctx per-tx scope context containing cached dump with all the interfaces. If the cache is not * available or outdated, another dump will be performed. @@ -158,10 +157,14 @@ public final class InterfaceUtils { */ @Nonnull public static SwInterfaceDetails getVppInterfaceDetails(@Nonnull final FutureJVpp futureJvpp, - @Nonnull InterfaceKey key, final int index, + @Nonnull final String name, final int index, @Nonnull final ModificationCache ctx) { + requireNonNull(futureJvpp, "futureJvpp should not be null"); + requireNonNull(name, "name should not be null"); + requireNonNull(ctx, "ctx should not be null"); + final SwInterfaceDump request = new SwInterfaceDump(); - request.nameFilter = key.getName().getBytes(); + request.nameFilter = name.getBytes(); request.nameFilterValid = 1; final Map<Integer, SwInterfaceDetails> allInterfaces = getCachedInterfaceDump(ctx); @@ -176,8 +179,8 @@ public final class InterfaceUtils { if (null == ifaces || null == ifaces.swInterfaceDetails || ifaces.swInterfaceDetails.isEmpty()) { request.nameFilterValid = 0; - LOG.warn("VPP returned null instead of interface by key {} and its not cached", key.getName()); - LOG.warn("Iterating through all the interfaces to find interface: {}", key.getName()); + LOG.warn("VPP returned null instead of interface by key {} and its not cached", name); + LOG.warn("Iterating through all the interfaces to find interface: {}", name); // Or else just perform full dump and do inefficient filtering requestFuture = futureJvpp.swInterfaceDump(request); @@ -191,10 +194,17 @@ public final class InterfaceUtils { if (allInterfaces.containsKey(index)) { return allInterfaces.get(index); } - throw new IllegalArgumentException("Unable to find interface " + key.getName()); + throw new IllegalArgumentException("Unable to find interface " + name); } - final SwInterfaceDetails iface = Iterables.getOnlyElement(ifaces.swInterfaceDetails); + // SwInterfaceDump's name filter does prefix match, so we need additional filtering: + final SwInterfaceDetails iface = ifaces.swInterfaceDetails.stream().filter(d -> d.swIfIndex == index).collect( + Collectors.collectingAndThen(toList(), l -> { + if (l.size() == 1) { + return l.get(0); + } + throw new RuntimeException(); + })); allInterfaces.put(index, iface); // update the cache return iface; } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2Customizer.java index 3fae8c713..63e51389c 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2Customizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/L2Customizer.java @@ -16,32 +16,20 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; -import static com.google.common.base.Preconditions.checkState; - -import com.google.common.base.Preconditions; import io.fd.honeycomb.v3po.translate.read.ReadContext; import io.fd.honeycomb.v3po.translate.read.ReadFailedException; import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer; import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; -import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentationBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.L2; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.L2Builder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBasedBuilder; import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.jvpp.dto.BridgeDomainDetails; -import org.openvpp.jvpp.dto.BridgeDomainDetailsReplyDump; -import org.openvpp.jvpp.dto.BridgeDomainDump; -import org.openvpp.jvpp.dto.BridgeDomainSwIfDetails; -import org.openvpp.jvpp.dto.SwInterfaceDetails; import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,19 +37,16 @@ import org.slf4j.LoggerFactory; /** * Customizer for reading ietf-interfaces:interfaces-state/interface/iface_name/v3po:l2 */ -public class L2Customizer extends FutureJVppCustomizer - implements ChildReaderCustomizer<L2, L2Builder> { +public class L2Customizer extends FutureJVppCustomizer implements ChildReaderCustomizer<L2, L2Builder> { private static final Logger LOG = LoggerFactory.getLogger(L2Customizer.class); - private final NamingContext interfaceContext; - private final NamingContext bridgeDomainContext; + private final InterconnectionReadUtils icReadUtils; public L2Customizer(@Nonnull final FutureJVpp futureJvpp, @Nonnull final NamingContext interfaceContext, @Nonnull final NamingContext bridgeDomainContext) { super(futureJvpp); - this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null"); - this.bridgeDomainContext = Preconditions.checkNotNull(bridgeDomainContext, "bridgeDomainContext should not be null"); + this.icReadUtils = new InterconnectionReadUtils(futureJvpp, interfaceContext, bridgeDomainContext); } @Override @@ -80,62 +65,8 @@ public class L2Customizer extends FutureJVppCustomizer @Nonnull final ReadContext ctx) throws ReadFailedException { LOG.debug("Reading attributes for L2: {}", id); final InterfaceKey key = id.firstKeyOf(Interface.class); - final int ifaceId = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); - - final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, - ifaceId, ctx.getModificationCache()); - LOG.debug("Interface details for interface: {}, details: {}", key.getName(), iface); - - final BridgeDomainDetailsReplyDump dumpReply = getDumpReply(); - final Optional<BridgeDomainSwIfDetails> bdForInterface = getBridgeDomainForInterface(ifaceId, dumpReply); - if (bdForInterface.isPresent()) { - final BridgeDomainSwIfDetails bdSwIfDetails = bdForInterface.get(); - final BridgeBasedBuilder bbBuilder = new BridgeBasedBuilder(); - bbBuilder.setBridgeDomain(bridgeDomainContext.getName(bdSwIfDetails.bdId, ctx.getMappingContext())); - - // Set BVI if the bridgeDomainDetails.bviSwIfIndex == current sw if index - final Optional<BridgeDomainDetails> bridgeDomainForInterface = - getBridgeDomainForInterface(ifaceId, dumpReply, bdForInterface.get().bdId); - // Since we already found an interface assigned to a bridge domain, the details for BD must be present - checkState(bridgeDomainForInterface.isPresent()); - if(bridgeDomainForInterface.get().bviSwIfIndex == ifaceId) { - bbBuilder.setBridgedVirtualInterface(true); - } - - if (bdSwIfDetails.shg != 0) { - bbBuilder.setSplitHorizonGroup((short)bdSwIfDetails.shg); - } - builder.setInterconnection(bbBuilder.build()); - } - - // TODO is there a way to check if interconnection is XconnectBased? - } - - private Optional<BridgeDomainSwIfDetails> getBridgeDomainForInterface(final int ifaceId, - final BridgeDomainDetailsReplyDump reply) { - if (null == reply || null == reply.bridgeDomainSwIfDetails || reply.bridgeDomainSwIfDetails.isEmpty()) { - return Optional.empty(); - } - // interface can be added to only one BD only - return reply.bridgeDomainSwIfDetails.stream().filter(a -> a.swIfIndex == ifaceId).findFirst(); - } - - - private Optional<BridgeDomainDetails> getBridgeDomainForInterface(final int ifaceId, - final BridgeDomainDetailsReplyDump reply, - int bdId) { - return reply.bridgeDomainDetails.stream().filter(a -> a.bdId == bdId).findFirst(); - } - - private BridgeDomainDetailsReplyDump getDumpReply() { - // We need to perform full bd dump, because there is no way - // to ask VPP for BD details given interface id/name (TODO add it to vpp.api?) - // TODO cache dump result - final BridgeDomainDump request = new BridgeDomainDump(); - request.bdId = -1; + final String ifaceName = key.getName(); - final CompletableFuture<BridgeDomainDetailsReplyDump> bdCompletableFuture = - getFutureJVpp().bridgeDomainSwIfDump(request).toCompletableFuture(); - return TranslateUtils.getReply(bdCompletableFuture); + builder.setInterconnection(icReadUtils.readInterconnection(ifaceName, ctx)); } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/RewriteCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/RewriteCustomizer.java new file mode 100644 index 000000000..143fb4d68 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/RewriteCustomizer.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; + +import static com.google.common.base.Preconditions.checkState; + +import com.google.common.base.Preconditions; +import io.fd.honeycomb.v3po.translate.read.ReadContext; +import io.fd.honeycomb.v3po.translate.read.ReadFailedException; +import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.util.SubInterfaceUtils; +import io.fd.honeycomb.v3po.translate.v3po.util.TagRewriteOperation; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nonnull; +import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.CVlan; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.Dot1qTagVlanType; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.Dot1qVlanId; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.SVlan; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.Dot1qTagBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527._802dot1ad; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527._802dot1q; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.L2Builder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.l2.Rewrite; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.l2.RewriteBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.tag.rewrite.PushTags; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.tag.rewrite.PushTagsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.tag.rewrite.PushTagsKey; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.SwInterfaceDetails; +import org.openvpp.jvpp.future.FutureJVpp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Customizer for reading vlan tag-rewrite configuration state form the VPP. + */ +public class RewriteCustomizer extends FutureJVppCustomizer + implements ChildReaderCustomizer<Rewrite, RewriteBuilder> { + + private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceCustomizer.class); + private final NamingContext interfaceContext; + + public RewriteCustomizer(@Nonnull final FutureJVpp futureJvpp, + @Nonnull final NamingContext interfaceContext) { + super(futureJvpp); + this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null"); + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, + @Nonnull final Rewrite readValue) { + ((L2Builder) parentBuilder).setRewrite(readValue); + } + + @Nonnull + @Override + public RewriteBuilder getBuilder(@Nonnull final InstanceIdentifier<Rewrite> id) { + return new RewriteBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<Rewrite> id, + @Nonnull final RewriteBuilder builder, @Nonnull final ReadContext ctx) + throws ReadFailedException { + final String subInterfaceName = getSubInterfaceName(id); + LOG.debug("Reading attributes for sub interface: {}", subInterfaceName); + + final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), subInterfaceName, + interfaceContext.getIndex(subInterfaceName, ctx.getMappingContext()), ctx.getModificationCache()); + LOG.debug("VPP sub-interface details: {}", ReflectionToStringBuilder.toString(iface)); + + checkState(iface.subId != 0, "Interface returned by the VPP is not a sub-interface"); + + final TagRewriteOperation operation = TagRewriteOperation.get(iface.vtrOp); + if (TagRewriteOperation.disabled == operation) { + LOG.debug("Tag rewrite operation is disabled for "); + return; + } + + builder.setVlanType(iface.vtrPushDot1Q == 1 + ? _802dot1q.class + : _802dot1ad.class); + + setPushTags(builder, iface); + setPopTags(builder, operation); + } + + private static String getSubInterfaceName(final InstanceIdentifier<Rewrite> id) { + return SubInterfaceUtils.getSubInterfaceName(id.firstKeyOf(Interface.class).getName(), + Math.toIntExact(id.firstKeyOf(SubInterface.class).getIdentifier())); + } + + private void setPopTags(final RewriteBuilder builder, final TagRewriteOperation operation) { + final byte numberOfTagsToPop = operation.getPopTags(); + if (numberOfTagsToPop != 0) { + builder.setPopTags(Short.valueOf(numberOfTagsToPop)); + } + } + + private void setPushTags(final RewriteBuilder builder, final SwInterfaceDetails iface) { + final List<PushTags> tags = new ArrayList<>(); + if (iface.vtrTag1 != 0) { + tags.add(buildTag((short) 0, SVlan.class, iface.vtrTag1)); + } + if (iface.vtrTag2 != 0) { + tags.add(buildTag((short) 1, CVlan.class, iface.vtrTag2)); + } + if (tags.size() > 0) { + builder.setPushTags(tags); + } + } + + private PushTags buildTag(final short index, final Class<? extends Dot1qTagVlanType> tagType, final int vlanId) { + final PushTagsBuilder tag = new PushTagsBuilder(); + tag.setIndex(index); + tag.setKey(new PushTagsKey(index)); + final Dot1qTagBuilder dtag = new Dot1qTagBuilder(); + dtag.setTagType(tagType); + dtag.setVlanId(new Dot1qVlanId(vlanId)); + tag.setDot1qTag(dtag.build()); + return tag.build(); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceCustomizer.java index 45ef0b490..5adb43874 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceCustomizer.java @@ -16,27 +16,55 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; -import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceUtils.isInterfaceOfType; +import static com.google.common.base.Preconditions.checkState; +import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceCustomizer.DUMPED_IFCS_CONTEXT_KEY; +import static io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils.byteToBoolean; import com.google.common.base.Preconditions; import io.fd.honeycomb.v3po.translate.read.ReadContext; import io.fd.honeycomb.v3po.translate.read.ReadFailedException; -import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer; +import io.fd.honeycomb.v3po.translate.spi.read.ListReaderCustomizer; import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.util.SubInterfaceUtils; +import io.fd.honeycomb.v3po.translate.v3po.util.TranslateUtils; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; import javax.annotation.Nonnull; import org.apache.commons.lang3.builder.ReflectionToStringBuilder; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.CVlan; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.Dot1qTagVlanType; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.Dot1qVlanId; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.SVlan; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.or.any.Dot1qTag; +import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.or.any.Dot1qTagBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VlanTag; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VlanType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentationBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.SubInterface; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.SubInterfaceBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.SubInterfaceStatus; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.SubInterfacesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterfaceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.match.attributes.match.type.DefaultBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.match.attributes.match.type.UntaggedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.match.attributes.match.type.vlan.tagged.VlanTaggedBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Match; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.MatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Tags; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.TagsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.tags.Tag; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.tags.TagBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.tags.TagKey; import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.openvpp.jvpp.dto.SwInterfaceDetails; +import org.openvpp.jvpp.dto.SwInterfaceDetailsReplyDump; +import org.openvpp.jvpp.dto.SwInterfaceDump; import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,10 +73,11 @@ import org.slf4j.LoggerFactory; * Customizer for reading sub interfaces form the VPP. */ public class SubInterfaceCustomizer extends FutureJVppCustomizer - implements ChildReaderCustomizer<SubInterface, SubInterfaceBuilder> { + implements ListReaderCustomizer<SubInterface, SubInterfaceKey, SubInterfaceBuilder> { private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceCustomizer.class); private NamingContext interfaceContext; + private static final Dot1qTag.VlanId ANY_VLAN_ID = new Dot1qTag.VlanId(Dot1qTag.VlanId.Enumeration.Any); public SubInterfaceCustomizer(@Nonnull final FutureJVpp jvpp, @Nonnull final NamingContext interfaceContext) { @@ -56,10 +85,53 @@ public class SubInterfaceCustomizer extends FutureJVppCustomizer this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null"); } + @Nonnull + @Override + public List<SubInterfaceKey> getAllIds(@Nonnull final InstanceIdentifier<SubInterface> id, + @Nonnull final ReadContext context) throws ReadFailedException { + // Relying here that parent InterfaceCustomizer was invoked first (PREORDER) + // to fill in the context with initial ifc mapping + final InterfaceKey key = id.firstKeyOf(Interface.class); + final String ifaceName = key.getName(); + final int ifaceId = interfaceContext.getIndex(ifaceName, context.getMappingContext()); + + // TODO if we know that full dump was already performed we could use cache + // (checking if getCachedInterfaceDump() returns non empty map is not enough, because + // we could be part of particular iface state read + final SwInterfaceDump request = new SwInterfaceDump(); + request.nameFilter = "".getBytes(); + request.nameFilterValid = 0; + + final CompletableFuture<SwInterfaceDetailsReplyDump> swInterfaceDetailsReplyDumpCompletableFuture = + getFutureJVpp().swInterfaceDump(request).toCompletableFuture(); + final SwInterfaceDetailsReplyDump ifaces = + TranslateUtils.getReply(swInterfaceDetailsReplyDumpCompletableFuture); + + if (null == ifaces || null == ifaces.swInterfaceDetails) { + LOG.warn("Looking for sub-interfaces, but no interfaces found in VPP"); + return Collections.emptyList(); + } + + // Cache interfaces dump in per-tx context to later be used in readCurrentAttributes + context.getModificationCache().put(DUMPED_IFCS_CONTEXT_KEY, ifaces.swInterfaceDetails.stream() + .collect(Collectors.toMap(t -> t.swIfIndex, swInterfaceDetails -> swInterfaceDetails))); + + final List<SubInterfaceKey> interfacesKeys = ifaces.swInterfaceDetails.stream() + .filter(elt -> elt != null) + // accept only sub-interfaces for current iface: + .filter(elt -> elt.subId != 0 && elt.supSwIfIndex == ifaceId) + .map(details -> new SubInterfaceKey(new Long(details.subId))) + .collect(Collectors.toList()); + + LOG.debug("Sub-interfaces of {} found in VPP: {}", ifaceName, interfacesKeys); + + return interfacesKeys; + } + @Override - public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, - @Nonnull final SubInterface readValue) { - ((VppInterfaceStateAugmentationBuilder) parentBuilder).setSubInterface(readValue); + public void merge(@Nonnull final Builder<? extends DataObject> builder, + @Nonnull final List<SubInterface> readData) { + ((SubInterfacesBuilder) builder).setSubInterface(readData); } @Nonnull @@ -72,44 +144,94 @@ public class SubInterfaceCustomizer extends FutureJVppCustomizer public void readCurrentAttributes(@Nonnull final InstanceIdentifier<SubInterface> id, @Nonnull final SubInterfaceBuilder builder, @Nonnull final ReadContext ctx) throws ReadFailedException { - final InterfaceKey key = id.firstKeyOf(Interface.class); - // Relying here that parent InterfaceCustomizer was invoked first (PREORDER) - // to fill in the context with initial ifc mapping - final int index = interfaceContext.getIndex(key.getName(), ctx.getMappingContext()); - if (!isInterfaceOfType(ctx.getModificationCache(), index, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.SubInterface.class)) { - return; - } + final String subInterfaceName = getSubInterfaceName(id); + LOG.debug("Reading attributes for sub interface: {}", subInterfaceName); - LOG.debug("Reading attributes for sub interface: {}", id); - final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, index, ctx.getModificationCache()); - LOG.debug("VPP interface details: {}", ReflectionToStringBuilder.toString(iface)); + final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), subInterfaceName, + interfaceContext.getIndex(subInterfaceName, ctx.getMappingContext()), ctx.getModificationCache()); + LOG.debug("VPP sub-interface details: {}", ReflectionToStringBuilder.toString(iface)); - if (iface.subId == 0) { - // Not a sub interface type - return; - } + checkState(iface.subId != 0, "Interface returned by the VPP is not a sub-interface"); builder.setIdentifier(Long.valueOf(iface.subId)); - builder.setSuperInterface(interfaceContext.getName(iface.supSwIfIndex, ctx.getMappingContext())); - builder.setNumberOfTags(Short.valueOf(iface.subNumberOfTags)); - builder.setVlanType(iface.subDot1Ad == 1 ? VlanType._802dot1ad : VlanType._802dot1q); - if (iface.subExactMatch == 1) { - builder.setExactMatch(true); - } - if (iface.subDefault == 1) { - builder.setDefaultSubif(true); - } - if (iface.subOuterVlanIdAny == 1) { - builder.setMatchAnyOuterId(true); + builder.setKey(new SubInterfaceKey(builder.getIdentifier())); + + // sub-interface-base-attributes: + builder.setTags(readTags(iface)); + builder.setMatch(readMatch(iface)); + + // sub-interface-operational-attributes: + builder.setAdminStatus(1 == iface.adminUpDown + ? SubInterfaceStatus.Up + : SubInterfaceStatus.Down); + builder.setOperStatus(1 == iface.linkUpDown + ? SubInterfaceStatus.Up + : SubInterfaceStatus.Down); + builder.setIfIndex(InterfaceUtils.vppIfIndexToYang(iface.swIfIndex)); + if (iface.l2AddressLength == 6) { + builder.setPhysAddress(new PhysAddress(InterfaceUtils.vppPhysAddrToYang(iface.l2Address))); } - if (iface.subOuterVlanIdAny == 1) { - builder.setMatchAnyInnerId(true); + if (0 != iface.linkSpeed) { + builder.setSpeed(InterfaceUtils.vppInterfaceSpeedToYang(iface.linkSpeed)); } - if (iface.subOuterVlanId != 0) { // optional - builder.setOuterId(new VlanTag(Integer.valueOf(iface.subOuterVlanId))); + } + + private static String getSubInterfaceName(final InstanceIdentifier<SubInterface> id) { + return SubInterfaceUtils.getSubInterfaceName(id.firstKeyOf(Interface.class).getName(), + Math.toIntExact(id.firstKeyOf(id.getTargetType()).getIdentifier())); + } + + private Tags readTags(final SwInterfaceDetails iface) { + final TagsBuilder tags = new TagsBuilder(); + final List<Tag> list = new ArrayList<>(); + if (iface.subNumberOfTags > 0) { + if (iface.subOuterVlanIdAny == 1) { + list.add(buildTag((short) 0, SVlan.class, ANY_VLAN_ID)); + } else { + list.add(buildTag((short) 0, SVlan.class, buildVlanId(iface.subOuterVlanId))); + } + // inner tag (customer tag): + if (iface.subNumberOfTags == 2) { + if (iface.subInnerVlanIdAny == 1) { + list.add(buildTag((short) 1, CVlan.class, ANY_VLAN_ID)); + } else { + list.add(buildTag((short) 1, CVlan.class, buildVlanId(iface.subInnerVlanId))); + } + } } - if (iface.subInnerVlanId != 0) { // optional - builder.setInnerId(new VlanTag(Integer.valueOf(iface.subInnerVlanId))); + tags.setTag(list); + return tags.build(); + } + + private static Tag buildTag(final short index, final Class<? extends Dot1qTagVlanType> tagType, + final Dot1qTag.VlanId vlanId) { + TagBuilder tag = new TagBuilder(); + tag.setIndex(index); + tag.setKey(new TagKey(index)); + final Dot1qTagBuilder dtag = new Dot1qTagBuilder(); + dtag.setTagType(tagType); + dtag.setVlanId(vlanId); + tag.setDot1qTag(dtag.build()); + return tag.build(); + } + + private static Dot1qTag.VlanId buildVlanId(final char vlanId) { + return new Dot1qTag.VlanId(new Dot1qVlanId((int) vlanId)); + } + + private Match readMatch(final SwInterfaceDetails iface) { + final MatchBuilder match = new MatchBuilder(); + if (iface.subDefault == 1) { + match.setMatchType(new DefaultBuilder().build()); + } else if (iface.subNumberOfTags == 0) { + match.setMatchType(new UntaggedBuilder().build()); + } else { + final VlanTaggedBuilder tagged = new VlanTaggedBuilder(); + tagged.setMatchExactTags(byteToBoolean(iface.subExactMatch)); + match.setMatchType( + new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.match.attributes.match.type.VlanTaggedBuilder() + .setVlanTagged(tagged.build()).build()); } + return match.build(); } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceL2Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceL2Customizer.java new file mode 100644 index 000000000..baff29466 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/SubInterfaceL2Customizer.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016 Cisco and/or its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; + +import static io.fd.honeycomb.v3po.translate.v3po.util.SubInterfaceUtils.getSubInterfaceName; + +import io.fd.honeycomb.v3po.translate.read.ReadContext; +import io.fd.honeycomb.v3po.translate.read.ReadFailedException; +import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterfaceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.L2; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.L2Builder; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.future.FutureJVpp; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Customizer for reading vlan sub interface L2 operational state + */ +public class SubInterfaceL2Customizer extends FutureJVppCustomizer implements ChildReaderCustomizer<L2, L2Builder> { + + private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceL2Customizer.class); + private final InterconnectionReadUtils icReadUtils; + + public SubInterfaceL2Customizer(@Nonnull final FutureJVpp futureJvpp, + @Nonnull final NamingContext interfaceContext, + @Nonnull final NamingContext bridgeDomainContext) { + super(futureJvpp); + this.icReadUtils = new InterconnectionReadUtils(futureJvpp, interfaceContext, bridgeDomainContext); + } + + @Override + public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, @Nonnull final L2 readValue) { + ((SubInterfaceBuilder) parentBuilder).setL2(readValue); + } + + @Nonnull + @Override + public L2Builder getBuilder(@Nonnull final InstanceIdentifier<L2> id) { + return new L2Builder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2Builder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + LOG.debug("Reading attributes for sub-interface L2: {}", id); + final InterfaceKey parentInterfacekey = id.firstKeyOf(Interface.class); + final SubInterfaceKey subInterfacekey = id.firstKeyOf(SubInterface.class); + final String subInterfaceName = getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue()); + + builder.setInterconnection(icReadUtils.readInterconnection(subInterfaceName, ctx)); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizer.java deleted file mode 100644 index ac180719c..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VlanTagRewriteCustomizer.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; - -import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceUtils.isInterfaceOfType; - -import com.google.common.base.Preconditions; -import io.fd.honeycomb.v3po.translate.read.ReadContext; -import io.fd.honeycomb.v3po.translate.read.ReadFailedException; -import io.fd.honeycomb.v3po.translate.spi.read.ChildReaderCustomizer; -import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; -import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.SubInterface; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.TagRewriteOperation; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VlanTag; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VlanType; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.L2Builder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.l2.VlanTagRewrite; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.l2.VlanTagRewriteBuilder; -import org.opendaylight.yangtools.concepts.Builder; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.jvpp.dto.SwInterfaceDetails; -import org.openvpp.jvpp.future.FutureJVpp; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Customizer for reading vlan tag-rewrite configuration state form the VPP. - */ -public class VlanTagRewriteCustomizer extends FutureJVppCustomizer - implements ChildReaderCustomizer<VlanTagRewrite, VlanTagRewriteBuilder> { - - private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceCustomizer.class); - private final NamingContext interfaceContext; - - public VlanTagRewriteCustomizer(@Nonnull final FutureJVpp futureJvpp, - @Nonnull final NamingContext interfaceContext) { - super(futureJvpp); - this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null"); - } - - @Override - public void merge(@Nonnull final Builder<? extends DataObject> parentBuilder, - @Nonnull final VlanTagRewrite readValue) { - ((L2Builder) parentBuilder).setVlanTagRewrite(readValue); - } - - @Nonnull - @Override - public VlanTagRewriteBuilder getBuilder(@Nonnull final InstanceIdentifier<VlanTagRewrite> id) { - return new VlanTagRewriteBuilder(); - } - - @Override - public void readCurrentAttributes(@Nonnull final InstanceIdentifier<VlanTagRewrite> id, - @Nonnull final VlanTagRewriteBuilder builder, @Nonnull final ReadContext ctx) - throws ReadFailedException { - LOG.debug("Reading attributes for sub interface: {}", id); - final InterfaceKey key = id.firstKeyOf(Interface.class); - - final SwInterfaceDetails iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key, - interfaceContext.getIndex(key.getName(), ctx.getMappingContext()), ctx.getModificationCache()); - - // Tag rewrite is only possible for subinterfaces - if (!isInterfaceOfType(SubInterface.class, iface)) { - return; - } - - builder.setFirstPushed(iface.vtrPushDot1Q == 1 ? VlanType._802dot1q : VlanType._802dot1ad); - builder.setRewriteOperation(TagRewriteOperation.forValue(iface.vtrOp)); - if (iface.vtrTag1 != 0) { - builder.setTag1(new VlanTag(iface.vtrTag1)); - } - if (iface.vtrTag2 != 0) { - builder.setTag2(new VlanTag(iface.vtrTag2)); - } - } -} |