diff options
author | Marek Gradzki <mgradzki@cisco.com> | 2016-07-20 09:48:14 +0200 |
---|---|---|
committer | Marek Gradzki <mgradzki@cisco.com> | 2016-09-13 09:44:50 +0200 |
commit | 6509e0875c394fa122e56bbaa93b2f11205d1d67 (patch) | |
tree | 4eb29d0f6cef0ce31bae4f25f3a99f25fa64f253 | |
parent | 81d2be3f014af6fd453b0be73999c38f7e2f734f (diff) |
HONEYCOMB-118: extend classifer model to support node names.
* configuration write is supported (updates local cache
with relative node mapping)
* operational read is supported only for nodes with existing
relative node mapping
* ACL support (using vpp-classfier or ietf-acl model)
is not affected by the patch (tables/sessions for access controll
refer to neighbour nodes as packet-handling-action, not vpp-node-name)
Change-Id: Ice0c846803cc7e8960c3571fd2a13ed46ba53702
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
31 files changed, 821 insertions, 225 deletions
diff --git a/v3po/api/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vpp/classifier/rev150603/VppNodeBuilder.java b/v3po/api/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vpp/classifier/rev150603/VppNodeBuilder.java index dd37bbe84..4ae04d48f 100644 --- a/v3po/api/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vpp/classifier/rev150603/VppNodeBuilder.java +++ b/v3po/api/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/vpp/classifier/rev150603/VppNodeBuilder.java @@ -18,7 +18,7 @@ public class VppNodeBuilder { } else if (PacketHandlingAction.Permit.toString().equalsIgnoreCase(defaultValue)) { return new VppNode(PacketHandlingAction.Permit); } else { - throw new IllegalArgumentException(String.format("Could not parse VppNode: %s", defaultValue)); + return new VppNode(new VppNodeName(defaultValue)); } } diff --git a/v3po/api/src/main/yang/vpp-classifier-context.yang b/v3po/api/src/main/yang/vpp-classifier-context.yang new file mode 100644 index 000000000..01eae862d --- /dev/null +++ b/v3po/api/src/main/yang/vpp-classifier-context.yang @@ -0,0 +1,68 @@ +module vpp-classifier-context { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:vpp:classifier"; + prefix "vpp-classifier-context"; + + description + "This module contains vpp classfier metadata definition"; + + revision "2016-09-09" { + description + "Initial revision."; + } + + container vpp-classifier-context { + + config "false"; + + description + "Classify tables and sessions contain relative node indexes. Management agent like Honeycomb, + needs to use node names instead (indexes might change after vpp restart). + VPP does not provide relative index to node name conversion (https://jira.fd.io/browse/VPP-219), + also finding base node that is needed to perform the conversion + is not allways possible (https://jira.fd.io/browse/VPP-220). + + Therefore Honeycomb needs to provide relative node to index mapping. + "; + + list classify-table-context { + key "name"; + unique "index"; + + leaf name { + type string; + description + "Name of the classify table."; + } + + leaf index { + type int32; + description + "Classify table index used by VPP."; + } + + leaf classifier-node-name { + type string; + description + "Name of VPP node the table is defined for."; + } + + list node-context { + key "name"; + unique "index"; + + leaf name { + type string; + description + "Name of vpp node (neighbour of classifier-node-name)"; + } + + leaf index { + type int32; + description + "Inted of the vpp node relative to classifier-node-name"; + } + } + } + } +}
\ No newline at end of file diff --git a/v3po/api/src/main/yang/vpp-classifier.yang b/v3po/api/src/main/yang/vpp-classifier.yang index 46bff2074..8bf939933 100644 --- a/v3po/api/src/main/yang/vpp-classifier.yang +++ b/v3po/api/src/main/yang/vpp-classifier.yang @@ -38,14 +38,18 @@ module vpp-classifier { } } + typedef vpp-node-name { + type string; + } + typedef vpp-node { type union { - // FIXME: enable after VPP-203 is fixed - // type string; // name of vpp-node neighbour, TODO: base node also needs to be defined type packet-handling-action; + type vpp-node-name; } description - "Defines VPP node reference using relative node name or packet handling action."; + "Defines VPP node reference using packet handling action or relative node name + (if definition in terms of packet handling action is not possible)."; } typedef opaque-index { @@ -85,6 +89,11 @@ module vpp-classifier { description "Defines classify table attributes that are mapped to classify_add_del_table message parameters."; + leaf classifier-node { + type vpp-node-name; + description + "Name of VPP node the table is defined for."; + } leaf nbuckets { mandatory true; type uint32; diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesStateReaderFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesStateReaderFactory.java index f2936cd9c..c0c0530d3 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesStateReaderFactory.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesStateReaderFactory.java @@ -38,6 +38,7 @@ import io.fd.honeycomb.translate.v3po.interfacesstate.ip.Ipv4Customizer; import io.fd.honeycomb.translate.v3po.interfacesstate.ip.Ipv4NeighbourCustomizer; import io.fd.honeycomb.translate.v3po.interfacesstate.ip.Ipv6Customizer; import io.fd.honeycomb.translate.v3po.util.NamingContext; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; 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; @@ -68,7 +69,7 @@ public final class InterfacesStateReaderFactory implements ReaderFactory { private final NamingContext ifcNamingCtx; private final NamingContext bdNamingCtx; - private final NamingContext classifyNamingCtx; + private final VppClassifierContextManager classifyContext; private final DisabledInterfacesManager ifcDisableContext; private final FutureJVppCore jvpp; @@ -80,12 +81,12 @@ public final class InterfacesStateReaderFactory implements ReaderFactory { public InterfacesStateReaderFactory(final FutureJVppCore jvpp, @Named("interface-context") final NamingContext ifcNamingCtx, @Named("bridge-domain-context") final NamingContext bdNamingCtx, - @Named("classify-table-context") final NamingContext classifyNamingCtx, + @Named("classify-table-context") final VppClassifierContextManager classifyContext, final DisabledInterfacesManager ifcDisableContext) { this.jvpp = jvpp; this.ifcNamingCtx = ifcNamingCtx; this.bdNamingCtx = bdNamingCtx; - this.classifyNamingCtx = classifyNamingCtx; + this.classifyContext = classifyContext; this.ifcDisableContext = ifcDisableContext; } @@ -101,7 +102,7 @@ public final class InterfacesStateReaderFactory implements ReaderFactory { // ietf-ip.yang initInterface2AugmentationReaders(registry, IFC_ID); // vpp-vlan.yang - new SubinterfaceStateAugmentationReaderFactory(jvpp, ifcNamingCtx, bdNamingCtx, classifyNamingCtx).init(registry); + new SubinterfaceStateAugmentationReaderFactory(jvpp, ifcNamingCtx, bdNamingCtx, classifyContext).init(registry); } private void initInterface2AugmentationReaders(final ModifiableReaderRegistryBuilder registry, @@ -149,7 +150,7 @@ public final class InterfacesStateReaderFactory implements ReaderFactory { registry.subtreeAdd( Sets.newHashSet(aclIdRelative.child(L2Acl.class), aclIdRelative.child(Ip4Acl.class), aclIdRelative.child(Ip6Acl.class)), new GenericReader<>(vppIfcAugId.child(Acl.class), new AclCustomizer(jvpp, ifcNamingCtx, - classifyNamingCtx))); + classifyContext))); // Proxy ARP registry.add(new GenericReader<>(vppIfcAugId.child(ProxyArp.class), new ProxyArpCustomizer(jvpp, ifcNamingCtx))); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesWriterFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesWriterFactory.java index 28d7b5007..0f7d517c4 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesWriterFactory.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/InterfacesWriterFactory.java @@ -42,6 +42,7 @@ import io.fd.honeycomb.translate.v3po.interfaces.ip.Ipv4Customizer; import io.fd.honeycomb.translate.v3po.interfaces.ip.Ipv4NeighbourCustomizer; import io.fd.honeycomb.translate.v3po.interfaces.ip.Ipv6Customizer; import io.fd.honeycomb.translate.v3po.util.NamingContext; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; import io.fd.honeycomb.translate.write.WriterFactory; import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder; import java.util.Set; @@ -85,7 +86,7 @@ public final class InterfacesWriterFactory implements WriterFactory { private final IetfAClWriter aclWriter; private final NamingContext bdNamingContext; private final NamingContext ifcNamingContext; - private final NamingContext classifyTableNamingContext; + private final VppClassifierContextManager classifyTableContext; private final DisabledInterfacesManager ifcDisableContext; @Inject @@ -93,14 +94,14 @@ public final class InterfacesWriterFactory implements WriterFactory { final IetfAClWriter aclWriter, @Named("bridge-domain-context") final NamingContext bridgeDomainContextDependency, @Named("interface-context") final NamingContext interfaceContextDependency, - @Named("classify-table-context") final NamingContext classifyTableContextDependency, + @Named("classify-table-context") final VppClassifierContextManager classifyTableContext, final DisabledInterfacesManager ifcDisableContext) { this.jvpp = vppJvppIfcDependency; this.aclWriter = aclWriter; this.bdNamingContext = bridgeDomainContextDependency; this.ifcNamingContext = interfaceContextDependency; this.ifcDisableContext = ifcDisableContext; - this.classifyTableNamingContext = classifyTableContextDependency; + this.classifyTableContext = classifyTableContext; } @Override @@ -114,7 +115,7 @@ public final class InterfacesWriterFactory implements WriterFactory { addInterface1AugmentationWriters(IFC_ID, registry); // SubinterfaceAugmentation TODO make dedicated module for subIfc writer factory new SubinterfaceAugmentationWriterFactory(jvpp, aclWriter, ifcNamingContext, bdNamingContext, - classifyTableNamingContext).init(registry); + classifyTableContext).init(registry); } private void addInterface1AugmentationWriters(final InstanceIdentifier<Interface> ifcId, @@ -183,7 +184,7 @@ public final class InterfacesWriterFactory implements WriterFactory { registry .subtreeAddAfter( Sets.newHashSet(aclId.child(L2Acl.class), aclId.child(Ip4Acl.class), aclId.child(Ip6Acl.class)), - new GenericWriter<>(ACL_ID, new AclCustomizer(jvpp, ifcNamingContext, classifyTableNamingContext)), + new GenericWriter<>(ACL_ID, new AclCustomizer(jvpp, ifcNamingContext, classifyTableContext)), Sets.newHashSet(CLASSIFY_TABLE_ID, CLASSIFY_SESSION_ID)); // IETF-ACL, also handles IetfAcl, AccessLists and Acl: diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/SubinterfaceAugmentationWriterFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/SubinterfaceAugmentationWriterFactory.java index 85c867e9b..ebe8c857f 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/SubinterfaceAugmentationWriterFactory.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/SubinterfaceAugmentationWriterFactory.java @@ -30,6 +30,7 @@ import io.fd.honeycomb.translate.v3po.interfaces.acl.IetfAClWriter; import io.fd.honeycomb.translate.v3po.interfaces.acl.SubInterfaceIetfAclCustomizer; import io.fd.honeycomb.translate.v3po.interfaces.ip.SubInterfaceIpv4AddressCustomizer; import io.fd.honeycomb.translate.v3po.util.NamingContext; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; import io.fd.honeycomb.translate.write.WriterFactory; import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder; import org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.or.any.Dot1qTag; @@ -60,7 +61,7 @@ public final class SubinterfaceAugmentationWriterFactory implements WriterFactor private final IetfAClWriter aclWriter; private final NamingContext ifcContext; private final NamingContext bdContext; - private final NamingContext classifyTableContext; + private final VppClassifierContextManager classifyTableContext; public static final InstanceIdentifier<SubinterfaceAugmentation> SUB_IFC_AUG_ID = InterfacesWriterFactory.IFC_ID.augmentation(SubinterfaceAugmentation.class); @@ -73,7 +74,7 @@ public final class SubinterfaceAugmentationWriterFactory implements WriterFactor public SubinterfaceAugmentationWriterFactory(final FutureJVppCore jvpp, final IetfAClWriter aclWriter, - final NamingContext ifcContext, final NamingContext bdContext, final NamingContext classifyTableContext) { + final NamingContext ifcContext, final NamingContext bdContext, final VppClassifierContextManager classifyTableContext) { this.jvpp = jvpp; this.aclWriter = aclWriter; this.ifcContext = ifcContext; diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/SubinterfaceStateAugmentationReaderFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/SubinterfaceStateAugmentationReaderFactory.java index ad7eabcd7..ed17954f3 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/SubinterfaceStateAugmentationReaderFactory.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/SubinterfaceStateAugmentationReaderFactory.java @@ -27,6 +27,7 @@ import io.fd.honeycomb.translate.v3po.interfacesstate.SubInterfaceCustomizer; import io.fd.honeycomb.translate.v3po.interfacesstate.SubInterfaceL2Customizer; import io.fd.honeycomb.translate.v3po.interfacesstate.ip.SubInterfaceIpv4AddressCustomizer; import io.fd.honeycomb.translate.v3po.util.NamingContext; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; 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.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip4Acl; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip6Acl; @@ -55,10 +56,10 @@ final class SubinterfaceStateAugmentationReaderFactory implements ReaderFactory private final FutureJVppCore jvpp; private final NamingContext ifcCtx; private final NamingContext bdCtx; - private final NamingContext classifyCtx; + private final VppClassifierContextManager classifyCtx; SubinterfaceStateAugmentationReaderFactory(final FutureJVppCore jvpp, final NamingContext ifcCtx, - final NamingContext bdCtx, final NamingContext classifyCtx) { + final NamingContext bdCtx, final VppClassifierContextManager classifyCtx) { this.jvpp = jvpp; this.ifcCtx = ifcCtx; this.bdCtx = bdCtx; diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/V3poModule.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/V3poModule.java index 0feeccab6..53fc37d09 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/V3poModule.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/V3poModule.java @@ -29,6 +29,8 @@ import io.fd.honeycomb.translate.v3po.initializers.VppInitializer; import io.fd.honeycomb.translate.v3po.interfaces.acl.IetfAClWriter; import io.fd.honeycomb.translate.v3po.notification.InterfaceChangeNotificationProducer; import io.fd.honeycomb.translate.v3po.util.NamingContext; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManagerImpl; import io.fd.honeycomb.translate.write.WriterFactory; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; @@ -48,9 +50,9 @@ public class V3poModule extends AbstractModule { bind(NamingContext.class) .annotatedWith(Names.named("bridge-domain-context")) .toInstance(new NamingContext("bridge-domain-", "bridge-domain-context")); - bind(NamingContext.class) + bind(VppClassifierContextManager.class) .annotatedWith(Names.named("classify-table-context")) - .toInstance(new NamingContext("classify-table-", "classify-table-context")); + .toInstance(new VppClassifierContextManagerImpl("classify-table-")); // Executor needed for keepalives bind(ScheduledExecutorService.class).toInstance(Executors.newScheduledThreadPool(1)); @@ -67,6 +69,8 @@ public class V3poModule extends AbstractModule { readerFactoryBinder.addBinding().to(VppClassifierReaderFactory.class); // Expose disabled interfaces in operational data readerFactoryBinder.addBinding().to(DisabledInterfacesManager.ContextsReaderFactory.class); + // Expose vpp-classfier-context interfaces in operational data + readerFactoryBinder.addBinding().to(VppClassifierContextManagerImpl.ContextsReaderFactory.class); // Writers final Multibinder<WriterFactory> writerFactoryBinder = Multibinder.newSetBinder(binder(), WriterFactory.class); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/VppClassifierHoneycombWriterFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/VppClassifierHoneycombWriterFactory.java index 6c52811fa..371287db1 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/VppClassifierHoneycombWriterFactory.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/VppClassifierHoneycombWriterFactory.java @@ -21,9 +21,9 @@ import static io.fd.honeycomb.translate.v3po.InterfacesWriterFactory.ACL_ID; import com.google.inject.Inject; import com.google.inject.name.Named; import io.fd.honeycomb.translate.impl.write.GenericListWriter; -import io.fd.honeycomb.translate.v3po.util.NamingContext; import io.fd.honeycomb.translate.v3po.vppclassifier.ClassifySessionWriter; import io.fd.honeycomb.translate.v3po.vppclassifier.ClassifyTableWriter; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; import io.fd.honeycomb.translate.write.WriterFactory; import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder; import javax.annotation.Nonnull; @@ -42,11 +42,11 @@ public final class VppClassifierHoneycombWriterFactory implements WriterFactory CLASSIFY_TABLE_ID.child(ClassifySession.class); private final FutureJVppCore jvpp; - private final NamingContext classifyTableContext; + private final VppClassifierContextManager classifyTableContext; @Inject public VppClassifierHoneycombWriterFactory(@Nonnull final FutureJVppCore jvpp, - @Named("classify-table-context") @Nonnull final NamingContext classifyTableContext) { + @Named("classify-table-context") @Nonnull final VppClassifierContextManager classifyTableContext) { this.jvpp = jvpp; this.classifyTableContext = classifyTableContext; } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/VppClassifierReaderFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/VppClassifierReaderFactory.java index 90fbb87ba..00481813d 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/VppClassifierReaderFactory.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/VppClassifierReaderFactory.java @@ -21,9 +21,9 @@ import com.google.inject.name.Named; import io.fd.honeycomb.translate.impl.read.GenericListReader; import io.fd.honeycomb.translate.read.ReaderFactory; import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder; -import io.fd.honeycomb.translate.v3po.util.NamingContext; import io.fd.honeycomb.translate.v3po.vppclassifier.ClassifySessionReader; import io.fd.honeycomb.translate.v3po.vppclassifier.ClassifyTableReader; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppClassifierState; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppClassifierStateBuilder; @@ -35,11 +35,11 @@ import org.openvpp.jvpp.core.future.FutureJVppCore; public final class VppClassifierReaderFactory implements ReaderFactory { private final FutureJVppCore jvpp; - private final NamingContext classifyCtx; + private final VppClassifierContextManager classifyCtx; @Inject public VppClassifierReaderFactory(final FutureJVppCore jvpp, - @Named("classify-table-context") final NamingContext classifyCtx) { + @Named("classify-table-context") final VppClassifierContextManager classifyCtx) { this.jvpp = jvpp; this.classifyCtx = classifyCtx; } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/AclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/AclCustomizer.java index ab71e6587..a920f38a3 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/AclCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/AclCustomizer.java @@ -22,6 +22,7 @@ import io.fd.honeycomb.translate.spi.write.WriterCustomizer; import io.fd.honeycomb.translate.v3po.util.FutureJVppCustomizer; import io.fd.honeycomb.translate.v3po.util.NamingContext; import io.fd.honeycomb.translate.v3po.util.WriteTimeoutException; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; import io.fd.honeycomb.translate.write.WriteContext; import io.fd.honeycomb.translate.write.WriteFailedException; import javax.annotation.Nonnull; @@ -40,10 +41,10 @@ public class AclCustomizer extends FutureJVppCustomizer implements WriterCustomi private static final Logger LOG = LoggerFactory.getLogger(AclCustomizer.class); private final NamingContext interfaceContext; - private final NamingContext classifyTableContext; + private final VppClassifierContextManager classifyTableContext; public AclCustomizer(@Nonnull final FutureJVppCore vppApi, @Nonnull final NamingContext interfaceContext, - @Nonnull final NamingContext classifyTableContext) { + @Nonnull final VppClassifierContextManager classifyTableContext) { super(vppApi); this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/AclWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/AclWriter.java index d29d213ea..a1bdf6aa9 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/AclWriter.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/AclWriter.java @@ -19,10 +19,10 @@ package io.fd.honeycomb.translate.v3po.interfaces; import static com.google.common.base.Preconditions.checkNotNull; import static io.fd.honeycomb.translate.v3po.util.TranslateUtils.booleanToByte; -import io.fd.honeycomb.translate.v3po.util.WriteTimeoutException; import io.fd.honeycomb.translate.MappingContext; -import io.fd.honeycomb.translate.v3po.util.NamingContext; import io.fd.honeycomb.translate.v3po.util.TranslateUtils; +import io.fd.honeycomb.translate.v3po.util.WriteTimeoutException; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; import java.util.concurrent.CompletionStage; import javax.annotation.Nonnegative; import javax.annotation.Nonnull; @@ -40,7 +40,7 @@ interface AclWriter { default void inputAclSetInterface(@Nonnull final FutureJVppCore futureJVppCore, final boolean isAdd, @Nonnull final InstanceIdentifier<?> id, @Nonnull final AclBaseAttributes acl, - @Nonnegative final int ifIndex, @Nonnull final NamingContext classifyTableContext, + @Nonnegative final int ifIndex, @Nonnull final VppClassifierContextManager classifyTableContext, @Nonnull final MappingContext mappingContext) throws VppBaseCallException, WriteTimeoutException { final InputAclSetInterface request = new InputAclSetInterface(); @@ -53,17 +53,17 @@ interface AclWriter { final L2Acl l2Acl = acl.getL2Acl(); if (l2Acl != null) { final String tableName = checkNotNull(l2Acl.getClassifyTable(), "L2 classify table is null"); - request.l2TableIndex = classifyTableContext.getIndex(tableName, mappingContext); + request.l2TableIndex = classifyTableContext.getTableIndex(tableName, mappingContext); } final Ip4Acl ip4Acl = acl.getIp4Acl(); if (ip4Acl != null) { final String tableName = checkNotNull(ip4Acl.getClassifyTable(), "IPv4 classify table is null"); - request.ip4TableIndex = classifyTableContext.getIndex(tableName, mappingContext); + request.ip4TableIndex = classifyTableContext.getTableIndex(tableName, mappingContext); } final Ip6Acl ip6Acl = acl.getIp6Acl(); if (ip6Acl != null) { final String tableName = checkNotNull(ip6Acl.getClassifyTable(), "IPv6 classify table is null"); - request.ip6TableIndex = classifyTableContext.getIndex(tableName, mappingContext); + request.ip6TableIndex = classifyTableContext.getTableIndex(tableName, mappingContext); } final CompletionStage<InputAclSetInterfaceReply> inputAclSetInterfaceReplyCompletionStage = diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/SubInterfaceAclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/SubInterfaceAclCustomizer.java index 962801a38..123826768 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/SubInterfaceAclCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/SubInterfaceAclCustomizer.java @@ -23,6 +23,7 @@ import io.fd.honeycomb.translate.v3po.util.FutureJVppCustomizer; import io.fd.honeycomb.translate.v3po.util.NamingContext; import io.fd.honeycomb.translate.v3po.util.SubInterfaceUtils; import io.fd.honeycomb.translate.v3po.util.WriteTimeoutException; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; import io.fd.honeycomb.translate.write.WriteContext; import io.fd.honeycomb.translate.write.WriteFailedException; import javax.annotation.Nonnull; @@ -45,11 +46,11 @@ public class SubInterfaceAclCustomizer extends FutureJVppCustomizer private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceAclCustomizer.class); private final NamingContext interfaceContext; - private final NamingContext classifyTableContext; + private final VppClassifierContextManager classifyTableContext; public SubInterfaceAclCustomizer(@Nonnull final FutureJVppCore vppApi, @Nonnull final NamingContext interfaceContext, - @Nonnull final NamingContext classifyTableContext) { + @Nonnull final VppClassifierContextManager classifyTableContext) { super(vppApi); this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclCustomizer.java index 9145d84e8..639b36651 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclCustomizer.java @@ -25,6 +25,7 @@ import io.fd.honeycomb.translate.v3po.util.FutureJVppCustomizer; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.v3po.util.NamingContext; import io.fd.honeycomb.translate.v3po.util.TranslateUtils; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; 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; @@ -49,10 +50,10 @@ public class AclCustomizer extends FutureJVppCustomizer private static final Logger LOG = LoggerFactory.getLogger(AclCustomizer.class); private final NamingContext interfaceContext; - private final NamingContext classifyTableContext; + private final VppClassifierContextManager classifyTableContext; public AclCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext, - @Nonnull final NamingContext classifyTableContext) { + @Nonnull final VppClassifierContextManager classifyTableContext) { super(jvpp); this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclReader.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclReader.java index c64c096a8..c16bfe6e3 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclReader.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclReader.java @@ -17,7 +17,7 @@ package io.fd.honeycomb.translate.v3po.interfacesstate; import io.fd.honeycomb.translate.MappingContext; -import io.fd.honeycomb.translate.v3po.util.NamingContext; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip4Acl; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip4AclBuilder; @@ -29,32 +29,32 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev interface AclReader { @Nonnull - default L2Acl readL2Acl(final int l2TableId, @Nonnull final NamingContext classifyTableContext, + default L2Acl readL2Acl(final int l2TableId, @Nonnull final VppClassifierContextManager classifyTableContext, @Nonnull final MappingContext mappingContext) { if (l2TableId == ~0) { return null; } return new L2AclBuilder() - .setClassifyTable(classifyTableContext.getName(l2TableId, mappingContext)).build(); + .setClassifyTable(classifyTableContext.getTableName(l2TableId, mappingContext)).build(); } @Nonnull - default Ip4Acl readIp4Acl(final int ip4TableId, @Nonnull final NamingContext classifyTableContext, + default Ip4Acl readIp4Acl(final int ip4TableId, @Nonnull final VppClassifierContextManager classifyTableContext, @Nonnull final MappingContext mappingContext) { if (ip4TableId == ~0) { return null; } return new Ip4AclBuilder() - .setClassifyTable(classifyTableContext.getName(ip4TableId, mappingContext)).build(); + .setClassifyTable(classifyTableContext.getTableName(ip4TableId, mappingContext)).build(); } @Nonnull - default Ip6Acl readIp6Acl(final int ip6TableId, @Nonnull final NamingContext classifyTableContext, + default Ip6Acl readIp6Acl(final int ip6TableId, @Nonnull final VppClassifierContextManager classifyTableContext, @Nonnull final MappingContext mappingContext) { if (ip6TableId == ~0) { return null; } return new Ip6AclBuilder() - .setClassifyTable(classifyTableContext.getName(ip6TableId, mappingContext)).build(); + .setClassifyTable(classifyTableContext.getTableName(ip6TableId, mappingContext)).build(); } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/SubInterfaceAclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/SubInterfaceAclCustomizer.java index bad919ffa..cbc8c7ed1 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/SubInterfaceAclCustomizer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/SubInterfaceAclCustomizer.java @@ -26,6 +26,7 @@ import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.v3po.util.FutureJVppCustomizer; import io.fd.honeycomb.translate.v3po.util.NamingContext; import io.fd.honeycomb.translate.v3po.util.TranslateUtils; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; 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; @@ -52,10 +53,10 @@ public class SubInterfaceAclCustomizer extends FutureJVppCustomizer private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceAclCustomizer.class); private final NamingContext interfaceContext; - private final NamingContext classifyTableContext; + private final VppClassifierContextManager classifyTableContext; public SubInterfaceAclCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext, - @Nonnull final NamingContext classifyTableContext) { + @Nonnull final VppClassifierContextManager classifyTableContext) { super(jvpp); this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionReader.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionReader.java index 590a502fd..143cd00da 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionReader.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionReader.java @@ -23,11 +23,11 @@ import static io.fd.honeycomb.translate.v3po.interfacesstate.InterfaceUtils.prin import com.google.common.base.Optional; import com.google.common.primitives.UnsignedInts; +import io.fd.honeycomb.translate.MappingContext; import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer; import io.fd.honeycomb.translate.v3po.util.FutureJVppCustomizer; -import io.fd.honeycomb.translate.read.ReadFailedException; -import io.fd.honeycomb.translate.v3po.util.NamingContext; import io.fd.honeycomb.translate.v3po.util.TranslateUtils; import java.util.Arrays; import java.util.Collections; @@ -66,10 +66,10 @@ public class ClassifySessionReader extends FutureJVppCustomizer private static final Logger LOG = LoggerFactory.getLogger(ClassifySessionReader.class); static final String CACHE_KEY = ClassifySessionReader.class.getName(); - private final NamingContext classifyTableContext; + private final VppClassifierContextManager classifyTableContext; public ClassifySessionReader(@Nonnull final FutureJVppCore futureJVppCore, - @Nonnull final NamingContext classifyTableContext) { + @Nonnull final VppClassifierContextManager classifyTableContext) { super(futureJVppCore); this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); } @@ -102,10 +102,11 @@ public class ClassifySessionReader extends FutureJVppCustomizer if (classifySession.isPresent()) { final ClassifySessionDetails detail = classifySession.get(); - builder.setHitNext(readVppNode(detail.hitNextIndex, LOG)); + builder.setHitNext( + readVppNode(detail.tableId, detail.hitNextIndex, classifyTableContext, ctx.getMappingContext(), LOG).get()); if (detail.opaqueIndex != ~0) { // value is specified: - builder.setOpaqueIndex(readOpaqueIndex(detail.opaqueIndex)); + builder.setOpaqueIndex(readOpaqueIndex(detail.tableId, detail.opaqueIndex, ctx.getMappingContext())); } builder.setAdvance(detail.advance); builder.setMatch(key.getMatch()); @@ -116,13 +117,14 @@ public class ClassifySessionReader extends FutureJVppCustomizer } } - private OpaqueIndex readOpaqueIndex(final int opaqueIndex) { + private OpaqueIndex readOpaqueIndex(final int tableIndex, final int opaqueIndex, final MappingContext ctx) { // We first try to map the value to a vpp node, if that fails, simply wrap the u32 value // FIXME: the approach might fail if the opaqueIndex contains small value that collides // with some of the adjacent nodes - final VppNode node = readVppNode(opaqueIndex, LOG); - if (node != null) { - return new OpaqueIndex(node); + + final Optional<VppNode> node = readVppNode(tableIndex, opaqueIndex, classifyTableContext, ctx, LOG); + if (node.isPresent()) { + return new OpaqueIndex(node.get()); } else { return new OpaqueIndex(UnsignedInts.toLong(opaqueIndex)); } @@ -145,10 +147,10 @@ public class ClassifySessionReader extends FutureJVppCustomizer } final String tableName = tableKey.getName(); - checkState(classifyTableContext.containsIndex(tableName, ctx.getMappingContext()), + checkState(classifyTableContext.containsTable(tableName, ctx.getMappingContext()), "Reading classify sessions for table {}, but table index could not be found in the classify table context", tableName); - final int tableId = classifyTableContext.getIndex(tableName, ctx.getMappingContext()); + final int tableId = classifyTableContext.getTableIndex(tableName, ctx.getMappingContext()); LOG.debug("Dumping classify sessions for classify table id={}", tableId); try { @@ -157,8 +159,11 @@ public class ClassifySessionReader extends FutureJVppCustomizer classifySessionDump = TranslateUtils .getReplyForRead(getFutureJVpp().classifySessionDump(dumpRequest).toCompletableFuture(), id); - // update the cache: - ctx.getModificationCache().put(cacheKey, classifySessionDump); + if (classifySessionDump != null) { + // update the cache: + ctx.getModificationCache().put(cacheKey, classifySessionDump); + } + return classifySessionDump; } catch (VppBaseCallException e) { throw new ReadFailedException(id, e); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionWriter.java index 8967dcf1e..d2029a368 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionWriter.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionWriter.java @@ -21,15 +21,15 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static io.fd.honeycomb.translate.v3po.util.TranslateUtils.booleanToByte; -import io.fd.honeycomb.translate.v3po.util.WriteTimeoutException; -import io.fd.honeycomb.translate.write.WriteContext; +import com.google.common.base.Optional; +import io.fd.honeycomb.translate.MappingContext; import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; -import io.fd.honeycomb.translate.v3po.util.FutureJVppCustomizer; -import io.fd.honeycomb.translate.v3po.util.NamingContext; import io.fd.honeycomb.translate.v3po.util.TranslateUtils; +import io.fd.honeycomb.translate.write.WriteContext; import io.fd.honeycomb.translate.write.WriteFailedException; import java.util.concurrent.CompletionStage; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.xml.bind.DatatypeConverter; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.OpaqueIndex; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.classify.table.base.attributes.ClassifySession; @@ -48,14 +48,14 @@ import org.slf4j.LoggerFactory; * Writer customizer responsible for classify session create/delete.<br> Sends {@code classify_add_del_session} message * to VPP.<br> Equivalent to invoking {@code vppctl classify table} command. */ -public class ClassifySessionWriter extends FutureJVppCustomizer +public class ClassifySessionWriter extends VppNodeWriter implements ListWriterCustomizer<ClassifySession, ClassifySessionKey> { private static final Logger LOG = LoggerFactory.getLogger(ClassifySessionWriter.class); - private final NamingContext classifyTableContext; + private final VppClassifierContextManager classifyTableContext; public ClassifySessionWriter(@Nonnull final FutureJVppCore futureJVppCore, - @Nonnull final NamingContext classifyTableContext) { + @Nonnull final VppClassifierContextManager classifyTableContext) { super(futureJVppCore); this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); } @@ -97,37 +97,51 @@ public class ClassifySessionWriter extends FutureJVppCustomizer private void classifyAddDelSession(final boolean isAdd, @Nonnull final InstanceIdentifier<ClassifySession> id, @Nonnull final ClassifySession classifySession, @Nonnull final WriteContext writeContext) - throws VppBaseCallException, WriteTimeoutException { + throws VppBaseCallException, WriteFailedException { final ClassifyTableKey tableKey = id.firstKeyOf(ClassifyTable.class); checkArgument(tableKey != null, "could not find classify table key in {}", id); final String tableName = tableKey.getName(); - checkState(classifyTableContext.containsIndex(tableName, writeContext.getMappingContext()), + checkState(classifyTableContext.containsTable(tableName, writeContext.getMappingContext()), "Could not find classify table index for {} in the classify table context", tableName); - final int tableIndex = classifyTableContext.getIndex(tableName, writeContext.getMappingContext()); + final int tableIndex = classifyTableContext.getTableIndex(tableName, writeContext.getMappingContext()); + + final ClassifyTable classifyTable = + getClassifyTable(writeContext, id.firstIdentifierOf(ClassifyTable.class), isAdd); + final int hitNextIndex = getNodeIndex(classifySession.getHitNext(), classifyTable, classifyTableContext, + writeContext.getMappingContext(), id); + final int opaqueIndex = + getOpaqueIndex(classifySession.getOpaqueIndex(), classifyTable, writeContext.getMappingContext(), id); final CompletionStage<ClassifyAddDelSessionReply> createClassifyTableReplyCompletionStage = getFutureJVpp() .classifyAddDelSession( - getClassifyAddDelSessionRequest(isAdd, tableIndex, classifySession)); + getClassifyAddDelSessionRequest(isAdd, classifySession, tableIndex, hitNextIndex, opaqueIndex)); TranslateUtils.getReplyForWrite(createClassifyTableReplyCompletionStage.toCompletableFuture(), id); } - private static ClassifyAddDelSession getClassifyAddDelSessionRequest(final boolean isAdd, final int tableIndex, - @Nonnull final ClassifySession classifySession) { + private ClassifyTable getClassifyTable(final WriteContext writeContext, + @Nonnull final InstanceIdentifier<ClassifyTable> id, + final boolean isAdd) { + final Optional<ClassifyTable> classifyTable; + if (isAdd) { + classifyTable = writeContext.readAfter(id); + } else { + classifyTable = writeContext.readBefore(id); + } + return classifyTable.get(); + } + + private static ClassifyAddDelSession getClassifyAddDelSessionRequest(final boolean isAdd, + @Nonnull final ClassifySession classifySession, + final int tableIndex, + final int hitNextIndex, + final int opaqueIndex) { ClassifyAddDelSession request = new ClassifyAddDelSession(); request.isAdd = booleanToByte(isAdd); request.tableIndex = tableIndex; - - // mandatory: - // TODO implement node name to index conversion after https://jira.fd.io/browse/VPP-203 is fixed - request.hitNextIndex = classifySession.getHitNext().getPacketHandlingAction().getIntValue(); - - if (classifySession.getOpaqueIndex() != null) { - request.opaqueIndex = getOpaqueIndexValue(classifySession.getOpaqueIndex()); - } else { - request.opaqueIndex = ~0; // value not specified - } + request.hitNextIndex = hitNextIndex; + request.opaqueIndex = opaqueIndex; // default 0: request.advance = classifySession.getAdvance(); @@ -136,12 +150,16 @@ public class ClassifySessionWriter extends FutureJVppCustomizer return request; } - private static int getOpaqueIndexValue(@Nonnull final OpaqueIndex opaqueIndex) { + private int getOpaqueIndex(@Nullable final OpaqueIndex opaqueIndex, final ClassifyTable classifyTable, + final MappingContext ctx, final InstanceIdentifier<ClassifySession> id) + throws VppBaseCallException, WriteFailedException { + if (opaqueIndex == null) { + return ~0; // value not specified + } if (opaqueIndex.getUint32() != null) { return opaqueIndex.getUint32().intValue(); } else { - // TODO: implement node name to index conversion after https://jira.fd.io/browse/VPP-203 is fixed - return opaqueIndex.getVppNode().getPacketHandlingAction().getIntValue(); + return getNodeIndex(opaqueIndex.getVppNode(), classifyTable, classifyTableContext, ctx, id); } } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableReader.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableReader.java index b7d54abb5..ad238d8bb 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableReader.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableReader.java @@ -20,12 +20,12 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static io.fd.honeycomb.translate.v3po.interfacesstate.InterfaceUtils.printHexBinary; +import com.google.common.base.Optional; import com.google.common.primitives.UnsignedInts; import io.fd.honeycomb.translate.read.ReadContext; -import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer; import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer; import io.fd.honeycomb.translate.v3po.util.FutureJVppCustomizer; -import io.fd.honeycomb.translate.v3po.util.NamingContext; import io.fd.honeycomb.translate.v3po.util.TranslateUtils; import java.util.Arrays; import java.util.Collections; @@ -34,6 +34,7 @@ import java.util.stream.Collectors; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppClassifierStateBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNodeName; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.state.ClassifyTable; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.state.ClassifyTableBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.state.ClassifyTableKey; @@ -57,10 +58,10 @@ public class ClassifyTableReader extends FutureJVppCustomizer implements ListReaderCustomizer<ClassifyTable, ClassifyTableKey, ClassifyTableBuilder>, VppNodeReader { private static final Logger LOG = LoggerFactory.getLogger(ClassifyTableReader.class); - private final NamingContext classifyTableContext; + private final VppClassifierContextManager classifyTableContext; public ClassifyTableReader(@Nonnull final FutureJVppCore futureJVppCore, - @Nonnull final NamingContext classifyTableContext) { + @Nonnull final VppClassifierContextManager classifyTableContext) { super(futureJVppCore); this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); } @@ -89,11 +90,11 @@ public class ClassifyTableReader extends FutureJVppCustomizer final ClassifyTableInfo request = new ClassifyTableInfo(); final String tableName = key.getName(); - if (!classifyTableContext.containsIndex(tableName, ctx.getMappingContext())) { + if (!classifyTableContext.containsTable(tableName, ctx.getMappingContext())) { LOG.debug("Could not find classify table {} in the naming context", tableName); return; } - request.tableId = classifyTableContext.getIndex(tableName, ctx.getMappingContext()); + request.tableId = classifyTableContext.getTableIndex(tableName, ctx.getMappingContext()); try { final ClassifyTableInfoReply reply = @@ -105,14 +106,22 @@ public class ClassifyTableReader extends FutureJVppCustomizer builder.setNbuckets(UnsignedInts.toLong(reply.nbuckets)); builder.setSkipNVectors(UnsignedInts.toLong(reply.skipNVectors)); + // optional value read from context + final Optional<String> tableBaseNode = + classifyTableContext.getTableBaseNode(tableName, ctx.getMappingContext()); + if (tableBaseNode.isPresent()) { + builder.setClassifierNode(new VppNodeName(tableBaseNode.get())); + } - builder.setMissNext(readVppNode(reply.missNextIndex, LOG)); + builder.setMissNext( + readVppNode(reply.tableId, reply.missNextIndex, classifyTableContext, ctx.getMappingContext(), LOG) + .get()); builder.setMask(new HexString(printHexBinary(reply.mask))); builder.setActiveSessions(UnsignedInts.toLong(reply.activeSessions)); if (reply.nextTableIndex != ~0) { // next table index is present: - builder.setNextTable(classifyTableContext.getName(reply.nextTableIndex, ctx.getMappingContext())); + builder.setNextTable(classifyTableContext.getTableName(reply.nextTableIndex, ctx.getMappingContext())); } if (LOG.isTraceEnabled()) { @@ -133,7 +142,7 @@ public class ClassifyTableReader extends FutureJVppCustomizer .getReplyForRead(getFutureJVpp().classifyTableIds(new ClassifyTableIds()).toCompletableFuture(), id); if (classifyTableIdsReply.ids != null) { return Arrays.stream(classifyTableIdsReply.ids).mapToObj(i -> { - final String tableName = classifyTableContext.getName(i, context.getMappingContext()); + final String tableName = classifyTableContext.getTableName(i, context.getMappingContext()); LOG.trace("Classify table with name: {} and index: {} found in VPP", tableName, i); return new ClassifyTableKey(tableName); }).collect(Collectors.toList()); diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableWriter.java index 3c3f9813b..3dc3cf7d1 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableWriter.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableWriter.java @@ -21,14 +21,11 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static io.fd.honeycomb.translate.v3po.util.TranslateUtils.booleanToByte; +import io.fd.honeycomb.translate.MappingContext; import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; -import io.fd.honeycomb.translate.v3po.util.FutureJVppCustomizer; -import io.fd.honeycomb.translate.v3po.util.NamingContext; -import io.fd.honeycomb.translate.v3po.util.WriteTimeoutException; +import io.fd.honeycomb.translate.v3po.util.TranslateUtils; import io.fd.honeycomb.translate.write.WriteContext; import io.fd.honeycomb.translate.write.WriteFailedException; -import io.fd.honeycomb.translate.MappingContext; -import io.fd.honeycomb.translate.v3po.util.TranslateUtils; import java.util.concurrent.CompletionStage; import javax.annotation.Nonnull; import javax.xml.bind.DatatypeConverter; @@ -46,14 +43,14 @@ import org.slf4j.LoggerFactory; * Writer customizer responsible for classify table create/delete. <br> Sends {@code classify_add_del_table} message to * VPP.<br> Equivalent to invoking {@code vppctl classify table} command. */ -public class ClassifyTableWriter extends FutureJVppCustomizer +public class ClassifyTableWriter extends VppNodeWriter implements ListWriterCustomizer<ClassifyTable, ClassifyTableKey> { private static final Logger LOG = LoggerFactory.getLogger(ClassifyTableWriter.class); - private final NamingContext classifyTableContext; + private final VppClassifierContextManager classifyTableContext; public ClassifyTableWriter(@Nonnull final FutureJVppCore futureJVppCore, - @Nonnull final NamingContext classifyTableContext) { + @Nonnull final VppClassifierContextManager classifyTableContext) { super(futureJVppCore); this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); } @@ -68,7 +65,7 @@ public class ClassifyTableWriter extends FutureJVppCustomizer classifyAddDelTable(true, id, dataAfter, ~0 /* value not present */, writeContext.getMappingContext()); // Add classify table name <-> vpp index mapping to the naming context: - classifyTableContext.addName(newTableIndex, dataAfter.getName(), writeContext.getMappingContext()); + classifyTableContext.addTable(newTableIndex, dataAfter.getName(), dataAfter.getClassifierNode(), writeContext.getMappingContext()); LOG.debug("Successfully created classify table(id={]): iid={} dataAfter={}", newTableIndex, id, dataAfter); } catch (VppBaseCallException e) { throw new WriteFailedException.CreateFailedException(id, dataAfter, e); @@ -88,15 +85,15 @@ public class ClassifyTableWriter extends FutureJVppCustomizer @Nonnull final WriteContext writeContext) throws WriteFailedException { LOG.debug("Removing classify table: iid={} dataBefore={}", id, dataBefore); final String tableName = dataBefore.getName(); - checkState(classifyTableContext.containsIndex(tableName, writeContext.getMappingContext()), + checkState(classifyTableContext.containsTable(tableName, writeContext.getMappingContext()), "Removing classify table {}, but index could not be found in the classify table context", tableName); - final int tableIndex = classifyTableContext.getIndex(tableName, writeContext.getMappingContext()); + final int tableIndex = classifyTableContext.getTableIndex(tableName, writeContext.getMappingContext()); try { classifyAddDelTable(false, id, dataBefore, tableIndex, writeContext.getMappingContext()); // Remove deleted interface from interface context: - classifyTableContext.removeName(dataBefore.getName(), writeContext.getMappingContext()); + classifyTableContext.removeTable(dataBefore.getName(), writeContext.getMappingContext()); LOG.debug("Successfully removed classify table(id={]): iid={} dataAfter={}", tableIndex, id, dataBefore); } catch (VppBaseCallException e) { throw new WriteFailedException.DeleteFailedException(id, e); @@ -105,18 +102,23 @@ public class ClassifyTableWriter extends FutureJVppCustomizer private int classifyAddDelTable(final boolean isAdd, @Nonnull final InstanceIdentifier<ClassifyTable> id, @Nonnull final ClassifyTable table, final int tableId, final MappingContext ctx) - throws VppBaseCallException, WriteTimeoutException { + throws VppBaseCallException, WriteFailedException { + + final int missNextIndex = + getNodeIndex(table.getMissNext(), table, classifyTableContext, ctx, id); + final CompletionStage<ClassifyAddDelTableReply> createClassifyTableReplyCompletionStage = - getFutureJVpp().classifyAddDelTable(getClassifyAddDelTableRequest(isAdd, tableId, table, ctx)); + getFutureJVpp() + .classifyAddDelTable(getClassifyAddDelTableRequest(isAdd, tableId, table, missNextIndex, ctx)); final ClassifyAddDelTableReply reply = TranslateUtils.getReplyForWrite(createClassifyTableReplyCompletionStage.toCompletableFuture(), id); return reply.newTableIndex; - } private ClassifyAddDelTable getClassifyAddDelTableRequest(final boolean isAdd, final int tableIndex, @Nonnull final ClassifyTable table, + final int missNextIndex, @Nonnull final MappingContext ctx) { final ClassifyAddDelTable request = new ClassifyAddDelTable(); request.isAdd = booleanToByte(isAdd); @@ -128,12 +130,11 @@ public class ClassifyTableWriter extends FutureJVppCustomizer request.skipNVectors = table.getSkipNVectors().intValue(); // mandatory - // TODO implement node name to index conversion after https://jira.fd.io/browse/VPP-203 is fixed - request.missNextIndex = table.getMissNext().getPacketHandlingAction().getIntValue(); + request.missNextIndex = missNextIndex; final String nextTable = table.getNextTable(); if (isAdd && nextTable != null) { - request.nextTableIndex = classifyTableContext.getIndex(nextTable, ctx); + request.nextTableIndex = classifyTableContext.getTableIndex(nextTable, ctx); } else { request.nextTableIndex = ~0; // value not specified } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppClassifierContextManager.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppClassifierContextManager.java new file mode 100644 index 000000000..7e9b6d6d5 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppClassifierContextManager.java @@ -0,0 +1,106 @@ +/* + * 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.translate.v3po.vppclassifier; + +import com.google.common.base.Optional; +import io.fd.honeycomb.translate.MappingContext; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNodeName; + +/** + * Manages metadata for vpp-classifier + */ +public interface VppClassifierContextManager { + + /** + * Creates metadata for classify table. + * + * @param id classify table index + * @param name classify table name + * @param classifierNode name of VPP node the table is defined for + * @param ctx mapping context providing context data for current transaction + */ + void addTable(final int id, @Nonnull final String name, @Nullable final VppNodeName classifierNode, + @Nonnull final MappingContext ctx); + + /** + * Check whether metadata for given classify table metadata is present. + * + * @param name classify table name + * @param ctx mapping context providing context data for current transaction + * @return true if present, false otherwise + */ + boolean containsTable(@Nonnull String name, @Nonnull final MappingContext ctx); + + /** + * Returns classify table index associated with the given name. + * + * @param name classify table name + * @param ctx mapping context providing context data for current transaction + * @return integer index value matching supplied classify table name + * @throws IllegalArgumentException if classify table was not found + */ + int getTableIndex(@Nonnull final String name, @Nonnull final MappingContext ctx); + + /** + * Retrieves classify table name for given id. If not present, artificial name will be generated. + * + * @param id classify table index + * @param ctx mapping context providing context data for current transaction + * @return classify table name matching supplied index + */ + String getTableName(final int id, @Nonnull final MappingContext ctx); + + /** + * Returns name of the base vpp node associated with the classify table. + * + * @param name classify table name + * @param ctx mapping context providing context data for current transaction + * @return name of VPP node the table is defined for + */ + Optional<String> getTableBaseNode(final String name, @Nonnull final MappingContext ctx); + + /** + * Removes classify table metadata from current context. + * + * @param name classify table name + * @param ctx mapping context providing context data for current transaction + */ + void removeTable(@Nonnull final String name, @Nonnull final MappingContext ctx); + + /** + * Adds relative node index to node name mapping for given classify table. + * + * @param tableName classify table name + * @param nodeIndex index of a vpp node, relative to table's base node + * @param nodeName name of a vpp node + * @param ctx mapping context providing context data for current transaction + */ + void addNodeName(@Nonnull String tableName, final int nodeIndex, @Nonnull final String nodeName, + @Nonnull final MappingContext ctx); + + /** + * Retrieves node name associated with the given classify table and node index. + * + * @param tableIndex classify table index + * @param nodeIndex relative index of a vpp node + * @param ctx mapping context providing context data for current transaction + * @return name of vpp node + */ + Optional<String> getNodeName(final int tableIndex, final int nodeIndex, @Nonnull final MappingContext ctx); +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppClassifierContextManagerImpl.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppClassifierContextManagerImpl.java new file mode 100644 index 000000000..9f61ab021 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppClassifierContextManagerImpl.java @@ -0,0 +1,176 @@ +/* + * 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.translate.v3po.vppclassifier; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.inject.Inject; +import io.fd.honeycomb.translate.MappingContext; +import io.fd.honeycomb.translate.read.ReaderFactory; +import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.honeycomb.translate.util.read.BindingBrokerReader; +import java.util.stream.Collector; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.inject.Named; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNodeName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.VppClassifierContext; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.VppClassifierContextBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContext; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContextBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContextKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContext; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContextBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContextKey; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; + +/** + * Facade on top of {@link MappingContext} that manages {@link ClassifyTableContext}. + */ +public final class VppClassifierContextManagerImpl implements VppClassifierContextManager { + private static final Collector<ClassifyTableContext, ?, ClassifyTableContext> SINGLE_ITEM_COLLECTOR = + RWUtils.singleItemCollector(); + + @VisibleForTesting + static final InstanceIdentifier<VppClassifierContext> + VPP_CLASSIFIER_CONTEXT_IID = KeyedInstanceIdentifier.create(VppClassifierContext.class); + private final String artificialNamePrefix; + + /** + * Creates new VppClassifierContextManagerImpl. + * + * @param artificialNamePrefix artificial name to be used to generate names for classify tables without existing + * metadata + */ + public VppClassifierContextManagerImpl(@Nonnull final String artificialNamePrefix) { + this.artificialNamePrefix = + Preconditions.checkNotNull(artificialNamePrefix, "artificialNamePrefix should not be null"); + } + + private KeyedInstanceIdentifier<ClassifyTableContext, ClassifyTableContextKey> getMappingIid(final String name) { + return VPP_CLASSIFIER_CONTEXT_IID.child(ClassifyTableContext.class, new ClassifyTableContextKey(name)); + } + + @Override + public void addTable(final int id, @Nonnull final String name, @Nullable final VppNodeName classifierNode, + @Nonnull final MappingContext ctx) { + final KeyedInstanceIdentifier<ClassifyTableContext, ClassifyTableContextKey> mappingIid = getMappingIid(name); + final ClassifyTableContextBuilder tableCtx = new ClassifyTableContextBuilder().setIndex(id).setName(name); + if (classifierNode != null) { + tableCtx.setClassifierNodeName(classifierNode.getValue()); + } + ctx.put(mappingIid, tableCtx.build()); + } + + @Override + public boolean containsTable(@Nonnull final String name, @Nonnull final MappingContext ctx) { + final Optional<ClassifyTableContext> read = ctx.read(getMappingIid(name)); + return read.isPresent(); + } + + @Override + public int getTableIndex(@Nonnull final String name, @Nonnull final MappingContext ctx) { + final Optional<ClassifyTableContext> read = ctx.read(getMappingIid(name)); + checkArgument(read.isPresent(), "No mapping stored for name: %s", name); + return read.get().getIndex(); + } + + @Override + public String getTableName(final int id, @Nonnull final MappingContext ctx) { + if (!containsName(id, ctx)) { + final String artificialName = getArtificialName(id); + addTable(id, artificialName, null, ctx); + } + + final Optional<VppClassifierContext> read = ctx.read(VPP_CLASSIFIER_CONTEXT_IID); + checkState(read.isPresent(), "VppClassifierContext for index: %s is not present. But should be", id); + + return read.get().getClassifyTableContext().stream() + .filter(t -> t.getIndex().equals(id)) + .collect(SINGLE_ITEM_COLLECTOR).getName(); + } + + private boolean containsName(final int index, @Nonnull final MappingContext mappingContext) { + final Optional<VppClassifierContext> read = mappingContext.read(VPP_CLASSIFIER_CONTEXT_IID); + return read.isPresent() + ? read.get().getClassifyTableContext().stream().anyMatch(t -> t.getIndex().equals(index)) + : false; + } + + @Override + public Optional<String> getTableBaseNode(@Nonnull final String name, @Nonnull final MappingContext ctx) { + final Optional<ClassifyTableContext> read = ctx.read(getMappingIid(name)); + if (read.isPresent()) { + return Optional.fromNullable(read.get().getClassifierNodeName()); + } + return Optional.absent(); + } + + @Override + public void removeTable(@Nonnull final String name, @Nonnull final MappingContext ctx) { + ctx.delete(getMappingIid(name)); + } + + @Override + public void addNodeName(@Nonnull final String tableName, final int nodeIndex, + @Nonnull final String nodeName, + @Nonnull final MappingContext ctx) { + final KeyedInstanceIdentifier<NodeContext, NodeContextKey> iid = + getMappingIid(tableName).child(NodeContext.class, new NodeContextKey(nodeName)); + ctx.put(iid, new NodeContextBuilder().setName(nodeName).setIndex(nodeIndex).build()); + } + + @Override + public Optional<String> getNodeName(final int tableIndex, final int nodeIndex, @Nonnull final MappingContext ctx) { + if (!containsName(tableIndex, ctx)) { + return Optional.absent(); + } + final String tableName = getTableName(tableIndex, ctx); + final Optional<ClassifyTableContext> tableCtx = ctx.read(getMappingIid(tableName)); + return Optional.fromNullable(tableCtx.get().getNodeContext().stream() + .filter(n -> n.getIndex().equals(nodeIndex)) + .findFirst() + .map(nodes -> nodes.getName()) + .orElse(null)); + } + + private String getArtificialName(final int index) { + return artificialNamePrefix + index; + } + + public static final class ContextsReaderFactory implements ReaderFactory { + + @Inject + @Named("honeycomb-context") + private DataBroker contextBindingBrokerDependency; + + @Override + public void init(final ModifiableReaderRegistryBuilder registry) { + registry.add(new BindingBrokerReader<>(VPP_CLASSIFIER_CONTEXT_IID, + contextBindingBrokerDependency, + LogicalDatastoreType.OPERATIONAL, VppClassifierContextBuilder.class)); + } + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppNodeReader.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppNodeReader.java index 6061b8672..9fca4161e 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppNodeReader.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppNodeReader.java @@ -16,9 +16,12 @@ package io.fd.honeycomb.translate.v3po.vppclassifier; +import com.google.common.base.Optional; +import io.fd.honeycomb.translate.MappingContext; import javax.annotation.Nonnull; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.PacketHandlingAction; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNodeName; import org.slf4j.Logger; interface VppNodeReader { @@ -29,13 +32,14 @@ interface VppNodeReader { * @param nodeIndex index of vpp node treated as signed integer. * @return vpp node representation */ - default VppNode readVppNode(final int nodeIndex, @Nonnull final Logger log) { + default Optional<VppNode> readVppNode(final int tableIndex, final int nodeIndex, + @Nonnull final VppClassifierContextManager vppClassifierContextManager, + @Nonnull final MappingContext ctx, @Nonnull final Logger log) { final PacketHandlingAction action = PacketHandlingAction.forValue(nodeIndex); if (action == null) { - // TODO: implement node index to name conversion after https://jira.fd.io/browse/VPP-203 is fixed - log.debug("VPP node index {} cannot be mapped to PacketHandlingAction", nodeIndex); - return null; + return vppClassifierContextManager.getNodeName(tableIndex, nodeIndex, ctx) + .transform(nodeName -> new VppNode(new VppNodeName(nodeName))); } - return new VppNode(action); + return Optional.of(new VppNode(action)); } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppNodeWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppNodeWriter.java new file mode 100644 index 000000000..a4667bf4d --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppNodeWriter.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.translate.v3po.vppclassifier; + +import static com.google.common.base.Preconditions.checkArgument; + +import io.fd.honeycomb.translate.MappingContext; +import io.fd.honeycomb.translate.v3po.util.FutureJVppCustomizer; +import io.fd.honeycomb.translate.v3po.util.ReadTimeoutException; +import io.fd.honeycomb.translate.v3po.util.TranslateUtils; +import io.fd.honeycomb.translate.write.WriteFailedException; +import java.util.concurrent.CompletionStage; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.ClassifyTable; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.openvpp.jvpp.VppBaseCallException; +import org.openvpp.jvpp.core.dto.GetNextIndex; +import org.openvpp.jvpp.core.dto.GetNextIndexReply; +import org.openvpp.jvpp.core.future.FutureJVppCore; + +abstract class VppNodeWriter extends FutureJVppCustomizer { + + protected VppNodeWriter(@Nonnull final FutureJVppCore futureJvpp) { + super(futureJvpp); + } + + protected int getNodeIndex(@Nonnull final VppNode node, @Nonnull final ClassifyTable classifyTable, + @Nonnull final VppClassifierContextManager vppClassifierContextManager, + @Nonnull final MappingContext ctx, @Nonnull final InstanceIdentifier<?> id) + throws VppBaseCallException, WriteFailedException { + if (node.getPacketHandlingAction() != null) { + return node.getPacketHandlingAction().getIntValue(); + } else { + return nodeNameToIndex(classifyTable, node.getVppNodeName().getValue(), vppClassifierContextManager, ctx, id); + } + } + + private int nodeNameToIndex(@Nonnull final ClassifyTable classifyTable, @Nonnull final String nextNodeName, + @Nonnull final VppClassifierContextManager vppClassifierContextManager, + @Nonnull final MappingContext ctx, @Nonnull final InstanceIdentifier<?> id) + throws VppBaseCallException, WriteFailedException { + checkArgument(classifyTable != null && classifyTable.getClassifierNode() != null, "to use relative node names, table classifier node needs to be provided"); + final GetNextIndex request = new GetNextIndex(); + request.nodeName = classifyTable.getClassifierNode().getValue().getBytes(); + request.nextName = nextNodeName.getBytes(); + final CompletionStage<GetNextIndexReply> getNextIndexCompletionStage = + getFutureJVpp().getNextIndex(request); + + final GetNextIndexReply reply; + try { + reply = TranslateUtils.getReplyForRead(getNextIndexCompletionStage.toCompletableFuture(), id); + + // vpp does not provide relative node index to node name conversion (https://jira.fd.io/browse/VPP-219) + // as a workaround we need to add mapping to vpp-classfier-context + vppClassifierContextManager.addNodeName(classifyTable.getName(), reply.nextIndex, nextNodeName, ctx); + } catch (ReadTimeoutException e) { + throw new WriteFailedException(id, String.format("Failed to get node index for %s relative to %s", + nextNodeName, classifyTable.getClassifierNode()), e); + } + return reply.nextIndex; + } +} diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/AclCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/AclCustomizerTest.java index 66e96b45d..578b24578 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/AclCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/AclCustomizerTest.java @@ -27,21 +27,18 @@ import static org.mockito.Mockito.verify; import static org.mockito.MockitoAnnotations.initMocks; import com.google.common.base.Optional; -import com.google.common.collect.Lists; import io.fd.honeycomb.translate.MappingContext; import io.fd.honeycomb.translate.v3po.test.TestHelperUtils; import io.fd.honeycomb.translate.v3po.util.NamingContext; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; import io.fd.honeycomb.translate.write.WriteContext; import io.fd.honeycomb.translate.write.WriteFailedException; -import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.MappingsBuilder; import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping; import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.MappingKey; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; @@ -68,13 +65,13 @@ public class AclCustomizerTest { private WriteContext writeContext; @Mock private MappingContext mappingContext; + @Mock + private VppClassifierContextManager classifyTableContext; private NamingContext interfaceContext; - private NamingContext classifyTableContext; private AclCustomizer customizer; private static final String IFC_TEST_INSTANCE = "ifc-test-instance"; - private static final String CT_TEST_INSTANCE = "ct-test-instance"; private static final String IF_NAME = "local0"; private static final int IF_INDEX = 1; @@ -85,23 +82,12 @@ public class AclCustomizerTest { public void setUp() throws Exception { initMocks(this); interfaceContext = new NamingContext("generatedInterfaceName", IFC_TEST_INSTANCE); - classifyTableContext = new NamingContext("generatedClassifyTable", CT_TEST_INSTANCE); doReturn(mappingContext).when(writeContext).getMappingContext(); customizer = new AclCustomizer(api, interfaceContext, classifyTableContext); final KeyedInstanceIdentifier<Mapping, MappingKey> ifcMappingKey = getMappingIid(IF_NAME, IFC_TEST_INSTANCE); final Optional<Mapping> ifcMapping = getMapping(IF_NAME, IF_INDEX); doReturn(ifcMapping).when(mappingContext).read(ifcMappingKey); - - final KeyedInstanceIdentifier<Mapping, MappingKey> ctMappingKey = - getMappingIid(ACL_TABLE_NAME, CT_TEST_INSTANCE); - final Optional<Mapping> ctMapping = getMapping(ACL_TABLE_NAME, ACL_TABLE_INDEX); - doReturn(ctMapping).when(mappingContext).read(ctMappingKey); - - final List<Mapping> allCtMappings = Lists.newArrayList(ctMapping.get()); - final Mappings allCtMappingsBaObject = new MappingsBuilder().setMapping(allCtMappings).build(); - doReturn(Optional.of(allCtMappingsBaObject)).when(mappingContext) - .read(ctMappingKey.firstIdentifierOf(Mappings.class)); } diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclCustomizerTest.java index 84d2306e6..86cb6b90a 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclCustomizerTest.java @@ -27,9 +27,11 @@ import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; import io.fd.honeycomb.translate.v3po.test.ContextTestUtils; import io.fd.honeycomb.translate.v3po.test.ReaderCustomizerTest; import io.fd.honeycomb.translate.v3po.util.NamingContext; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; import java.util.List; import java.util.concurrent.CompletableFuture; import org.junit.Test; +import org.mockito.Mock; import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings; import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.MappingsBuilder; import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping; @@ -55,10 +57,11 @@ public class AclCustomizerTest extends ReaderCustomizerTest<Acl, AclBuilder> { private static final String TABLE_NAME = "table123"; private static final String IFC_TEST_INSTANCE = "ifc-test-instance"; - private static final String CT_TEST_INSTANCE = "ct-test-instance"; private NamingContext interfaceContext; - private NamingContext classifyTableContext; + + @Mock + private VppClassifierContextManager classifyTableContext; public AclCustomizerTest() { super(Acl.class); @@ -67,23 +70,12 @@ public class AclCustomizerTest extends ReaderCustomizerTest<Acl, AclBuilder> { @Override public void setUpBefore() { interfaceContext = new NamingContext("generatedIfaceName", IFC_TEST_INSTANCE); - classifyTableContext = new NamingContext("generatedTableContext", CT_TEST_INSTANCE); final KeyedInstanceIdentifier<Mapping, MappingKey> ifcMappingKey = ContextTestUtils .getMappingIid(IF_NAME, IFC_TEST_INSTANCE); final Optional<Mapping> ifcMapping = ContextTestUtils.getMapping(IF_NAME, IF_INDEX); doReturn(ifcMapping).when(mappingContext).read(ifcMappingKey); - final KeyedInstanceIdentifier<Mapping, MappingKey> ctMappingKey = ContextTestUtils - .getMappingIid(TABLE_NAME, CT_TEST_INSTANCE); - final Optional<Mapping> ctMapping = ContextTestUtils.getMapping(TABLE_NAME, TABLE_INDEX); - doReturn(ctMapping).when(mappingContext).read(ctMappingKey); - - final List<Mapping> allCtMappings = Lists.newArrayList(ctMapping.get()); - final Mappings allCtMappingsBaObject = new MappingsBuilder().setMapping(allCtMappings).build(); - doReturn(Optional.of(allCtMappingsBaObject)).when(mappingContext) - .read(ctMappingKey.firstIdentifierOf(Mappings.class)); - final List<Mapping> allIfcMappings = Lists.newArrayList(ifcMapping.get()); final Mappings allIfcMappingsBaObject = new MappingsBuilder().setMapping(allIfcMappings).build(); doReturn(Optional.of(allIfcMappingsBaObject)).when(mappingContext) @@ -122,6 +114,8 @@ public class AclCustomizerTest extends ReaderCustomizerTest<Acl, AclBuilder> { replyFuture.complete(reply); doReturn(replyFuture).when(api).classifyTableByInterface(any(ClassifyTableByInterface.class)); + doReturn(TABLE_NAME).when(classifyTableContext).getTableName(TABLE_INDEX, mappingContext); + getCustomizer().readCurrentAttributes(id, builder, ctx); verify(builder).setL2Acl(new L2AclBuilder().setClassifyTable(TABLE_NAME).build()); diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionReaderTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionReaderTest.java index f5159919c..d1bda8793 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionReaderTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionReaderTest.java @@ -23,19 +23,16 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import com.google.common.base.Optional; import io.fd.honeycomb.translate.ModificationCache; import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; -import io.fd.honeycomb.translate.v3po.test.ContextTestUtils; import io.fd.honeycomb.translate.v3po.test.ListReaderCustomizerTest; -import io.fd.honeycomb.translate.v3po.util.NamingContext; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; import org.junit.Test; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping; +import org.mockito.Mock; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppClassifierState; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.classify.table.base.attributes.ClassifySession; @@ -58,23 +55,16 @@ public class ClassifySessionReaderTest extends private static final int TABLE_INDEX = 1; private static final String TABLE_NAME = "table1"; - private NamingContext classifyTableContext; + @Mock + private VppClassifierContextManager classifierContext; public ClassifySessionReaderTest() { super(ClassifySession.class); } @Override - public void setUpBefore() { - classifyTableContext = new NamingContext("classifyTableContext", "test-instance"); - - final Optional<Mapping> ifcMapping = ContextTestUtils.getMapping(TABLE_NAME, TABLE_INDEX); - doReturn(ifcMapping).when(mappingContext).read(any()); - } - - @Override protected ReaderCustomizer<ClassifySession, ClassifySessionBuilder> initCustomizer() { - return new ClassifySessionReader(api, classifyTableContext); + return new ClassifySessionReader(api, classifierContext); } private static InstanceIdentifier<ClassifySession> getClassifySessionId(final String tableName, @@ -127,6 +117,9 @@ public class ClassifySessionReaderTest extends replyFuture.complete(dump); doReturn(replyFuture).when(api).classifySessionDump(any(ClassifySessionDump.class)); + when(classifierContext.containsTable(TABLE_NAME, mappingContext)).thenReturn(true); + when(classifierContext.getTableIndex(TABLE_NAME, mappingContext)).thenReturn(TABLE_INDEX); + final List<ClassifySessionKey> allIds = getCustomizer().getAllIds(id, ctx); assertEquals(2, allIds.size()); assertEquals(MATCH_1, allIds.get(0).getMatch().getValue()); diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionWriterTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionWriterTest.java index 85f7b8638..d7d7ded25 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionWriterTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifySessionWriterTest.java @@ -16,20 +16,20 @@ package io.fd.honeycomb.translate.v3po.vppclassifier; -import static io.fd.honeycomb.translate.v3po.test.ContextTestUtils.getMapping; -import static junit.framework.TestCase.assertTrue; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; import com.google.common.base.Optional; import io.fd.honeycomb.translate.MappingContext; import io.fd.honeycomb.translate.v3po.test.TestHelperUtils; -import io.fd.honeycomb.translate.v3po.util.NamingContext; import io.fd.honeycomb.translate.write.WriteContext; import io.fd.honeycomb.translate.write.WriteFailedException; import java.util.concurrent.CompletableFuture; @@ -38,12 +38,12 @@ import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.OpaqueIndex; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.PacketHandlingAction; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppClassifier; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNodeName; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.classify.table.base.attributes.ClassifySession; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.classify.table.base.attributes.ClassifySessionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.classify.table.base.attributes.ClassifySessionKey; @@ -66,21 +66,26 @@ public class ClassifySessionWriterTest { @Mock private WriteContext writeContext; @Mock - private MappingContext mappingContext; + private MappingContext ctx; + @Mock + private VppClassifierContextManager classfierContext; - private NamingContext classifyTableContext; private ClassifySessionWriter customizer; private static final int SESSION_INDEX = 456; @Before public void setUp() throws Exception { initMocks(this); - classifyTableContext = new NamingContext("generatedClassifyTableName", "test-instance"); - doReturn(mappingContext).when(writeContext).getMappingContext(); - customizer = new ClassifySessionWriter(api, classifyTableContext); + doReturn(ctx).when(writeContext).getMappingContext(); + customizer = new ClassifySessionWriter(api, classfierContext); + + when(classfierContext.containsTable(TABLE_NAME, ctx)).thenReturn(true); + when(classfierContext.getTableIndex(TABLE_NAME, ctx)).thenReturn(TABLE_INDEX); - final Optional<Mapping> ifcMapping = getMapping(TABLE_NAME, TABLE_INDEX); - doReturn(ifcMapping).when(mappingContext).read(any()); + final ClassifyTable table = mock(ClassifyTable.class); + when(table.getClassifierNode()).thenReturn(new VppNodeName("ip4-classifier")); + when(writeContext.readAfter(any())).thenReturn(Optional.of(table)); + when(writeContext.readBefore(any())).thenReturn(Optional.of(table)); } private static ClassifySession generateClassifySession(final long opaqueIndex, final String match) { diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableReaderTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableReaderTest.java index 38ca324d9..d4a8c4363 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableReaderTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableReaderTest.java @@ -23,21 +23,16 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import com.google.common.base.Optional; -import com.google.common.collect.Lists; +import io.fd.honeycomb.translate.read.ReadFailedException; import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; -import io.fd.honeycomb.translate.v3po.test.ContextTestUtils; import io.fd.honeycomb.translate.v3po.test.ListReaderCustomizerTest; -import io.fd.honeycomb.translate.read.ReadFailedException; -import io.fd.honeycomb.translate.v3po.util.NamingContext; import java.util.List; import java.util.concurrent.CompletableFuture; import org.junit.Test; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.Mappings; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.MappingsBuilder; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.MappingKey; +import org.mockito.Mock; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.PacketHandlingAction; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppClassifierState; @@ -47,7 +42,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.clas import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.state.ClassifyTableBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.state.ClassifyTableKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.openvpp.jvpp.core.dto.ClassifyTableIds; import org.openvpp.jvpp.core.dto.ClassifyTableIdsReply; import org.openvpp.jvpp.core.dto.ClassifyTableInfo; @@ -61,32 +55,16 @@ public class ClassifyTableReaderTest extends private static final int TABLE_INDEX_2 = 2; private static final String TABLE_NAME_2 = "table2"; - private NamingContext classifyTableContext; + @Mock + private VppClassifierContextManager classifierContext; public ClassifyTableReaderTest() { super(ClassifyTable.class); } @Override - public void setUpBefore() { - classifyTableContext = new NamingContext("classifyTableContext", "test-instance"); - - final KeyedInstanceIdentifier<Mapping, MappingKey> t0Id = ContextTestUtils - .getMappingIid(TABLE_NAME_1, "test-instance"); - final KeyedInstanceIdentifier<Mapping, MappingKey> t1Id = ContextTestUtils - .getMappingIid(TABLE_NAME_2, "test-instance"); - final Optional<Mapping> t0 = ContextTestUtils.getMapping(TABLE_NAME_1, TABLE_INDEX_1); - final Optional<Mapping> t1 = ContextTestUtils.getMapping(TABLE_NAME_2, TABLE_INDEX_2); - final List<Mapping> allMappings = Lists.newArrayList(t0.get(), t1.get()); - final Mappings allMappingsBaObject = new MappingsBuilder().setMapping(allMappings).build(); - doReturn(Optional.of(allMappingsBaObject)).when(mappingContext).read(t0Id.firstIdentifierOf(Mappings.class)); - doReturn(t0).when(mappingContext).read(t0Id); - doReturn(t1).when(mappingContext).read(t1Id); - } - - @Override protected ReaderCustomizer<ClassifyTable, ClassifyTableBuilder> initCustomizer() { - return new ClassifyTableReader(api, classifyTableContext); + return new ClassifyTableReader(api, classifierContext); } private static InstanceIdentifier<ClassifyTable> getClassifyTableId(final String name) { @@ -131,6 +109,10 @@ public class ClassifyTableReaderTest extends replyFuture.complete(generateClassifyTableInfoReply()); doReturn(replyFuture).when(api).classifyTableInfo(any(ClassifyTableInfo.class)); + when(classifierContext.containsTable(TABLE_NAME_1, mappingContext)).thenReturn(true); + when(classifierContext.getTableIndex(TABLE_NAME_1, mappingContext)).thenReturn(TABLE_INDEX_1); + when(classifierContext.getTableBaseNode(TABLE_NAME_1, mappingContext)).thenReturn(Optional.absent()); + final ClassifyTableBuilder builder = mock(ClassifyTableBuilder.class); getCustomizer().readCurrentAttributes(getClassifyTableId(TABLE_NAME_1), builder, ctx); @@ -145,6 +127,9 @@ public class ClassifyTableReaderTest extends replyFuture.complete(reply); doReturn(replyFuture).when(api).classifyTableIds(any(ClassifyTableIds.class)); + when(classifierContext.getTableName(TABLE_INDEX_1, mappingContext)).thenReturn(TABLE_NAME_1); + when(classifierContext.getTableName(TABLE_INDEX_2, mappingContext)).thenReturn(TABLE_NAME_2); + final List<ClassifyTableKey> allIds = getCustomizer().getAllIds(getClassifyTableId(TABLE_NAME_1), ctx); assertEquals(reply.ids.length, allIds.size()); diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableWriterTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableWriterTest.java index 5a3717e50..af91ead8c 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableWriterTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/ClassifyTableWriterTest.java @@ -16,23 +16,19 @@ package io.fd.honeycomb.translate.v3po.vppclassifier; -import static io.fd.honeycomb.translate.v3po.test.ContextTestUtils.getMapping; -import static io.fd.honeycomb.translate.v3po.test.ContextTestUtils.getMappingIid; -import static junit.framework.TestCase.assertTrue; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; -import com.google.common.base.Optional; import io.fd.honeycomb.translate.MappingContext; import io.fd.honeycomb.translate.v3po.test.TestHelperUtils; -import io.fd.honeycomb.translate.v3po.util.NamingContext; import io.fd.honeycomb.translate.write.WriteContext; import io.fd.honeycomb.translate.write.WriteFailedException; import java.util.concurrent.CompletableFuture; @@ -41,11 +37,11 @@ import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.opendaylight.yang.gen.v1.urn.honeycomb.params.xml.ns.yang.naming.context.rev160513.contexts.naming.context.mappings.Mapping; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.PacketHandlingAction; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppClassifier; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNodeName; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.ClassifyTable; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.ClassifyTableBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.vpp.classifier.ClassifyTableKey; @@ -66,22 +62,23 @@ public class ClassifyTableWriterTest { @Mock private WriteContext writeContext; @Mock - private MappingContext mappingContext; + private MappingContext ctx; + @Mock + private VppClassifierContextManager classifierContext; - private NamingContext classifyTableContext; private ClassifyTableWriter customizer; @Before public void setUp() throws Exception { initMocks(this); - classifyTableContext = new NamingContext("generatedClassifyTableName", "test-instance"); - doReturn(mappingContext).when(writeContext).getMappingContext(); - customizer = new ClassifyTableWriter(api, classifyTableContext); + customizer = new ClassifyTableWriter(api, classifierContext); + doReturn(ctx).when(writeContext).getMappingContext(); } private static ClassifyTable generateClassifyTable(final String name) { final ClassifyTableBuilder builder = new ClassifyTableBuilder(); builder.setName(name); + builder.setClassifierNode(new VppNodeName("ip4-classifier")); builder.setKey(new ClassifyTableKey(name)); builder.setSkipNVectors(0L); builder.setNbuckets(2L); @@ -158,8 +155,7 @@ public class ClassifyTableWriterTest { customizer.writeCurrentAttributes(id, classifyTable, writeContext); verifyClassifyAddDelTableAddWasInvoked(generateClassifyAddDelTable((byte) 1, TABLE_INDEX)); - verify(mappingContext) - .put(eq(getMappingIid(TABLE_NAME, "test-instance")), eq(getMapping(TABLE_NAME, TABLE_INDEX).get())); + verify(classifierContext).addTable(TABLE_INDEX, classifyTable.getName(), classifyTable.getClassifierNode(), ctx); } @Test @@ -174,9 +170,8 @@ public class ClassifyTableWriterTest { } catch (WriteFailedException.CreateFailedException e) { assertTrue(e.getCause() instanceof VppBaseCallException); verifyClassifyAddDelTableAddWasInvoked(generateClassifyAddDelTable((byte) 1, TABLE_INDEX)); - verify(mappingContext, times(0)).put( - eq(getMappingIid(TABLE_NAME, "test-instance")), - eq(getMapping(TABLE_NAME, TABLE_INDEX).get())); + verify(classifierContext, times(0)) + .addTable(TABLE_INDEX, classifyTable.getName(), classifyTable.getClassifierNode(), ctx); return; } fail("WriteFailedException.CreateFailedException was expected"); @@ -187,9 +182,8 @@ public class ClassifyTableWriterTest { final ClassifyTable classifyTable = generateClassifyTable(TABLE_NAME); final InstanceIdentifier<ClassifyTable> id = getClassifyTableId(TABLE_NAME); - final Optional<Mapping> ifcMapping = getMapping(TABLE_NAME, TABLE_INDEX); - doReturn(ifcMapping).when(mappingContext).read(any()); - + when(classifierContext.containsTable(TABLE_NAME, ctx)).thenReturn(true); + when(classifierContext.getTableIndex(TABLE_NAME, ctx)).thenReturn(TABLE_INDEX); whenClassifyAddDelTableThenSuccess(); customizer.deleteCurrentAttributes(id, classifyTable, writeContext); @@ -202,9 +196,8 @@ public class ClassifyTableWriterTest { final ClassifyTable classifyTable = generateClassifyTable(TABLE_NAME); final InstanceIdentifier<ClassifyTable> id = getClassifyTableId(TABLE_NAME); - final Optional<Mapping> ifcMapping = getMapping(TABLE_NAME, TABLE_INDEX); - doReturn(ifcMapping).when(mappingContext).read(any()); - + when(classifierContext.containsTable(TABLE_NAME, ctx)).thenReturn(true); + when(classifierContext.getTableIndex(TABLE_NAME, ctx)).thenReturn(TABLE_INDEX); whenClassifyAddDelTableThenFailure(); try { diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppClassifierContextManagerImplTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppClassifierContextManagerImplTest.java new file mode 100644 index 000000000..cbc0c3802 --- /dev/null +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/vppclassifier/VppClassifierContextManagerImplTest.java @@ -0,0 +1,155 @@ +/* + * 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.translate.v3po.vppclassifier; + +import static io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManagerImpl.VPP_CLASSIFIER_CONTEXT_IID; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.MockitoAnnotations.initMocks; + +import com.google.common.base.Optional; +import io.fd.honeycomb.translate.MappingContext; +import java.util.Arrays; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev150603.VppNodeName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.VppClassifierContext; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.VppClassifierContextBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContext; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContextBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.ClassifyTableContextKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContext; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContextBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.classifier.rev160909.vpp.classifier.context.classify.table.context.NodeContextKey; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; + +public class VppClassifierContextManagerImplTest { + + private static final int TABLE_ID_0 = 0; + private static final String TABLE_NAME_0 = "table0"; + private static final KeyedInstanceIdentifier<ClassifyTableContext, ClassifyTableContextKey> TABLE_IID_0 = + VPP_CLASSIFIER_CONTEXT_IID.child(ClassifyTableContext.class, new ClassifyTableContextKey(TABLE_NAME_0)); + + private static final int TABLE_ID_1 = 1; + private static final String TABLE_NAME_1 = "table1"; + + private VppClassifierContextManagerImpl vppClassfierContext; + + @Mock + private MappingContext ctx; + + @Before + public void setUp() throws Exception { + initMocks(this); + vppClassfierContext = new VppClassifierContextManagerImpl("classify-table-"); + } + + @Test + public void testAddTable() throws Exception { + final String classfierNodeName = "node123"; + vppClassfierContext.addTable(TABLE_ID_0, TABLE_NAME_0, new VppNodeName(classfierNodeName), ctx); + verify(ctx).put(TABLE_IID_0, table(TABLE_ID_0, TABLE_NAME_0, classfierNodeName)); + } + + @Test + public void testContainsTable() throws Exception { + when(ctx.read(TABLE_IID_0)).thenReturn(Optional.absent()); + assertFalse(vppClassfierContext.containsTable(TABLE_NAME_0, ctx)); + } + + @Test + public void testGetTableIndex() throws Exception { + when(ctx.read(TABLE_IID_0)).thenReturn(Optional.of(table(TABLE_ID_0, TABLE_NAME_0))); + assertEquals(TABLE_ID_0, vppClassfierContext.getTableIndex(TABLE_NAME_0, ctx)); + } + + @Test + public void testGetTableName() throws Exception { + when(ctx.read(VPP_CLASSIFIER_CONTEXT_IID)) + .thenReturn(Optional.of(context(table(TABLE_ID_0, TABLE_NAME_0), table(TABLE_ID_1, TABLE_NAME_1)))); + assertEquals(TABLE_NAME_0, (vppClassfierContext.getTableName(TABLE_ID_0, ctx))); + } + + @Test + public void testGetTableBaseNode() throws Exception { + final String classfierNodeName = "node123"; + when(ctx.read(TABLE_IID_0)).thenReturn(Optional.of(table(TABLE_ID_0, TABLE_NAME_0, classfierNodeName))); + vppClassfierContext.getTableBaseNode(TABLE_NAME_0, ctx); + assertEquals(Optional.of(classfierNodeName), (vppClassfierContext.getTableBaseNode(TABLE_NAME_0, ctx))); + } + + @Test + public void testRemoveTable() throws Exception { + vppClassfierContext.removeTable(TABLE_NAME_0, ctx); + verify(ctx).delete(TABLE_IID_0); + } + + @Test + public void testAddNodeName() throws Exception { + final String nodeName = "node123"; + final int nodeIndex = 1; + + vppClassfierContext.addNodeName(TABLE_NAME_0, nodeIndex, nodeName, ctx); + verify(ctx).put( + TABLE_IID_0.child(NodeContext.class, new NodeContextKey(nodeName)), + node(nodeName, nodeIndex) + ); + } + + @Test + public void testGetNonExistingNodeName() throws Exception { + when(ctx.read(VPP_CLASSIFIER_CONTEXT_IID)).thenReturn(Optional.of(context(table(TABLE_ID_1, TABLE_NAME_1)))); + assertFalse(vppClassfierContext.getNodeName(TABLE_ID_0, 123, ctx).isPresent()); + } + + @Test + public void testGetNodeName() throws Exception { + final ClassifyTableContext tableCtx = table(TABLE_ID_0, TABLE_NAME_0, "aa", node("node123", 123)); + when(ctx.read(VPP_CLASSIFIER_CONTEXT_IID)).thenReturn(Optional.of(context(tableCtx))); + when(ctx.read(TABLE_IID_0)).thenReturn(Optional.of(tableCtx)); + assertEquals(Optional.of("node123"), vppClassfierContext.getNodeName(TABLE_ID_0, 123, ctx)); + } + + private VppClassifierContext context(ClassifyTableContext... tables) { + VppClassifierContextBuilder context = new VppClassifierContextBuilder(); + context.setClassifyTableContext(Arrays.asList(tables)); + return context.build(); + } + + private static ClassifyTableContext table(final Integer id, final String name) { + return table(id, name, null); + } + + private static ClassifyTableContext table(final Integer id, final String name, final String classfierNodeName, + final NodeContext... nodeContexts) { + final ClassifyTableContextBuilder builder = + new ClassifyTableContextBuilder().setIndex(id).setName(name).setClassifierNodeName(classfierNodeName); + + if (nodeContexts.length > 0) { + builder.setNodeContext(Arrays.asList(nodeContexts)); + } + + return builder.build(); + } + + private NodeContext node(final String nodeName, final int nodeIndex) { + return new NodeContextBuilder().setName(nodeName).setIndex(nodeIndex).build(); + } +}
\ No newline at end of file |