diff options
author | Marek Gradzki <mgradzki@cisco.com> | 2016-10-07 15:26:06 +0200 |
---|---|---|
committer | Marek Gradzki <mgradzki@cisco.com> | 2016-10-10 13:02:31 +0000 |
commit | 8f6c292af0821fd8a8e8d80aea0e9cf97447a747 (patch) | |
tree | 3dae468a7a41be9a7d91c4ddf1b9d080d1f5e1c0 | |
parent | 6d4040025235da89ff4c43b8f0f82d1b0e593c67 (diff) |
HONEYCOMB-246: allow mixing deny/permit rules
- adds classify table on the end of each of the 3 chains to enforce ordering
- updates v3po.yang with default-action leaf
- updates postman collection
Change-Id: If54abec1a6516eaf87aae0e5da9382a6e5dee1f3
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
14 files changed, 176 insertions, 86 deletions
diff --git a/v3po/api/src/main/yang/v3po.yang b/v3po/api/src/main/yang/v3po.yang index 69e2f73b3..3e981c3ff 100644 --- a/v3po/api/src/main/yang/v3po.yang +++ b/v3po/api/src/main/yang/v3po.yang @@ -7,7 +7,7 @@ module v3po { description "This revision adds the following new features: - ingress/egress ACLs support - - interface-mode type as a part of ietf-acl configuration"; + - default-action and interface-mode type as a part of ietf-acl configuration"; } revision "2015-01-05" { @@ -464,10 +464,10 @@ module v3po { container access-lists { description "Defines references to ietf-acl lists. Before assignment to interface, - ACL lists are merged into 3 type of acls (eth0, ip4 and ip6) that are supported by vpp. - Then corresponding tables and sessions are created and assigned to the interface. - - All ACEs for all assigned ACLs have to use the same packet-handling action (either deny or parmit). + ACL lists are merged into 3 type of acls (l2, ip4 and ip6) that are supported by vpp. + Then 3 corresponding chains of tables and sessions are created and assigned to the interface + as l2, ip4 and ip6 classify table chains. + User ordering is preserved in each group separately. Assignment update/delete removes all created tables and sessions and repeats process described above. Update/delete of ACL lists referenced here is not permitted (assignment needs to be removed first). @@ -484,6 +484,7 @@ module v3po { - vlan tags are supported only for sub-interfaces defined as exact-match"; list acl { key "type name"; + ordered-by user; leaf type { type acl:acl-type; @@ -494,6 +495,17 @@ module v3po { } } + leaf default-action { + type enumeration { + enum "deny"; + enum "permit"; + } + default "deny"; + description + "Default action applied to packet that does not match any of rules defined in assigned ACLs. + It is translated to single classify table and applied at the end of assigned chains."; + } + leaf mode { type interface-mode; default l3; diff --git a/v3po/postman_rest_collection.json b/v3po/postman_rest_collection.json index 40019526b..923033dd4 100644 --- a/v3po/postman_rest_collection.json +++ b/v3po/postman_rest_collection.json @@ -912,7 +912,7 @@ "description": "Creates chain of classfy tabless/sessions in VPP and assigns them to local0 interface.\n\nCan be verified with:\nvppctl show classify table verbose\n\nthen:\nvppctl show inacl type l2", "collectionId": "5bad4634-e5cf-900e-9733-0976aa9bea64", "responses": [], - "rawModeData": "{\n \"ingress\": {\n \"access-lists\": {\n \"acl\": [\n {\n \"type\" : \"ietf-access-control-list:eth-acl\",\n \"name\" : \"acl1\"\n },\n {\n \"type\" : \"ietf-access-control-list:eth-acl\",\n \"name\" : \"acl2\"\n }\n ]\n }\n }\n}", + "rawModeData": "{\n \"ingress\": {\n \"access-lists\": {\n \"acl\": [\n {\n \"type\" : \"ietf-access-control-list:eth-acl\",\n \"name\" : \"acl1\"\n },\n {\n \"type\" : \"ietf-access-control-list:eth-acl\",\n \"name\" : \"acl2\"\n }\n ],\n \"default-action\": \"permit\",\n \"mode\": \"l2\"\n }\n }\n}", "folder": "c05d7211-11b0-5688-2079-afa51196045c" }, { 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 index 70cfee894..2e2d1648e 100644 --- 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 @@ -20,7 +20,6 @@ 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.write.WriteFailedException; import io.fd.vpp.jvpp.core.dto.ClassifyAddDelSession; @@ -30,8 +29,8 @@ import io.fd.vpp.jvpp.core.dto.ClassifyAddDelTableReply; import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; import io.fd.vpp.jvpp.core.future.FutureJVppCore; import java.util.List; +import java.util.ListIterator; import java.util.concurrent.CompletionStage; -import java.util.stream.Collector; import javax.annotation.Nonnegative; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -40,6 +39,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.cont 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.InterfaceMode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.ietf.acl.base.attributes.AccessLists; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; /** @@ -59,8 +59,8 @@ abstract class AbstractAceWriter<T extends AceType> implements AceWriter, JvppRe @VisibleForTesting static final int VLAN_TAG_LEN = 4; - private static final Collector<PacketHandling, ?, PacketHandling> SINGLE_ITEM_COLLECTOR = - RWUtils.singleItemCollector(); + private static final int PERMIT = -1; + private static final int DENY = 0; private final FutureJVppCore futureJVppCore; @@ -71,15 +71,13 @@ abstract class AbstractAceWriter<T extends AceType> implements AceWriter, JvppRe /** * Creates classify table for given ACE. * - * @param action packet handling action (permit/deny) * @param ace ACE to be translated * @param mode interface mode * @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, + protected abstract ClassifyAddDelTable createClassifyTable(@Nonnull final T ace, @Nullable final InterfaceMode mode, final int nextTableIndex, final int vlanTags); @@ -110,26 +108,41 @@ abstract class AbstractAceWriter<T extends AceType> implements AceWriter, JvppRe @Override public final void write(@Nonnull final InstanceIdentifier<?> id, @Nonnull final List<Ace> aces, - final InterfaceMode mode, @Nonnull final InputAclSetInterface request, + final InterfaceMode mode, final AccessLists.DefaultAction defaultAction, + @Nonnull final InputAclSetInterface request, @Nonnegative final int vlanTags) throws WriteFailedException { - 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 + int nextTableIndex = configureDefaltAction(id, defaultAction); - final ClassifyAddDelTable ctRequest = - createClassifyTable(action, (T) ace.getMatches().getAceType(), mode, nextTableIndex, vlanTags); + final ListIterator<Ace> iterator = aces.listIterator(aces.size()); + while (iterator.hasPrevious()) { + // Create table + session per entry + final Ace ace = iterator.previous(); + final PacketHandling action = ace.getActions().getPacketHandling(); + final T type = (T)ace.getMatches().getAceType(); + final ClassifyAddDelTable ctRequest = createClassifyTable(type, mode, nextTableIndex, vlanTags); nextTableIndex = createClassifyTable(id, ctRequest); - createClassifySession(id, - createClassifySession(action, (T) ace.getMatches().getAceType(), mode, nextTableIndex, vlanTags)); + createClassifySession(id, createClassifySession(action, type, mode, nextTableIndex, vlanTags)); } setClassifyTable(request, nextTableIndex); } + private int configureDefaltAction(@Nonnull final InstanceIdentifier<?> id, final AccessLists.DefaultAction defaultAction) + throws WriteFailedException { + ClassifyAddDelTable ctRequest = createClassifyTable(-1); + if (AccessLists.DefaultAction.Permit.equals(defaultAction)) { + ctRequest.missNextIndex = PERMIT; + } else { + ctRequest.missNextIndex = DENY; + } + ctRequest.mask = new byte[16]; + ctRequest.skipNVectors = 0; + ctRequest.matchNVectors = 1; + return createClassifyTable(id, ctRequest); + } + private int createClassifyTable(@Nonnull final InstanceIdentifier<?> id, @Nonnull final ClassifyAddDelTable request) throws WriteFailedException { @@ -147,22 +160,14 @@ abstract class AbstractAceWriter<T extends AceType> implements AceWriter, JvppRe getReplyForWrite(cs.toCompletableFuture(), id); } - protected ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action, final int nextTableIndex) { + protected ClassifyAddDelTable createClassifyTable(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; - + request.missNextIndex = -1; // value not set, but anyway it is ignored for tables in chain return request; } 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 index 89a92f5c0..667d9cc38 100644 --- 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 @@ -48,14 +48,13 @@ final class AceEthWriter extends AbstractAceWriter<AceEth> implements MacTransla } @Override - public ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action, - @Nonnull final AceEth aceEth, + public ClassifyAddDelTable createClassifyTable(@Nonnull final AceEth aceEth, @Nullable final InterfaceMode mode, final int nextTableIndex, final int vlanTags) { checkInterfaceMode(mode); - final ClassifyAddDelTable request = createClassifyTable(action, nextTableIndex); + final ClassifyAddDelTable request = createClassifyTable(nextTableIndex); request.mask = new byte[16]; boolean aceIsEmpty = true; @@ -102,7 +101,7 @@ final class AceEthWriter extends AbstractAceWriter<AceEth> implements MacTransla request.skipNVectors = 0; request.matchNVectors = MATCH_N_VECTORS; - LOG.debug("ACE action={}, rule={} translated to table={}.", action, aceEth, request); + LOG.debug("ACE rule={} translated to table={}.", aceEth, request); return request; } 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 index e539d4e14..e1d05f6ec 100644 --- 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 @@ -78,15 +78,14 @@ final class AceIp4Writer extends AbstractAceWriter<AceIp> implements Ipv4Transla } @Override - public ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action, - @Nonnull final AceIp aceIp, + public ClassifyAddDelTable createClassifyTable(@Nonnull final AceIp aceIp, @Nullable final InterfaceMode mode, 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); + final ClassifyAddDelTable request = createClassifyTable(nextTableIndex); request.skipNVectors = 0; // match entire L2 and L3 header request.matchNVectors = MATCH_N_VECTORS; @@ -137,7 +136,7 @@ final class AceIp4Writer extends AbstractAceWriter<AceIp> implements Ipv4Transla String.format("Ace %s does not define packet field match values", aceIp.toString())); } - LOG.debug("ACE action={}, rule={} translated to table={}.", action, aceIp, request); + LOG.debug("ACE rule={} translated to table={}.", aceIp, request); return request; } 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 index 2afc75c28..18fa1ec4d 100644 --- 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 @@ -92,15 +92,14 @@ final class AceIp6Writer extends AbstractAceWriter<AceIp> { } @Override - public ClassifyAddDelTable createClassifyTable(@Nonnull final PacketHandling action, - @Nonnull final AceIp aceIp, + public ClassifyAddDelTable createClassifyTable(@Nonnull final AceIp aceIp, @Nullable final InterfaceMode mode, 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); + final ClassifyAddDelTable request = createClassifyTable(nextTableIndex); request.skipNVectors = 0; // match entire L2 and L3 header request.matchNVectors = MATCH_N_VECTORS; @@ -160,7 +159,7 @@ final class AceIp6Writer extends AbstractAceWriter<AceIp> { String.format("Ace %s does not define packet field match values", aceIp.toString())); } - LOG.debug("ACE action={}, rule={} translated to table={}.", action, aceIp, request); + LOG.debug("ACE rule={} translated to table={}.", aceIp, request); return request; } 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 index 63bd6a897..c2c024870 100644 --- 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 @@ -17,13 +17,14 @@ package io.fd.honeycomb.translate.v3po.interfaces.acl.ingress; import io.fd.honeycomb.translate.write.WriteFailedException; +import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.InterfaceMode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.ietf.acl.base.attributes.AccessLists; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import io.fd.vpp.jvpp.core.dto.InputAclSetInterface; /** * Writer responsible for translation of ietf-acl model ACEs to VPP's classify tables and sessions. @@ -34,12 +35,15 @@ 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 mode - * @param request input_acl_set_interface request DTO + * + * @param id uniquely identifies ietf-acl container + * @param aces list of access control entries + * @param mode interface mode (L2/L3) + * @param defaultAction to be taken when packet that does not match any of rules defined in + * @param request input_acl_set_interface request DTO */ void write(@Nonnull final InstanceIdentifier<?> id, @Nonnull final List<Ace> aces, - final InterfaceMode mode, @Nonnull final InputAclSetInterface request, @Nonnegative final int vlanTags) + final InterfaceMode mode, final AccessLists.DefaultAction defaultAction, + @Nonnull final InputAclSetInterface request, @Nonnegative final int vlanTags) throws WriteFailedException; } 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 index 7105009dc..526fdd71f 100644 --- 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 @@ -50,6 +50,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.cont 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.rev161214.InterfaceMode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.ietf.acl.base.attributes.AccessLists; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.ietf.acl.base.attributes.access.lists.Acl; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; @@ -134,13 +135,13 @@ public final class IetfAClWriter implements JvppReplyConsumer { } void write(@Nonnull final InstanceIdentifier<?> id, final int swIfIndex, @Nonnull final List<Acl> acls, - @Nullable final InterfaceMode mode, @Nonnull final WriteContext writeContext) + final AccessLists.DefaultAction defaultAction, @Nullable final InterfaceMode mode, @Nonnull final WriteContext writeContext) throws WriteFailedException { - write(id, swIfIndex, mode, acls, writeContext, 0); + write(id, swIfIndex, mode, acls, defaultAction, writeContext, 0); } void write(@Nonnull final InstanceIdentifier<?> id, final int swIfIndex, final InterfaceMode mode, - @Nonnull final List<Acl> acls, + @Nonnull final List<Acl> acls, final AccessLists.DefaultAction defaultAction, @Nonnull final WriteContext writeContext, @Nonnegative final int numberOfTags) throws WriteFailedException { @@ -166,7 +167,7 @@ public final class IetfAClWriter implements JvppReplyConsumer { if (aceWriter == null) { LOG.warn("AceProcessor for {} not registered. Skipping ACE.", aceType); } else { - aceWriter.write(id, aces, mode, request, numberOfTags); + aceWriter.write(id, aces, mode, defaultAction, request, numberOfTags); } } 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 index a98ee30a2..3a55e0068 100644 --- 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 @@ -61,7 +61,8 @@ public class IetfAclCustomizer implements WriterCustomizer<Ingress> { checkArgument(accessLists != null && accessLists.getAcl() != null, "ietf-acl container does not define acl list"); - aclWriter.write(id, ifIndex, accessLists.getAcl(), accessLists.getMode(), writeContext); + aclWriter.write(id, ifIndex, accessLists.getAcl(), accessLists.getDefaultAction(), accessLists.getMode(), + writeContext); } @Override 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 index d5f1eb27d..79ee72825 100644 --- 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 @@ -80,8 +80,8 @@ public class SubInterfaceIetfAclCustomizer implements WriterCustomizer<Ingress> checkState(subInterfaceOptional.isPresent(), "Could not read SubInterface data object for %s", id); final SubInterface subInterface = subInterfaceOptional.get(); - aclWriter.write(id, subInterfaceIndex, accessLists.getMode(), accessLists.getAcl(), writeContext, - getNumberOfTags(subInterface.getTags())); + aclWriter.write(id, subInterfaceIndex, accessLists.getMode(), accessLists.getAcl(), + accessLists.getDefaultAction(), writeContext, getNumberOfTags(subInterface.getTags())); } @Override diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceEthWriterTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceEthWriterTest.java index e1f813eed..759c77477 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceEthWriterTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceEthWriterTest.java @@ -58,12 +58,11 @@ public class AceEthWriterTest { @Test public void testCreateClassifyTable() { final int nextTableIndex = 42; - final ClassifyAddDelTable request = writer.createClassifyTable(action, aceEth, InterfaceMode.L2, nextTableIndex, 0); + final ClassifyAddDelTable request = writer.createClassifyTable(aceEth, InterfaceMode.L2, nextTableIndex, 0); assertEquals(1, request.isAdd); assertEquals(-1, request.tableIndex); assertEquals(1, request.nbuckets); - assertEquals(-1, request.missNextIndex); assertEquals(nextTableIndex, request.nextTableIndex); assertEquals(0, request.skipNVectors); assertEquals(AceEthWriter.MATCH_N_VECTORS, request.matchNVectors); @@ -81,7 +80,7 @@ public class AceEthWriterTest { @Test(expected = IllegalArgumentException.class) public void testCreateClassifyTableForL3Interface() { - writer.createClassifyTable(action, aceEth, InterfaceMode.L3, 42, 0); + writer.createClassifyTable(aceEth, InterfaceMode.L3, 42, 0); } @Test diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp4WriterTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp4WriterTest.java index 9597c1688..b454acc0b 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp4WriterTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp4WriterTest.java @@ -64,7 +64,6 @@ public class AceIp4WriterTest { assertEquals(1, request.isAdd); assertEquals(-1, request.tableIndex); assertEquals(1, request.nbuckets); - assertEquals(-1, request.missNextIndex); assertEquals(nextTableIndex, request.nextTableIndex); assertEquals(0, request.skipNVectors); assertEquals(AceIp4Writer.MATCH_N_VECTORS, request.matchNVectors); @@ -107,14 +106,14 @@ public class AceIp4WriterTest { @Test public void testCreateClassifyTable() throws Exception { final int nextTableIndex = 42; - final ClassifyAddDelTable request = writer.createClassifyTable(action, aceIp, InterfaceMode.L3, nextTableIndex, 0); + final ClassifyAddDelTable request = writer.createClassifyTable(aceIp, InterfaceMode.L3, nextTableIndex, 0); verifyTableRequest(request, nextTableIndex, 0, false); } @Test public void testCreateClassifyTableForL2Interface() throws Exception { final int nextTableIndex = 42; - final ClassifyAddDelTable request = writer.createClassifyTable(action, aceIp, InterfaceMode.L2, nextTableIndex, 0); + final ClassifyAddDelTable request = writer.createClassifyTable(aceIp, InterfaceMode.L2, nextTableIndex, 0); verifyTableRequest(request, nextTableIndex, 0, true); } @@ -122,7 +121,7 @@ public class AceIp4WriterTest { public void testCreateClassifyTable1VlanTag() throws Exception { final int nextTableIndex = 42; final int vlanTags = 1; - final ClassifyAddDelTable request = writer.createClassifyTable(action, aceIp, InterfaceMode.L3, nextTableIndex, vlanTags); + final ClassifyAddDelTable request = writer.createClassifyTable(aceIp, InterfaceMode.L3, nextTableIndex, vlanTags); verifyTableRequest(request, nextTableIndex, vlanTags, false); } @@ -130,7 +129,7 @@ public class AceIp4WriterTest { public void testCreateClassifyTable2VlanTags() throws Exception { final int nextTableIndex = 42; final int vlanTags = 2; - final ClassifyAddDelTable request = writer.createClassifyTable(action, aceIp, InterfaceMode.L3, nextTableIndex, vlanTags); + final ClassifyAddDelTable request = writer.createClassifyTable(aceIp, InterfaceMode.L3, nextTableIndex, vlanTags); verifyTableRequest(request, nextTableIndex, vlanTags, false); } diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp6WriterTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp6WriterTest.java index 504d502a3..6ac469f93 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp6WriterTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/AceIp6WriterTest.java @@ -67,7 +67,6 @@ public class AceIp6WriterTest { assertEquals(1, request.isAdd); assertEquals(-1, request.tableIndex); assertEquals(1, request.nbuckets); - assertEquals(-1, request.missNextIndex); assertEquals(nextTableIndex, request.nextTableIndex); assertEquals(0, request.skipNVectors); assertEquals(AceIp6Writer.MATCH_N_VECTORS, request.matchNVectors); @@ -130,7 +129,7 @@ public class AceIp6WriterTest { public void testCreateClassifyTable() { final int nextTableIndex = 42; final ClassifyAddDelTable request = - writer.createClassifyTable(action, aceIp, InterfaceMode.L3, nextTableIndex, 0); + writer.createClassifyTable(aceIp, InterfaceMode.L3, nextTableIndex, 0); verifyTableRequest(request, nextTableIndex, 0, false); } @@ -138,7 +137,7 @@ public class AceIp6WriterTest { public void testCreateClassifyTableForL2Interface() { final int nextTableIndex = 42; final ClassifyAddDelTable request = - writer.createClassifyTable(action, aceIp, InterfaceMode.L2, nextTableIndex, 0); + writer.createClassifyTable(aceIp, InterfaceMode.L2, nextTableIndex, 0); verifyTableRequest(request, nextTableIndex, 0, true); } @@ -147,7 +146,7 @@ public class AceIp6WriterTest { final int nextTableIndex = 42; final int vlanTags = 1; final ClassifyAddDelTable request = - writer.createClassifyTable(action, aceIp, InterfaceMode.L3, nextTableIndex, vlanTags); + writer.createClassifyTable(aceIp, InterfaceMode.L3, nextTableIndex, vlanTags); verifyTableRequest(request, nextTableIndex, vlanTags, false); } @@ -156,7 +155,7 @@ public class AceIp6WriterTest { final int nextTableIndex = 42; final int vlanTags = 2; final ClassifyAddDelTable request = - writer.createClassifyTable(action, aceIp, InterfaceMode.L3, nextTableIndex, vlanTags); + writer.createClassifyTable(aceIp, InterfaceMode.L3, nextTableIndex, vlanTags); verifyTableRequest(request, nextTableIndex, vlanTags, false); } diff --git a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/IetfAclCustomizerTest.java b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/IetfAclCustomizerTest.java index e2c5f1c38..d25d6c329 100644 --- a/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/IetfAclCustomizerTest.java +++ b/v3po/v3po2vpp/src/test/java/io/fd/honeycomb/translate/v3po/interfaces/acl/ingress/IetfAclCustomizerTest.java @@ -17,6 +17,7 @@ package io.fd.honeycomb.translate.v3po.interfaces.acl.ingress; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.argThat; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -24,6 +25,7 @@ import com.google.common.base.Optional; import io.fd.honeycomb.translate.vpp.util.NamingContext; import io.fd.honeycomb.translate.write.WriteFailedException; import io.fd.honeycomb.vpp.test.write.WriterCustomizerTest; +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; @@ -31,15 +33,26 @@ 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 java.util.Arrays; import java.util.Collections; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mockito; 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.EthAcl; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.AccessListEntriesBuilder; +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.AceBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.ActionsBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.acl.access.list.entries.ace.MatchesBuilder; +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.Deny; 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.DenyBuilder; +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.actions.packet.handling.PermitBuilder; 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.AceIpBuilder; 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.AceIpv6Builder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; @@ -58,13 +71,16 @@ public class IetfAclCustomizerTest extends WriterCustomizerTest { private static final String IFC_TEST_INSTANCE = "ifc-test-instance"; private static final String IF_NAME = "local0"; private static final int IF_INDEX = 1; - private static final InstanceIdentifier<Ingress> IID = InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME)).augmentation( - VppInterfaceAugmentation.class).child(IetfAcl.class).child(Ingress.class); + private static final InstanceIdentifier<Ingress> IID = + InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME)).augmentation( + VppInterfaceAugmentation.class).child(IetfAcl.class).child(Ingress.class); private static final String ACL_NAME = "acl1"; private static final Class<? extends AclBase> ACL_TYPE = EthAcl.class; private IetfAclCustomizer customizer; private Ingress acl; + private int DENY = 0; + private int PERMIT = -1; @Override protected void setUp() { @@ -88,16 +104,7 @@ public class IetfAclCustomizerTest extends WriterCustomizerTest { when(writeContext.readAfter(any())).thenReturn(Optional.of( new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclBuilder() .setAccessListEntries( - new AccessListEntriesBuilder().setAce(Collections.singletonList( - new AceBuilder() - .setMatches(new MatchesBuilder().setAceType( - new AceIpBuilder() - .setAceIpVersion(new AceIpv6Builder().build()) - .setProtocol((short)1) - .build() - ).build()) - .setActions(new ActionsBuilder().setPacketHandling(new DenyBuilder().build()).build()) - .build() + new AccessListEntriesBuilder().setAce(Arrays.asList(ace(permit()), ace(permit()), ace(deny()) )).build() ).build() @@ -106,9 +113,75 @@ public class IetfAclCustomizerTest extends WriterCustomizerTest { customizer.writeCurrentAttributes(IID, acl, writeContext); - verify(api).classifyAddDelTable(any()); - verify(api).classifyAddDelSession(any()); - verify(api).inputAclSetInterface(inputAclSetInterfaceWriteRequest()); + final InOrder inOrder = Mockito.inOrder(api); + inOrder.verify(api).classifyAddDelTable(argThat(actionOnMissEquals(DENY))); // default action + inOrder.verify(api).classifyAddDelTable(any()); + inOrder.verify(api).classifyAddDelSession(argThat(actionOnHitEquals(DENY))); // last deny ACE + inOrder.verify(api).classifyAddDelTable(any()); + inOrder.verify(api).classifyAddDelSession(argThat(actionOnHitEquals(PERMIT))); + inOrder.verify(api).classifyAddDelTable(any()); + inOrder.verify(api).classifyAddDelSession(argThat(actionOnHitEquals(PERMIT))); + inOrder.verify(api).inputAclSetInterface(inputAclSetInterfaceWriteRequest()); // assignment + } + + private Matcher<ClassifyAddDelTable> actionOnMissEquals(final int action) { + return new BaseMatcher<ClassifyAddDelTable>() { + public Object item; + + @Override + public void describeTo(final Description description) { + description.appendText("Expected ClassifyAddDelTable[missNextIndex=" + action + "] but was " + item); + } + + @Override + public boolean matches(final Object item) { + this.item = item; + if (item instanceof ClassifyAddDelTable) { + return ((ClassifyAddDelTable) item).missNextIndex == action; + } + return false; + } + }; + } + + private Matcher<ClassifyAddDelSession> actionOnHitEquals(final int action) { + return new BaseMatcher<ClassifyAddDelSession>() { + public Object item; + + @Override + public void describeTo(final Description description) { + description.appendText("Expected ClassifyAddDelSession[hitNextIndex=" + action + "] but was " + item); + } + + @Override + public boolean matches(final Object item) { + this.item = item; + if (item instanceof ClassifyAddDelSession) { + return ((ClassifyAddDelSession) item).hitNextIndex == action; + } + return false; + } + }; + } + + private Deny deny() { + return new DenyBuilder().build(); + } + + private Permit permit() { + return new PermitBuilder().build(); + } + + private static Ace ace(final PacketHandling action) { + return new AceBuilder() + .setMatches(new MatchesBuilder().setAceType( + new AceIpBuilder() + .setAceIpVersion(new AceIpv6Builder().build()) + .setProtocol((short) 1) + .build() + ).build()) + .setActions(new ActionsBuilder().setPacketHandling(action).build()) + .build(); } @Test |