diff options
author | Marek Gradzki <mgradzki@cisco.com> | 2016-05-04 10:17:39 +0200 |
---|---|---|
committer | Marek Gradzki <mgradzki@cisco.com> | 2016-05-05 08:41:23 +0200 |
commit | f187ae2f6a363616442a8968db1450977ce69078 (patch) | |
tree | 7e3c8799f931a47edbbf3a6ec40494a75a2a7d7f /v3po/v3po2vpp/src/main/java/io | |
parent | fd5c022142f871c78d29708c89afc941518acbd0 (diff) |
HONEYCOMB-10: Porting v3po2vpp to the new Java API
Change-Id: Ic7166b0f578442165595aa44a587ebbc5db0e75c
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
Diffstat (limited to 'v3po/v3po2vpp/src/main/java/io')
15 files changed, 552 insertions, 367 deletions
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java index 69ff63137..cdcea45f3 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/EthernetCustomizer.java @@ -19,20 +19,21 @@ package io.fd.honeycomb.v3po.translate.v3po.interfaces; import com.google.common.base.Optional; import io.fd.honeycomb.v3po.translate.Context; import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; -import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; import javax.annotation.Nonnull; 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.Ethernet; 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; -public class EthernetCustomizer extends VppApiCustomizer implements ChildWriterCustomizer<Ethernet> { +public class EthernetCustomizer extends FutureJVppCustomizer implements ChildWriterCustomizer<Ethernet> { private static final Logger LOG = LoggerFactory.getLogger(EthernetCustomizer.class); - public EthernetCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { + public EthernetCustomizer(final FutureJVpp vppApi) { super(vppApi); } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceCustomizer.java index 30600d81e..5d5a6c08b 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/InterfaceCustomizer.java @@ -18,30 +18,36 @@ package io.fd.honeycomb.v3po.translate.v3po.interfaces; import io.fd.honeycomb.v3po.translate.Context; import io.fd.honeycomb.v3po.translate.spi.write.ListWriterCustomizer; -import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; import io.fd.honeycomb.v3po.translate.write.WriteFailedException; import java.util.List; +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; 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.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.vppjapi.vppApi; +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; /** * Ietf interface write customizer that only caches interface objects for child writers */ -public class InterfaceCustomizer extends VppApiCustomizer implements ListWriterCustomizer<Interface, InterfaceKey> { +public class InterfaceCustomizer extends FutureJVppCustomizer implements ListWriterCustomizer<Interface, InterfaceKey> { private static final Logger LOG = LoggerFactory.getLogger(InterfaceCustomizer.class); + private final NamingContext interfaceContext; - public InterfaceCustomizer(final vppApi vppApi) { + public InterfaceCustomizer(final FutureJVpp vppApi, final NamingContext interfaceContext) { super(vppApi); + this.interfaceContext = interfaceContext; } @Override @@ -94,20 +100,15 @@ public class InterfaceCustomizer extends VppApiCustomizer implements ListWriterC LOG.info("Setting interface {}, type: {}", swIf.getName(), swIf.getType().getSimpleName()); LOG.debug("Setting interface {}", swIf); - String swIfName = swIf.getName(); - int swIfIndex = getVppApi().swIfIndexFromName(swIfName); - - setInterfaceAttributes(swIf, swIfName); + setInterfaceAttributes(swIf, swIf.getName()); } private void setInterfaceAttributes(final Interface swIf, final String swIfName) throws VppApiInvocationException { LOG.debug("Creating {} interface {}", swIf.getType().getSimpleName(), swIf.getName()); - setInterfaceFlags(swIfName, getVppApi().swIfIndexFromName(swIfName), + setInterfaceFlags(swIfName, interfaceContext.getIndex(swIfName), swIf.isEnabled() ? (byte) 1 : (byte) 0); - - setDescription(swIf); } private void updateInterface(final InstanceIdentifier<Interface> id, @@ -116,35 +117,33 @@ public class InterfaceCustomizer extends VppApiCustomizer implements ListWriterC LOG.info("Updating interface {}, type: {}", dataAfter.getName(), dataAfter.getType().getSimpleName()); LOG.debug("Updating interface {}", dataAfter); - String swIfName = dataAfter.getName(); - int swIfIndex = getVppApi().swIfIndexFromName(swIfName); - - setInterfaceAttributes(dataAfter, swIfName); + setInterfaceAttributes(dataAfter, dataAfter.getName()); } private void setInterfaceFlags(final String swIfName, final int swIfIndex, final byte enabled) throws VppApiInvocationException { - int ctxId = getVppApi().swInterfaceSetFlags(swIfIndex, enabled, enabled, (byte) 0 /* deleted */); + final CompletionStage<SwInterfaceSetFlagsReply> swInterfaceSetFlagsReplyFuture = getFutureJVpp().swInterfaceSetFlags( + getSwInterfaceSetFlagsInput(swIfIndex, enabled, (byte) 0 /* deleted */)); - LOG.debug("Updating interface flags for: {}, index: {}, enabled: {}, ctxId: {}", swIfName, swIfIndex, - enabled, ctxId); + LOG.debug("Updating interface flags for: {}, index: {}, enabled: {}", swIfName, swIfIndex, enabled); - final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); - if (rv < 0) { - LOG.warn("Failed to update interface flags for: {}, index: {}, enabled: {}, ctxId: {}", swIfName, swIfIndex, - enabled, ctxId); - throw new VppApiInvocationException("swInterfaceSetFlags", ctxId, rv); + SwInterfaceSetFlagsReply reply = V3poUtils.getReply(swInterfaceSetFlagsReplyFuture.toCompletableFuture()); + if (reply.retval < 0) { + LOG.warn("Failed to update interface flags for: {}, index: {}, enabled: {}", swIfName, swIfIndex, + enabled); + throw new VppApiInvocationException("swInterfaceSetFlags", reply.context, reply.retval); } else { LOG.debug("Interface flags updated successfully for: {}, index: {}, enabled: {}, ctxId: {}", - swIfName, swIfIndex, enabled, ctxId); + swIfName, swIfIndex, enabled, reply.context); } } - private void setDescription(final Interface swIf) { - if (swIf.getDescription() != null) { - getVppApi().setInterfaceDescription(swIf.getName(), swIf.getDescription()); - } else { - getVppApi().setInterfaceDescription(swIf.getName(), ""); - } + private SwInterfaceSetFlags getSwInterfaceSetFlagsInput(final int swIfIndex, final byte enabled, final byte deleted) { + final SwInterfaceSetFlags swInterfaceSetFlags = new SwInterfaceSetFlags(); + swInterfaceSetFlags.swIfIndex = swIfIndex; + swInterfaceSetFlags.adminUpDown = enabled; + swInterfaceSetFlags.linkUpDown = enabled; + swInterfaceSetFlags.deleted = deleted; + return swInterfaceSetFlags; } } 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 b9296b481..3bc04f81d 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 @@ -21,10 +21,12 @@ import static com.google.common.base.Preconditions.checkArgument; import com.google.common.base.Optional; import io.fd.honeycomb.v3po.translate.Context; import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; -import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; 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; @@ -34,15 +36,25 @@ 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.interfaces._interface.l2.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; -public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomizer<L2> { +public class L2Customizer extends FutureJVppCustomizer implements ChildWriterCustomizer<L2> { private static final Logger LOG = LoggerFactory.getLogger(L2Customizer.class); + private final NamingContext interfaceContext; + private final NamingContext bridgeDomainContext; - public L2Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + public L2Customizer(final FutureJVpp vppApi, final NamingContext interfaceContext, + final NamingContext bridgeDomainContext) { super(vppApi); + this.interfaceContext = interfaceContext; + this.bridgeDomainContext = bridgeDomainContext; } @Nonnull @@ -57,7 +69,7 @@ public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomi throws WriteFailedException { final String ifcName = id.firstKeyOf(Interface.class).getName(); - final int swIfc = getSwIfc(ifcName); + final int swIfc = interfaceContext.getIndex(ifcName); try { setL2(id, swIfc, ifcName, dataAfter); } catch (VppApiInvocationException e) { @@ -72,7 +84,7 @@ public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomi throws WriteFailedException { final String ifcName = id.firstKeyOf(Interface.class).getName(); - final int swIfc = getSwIfc(ifcName); + final int swIfc = interfaceContext.getIndex(ifcName); // TODO handle update properly (if possible) try { setL2(id, swIfc, ifcName, dataAfter); @@ -82,12 +94,6 @@ public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomi } } - private int getSwIfc(final String ifcName) { - int swIfcIndex = getVppApi().swIfIndexFromName(ifcName); - checkArgument(swIfcIndex != -1, "Interface %s does not exist", ifcName); - return swIfcIndex; - } - @Override public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore, @Nonnull final Context writeContext) { @@ -126,7 +132,9 @@ public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomi bb.getBridgeDomain(), ifcName); String bdName = bb.getBridgeDomain(); - int bdId = getVppApi().bridgeDomainIdFromName(bdName); + + // FIXME need BridgeDomainContext here + int bdId = bridgeDomainContext.getIndex(bdName); checkArgument(bdId > 0, "Unable to set Interconnection for Interface: %s, bridge domain: %s does not exist", ifcName, bdName); @@ -135,19 +143,32 @@ public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomi : (byte) 0; byte shg = bb.getSplitHorizonGroup().byteValue(); - final int ctxId = getVppApi().swInterfaceSetL2Bridge(swIfIndex, bdId, shg, bvi, (byte) 1 /* enable */); - final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); + final CompletionStage<SwInterfaceSetL2BridgeReply> swInterfaceSetL2BridgeReplyCompletionStage = getFutureJVpp() + .swInterfaceSetL2Bridge(getL2BridgeRequest(swIfIndex, bdId, shg, bvi, (byte) 1 /* enable */)); + final SwInterfaceSetL2BridgeReply reply = + V3poUtils.getReply(swInterfaceSetL2BridgeReplyCompletionStage.toCompletableFuture()); - if (rv < 0) { + if (reply.retval < 0) { LOG.warn("Failed to update bridge based interconnection flags for: {}, interconnection: {}", ifcName, bb); - throw new VppApiInvocationException("swInterfaceSetL2Bridge", ctxId, rv); + 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) throws VppApiInvocationException { @@ -155,21 +176,34 @@ public class L2Customizer extends VppApiCustomizer implements ChildWriterCustomi LOG.debug("Setting xconnect based interconnection(outgoing ifc=%s) for interface: %s", outSwIfName, ifcName); - int outSwIfIndex = getVppApi().swIfIndexFromName(outSwIfName); + int outSwIfIndex = interfaceContext.getIndex(outSwIfName); checkArgument(outSwIfIndex > 0, "Unable to set Interconnection for Interface: %s, outgoing interface: %s does not exist", ifcName, outSwIfIndex); - int ctxId = getVppApi().swInterfaceSetL2Xconnect(swIfIndex, outSwIfIndex, (byte) 1 /* enable */); - final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); + final CompletionStage<SwInterfaceSetL2XconnectReply> swInterfaceSetL2XconnectReplyCompletionStage = + getFutureJVpp() + .swInterfaceSetL2Xconnect(getL2XConnectRequest(swIfIndex, outSwIfIndex, (byte) 1 /* enable */)); + final SwInterfaceSetL2XconnectReply reply = + V3poUtils.getReply(swInterfaceSetL2XconnectReplyCompletionStage.toCompletableFuture()); - if (rv < 0) { + if (reply.retval < 0) { LOG.warn("Failed to update xconnect based interconnection flags for: {}, interconnection: {}", ifcName, ic); - throw new VppApiInvocationException("swInterfaceSetL2Xconnect", ctxId, rv); + 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/RoutingCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/RoutingCustomizer.java index 718afc0e1..b15050cd0 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/RoutingCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/RoutingCustomizer.java @@ -16,30 +16,35 @@ 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.Context; import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; -import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +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.utils.V3poUtils; 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.Routing; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.SwInterfaceSetTable; +import org.openvpp.jvpp.dto.SwInterfaceSetTableReply; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class RoutingCustomizer extends VppApiCustomizer implements ChildWriterCustomizer<Routing> { +public class RoutingCustomizer extends FutureJVppCustomizer implements ChildWriterCustomizer<Routing> { private static final Logger LOG = LoggerFactory.getLogger(RoutingCustomizer.class); + private final NamingContext interfaceContext; - public RoutingCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { + public RoutingCustomizer(final FutureJVpp vppApi, final NamingContext interfaceContext) { super(vppApi); + this.interfaceContext = interfaceContext; } @Nonnull @@ -84,7 +89,7 @@ public class RoutingCustomizer extends VppApiCustomizer implements ChildWriterCu } private void setRouting(final String name, final Routing rt) throws VppApiInvocationException { - final int swIfc = getSwIfc(name); + final int swIfc = interfaceContext.getIndex(name); LOG.debug("Setting routing for interface: {}, {}. Routing: {}", name, swIfc, rt); int vrfId = (rt != null) @@ -92,21 +97,25 @@ public class RoutingCustomizer extends VppApiCustomizer implements ChildWriterCu : 0; if (vrfId != 0) { - final int ctxId = getVppApi().swInterfaceSetTable(swIfc, (byte) 0, /* isIpv6 */ vrfId); - final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); - if (rv < 0) { + final CompletionStage<SwInterfaceSetTableReply> swInterfaceSetTableReplyCompletionStage = + getFutureJVpp().swInterfaceSetTable(getInterfaceSetTableRequest(swIfc, (byte) 0, /* isIpv6 */ vrfId)); + final SwInterfaceSetTableReply reply = + V3poUtils.getReply(swInterfaceSetTableReplyCompletionStage.toCompletableFuture()); + if (reply.retval < 0) { LOG.debug("Failed to set routing for interface: {}, {}, vxlan: {}", name, swIfc, rt); - throw new VppApiInvocationException("swInterfaceSetTable", ctxId, rv); + throw new VppApiInvocationException("swInterfaceSetTable", reply.context, reply.retval); } else { LOG.debug("Routing set successfully for interface: {}, {}, routing: {}", name, swIfc, rt); } } } - private int getSwIfc(final String name) { - int swIfcIndex = getVppApi().swIfIndexFromName(name); - checkArgument(swIfcIndex != -1, "Interface %s does not exist", name); - return swIfcIndex; + private SwInterfaceSetTable getInterfaceSetTableRequest(final int swIfc, final byte isIpv6, final int vrfId) { + final SwInterfaceSetTable swInterfaceSetTable = new SwInterfaceSetTable(); + swInterfaceSetTable.isIpv6 = isIpv6; + swInterfaceSetTable.swIfIndex = swIfc; + swInterfaceSetTable.vrfId = vrfId; + return swInterfaceSetTable; } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java index 6e84c303a..2e532660e 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/VxlanCustomizer.java @@ -17,30 +17,36 @@ package io.fd.honeycomb.v3po.translate.v3po.interfaces; import com.google.common.base.Optional; +import com.google.common.net.InetAddresses; import io.fd.honeycomb.v3po.translate.Context; import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; -import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +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.utils.V3poUtils; import io.fd.honeycomb.v3po.translate.write.WriteFailedException; +import java.net.InetAddress; +import java.util.concurrent.CompletionStage; import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone; 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.VxlanTunnel; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Vxlan; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.VxlanAddDelTunnel; +import org.openvpp.jvpp.dto.VxlanAddDelTunnelReply; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class VxlanCustomizer extends VppApiCustomizer implements ChildWriterCustomizer<Vxlan> { +public class VxlanCustomizer extends FutureJVppCustomizer implements ChildWriterCustomizer<Vxlan> { private static final Logger LOG = LoggerFactory.getLogger(VxlanCustomizer.class); + private final NamingContext interfaceContext; - - public VxlanCustomizer(final org.openvpp.vppjapi.vppApi vppApi) { + public VxlanCustomizer(final FutureJVpp vppApi, final NamingContext interfaceContext) { super(vppApi); + this.interfaceContext = interfaceContext; } @Nonnull @@ -84,28 +90,39 @@ public class VxlanCustomizer extends VppApiCustomizer implements ChildWriterCust } private void createVxlanTunnel(final String swIfName, final Vxlan vxlan) throws VppApiInvocationException { - Ipv4AddressNoZone srcAddress = V3poUtils.removeIpv4AddressNoZone(vxlan.getSrc()); - Ipv4AddressNoZone dstAddress = V3poUtils.removeIpv4AddressNoZone(vxlan.getDst()); - - byte[] srcAddr = V3poUtils.ipv4AddressNoZoneToArray(srcAddress); - byte[] dstAddr = V3poUtils.ipv4AddressNoZoneToArray(dstAddress); + final InetAddress srcAddress = InetAddresses.forString(vxlan.getSrc().getValue()); + final InetAddress dstAddress = InetAddresses.forString(vxlan.getDst().getValue()); int encapVrfId = vxlan.getEncapVrfId().intValue(); int vni = vxlan.getVni().getValue().intValue(); LOG.debug("Setting vxlan tunnel for interface: {}. Vxlan: {}", swIfName, vxlan); - int ctxId = 0; getVppApi().vxlanAddDelTunnel( - (byte) 1 /* is add */, - (byte) 0 /* is ipv6 */, - srcAddr, dstAddr, encapVrfId, -1, vni); - final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); - if (rv < 0) { + final CompletionStage<VxlanAddDelTunnelReply> vxlanAddDelTunnelReplyCompletionStage = + getFutureJVpp().vxlanAddDelTunnel(getVxlanTunnelRequest((byte) 1 /* is add */, srcAddress.getAddress(), + dstAddress.getAddress(), encapVrfId, -1, vni, (byte) 0 /* is IPV6 */)); + + final VxlanAddDelTunnelReply reply = + V3poUtils.getReply(vxlanAddDelTunnelReplyCompletionStage.toCompletableFuture()); + if (reply.retval < 0) { LOG.debug("Failed to set vxlan tunnel for interface: {}, vxlan: {}", swIfName, vxlan); - throw new VppApiInvocationException("vxlanAddDelTunnel", ctxId, rv); + throw new VppApiInvocationException("vxlanAddDelTunnel", reply.context, reply.retval); } else { LOG.debug("Vxlan tunnel set successfully for: {}, vxlan: {}", swIfName, vxlan); - // FIXME avoid this dump just to fill cache in vpp-japi - // refresh interfaces to be able to get ifIndex - getVppApi().swInterfaceDump((byte) 1, V3poUtils.IFC_TYPES.inverse().get(VxlanTunnel.class).getBytes()); + // Add new interface to our interface context + interfaceContext.addName(reply.swIfIndex, swIfName); } } + + private VxlanAddDelTunnel getVxlanTunnelRequest(final byte isAdd, final byte[] srcAddr, final byte[] dstAddr, + final int encapVrfId, + final int decapNextIndex, final int vni, final byte isIpv6) { + final VxlanAddDelTunnel vxlanAddDelTunnel = new VxlanAddDelTunnel(); + vxlanAddDelTunnel.isAdd = isAdd; + vxlanAddDelTunnel.srcAddress = srcAddr; + vxlanAddDelTunnel.dstAddress = dstAddr; + vxlanAddDelTunnel.encapVrfId = encapVrfId; + vxlanAddDelTunnel.vni = vni; + vxlanAddDelTunnel.decapNextIndex = decapNextIndex; + vxlanAddDelTunnel.isIpv6 = isIpv6; + return vxlanAddDelTunnel; + } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Interface1Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Interface1Customizer.java index 9f3584908..e309294ef 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Interface1Customizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Interface1Customizer.java @@ -19,16 +19,17 @@ package io.fd.honeycomb.v3po.translate.v3po.interfaces.ip; import com.google.common.base.Optional; import io.fd.honeycomb.v3po.translate.Context; import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; -import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; 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.ip.rev140616.Interface1; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.future.FutureJVpp; -public class Interface1Customizer extends VppApiCustomizer implements ChildWriterCustomizer<Interface1> { +public class Interface1Customizer extends FutureJVppCustomizer implements ChildWriterCustomizer<Interface1> { - public Interface1Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + public Interface1Customizer(final FutureJVpp vppApi) { super(vppApi); } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv4Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv4Customizer.java index 8349ebb9b..de2015c64 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv4Customizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv4Customizer.java @@ -22,10 +22,12 @@ import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.base.Optional; import io.fd.honeycomb.v3po.translate.Context; import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; -import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.NamingContext; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; import io.fd.honeycomb.v3po.translate.v3po.util.VppApiInvocationException; import io.fd.honeycomb.v3po.translate.v3po.utils.V3poUtils; 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.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1; @@ -36,17 +38,23 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev14061 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.address.subnet.PrefixLength; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.SwInterfaceAddDelAddress; +import org.openvpp.jvpp.dto.SwInterfaceAddDelAddressReply; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class Ipv4Customizer extends VppApiCustomizer implements ChildWriterCustomizer<Ipv4> { +public class Ipv4Customizer extends FutureJVppCustomizer implements ChildWriterCustomizer<Ipv4> { private static final Logger LOG = LoggerFactory.getLogger(Ipv4Customizer.class); + private final NamingContext interfaceContext; - public Ipv4Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + public Ipv4Customizer(final FutureJVpp vppApi, final NamingContext interfaceContext) { super(vppApi); + this.interfaceContext = interfaceContext; } + // TODO replace guava's Optionals with Java8 @Nonnull @Override public Optional<Ipv4> extract(@Nonnull final InstanceIdentifier<Ipv4> currentId, @@ -91,7 +99,7 @@ public class Ipv4Customizer extends VppApiCustomizer implements ChildWriterCusto private void setIpv4(final InstanceIdentifier<Ipv4> id, final String name, final Ipv4 ipv4) throws WriteFailedException, VppApiInvocationException { - final int swIfc = getSwIfc(name); + final int swIfc = interfaceContext.getIndex(name); for (Address ipv4Addr : ipv4.getAddress()) { Subnet subnet = ipv4Addr.getSubnet(); @@ -127,24 +135,34 @@ public class Ipv4Customizer extends VppApiCustomizer implements ChildWriterCusto checkArgument(plen > 0, "Invalid length"); checkNotNull(addr, "Null address"); - final int ctxId = getVppApi().swInterfaceAddDelAddress(swIfc, (byte) 1 /* isAdd */, (byte) 0 /* isIpv6 */, - (byte) 0 /* delAll */, plen.byteValue(), addr); + final CompletionStage<SwInterfaceAddDelAddressReply> swInterfaceAddDelAddressReplyCompletionStage = + getFutureJVpp().swInterfaceAddDelAddress(getSwInterfaceAddDelAddressRequest( + swIfc, (byte) 1 /* isAdd */, (byte) 0 /* isIpv6 */, (byte) 0 /* delAll */, plen.byteValue(), addr)); - final int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); - if (rv < 0) { + final SwInterfaceAddDelAddressReply reply = + V3poUtils.getReply(swInterfaceAddDelAddressReplyCompletionStage.toCompletableFuture()); + + if (reply.retval < 0) { LOG.warn("Failed to set Subnet(prefix-length) for interface: {}, {}, Subnet: {}, Ipv4: {}", name, swIfc, subnet, ipv4Addr); - throw new VppApiInvocationException("swInterfaceAddDelAddress", ctxId, rv); + throw new VppApiInvocationException("swInterfaceAddDelAddress", reply.context, reply.retval); } else { LOG.debug("Subnet(prefix-length) set successfully for interface: {}, {}, Subnet: {}, Ipv4: {}", name, swIfc, subnet, ipv4Addr); } } - - private int getSwIfc(final String name) { - int swIfcIndex = getVppApi().swIfIndexFromName(name); - checkArgument(swIfcIndex != -1, "Interface %s does not exist", name); - return swIfcIndex; + private SwInterfaceAddDelAddress getSwInterfaceAddDelAddressRequest(final int swIfc, final byte isAdd, final byte ipv6, + final byte deleteAll, + final byte length, final byte[] addr) { + final SwInterfaceAddDelAddress swInterfaceAddDelAddress = new SwInterfaceAddDelAddress(); + swInterfaceAddDelAddress.swIfIndex = swIfc; + swInterfaceAddDelAddress.isAdd = isAdd; + swInterfaceAddDelAddress.isIpv6 = ipv6; + swInterfaceAddDelAddress.delAll = deleteAll; + swInterfaceAddDelAddress.address = addr; + swInterfaceAddDelAddress.addressLength = length; + return swInterfaceAddDelAddress; } + } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv6Customizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv6Customizer.java index 3798f891a..e3ad3928e 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv6Customizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfaces/ip/Ipv6Customizer.java @@ -19,20 +19,21 @@ package io.fd.honeycomb.v3po.translate.v3po.interfaces.ip; import com.google.common.base.Optional; import io.fd.honeycomb.v3po.translate.Context; import io.fd.honeycomb.v3po.translate.spi.write.ChildWriterCustomizer; -import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import io.fd.honeycomb.v3po.translate.v3po.util.FutureJVppCustomizer; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv6; 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; -public class Ipv6Customizer extends VppApiCustomizer implements ChildWriterCustomizer<Ipv6> { +public class Ipv6Customizer extends FutureJVppCustomizer implements ChildWriterCustomizer<Ipv6> { private static final Logger LOG = LoggerFactory.getLogger(Ipv6Customizer.class); - public Ipv6Customizer(final org.openvpp.vppjapi.vppApi vppApi) { + public Ipv6Customizer(final FutureJVpp vppApi) { super(vppApi); } 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 718cef1b5..f7d473f73 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 @@ -19,6 +19,14 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; import io.fd.honeycomb.v3po.translate.Context; import io.fd.honeycomb.v3po.translate.read.ReadFailedException; 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.utils.V3poUtils; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +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.InterfacesStateBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; @@ -29,21 +37,23 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces. import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.vppjapi.vppInterfaceDetails; +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; -import java.util.ArrayList; -import java.util.List; - -public class InterfaceCustomizer extends io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer +public class InterfaceCustomizer extends FutureJVppCustomizer implements ListReaderCustomizer<Interface, InterfaceKey, InterfaceBuilder> { private static final Logger LOG = LoggerFactory.getLogger(InterfaceCustomizer.class); + private final NamingContext interfaceContext; - public InterfaceCustomizer(org.openvpp.vppjapi.vppApi vppApi) { - super(vppApi); + public InterfaceCustomizer(@Nonnull final FutureJVpp jvpp, final NamingContext interfaceContext) { + super(jvpp); + this.interfaceContext = interfaceContext; } @Override @@ -54,56 +64,67 @@ public class InterfaceCustomizer extends io.fd.honeycomb.v3po.translate.v3po.uti @Override public void readCurrentAttributes(InstanceIdentifier<Interface> id, InterfaceBuilder builder, Context ctx) throws ReadFailedException { - vppInterfaceDetails[] ifaces; - final InterfaceKey key = id.firstKeyOf(id.getTargetType()); - // Extract one interface detail from VPP - ifaces = getVppApi().swInterfaceDump((byte) 1, key.getName().getBytes()); - if (null == ifaces) { - LOG.warn("VPP returned null instead of interface by key {}", key.getName().getBytes()); - return; - } - if (1 != ifaces.length) { - LOG.error("Failed to extract interface {} details from VPP", key.getName()); - return; + final SwInterfaceDetails iface; + try { + iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key); + } catch (Exception e) { + throw new ReadFailedException(id, e); } - final vppInterfaceDetails iface = ifaces[0]; - builder.setName(iface.interfaceName); + builder.setName(key.getName()); // FIXME: report interface type based on name //Tunnel.class l2vlan(802.1q) bridge (transparent bridge?) builder.setType(EthernetCsmacd.class); - builder.setIfIndex(InterfaceUtils.vppIfIndexToYang(iface.ifIndex)); - builder.setAdminStatus(iface.adminUp == 1 ? AdminStatus.Up : AdminStatus.Down); - builder.setOperStatus(1 == iface.linkUp ? OperStatus.Up : OperStatus.Down); + builder.setIfIndex(InterfaceUtils.vppIfIndexToYang(iface.swIfIndex)); + builder.setAdminStatus(iface.adminUpDown == 1 + ? AdminStatus.Up + : AdminStatus.Down); + builder.setOperStatus(1 == iface.linkUpDown + ? OperStatus.Up + : OperStatus.Down); if (0 != iface.linkSpeed) { builder.setSpeed(InterfaceUtils.vppInterfaceSpeedToYang(iface.linkSpeed)); } - if (iface.physAddr.length == 6) { - builder.setPhysAddress(new PhysAddress(InterfaceUtils.vppPhysAddrToYang(iface.physAddr))); + if (iface.l2AddressLength == 6) { + builder.setPhysAddress(new PhysAddress(InterfaceUtils.vppPhysAddrToYang(iface.l2Address))); } } + @Nonnull @Override - public List<InterfaceKey> getAllIds(InstanceIdentifier<Interface> id, Context context) { - vppInterfaceDetails[] ifaces; - final ArrayList<InterfaceKey> interfaceKeys = new ArrayList<>(); - - ifaces = getVppApi().swInterfaceDump((byte) 0, "".getBytes()); - if (null != ifaces) { - for (vppInterfaceDetails ifc : ifaces) { - interfaceKeys.add(new InterfaceKey(ifc.interfaceName)); - } + public List<InterfaceKey> getAllIds(@Nonnull final InstanceIdentifier<Interface> id, + @Nonnull final Context context) throws ReadFailedException { + final SwInterfaceDump request = new SwInterfaceDump(); + request.nameFilter = "".getBytes(); + request.nameFilterValid = 0; + + final CompletableFuture<SwInterfaceDetailsReplyDump> swInterfaceDetailsReplyDumpCompletableFuture = + getFutureJVpp().swInterfaceDump(request).toCompletableFuture(); + final SwInterfaceDetailsReplyDump ifaces = V3poUtils.getReply(swInterfaceDetailsReplyDumpCompletableFuture); + + // TODO can we get null here? + if (null == ifaces || null == ifaces.swInterfaceDetails) { + return Collections.emptyList(); } - return interfaceKeys; + return ifaces.swInterfaceDetails.stream() + .filter(elt -> elt != null) + .map((elt) -> { + // Store interface name from VPP in context if not yet present + if(!interfaceContext.containsName(elt.swIfIndex)){ + interfaceContext.addName(elt.swIfIndex, V3poUtils.toString(elt.interfaceName)); + } + return new InterfaceKey(interfaceContext.getName(elt.swIfIndex)); + }) + .collect(Collectors.toList()); } @Override - public void merge(org.opendaylight.yangtools.concepts.Builder<? extends DataObject> builder, - List<Interface> readData) { + public void merge(@Nonnull final org.opendaylight.yangtools.concepts.Builder<? extends DataObject> builder, + @Nonnull final List<Interface> readData) { ((InterfacesStateBuilder) builder).setInterface(readData); } 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 d589c257f..979c9d6bd 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 @@ -16,15 +16,18 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; import java.math.BigInteger; - +import java.util.concurrent.ExecutionException; import javax.annotation.Nonnull; - +import javax.annotation.Nullable; +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 com.google.common.base.Preconditions; -import org.openvpp.vppjapi.vppApi; -import org.openvpp.vppjapi.vppInterfaceDetails; +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; @@ -42,8 +45,7 @@ public class InterfaceUtils { private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray(); /** - * Convert VPP's link speed bitmask to Yang type. 1 = 10M, 2 = 100M, 4 = 1G, - * 8 = 10G, 16 = 40G, 32 = 100G + * Convert VPP's link speed bitmask to Yang type. 1 = 10M, 2 = 100M, 4 = 1G, 8 = 10G, 16 = 40G, 32 = 100G * * @param vppLinkSpeed Link speed in bitmask format from VPP. * @return Converted value from VPP link speed @@ -74,16 +76,11 @@ public class InterfaceUtils { } /** - * Convert VPP's physical address stored byte array format to string as Yang - * dictates - * <p> - * Replace later with - * https://git.opendaylight.org/gerrit/#/c/34869/10/model/ietf/ietf-type- - * util/src/main/ + * Convert VPP's physical address stored byte array format to string as Yang dictates <p> Replace later with + * https://git.opendaylight.org/gerrit/#/c/34869/10/model/ietf/ietf-type- util/src/main/ * java/org/opendaylight/mdsal/model/ietf/util/AbstractIetfYangUtil.java * - * @param vppPhysAddress byte array of bytes constructing the network IF physical - * address. + * @param vppPhysAddress byte array of bytes constructing the network IF physical address. * @return String like "aa:bb:cc:dd:ee:ff" */ public static String vppPhysAddrToYang(@Nonnull final byte[] vppPhysAddress) { @@ -102,8 +99,8 @@ public class InterfaceUtils { } /** - * VPP's interface index is counted from 0, whereas ietf-interface's - * if-index is from 1. This function converts from VPP's interface index to YANG's interface index. + * VPP's interface index is counted from 0, whereas ietf-interface's if-index is from 1. This function converts from + * VPP's interface index to YANG's interface index. * * @param vppIfIndex the sw interface index VPP reported. * @return VPP's interface index incremented by one @@ -115,7 +112,7 @@ public class InterfaceUtils { /** * This function does the opposite of what {@link #vppIfIndexToYang(int)} does. * - * @param yangIf if-index from ietf-interfaces. + * @param yangIfIndex if-index from ietf-interfaces. * @return VPP's representation of the if-index */ public static int YangIfIndexToVpp(int yangIfIndex) { @@ -124,25 +121,31 @@ public class InterfaceUtils { } - public static vppInterfaceDetails[] getVppInterfaceDetails(final vppApi api, - final boolean specificInterface, - String interfaceName) { - if (interfaceName == null) { - interfaceName = new String(); - } - vppInterfaceDetails[] ifaces = api.swInterfaceDump( - (byte) (specificInterface ? 1 : 0), - interfaceName.getBytes()); - if (null == ifaces) { - LOG.warn("VPP returned null instead of interface by key {}", interfaceName); + /** + * Queries VPP for interface description given interface key. + * + * @param futureJvpp VPP Java Future API + * @param key interface key + * @return SwInterfaceDetails DTO or null if interface was not found + * @throws ExecutionException if exception has been thrown while executing VPP query + * @throws InterruptedException if the current thread was interrupted + */ + @Nullable + public static SwInterfaceDetails getVppInterfaceDetails(@Nonnull final FutureJVpp futureJvpp, + @Nonnull InterfaceKey key) + throws ExecutionException, InterruptedException { + final SwInterfaceDump request = new SwInterfaceDump(); + request.nameFilter = key.getName().getBytes(); + request.nameFilterValid = 1; + + // TODO should we use timeout? + SwInterfaceDetailsReplyDump ifaces = futureJvpp.swInterfaceDump(request).toCompletableFuture().get(); + if (null == ifaces) { // TODO can we get null here? + LOG.warn("VPP returned null instead of interface by key {}", key.getName().getBytes()); return null; } - if (1 != ifaces.length) { - LOG.error("Failed to extract interface {} details from VPP", interfaceName); - } - - return ifaces; + return Iterables.getOnlyElement(ifaces.swInterfaceDetails); } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VppInterfaceStateCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VppInterfaceStateCustomizer.java index 8e5cc8932..2bc8beaaa 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VppInterfaceStateCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/interfacesstate/VppInterfaceStateCustomizer.java @@ -16,11 +16,10 @@ package io.fd.honeycomb.v3po.translate.v3po.interfacesstate; -import static io.fd.honeycomb.v3po.translate.v3po.interfacesstate.InterfaceUtils.getVppInterfaceDetails; - import io.fd.honeycomb.v3po.translate.Context; 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 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.InterfaceBuilder; @@ -32,28 +31,31 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.vppjapi.vppInterfaceDetails; +import org.openvpp.jvpp.dto.SwInterfaceDetails; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class VppInterfaceStateCustomizer extends io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer +public class VppInterfaceStateCustomizer extends FutureJVppCustomizer implements ChildReaderCustomizer<VppInterfaceStateAugmentation, VppInterfaceStateAugmentationBuilder> { private static final Logger LOG = LoggerFactory.getLogger(VppInterfaceStateCustomizer.class); - public VppInterfaceStateCustomizer(org.openvpp.vppjapi.vppApi vppApi) { - super(vppApi); + public VppInterfaceStateCustomizer(@Nonnull final FutureJVpp jvpp) { + super(jvpp); } @Override - public void merge(@Nonnull Builder<? extends DataObject> parentBuilder, @Nonnull VppInterfaceStateAugmentation readValue) { + public void merge(@Nonnull Builder<? extends DataObject> parentBuilder, + @Nonnull VppInterfaceStateAugmentation readValue) { ((InterfaceBuilder) parentBuilder).addAugmentation(VppInterfaceStateAugmentation.class, readValue); } @Nonnull @Override - public VppInterfaceStateAugmentationBuilder getBuilder(@Nonnull InstanceIdentifier<VppInterfaceStateAugmentation> id) { + public VppInterfaceStateAugmentationBuilder getBuilder( + @Nonnull InstanceIdentifier<VppInterfaceStateAugmentation> id) { return new VppInterfaceStateAugmentationBuilder(); } @@ -63,15 +65,15 @@ public class VppInterfaceStateCustomizer extends io.fd.honeycomb.v3po.translate. @Nonnull final Context ctx) throws ReadFailedException { final InterfaceKey key = id.firstKeyOf(Interface.class); - vppInterfaceDetails[] ifaces = getVppInterfaceDetails(getVppApi(), true, key.getName()); - if (null == ifaces || ifaces.length != 1) { - return; + final SwInterfaceDetails iface; + try { + iface = InterfaceUtils.getVppInterfaceDetails(getFutureJVpp(), key); + } catch (Exception e) { + throw new ReadFailedException(id, e); } - final vppInterfaceDetails iface = ifaces[0]; final EthernetBuilder ethernet = new EthernetBuilder(); - - ethernet.setMtu(iface.linkMtu); + ethernet.setMtu((int) iface.linkMtu); switch (iface.linkDuplex) { case 1: ethernet.setDuplex(Ethernet.Duplex.Half); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtils.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtils.java index 88626453e..b4217df46 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtils.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/utils/V3poUtils.java @@ -16,18 +16,17 @@ package io.fd.honeycomb.v3po.translate.v3po.utils; -import com.google.common.base.Preconditions; import com.google.common.base.Splitter; import com.google.common.collect.BiMap; import com.google.common.collect.HashBiMap; -import javax.annotation.Nonnull; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; 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.iana._if.type.rev140508.SoftwareLoopback; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VxlanTunnel; -import org.openvpp.vppjapi.vppApi; +import org.openvpp.jvpp.dto.JVppReply; public final class V3poUtils { @@ -48,25 +47,17 @@ public final class V3poUtils { private V3poUtils() {} - public static int waitForResponse(final int ctxId, final vppApi vppApi) { - int rv; - while ((rv = vppApi.getRetval(ctxId, RELEASE)) == RESPONSE_NOT_READY) { - // TODO limit attempts + public static <REP extends JVppReply<?>> REP getReply(Future<REP> future) { + try { + return future.get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IllegalStateException("Interrupted", e); + } catch (ExecutionException e) { + // Execution exception should not occur, since we are using return codes for errors + // TODO fix when using exceptions instead of return codes + throw new IllegalArgumentException("Future " + " should not fail with an exception", e); } - return rv; - } - - public static int parseIp(final String address) { - int result = 0; - - // iterate over each octet - for (String part : DOT_SPLITTER.split(address)) { - // shift the previously parsed bits over by 1 byte - result = result << 8; - // set the low order bits to the current octet - result |= Integer.parseInt(part); - } - return result; } public static byte[] ipv4AddressNoZoneToArray(final Ipv4AddressNoZone ipv4Addr) { @@ -80,22 +71,10 @@ public final class V3poUtils { } /** - * Removes zone index from Ipv4Address. - * @param ipv4Addr ipv4 address which can contain zone index - * @return ipv4 address without zone index + * Return (interned) string from byte array while removing \u0000. + * Strings represented as fixed length byte[] from vpp contain \u0000. */ - @Nonnull - public static Ipv4AddressNoZone removeIpv4AddressNoZone(@Nonnull final Ipv4Address ipv4Addr) { - Preconditions.checkNotNull(ipv4Addr, "ipv4Addr should not be null"); - if (ipv4Addr instanceof Ipv4AddressNoZone) { - return (Ipv4AddressNoZone)ipv4Addr; - } else { - String value = ipv4Addr.getValue(); - final int index = value.indexOf('%'); - if (index != -1) { - value = value.substring(0, index); - } - return new Ipv4AddressNoZone(value); - } + public static String toString(final byte[] cString) { + return new String(cString).replaceAll("\\u0000", "").intern(); } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizer.java index c69f2ef0a..4b4d7b3c1 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vpp/BridgeDomainCustomizer.java @@ -18,12 +18,15 @@ package io.fd.honeycomb.v3po.translate.v3po.vpp; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import io.fd.honeycomb.v3po.translate.spi.write.ListWriterCustomizer; -import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import com.google.common.base.Preconditions; import io.fd.honeycomb.v3po.translate.Context; +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.utils.V3poUtils; +import io.fd.honeycomb.v3po.translate.write.WriteFailedException; import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -32,19 +35,24 @@ 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.vpp.bridge.domains.BridgeDomainKey; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.dto.BridgeDomainAddDel; +import org.openvpp.jvpp.dto.BridgeDomainAddDelReply; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class BridgeDomainCustomizer - extends VppApiCustomizer - implements ListWriterCustomizer<BridgeDomain, BridgeDomainKey> { + extends FutureJVppCustomizer + implements ListWriterCustomizer<BridgeDomain, BridgeDomainKey> { private static final Logger LOG = LoggerFactory.getLogger(BridgeDomainCustomizer.class); private static final byte ADD_OR_UPDATE_BD = (byte) 1; + private final NamingContext bdContext; - public BridgeDomainCustomizer(final org.openvpp.vppjapi.vppApi api) { - super(api); + public BridgeDomainCustomizer(@Nonnull final FutureJVpp futureJvpp, @Nonnull final NamingContext bdContext) { + super(futureJvpp); + this.bdContext = Preconditions.checkNotNull(bdContext, "bdContext should not be null"); } @Nonnull @@ -54,76 +62,96 @@ public class BridgeDomainCustomizer return ((BridgeDomains) parentData).getBridgeDomain(); } - private int addOrUpdateBridgeDomain(final int bdId, @Nonnull final BridgeDomain bd) { - byte flood = booleanToByte(bd.isFlood()); - byte forward = booleanToByte(bd.isForward()); - byte learn = booleanToByte(bd.isLearn()); - byte uuf = booleanToByte(bd.isUnknownUnicastFlood()); - byte arpTerm = booleanToByte(bd.isArpTermination()); - - int ctxId = getVppApi().bridgeDomainAddDel(bdId, flood, forward, learn, uuf, arpTerm, ADD_OR_UPDATE_BD); - return V3poUtils.waitForResponse(ctxId, getVppApi()); + private BridgeDomainAddDelReply addOrUpdateBridgeDomain(final int bdId, @Nonnull final BridgeDomain bd) + throws VppApiInvocationException { + final BridgeDomainAddDel request = new BridgeDomainAddDel(); + request.bdId = bdId; + request.flood = booleanToByte(bd.isFlood()); + request.forward = booleanToByte(bd.isForward()); + request.learn = booleanToByte(bd.isLearn()); + request.uuFlood = booleanToByte(bd.isUnknownUnicastFlood()); + request.arpTerm = booleanToByte(bd.isArpTermination()); + request.isAdd = ADD_OR_UPDATE_BD; + + final BridgeDomainAddDelReply reply = + V3poUtils.getReply(getFutureJVpp().bridgeDomainAddDel(request).toCompletableFuture()); + if (reply.retval < 0) { + LOG.warn("Bridge domain {} (id={}) add/update failed", bd.getName(), bdId); + throw new VppApiInvocationException("bridgeDomainAddDel", reply.context, reply.retval); + } else { + LOG.debug("Bridge domain {} (id={}) add/update successful", bd.getName(), bdId); + } + + return reply; } @Override public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id, - @Nonnull final BridgeDomain current, - @Nonnull final Context ctx) { - LOG.debug("writeCurrentAttributes: id={}, current={}, ctx={}", id, current, ctx); - final String bdName = current.getName(); - int bdId = getVppApi().findOrAddBridgeDomainId(bdName); - checkState(bdId > 0, "Unable to find or create bridge domain. Return code: %s", bdId); - - int rv = addOrUpdateBridgeDomain(bdId, current); - - checkState(rv >= 0, "Bridge domain %s(%s) write failed. Return code: %s", bdName, bdId, rv); - LOG.debug("Bridge domain {} written as {} successfully", bdName, bdId); + @Nonnull final BridgeDomain dataBefore, + @Nonnull final Context ctx) throws WriteFailedException.CreateFailedException { + LOG.debug("writeCurrentAttributes: id={}, current={}, ctx={}", id, dataBefore, ctx); + final String bdName = dataBefore.getName(); + + try { + // FIXME we need the bd index to be returned by VPP or we should have a counter field (maybe in context similar to artificial name) + // Here we assign the next available ID from bdContext's perspective + int index = 1; + while(bdContext.containsName(index)) { + index++; + } + addOrUpdateBridgeDomain(index, dataBefore); + bdContext.addName(index, bdName); + } catch (VppApiInvocationException e) { + LOG.warn("Failed to create bridge domain", e); + throw new WriteFailedException.CreateFailedException(id, dataBefore, e); + } } private byte booleanToByte(@Nullable final Boolean aBoolean) { - return aBoolean != null && aBoolean ? (byte) 1 : (byte) 0; + return aBoolean != null && aBoolean + ? (byte) 1 + : (byte) 0; } @Override public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id, @Nonnull final BridgeDomain dataBefore, - @Nonnull final Context ctx) { + @Nonnull final Context ctx) throws WriteFailedException.DeleteFailedException { LOG.debug("deleteCurrentAttributes: id={}, dataBefore={}, ctx={}", id, dataBefore, ctx); - String bdName = id.firstKeyOf(BridgeDomain.class).getName(); - - int bdId = getVppApi().bridgeDomainIdFromName(bdName); - checkState(bdId > 0, "Unable to delete bridge domain. Does not exist. Return code: %s", bdId); - int ctxId = getVppApi().bridgeDomainAddDel(bdId, - (byte) 0 /* flood */, - (byte) 0 /* forward */, - (byte) 0 /* learn */, - (byte) 0 /* uuf */, - (byte) 0 /* arpTerm */, - (byte) 0 /* isAdd */); - - int rv = V3poUtils.waitForResponse(ctxId, getVppApi()); - - checkState(rv >= 0, "Bridge domain delete failed. Return code: %s", rv); - LOG.debug("Bridge domain {} deleted as {} successfully", bdName, bdId); + final String bdName = id.firstKeyOf(BridgeDomain.class).getName(); + int bdId = bdContext.getIndex(bdName); + final BridgeDomainAddDel request = new BridgeDomainAddDel(); + request.bdId = bdId; + + final BridgeDomainAddDelReply reply = + V3poUtils.getReply(getFutureJVpp().bridgeDomainAddDel(request).toCompletableFuture()); + if (reply.retval < 0) { + LOG.warn("Bridge domain {} (id={}) delete failed", bdName, bdId); + throw new WriteFailedException.DeleteFailedException(id, + new VppApiInvocationException("bridgeDomainAddDel", reply.context, reply.retval)); + } else { + LOG.debug("Bridge domain {} (id={}) deleted successfully", bdName, bdId); + } } @Override public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id, @Nonnull final BridgeDomain dataBefore, @Nonnull final BridgeDomain dataAfter, - @Nonnull final Context ctx) { - LOG.debug("updateCurrentAttributes: id={}, dataBefore={}, dataAfter={}, ctx={}", id, dataBefore, dataAfter, ctx); + @Nonnull final Context ctx) throws WriteFailedException.UpdateFailedException { + LOG.debug("updateCurrentAttributes: id={}, dataBefore={}, dataAfter={}, ctx={}", id, dataBefore, dataAfter, + ctx); final String bdName = checkNotNull(dataAfter.getName()); - checkArgument(bdName.equals(dataBefore.getName()), "BridgeDomain name changed. It should be deleted and then created."); - - int bdId = getVppApi().bridgeDomainIdFromName(bdName); - checkState(bdId > 0, "Unable to find bridge domain. Return code: %s", bdId); - - final int rv = addOrUpdateBridgeDomain(bdId, dataAfter); - - checkState(rv >= 0, "Bridge domain %s(%s) update failed. Return code: %s", bdName, bdId, rv); - LOG.debug("Bridge domain {}({}) updated successfully", bdName, bdId); + checkArgument(bdName.equals(dataBefore.getName()), + "BridgeDomain name changed. It should be deleted and then created."); + + try { + addOrUpdateBridgeDomain(bdContext.getIndex(bdName), dataAfter); + } catch (VppApiInvocationException e) { + LOG.warn("Failed to create bridge domain", e); + throw new WriteFailedException.UpdateFailedException(id, dataBefore, dataAfter, e); + } } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/BridgeDomainCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/BridgeDomainCustomizer.java index 61c345b44..addb425f6 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/BridgeDomainCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/BridgeDomainCustomizer.java @@ -16,10 +16,15 @@ package io.fd.honeycomb.v3po.translate.v3po.vppstate; +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; -import io.fd.honeycomb.v3po.translate.spi.read.ListReaderCustomizer; -import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +import com.google.common.primitives.Longs; import io.fd.honeycomb.v3po.translate.Context; +import io.fd.honeycomb.v3po.translate.read.ReadFailedException; +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 java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -34,104 +39,150 @@ 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.vpp.state.bridge.domains.bridge.domain.InterfaceKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.bridge.domain.L2Fib; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.bridge.domain.L2FibBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.bridge.domains.bridge.domain.L2FibKey; import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.vppjapi.vppBridgeDomainDetails; -import org.openvpp.vppjapi.vppBridgeDomainInterfaceDetails; -import org.openvpp.vppjapi.vppL2Fib; +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.L2FibTableDump; +import org.openvpp.jvpp.dto.L2FibTableEntry; +import org.openvpp.jvpp.dto.L2FibTableEntryReplyDump; +import org.openvpp.jvpp.future.FutureJVpp; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public final class BridgeDomainCustomizer extends VppApiCustomizer - implements ListReaderCustomizer<BridgeDomain, BridgeDomainKey, BridgeDomainBuilder> { +public final class BridgeDomainCustomizer extends FutureJVppCustomizer + implements ListReaderCustomizer<BridgeDomain, BridgeDomainKey, BridgeDomainBuilder> { private static final Logger LOG = LoggerFactory.getLogger(BridgeDomainCustomizer.class); - - public BridgeDomainCustomizer(@Nonnull final org.openvpp.vppjapi.vppApi vppApi) { - super(vppApi); + private final NamingContext bdContext; + private final NamingContext interfaceContext; + + public BridgeDomainCustomizer(@Nonnull final FutureJVpp futureJVpp, @Nonnull final NamingContext bdContext, + @Nonnull final NamingContext interfaceContext) { + super(futureJVpp); + this.bdContext = Preconditions.checkNotNull(bdContext, "bdContext should not be null"); + this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null");; } @Override public void readCurrentAttributes(@Nonnull final InstanceIdentifier<BridgeDomain> id, - @Nonnull final BridgeDomainBuilder builder, @Nonnull final Context context) { + @Nonnull final BridgeDomainBuilder builder, @Nonnull final Context context) + throws ReadFailedException { LOG.debug("vppstate.BridgeDomainCustomizer.readCurrentAttributes: id={}, builderbuilder={}, context={}", id, builder, context); final BridgeDomainKey key = id.firstKeyOf(id.getTargetType()); LOG.debug("vppstate.BridgeDomainCustomizer.readCurrentAttributes: key={}", key); - final int bdId = getVppApi().bridgeDomainIdFromName(key.getName()); + final int bdId = bdContext.getIndex(key.getName()); LOG.debug("vppstate.BridgeDomainCustomizer.readCurrentAttributes: bdId={}", bdId); - final vppBridgeDomainDetails bridgeDomainDetails = getVppApi().getBridgeDomainDetails(bdId); - if(bridgeDomainDetails == null) { - LOG.debug("Bridge domain name={} does not exist", key.getName()); + BridgeDomainDetailsReplyDump reply; + BridgeDomainDetails bridgeDomainDetails; + final BridgeDomainDump request = new BridgeDomainDump(); + request.bdId = bdContext.getIndex(key.getName()); + try { + reply = getFutureJVpp().bridgeDomainDump(request).toCompletableFuture().get(); + bridgeDomainDetails = Iterables.getOnlyElement(reply.bridgeDomainDetails); + } catch (Exception e) { + LOG.debug("Unable to read bridge domain: {}", key.getName(), e); return; } + logBridgeDomainDetails(bridgeDomainDetails); builder.setName(key.getName()); - // builder.setName(bridgeDomainDetails.name); - builder.setArpTermination(bridgeDomainDetails.arpTerm); - builder.setFlood(bridgeDomainDetails.flood); - builder.setForward(bridgeDomainDetails.forward); - builder.setLearn(bridgeDomainDetails.learn); - builder.setUnknownUnicastFlood(bridgeDomainDetails.uuFlood); - - builder.setInterface(getIfcs(bridgeDomainDetails)); - - final vppL2Fib[] vppL2Fibs = getVppApi().l2FibTableDump(bdId); - - final List<L2Fib> l2Fibs = Lists.newArrayListWithCapacity(vppL2Fibs.length); - for (vppL2Fib vppL2Fib : vppL2Fibs) { - l2Fibs.add(new L2FibBuilder() - .setAction((vppL2Fib.filter - ? L2Fib.Action.Filter - : L2Fib.Action.Forward)) - .setBridgedVirtualInterface(vppL2Fib.bridgedVirtualInterface) - .setOutgoingInterface(vppL2Fib.outgoingInterface) - .setPhysAddress(new PhysAddress(getMacAddress(vppL2Fib.physAddress))) - .setStaticConfig(vppL2Fib.staticConfig) - .build()); + builder.setArpTermination(byteToBoolean(bridgeDomainDetails.arpTerm)); + builder.setFlood(byteToBoolean(bridgeDomainDetails.flood)); + builder.setForward(byteToBoolean(bridgeDomainDetails.forward)); + builder.setLearn(byteToBoolean(bridgeDomainDetails.learn)); + builder.setUnknownUnicastFlood(byteToBoolean(bridgeDomainDetails.uuFlood)); + + builder.setInterface(getIfcs(bridgeDomainDetails, reply.bridgeDomainSwIfDetails)); + + final L2FibTableDump l2FibRequest = new L2FibTableDump(); + l2FibRequest.bdId = bdId; + try { + final L2FibTableEntryReplyDump dump = + getFutureJVpp().l2FibTableDump(l2FibRequest).toCompletableFuture().get(); + final List<L2Fib> l2Fibs = Lists.newArrayListWithCapacity(dump.l2FibTableEntry.size()); + for (L2FibTableEntry entry : dump.l2FibTableEntry) { + // entry.mac is a long value in the format 66:55:44:33:22:11:XX:XX + // where mac address is 11:22:33:44:55:66 + final PhysAddress address = new PhysAddress(getMacAddress(Longs.toByteArray(entry.mac))); + l2Fibs.add(new L2FibBuilder() + .setAction((byteToBoolean(entry.filterMac) + ? L2Fib.Action.Filter + : L2Fib.Action.Forward)) + .setBridgedVirtualInterface(byteToBoolean(entry.bviMac)) + .setOutgoingInterface(interfaceContext.getName(entry.swIfIndex)) + .setStaticConfig(byteToBoolean(entry.staticMac)) + .setPhysAddress(address) + .setKey(new L2FibKey(address)) + .build()); + } + builder.setL2Fib(l2Fibs); + + } catch (Exception e) { + LOG.warn("Failed to acquire l2FibTableDump for domain id={}", bdId, e); + } + } + + // TODO move to utils + private static Boolean byteToBoolean(final byte aByte) { + if (aByte == 0) { + return Boolean.FALSE; + } else if (aByte == 1) { + return Boolean.TRUE; } - builder.setL2Fib(l2Fibs); + throw new IllegalArgumentException(String.format("0 or 1 was expected but was %d", aByte)); } - private void logBridgeDomainDetails(final vppBridgeDomainDetails bridgeDomainDetails) { + private void logBridgeDomainDetails(final BridgeDomainDetails bridgeDomainDetails) { LOG.debug("bridgeDomainDetails={}", bridgeDomainDetails); if (bridgeDomainDetails != null) { LOG.debug("bridgeDomainDetails.arpTerm={}", bridgeDomainDetails.arpTerm); LOG.debug("bridgeDomainDetails.bdId={}", bridgeDomainDetails.bdId); - LOG.debug("bridgeDomainDetails.bviInterfaceName={}", bridgeDomainDetails.bviInterfaceName); + LOG.debug("bridgeDomainDetails.bviSwIfIndex={}", bridgeDomainDetails.bviSwIfIndex); LOG.debug("bridgeDomainDetails.flood={}", bridgeDomainDetails.flood); LOG.debug("bridgeDomainDetails.forward={}", bridgeDomainDetails.forward); LOG.debug("bridgeDomainDetails.learn={}", bridgeDomainDetails.learn); - LOG.debug("bridgeDomainDetails.name={}", bridgeDomainDetails.name); + LOG.debug("bridgeDomainDetails.nSwIfs={}", bridgeDomainDetails.nSwIfs); LOG.debug("bridgeDomainDetails.uuFlood={}", bridgeDomainDetails.uuFlood); } } - + // TODO move to some utility class private static String getMacAddress(byte[] mac) { StringBuilder sb = new StringBuilder(18); - for (byte b : mac) { + for (int i=5; i>=0; --i) { if (sb.length() > 0) { sb.append(':'); } - sb.append(String.format("%02x", b)); + sb.append(String.format("%02x", mac[i])); } return sb.toString(); } - private List<Interface> getIfcs(final vppBridgeDomainDetails bridgeDomainDetails) { - final List<Interface> ifcs = new ArrayList<>(bridgeDomainDetails.interfaces.length); - for (vppBridgeDomainInterfaceDetails anInterface : bridgeDomainDetails.interfaces) { - ifcs.add(new InterfaceBuilder() - .setBridgedVirtualInterface(bridgeDomainDetails.bviInterfaceName.equals(anInterface.interfaceName)) - .setName(anInterface.interfaceName) - .setKey(new InterfaceKey(anInterface.interfaceName)) - .build()); + private List<Interface> getIfcs(final BridgeDomainDetails bridgeDomainDetails, + final List<BridgeDomainSwIfDetails> bridgeDomainSwIfDetails) { + final List<Interface> ifcs = new ArrayList<>(bridgeDomainSwIfDetails.size()); + for (BridgeDomainSwIfDetails anInterface : bridgeDomainSwIfDetails) { + final String interfaceName = interfaceContext.getName(anInterface.swIfIndex); + if (anInterface.bdId == bridgeDomainDetails.bdId) { + ifcs.add(new InterfaceBuilder() + .setBridgedVirtualInterface(bridgeDomainDetails.bviSwIfIndex == anInterface.swIfIndex) + .setSplitHorizonGroup((short) anInterface.shg) + .setName(interfaceName) + .setKey(new InterfaceKey(interfaceName)) + .build()); + } + + } return ifcs; } @@ -144,25 +195,34 @@ public final class BridgeDomainCustomizer extends VppApiCustomizer @Nonnull @Override - public List<BridgeDomainKey> getAllIds(@Nonnull final InstanceIdentifier<BridgeDomain> id, @Nonnull final Context context) { - final int[] bIds = getVppApi().bridgeDomainDump(-1); + public List<BridgeDomainKey> getAllIds(@Nonnull final InstanceIdentifier<BridgeDomain> id, + @Nonnull final Context context) { + final BridgeDomainDump request = new BridgeDomainDump(); + request.bdId = -1; // dump call + + BridgeDomainDetailsReplyDump reply; + try { + reply = getFutureJVpp().bridgeDomainDump(request).toCompletableFuture().get(); + } catch (Exception e) { + throw new IllegalStateException("Bridge domain dump failed", e); // TODO ReadFailedException? + } - if(bIds == null) { + if(reply == null || reply.bridgeDomainDetails == null) { + return Collections.emptyList(); + } + + final int bIdsLength = reply.bridgeDomainDetails.size(); + LOG.debug("vppstate.BridgeDomainCustomizer.getAllIds: bIds.length={}", bIdsLength); + if (bIdsLength == 0) { // No bridge domains return Collections.emptyList(); } - LOG.debug("vppstate.BridgeDomainCustomizer.getAllIds: bIds.length={}", bIds.length); - final List<BridgeDomainKey> allIds = new ArrayList<>(bIds.length); - for (int bId : bIds) { - LOG.debug("vppstate.BridgeDomainCustomizer.getAllIds: bId={}", bId); - // FIXME this is highly inefficient having to dump all of the bridge domain details - // Use context to store already read information - // TODO Or just remove the getAllIds method and replace with a simple readAll - final vppBridgeDomainDetails bridgeDomainDetails = getVppApi().getBridgeDomainDetails(bId); - logBridgeDomainDetails(bridgeDomainDetails); - - final String bName = bridgeDomainDetails.name; + final List<BridgeDomainKey> allIds = new ArrayList<>(bIdsLength); + for (BridgeDomainDetails detail : reply.bridgeDomainDetails) { + logBridgeDomainDetails(detail); + + final String bName = bdContext.getName(detail.bdId); LOG.debug("vppstate.BridgeDomainCustomizer.getAllIds: bName={}", bName); allIds.add(new BridgeDomainKey(bName)); } @@ -171,7 +231,8 @@ public final class BridgeDomainCustomizer extends VppApiCustomizer } @Override - public void merge(@Nonnull final Builder<? extends DataObject> builder, @Nonnull final List<BridgeDomain> readData) { + public void merge(@Nonnull final Builder<? extends DataObject> builder, + @Nonnull final List<BridgeDomain> readData) { ((BridgeDomainsBuilder) builder).setBridgeDomain(readData); } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VersionCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VersionCustomizer.java index 31e3166bb..1db8217f9 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VersionCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/v3po/translate/v3po/vppstate/VersionCustomizer.java @@ -17,8 +17,10 @@ package io.fd.honeycomb.v3po.translate.v3po.vppstate; import io.fd.honeycomb.v3po.translate.Context; -import io.fd.honeycomb.v3po.translate.v3po.util.VppApiCustomizer; +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.utils.V3poUtils; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppStateBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.vpp.state.Version; @@ -26,14 +28,16 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.openvpp.vppjapi.vppVersion; +import org.openvpp.jvpp.dto.ShowVersion; +import org.openvpp.jvpp.dto.ShowVersionReply; +import org.openvpp.jvpp.future.FutureJVpp; public final class VersionCustomizer - extends VppApiCustomizer + extends FutureJVppCustomizer implements ChildReaderCustomizer<Version, VersionBuilder> { - public VersionCustomizer(@Nonnull final org.openvpp.vppjapi.vppApi vppApi) { - super(vppApi); + public VersionCustomizer(@Nonnull final FutureJVpp futureJVpp) { + super(futureJVpp); } @Override @@ -49,11 +53,18 @@ public final class VersionCustomizer @Override public void readCurrentAttributes(@Nonnull InstanceIdentifier<Version> id, @Nonnull final VersionBuilder builder, - @Nonnull final Context context) { - final vppVersion vppVersion = getVppApi().getVppVersion(); - builder.setBranch(vppVersion.gitBranch); - builder.setName(vppVersion.programName); - builder.setBuildDate(vppVersion.buildDate); - builder.setBuildDirectory(vppVersion.buildDirectory); + @Nonnull final Context context) throws ReadFailedException { + + ShowVersionReply reply; + try { + reply = getFutureJVpp().showVersion(new ShowVersion()).toCompletableFuture().get(); + } catch (Exception e) { + throw new ReadFailedException(id, e); + } + builder.setBranch(V3poUtils.toString(reply.version)); + builder.setName(V3poUtils.toString(reply.program)); + builder.setBuildDate(V3poUtils.toString(reply.buildDate)); + builder.setBuildDirectory(V3poUtils.toString(reply.buildDirectory)); } + } |