From 91ed838793842d1006ff058dd87930013a321f7f Mon Sep 17 00:00:00 2001 From: Marek Gradzki Date: Fri, 30 Sep 2016 12:28:28 +0200 Subject: HONEYCOMB-234: update YANG model to support egress ACLs - marks existing ACL support as ingress - updates postman collection Change-Id: I7ae39cb6698d9aafbe932d57725f138194b52e70 Signed-off-by: Maros Marsalek Signed-off-by: Marek Gradzki --- .../honeycomb/translate/v3po/AclWriterFactory.java | 4 +- .../translate/v3po/IetfAClWriterProvider.java | 2 +- .../v3po/InterfacesStateReaderFactory.java | 40 ++-- .../translate/v3po/InterfacesWriterFactory.java | 61 +++--- .../SubinterfaceAugmentationWriterFactory.java | 23 ++- ...SubinterfaceStateAugmentationReaderFactory.java | 50 +++-- .../io/fd/honeycomb/translate/v3po/V3poModule.java | 2 +- .../v3po/initializers/InterfacesInitializer.java | 25 ++- .../SubInterfaceInitializationUtils.java | 24 ++- .../translate/v3po/interfaces/AclCustomizer.java | 92 --------- .../translate/v3po/interfaces/AclWriter.java | 75 ------- .../v3po/interfaces/SubInterfaceAclCustomizer.java | 102 --------- .../v3po/interfaces/acl/AbstractAceWriter.java | 181 ---------------- .../v3po/interfaces/acl/AceEthWriter.java | 142 ------------- .../v3po/interfaces/acl/AceIp4Writer.java | 195 ------------------ .../v3po/interfaces/acl/AceIp6Writer.java | 227 --------------------- .../translate/v3po/interfaces/acl/AceWriter.java | 45 ---- .../translate/v3po/interfaces/acl/AclWriter.java | 105 ---------- .../v3po/interfaces/acl/IetfAClWriter.java | 208 ------------------- .../v3po/interfaces/acl/IetfAclCustomizer.java | 93 --------- .../v3po/interfaces/acl/IetfAclWriter.java | 106 ++++++++++ .../acl/SubInterfaceIetfAclCustomizer.java | 112 ---------- .../interfaces/acl/ingress/AbstractAceWriter.java | 181 ++++++++++++++++ .../v3po/interfaces/acl/ingress/AceEthWriter.java | 142 +++++++++++++ .../v3po/interfaces/acl/ingress/AceIp4Writer.java | 195 ++++++++++++++++++ .../v3po/interfaces/acl/ingress/AceIp6Writer.java | 227 +++++++++++++++++++++ .../v3po/interfaces/acl/ingress/AceWriter.java | 45 ++++ .../v3po/interfaces/acl/ingress/AclCustomizer.java | 92 +++++++++ .../v3po/interfaces/acl/ingress/AclWriter.java | 75 +++++++ .../v3po/interfaces/acl/ingress/IetfAClWriter.java | 209 +++++++++++++++++++ .../interfaces/acl/ingress/IetfAclCustomizer.java | 93 +++++++++ .../acl/ingress/SubInterfaceAclCustomizer.java | 102 +++++++++ .../acl/ingress/SubInterfaceIetfAclCustomizer.java | 112 ++++++++++ .../v3po/interfacesstate/AclCustomizer.java | 97 --------- .../translate/v3po/interfacesstate/AclReader.java | 60 ------ .../interfacesstate/SubInterfaceAclCustomizer.java | 104 ---------- .../interfacesstate/acl/ingress/AclCustomizer.java | 97 +++++++++ .../interfacesstate/acl/ingress/AclReader.java | 60 ++++++ .../acl/ingress/SubInterfaceAclCustomizer.java | 104 ++++++++++ 39 files changed, 1991 insertions(+), 1918 deletions(-) delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/AclCustomizer.java delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/AclWriter.java delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/SubInterfaceAclCustomizer.java delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AbstractAceWriter.java delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceEthWriter.java delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceIp4Writer.java delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceIp6Writer.java delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceWriter.java delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AclWriter.java delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/IetfAClWriter.java delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/IetfAclCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/IetfAclWriter.java delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/SubInterfaceIetfAclCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AbstractAceWriter.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceEthWriter.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp4Writer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp6Writer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceWriter.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AclCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AclWriter.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/IetfAClWriter.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/IetfAclCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/SubInterfaceAclCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/SubInterfaceIetfAclCustomizer.java delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclCustomizer.java delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclReader.java delete mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/SubInterfaceAclCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/acl/ingress/AclCustomizer.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/acl/ingress/AclReader.java create mode 100644 v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/acl/ingress/SubInterfaceAclCustomizer.java (limited to 'v3po/v3po2vpp/src/main/java') diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/AclWriterFactory.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/AclWriterFactory.java index 21bc2e6cb..ef0fc7ea5 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/AclWriterFactory.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/AclWriterFactory.java @@ -21,7 +21,7 @@ import static io.fd.honeycomb.translate.v3po.SubinterfaceAugmentationWriterFacto import com.google.common.collect.Sets; import io.fd.honeycomb.translate.impl.write.GenericListWriter; -import io.fd.honeycomb.translate.v3po.interfaces.acl.AclWriter; +import io.fd.honeycomb.translate.v3po.interfaces.acl.IetfAclWriter; import io.fd.honeycomb.translate.write.WriterFactory; import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder; import javax.annotation.Nonnull; @@ -48,7 +48,7 @@ public final class AclWriterFactory implements WriterFactory { final InstanceIdentifier matchesId = aceId.child(Matches.class); registry.subtreeAddBefore(Sets.newHashSet(aceId, actionsId, matchesId), - new GenericListWriter<>(ACL_ID, new AclWriter()), + new GenericListWriter<>(ACL_ID, new IetfAclWriter()), Sets.newHashSet(IETF_ACL_ID, SUBIF_IETF_ACL_ID)); } } diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/IetfAClWriterProvider.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/IetfAClWriterProvider.java index 68387603d..8e001b75d 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/IetfAClWriterProvider.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/IetfAClWriterProvider.java @@ -18,7 +18,7 @@ package io.fd.honeycomb.translate.v3po; import com.google.inject.Inject; import com.google.inject.Provider; -import io.fd.honeycomb.translate.v3po.interfaces.acl.IetfAClWriter; +import io.fd.honeycomb.translate.v3po.interfaces.acl.ingress.IetfAClWriter; import io.fd.vpp.jvpp.core.future.FutureJVppCore; class IetfAClWriterProvider implements Provider { 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 3aafea2ec..0a94a1bed 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 @@ -23,9 +23,9 @@ import io.fd.honeycomb.translate.impl.read.GenericListReader; import io.fd.honeycomb.translate.impl.read.GenericReader; import io.fd.honeycomb.translate.read.ReaderFactory; import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder; -import io.fd.honeycomb.translate.v3po.interfacesstate.AclCustomizer; import io.fd.honeycomb.translate.v3po.interfacesstate.EthernetCustomizer; import io.fd.honeycomb.translate.v3po.interfacesstate.GreCustomizer; +import io.fd.honeycomb.translate.v3po.interfacesstate.acl.ingress.AclCustomizer; import io.fd.honeycomb.translate.v3po.interfacesstate.InterfaceCustomizer; import io.fd.honeycomb.translate.v3po.interfacesstate.L2Customizer; import io.fd.honeycomb.translate.v3po.interfacesstate.ProxyArpCustomizer; @@ -37,8 +37,9 @@ import io.fd.honeycomb.translate.v3po.interfacesstate.ip.Ipv4AddressCustomizer; 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.vpp.util.NamingContext; import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; +import io.fd.honeycomb.translate.vpp.util.NamingContext; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; 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; @@ -54,6 +55,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip6Acl; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.L2Acl; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Acl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.AclBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Ethernet; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Gre; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.L2; @@ -62,8 +64,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VhostUser; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Vxlan; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VxlanGpe; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.acl.Ingress; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; public final class InterfacesStateReaderFactory implements ReaderFactory { @@ -74,7 +76,7 @@ public final class InterfacesStateReaderFactory implements ReaderFactory { private final FutureJVppCore jvpp; static final InstanceIdentifier IFC_STATE_ID = - InstanceIdentifier.create(InterfacesState.class); + InstanceIdentifier.create(InterfacesState.class); static final InstanceIdentifier IFC_ID = IFC_STATE_ID.child(Interface.class); @Inject @@ -127,30 +129,40 @@ public final class InterfacesStateReaderFactory implements ReaderFactory { private void initVppIfcAugmentationReaders(final ModifiableReaderRegistryBuilder registry, final InstanceIdentifier ifcId) { // VppInterfaceStateAugmentation - final InstanceIdentifier vppIfcAugId = ifcId.augmentation(VppInterfaceStateAugmentation.class); + final InstanceIdentifier vppIfcAugId = + ifcId.augmentation(VppInterfaceStateAugmentation.class); registry.addStructuralReader(vppIfcAugId, VppInterfaceStateAugmentationBuilder.class); // Ethernet - registry.add(new GenericReader<>(vppIfcAugId.child(Ethernet.class), new EthernetCustomizer(jvpp, ifcNamingCtx))); + registry + .add(new GenericReader<>(vppIfcAugId.child(Ethernet.class), new EthernetCustomizer(jvpp, ifcNamingCtx))); // Tap registry.add(new GenericReader<>(vppIfcAugId.child(Tap.class), new TapCustomizer(jvpp, ifcNamingCtx))); // VhostUser - registry.add(new GenericReader<>(vppIfcAugId.child(VhostUser.class), new VhostUserCustomizer(jvpp, ifcNamingCtx))); + registry + .add(new GenericReader<>(vppIfcAugId.child(VhostUser.class), new VhostUserCustomizer(jvpp, ifcNamingCtx))); // Vxlan registry.add(new GenericReader<>(vppIfcAugId.child(Vxlan.class), new VxlanCustomizer(jvpp, ifcNamingCtx))); // VxlanGpe - registry.add(new GenericReader<>(vppIfcAugId.child(VxlanGpe.class), new VxlanGpeCustomizer(jvpp, ifcNamingCtx))); + registry + .add(new GenericReader<>(vppIfcAugId.child(VxlanGpe.class), new VxlanGpeCustomizer(jvpp, ifcNamingCtx))); // Gre registry.add(new GenericReader<>(vppIfcAugId.child(Gre.class), new GreCustomizer(jvpp, ifcNamingCtx))); // L2 - registry.add(new GenericReader<>(vppIfcAugId.child(L2.class), new L2Customizer(jvpp, ifcNamingCtx, bdNamingCtx))); - // Acl(Subtree) - final InstanceIdentifier aclIdRelative = InstanceIdentifier.create(Acl.class); + registry + .add(new GenericReader<>(vppIfcAugId.child(L2.class), new L2Customizer(jvpp, ifcNamingCtx, bdNamingCtx))); + // Acl(Structural) + final InstanceIdentifier aclIid = vppIfcAugId.child(Acl.class); + registry.addStructuralReader(aclIid, AclBuilder.class); + // Ingress(Subtree) + final InstanceIdentifier ingressIdRelative = InstanceIdentifier.create(Ingress.class); 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, + Sets.newHashSet(ingressIdRelative.child(L2Acl.class), ingressIdRelative.child(Ip4Acl.class), + ingressIdRelative.child(Ip6Acl.class)), + new GenericReader<>(aclIid.child(Ingress.class), + new AclCustomizer(jvpp, ifcNamingCtx, classifyContext))); // Proxy ARP registry.add(new GenericReader<>(vppIfcAugId.child(ProxyArp.class), new ProxyArpCustomizer(jvpp, - ifcNamingCtx))); + 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 a71e0504c..f12f7b69d 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 @@ -24,7 +24,6 @@ import com.google.inject.Inject; import com.google.inject.name.Named; import io.fd.honeycomb.translate.impl.write.GenericListWriter; import io.fd.honeycomb.translate.impl.write.GenericWriter; -import io.fd.honeycomb.translate.v3po.interfaces.AclCustomizer; import io.fd.honeycomb.translate.v3po.interfaces.EthernetCustomizer; import io.fd.honeycomb.translate.v3po.interfaces.GreCustomizer; import io.fd.honeycomb.translate.v3po.interfaces.InterfaceCustomizer; @@ -35,16 +34,18 @@ import io.fd.honeycomb.translate.v3po.interfaces.TapCustomizer; import io.fd.honeycomb.translate.v3po.interfaces.VhostUserCustomizer; import io.fd.honeycomb.translate.v3po.interfaces.VxlanCustomizer; import io.fd.honeycomb.translate.v3po.interfaces.VxlanGpeCustomizer; -import io.fd.honeycomb.translate.v3po.interfaces.acl.IetfAClWriter; -import io.fd.honeycomb.translate.v3po.interfaces.acl.IetfAclCustomizer; +import io.fd.honeycomb.translate.v3po.interfaces.acl.ingress.AclCustomizer; +import io.fd.honeycomb.translate.v3po.interfaces.acl.ingress.IetfAClWriter; +import io.fd.honeycomb.translate.v3po.interfaces.acl.ingress.IetfAclCustomizer; import io.fd.honeycomb.translate.v3po.interfaces.ip.Ipv4AddressCustomizer; 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.vpp.util.NamingContext; import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; +import io.fd.honeycomb.translate.vpp.util.NamingContext; import io.fd.honeycomb.translate.write.WriterFactory; import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; import java.util.Set; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; @@ -69,8 +70,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VhostUser; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.Vxlan; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VxlanGpe; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.acl.Ingress; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; public final class InterfacesWriterFactory implements WriterFactory { @@ -79,8 +80,12 @@ public final class InterfacesWriterFactory implements WriterFactory { public static final InstanceIdentifier VPP_IFC_AUG_ID = IFC_ID.augmentation(VppInterfaceAugmentation.class); public static final InstanceIdentifier ACL_ID = VPP_IFC_AUG_ID.child(Acl.class); + public static final InstanceIdentifier INGRESS_ACL_ID = ACL_ID.child(Ingress.class); public static final InstanceIdentifier L2_ID = VPP_IFC_AUG_ID.child(L2.class); public static final InstanceIdentifier IETF_ACL_ID = VPP_IFC_AUG_ID.child(IetfAcl.class); + public static final InstanceIdentifier + INGRESS_IETF_ACL_ID = IETF_ACL_ID.child( + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.ietf.acl.Ingress.class); private final FutureJVppCore jvpp; private final IetfAClWriter aclWriter; @@ -123,19 +128,19 @@ public final class InterfacesWriterFactory implements WriterFactory { final InstanceIdentifier ifc1AugId = ifcId.augmentation(Interface1.class); // Ipv6(after interface) = registry.addAfter(new GenericWriter<>(ifc1AugId.child(Ipv6.class), new Ipv6Customizer(jvpp)), - ifcId); + ifcId); // Ipv4(after interface) final InstanceIdentifier ipv4Id = ifc1AugId.child(Ipv4.class); registry.addAfter(new GenericWriter<>(ipv4Id, new Ipv4Customizer(jvpp)), - ifcId); + ifcId); // Address(after Ipv4) = final InstanceIdentifier
ipv4AddressId = ipv4Id.child(Address.class); registry.addAfter(new GenericListWriter<>(ipv4AddressId, new Ipv4AddressCustomizer(jvpp, ifcNamingContext)), - ipv4Id); + ipv4Id); // Neighbor(after ipv4Address) registry.addAfter(new GenericListWriter<>(ipv4Id.child(Neighbor.class), new Ipv4NeighbourCustomizer(jvpp, - ifcNamingContext)), - ipv4AddressId); + ifcNamingContext)), + ipv4AddressId); } private void addVppInterfaceAgmentationWriters(final InstanceIdentifier ifcId, @@ -143,24 +148,24 @@ public final class InterfacesWriterFactory implements WriterFactory { // VhostUser(Needs to be executed before Interface customizer) = final InstanceIdentifier vhostId = VPP_IFC_AUG_ID.child(VhostUser.class); registry.addBefore(new GenericWriter<>(vhostId, new VhostUserCustomizer(jvpp, ifcNamingContext)), - ifcId); + ifcId); // Vxlan(Needs to be executed before Interface customizer) = final InstanceIdentifier vxlanId = VPP_IFC_AUG_ID.child(Vxlan.class); registry.addBefore(new GenericWriter<>(vxlanId, new VxlanCustomizer(jvpp, ifcNamingContext, ifcDisableContext)), - ifcId); + ifcId); // VxlanGpe(Needs to be executed before Interface customizer) = final InstanceIdentifier vxlanGpeId = VPP_IFC_AUG_ID.child(VxlanGpe.class); registry.addBefore(new GenericWriter<>(vxlanGpeId, - new VxlanGpeCustomizer(jvpp, ifcNamingContext, ifcDisableContext)), ifcId); + new VxlanGpeCustomizer(jvpp, ifcNamingContext, ifcDisableContext)), ifcId); // Tap(Needs to be executed before Interface customizer) = final InstanceIdentifier tapId = VPP_IFC_AUG_ID.child(Tap.class); registry.addBefore(new GenericWriter<>(tapId, new TapCustomizer(jvpp, ifcNamingContext)), - ifcId); + ifcId); // Gre(Needs to be executed before Interface customizer) = final InstanceIdentifier greId = VPP_IFC_AUG_ID.child(Gre.class); registry.addBefore(new GenericWriter<>(greId, new GreCustomizer(jvpp, ifcNamingContext)), - ifcId); + ifcId); final Set> specificIfcTypes = Sets.newHashSet(vhostId, vxlanGpeId, vxlanGpeId, tapId); @@ -169,32 +174,34 @@ public final class InterfacesWriterFactory implements WriterFactory { registry.add(new GenericWriter<>(VPP_IFC_AUG_ID.child(Ethernet.class), new EthernetCustomizer(jvpp))); // Routing(Execute only after specific interface customizers) = registry.addAfter( - new GenericWriter<>(VPP_IFC_AUG_ID.child(Routing.class), new RoutingCustomizer(jvpp, ifcNamingContext)), - specificIfcTypes); + new GenericWriter<>(VPP_IFC_AUG_ID.child(Routing.class), new RoutingCustomizer(jvpp, ifcNamingContext)), + specificIfcTypes); // L2(Execute only after subinterface (and all other ifc types) = registry.addAfter(new GenericWriter<>(L2_ID, new L2Customizer(jvpp, ifcNamingContext, bdNamingContext)), - SubinterfaceAugmentationWriterFactory.SUB_IFC_ID); + SubinterfaceAugmentationWriterFactory.SUB_IFC_ID); // Proxy Arp (execute after specific interface customizers) registry.addAfter( - new GenericWriter<>(VPP_IFC_AUG_ID.child(ProxyArp.class), new ProxyArpCustomizer(jvpp)), - specificIfcTypes); - // ACL (execute after classify table and session writers) + new GenericWriter<>(VPP_IFC_AUG_ID.child(ProxyArp.class), new ProxyArpCustomizer(jvpp)), + specificIfcTypes); + // Ingress (execute after classify table and session writers) // also handles L2Acl, Ip4Acl and Ip6Acl: - final InstanceIdentifier aclId = InstanceIdentifier.create(Acl.class); + final InstanceIdentifier ingressId = InstanceIdentifier.create(Ingress.class); registry .subtreeAddAfter( - Sets.newHashSet(aclId.child(L2Acl.class), aclId.child(Ip4Acl.class), aclId.child(Ip6Acl.class)), - new GenericWriter<>(ACL_ID, new AclCustomizer(jvpp, ifcNamingContext, classifyTableContext)), + Sets.newHashSet(ingressId.child(L2Acl.class), ingressId.child(Ip4Acl.class), ingressId.child(Ip6Acl.class)), + new GenericWriter<>(INGRESS_ACL_ID, + new AclCustomizer(jvpp, ifcNamingContext, classifyTableContext)), Sets.newHashSet(CLASSIFY_TABLE_ID, CLASSIFY_SESSION_ID)); - // IETF-ACL, also handles IetfAcl, AccessLists and Acl: - final InstanceIdentifier accessListsID = InstanceIdentifier.create(IetfAcl.class) + // Ingress IETF-ACL, also handles AccessLists and Acl: + final InstanceIdentifier accessListsID = InstanceIdentifier.create( + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.ietf.acl.Ingress.class) .child(AccessLists.class); final InstanceIdentifier aclListId = accessListsID.child( org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.ietf.acl.base.attributes.access.lists.Acl.class); registry.subtreeAdd( Sets.newHashSet(accessListsID, aclListId), - new GenericWriter<>(IETF_ACL_ID, new IetfAclCustomizer(aclWriter, ifcNamingContext))); + new GenericWriter<>(INGRESS_IETF_ACL_ID, new IetfAclCustomizer(aclWriter, ifcNamingContext))); } 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 f671e7076..d34a101a7 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 @@ -23,11 +23,11 @@ import com.google.common.collect.Sets; import io.fd.honeycomb.translate.impl.write.GenericListWriter; import io.fd.honeycomb.translate.impl.write.GenericWriter; import io.fd.honeycomb.translate.v3po.interfaces.RewriteCustomizer; -import io.fd.honeycomb.translate.v3po.interfaces.SubInterfaceAclCustomizer; +import io.fd.honeycomb.translate.v3po.interfaces.acl.ingress.SubInterfaceAclCustomizer; import io.fd.honeycomb.translate.v3po.interfaces.SubInterfaceCustomizer; import io.fd.honeycomb.translate.v3po.interfaces.SubInterfaceL2Customizer; -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.acl.ingress.IetfAClWriter; +import io.fd.honeycomb.translate.v3po.interfaces.acl.ingress.SubInterfaceIetfAclCustomizer; import io.fd.honeycomb.translate.v3po.interfaces.ip.SubInterfaceIpv4AddressCustomizer; import io.fd.honeycomb.translate.vpp.util.NamingContext; import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; @@ -47,6 +47,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.L2; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Match; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Tags; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.acl.Ingress; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.l2.Rewrite; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.tags.Tag; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.ip4.attributes.Ipv4; @@ -70,7 +71,10 @@ public final class SubinterfaceAugmentationWriterFactory implements WriterFactor public static final InstanceIdentifier L2_ID = SUB_IFC_ID.child( L2.class); public static final InstanceIdentifier SUBIF_ACL_ID = SUB_IFC_ID.child(Acl.class); + public static final InstanceIdentifier SUBIF_INGRESS_ACL_ID = SUBIF_ACL_ID.child(Ingress.class); public static final InstanceIdentifier SUBIF_IETF_ACL_ID = SUB_IFC_ID.child(IetfAcl.class); + public static final InstanceIdentifier SUBIF_INGRESS_IETF_ACL_ID = SUBIF_IETF_ACL_ID.child( + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.ietf.acl.Ingress.class); public SubinterfaceAugmentationWriterFactory(final FutureJVppCore jvpp, final IetfAClWriter aclWriter, @@ -115,22 +119,23 @@ public final class SubinterfaceAugmentationWriterFactory implements WriterFactor new SubInterfaceIpv4AddressCustomizer(jvpp, ifcContext)), rewriteId); - // ACL (execute after classify table and session writers) + // Ingress (execute after classify table and session writers) // also handles L2Acl, Ip4Acl and Ip6Acl: - final InstanceIdentifier aclId = InstanceIdentifier.create(Acl.class); + final InstanceIdentifier aclId = InstanceIdentifier.create(Ingress.class); registry .subtreeAddAfter( Sets.newHashSet(aclId.child(L2Acl.class), aclId.child(Ip4Acl.class), aclId.child(Ip6Acl.class)), - new GenericWriter<>(SUBIF_ACL_ID, new SubInterfaceAclCustomizer(jvpp, ifcContext, classifyTableContext)), + new GenericWriter<>(SUBIF_INGRESS_ACL_ID, new SubInterfaceAclCustomizer(jvpp, ifcContext, classifyTableContext)), Sets.newHashSet(CLASSIFY_TABLE_ID, CLASSIFY_SESSION_ID)); - // IETF-ACL, also handles IetfAcl, AccessLists and Acl: - final InstanceIdentifier accessListsID = InstanceIdentifier.create(IetfAcl.class) + // Ingress IETF-ACL, also handles AccessLists and Acl: + final InstanceIdentifier accessListsID = InstanceIdentifier.create( + org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.ietf.acl.Ingress.class) .child(AccessLists.class); final InstanceIdentifier aclListId = accessListsID.child( org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.ietf.acl.base.attributes.access.lists.Acl.class); registry.subtreeAdd( Sets.newHashSet(accessListsID, aclListId), - new GenericWriter<>(SUBIF_IETF_ACL_ID, new SubInterfaceIetfAclCustomizer(aclWriter, ifcContext))); + new GenericWriter<>(SUBIF_INGRESS_IETF_ACL_ID, new SubInterfaceIetfAclCustomizer(aclWriter, 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 119bc18bf..841885365 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 @@ -22,12 +22,13 @@ import io.fd.honeycomb.translate.impl.read.GenericReader; import io.fd.honeycomb.translate.read.ReaderFactory; import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder; import io.fd.honeycomb.translate.v3po.interfacesstate.RewriteCustomizer; -import io.fd.honeycomb.translate.v3po.interfacesstate.SubInterfaceAclCustomizer; import io.fd.honeycomb.translate.v3po.interfacesstate.SubInterfaceCustomizer; +import io.fd.honeycomb.translate.v3po.interfacesstate.acl.ingress.SubInterfaceAclCustomizer; import io.fd.honeycomb.translate.v3po.interfacesstate.SubInterfaceL2Customizer; import io.fd.honeycomb.translate.v3po.interfacesstate.ip.SubInterfaceIpv4AddressCustomizer; -import io.fd.honeycomb.translate.vpp.util.NamingContext; import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; +import io.fd.honeycomb.translate.vpp.util.NamingContext; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; 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; @@ -39,9 +40,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterface; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.match.attributes.match.type.vlan.tagged.VlanTagged; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Acl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.AclBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.L2; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Match; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Tags; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.acl.Ingress; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.l2.Rewrite; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.tags.Tag; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.ip4.attributes.Ipv4; @@ -49,7 +52,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.ip4.attributes.ipv4.Address; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.tag.rewrite.PushTags; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; final class SubinterfaceStateAugmentationReaderFactory implements ReaderFactory { @@ -59,7 +61,8 @@ final class SubinterfaceStateAugmentationReaderFactory implements ReaderFactory private final VppClassifierContextManager classifyCtx; SubinterfaceStateAugmentationReaderFactory(final FutureJVppCore jvpp, final NamingContext ifcCtx, - final NamingContext bdCtx, final VppClassifierContextManager classifyCtx) { + final NamingContext bdCtx, + final VppClassifierContextManager classifyCtx) { this.jvpp = jvpp; this.ifcCtx = ifcCtx; this.bdCtx = bdCtx; @@ -70,7 +73,7 @@ final class SubinterfaceStateAugmentationReaderFactory implements ReaderFactory public void init(final ModifiableReaderRegistryBuilder registry) { // SubinterfaceStateAugmentation(Structural) final InstanceIdentifier subIfcAugId = - InterfacesStateReaderFactory.IFC_ID.augmentation(SubinterfaceStateAugmentation.class); + InterfacesStateReaderFactory.IFC_ID.augmentation(SubinterfaceStateAugmentation.class); registry.addStructuralReader(subIfcAugId, SubinterfaceStateAugmentationBuilder.class); // SubInterfaces(Structural) final InstanceIdentifier subIfcsId = subIfcAugId.child(SubInterfaces.class); @@ -78,30 +81,37 @@ final class SubinterfaceStateAugmentationReaderFactory implements ReaderFactory // SubInterface(Subtree) final InstanceIdentifier subIfcId = subIfcsId.child(SubInterface.class); registry.subtreeAdd(Sets.newHashSet( - InstanceIdentifier.create(SubInterface.class).child(Tags.class), - InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class), - InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class).child(Dot1qTag.class), - InstanceIdentifier.create(SubInterface.class).child(Match.class), - InstanceIdentifier.create(SubInterface.class).child(Match.class).child(VlanTagged.class)), - new GenericListReader<>(subIfcId, new SubInterfaceCustomizer(jvpp, ifcCtx))); + InstanceIdentifier.create(SubInterface.class).child(Tags.class), + InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class), + InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class).child(Dot1qTag.class), + InstanceIdentifier.create(SubInterface.class).child(Match.class), + InstanceIdentifier.create(SubInterface.class).child(Match.class).child(VlanTagged.class)), + new GenericListReader<>(subIfcId, new SubInterfaceCustomizer(jvpp, ifcCtx))); // L2 final InstanceIdentifier l2Id = subIfcId.child(L2.class); registry.add(new GenericReader<>(l2Id, new SubInterfaceL2Customizer(jvpp, ifcCtx, bdCtx))); // Rewrite(Subtree) registry.subtreeAdd(Sets.newHashSet( - InstanceIdentifier.create(Rewrite.class).child(PushTags.class), - InstanceIdentifier.create(Rewrite.class).child(PushTags.class) - .child(org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.Dot1qTag.class)), - new GenericReader<>(l2Id.child(Rewrite.class), new RewriteCustomizer(jvpp, ifcCtx))); + InstanceIdentifier.create(Rewrite.class).child(PushTags.class), + InstanceIdentifier.create(Rewrite.class).child(PushTags.class) + .child( + org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.Dot1qTag.class)), + new GenericReader<>(l2Id.child(Rewrite.class), new RewriteCustomizer(jvpp, ifcCtx))); // Ipv4(Structural) final InstanceIdentifier ipv4Id = subIfcId.child(Ipv4.class); registry.addStructuralReader(ipv4Id, Ipv4Builder.class); // Address - registry.add(new GenericListReader<>(ipv4Id.child(Address.class), new SubInterfaceIpv4AddressCustomizer(jvpp, ifcCtx))); - // Acl(Subtree) - final InstanceIdentifier aclIdRelative = InstanceIdentifier.create(Acl.class); + registry.add( + new GenericListReader<>(ipv4Id.child(Address.class), new SubInterfaceIpv4AddressCustomizer(jvpp, ifcCtx))); + // Acl(Structural) + final InstanceIdentifier aclIid = subIfcId.child(Acl.class); + registry.addStructuralReader(aclIid, AclBuilder.class); + // Ingress(Subtree) + final InstanceIdentifier ingressIdRelative = InstanceIdentifier.create(Ingress.class); registry.subtreeAdd( - Sets.newHashSet(aclIdRelative.child(L2Acl.class), aclIdRelative.child(Ip4Acl.class), aclIdRelative.child(Ip6Acl.class)), - new GenericReader<>(subIfcId.child(Acl.class), new SubInterfaceAclCustomizer(jvpp, ifcCtx, classifyCtx))); + Sets.newHashSet(ingressIdRelative.child(L2Acl.class), ingressIdRelative.child(Ip4Acl.class), + ingressIdRelative.child(Ip6Acl.class)), + new GenericReader<>(aclIid.child(Ingress.class), + new SubInterfaceAclCustomizer(jvpp, ifcCtx, classifyCtx))); } } 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 3846107c0..de29d5d2c 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 @@ -26,7 +26,7 @@ import io.fd.honeycomb.translate.v3po.cfgattrs.V3poConfiguration; import io.fd.honeycomb.translate.v3po.initializers.InterfacesInitializer; import io.fd.honeycomb.translate.v3po.initializers.VppClassifierInitializer; import io.fd.honeycomb.translate.v3po.initializers.VppInitializer; -import io.fd.honeycomb.translate.v3po.interfaces.acl.IetfAClWriter; +import io.fd.honeycomb.translate.v3po.interfaces.acl.ingress.IetfAClWriter; import io.fd.honeycomb.translate.v3po.notification.InterfaceChangeNotificationProducer; import io.fd.honeycomb.translate.vpp.util.NamingContext; import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/initializers/InterfacesInitializer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/initializers/InterfacesInitializer.java index 7ecf0c0f5..7c8af2225 100644 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/initializers/InterfacesInitializer.java +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/initializers/InterfacesInitializer.java @@ -55,6 +55,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VhostUserBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VxlanBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VxlanGpeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.acl.EgressBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.acl.IngressBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Acl; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Ethernet; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Gre; @@ -63,6 +65,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VhostUser; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Vxlan; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.VxlanGpe; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.acl.Egress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.acl.Ingress; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.Interconnection; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBased; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.l2.base.attributes.interconnection.BridgeBasedBuilder; @@ -220,9 +224,24 @@ public class InterfacesInitializer extends AbstractDataTreeConverter, AclWriter { - - private static final Logger LOG = LoggerFactory.getLogger(AclCustomizer.class); - private final NamingContext interfaceContext; - private final VppClassifierContextManager classifyTableContext; - - public AclCustomizer(@Nonnull final FutureJVppCore vppApi, @Nonnull final NamingContext interfaceContext, - @Nonnull final VppClassifierContextManager classifyTableContext) { - super(vppApi); - this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); - this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); - } - - @Override - public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Acl dataAfter, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - try { - setAcl(true, id, dataAfter, writeContext); - } catch (VppBaseCallException e) { - throw new WriteFailedException.CreateFailedException(id, dataAfter, e); - } - } - - @Override - public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Acl dataBefore, - @Nonnull final Acl dataAfter, @Nonnull final WriteContext writeContext) - throws WriteFailedException { - throw new UnsupportedOperationException("Acl update is not supported. Please delete Acl container first."); - } - - @Override - public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Acl dataBefore, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - try { - setAcl(false, id, dataBefore, writeContext); - } catch (VppBaseCallException e) { - throw new WriteFailedException.DeleteFailedException(id, e); - } - } - - private void setAcl(final boolean isAdd, @Nonnull final InstanceIdentifier id, @Nonnull final Acl acl, - @Nonnull final WriteContext writeContext) - throws VppBaseCallException, WriteTimeoutException { - final String ifName = id.firstKeyOf(Interface.class).getName(); - final int ifIndex = interfaceContext.getIndex(ifName, writeContext.getMappingContext()); - - LOG.debug("Setting ACL(isAdd={}) on interface={}(id={}): {}", isAdd, ifName, ifIndex, acl); - - inputAclSetInterface(getFutureJVpp(), isAdd, id, acl, ifIndex, classifyTableContext, - writeContext.getMappingContext()); - LOG.debug("Successfully set ACL(isAdd={}) on interface={}(id={}): {}", isAdd, ifName, ifIndex, acl); - } -} 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 deleted file mode 100644 index 6d3cd51fe..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/AclWriter.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.translate.v3po.interfaces; - -import static com.google.common.base.Preconditions.checkNotNull; - -import io.fd.honeycomb.translate.MappingContext; -import io.fd.honeycomb.translate.vpp.util.ByteDataTranslator; -import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer; -import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException; -import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; -import java.util.concurrent.CompletionStage; -import javax.annotation.Nonnegative; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.AclBaseAttributes; -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; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.L2Acl; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.VppBaseCallException; -import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; -import io.fd.vpp.jvpp.core.dto.InputAclSetInterfaceReply; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; - -interface AclWriter extends ByteDataTranslator, JvppReplyConsumer { - - default void inputAclSetInterface(@Nonnull final FutureJVppCore futureJVppCore, final boolean isAdd, - @Nonnull final InstanceIdentifier id, @Nonnull final AclBaseAttributes acl, - @Nonnegative final int ifIndex, - @Nonnull final VppClassifierContextManager classifyTableContext, - @Nonnull final MappingContext mappingContext) - throws VppBaseCallException, WriteTimeoutException { - final InputAclSetInterface request = new InputAclSetInterface(); - request.isAdd = booleanToByte(isAdd); - request.swIfIndex = ifIndex; - request.l2TableIndex = ~0; // skip - request.ip4TableIndex = ~0; // skip - request.ip6TableIndex = ~0; // skip - - final L2Acl l2Acl = acl.getL2Acl(); - if (l2Acl != null) { - final String tableName = checkNotNull(l2Acl.getClassifyTable(), "L2 classify table is null"); - 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.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.getTableIndex(tableName, mappingContext); - } - - final CompletionStage inputAclSetInterfaceReplyCompletionStage = - futureJVppCore.inputAclSetInterface(request); - - getReplyForWrite(inputAclSetInterfaceReplyCompletionStage.toCompletableFuture(), id); - } -} 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 deleted file mode 100644 index 5483c441d..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/SubInterfaceAclCustomizer.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.translate.v3po.interfaces; - -import static com.google.common.base.Preconditions.checkNotNull; - -import io.fd.honeycomb.translate.spi.write.WriterCustomizer; -import io.fd.honeycomb.translate.vpp.util.FutureJVppCustomizer; -import io.fd.honeycomb.translate.vpp.util.NamingContext; -import io.fd.honeycomb.translate.vpp.util.SubInterfaceUtils; -import io.fd.honeycomb.translate.vpp.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; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterface; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterfaceKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Acl; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.VppBaseCallException; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Customizer for enabling/disabling ACLs on given sub-interface. - */ -public class SubInterfaceAclCustomizer extends FutureJVppCustomizer - implements WriterCustomizer, AclWriter { - - private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceAclCustomizer.class); - private final NamingContext interfaceContext; - private final VppClassifierContextManager classifyTableContext; - - public SubInterfaceAclCustomizer(@Nonnull final FutureJVppCore vppApi, - @Nonnull final NamingContext interfaceContext, - @Nonnull final VppClassifierContextManager classifyTableContext) { - super(vppApi); - this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); - this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); - } - - @Override - public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Acl dataAfter, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - try { - setAcl(true, id, dataAfter, writeContext); - } catch (VppBaseCallException e) { - throw new WriteFailedException.CreateFailedException(id, dataAfter, e); - } - } - - @Override - public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Acl dataBefore, - @Nonnull final Acl dataAfter, @Nonnull final WriteContext writeContext) - throws WriteFailedException { - throw new UnsupportedOperationException("Acl update is not supported. Please delete Acl container first."); - } - - @Override - public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Acl dataBefore, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - try { - setAcl(false, id, dataBefore, writeContext); - } catch (VppBaseCallException e) { - throw new WriteFailedException.DeleteFailedException(id, e); - } - } - - private void setAcl(final boolean isAdd, @Nonnull final InstanceIdentifier id, @Nonnull final Acl acl, - @Nonnull final WriteContext writeContext) - throws VppBaseCallException, WriteTimeoutException { - final InterfaceKey parentInterfacekey = id.firstKeyOf(Interface.class); - final SubInterfaceKey subInterfacekey = id.firstKeyOf(SubInterface.class); - final String subInterfaceName = SubInterfaceUtils - .getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue()); - final int subInterfaceIndex = interfaceContext.getIndex(subInterfaceName, writeContext.getMappingContext()); - - LOG.debug("Setting ACL(isAdd={}) on sub-interface={}(id={}): {}", - isAdd, subInterfaceName, subInterfaceIndex, acl); - inputAclSetInterface(getFutureJVpp(), isAdd, id, acl, subInterfaceIndex, classifyTableContext, - writeContext.getMappingContext()); - LOG.debug("Successfully set ACL(isAdd={}) on sub-interface={}(id={}): {}", - isAdd, subInterfaceName, subInterfaceIndex, acl); - } -} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AbstractAceWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AbstractAceWriter.java deleted file mode 100644 index e04371ec5..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AbstractAceWriter.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.translate.v3po.interfaces.acl; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import com.google.common.annotations.VisibleForTesting; -import io.fd.honeycomb.translate.util.RWUtils; -import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer; -import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException; -import java.util.List; -import java.util.concurrent.CompletionStage; -import java.util.stream.Collector; -import javax.annotation.Nonnegative; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.Ace; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.Permit; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.AceType; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.VppBaseCallException; -import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession; -import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSessionReply; -import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable; -import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply; -import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; - -/** - * Base writer for translation of ietf-acl model ACEs to VPP's classify tables and sessions. - *

- * Creates one classify table with single session per ACE. - * - * @param type of access control list entry - */ -abstract class AbstractAceWriter implements AceWriter, JvppReplyConsumer { - - // TODO: HONEYCOMB-181 minimise memory used by classify tables (we create a lot of them to make ietf-acl model - // mapping more convenient): - // according to https://wiki.fd.io/view/VPP/Introduction_To_N-tuple_Classifiers#Creating_a_classifier_table, - // classify table needs 16*(1 + match_n_vectors) bytes, but this does not quite work, so setting 8K for now - protected static final int TABLE_MEM_SIZE = 8 * 1024; - - @VisibleForTesting - static final int VLAN_TAG_LEN = 4; - - private static final Collector SINGLE_ITEM_COLLECTOR = - RWUtils.singleItemCollector(); - - private final FutureJVppCore futureJVppCore; - - public AbstractAceWriter(@Nonnull final FutureJVppCore futureJVppCore) { - this.futureJVppCore = checkNotNull(futureJVppCore, "futureJVppCore should not be null"); - } - - /** - * Creates classify table for given ACE. - * - * @param action packet handling action (permit/deny) - * @param ace ACE to be translated - * @param nextTableIndex classify table index - * @param vlanTags number of vlan tags - * @return classify table that represents given ACE - */ - protected abstract ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action, - @Nonnull final T ace, - final int nextTableIndex, - final int vlanTags); - - /** - * Creates classify session for given ACE. - * - * @param action packet handling action (permit/deny) - * @param ace ACE to be translated - * @param tableIndex classify table index for the given session - * @param vlanTags number of vlan tags - * @return classify session that represents given ACE - */ - protected abstract ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action, - @Nonnull final T ace, - final int tableIndex, - final int vlanTags); - - /** - * Sets classify table index for input_acl_set_interface request. - * - * @param request request DTO - * @param tableIndex pointer to a chain of classify tables - */ - protected abstract void setClassifyTable(@Nonnull final InputAclSetInterface request, final int tableIndex); - - @Override - public final void write(@Nonnull final InstanceIdentifier id, @Nonnull final List aces, - @Nonnull final InputAclSetInterface request, @Nonnegative final int vlanTags) - throws VppBaseCallException, WriteTimeoutException { - final PacketHandling action = aces.stream().map(ace -> ace.getActions().getPacketHandling()).distinct() - .collect(SINGLE_ITEM_COLLECTOR); - - checkArgument(vlanTags >= 0 && vlanTags <= 2, "Number of vlan tags %s is not in [0,2] range"); - - int nextTableIndex = -1; - for (final Ace ace : aces) { - // Create table + session per entry - - final ClassifyAddDelTable ctRequest = - createClassifyTable(action, (T) ace.getMatches().getAceType(), nextTableIndex, vlanTags); - nextTableIndex = createClassifyTable(id, ctRequest); - createClassifySession(id, - createClassifySession(action, (T) ace.getMatches().getAceType(), nextTableIndex, vlanTags)); - } - setClassifyTable(request, nextTableIndex); - } - - private int createClassifyTable(@Nonnull final InstanceIdentifier id, - @Nonnull final ClassifyAddDelTable request) - throws VppBaseCallException, WriteTimeoutException { - final CompletionStage cs = futureJVppCore.classifyAddDelTable(request); - - final ClassifyAddDelTableReply reply = getReplyForWrite(cs.toCompletableFuture(), id); - return reply.newTableIndex; - } - - private void createClassifySession(@Nonnull final InstanceIdentifier id, - @Nonnull final ClassifyAddDelSession request) - throws VppBaseCallException, WriteTimeoutException { - final CompletionStage cs = futureJVppCore.classifyAddDelSession(request); - - getReplyForWrite(cs.toCompletableFuture(), id); - } - - protected ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action, final int nextTableIndex) { - final ClassifyAddDelTable request = new ClassifyAddDelTable(); - request.isAdd = 1; - request.tableIndex = -1; // value not present - - request.nbuckets = 1; // we expect exactly one session per table - - if (action instanceof Permit) { - request.missNextIndex = 0; // for list of permit rules, deny (0) should be default action - } else { // deny is default value - request.missNextIndex = -1; // for list of deny rules, permit (-1) should be default action - } - - request.nextTableIndex = nextTableIndex; - request.memorySize = TABLE_MEM_SIZE; - - return request; - } - - protected ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action, final int tableIndex) { - final ClassifyAddDelSession request = new ClassifyAddDelSession(); - request.isAdd = 1; - request.tableIndex = tableIndex; - request.opaqueIndex = ~0; // value not used - - if (action instanceof Permit) { - request.hitNextIndex = -1; - } // deny (0) is default value - - return request; - } - - protected int getVlanTagsLen(final int vlanTags) { - return vlanTags * VLAN_TAG_LEN; - } -} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceEthWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceEthWriter.java deleted file mode 100644 index 8374412a0..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceEthWriter.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.translate.v3po.interfaces.acl; - -import com.google.common.annotations.VisibleForTesting; -import io.fd.honeycomb.translate.vpp.util.MacTranslator; -import java.util.List; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceEth; -import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession; -import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable; -import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class AceEthWriter extends AbstractAceWriter implements MacTranslator { - - @VisibleForTesting - static final int MATCH_N_VECTORS = 1; - private static final Logger LOG = LoggerFactory.getLogger(AceEthWriter.class); - - public AceEthWriter(@Nonnull final FutureJVppCore futureJVppCore) { - super(futureJVppCore); - } - - @Override - public ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action, - @Nonnull final AceEth aceEth, - @Nonnull final int nextTableIndex, - final int vlanTags) { - final ClassifyAddDelTable request = createClassifyTable(action, nextTableIndex); - - request.mask = new byte[16]; - boolean aceIsEmpty = true; - - // destination-mac-address or destination-mac-address-mask is present => - // ff:ff:ff:ff:ff:ff:00:00:00:00:00:00:00:00:00:00 - if (aceEth.getDestinationMacAddressMask() != null) { - aceIsEmpty = false; - final String macAddress = aceEth.getDestinationMacAddressMask().getValue(); - final List parts = COLON_SPLITTER.splitToList(macAddress); - int i = 0; - for (String part : parts) { - request.mask[i++] = parseHexByte(part); - } - } else if (aceEth.getDestinationMacAddress() != null) { - aceIsEmpty = false; - for (int i = 0; i < 6; ++i) { - request.mask[i] = (byte) 0xff; - } - } - - // source-mac-address or source-mac-address-mask => - // 00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:00:00:00:00 - if (aceEth.getSourceMacAddressMask() != null) { - aceIsEmpty = false; - final String macAddress = aceEth.getSourceMacAddressMask().getValue(); - final List parts = COLON_SPLITTER.splitToList(macAddress); - int i = 6; - for (String part : parts) { - request.mask[i++] = parseHexByte(part); - } - } else if (aceEth.getSourceMacAddress() != null) { - aceIsEmpty = false; - for (int i = 6; i < 12; ++i) { - request.mask[i] = (byte) 0xff; - } - } - - if (aceIsEmpty) { - throw new IllegalArgumentException( - String.format("Ace %s does not define packet field match values", aceEth.toString())); - } - - request.skipNVectors = 0; - request.matchNVectors = MATCH_N_VECTORS; - - LOG.debug("ACE action={}, rule={} translated to table={}.", action, aceEth, request); - return request; - } - - @Override - public ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action, - @Nonnull final AceEth aceEth, - @Nonnull final int tableIndex, - final int vlanTags) { - final ClassifyAddDelSession request = createClassifySession(action, tableIndex); - - request.match = new byte[16]; - boolean noMatch = true; - - if (aceEth.getDestinationMacAddress() != null) { - noMatch = false; - final String macAddress = aceEth.getDestinationMacAddress().getValue(); - final List parts = COLON_SPLITTER.splitToList(macAddress); - int i = 0; - for (String part : parts) { - request.match[i++] = parseHexByte(part); - } - } - - if (aceEth.getSourceMacAddress() != null) { - noMatch = false; - final String macAddress = aceEth.getSourceMacAddress().getValue(); - final List parts = COLON_SPLITTER.splitToList(macAddress); - int i = 6; - for (String part : parts) { - request.match[i++] = parseHexByte(part); - } - } - - if (noMatch) { - throw new IllegalArgumentException( - String.format("Ace %s does not define neither source nor destination MAC address", - aceEth.toString())); - } - - LOG.debug("ACE action={}, rule={} translated to session={}.", action, aceEth, request); - return request; - } - - @Override - protected void setClassifyTable(@Nonnull final InputAclSetInterface request, final int tableIndex) { - request.l2TableIndex = tableIndex; - } -} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceIp4Writer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceIp4Writer.java deleted file mode 100644 index 9fc1a237f..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceIp4Writer.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.translate.v3po.interfaces.acl; - -import static com.google.common.base.Preconditions.checkArgument; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.primitives.Ints; -import io.fd.honeycomb.translate.vpp.util.Ipv4Translator; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; -import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession; -import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable; -import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class AceIp4Writer extends AbstractAceWriter implements Ipv4Translator { - - @VisibleForTesting - static final int MATCH_N_VECTORS = 3; // number of 16B vectors - private static final Logger LOG = LoggerFactory.getLogger(AceIp4Writer.class); - private static final int TABLE_MASK_LENGTH = 48; - private static final int IP4_MASK_BIT_LENGTH = 32; - - private static final int IP_VERSION_OFFSET = 14; // first 14 bytes represent L2 header (2x6 + etherType(2)) - private static final int IP_VERSION_MASK = 0xf0; - private static final int DSCP_OFFSET = 15; - private static final int DSCP_MASK = 0xfc; - private static final int IP4_LEN = 4; - private static final int SRC_IP_OFFSET = IP_VERSION_OFFSET + 12; - private static final int DST_IP_OFFSET = SRC_IP_OFFSET + IP4_LEN; - - public AceIp4Writer(@Nonnull final FutureJVppCore futureJVppCore) { - super(futureJVppCore); - } - - private static byte[] toByteMask(final int prefixLength) { - final long mask = ((1L << prefixLength) - 1) << (IP4_MASK_BIT_LENGTH - prefixLength); - return Ints.toByteArray((int) mask); - } - - private static byte[] toByteMask(final Ipv4Prefix ipv4Prefix) { - final int prefixLength = Byte.valueOf(ipv4Prefix.getValue().split("/")[1]); - return toByteMask(prefixLength); - } - - // static removed, cant use default from static content - private byte[] toMatchValue(final Ipv4Prefix ipv4Prefix) { - final String[] split = ipv4Prefix.getValue().split("/"); - final byte[] addressBytes = ipv4AddressNoZoneToArray(split[0]); - final byte[] mask = toByteMask(Byte.valueOf(split[1])); - for (int i = 0; i < addressBytes.length; ++i) { - addressBytes[i] &= mask[i]; - } - return addressBytes; - } - - @Override - public ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action, - @Nonnull final AceIp aceIp, - final int nextTableIndex, - final int vlanTags) { - checkArgument(aceIp.getAceIpVersion() instanceof AceIpv4, "Expected AceIpv4 version, but was %", aceIp); - final AceIpv4 ipVersion = (AceIpv4) aceIp.getAceIpVersion(); - - final ClassifyAddDelTable request = createClassifyTable(action, nextTableIndex); - request.skipNVectors = 0; // match entire L2 and L3 header - request.matchNVectors = MATCH_N_VECTORS; - - boolean aceIsEmpty = true; - request.mask = new byte[TABLE_MASK_LENGTH]; - - final int baseOffset = getVlanTagsLen(vlanTags); - - // First 14 bytes represent l2 header (2x6 + etherType(2)) - if (aceIp.getProtocol() != null) { // Internet Protocol number - request.mask[baseOffset + IP_VERSION_OFFSET] = (byte) IP_VERSION_MASK; // first 4 bits - } - - if (aceIp.getDscp() != null) { - aceIsEmpty = false; - request.mask[baseOffset + DSCP_OFFSET] = (byte) DSCP_MASK; // first 6 bits - } - - if (aceIp.getSourcePortRange() != null) { - LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getSourcePortRange()); - } - - if (aceIp.getDestinationPortRange() != null) { - LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getDestinationPortRange()); - } - - if (ipVersion.getSourceIpv4Network() != null) { - aceIsEmpty = false; - System.arraycopy(toByteMask(ipVersion.getSourceIpv4Network()), 0, request.mask, baseOffset + SRC_IP_OFFSET, - IP4_LEN); - } - - if (ipVersion.getDestinationIpv4Network() != null) { - aceIsEmpty = false; - System - .arraycopy(toByteMask(ipVersion.getDestinationIpv4Network()), 0, request.mask, - baseOffset + DST_IP_OFFSET, IP4_LEN); - } - - if (aceIsEmpty) { - throw new IllegalArgumentException( - String.format("Ace %s does not define packet field match values", aceIp.toString())); - } - - LOG.debug("ACE action={}, rule={} translated to table={}.", action, aceIp, request); - return request; - } - - @Override - public ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action, - @Nonnull final AceIp aceIp, - final int tableIndex, - final int vlanTags) { - checkArgument(aceIp.getAceIpVersion() instanceof AceIpv4, "Expected AceIpv4 version, but was %", aceIp); - final AceIpv4 ipVersion = (AceIpv4) aceIp.getAceIpVersion(); - - final ClassifyAddDelSession request = createClassifySession(action, tableIndex); - - request.match = new byte[TABLE_MASK_LENGTH]; - boolean noMatch = true; - - final int baseOffset = getVlanTagsLen(vlanTags); - - if (aceIp.getProtocol() != null) { - request.match[baseOffset + IP_VERSION_OFFSET] = - (byte) (IP_VERSION_MASK & (aceIp.getProtocol().intValue() << 4)); - } - - if (aceIp.getDscp() != null) { - noMatch = false; - request.match[baseOffset + DSCP_OFFSET] = (byte) (DSCP_MASK & (aceIp.getDscp().getValue() << 2)); - } - - if (aceIp.getSourcePortRange() != null) { - LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getSourcePortRange()); - } - - if (aceIp.getDestinationPortRange() != null) { - LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getDestinationPortRange()); - } - - if (ipVersion.getSourceIpv4Network() != null) { - noMatch = false; - System - .arraycopy(toMatchValue(ipVersion.getSourceIpv4Network()), 0, request.match, - baseOffset + SRC_IP_OFFSET, - IP4_LEN); - } - - if (ipVersion.getDestinationIpv4Network() != null) { - noMatch = false; - System.arraycopy(toMatchValue(ipVersion.getDestinationIpv4Network()), 0, request.match, - baseOffset + DST_IP_OFFSET, - IP4_LEN); - } - - if (noMatch) { - throw new IllegalArgumentException( - String.format("Ace %s does not define packet field match values", aceIp.toString())); - } - - LOG.debug("ACE action={}, rule={} translated to session={}.", action, aceIp, request); - return request; - } - - @Override - protected void setClassifyTable(@Nonnull final InputAclSetInterface request, final int tableIndex) { - request.ip4TableIndex = tableIndex; - } -} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceIp6Writer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceIp6Writer.java deleted file mode 100644 index d58ca3d0b..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceIp6Writer.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.translate.v3po.interfaces.acl; - -import static com.google.common.base.Preconditions.checkArgument; - -import com.google.common.annotations.VisibleForTesting; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.BitSet; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv6; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix; -import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession; -import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable; -import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -final class AceIp6Writer extends AbstractAceWriter { - - @VisibleForTesting - static final int MATCH_N_VECTORS = 4; // number of 16B vectors - private static final Logger LOG = LoggerFactory.getLogger(AceIp6Writer.class); - private static final int TABLE_MASK_LENGTH = 64; - private static final int IP6_MASK_BIT_LENGTH = 128; - - private static final int IP_VERSION_OFFSET = 14; // first 14 bytes represent L2 header (2x6 + etherType(2)) - private static final int IP_VERSION_MASK = 0xf0; - private static final int DSCP_MASK1 = 0x0f; - private static final int DSCP_MASK2 = 0xc0; - private static final int IP6_LEN = 16; - private static final int SRC_IP_OFFSET = IP_VERSION_OFFSET + 8; - private static final int DST_IP_OFFSET = SRC_IP_OFFSET + IP6_LEN; - - public AceIp6Writer(@Nonnull final FutureJVppCore futureJVppCore) { - super(futureJVppCore); - } - - private static byte[] toByteMask(final int prefixLength) { - final BitSet mask = new BitSet(IP6_MASK_BIT_LENGTH); - mask.set(0, prefixLength, true); - if (prefixLength < IP6_MASK_BIT_LENGTH) { - mask.set(prefixLength, IP6_MASK_BIT_LENGTH, false); - } - return mask.toByteArray(); - } - - private static byte[] toByteMask(final Ipv6Prefix ipv6Prefix) { - final int prefixLength = Short.valueOf(ipv6Prefix.getValue().split("/")[1]); - return toByteMask(prefixLength); - } - - private static byte[] toMatchValue(final Ipv6Prefix ipv6Prefix) { - final String[] split = ipv6Prefix.getValue().split("/"); - final byte[] addressBytes; - try { - addressBytes = InetAddress.getByName(split[0]).getAddress(); - } catch (UnknownHostException e) { - throw new IllegalArgumentException("Invalid IP6 address", e); - } - final byte[] mask = toByteMask(Short.valueOf(split[1])); - int pos = 0; - for (; pos < mask.length; ++pos) { - addressBytes[pos] &= mask[pos]; - } - // mask can be shorter that address, so we need to clear rest of the address: - for (; pos < addressBytes.length; ++pos) { - addressBytes[pos] = 0; - } - return addressBytes; - } - - @Override - public ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action, - @Nonnull final AceIp aceIp, - final int nextTableIndex, - final int vlanTags) { - checkArgument(aceIp.getAceIpVersion() instanceof AceIpv6, "Expected AceIpv6 version, but was %", aceIp); - final AceIpv6 ipVersion = (AceIpv6) aceIp.getAceIpVersion(); - - final ClassifyAddDelTable request = createClassifyTable(action, nextTableIndex); - request.skipNVectors = 0; // match entire L2 and L3 header - request.matchNVectors = MATCH_N_VECTORS; - - boolean aceIsEmpty = true; - request.mask = new byte[TABLE_MASK_LENGTH]; - - final int baseOffset = getVlanTagsLen(vlanTags); - - if (aceIp.getProtocol() != null) { - aceIsEmpty = false; - request.mask[baseOffset + IP_VERSION_OFFSET] |= IP_VERSION_MASK; - } - - if (aceIp.getDscp() != null) { - aceIsEmpty = false; - // DCSP (bits 4-9 of IP6 header) - request.mask[baseOffset + IP_VERSION_OFFSET] |= DSCP_MASK1; - request.mask[baseOffset + IP_VERSION_OFFSET + 1] |= DSCP_MASK2; - } - - if (aceIp.getSourcePortRange() != null) { - LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getSourcePortRange()); - } - - if (aceIp.getDestinationPortRange() != null) { - LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getDestinationPortRange()); - } - - if (ipVersion.getFlowLabel() != null) { - aceIsEmpty = false; - // bits 12-31 - request.mask[baseOffset + IP_VERSION_OFFSET + 1] |= (byte) 0x0f; - request.mask[baseOffset + IP_VERSION_OFFSET + 2] = (byte) 0xff; - request.mask[baseOffset + IP_VERSION_OFFSET + 3] = (byte) 0xff; - } - - if (ipVersion.getSourceIpv6Network() != null) { - aceIsEmpty = false; - final byte[] mask = toByteMask(ipVersion.getSourceIpv6Network()); - System.arraycopy(mask, 0, request.mask, baseOffset + SRC_IP_OFFSET, mask.length); - } - - if (ipVersion.getDestinationIpv6Network() != null) { - aceIsEmpty = false; - final byte[] mask = toByteMask(ipVersion.getDestinationIpv6Network()); - System.arraycopy(mask, 0, request.mask, baseOffset + DST_IP_OFFSET, mask.length); - } - - if (aceIsEmpty) { - throw new IllegalArgumentException( - String.format("Ace %s does not define packet field match values", aceIp.toString())); - } - - LOG.debug("ACE action={}, rule={} translated to table={}.", action, aceIp, request); - return request; - } - - @Override - public ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action, - @Nonnull final AceIp aceIp, - final int tableIndex, - final int vlanTags) { - checkArgument(aceIp.getAceIpVersion() instanceof AceIpv6, "Expected AceIpv6 version, but was %", aceIp); - final AceIpv6 ipVersion = (AceIpv6) aceIp.getAceIpVersion(); - - final ClassifyAddDelSession request = createClassifySession(action, tableIndex); - request.match = new byte[TABLE_MASK_LENGTH]; - boolean noMatch = true; - - final int baseOffset = getVlanTagsLen(vlanTags); - - if (aceIp.getProtocol() != null) { - noMatch = false; - request.match[baseOffset + IP_VERSION_OFFSET] |= - (byte) (IP_VERSION_MASK & (aceIp.getProtocol().intValue() << 4)); - } - - if (aceIp.getDscp() != null) { - noMatch = false; - final int dscp = aceIp.getDscp().getValue(); - // set bits 4-9 of IP6 header: - request.match[baseOffset + IP_VERSION_OFFSET] |= (byte) (DSCP_MASK1 & (dscp >> 2)); - request.match[baseOffset + IP_VERSION_OFFSET + 1] |= (byte) (DSCP_MASK2 & (dscp << 6)); - } - - if (aceIp.getSourcePortRange() != null) { - LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getSourcePortRange()); - } - - if (aceIp.getDestinationPortRange() != null) { - LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getDestinationPortRange()); - } - - if (ipVersion.getFlowLabel() != null) { - noMatch = false; - final int flowLabel = ipVersion.getFlowLabel().getValue().intValue(); - // bits 12-31 - request.match[baseOffset + IP_VERSION_OFFSET + 1] |= (byte) (0x0f & (flowLabel >> 16)); - request.match[baseOffset + IP_VERSION_OFFSET + 2] = (byte) (0xff & (flowLabel >> 8)); - request.match[baseOffset + IP_VERSION_OFFSET + 3] = (byte) (0xff & flowLabel); - } - - if (ipVersion.getSourceIpv6Network() != null) { - noMatch = false; - final byte[] match = toMatchValue(ipVersion.getSourceIpv6Network()); - System.arraycopy(match, 0, request.match, baseOffset + SRC_IP_OFFSET, IP6_LEN); - } - - if (ipVersion.getDestinationIpv6Network() != null) { - noMatch = false; - final byte[] match = toMatchValue(ipVersion.getDestinationIpv6Network()); - System.arraycopy(match, 0, request.match, baseOffset + DST_IP_OFFSET, IP6_LEN); - } - - if (noMatch) { - throw new IllegalArgumentException( - String.format("Ace %s does not define packet field match values", aceIp.toString())); - } - - LOG.debug("ACE action={}, rule={} translated to session={}.", action, aceIp, request); - return request; - } - - @Override - protected void setClassifyTable(@Nonnull final InputAclSetInterface request, final int tableIndex) { - request.ip6TableIndex = tableIndex; - } -} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceWriter.java deleted file mode 100644 index 64e5eba90..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AceWriter.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.translate.v3po.interfaces.acl; - -import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException; -import java.util.List; -import javax.annotation.Nonnegative; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.Ace; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.VppBaseCallException; -import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; - -/** - * Writer responsible for translation of ietf-acl model ACEs to VPP's classify tables and sessions. - */ -interface AceWriter { - - /** - * Translates list of ACEs to chain of classify tables. Each ACE is translated into one classify table with single - * classify session. Also initializes input_acl_set_interface request message DTO with first classify table of the - * chain that was created. - * - * @param id uniquely identifies ietf-acl container - * @param aces list of access control entries - * @param request input_acl_set_interface request DTO - */ - void write(@Nonnull final InstanceIdentifier id, @Nonnull final List aces, - @Nonnull final InputAclSetInterface request, @Nonnegative final int vlanTags) - throws VppBaseCallException, WriteTimeoutException; -} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AclWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AclWriter.java deleted file mode 100644 index 875e9dbae..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/AclWriter.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.translate.v3po.interfaces.acl; - -import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; -import io.fd.honeycomb.translate.write.WriteContext; -import io.fd.honeycomb.translate.write.WriteFailedException; -import java.util.Optional; -import java.util.stream.Stream; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AccessLists; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AclBase; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclKey; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Writer customizer responsible for Access Control Lists management. Does not send any messages to VPP. All the config - * data are stored in HC and used when acl is assigned/unassigned to/from an interface. - * - * ACLs that are currently assigned to an interface cannot be updated/deleted. - */ -public class AclWriter implements ListWriterCustomizer { - - public static final InstanceIdentifier ACL_ID = - InstanceIdentifier.create(AccessLists.class); - - private static final Logger LOG = LoggerFactory.getLogger(AclWriter.class); - - @Override - public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Acl dataAfter, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - LOG.debug("Creating ACL: iid={} dataAfter={}", id, dataAfter); - - // no vpp call, just updates DataTree - } - - @Override - public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Acl dataBefore, - @Nonnull final Acl dataAfter, @Nonnull final WriteContext writeContext) - throws WriteFailedException { - LOG.debug("Updating ACL: iid={} dataBefore={} dataAfter={}", id, dataBefore, dataAfter); - - if (isAssigned(dataAfter, writeContext)) { - throw new WriteFailedException(id, - String.format("Failed to update data at %s: acl %s is already assigned", id, dataAfter)); - } - - LOG.debug("Updating unassigned ACL: iid={} dataBefore={} dataAfter={}", id, dataBefore, dataAfter); - - // no vpp call, just updates DataTree - } - - @Override - public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Acl dataBefore, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - LOG.debug("Deleting ACL: iid={} dataBefore={}", id, dataBefore); - - if (isAssigned(dataBefore, writeContext)) { - throw new WriteFailedException(id, - String.format("Failed to delete data at %s: acl %s is already assigned", id, dataBefore)); - } - - LOG.debug("Deleting unassigned ACL: iid={} dataBefore={}", id, dataBefore); - - // no vpp call, just updates DataTree - } - - private static boolean isAssigned(@Nonnull final Acl acl, - @Nonnull final WriteContext writeContext) { - final String aclName = acl.getAclName(); - final Class aclType = acl.getAclType(); - final Interfaces interfaces = writeContext.readAfter(InstanceIdentifier.create(Interfaces.class)).get(); - - return interfaces.getInterface().stream() - .map(i -> Optional.ofNullable(i.getAugmentation(VppInterfaceAugmentation.class)) - .map(aug -> aug.getIetfAcl()) - .map(ietfAcl -> ietfAcl.getAccessLists()) - .map(accessLists -> accessLists.getAcl()) - ) - .flatMap(iacl -> iacl.isPresent() - ? iacl.get().stream() - : Stream.empty()) - .filter(assignedAcl -> aclName.equals(assignedAcl.getName()) && aclType.equals(assignedAcl.getType())) - .findFirst().isPresent(); - } -} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/IetfAClWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/IetfAClWriter.java deleted file mode 100644 index 427afa5cf..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/IetfAClWriter.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.translate.v3po.interfaces.acl; - -import static com.google.common.base.Preconditions.checkArgument; - -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; -import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer; -import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException; -import io.fd.honeycomb.translate.write.WriteContext; -import io.fd.honeycomb.translate.write.WriteFailedException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletionStage; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import javax.annotation.Nonnegative; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AclBase; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclKey; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.AccessListEntries; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.Ace; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.AceType; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceEth; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.AceIpVersion; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.ietf.acl.base.attributes.access.lists.Acl; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.VppBaseCallException; -import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable; -import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply; -import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterface; -import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterfaceReply; -import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; -import io.fd.vpp.jvpp.core.dto.InputAclSetInterfaceReply; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public final class IetfAClWriter implements JvppReplyConsumer { - - private static final Logger LOG = LoggerFactory.getLogger(IetfAClWriter.class); - private final FutureJVppCore jvpp; - - private Map aceWriters = new HashMap<>(); - - public IetfAClWriter(@Nonnull final FutureJVppCore futureJVppCore) { - this.jvpp = Preconditions.checkNotNull(futureJVppCore, "futureJVppCore should not be null"); - aceWriters.put(AclType.ETH, new AceEthWriter(futureJVppCore)); - aceWriters.put(AclType.IP4, new AceIp4Writer(futureJVppCore)); - aceWriters.put(AclType.IP6, new AceIp6Writer(futureJVppCore)); - } - - private static Stream aclToAceStream(@Nonnull final Acl assignedAcl, - @Nonnull final WriteContext writeContext) { - final String aclName = assignedAcl.getName(); - final Class aclType = assignedAcl.getType(); - - // ietf-acl updates are handled first, so we use writeContext.readAfter - final Optional - aclOptional = writeContext.readAfter(AclWriter.ACL_ID.child( - org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl.class, - new AclKey(aclName, aclType))); - checkArgument(aclOptional.isPresent(), "Acl lists not configured"); - final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl - acl = aclOptional.get(); - - final AccessListEntries accessListEntries = acl.getAccessListEntries(); - checkArgument(accessListEntries != null, "access list entries not configured"); - - return accessListEntries.getAce().stream(); - } - - void deleteAcl(@Nonnull final InstanceIdentifier id, final int swIfIndex) - throws WriteTimeoutException, WriteFailedException.DeleteFailedException { - final ClassifyTableByInterface request = new ClassifyTableByInterface(); - request.swIfIndex = swIfIndex; - - try { - final CompletionStage cs = jvpp.classifyTableByInterface(request); - final ClassifyTableByInterfaceReply reply = getReplyForWrite(cs.toCompletableFuture(), id); - - // We unassign and remove all ACL-related classify tables for given interface (we assume we are the only - // classify table manager) - - unassignClassifyTables(id, reply); - - removeClassifyTable(id, reply.l2TableId); - removeClassifyTable(id, reply.ip4TableId); - removeClassifyTable(id, reply.ip6TableId); - } catch (VppBaseCallException e) { - throw new WriteFailedException.DeleteFailedException(id, e); - } - } - - private void unassignClassifyTables(@Nonnull final InstanceIdentifier id, - final ClassifyTableByInterfaceReply currentState) - throws VppBaseCallException, WriteTimeoutException { - final InputAclSetInterface request = new InputAclSetInterface(); - request.isAdd = 0; - request.swIfIndex = currentState.swIfIndex; - request.l2TableIndex = currentState.l2TableId; - request.ip4TableIndex = currentState.ip4TableId; - request.ip6TableIndex = currentState.ip6TableId; - final CompletionStage inputAclSetInterfaceReplyCompletionStage = - jvpp.inputAclSetInterface(request); - getReplyForWrite(inputAclSetInterfaceReplyCompletionStage.toCompletableFuture(), id); - } - - private void removeClassifyTable(@Nonnull final InstanceIdentifier id, final int tableIndex) - throws VppBaseCallException, WriteTimeoutException { - - if (tableIndex == -1) { - return; // classify table id is absent - } - final ClassifyAddDelTable request = new ClassifyAddDelTable(); - request.tableIndex = tableIndex; - final CompletionStage cs = jvpp.classifyAddDelTable(request); - getReplyForWrite(cs.toCompletableFuture(), id); - } - - void write(@Nonnull final InstanceIdentifier id, final int swIfIndex, @Nonnull final List acls, - @Nonnull final WriteContext writeContext) - throws VppBaseCallException, WriteTimeoutException { - write(id, swIfIndex, acls, writeContext, 0); - } - - void write(@Nonnull final InstanceIdentifier id, final int swIfIndex, @Nonnull final List acls, - @Nonnull final WriteContext writeContext, @Nonnegative final int numberOfTags) - throws VppBaseCallException, WriteTimeoutException { - - // filter ACE entries and group by AceType - final Map> acesByType = acls.stream() - .flatMap(acl -> aclToAceStream(acl, writeContext)) - .collect(Collectors.groupingBy(AclType::fromAce)); - - final InputAclSetInterface request = new InputAclSetInterface(); - request.isAdd = 1; - request.swIfIndex = swIfIndex; - request.l2TableIndex = -1; - request.ip4TableIndex = -1; - request.ip6TableIndex = -1; - - // for each AceType: - for (Map.Entry> entry : acesByType.entrySet()) { - final AclType aceType = entry.getKey(); - final List aces = entry.getValue(); - LOG.trace("Processing ACEs of {} type: {}", aceType, aces); - - final AceWriter aceWriter = aceWriters.get(aceType); - if (aceWriter == null) { - LOG.warn("AceProcessor for {} not registered. Skipping ACE.", aceType); - } else { - aceWriter.write(id, aces, request, numberOfTags); - } - } - - final CompletionStage inputAclSetInterfaceReplyCompletionStage = - jvpp.inputAclSetInterface(request); - getReplyForWrite(inputAclSetInterfaceReplyCompletionStage.toCompletableFuture(), id); - } - - private enum AclType { - ETH, IP4, IP6; - - @Nonnull - private static AclType fromAce(final Ace ace) { - AclType result = null; - final AceType aceType; - try { - aceType = ace.getMatches().getAceType(); - if (aceType instanceof AceEth) { - result = ETH; - } else if (aceType instanceof AceIp) { - final AceIpVersion aceIpVersion = ((AceIp) aceType).getAceIpVersion(); - if (aceIpVersion instanceof AceIpv4) { - result = IP4; - } else { - result = IP6; - } - } - } catch (NullPointerException e) { - throw new IllegalArgumentException("Incomplete ACE: " + ace, e); - } - if (result == null) { - throw new IllegalArgumentException(String.format("Not supported ace type %s", aceType)); - } - return result; - } - } -} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/IetfAclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/IetfAclCustomizer.java deleted file mode 100644 index e71135790..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/IetfAclCustomizer.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.translate.v3po.interfaces.acl; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import io.fd.honeycomb.translate.spi.write.WriterCustomizer; -import io.fd.honeycomb.translate.vpp.util.NamingContext; -import io.fd.honeycomb.translate.write.WriteContext; -import io.fd.honeycomb.translate.write.WriteFailedException; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.ietf.acl.base.attributes.AccessLists; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.IetfAcl; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.VppBaseCallException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Customizer for enabling/disabling ACLs for given interface (as defined in ietf-acl model). - * - * The customizer assumes it owns classify table management for interfaces where ietf-acl container is present. Using - * low level classifier model or direct changes to classify tables in combination with ietf-acls are not supported and - * can result in unpredictable behaviour. - */ -public class IetfAclCustomizer implements WriterCustomizer { - - private static final Logger LOG = LoggerFactory.getLogger(IetfAclCustomizer.class); - private final IetfAClWriter aclWriter; - private final NamingContext interfaceContext; - - public IetfAclCustomizer(@Nonnull final IetfAClWriter aclWriter, - @Nonnull final NamingContext interfaceContext) { - this.aclWriter = checkNotNull(aclWriter, "aclWriter should not be null"); - this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); - } - - @Override - public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final IetfAcl dataAfter, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - final String ifName = id.firstKeyOf(Interface.class).getName(); - final int ifIndex = interfaceContext.getIndex(ifName, writeContext.getMappingContext()); - LOG.debug("Adding ACLs for interface={}(id={}): {}", ifName, ifIndex, dataAfter); - - final AccessLists accessLists = dataAfter.getAccessLists(); - checkArgument(accessLists != null && accessLists.getAcl() != null, - "ietf-acl container does not define acl list"); - - try { - aclWriter.write(id, ifIndex, accessLists.getAcl(), writeContext); - } catch (VppBaseCallException e) { - throw new WriteFailedException.CreateFailedException(id, dataAfter, e); - } - } - - @Override - public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final IetfAcl dataBefore, @Nonnull final IetfAcl dataAfter, - @Nonnull final WriteContext writeContext) - throws WriteFailedException { - LOG.debug("ACLs update: removing previously configured ACLs"); - deleteCurrentAttributes(id, dataBefore, writeContext); - LOG.debug("ACLs update: adding updated ACLs"); - writeCurrentAttributes(id, dataAfter, writeContext); - LOG.debug("ACLs update was successful"); - } - - @Override - public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final IetfAcl dataBefore, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - final String ifName = id.firstKeyOf(Interface.class).getName(); - final int ifIndex = interfaceContext.getIndex(ifName, writeContext.getMappingContext()); - LOG.debug("Removing ACLs for interface={}(id={}): {}", ifName, ifIndex, dataBefore); - aclWriter.deleteAcl(id, ifIndex); - } -} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/IetfAclWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/IetfAclWriter.java new file mode 100644 index 000000000..929cec6f1 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/IetfAclWriter.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.interfaces.acl; + +import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import java.util.Optional; +import java.util.stream.Stream; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AccessLists; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AclBase; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Writer customizer responsible for Access Control Lists management. Does not send any messages to VPP. All the config + * data are stored in HC and used when acl is assigned/unassigned to/from an interface. + * + * ACLs that are currently assigned to an interface cannot be updated/deleted. + */ +public class IetfAclWriter implements ListWriterCustomizer { + + public static final InstanceIdentifier ACL_ID = + InstanceIdentifier.create(AccessLists.class); + + private static final Logger LOG = LoggerFactory.getLogger(IetfAclWriter.class); + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Acl dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + LOG.debug("Creating ACL: iid={} dataAfter={}", id, dataAfter); + + // no vpp call, just updates DataTree + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Acl dataBefore, + @Nonnull final Acl dataAfter, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + LOG.debug("Updating ACL: iid={} dataBefore={} dataAfter={}", id, dataBefore, dataAfter); + + if (isAssigned(dataAfter, writeContext)) { + throw new WriteFailedException(id, + String.format("Failed to update data at %s: acl %s is already assigned", id, dataAfter)); + } + + LOG.debug("Updating unassigned ACL: iid={} dataBefore={} dataAfter={}", id, dataBefore, dataAfter); + + // no vpp call, just updates DataTree + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Acl dataBefore, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + LOG.debug("Deleting ACL: iid={} dataBefore={}", id, dataBefore); + + if (isAssigned(dataBefore, writeContext)) { + throw new WriteFailedException(id, + String.format("Failed to delete data at %s: acl %s is already assigned", id, dataBefore)); + } + + LOG.debug("Deleting unassigned ACL: iid={} dataBefore={}", id, dataBefore); + + // no vpp call, just updates DataTree + } + + private static boolean isAssigned(@Nonnull final Acl acl, + @Nonnull final WriteContext writeContext) { + final String aclName = acl.getAclName(); + final Class aclType = acl.getAclType(); + final Interfaces interfaces = writeContext.readAfter(InstanceIdentifier.create(Interfaces.class)).get(); + + return interfaces.getInterface().stream() + .map(i -> Optional.ofNullable(i.getAugmentation(VppInterfaceAugmentation.class)) + .map(aug -> aug.getIetfAcl()) + .map(ietfAcl -> ietfAcl.getIngress()) + .map(ingress -> ingress.getAccessLists()) + .map(accessLists -> accessLists.getAcl()) + ) + .flatMap(iacl -> iacl.isPresent() + ? iacl.get().stream() + : Stream.empty()) + .filter(assignedAcl -> aclName.equals(assignedAcl.getName()) && aclType.equals(assignedAcl.getType())) + .findFirst().isPresent(); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/SubInterfaceIetfAclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/SubInterfaceIetfAclCustomizer.java deleted file mode 100644 index 9586208da..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/SubInterfaceIetfAclCustomizer.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.translate.v3po.interfaces.acl; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; -import static io.fd.honeycomb.translate.vpp.util.SubInterfaceUtils.getNumberOfTags; - -import com.google.common.base.Optional; -import io.fd.honeycomb.translate.spi.write.WriterCustomizer; -import io.fd.honeycomb.translate.vpp.util.NamingContext; -import io.fd.honeycomb.translate.vpp.util.SubInterfaceUtils; -import io.fd.honeycomb.translate.write.WriteContext; -import io.fd.honeycomb.translate.write.WriteFailedException; -import javax.annotation.Nonnull; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.ietf.acl.base.attributes.AccessLists; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterface; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterfaceKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.IetfAcl; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.VppBaseCallException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Customizer for enabling/disabling ACLs for given sub-interface (as defined in ietf-acl model). - * - * The customizer assumes it owns classify table management for sub-interfaces where ietf-acl container is present. - * Using low level classifier model or direct changes to classify tables in combination with ietf-acls are not supported - * and can result in unpredictable behaviour. - */ -public class SubInterfaceIetfAclCustomizer implements WriterCustomizer { - - private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceIetfAclCustomizer.class); - private final IetfAClWriter aclWriter; - private final NamingContext interfaceContext; - - public SubInterfaceIetfAclCustomizer(@Nonnull final IetfAClWriter aclWriter, - @Nonnull final NamingContext interfaceContext) { - this.aclWriter = checkNotNull(aclWriter, "aclWriter should not be null"); - this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); - } - - private String getSubInterfaceName(@Nonnull final InstanceIdentifier id) { - final InterfaceKey parentInterfacekey = id.firstKeyOf(Interface.class); - final SubInterfaceKey subInterfacekey = id.firstKeyOf(SubInterface.class); - return SubInterfaceUtils - .getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue()); - } - - @Override - public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final IetfAcl dataAfter, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - final String subInterfaceName = getSubInterfaceName(id); - final int subInterfaceIndex = interfaceContext.getIndex(subInterfaceName, writeContext.getMappingContext()); - LOG.debug("Adding IETF-ACL for sub-interface: {}(id={}): {}", subInterfaceName, subInterfaceIndex, dataAfter); - - final AccessLists accessLists = dataAfter.getAccessLists(); - checkArgument(accessLists != null && accessLists.getAcl() != null, - "ietf-acl container does not define acl list"); - - final Optional subInterfaceOptional = - writeContext.readAfter(id.firstIdentifierOf(SubInterface.class)); - checkState(subInterfaceOptional.isPresent(), "Could not read SubInterface data object for %s", id); - final SubInterface subInterface = subInterfaceOptional.get(); - - try { - aclWriter.write(id, subInterfaceIndex, accessLists.getAcl(), writeContext, - getNumberOfTags(subInterface.getTags())); - } catch (VppBaseCallException e) { - throw new WriteFailedException.CreateFailedException(id, dataAfter, e); - } - } - - @Override - public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final IetfAcl dataBefore, @Nonnull final IetfAcl dataAfter, - @Nonnull final WriteContext writeContext) throws WriteFailedException { - LOG.debug("Sub-interface ACLs update: removing previously configured ACLs"); - deleteCurrentAttributes(id, dataBefore, writeContext); - LOG.debug("Sub-interface ACLs update: adding updated ACLs"); - writeCurrentAttributes(id, dataAfter, writeContext); - LOG.debug("Sub-interface ACLs update was successful"); - } - - @Override - public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, - @Nonnull final IetfAcl dataBefore, @Nonnull final WriteContext writeContext) - throws WriteFailedException { - final String subInterfaceName = getSubInterfaceName(id); - final int subInterfaceIndex = interfaceContext.getIndex(subInterfaceName, writeContext.getMappingContext()); - LOG.debug("Removing ACLs for sub-interface={}(id={}): {}", subInterfaceName, subInterfaceIndex, dataBefore); - aclWriter.deleteAcl(id, subInterfaceIndex); - } -} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AbstractAceWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AbstractAceWriter.java new file mode 100644 index 000000000..022726e46 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AbstractAceWriter.java @@ -0,0 +1,181 @@ +/* + * 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.interfaces.acl.ingress; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.VisibleForTesting; +import io.fd.honeycomb.translate.util.RWUtils; +import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer; +import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException; +import java.util.List; +import java.util.concurrent.CompletionStage; +import java.util.stream.Collector; +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.Ace; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.packet.handling.Permit; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.AceType; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import io.fd.vpp.jvpp.VppBaseCallException; +import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession; +import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSessionReply; +import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable; +import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply; +import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; + +/** + * Base writer for translation of ietf-acl model ACEs to VPP's classify tables and sessions. + *

+ * Creates one classify table with single session per ACE. + * + * @param type of access control list entry + */ +abstract class AbstractAceWriter implements AceWriter, JvppReplyConsumer { + + // TODO: HONEYCOMB-181 minimise memory used by classify tables (we create a lot of them to make ietf-acl model + // mapping more convenient): + // according to https://wiki.fd.io/view/VPP/Introduction_To_N-tuple_Classifiers#Creating_a_classifier_table, + // classify table needs 16*(1 + match_n_vectors) bytes, but this does not quite work, so setting 8K for now + protected static final int TABLE_MEM_SIZE = 8 * 1024; + + @VisibleForTesting + static final int VLAN_TAG_LEN = 4; + + private static final Collector SINGLE_ITEM_COLLECTOR = + RWUtils.singleItemCollector(); + + private final FutureJVppCore futureJVppCore; + + public AbstractAceWriter(@Nonnull final FutureJVppCore futureJVppCore) { + this.futureJVppCore = checkNotNull(futureJVppCore, "futureJVppCore should not be null"); + } + + /** + * Creates classify table for given ACE. + * + * @param action packet handling action (permit/deny) + * @param ace ACE to be translated + * @param nextTableIndex classify table index + * @param vlanTags number of vlan tags + * @return classify table that represents given ACE + */ + protected abstract ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action, + @Nonnull final T ace, + final int nextTableIndex, + final int vlanTags); + + /** + * Creates classify session for given ACE. + * + * @param action packet handling action (permit/deny) + * @param ace ACE to be translated + * @param tableIndex classify table index for the given session + * @param vlanTags number of vlan tags + * @return classify session that represents given ACE + */ + protected abstract ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action, + @Nonnull final T ace, + final int tableIndex, + final int vlanTags); + + /** + * Sets classify table index for input_acl_set_interface request. + * + * @param request request DTO + * @param tableIndex pointer to a chain of classify tables + */ + protected abstract void setClassifyTable(@Nonnull final InputAclSetInterface request, final int tableIndex); + + @Override + public final void write(@Nonnull final InstanceIdentifier id, @Nonnull final List aces, + @Nonnull final InputAclSetInterface request, @Nonnegative final int vlanTags) + throws VppBaseCallException, WriteTimeoutException { + final PacketHandling action = aces.stream().map(ace -> ace.getActions().getPacketHandling()).distinct() + .collect(SINGLE_ITEM_COLLECTOR); + + checkArgument(vlanTags >= 0 && vlanTags <= 2, "Number of vlan tags %s is not in [0,2] range"); + + int nextTableIndex = -1; + for (final Ace ace : aces) { + // Create table + session per entry + + final ClassifyAddDelTable ctRequest = + createClassifyTable(action, (T) ace.getMatches().getAceType(), nextTableIndex, vlanTags); + nextTableIndex = createClassifyTable(id, ctRequest); + createClassifySession(id, + createClassifySession(action, (T) ace.getMatches().getAceType(), nextTableIndex, vlanTags)); + } + setClassifyTable(request, nextTableIndex); + } + + private int createClassifyTable(@Nonnull final InstanceIdentifier id, + @Nonnull final ClassifyAddDelTable request) + throws VppBaseCallException, WriteTimeoutException { + final CompletionStage cs = futureJVppCore.classifyAddDelTable(request); + + final ClassifyAddDelTableReply reply = getReplyForWrite(cs.toCompletableFuture(), id); + return reply.newTableIndex; + } + + private void createClassifySession(@Nonnull final InstanceIdentifier id, + @Nonnull final ClassifyAddDelSession request) + throws VppBaseCallException, WriteTimeoutException { + final CompletionStage cs = futureJVppCore.classifyAddDelSession(request); + + getReplyForWrite(cs.toCompletableFuture(), id); + } + + protected ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action, final int nextTableIndex) { + final ClassifyAddDelTable request = new ClassifyAddDelTable(); + request.isAdd = 1; + request.tableIndex = -1; // value not present + + request.nbuckets = 1; // we expect exactly one session per table + + if (action instanceof Permit) { + request.missNextIndex = 0; // for list of permit rules, deny (0) should be default action + } else { // deny is default value + request.missNextIndex = -1; // for list of deny rules, permit (-1) should be default action + } + + request.nextTableIndex = nextTableIndex; + request.memorySize = TABLE_MEM_SIZE; + + return request; + } + + protected ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action, final int tableIndex) { + final ClassifyAddDelSession request = new ClassifyAddDelSession(); + request.isAdd = 1; + request.tableIndex = tableIndex; + request.opaqueIndex = ~0; // value not used + + if (action instanceof Permit) { + request.hitNextIndex = -1; + } // deny (0) is default value + + return request; + } + + protected int getVlanTagsLen(final int vlanTags) { + return vlanTags * VLAN_TAG_LEN; + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceEthWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceEthWriter.java new file mode 100644 index 000000000..167196e21 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceEthWriter.java @@ -0,0 +1,142 @@ +/* + * 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.interfaces.acl.ingress; + +import com.google.common.annotations.VisibleForTesting; +import io.fd.honeycomb.translate.vpp.util.MacTranslator; +import java.util.List; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceEth; +import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession; +import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable; +import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class AceEthWriter extends AbstractAceWriter implements MacTranslator { + + @VisibleForTesting + static final int MATCH_N_VECTORS = 1; + private static final Logger LOG = LoggerFactory.getLogger(AceEthWriter.class); + + public AceEthWriter(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + @Override + public ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action, + @Nonnull final AceEth aceEth, + @Nonnull final int nextTableIndex, + final int vlanTags) { + final ClassifyAddDelTable request = createClassifyTable(action, nextTableIndex); + + request.mask = new byte[16]; + boolean aceIsEmpty = true; + + // destination-mac-address or destination-mac-address-mask is present => + // ff:ff:ff:ff:ff:ff:00:00:00:00:00:00:00:00:00:00 + if (aceEth.getDestinationMacAddressMask() != null) { + aceIsEmpty = false; + final String macAddress = aceEth.getDestinationMacAddressMask().getValue(); + final List parts = COLON_SPLITTER.splitToList(macAddress); + int i = 0; + for (String part : parts) { + request.mask[i++] = parseHexByte(part); + } + } else if (aceEth.getDestinationMacAddress() != null) { + aceIsEmpty = false; + for (int i = 0; i < 6; ++i) { + request.mask[i] = (byte) 0xff; + } + } + + // source-mac-address or source-mac-address-mask => + // 00:00:00:00:00:00:ff:ff:ff:ff:ff:ff:00:00:00:00 + if (aceEth.getSourceMacAddressMask() != null) { + aceIsEmpty = false; + final String macAddress = aceEth.getSourceMacAddressMask().getValue(); + final List parts = COLON_SPLITTER.splitToList(macAddress); + int i = 6; + for (String part : parts) { + request.mask[i++] = parseHexByte(part); + } + } else if (aceEth.getSourceMacAddress() != null) { + aceIsEmpty = false; + for (int i = 6; i < 12; ++i) { + request.mask[i] = (byte) 0xff; + } + } + + if (aceIsEmpty) { + throw new IllegalArgumentException( + String.format("Ace %s does not define packet field match values", aceEth.toString())); + } + + request.skipNVectors = 0; + request.matchNVectors = MATCH_N_VECTORS; + + LOG.debug("ACE action={}, rule={} translated to table={}.", action, aceEth, request); + return request; + } + + @Override + public ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action, + @Nonnull final AceEth aceEth, + @Nonnull final int tableIndex, + final int vlanTags) { + final ClassifyAddDelSession request = createClassifySession(action, tableIndex); + + request.match = new byte[16]; + boolean noMatch = true; + + if (aceEth.getDestinationMacAddress() != null) { + noMatch = false; + final String macAddress = aceEth.getDestinationMacAddress().getValue(); + final List parts = COLON_SPLITTER.splitToList(macAddress); + int i = 0; + for (String part : parts) { + request.match[i++] = parseHexByte(part); + } + } + + if (aceEth.getSourceMacAddress() != null) { + noMatch = false; + final String macAddress = aceEth.getSourceMacAddress().getValue(); + final List parts = COLON_SPLITTER.splitToList(macAddress); + int i = 6; + for (String part : parts) { + request.match[i++] = parseHexByte(part); + } + } + + if (noMatch) { + throw new IllegalArgumentException( + String.format("Ace %s does not define neither source nor destination MAC address", + aceEth.toString())); + } + + LOG.debug("ACE action={}, rule={} translated to session={}.", action, aceEth, request); + return request; + } + + @Override + protected void setClassifyTable(@Nonnull final InputAclSetInterface request, final int tableIndex) { + request.l2TableIndex = tableIndex; + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp4Writer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp4Writer.java new file mode 100644 index 000000000..63d430bee --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp4Writer.java @@ -0,0 +1,195 @@ +/* + * 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.interfaces.acl.ingress; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.primitives.Ints; +import io.fd.honeycomb.translate.vpp.util.Ipv4Translator; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix; +import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession; +import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable; +import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class AceIp4Writer extends AbstractAceWriter implements Ipv4Translator { + + @VisibleForTesting + static final int MATCH_N_VECTORS = 3; // number of 16B vectors + private static final Logger LOG = LoggerFactory.getLogger(AceIp4Writer.class); + private static final int TABLE_MASK_LENGTH = 48; + private static final int IP4_MASK_BIT_LENGTH = 32; + + private static final int IP_VERSION_OFFSET = 14; // first 14 bytes represent L2 header (2x6 + etherType(2)) + private static final int IP_VERSION_MASK = 0xf0; + private static final int DSCP_OFFSET = 15; + private static final int DSCP_MASK = 0xfc; + private static final int IP4_LEN = 4; + private static final int SRC_IP_OFFSET = IP_VERSION_OFFSET + 12; + private static final int DST_IP_OFFSET = SRC_IP_OFFSET + IP4_LEN; + + public AceIp4Writer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + private static byte[] toByteMask(final int prefixLength) { + final long mask = ((1L << prefixLength) - 1) << (IP4_MASK_BIT_LENGTH - prefixLength); + return Ints.toByteArray((int) mask); + } + + private static byte[] toByteMask(final Ipv4Prefix ipv4Prefix) { + final int prefixLength = Byte.valueOf(ipv4Prefix.getValue().split("/")[1]); + return toByteMask(prefixLength); + } + + // static removed, cant use default from static content + private byte[] toMatchValue(final Ipv4Prefix ipv4Prefix) { + final String[] split = ipv4Prefix.getValue().split("/"); + final byte[] addressBytes = ipv4AddressNoZoneToArray(split[0]); + final byte[] mask = toByteMask(Byte.valueOf(split[1])); + for (int i = 0; i < addressBytes.length; ++i) { + addressBytes[i] &= mask[i]; + } + return addressBytes; + } + + @Override + public ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action, + @Nonnull final AceIp aceIp, + final int nextTableIndex, + final int vlanTags) { + checkArgument(aceIp.getAceIpVersion() instanceof AceIpv4, "Expected AceIpv4 version, but was %", aceIp); + final AceIpv4 ipVersion = (AceIpv4) aceIp.getAceIpVersion(); + + final ClassifyAddDelTable request = createClassifyTable(action, nextTableIndex); + request.skipNVectors = 0; // match entire L2 and L3 header + request.matchNVectors = MATCH_N_VECTORS; + + boolean aceIsEmpty = true; + request.mask = new byte[TABLE_MASK_LENGTH]; + + final int baseOffset = getVlanTagsLen(vlanTags); + + // First 14 bytes represent l2 header (2x6 + etherType(2)) + if (aceIp.getProtocol() != null) { // Internet Protocol number + request.mask[baseOffset + IP_VERSION_OFFSET] = (byte) IP_VERSION_MASK; // first 4 bits + } + + if (aceIp.getDscp() != null) { + aceIsEmpty = false; + request.mask[baseOffset + DSCP_OFFSET] = (byte) DSCP_MASK; // first 6 bits + } + + if (aceIp.getSourcePortRange() != null) { + LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getSourcePortRange()); + } + + if (aceIp.getDestinationPortRange() != null) { + LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getDestinationPortRange()); + } + + if (ipVersion.getSourceIpv4Network() != null) { + aceIsEmpty = false; + System.arraycopy(toByteMask(ipVersion.getSourceIpv4Network()), 0, request.mask, baseOffset + SRC_IP_OFFSET, + IP4_LEN); + } + + if (ipVersion.getDestinationIpv4Network() != null) { + aceIsEmpty = false; + System + .arraycopy(toByteMask(ipVersion.getDestinationIpv4Network()), 0, request.mask, + baseOffset + DST_IP_OFFSET, IP4_LEN); + } + + if (aceIsEmpty) { + throw new IllegalArgumentException( + String.format("Ace %s does not define packet field match values", aceIp.toString())); + } + + LOG.debug("ACE action={}, rule={} translated to table={}.", action, aceIp, request); + return request; + } + + @Override + public ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action, + @Nonnull final AceIp aceIp, + final int tableIndex, + final int vlanTags) { + checkArgument(aceIp.getAceIpVersion() instanceof AceIpv4, "Expected AceIpv4 version, but was %", aceIp); + final AceIpv4 ipVersion = (AceIpv4) aceIp.getAceIpVersion(); + + final ClassifyAddDelSession request = createClassifySession(action, tableIndex); + + request.match = new byte[TABLE_MASK_LENGTH]; + boolean noMatch = true; + + final int baseOffset = getVlanTagsLen(vlanTags); + + if (aceIp.getProtocol() != null) { + request.match[baseOffset + IP_VERSION_OFFSET] = + (byte) (IP_VERSION_MASK & (aceIp.getProtocol().intValue() << 4)); + } + + if (aceIp.getDscp() != null) { + noMatch = false; + request.match[baseOffset + DSCP_OFFSET] = (byte) (DSCP_MASK & (aceIp.getDscp().getValue() << 2)); + } + + if (aceIp.getSourcePortRange() != null) { + LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getSourcePortRange()); + } + + if (aceIp.getDestinationPortRange() != null) { + LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getDestinationPortRange()); + } + + if (ipVersion.getSourceIpv4Network() != null) { + noMatch = false; + System + .arraycopy(toMatchValue(ipVersion.getSourceIpv4Network()), 0, request.match, + baseOffset + SRC_IP_OFFSET, + IP4_LEN); + } + + if (ipVersion.getDestinationIpv4Network() != null) { + noMatch = false; + System.arraycopy(toMatchValue(ipVersion.getDestinationIpv4Network()), 0, request.match, + baseOffset + DST_IP_OFFSET, + IP4_LEN); + } + + if (noMatch) { + throw new IllegalArgumentException( + String.format("Ace %s does not define packet field match values", aceIp.toString())); + } + + LOG.debug("ACE action={}, rule={} translated to session={}.", action, aceIp, request); + return request; + } + + @Override + protected void setClassifyTable(@Nonnull final InputAclSetInterface request, final int tableIndex) { + request.ip4TableIndex = tableIndex; + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp6Writer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp6Writer.java new file mode 100644 index 000000000..94c12e536 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp6Writer.java @@ -0,0 +1,227 @@ +/* + * 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.interfaces.acl.ingress; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.annotations.VisibleForTesting; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.BitSet; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.actions.PacketHandling; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv6; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix; +import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession; +import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable; +import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class AceIp6Writer extends AbstractAceWriter { + + @VisibleForTesting + static final int MATCH_N_VECTORS = 4; // number of 16B vectors + private static final Logger LOG = LoggerFactory.getLogger(AceIp6Writer.class); + private static final int TABLE_MASK_LENGTH = 64; + private static final int IP6_MASK_BIT_LENGTH = 128; + + private static final int IP_VERSION_OFFSET = 14; // first 14 bytes represent L2 header (2x6 + etherType(2)) + private static final int IP_VERSION_MASK = 0xf0; + private static final int DSCP_MASK1 = 0x0f; + private static final int DSCP_MASK2 = 0xc0; + private static final int IP6_LEN = 16; + private static final int SRC_IP_OFFSET = IP_VERSION_OFFSET + 8; + private static final int DST_IP_OFFSET = SRC_IP_OFFSET + IP6_LEN; + + public AceIp6Writer(@Nonnull final FutureJVppCore futureJVppCore) { + super(futureJVppCore); + } + + private static byte[] toByteMask(final int prefixLength) { + final BitSet mask = new BitSet(IP6_MASK_BIT_LENGTH); + mask.set(0, prefixLength, true); + if (prefixLength < IP6_MASK_BIT_LENGTH) { + mask.set(prefixLength, IP6_MASK_BIT_LENGTH, false); + } + return mask.toByteArray(); + } + + private static byte[] toByteMask(final Ipv6Prefix ipv6Prefix) { + final int prefixLength = Short.valueOf(ipv6Prefix.getValue().split("/")[1]); + return toByteMask(prefixLength); + } + + private static byte[] toMatchValue(final Ipv6Prefix ipv6Prefix) { + final String[] split = ipv6Prefix.getValue().split("/"); + final byte[] addressBytes; + try { + addressBytes = InetAddress.getByName(split[0]).getAddress(); + } catch (UnknownHostException e) { + throw new IllegalArgumentException("Invalid IP6 address", e); + } + final byte[] mask = toByteMask(Short.valueOf(split[1])); + int pos = 0; + for (; pos < mask.length; ++pos) { + addressBytes[pos] &= mask[pos]; + } + // mask can be shorter that address, so we need to clear rest of the address: + for (; pos < addressBytes.length; ++pos) { + addressBytes[pos] = 0; + } + return addressBytes; + } + + @Override + public ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action, + @Nonnull final AceIp aceIp, + final int nextTableIndex, + final int vlanTags) { + checkArgument(aceIp.getAceIpVersion() instanceof AceIpv6, "Expected AceIpv6 version, but was %", aceIp); + final AceIpv6 ipVersion = (AceIpv6) aceIp.getAceIpVersion(); + + final ClassifyAddDelTable request = createClassifyTable(action, nextTableIndex); + request.skipNVectors = 0; // match entire L2 and L3 header + request.matchNVectors = MATCH_N_VECTORS; + + boolean aceIsEmpty = true; + request.mask = new byte[TABLE_MASK_LENGTH]; + + final int baseOffset = getVlanTagsLen(vlanTags); + + if (aceIp.getProtocol() != null) { + aceIsEmpty = false; + request.mask[baseOffset + IP_VERSION_OFFSET] |= IP_VERSION_MASK; + } + + if (aceIp.getDscp() != null) { + aceIsEmpty = false; + // DCSP (bits 4-9 of IP6 header) + request.mask[baseOffset + IP_VERSION_OFFSET] |= DSCP_MASK1; + request.mask[baseOffset + IP_VERSION_OFFSET + 1] |= DSCP_MASK2; + } + + if (aceIp.getSourcePortRange() != null) { + LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getSourcePortRange()); + } + + if (aceIp.getDestinationPortRange() != null) { + LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getDestinationPortRange()); + } + + if (ipVersion.getFlowLabel() != null) { + aceIsEmpty = false; + // bits 12-31 + request.mask[baseOffset + IP_VERSION_OFFSET + 1] |= (byte) 0x0f; + request.mask[baseOffset + IP_VERSION_OFFSET + 2] = (byte) 0xff; + request.mask[baseOffset + IP_VERSION_OFFSET + 3] = (byte) 0xff; + } + + if (ipVersion.getSourceIpv6Network() != null) { + aceIsEmpty = false; + final byte[] mask = toByteMask(ipVersion.getSourceIpv6Network()); + System.arraycopy(mask, 0, request.mask, baseOffset + SRC_IP_OFFSET, mask.length); + } + + if (ipVersion.getDestinationIpv6Network() != null) { + aceIsEmpty = false; + final byte[] mask = toByteMask(ipVersion.getDestinationIpv6Network()); + System.arraycopy(mask, 0, request.mask, baseOffset + DST_IP_OFFSET, mask.length); + } + + if (aceIsEmpty) { + throw new IllegalArgumentException( + String.format("Ace %s does not define packet field match values", aceIp.toString())); + } + + LOG.debug("ACE action={}, rule={} translated to table={}.", action, aceIp, request); + return request; + } + + @Override + public ClassifyAddDelSession createClassifySession(@Nonnull final PacketHandling action, + @Nonnull final AceIp aceIp, + final int tableIndex, + final int vlanTags) { + checkArgument(aceIp.getAceIpVersion() instanceof AceIpv6, "Expected AceIpv6 version, but was %", aceIp); + final AceIpv6 ipVersion = (AceIpv6) aceIp.getAceIpVersion(); + + final ClassifyAddDelSession request = createClassifySession(action, tableIndex); + request.match = new byte[TABLE_MASK_LENGTH]; + boolean noMatch = true; + + final int baseOffset = getVlanTagsLen(vlanTags); + + if (aceIp.getProtocol() != null) { + noMatch = false; + request.match[baseOffset + IP_VERSION_OFFSET] |= + (byte) (IP_VERSION_MASK & (aceIp.getProtocol().intValue() << 4)); + } + + if (aceIp.getDscp() != null) { + noMatch = false; + final int dscp = aceIp.getDscp().getValue(); + // set bits 4-9 of IP6 header: + request.match[baseOffset + IP_VERSION_OFFSET] |= (byte) (DSCP_MASK1 & (dscp >> 2)); + request.match[baseOffset + IP_VERSION_OFFSET + 1] |= (byte) (DSCP_MASK2 & (dscp << 6)); + } + + if (aceIp.getSourcePortRange() != null) { + LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getSourcePortRange()); + } + + if (aceIp.getDestinationPortRange() != null) { + LOG.warn("L4 Header fields are not supported. Ignoring {}", aceIp.getDestinationPortRange()); + } + + if (ipVersion.getFlowLabel() != null) { + noMatch = false; + final int flowLabel = ipVersion.getFlowLabel().getValue().intValue(); + // bits 12-31 + request.match[baseOffset + IP_VERSION_OFFSET + 1] |= (byte) (0x0f & (flowLabel >> 16)); + request.match[baseOffset + IP_VERSION_OFFSET + 2] = (byte) (0xff & (flowLabel >> 8)); + request.match[baseOffset + IP_VERSION_OFFSET + 3] = (byte) (0xff & flowLabel); + } + + if (ipVersion.getSourceIpv6Network() != null) { + noMatch = false; + final byte[] match = toMatchValue(ipVersion.getSourceIpv6Network()); + System.arraycopy(match, 0, request.match, baseOffset + SRC_IP_OFFSET, IP6_LEN); + } + + if (ipVersion.getDestinationIpv6Network() != null) { + noMatch = false; + final byte[] match = toMatchValue(ipVersion.getDestinationIpv6Network()); + System.arraycopy(match, 0, request.match, baseOffset + DST_IP_OFFSET, IP6_LEN); + } + + if (noMatch) { + throw new IllegalArgumentException( + String.format("Ace %s does not define packet field match values", aceIp.toString())); + } + + LOG.debug("ACE action={}, rule={} translated to session={}.", action, aceIp, request); + return request; + } + + @Override + protected void setClassifyTable(@Nonnull final InputAclSetInterface request, final int tableIndex) { + request.ip6TableIndex = tableIndex; + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceWriter.java new file mode 100644 index 000000000..a687d4a86 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceWriter.java @@ -0,0 +1,45 @@ +/* + * 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.interfaces.acl.ingress; + +import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException; +import java.util.List; +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.Ace; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import io.fd.vpp.jvpp.VppBaseCallException; +import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; + +/** + * Writer responsible for translation of ietf-acl model ACEs to VPP's classify tables and sessions. + */ +interface AceWriter { + + /** + * Translates list of ACEs to chain of classify tables. Each ACE is translated into one classify table with single + * classify session. Also initializes input_acl_set_interface request message DTO with first classify table of the + * chain that was created. + * + * @param id uniquely identifies ietf-acl container + * @param aces list of access control entries + * @param request input_acl_set_interface request DTO + */ + void write(@Nonnull final InstanceIdentifier id, @Nonnull final List aces, + @Nonnull final InputAclSetInterface request, @Nonnegative final int vlanTags) + throws VppBaseCallException, WriteTimeoutException; +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AclCustomizer.java new file mode 100644 index 000000000..a423a456f --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AclCustomizer.java @@ -0,0 +1,92 @@ +/* + * 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.interfaces.acl.ingress; + +import static com.google.common.base.Preconditions.checkNotNull; + +import io.fd.honeycomb.translate.spi.write.WriterCustomizer; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; +import io.fd.honeycomb.translate.vpp.util.FutureJVppCustomizer; +import io.fd.honeycomb.translate.vpp.util.NamingContext; +import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.VppBaseCallException; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.acl.Ingress; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Customizer for enabling/disabling ingress ACLs on given interface based on low lever classfier model. + */ +public class AclCustomizer extends FutureJVppCustomizer implements WriterCustomizer, AclWriter { + + private static final Logger LOG = LoggerFactory.getLogger(AclCustomizer.class); + private final NamingContext interfaceContext; + private final VppClassifierContextManager classifyTableContext; + + public AclCustomizer(@Nonnull final FutureJVppCore vppApi, @Nonnull final NamingContext interfaceContext, + @Nonnull final VppClassifierContextManager classifyTableContext) { + super(vppApi); + this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); + this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Ingress dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + try { + setAcl(true, id, dataAfter, writeContext); + } catch (VppBaseCallException e) { + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Ingress dataBefore, + @Nonnull final Ingress dataAfter, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + throw new UnsupportedOperationException("Acl update is not supported. Please delete Acl container first."); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Ingress dataBefore, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + try { + setAcl(false, id, dataBefore, writeContext); + } catch (VppBaseCallException e) { + throw new WriteFailedException.DeleteFailedException(id, e); + } + } + + private void setAcl(final boolean isAdd, @Nonnull final InstanceIdentifier id, @Nonnull final Ingress acl, + @Nonnull final WriteContext writeContext) + throws VppBaseCallException, WriteTimeoutException { + final String ifName = id.firstKeyOf(Interface.class).getName(); + final int ifIndex = interfaceContext.getIndex(ifName, writeContext.getMappingContext()); + + LOG.debug("Setting ACL(isAdd={}) on interface={}(id={}): {}", isAdd, ifName, ifIndex, acl); + + inputAclSetInterface(getFutureJVpp(), isAdd, id, acl, ifIndex, classifyTableContext, + writeContext.getMappingContext()); + LOG.debug("Successfully set ACL(isAdd={}) on interface={}(id={}): {}", isAdd, ifName, ifIndex, acl); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AclWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AclWriter.java new file mode 100644 index 000000000..8c3333476 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AclWriter.java @@ -0,0 +1,75 @@ +/* + * 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.interfaces.acl.ingress; + +import static com.google.common.base.Preconditions.checkNotNull; + +import io.fd.honeycomb.translate.MappingContext; +import io.fd.honeycomb.translate.vpp.util.ByteDataTranslator; +import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer; +import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; +import java.util.concurrent.CompletionStage; +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.AclBaseAttributes; +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; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.L2Acl; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import io.fd.vpp.jvpp.VppBaseCallException; +import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; +import io.fd.vpp.jvpp.core.dto.InputAclSetInterfaceReply; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; + +interface AclWriter extends ByteDataTranslator, JvppReplyConsumer { + + default void inputAclSetInterface(@Nonnull final FutureJVppCore futureJVppCore, final boolean isAdd, + @Nonnull final InstanceIdentifier id, @Nonnull final AclBaseAttributes acl, + @Nonnegative final int ifIndex, + @Nonnull final VppClassifierContextManager classifyTableContext, + @Nonnull final MappingContext mappingContext) + throws VppBaseCallException, WriteTimeoutException { + final InputAclSetInterface request = new InputAclSetInterface(); + request.isAdd = booleanToByte(isAdd); + request.swIfIndex = ifIndex; + request.l2TableIndex = ~0; // skip + request.ip4TableIndex = ~0; // skip + request.ip6TableIndex = ~0; // skip + + final L2Acl l2Acl = acl.getL2Acl(); + if (l2Acl != null) { + final String tableName = checkNotNull(l2Acl.getClassifyTable(), "L2 classify table is null"); + 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.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.getTableIndex(tableName, mappingContext); + } + + final CompletionStage inputAclSetInterfaceReplyCompletionStage = + futureJVppCore.inputAclSetInterface(request); + + getReplyForWrite(inputAclSetInterfaceReplyCompletionStage.toCompletableFuture(), id); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/IetfAClWriter.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/IetfAClWriter.java new file mode 100644 index 000000000..0fe9954d4 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/IetfAClWriter.java @@ -0,0 +1,209 @@ +/* + * 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.interfaces.acl.ingress; + +import static com.google.common.base.Preconditions.checkArgument; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import io.fd.honeycomb.translate.v3po.interfaces.acl.IetfAclWriter; +import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer; +import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletionStage; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.annotation.Nonnegative; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AclBase; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.AccessListEntries; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.Ace; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.AceType; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceEth; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.AceIpVersion; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.ietf.acl.base.attributes.access.lists.Acl; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import io.fd.vpp.jvpp.VppBaseCallException; +import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTable; +import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply; +import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterface; +import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterfaceReply; +import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; +import io.fd.vpp.jvpp.core.dto.InputAclSetInterfaceReply; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class IetfAClWriter implements JvppReplyConsumer { + + private static final Logger LOG = LoggerFactory.getLogger(IetfAClWriter.class); + private final FutureJVppCore jvpp; + + private Map aceWriters = new HashMap<>(); + + public IetfAClWriter(@Nonnull final FutureJVppCore futureJVppCore) { + this.jvpp = Preconditions.checkNotNull(futureJVppCore, "futureJVppCore should not be null"); + aceWriters.put(AclType.ETH, new AceEthWriter(futureJVppCore)); + aceWriters.put(AclType.IP4, new AceIp4Writer(futureJVppCore)); + aceWriters.put(AclType.IP6, new AceIp6Writer(futureJVppCore)); + } + + private static Stream aclToAceStream(@Nonnull final Acl assignedAcl, + @Nonnull final WriteContext writeContext) { + final String aclName = assignedAcl.getName(); + final Class aclType = assignedAcl.getType(); + + // ietf-acl updates are handled first, so we use writeContext.readAfter + final Optional + aclOptional = writeContext.readAfter(IetfAclWriter.ACL_ID.child( + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl.class, + new AclKey(aclName, aclType))); + checkArgument(aclOptional.isPresent(), "Acl lists not configured"); + final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl + acl = aclOptional.get(); + + final AccessListEntries accessListEntries = acl.getAccessListEntries(); + checkArgument(accessListEntries != null, "access list entries not configured"); + + return accessListEntries.getAce().stream(); + } + + void deleteAcl(@Nonnull final InstanceIdentifier id, final int swIfIndex) + throws WriteTimeoutException, WriteFailedException.DeleteFailedException { + final ClassifyTableByInterface request = new ClassifyTableByInterface(); + request.swIfIndex = swIfIndex; + + try { + final CompletionStage cs = jvpp.classifyTableByInterface(request); + final ClassifyTableByInterfaceReply reply = getReplyForWrite(cs.toCompletableFuture(), id); + + // We unassign and remove all ACL-related classify tables for given interface (we assume we are the only + // classify table manager) + + unassignClassifyTables(id, reply); + + removeClassifyTable(id, reply.l2TableId); + removeClassifyTable(id, reply.ip4TableId); + removeClassifyTable(id, reply.ip6TableId); + } catch (VppBaseCallException e) { + throw new WriteFailedException.DeleteFailedException(id, e); + } + } + + private void unassignClassifyTables(@Nonnull final InstanceIdentifier id, + final ClassifyTableByInterfaceReply currentState) + throws VppBaseCallException, WriteTimeoutException { + final InputAclSetInterface request = new InputAclSetInterface(); + request.isAdd = 0; + request.swIfIndex = currentState.swIfIndex; + request.l2TableIndex = currentState.l2TableId; + request.ip4TableIndex = currentState.ip4TableId; + request.ip6TableIndex = currentState.ip6TableId; + final CompletionStage inputAclSetInterfaceReplyCompletionStage = + jvpp.inputAclSetInterface(request); + getReplyForWrite(inputAclSetInterfaceReplyCompletionStage.toCompletableFuture(), id); + } + + private void removeClassifyTable(@Nonnull final InstanceIdentifier id, final int tableIndex) + throws VppBaseCallException, WriteTimeoutException { + + if (tableIndex == -1) { + return; // classify table id is absent + } + final ClassifyAddDelTable request = new ClassifyAddDelTable(); + request.tableIndex = tableIndex; + final CompletionStage cs = jvpp.classifyAddDelTable(request); + getReplyForWrite(cs.toCompletableFuture(), id); + } + + void write(@Nonnull final InstanceIdentifier id, final int swIfIndex, @Nonnull final List acls, + @Nonnull final WriteContext writeContext) + throws VppBaseCallException, WriteTimeoutException { + write(id, swIfIndex, acls, writeContext, 0); + } + + void write(@Nonnull final InstanceIdentifier id, final int swIfIndex, @Nonnull final List acls, + @Nonnull final WriteContext writeContext, @Nonnegative final int numberOfTags) + throws VppBaseCallException, WriteTimeoutException { + + // filter ACE entries and group by AceType + final Map> acesByType = acls.stream() + .flatMap(acl -> aclToAceStream(acl, writeContext)) + .collect(Collectors.groupingBy(AclType::fromAce)); + + final InputAclSetInterface request = new InputAclSetInterface(); + request.isAdd = 1; + request.swIfIndex = swIfIndex; + request.l2TableIndex = -1; + request.ip4TableIndex = -1; + request.ip6TableIndex = -1; + + // for each AceType: + for (Map.Entry> entry : acesByType.entrySet()) { + final AclType aceType = entry.getKey(); + final List aces = entry.getValue(); + LOG.trace("Processing ACEs of {} type: {}", aceType, aces); + + final AceWriter aceWriter = aceWriters.get(aceType); + if (aceWriter == null) { + LOG.warn("AceProcessor for {} not registered. Skipping ACE.", aceType); + } else { + aceWriter.write(id, aces, request, numberOfTags); + } + } + + final CompletionStage inputAclSetInterfaceReplyCompletionStage = + jvpp.inputAclSetInterface(request); + getReplyForWrite(inputAclSetInterfaceReplyCompletionStage.toCompletableFuture(), id); + } + + private enum AclType { + ETH, IP4, IP6; + + @Nonnull + private static AclType fromAce(final Ace ace) { + AclType result = null; + final AceType aceType; + try { + aceType = ace.getMatches().getAceType(); + if (aceType instanceof AceEth) { + result = ETH; + } else if (aceType instanceof AceIp) { + final AceIpVersion aceIpVersion = ((AceIp) aceType).getAceIpVersion(); + if (aceIpVersion instanceof AceIpv4) { + result = IP4; + } else { + result = IP6; + } + } + } catch (NullPointerException e) { + throw new IllegalArgumentException("Incomplete ACE: " + ace, e); + } + if (result == null) { + throw new IllegalArgumentException(String.format("Not supported ace type %s", aceType)); + } + return result; + } + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/IetfAclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/IetfAclCustomizer.java new file mode 100644 index 000000000..5ffb95a59 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/IetfAclCustomizer.java @@ -0,0 +1,93 @@ +/* + * 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.interfaces.acl.ingress; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import io.fd.honeycomb.translate.spi.write.WriterCustomizer; +import io.fd.honeycomb.translate.vpp.util.NamingContext; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.VppBaseCallException; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.ietf.acl.base.attributes.AccessLists; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.ietf.acl.Ingress; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Customizer for enabling/disabling ingress ACLs for given interface (as defined in ietf-acl model). + * + * The customizer assumes it owns classify table management for interfaces where ietf-acl container is present. Using + * low level classifier model or direct changes to classify tables in combination with ietf-acls are not supported and + * can result in unpredictable behaviour. + */ +public class IetfAclCustomizer implements WriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(IetfAclCustomizer.class); + private final IetfAClWriter aclWriter; + private final NamingContext interfaceContext; + + public IetfAclCustomizer(@Nonnull final IetfAClWriter aclWriter, + @Nonnull final NamingContext interfaceContext) { + this.aclWriter = checkNotNull(aclWriter, "aclWriter should not be null"); + this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Ingress dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + final String ifName = id.firstKeyOf(Interface.class).getName(); + final int ifIndex = interfaceContext.getIndex(ifName, writeContext.getMappingContext()); + LOG.debug("Adding ACLs for interface={}(id={}): {}", ifName, ifIndex, dataAfter); + + final AccessLists accessLists = dataAfter.getAccessLists(); + checkArgument(accessLists != null && accessLists.getAcl() != null, + "ietf-acl container does not define acl list"); + + try { + aclWriter.write(id, ifIndex, accessLists.getAcl(), writeContext); + } catch (VppBaseCallException e) { + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ingress dataBefore, @Nonnull final Ingress dataAfter, + @Nonnull final WriteContext writeContext) + throws WriteFailedException { + LOG.debug("ACLs update: removing previously configured ACLs"); + deleteCurrentAttributes(id, dataBefore, writeContext); + LOG.debug("ACLs update: adding updated ACLs"); + writeCurrentAttributes(id, dataAfter, writeContext); + LOG.debug("ACLs update was successful"); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ingress dataBefore, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + final String ifName = id.firstKeyOf(Interface.class).getName(); + final int ifIndex = interfaceContext.getIndex(ifName, writeContext.getMappingContext()); + LOG.debug("Removing ACLs for interface={}(id={}): {}", ifName, ifIndex, dataBefore); + aclWriter.deleteAcl(id, ifIndex); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/SubInterfaceAclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/SubInterfaceAclCustomizer.java new file mode 100644 index 000000000..e71770121 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/SubInterfaceAclCustomizer.java @@ -0,0 +1,102 @@ +/* + * 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.interfaces.acl.ingress; + +import static com.google.common.base.Preconditions.checkNotNull; + +import io.fd.honeycomb.translate.spi.write.WriterCustomizer; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; +import io.fd.honeycomb.translate.vpp.util.FutureJVppCustomizer; +import io.fd.honeycomb.translate.vpp.util.NamingContext; +import io.fd.honeycomb.translate.vpp.util.SubInterfaceUtils; +import io.fd.honeycomb.translate.vpp.util.WriteTimeoutException; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.VppBaseCallException; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.acl.Ingress; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Customizer for enabling/disabling ingress ACLs on given sub-interface. + */ +public class SubInterfaceAclCustomizer extends FutureJVppCustomizer + implements WriterCustomizer, AclWriter { + + private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceAclCustomizer.class); + private final NamingContext interfaceContext; + private final VppClassifierContextManager classifyTableContext; + + public SubInterfaceAclCustomizer(@Nonnull final FutureJVppCore vppApi, + @Nonnull final NamingContext interfaceContext, + @Nonnull final VppClassifierContextManager classifyTableContext) { + super(vppApi); + this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); + this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Ingress dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + try { + setAcl(true, id, dataAfter, writeContext); + } catch (VppBaseCallException e) { + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Ingress dataBefore, + @Nonnull final Ingress dataAfter, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + throw new UnsupportedOperationException("Acl update is not supported. Please delete Acl container first."); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Ingress dataBefore, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + try { + setAcl(false, id, dataBefore, writeContext); + } catch (VppBaseCallException e) { + throw new WriteFailedException.DeleteFailedException(id, e); + } + } + + private void setAcl(final boolean isAdd, @Nonnull final InstanceIdentifier id, @Nonnull final Ingress acl, + @Nonnull final WriteContext writeContext) + throws VppBaseCallException, WriteTimeoutException { + final InterfaceKey parentInterfacekey = id.firstKeyOf(Interface.class); + final SubInterfaceKey subInterfacekey = id.firstKeyOf(SubInterface.class); + final String subInterfaceName = SubInterfaceUtils + .getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue()); + final int subInterfaceIndex = interfaceContext.getIndex(subInterfaceName, writeContext.getMappingContext()); + + LOG.debug("Setting ACL(isAdd={}) on sub-interface={}(id={}): {}", + isAdd, subInterfaceName, subInterfaceIndex, acl); + inputAclSetInterface(getFutureJVpp(), isAdd, id, acl, subInterfaceIndex, classifyTableContext, + writeContext.getMappingContext()); + LOG.debug("Successfully set ACL(isAdd={}) on sub-interface={}(id={}): {}", + isAdd, subInterfaceName, subInterfaceIndex, acl); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/SubInterfaceIetfAclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/SubInterfaceIetfAclCustomizer.java new file mode 100644 index 000000000..285ebce99 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/SubInterfaceIetfAclCustomizer.java @@ -0,0 +1,112 @@ +/* + * 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.interfaces.acl.ingress; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static io.fd.honeycomb.translate.vpp.util.SubInterfaceUtils.getNumberOfTags; + +import com.google.common.base.Optional; +import io.fd.honeycomb.translate.spi.write.WriterCustomizer; +import io.fd.honeycomb.translate.vpp.util.NamingContext; +import io.fd.honeycomb.translate.vpp.util.SubInterfaceUtils; +import io.fd.honeycomb.translate.write.WriteContext; +import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.VppBaseCallException; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.ietf.acl.base.attributes.AccessLists; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces._interface.sub.interfaces.SubInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.ietf.acl.Ingress; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Customizer for enabling/disabling ingress ACLs for given sub-interface (as defined in ietf-acl model). + * + * The customizer assumes it owns classify table management for sub-interfaces where ietf-acl container is present. + * Using low level classifier model or direct changes to classify tables in combination with ietf-acls are not supported + * and can result in unpredictable behaviour. + */ +public class SubInterfaceIetfAclCustomizer implements WriterCustomizer { + + private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceIetfAclCustomizer.class); + private final IetfAClWriter aclWriter; + private final NamingContext interfaceContext; + + public SubInterfaceIetfAclCustomizer(@Nonnull final IetfAClWriter aclWriter, + @Nonnull final NamingContext interfaceContext) { + this.aclWriter = checkNotNull(aclWriter, "aclWriter should not be null"); + this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); + } + + private String getSubInterfaceName(@Nonnull final InstanceIdentifier id) { + final InterfaceKey parentInterfacekey = id.firstKeyOf(Interface.class); + final SubInterfaceKey subInterfacekey = id.firstKeyOf(SubInterface.class); + return SubInterfaceUtils + .getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue()); + } + + @Override + public void writeCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final Ingress dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + final String subInterfaceName = getSubInterfaceName(id); + final int subInterfaceIndex = interfaceContext.getIndex(subInterfaceName, writeContext.getMappingContext()); + LOG.debug("Adding IETF-ACL for sub-interface: {}(id={}): {}", subInterfaceName, subInterfaceIndex, dataAfter); + + final AccessLists accessLists = dataAfter.getAccessLists(); + checkArgument(accessLists != null && accessLists.getAcl() != null, + "ietf-acl container does not define acl list"); + + final Optional subInterfaceOptional = + writeContext.readAfter(id.firstIdentifierOf(SubInterface.class)); + checkState(subInterfaceOptional.isPresent(), "Could not read SubInterface data object for %s", id); + final SubInterface subInterface = subInterfaceOptional.get(); + + try { + aclWriter.write(id, subInterfaceIndex, accessLists.getAcl(), writeContext, + getNumberOfTags(subInterface.getTags())); + } catch (VppBaseCallException e) { + throw new WriteFailedException.CreateFailedException(id, dataAfter, e); + } + } + + @Override + public void updateCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ingress dataBefore, @Nonnull final Ingress dataAfter, + @Nonnull final WriteContext writeContext) throws WriteFailedException { + LOG.debug("Sub-interface ACLs update: removing previously configured ACLs"); + deleteCurrentAttributes(id, dataBefore, writeContext); + LOG.debug("Sub-interface ACLs update: adding updated ACLs"); + writeCurrentAttributes(id, dataAfter, writeContext); + LOG.debug("Sub-interface ACLs update was successful"); + } + + @Override + public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier id, + @Nonnull final Ingress dataBefore, @Nonnull final WriteContext writeContext) + throws WriteFailedException { + final String subInterfaceName = getSubInterfaceName(id); + final int subInterfaceIndex = interfaceContext.getIndex(subInterfaceName, writeContext.getMappingContext()); + LOG.debug("Removing ACLs for sub-interface={}(id={}): {}", subInterfaceName, subInterfaceIndex, dataBefore); + aclWriter.deleteAcl(id, subInterfaceIndex); + } +} 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 deleted file mode 100644 index 864ae9f4e..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclCustomizer.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.translate.v3po.interfacesstate; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import io.fd.honeycomb.translate.read.ReadContext; -import io.fd.honeycomb.translate.read.ReadFailedException; -import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; -import io.fd.honeycomb.translate.vpp.util.FutureJVppCustomizer; -import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer; -import io.fd.honeycomb.translate.vpp.util.NamingContext; -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; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceStateAugmentationBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.Acl; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.AclBuilder; -import org.opendaylight.yangtools.concepts.Builder; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.VppBaseCallException; -import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterface; -import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterfaceReply; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Customizer for reading ACLs enabled on given interface. - */ -public class AclCustomizer extends FutureJVppCustomizer - implements ReaderCustomizer, AclReader, JvppReplyConsumer { - - private static final Logger LOG = LoggerFactory.getLogger(AclCustomizer.class); - private final NamingContext interfaceContext; - private final VppClassifierContextManager classifyTableContext; - - public AclCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext, - @Nonnull final VppClassifierContextManager classifyTableContext) { - super(jvpp); - this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); - this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); - } - - @Override - public void merge(@Nonnull final Builder parentBuilder, @Nonnull final Acl readValue) { - ((VppInterfaceStateAugmentationBuilder) parentBuilder).setAcl(readValue); - } - - @Nonnull - @Override - public AclBuilder getBuilder(@Nonnull final InstanceIdentifier id) { - return new AclBuilder(); - } - - @Override - public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final AclBuilder builder, - @Nonnull final ReadContext ctx) throws ReadFailedException { - LOG.debug("Reading attributes for interface ACL: {}", id); - final InterfaceKey interfaceKey = id.firstKeyOf(Interface.class); - checkArgument(interfaceKey != null, "No parent interface key found"); - - final ClassifyTableByInterface request = new ClassifyTableByInterface(); - request.swIfIndex = interfaceContext.getIndex(interfaceKey.getName(), ctx.getMappingContext()); - try { - final ClassifyTableByInterfaceReply reply = - getReplyForRead(getFutureJVpp().classifyTableByInterface(request).toCompletableFuture(), id); - - builder.setL2Acl(readL2Acl(reply.l2TableId, classifyTableContext, ctx.getMappingContext())); - builder.setIp4Acl(readIp4Acl(reply.ip4TableId, classifyTableContext, ctx.getMappingContext())); - builder.setIp6Acl(readIp6Acl(reply.ip6TableId, classifyTableContext, ctx.getMappingContext())); - - if (LOG.isTraceEnabled()) { - LOG.trace("Attributes for ACL {} successfully read: {}", id, builder.build()); - } - } catch (VppBaseCallException e) { - throw new ReadFailedException(id, e); - } - } -} 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 deleted file mode 100644 index c16bfe6e3..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/AclReader.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.translate.v3po.interfacesstate; - -import io.fd.honeycomb.translate.MappingContext; -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; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip6Acl; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip6AclBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.L2Acl; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.L2AclBuilder; - -interface AclReader { - - @Nonnull - default L2Acl readL2Acl(final int l2TableId, @Nonnull final VppClassifierContextManager classifyTableContext, - @Nonnull final MappingContext mappingContext) { - if (l2TableId == ~0) { - return null; - } - return new L2AclBuilder() - .setClassifyTable(classifyTableContext.getTableName(l2TableId, mappingContext)).build(); - } - - @Nonnull - default Ip4Acl readIp4Acl(final int ip4TableId, @Nonnull final VppClassifierContextManager classifyTableContext, - @Nonnull final MappingContext mappingContext) { - if (ip4TableId == ~0) { - return null; - } - return new Ip4AclBuilder() - .setClassifyTable(classifyTableContext.getTableName(ip4TableId, mappingContext)).build(); - } - - @Nonnull - default Ip6Acl readIp6Acl(final int ip6TableId, @Nonnull final VppClassifierContextManager classifyTableContext, - @Nonnull final MappingContext mappingContext) { - if (ip6TableId == ~0) { - return null; - } - return new Ip6AclBuilder() - .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 deleted file mode 100644 index 639ad6b2a..000000000 --- a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/SubInterfaceAclCustomizer.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.fd.honeycomb.translate.v3po.interfacesstate; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static io.fd.honeycomb.translate.vpp.util.SubInterfaceUtils.getSubInterfaceName; - -import io.fd.honeycomb.translate.read.ReadContext; -import io.fd.honeycomb.translate.read.ReadFailedException; -import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; -import io.fd.honeycomb.translate.vpp.util.FutureJVppCustomizer; -import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer; -import io.fd.honeycomb.translate.vpp.util.NamingContext; -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; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterface; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterfaceBuilder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterfaceKey; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.Acl; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.AclBuilder; -import org.opendaylight.yangtools.concepts.Builder; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.VppBaseCallException; -import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterface; -import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterfaceReply; -import io.fd.vpp.jvpp.core.future.FutureJVppCore; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Customizer for reading ACLs enabled on given sub-interface. - */ -public class SubInterfaceAclCustomizer extends FutureJVppCustomizer - implements ReaderCustomizer, AclReader, JvppReplyConsumer { - - private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceAclCustomizer.class); - private final NamingContext interfaceContext; - private final VppClassifierContextManager classifyTableContext; - - public SubInterfaceAclCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext, - @Nonnull final VppClassifierContextManager classifyTableContext) { - super(jvpp); - this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); - this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); - } - - @Override - public void merge(@Nonnull final Builder parentBuilder, @Nonnull final Acl readValue) { - ((SubInterfaceBuilder) parentBuilder).setAcl(readValue); - } - - @Nonnull - @Override - public AclBuilder getBuilder(@Nonnull final InstanceIdentifier id) { - return new AclBuilder(); - } - - @Override - public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final AclBuilder builder, - @Nonnull final ReadContext ctx) throws ReadFailedException { - LOG.debug("Reading attributes for sub-interface ACL: {}", id); - final InterfaceKey parentInterfacekey = id.firstKeyOf(Interface.class); - checkArgument(parentInterfacekey != null, "No parent interface key found"); - final SubInterfaceKey subInterfacekey = id.firstKeyOf(SubInterface.class); - checkArgument(subInterfacekey != null, "No sub-interface key found"); - final String subInterfaceName = - getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue()); - - final ClassifyTableByInterface request = new ClassifyTableByInterface(); - request.swIfIndex = interfaceContext.getIndex(subInterfaceName, ctx.getMappingContext()); - try { - final ClassifyTableByInterfaceReply reply = - getReplyForRead(getFutureJVpp().classifyTableByInterface(request).toCompletableFuture(), id); - - builder.setL2Acl(readL2Acl(reply.l2TableId, classifyTableContext, ctx.getMappingContext())); - builder.setIp4Acl(readIp4Acl(reply.ip4TableId, classifyTableContext, ctx.getMappingContext())); - builder.setIp6Acl(readIp6Acl(reply.ip6TableId, classifyTableContext, ctx.getMappingContext())); - - if (LOG.isTraceEnabled()) { - LOG.trace("Attributes for ACL {} successfully read: {}", id, builder.build()); - } - } catch (VppBaseCallException e) { - throw new ReadFailedException(id, e); - } - } -} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/acl/ingress/AclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/acl/ingress/AclCustomizer.java new file mode 100644 index 000000000..c248575ca --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/acl/ingress/AclCustomizer.java @@ -0,0 +1,97 @@ +/* + * 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.interfacesstate.acl.ingress; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; + +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; +import io.fd.honeycomb.translate.vpp.util.FutureJVppCustomizer; +import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer; +import io.fd.honeycomb.translate.vpp.util.NamingContext; +import io.fd.vpp.jvpp.VppBaseCallException; +import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterface; +import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterfaceReply; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.AclBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.acl.Ingress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces.state._interface.acl.IngressBuilder; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Customizer for reading ingress ACLs enabled on given interface. + */ +public class AclCustomizer extends FutureJVppCustomizer + implements ReaderCustomizer, AclReader, JvppReplyConsumer { + + private static final Logger LOG = LoggerFactory.getLogger(AclCustomizer.class); + private final NamingContext interfaceContext; + private final VppClassifierContextManager classifyTableContext; + + public AclCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext, + @Nonnull final VppClassifierContextManager classifyTableContext) { + super(jvpp); + this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); + this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); + } + + @Override + public void merge(@Nonnull final Builder parentBuilder, @Nonnull final Ingress readValue) { + ((AclBuilder) parentBuilder).setIngress(readValue); + } + + @Nonnull + @Override + public IngressBuilder getBuilder(@Nonnull final InstanceIdentifier id) { + return new IngressBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final IngressBuilder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + LOG.debug("Reading attributes for interface ACL: {}", id); + final InterfaceKey interfaceKey = id.firstKeyOf(Interface.class); + checkArgument(interfaceKey != null, "No parent interface key found"); + + final ClassifyTableByInterface request = new ClassifyTableByInterface(); + request.swIfIndex = interfaceContext.getIndex(interfaceKey.getName(), ctx.getMappingContext()); + try { + final ClassifyTableByInterfaceReply reply = + getReplyForRead(getFutureJVpp().classifyTableByInterface(request).toCompletableFuture(), id); + + builder.setL2Acl(readL2Acl(reply.l2TableId, classifyTableContext, ctx.getMappingContext())); + builder.setIp4Acl(readIp4Acl(reply.ip4TableId, classifyTableContext, ctx.getMappingContext())); + builder.setIp6Acl(readIp6Acl(reply.ip6TableId, classifyTableContext, ctx.getMappingContext())); + + if (LOG.isTraceEnabled()) { + LOG.trace("Attributes for ACL {} successfully read: {}", id, builder.build()); + } + } catch (VppBaseCallException e) { + throw new ReadFailedException(id, e); + } + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/acl/ingress/AclReader.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/acl/ingress/AclReader.java new file mode 100644 index 000000000..ec847ac5e --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/acl/ingress/AclReader.java @@ -0,0 +1,60 @@ +/* + * 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.interfacesstate.acl.ingress; + +import io.fd.honeycomb.translate.MappingContext; +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; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip6Acl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.Ip6AclBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.L2Acl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.acl.base.attributes.L2AclBuilder; + +interface AclReader { + + @Nonnull + default L2Acl readL2Acl(final int l2TableId, @Nonnull final VppClassifierContextManager classifyTableContext, + @Nonnull final MappingContext mappingContext) { + if (l2TableId == ~0) { + return null; + } + return new L2AclBuilder() + .setClassifyTable(classifyTableContext.getTableName(l2TableId, mappingContext)).build(); + } + + @Nonnull + default Ip4Acl readIp4Acl(final int ip4TableId, @Nonnull final VppClassifierContextManager classifyTableContext, + @Nonnull final MappingContext mappingContext) { + if (ip4TableId == ~0) { + return null; + } + return new Ip4AclBuilder() + .setClassifyTable(classifyTableContext.getTableName(ip4TableId, mappingContext)).build(); + } + + @Nonnull + default Ip6Acl readIp6Acl(final int ip6TableId, @Nonnull final VppClassifierContextManager classifyTableContext, + @Nonnull final MappingContext mappingContext) { + if (ip6TableId == ~0) { + return null; + } + return new Ip6AclBuilder() + .setClassifyTable(classifyTableContext.getTableName(ip6TableId, mappingContext)).build(); + } +} diff --git a/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/acl/ingress/SubInterfaceAclCustomizer.java b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/acl/ingress/SubInterfaceAclCustomizer.java new file mode 100644 index 000000000..ad80f6ee2 --- /dev/null +++ b/v3po/v3po2vpp/src/main/java/io/fd/honeycomb/translate/v3po/interfacesstate/acl/ingress/SubInterfaceAclCustomizer.java @@ -0,0 +1,104 @@ +/* + * 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.interfacesstate.acl.ingress; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static io.fd.honeycomb.translate.vpp.util.SubInterfaceUtils.getSubInterfaceName; + +import io.fd.honeycomb.translate.read.ReadContext; +import io.fd.honeycomb.translate.read.ReadFailedException; +import io.fd.honeycomb.translate.spi.read.ReaderCustomizer; +import io.fd.honeycomb.translate.v3po.vppclassifier.VppClassifierContextManager; +import io.fd.honeycomb.translate.vpp.util.FutureJVppCustomizer; +import io.fd.honeycomb.translate.vpp.util.JvppReplyConsumer; +import io.fd.honeycomb.translate.vpp.util.NamingContext; +import io.fd.vpp.jvpp.VppBaseCallException; +import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterface; +import io.fd.vpp.jvpp.core.dto.ClassifyTableByInterfaceReply; +import io.fd.vpp.jvpp.core.future.FutureJVppCore; +import javax.annotation.Nonnull; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.interfaces.state._interface.sub.interfaces.SubInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.AclBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.acl.Ingress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.vlan.rev150527.sub._interface.base.attributes.acl.IngressBuilder; +import org.opendaylight.yangtools.concepts.Builder; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Customizer for reading ingress ACLs enabled on given sub-interface. + */ +public class SubInterfaceAclCustomizer extends FutureJVppCustomizer + implements ReaderCustomizer, AclReader, JvppReplyConsumer { + + private static final Logger LOG = LoggerFactory.getLogger(SubInterfaceAclCustomizer.class); + private final NamingContext interfaceContext; + private final VppClassifierContextManager classifyTableContext; + + public SubInterfaceAclCustomizer(@Nonnull final FutureJVppCore jvpp, @Nonnull final NamingContext interfaceContext, + @Nonnull final VppClassifierContextManager classifyTableContext) { + super(jvpp); + this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null"); + this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null"); + } + + @Override + public void merge(@Nonnull final Builder parentBuilder, @Nonnull final Ingress readValue) { + ((AclBuilder) parentBuilder).setIngress(readValue); + } + + @Nonnull + @Override + public IngressBuilder getBuilder(@Nonnull final InstanceIdentifier id) { + return new IngressBuilder(); + } + + @Override + public void readCurrentAttributes(@Nonnull final InstanceIdentifier id, @Nonnull final IngressBuilder builder, + @Nonnull final ReadContext ctx) throws ReadFailedException { + LOG.debug("Reading attributes for sub-interface ACL: {}", id); + final InterfaceKey parentInterfacekey = id.firstKeyOf(Interface.class); + checkArgument(parentInterfacekey != null, "No parent interface key found"); + final SubInterfaceKey subInterfacekey = id.firstKeyOf(SubInterface.class); + checkArgument(subInterfacekey != null, "No sub-interface key found"); + final String subInterfaceName = + getSubInterfaceName(parentInterfacekey.getName(), subInterfacekey.getIdentifier().intValue()); + + final ClassifyTableByInterface request = new ClassifyTableByInterface(); + request.swIfIndex = interfaceContext.getIndex(subInterfaceName, ctx.getMappingContext()); + try { + final ClassifyTableByInterfaceReply reply = + getReplyForRead(getFutureJVpp().classifyTableByInterface(request).toCompletableFuture(), id); + + builder.setL2Acl(readL2Acl(reply.l2TableId, classifyTableContext, ctx.getMappingContext())); + builder.setIp4Acl(readIp4Acl(reply.ip4TableId, classifyTableContext, ctx.getMappingContext())); + builder.setIp6Acl(readIp6Acl(reply.ip6TableId, classifyTableContext, ctx.getMappingContext())); + + if (LOG.isTraceEnabled()) { + LOG.trace("Attributes for ACL {} successfully read: {}", id, builder.build()); + } + } catch (VppBaseCallException e) { + throw new ReadFailedException(id, e); + } + } +} -- cgit 1.2.3-korg