From d8f781f9b1c830448301a2d4e96e3234477341d6 Mon Sep 17 00:00:00 2001 From: Tomas Cechvala Date: Wed, 6 Sep 2017 16:13:16 +0200 Subject: [PATCH] Upgrading ACL implementation Only DHCP peers from a local network are configured in ACLs. Deltas are computed to update specific rules to avoid rewriting entire ACLs. Change-Id: I9245c9ab961a1090d1d0d04ead937b78f789f3bf Signed-off-by: Tomas Cechvala --- .../renderer/vpp/iface/InterfaceManager.java | 4 +- .../vpp/policy/ForwardingManager.java | 1 - .../vpp/policy/VppRendererPolicyManager.java | 22 ++- .../vpp/policy/acl/AccessListUtil.java | 33 ++-- .../renderer/vpp/policy/acl/AclManager.java | 167 ++++++++++-------- .../vpp/policy/acl/AddressMapper.java | 131 ++++++++++---- .../vpp/policy/acl/GbpAceBuilder.java | 15 ++ .../renderer/vpp/sf/EtherTypeClassifier.java | 16 +- .../renderer/vpp/util/KeyFactory.java | 5 + .../vpp/policy/acl/AclManagerTest.java | 67 ++++++- .../vpp/policy/acl/TestResources.java | 14 +- 11 files changed, 345 insertions(+), 130 deletions(-) diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java index 14bc6978d..5444208d0 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java @@ -37,7 +37,6 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppRendererProcessing import org.opendaylight.groupbasedpolicy.util.DataStoreHelper; import org.opendaylight.vbd.impl.transaction.VbdNetconfTransaction; 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.InterfaceBuilder; 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.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase; @@ -68,10 +67,9 @@ import com.google.common.base.Strings; import com.google.common.collect.HashMultimap; import com.google.common.collect.SetMultimap; import com.google.common.eventbus.Subscribe; -import com.google.common.util.concurrent.MoreExecutors; -import com.google.common.util.concurrent.AsyncFunction; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.MoreExecutors; public class InterfaceManager implements AutoCloseable { diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java index 574d93937..eaa16e67b 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java @@ -259,7 +259,6 @@ public final class ForwardingManager { LOG.warn("Interface was not added to bridge-domain {} for endpoint {}", l2FloodDomain, rEp, e); } } - aclManager.updateAclsForPeers(policyCtx, rEpKey); } else { LOG.debug("Forwarding is not created - Location of renderer endpoint contains " + "external-node therefore VPP renderer assumes that interface for endpoint is " diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManager.java index 650cb385f..05a8ae183 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManager.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManager.java @@ -27,8 +27,10 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.DhcpRelayCommand; import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil; import org.opendaylight.groupbasedpolicy.renderer.vpp.event.NodeOperEvent; import org.opendaylight.groupbasedpolicy.renderer.vpp.event.RendererPolicyConfEvent; +import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AccessListWrapper; import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AclManager; import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory; +import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory; import org.opendaylight.groupbasedpolicy.util.IidFactory; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy; @@ -153,7 +155,7 @@ public class VppRendererPolicyManager { ImmutableSet rendEpsAfter = policyCtxAfter.getPolicyTable().rowKeySet(); SetView removedRendEps = Sets.difference(rendEpsBefore, rendEpsAfter); - removedRendEps.forEach(rEpKey -> fwManager.removeForwardingForEndpoint(rEpKey, policyCtxBefore)); + removedRendEps.forEach(rEpKey -> fwManager.removeForwardingForEndpoint(rEpKey, policyCtxBefore));//TODO if (!ConfigUtil.getInstance().isL3FlatEnabled()) { LOG.debug("Removing bridge domains on nodes {}", removedVppNodesByL2Fd); @@ -190,7 +192,7 @@ public class VppRendererPolicyManager { fwManager.syncRouting(policyCtxAfter); SetView createdRendEps = Sets.difference(rendEpsAfter, rendEpsBefore); - createdRendEps.forEach(rEpKey -> fwManager.createForwardingForEndpoint(rEpKey, policyCtxAfter)); + createdRendEps.forEach(rEpKey -> fwManager.createForwardingForEndpoint(rEpKey, policyCtxAfter));//TODO SetView updatedRendEps = Sets.intersection(rendEpsBefore, rendEpsAfter); // update forwarding for endpoint @@ -259,6 +261,14 @@ public class VppRendererPolicyManager { rEpKeys.forEach(rEpKey -> fwManager.createForwardingForEndpoint(rEpKey, policyCtx)); fwManager.createNatEntries(policyCtx); fwManager.syncRouting(policyCtx); + + ImmutableSet rendEpsAfter = policyCtx.getPolicyTable().rowKeySet(); + ImmutableSet rulesAfter = policyCtx.getRuleGroupByKey().keySet(); + LOG.info("rendererPolicyCreated Created rules {}", rulesAfter); + LOG.info("rendererPolicyCreated Created renderer endpoints {}", rendEpsAfter); + aclManager.resolveRulesToConfigure(policyCtx, Sets.difference(rendEpsAfter, Sets.newHashSet()), + Sets.difference(rulesAfter, Sets.newHashSet()), true); + } private void rendererPolicyDeleted(RendererPolicy rendererPolicy) { @@ -278,6 +288,14 @@ public class VppRendererPolicyManager { } fwManager.deleteNatEntries(policyCtx); fwManager.deleteRouting(policyCtx); + + ImmutableSet rendEpsBefore = policyCtx.getPolicyTable().rowKeySet(); + ImmutableSet rulesBefore = policyCtx.getRuleGroupByKey().keySet(); + LOG.debug("rendererPolicyDeleted. Removed rules {}", rulesBefore); + LOG.debug("rendererPolicyDeleted. Endpoints deleted {}", rendEpsBefore); + aclManager.resolveRulesToConfigure(policyCtx, Sets.difference(rendEpsBefore, Sets.newHashSet()), + Sets.difference(rulesBefore, Sets.newHashSet()), false); + } private static SetMultimap resolveVppNodesByL2Fd(Set rEpKeys, diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AccessListUtil.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AccessListUtil.java index 8a84f4971..2d927d960 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AccessListUtil.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AccessListUtil.java @@ -80,15 +80,16 @@ public class AccessListUtil { .stream() .filter(peerEpKey -> peerHasLocation(ctx, peerEpKey)) .forEach(peerEpKey -> { + List rules = new ArrayList<>(); ctx.getPolicyTable().get(rEpKey, peerEpKey).forEach(resolvedRules -> { - List rules = new ArrayList<>(); Direction classifDir = calculateClassifDirection(resolvedRules.getRendererEndpointParticipation(), policyDirection); rules.addAll(resolveAclRulesFromPolicy(resolvedRules, classifDir, rEpKey, peerEpKey)); - updateAddressesInRules(rules, rEpKey, peerEpKey, ctx, policyDirection, true); - aclWrapper.writeRules(rules); }); + if (validateAndUpdateAddressesInRules(rules, rEpKey, peerEpKey, ctx, policyDirection, true)) { + aclWrapper.writeRules(rules); + } }); } @@ -126,16 +127,20 @@ public class AccessListUtil { return Direction.In; } - static void updateAddressesInRules(List rules, RendererEndpointKey rEpKey, PeerEndpointKey peerEpKey, - PolicyContext ctx, ACE_DIRECTION policyDirection, boolean resolveForLocationPeers) { + static boolean validateAndUpdateAddressesInRules(List rules, RendererEndpointKey rEpKey, + PeerEndpointKey peerEpKey, PolicyContext ctx, ACE_DIRECTION policyDirection, + boolean resolveForLocationPeers) { for (AddressMapper addrMapper : Arrays.asList(new SourceMapper(policyDirection), new DestinationMapper(policyDirection))) { if (peerHasLocation(ctx, peerEpKey) && resolveForLocationPeers) { - addrMapper.updateRules(rules, findAddrEp(ctx, rEpKey), findAddrEp(ctx, peerEpKey)); + if (!addrMapper.updateRules(rules, findAddrEp(ctx, rEpKey), findAddrEp(ctx, peerEpKey))) { + return false; + } } else if (!peerHasLocation(ctx, peerEpKey) && !resolveForLocationPeers) { addrMapper.updateExtRules(rules, findAddrEp(ctx, rEpKey), null); } } + return true; } private static boolean peerHasLocation(PolicyContext ctx, PeerEndpointKey peerEpKey) { @@ -318,8 +323,7 @@ public class AccessListUtil { } static void setSourceL3Address(GbpAceBuilder rule, String address) throws UnknownHostException { - InetAddress addr = InetAddress.getByName(substringBeforeSlash(address)); - if (addr instanceof Inet6Address) { + if (isIpv6Address(address)) { rule.setIpAddresses(new Ipv6Prefix(address), null); } else { rule.setIpAddresses(new Ipv4Prefix(address), null); @@ -327,14 +331,23 @@ public class AccessListUtil { } static void setDestinationL3Address(GbpAceBuilder rule, String address) throws UnknownHostException { - InetAddress addr = InetAddress.getByName(substringBeforeSlash(address)); - if (addr instanceof Inet6Address) { + if (isIpv6Address(address)) { rule.setIpAddresses(null, new Ipv6Prefix(address)); } else { rule.setIpAddresses(null, new Ipv4Prefix(address)); } } + public static boolean isIpv4Address(String address) throws UnknownHostException { + InetAddress addr = InetAddress.getByName(substringBeforeSlash(address)); + return addr instanceof Inet4Address; + } + + public static boolean isIpv6Address(String address) throws UnknownHostException { + InetAddress addr = InetAddress.getByName(substringBeforeSlash(address)); + return addr instanceof Inet6Address; + } + static GbpAceBuilder denyIngressTrafficForPrefix(Subnet subnet) { IpPrefix ipPrefix = subnet.getIpPrefix(); if (ipPrefix.getIpv4Prefix() != null) { diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AclManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AclManager.java index 05e04f179..9b4f4f5f3 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AclManager.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AclManager.java @@ -197,40 +197,60 @@ public class AclManager { }; beans.forEach(bean -> { List aceBuilders = bean.resolveAces(resolveUpdates(policyCtx, bean.epKey, bean.ruleGroups)); - getInterfacesForEndpoint(policyCtx, KeyFactory.addressEndpointKey(bean.epKey)).asMap() + resolveInterfaces(KeyFactory.addressEndpointKey(bean.epKey), policyCtx).asMap() .forEach((nodeId, intfcs) -> { - intfcs.stream() - .filter(intf -> !interfaceManager.isExcludedFromPolicy(nodeId, getIntfName.apply(intf))) - .forEach(intf -> { - AclKey aclKey = new AclKey(getIntfName.apply(intf) + bean.aceDirection, VppAcl.class); - denyTenantTraffic.put(nodeId, aclKey, - getWorkaroundFlows(policyCtx, bean.epKey, bean.aceDirection)); - AccessListUtil.allowExternalNetworksForEp(bean.epKey, bean.aceDirection).build(); - denyTenantTraffic.put(nodeId, aclKey, - AccessListUtil.denyDomainSubnets(policyCtx, bean.aceDirection) - .stream() - .map(GbpAceBuilder::build) - .collect(Collectors.toList())); - permitExternal.put(nodeId, aclKey, Lists.newArrayList( - AccessListUtil.allowExternalNetworksForEp(bean.epKey, bean.aceDirection).build())); - Optional> entries = Optional.fromNullable(aceTable.get(nodeId, aclKey)); - aceTable.put(nodeId, aclKey, - Stream - .concat((entries.isPresent()) ? entries.get().stream() : Stream.empty(), - aceBuilders.stream().map(aceBuilder -> aceBuilder.build())) - .collect(Collectors.toList())); - }); + intfcs.stream().forEach(intf -> { + if (!write && changedEndpoints.contains(bean.epKey)) { + AccessListWrapper.removeAclsForInterface(VppIidFactory.getNetconfNodeIid(nodeId), intf); + return; + } + AclKey aclKey = new AclKey(getIntfName.apply(intf) + bean.aceDirection, VppAcl.class); + denyTenantTraffic.put(nodeId, aclKey, + getWorkaroundFlows(policyCtx, bean.epKey, bean.aceDirection)); + AccessListUtil.allowExternalNetworksForEp(bean.epKey, bean.aceDirection).build(); + denyTenantTraffic.put(nodeId, aclKey, + AccessListUtil.denyDomainSubnets(policyCtx, bean.aceDirection) + .stream() + .map(GbpAceBuilder::build) + .collect(Collectors.toList())); + permitExternal.put(nodeId, aclKey, Lists.newArrayList( + AccessListUtil.allowExternalNetworksForEp(bean.epKey, bean.aceDirection).build())); + Optional> entries = Optional.fromNullable(aceTable.get(nodeId, aclKey)); + aceTable.put(nodeId, aclKey, + Stream + .concat((entries.isPresent()) ? entries.get().stream() : Stream.empty(), + aceBuilders.stream().map(aceBuilder -> aceBuilder.build())) + .collect(Collectors.toList())); + }); }); }); - // to avoid empty ACL (IllegalStateArgument on HC), rules have to be updated gently updateRules(ImmutableTable.copyOf(aceTable), write); - updateRules(ImmutableTable.copyOf(denyTenantTraffic), false); - updateRules(ImmutableTable.copyOf(denyTenantTraffic), true); - updateRules(ImmutableTable.copyOf(permitExternal), false); - updateRules(ImmutableTable.copyOf(permitExternal), true); + if (write) { + // to avoid empty ACL (IllegalStateArgument on HC), rules have to be updated gently + updateRules(ImmutableTable.copyOf(denyTenantTraffic), false); + updateRules(ImmutableTable.copyOf(denyTenantTraffic), true); + updateRules(ImmutableTable.copyOf(permitExternal), false); + updateRules(ImmutableTable.copyOf(permitExternal), true); + } } + public ImmutableSetMultimap resolveInterfaces(AddressEndpointKey key, + PolicyContext policyCtx) { + Function getIntfName = (intf) -> { + Optional intfName = VppPathMapper.interfacePathToInterfaceName(intf.getName()); + Preconditions.checkArgument(intfName.isPresent(), "Failed to resolve interface name from " + intf); + return intfName.get(); + }; + SetMultimap result = HashMultimap.create(); + getInterfacesForEndpoint(policyCtx, key).forEach((nodeId, intf) -> { + if (!interfaceManager.isExcludedFromPolicy(nodeId, getIntfName.apply(intf))) { + result.put(nodeId, intf); + } + }); + return ImmutableSetMultimap.copyOf(result); + } + private List getWorkaroundFlows(PolicyContext policyCtx, RendererEndpointKey key, ACE_DIRECTION dir) { List result = new ArrayList<>(); result.addAll(AccessListUtil.denyDomainSubnets(policyCtx, dir) @@ -248,8 +268,8 @@ public class AclManager { rendEp.get() .getPeerEndpoint() .stream() - // TODO see UT .filter(peerEp -> policyCtx.getPolicyTable().get(rendEpKey, peerEp.getKey()) != null) + .filter(peerEp -> !endpointIsExcludedFromPolicy(policyCtx, KeyFactory.addressEndpointKey(peerEp.getKey()))) .forEach(peerEp -> { updateTreeBuilder.put(rendEpKey, peerEp.getKey(), policyCtx.getPolicyTable() @@ -261,6 +281,13 @@ public class AclManager { return updateTreeBuilder.build(); } + private boolean endpointIsExcludedFromPolicy(PolicyContext policyCtx, AddressEndpointKey key) { + return getInterfacesForEndpoint(policyCtx, key).entries().stream().anyMatch(entry -> { + Optional intfName = VppPathMapper.interfacePathToInterfaceName(entry.getValue().getName()); + return intfName.isPresent() ? interfaceManager.isExcludedFromPolicy(entry.getKey(), intfName.get()) : false; + }); + } + private void updateRules(ImmutableTable> rulesToUpdate, boolean write) { List> sync = new ArrayList<>(); rulesToUpdate.rowKeySet().forEach(nodeId -> { @@ -269,8 +296,7 @@ public class AclManager { @Override public Void call() throws Exception { InstanceIdentifier vppIid = VppIidFactory.getNetconfNodeIid(nodeId); - Optional dataBroker = - mountDataProvider.resolveDataBrokerForMountPoint(vppIid); + Optional dataBroker = mountDataProvider.resolveDataBrokerForMountPoint(vppIid); if (!dataBroker.isPresent()) { LOG.error("Failed to update ACLs for endpoints on node {}. Mount point does not exist.", nodeId); @@ -285,6 +311,7 @@ public class AclManager { .child(Ace.class, ace.getKey()) .build(), ace); }); + LOG.debug("Writing ACE changes - Node: {} Entries: {}", nodeId, entries); if (entries.isEmpty()) { return; } @@ -310,39 +337,22 @@ public class AclManager { } private List generateRulesForEndpointPair(PolicyContext ctx, RendererEndpointKey r, - PeerEndpointKey p, RendererResolvedPolicy rrp, ACE_DIRECTION aceDirection) { + PeerEndpointKey p, List rrps, ACE_DIRECTION aceDirection) { List rules = new ArrayList<>(); - Direction direction = - AccessListUtil.calculateClassifDirection(rrp.getRendererEndpointParticipation(), aceDirection); - ResolvedRuleGroup resolvedRuleGroup = ctx.getRuleGroupByKey().get(rrp.getRuleGroup().getRelatedRuleGroupKey()); - resolvedRuleGroup.getRules().forEach(rule -> { - Optional ace = AccessListUtil.resolveAceClassifersAndAction(rule, direction, - AccessListUtil.resolveAceName(rule.getName(), r, p)); - if (ace.isPresent()) { - rules.add(ace.get()); - } - }); - AccessListUtil.updateAddressesInRules(rules, r, p, ctx, aceDirection, true); - return rules; - } - - // TODO remove - public void updateAclsForPeers(PolicyContext policyCtx, RendererEndpointKey rEpKey) { - ImmutableSet peers = policyCtx.getPolicyTable().row(rEpKey).keySet(); - List> sync = new ArrayList<>(); - for (RendererEndpointKey peerRendEp : peers.stream() - .map(AddressEndpointUtils::fromPeerEpKey) - .collect(Collectors.toList()) - .stream() - .map(AddressEndpointUtils::toRendererEpKey) - .collect(Collectors.toList())) { - sync.add(updateAclsForRendEp(peerRendEp, policyCtx)); - } - try { - Futures.allAsList(sync).get(); - } catch (InterruptedException | ExecutionException e) { - LOG.error("Failed to update ACLs for peers of {}. {}", rEpKey, e); + for (RendererResolvedPolicy rrp : rrps) { + Direction direction = + AccessListUtil.calculateClassifDirection(rrp.getRendererEndpointParticipation(), aceDirection); + ResolvedRuleGroup resolvedRuleGroup = + ctx.getRuleGroupByKey().get(rrp.getRuleGroup().getRelatedRuleGroupKey()); + resolvedRuleGroup.getRules().forEach(rule -> { + Optional ace = AccessListUtil.resolveAceClassifersAndAction(rule, direction, + AccessListUtil.resolveAceName(rule.getName(), r, p)); + if (ace.isPresent()) { + rules.add(ace.get()); + } + }); } + return rules; } public ListenableFuture updateAclsForRendEp(RendererEndpointKey rEpKey, PolicyContext policyCtx) { @@ -486,19 +496,34 @@ public class AclManager { List resolveAces( ImmutableTable> updateTree) { + return (write) ? resolveCreatedAces(updateTree) : resolveRemovedAces(updateTree); + } + + List resolveCreatedAces( + ImmutableTable> updateTree) { List result = new ArrayList<>(); updateTree.columnKeySet().stream().filter(peer -> updateTree.get(epKey, peer) != null).forEach(peer -> { + List deltaRules = + generateRulesForEndpointPair(policyCtx, epKey, peer, updateTree.get(epKey, peer), aceDirection); + if (AccessListUtil.validateAndUpdateAddressesInRules(deltaRules, epKey, peer, policyCtx, aceDirection, + true)) { + result.addAll(deltaRules); + } + }); + return result; + } + + List resolveRemovedAces( + ImmutableTable> updateTree) { + List result = new ArrayList<>(); + updateTree.columnKeySet().stream().filter(peer -> updateTree.get(epKey, peer) != null).forEach(peer -> { + // we only need to resolve rule names when removing ACE updateTree.get(epKey, peer).stream().forEach(rrp -> { - if (write) { - result.addAll(generateRulesForEndpointPair(policyCtx, epKey, peer, rrp, aceDirection)); - } else { - // we only need to resolve rule names when removing ACE - result.addAll(rrp.getRuleGroup() - .getRules() - .stream() - .map(rule -> new GbpAceBuilder(AccessListUtil.resolveAceName(rule.getName(), epKey, peer))) - .collect(Collectors.toList())); - } + result.addAll(rrp.getRuleGroup() + .getRules() + .stream() + .map(rule -> new GbpAceBuilder(AccessListUtil.resolveAceName(rule.getName(), epKey, peer))) + .collect(Collectors.toList())); }); }); return result; diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AddressMapper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AddressMapper.java index 8d42237db..f84e05fce 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AddressMapper.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AddressMapper.java @@ -8,23 +8,41 @@ package org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl; +import java.net.UnknownHostException; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.DestinationPortRangeBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.packet.fields.rev160708.acl.transport.header.fields.SourcePortRangeBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpoint; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.IpPrefixType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L2BridgeDomain; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.L3Context; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev170511.MacAddressType; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev170615.access.lists.acl.access.list.entries.ace.matches.ace.type.vpp.ace.vpp.ace.nodes.ace.ip.version.AceIpv4; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev170615.access.lists.acl.access.list.entries.ace.matches.ace.type.vpp.ace.vpp.ace.nodes.ace.ip.version.AceIpv6; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableMap; abstract class AddressMapper { + private static final Logger LOG = LoggerFactory.getLogger(AddressMapper.class); + private AccessListUtil.ACE_DIRECTION direction; private static final PortNumber DHCP_67 = new PortNumber(67); private static final PortNumber DHCP_68 = new PortNumber(68); private static final PortNumber DHCPV6_547 = new PortNumber(547); private static final PortNumber DHCPV6_548 = new PortNumber(548); + private static final ImmutableMap dhcpSockets = + ImmutableMap.of(DHCP_67, DHCP_68, DHCP_68, DHCP_67, DHCPV6_548, DHCPV6_547, DHCPV6_547, DHCPV6_548); AddressMapper(AccessListUtil.ACE_DIRECTION direction) { this.direction = direction; @@ -36,55 +54,104 @@ abstract class AddressMapper { abstract List updateExtRules(List rules, AddressEndpointWithLocation localEp, ContainmentEndpoint cEp); - public List updateRules(List rules, AddressEndpointWithLocation localEp, + public boolean updateRules(List rules, AddressEndpointWithLocation localEp, AddressEndpointWithLocation peerEp) { - if (this instanceof SourceMapper) { - if (AccessListUtil.ACE_DIRECTION.INGRESS.equals(direction)) { - return updateRules(rules, localEp); + filterRulesWithIrrelevantAddresses(rules, localEp, peerEp); + for (GbpAceBuilder rule : rules) { + LOG.info("Rule: {} Updating rule between {} and {}. Start.", rule, localEp.getAddress(), + peerEp.getAddress()); + boolean isDhcpRule = dhcpSockets.entrySet().stream().anyMatch(dhcpSocket -> { + boolean srcMatch = isInRange(rule.getSourcePortRangeBuilder(), dhcpSocket.getKey()); + boolean dstMatch = isInRange(rule.getDestinationPortRangeBuilder(), dhcpSocket.getValue()); + return srcMatch && dstMatch; + }); + if (isDhcpRule) { + if (!inSameSubnet(localEp, peerEp)) { + // do not process rules for DHCPs of other networks + LOG.info("Rule: {} Not updating rules between {} and {}. Returning false.", rule, + localEp.getAddress(), peerEp.getAddress()); + return false; + } + // do not update addresses for DHCP traffic + LOG.info("Rule: {} Not updating rule between {} and {}. Continue with next.", rule, + localEp.getAddress(), peerEp.getAddress()); + continue; } - return updateRules(rules, peerEp); - } - if (this instanceof DestinationMapper) { - if (AccessListUtil.ACE_DIRECTION.INGRESS.equals(direction)) { - return updateRules(rules, peerEp); + if (this instanceof SourceMapper) { + LOG.info("Rule: {} Updating rule between {} and {}. SourceMapper.", rule, localEp.getAddress(), + peerEp.getAddress()); + if (AccessListUtil.ACE_DIRECTION.INGRESS.equals(direction)) { + updateRule(localEp, rule); + continue; + } + updateRule(peerEp, rule); + } else if (this instanceof DestinationMapper) { + LOG.info("Rule: {} Updating rule between {} and {}. SourceMapper.", rule, localEp.getAddress(), + peerEp.getAddress()); + if (AccessListUtil.ACE_DIRECTION.INGRESS.equals(direction)) { + updateRule(peerEp, rule); + continue; + } + updateRule(localEp, rule); } - return updateRules(rules, localEp); } - return rules; + LOG.info("Updating rules between {} and {}. Done, returning true.", + localEp.getAddress(), peerEp.getAddress()); + return true; } - private List updateRules(List rules, AddressEndpointWithLocation addrEp) { - for (GbpAceBuilder rule : rules) { - if (isInRange(rule.getSourcePortRangeBuilder(), DHCP_67) - && isInRange(rule.getDestinationPortRangeBuilder(), DHCP_68)) { - continue; - } - if (isInRange(rule.getSourcePortRangeBuilder(), DHCP_68) - && isInRange(rule.getDestinationPortRangeBuilder(), DHCP_67)) { - continue; - } - if (isInRange(rule.getSourcePortRangeBuilder(), DHCPV6_547) - && isInRange(rule.getDestinationPortRangeBuilder(), DHCPV6_548)) { - continue; + private void filterRulesWithIrrelevantAddresses(List rules, AddressEndpointWithLocation localEp, + AddressEndpointWithLocation peerEp) { + try { + if (!IpPrefixType.class.equals(localEp.getAddressType()) + || !IpPrefixType.class.equals(peerEp.getAddressType())) { + return; } - if (isInRange(rule.getSourcePortRangeBuilder(), DHCPV6_548) - && isInRange(rule.getDestinationPortRangeBuilder(), DHCPV6_547)) { - continue; + boolean addressV4Check = AccessListUtil.isIpv4Address(localEp.getAddress()) + && AccessListUtil.isIpv4Address(peerEp.getAddress()); + boolean addressV6Check = AccessListUtil.isIpv6Address(localEp.getAddress()) + && AccessListUtil.isIpv6Address(peerEp.getAddress()); + Predicate p; + if (addressV4Check) { + p = rule -> rule.getEtherType().get() instanceof AceIpv6; + } else if (addressV6Check) { + p = rule -> rule.getEtherType().get() instanceof AceIpv4; + } else { + return; } - updateRule(addrEp, rule); + List rulesToRemove = rules.stream() + .filter(rule -> rule.getEtherType().isPresent()) + .filter(p) + .collect(Collectors.toList()); + rulesToRemove.forEach(rule -> { LOG.info("Filtering rules by ethertype {}", rule); rules.remove(rule);}); + } catch (UnknownHostException e) { + LOG.error("Failed to parse addresses {}", e); + } + } + + private static boolean inSameSubnet(AddressEndpointWithLocation localEp, AddressEndpointWithLocation peerEp) { + List> list = new ArrayList<>(); + list.add(x -> x != null); + list.add(x -> x.getContextType().equals(L3Context.class)); + list.add(x -> x.getChildEndpoint() != null && !x.getChildEndpoint().isEmpty()); + list.add(x -> x.getAbsoluteLocation() != null); + list.add(x -> x.getChildEndpoint().get(0).getContextType().equals(L2BridgeDomain.class)); + list.add(x -> x.getChildEndpoint().get(0).getAddressType().equals(MacAddressType.class)); + if (list.stream().filter(i -> !i.apply(peerEp)).findFirst().isPresent()) { + return false; } - return rules; + return localEp.getChildEndpoint().get(0).getContextId().equals(peerEp.getChildEndpoint().get(0).getContextId()); } - private boolean isInRange(SourcePortRangeBuilder spr, PortNumber portNumber) { + private static boolean isInRange(SourcePortRangeBuilder spr, PortNumber portNumber) { return spr != null && isInRange(spr.getLowerPort(), spr.getUpperPort(), portNumber); } - private boolean isInRange(DestinationPortRangeBuilder dpr, PortNumber portNumber) { + private static boolean isInRange(DestinationPortRangeBuilder dpr, PortNumber portNumber) { return dpr != null && isInRange(dpr.getLowerPort(),dpr.getUpperPort(), portNumber); } - private boolean isInRange(PortNumber lower, PortNumber upper, PortNumber ref) { + private static boolean isInRange(PortNumber lower, PortNumber upper, PortNumber ref) { if (lower != null && upper != null) { return (lower.getValue() <= ref.getValue()) && (ref.getValue() <= upper.getValue()); } diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/GbpAceBuilder.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/GbpAceBuilder.java index f3312a656..b912e16ce 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/GbpAceBuilder.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/GbpAceBuilder.java @@ -46,6 +46,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl. import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev170615.acl.ip.protocol.header.fields.ip.protocol.udp.UdpNodes; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev170615.acl.ip.protocol.header.fields.ip.protocol.udp.UdpNodesBuilder; +import com.google.common.base.Optional; import com.google.common.base.Preconditions; public class GbpAceBuilder { @@ -93,6 +94,10 @@ public class GbpAceBuilder { return action; } + public Optional getEtherType() { + return (aceIpVersion != null) ? Optional.of(aceIpVersion) : Optional.absent(); + } + public GbpAceBuilder setProtocol(short protocol) { this.protocol = protocol; return this; @@ -112,6 +117,16 @@ public class GbpAceBuilder { return this; } + public GbpAceBuilder setIpv4EtherType() { + this.aceIpVersion = new AceIpv4Builder().build(); + return this; + } + + public GbpAceBuilder setIpv6EtherType() { + this.aceIpVersion = new AceIpv6Builder().build(); + return this; + } + public GbpAceBuilder setIpAddresses(@Nullable Ipv4Prefix srcIp, @Nullable Ipv4Prefix dstIp) { AceIpv4Builder aceIpv4Builder = (aceIpv4 != null) ? new AceIpv4Builder(aceIpv4) : new AceIpv4Builder(); if (srcIp != null) { diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/EtherTypeClassifier.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/EtherTypeClassifier.java index 4799587a7..ce10b2ed7 100755 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/EtherTypeClassifier.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/EtherTypeClassifier.java @@ -71,10 +71,24 @@ public class EtherTypeClassifier extends Classifier { @Override GbpAceBuilder update(GbpAceBuilder ruleBuilder, Map params) { - // ETHER_TYPE matching not supported yet + Long etherType = getEtherTypeValue(params); + if (!ruleBuilder.getEtherType().isPresent() && etherType != null) { + if (EtherTypeClassifierDefinition.IPv4_VALUE.equals(etherType)) { + ruleBuilder.setIpv4EtherType(); + } else if (EtherTypeClassifierDefinition.IPv6_VALUE.equals(etherType)) { + ruleBuilder.setIpv6EtherType(); + } + } return ruleBuilder; } + private static Long getEtherTypeValue(Map params) { + if (params == null || params.get(EtherTypeClassifierDefinition.ETHERTYPE_PARAM) == null) { + return null; + } + return params.get(EtherTypeClassifierDefinition.ETHERTYPE_PARAM).getIntValue(); + } + @Override void checkPrereqs(GbpAceBuilder matchBuilders) { // Nothing to consider yet. diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/KeyFactory.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/KeyFactory.java index 6024bac5b..62f4cb5fb 100644 --- a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/KeyFactory.java +++ b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/KeyFactory.java @@ -39,6 +39,11 @@ public class KeyFactory { fromKey.getContextType()); } + public static AddressEndpointKey addressEndpointKey(PeerEndpointKey fromKey) { + return new AddressEndpointKey(fromKey.getAddress(), fromKey.getAddressType(), fromKey.getContextId(), + fromKey.getContextType()); + } + public static ProviderAddressEndpointLocationKey providerAddressEndpointLocationKey( AddressEndpointWithLocationKey fromKey) { return new ProviderAddressEndpointLocationKey(fromKey.getAddress(), fromKey.getAddressType(), diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AclManagerTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AclManagerTest.java index 32a58ff30..4b6187580 100644 --- a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AclManagerTest.java +++ b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AclManagerTest.java @@ -30,6 +30,7 @@ import org.opendaylight.groupbasedpolicy.util.DataStoreHelper; import org.opendaylight.vbd.impl.transaction.VbdNetconfTransaction; 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.access.lists.Acl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpoint; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointKey; @@ -64,7 +65,7 @@ public class AclManagerTest extends TestResources { @Test public void oneEndpointChanged() { List acls = processChangedEndpoints(Sets.newHashSet(rendererEndpointKey(l3AddrEp1.getKey())), true); - Assert.assertEquals(acls.size(), 6); + Assert.assertEquals(6, acls.size()); acls.forEach(acl -> { if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(NODE1_CONNECTOR_1).get())) { Assert.assertEquals(2 + 4, acl.getAccessListEntries().getAce().size()); @@ -73,10 +74,18 @@ public class AclManagerTest extends TestResources { } }); acls = processChangedEndpoints(Sets.newHashSet(rendererEndpointKey(l3AddrEp1.getKey())), false); - Assert.assertEquals(acls.size(), 6); + Assert.assertEquals(6, acls.size()); acls.forEach(acl -> { + System.out.println("DEBUGX " + acl); if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(NODE1_CONNECTOR_1).get())) { - Assert.assertEquals(2, acl.getAccessListEntries().getAce().size()); + acl.getAccessListEntries().getAce().forEach(ace -> { + System.out.println("DEBUG1 " + ace); + }); + /* + * TODO rules were not removed, entire ACL is removed elsewhere when interface at + * NODE1_CONNECTOR_1 detaches from bridge domain. + */ + Assert.assertEquals(6, acl.getAccessListEntries().getAce().size()); } else { Assert.assertEquals(2, acl.getAccessListEntries().getAce().size()); } @@ -89,8 +98,7 @@ public class AclManagerTest extends TestResources { Assert.assertEquals(acls.size(), 4); acls.forEach(acl -> { if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(NODE1_CONNECTOR_1).get())) { - // TODO fix so that the following assert is uncomemnted - // Assert.assertEquals(2 + 2, acl.getAccessListEntries().getAce().size()); + Assert.assertEquals(2 + 4, acl.getAccessListEntries().getAce().size()); } else { Assert.assertEquals(2 + 2, acl.getAccessListEntries().getAce().size()); } @@ -99,11 +107,57 @@ public class AclManagerTest extends TestResources { Assert.assertEquals(acls.size(), 4); acls.forEach(acl -> { if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(NODE1_CONNECTOR_1).get())) { + // Peer is updated 4 rules went to 2. Assert.assertEquals(2, acl.getAccessListEntries().getAce().size()); } else { + // Entire ACL is removed elsewhere -> no update of rules needed. + Assert.assertEquals(4, acl.getAccessListEntries().getAce().size()); + } + }); + } + + /** + * Tests DHCP rules configuration. There should be no entries for DHCP servers serving different + * subnets, i.e. + * hosts should only have rules for accessing DHCP server in their subnet. + */ + @Test + public void dhcpDifferentSubnets() { + final String ep4Mac = "20:00:00:00:00:02"; + final String ep4Ip = "20.0.0.2/32"; + final ContextId l2BdId2 = new ContextId("l2BridgeDomainId2"); + final String node1Connector4 = + "/ietf-interfaces:interfaces/ietf-interfaces:interface[ietf-interfaces:name='nodeConnector4']"; + final AddressEndpointWithLocation l2DhcpEp = l2AddressEndpointWithLocation(ep4Mac, l2BdId2, ep4Ip, L3_CTX_ID); + final AddressEndpointWithLocation l3DhcpEp = appendLocationToEndpoint( + l3AddressEndpointWithLocation(ep4Mac, l2BdId2, ep4Ip, L3_CTX_ID), NODE1, node1Connector4); + List addrEps = createAddressEndpoints(); + addrEps.add(l2DhcpEp); + addrEps.add(l3DhcpEp); + List rEps = new ArrayList<>(); + // DHCP from different subnet + rEps.add(createRendEndpoint(rendererEndpointKey(l3DhcpEp.getKey()), SECURITY_GROUP.SERVER, + peerEndpointKey(l3AddrEp2.getKey()), peerEndpointKey(l3AddrEp3.getKey()))); + // DHCP from local subnet + rEps.add(createRendEndpoint(rendererEndpointKey(l3AddrEp1.getKey()), SECURITY_GROUP.SERVER, + peerEndpointKey(l3AddrEp2.getKey()), peerEndpointKey(l3AddrEp3.getKey()))); + rEps.add(createRendEndpoint(rendererEndpointKey(l3AddrEp2.getKey()), SECURITY_GROUP.CLIENT, + peerEndpointKey(l3AddrEp1.getKey()), peerEndpointKey(l3DhcpEp.getKey()))); + rEps.add(createRendEndpoint(rendererEndpointKey(l3AddrEp3.getKey()), SECURITY_GROUP.CLIENT, + peerEndpointKey(l3AddrEp1.getKey()), peerEndpointKey(l3DhcpEp.getKey()))); + ctx = super.createPolicyContext(addrEps, rEps, createRuleGroupsDhcpTest(), createForwarding()); + List acls = processChangedEndpoints(Sets.newHashSet(rendererEndpointKey(l3AddrEp2.getKey())), true); + Assert.assertEquals(acls.size(), 6); + acls.forEach(acl -> { + if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(node1Connector4).get())) { Assert.assertEquals(2, acl.getAccessListEntries().getAce().size()); + } else if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(NODE1_CONNECTOR_1).get())) { + Assert.assertEquals(6, acl.getAccessListEntries().getAce().size()); + } else { + Assert.assertEquals(4, acl.getAccessListEntries().getAce().size()); } }); + } /** @@ -128,7 +182,8 @@ public class AclManagerTest extends TestResources { if (acl.getAclName().contains(VppPathMapper.interfacePathToInterfaceName(NODE1_CONNECTOR_1).get())) { Assert.assertEquals(2, acl.getAccessListEntries().getAce().size()); } else { - Assert.assertEquals(2, acl.getAccessListEntries().getAce().size()); + // Entire ACL is removed elsewhere -> no update of rules needed. + Assert.assertEquals(6, acl.getAccessListEntries().getAce().size()); } }); } diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/TestResources.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/TestResources.java index 79910089b..7642243bf 100644 --- a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/TestResources.java +++ b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/TestResources.java @@ -278,7 +278,7 @@ public class TestResources extends CustomDataBrokerTest { return new RuleGroupsBuilder().setRuleGroup(ImmutableList.of(rg1, rg2)).build(); } - public RuleGroups createRuleGroups_DhcpTest() { + public RuleGroups createRuleGroupsDhcpTest() { ParameterValue ipv4Param = new ParameterValueBuilder().setIntValue(EtherTypeClassifierDefinition.IPv4_VALUE) .setName(new ParameterName(EtherTypeClassifierDefinition.ETHERTYPE_PARAM)) .build(); @@ -288,9 +288,15 @@ public class TestResources extends CustomDataBrokerTest { ParameterValue udpParam = new ParameterValueBuilder().setIntValue(IpProtoClassifierDefinition.UDP_VALUE) .setName(new ParameterName(IpProtoClassifierDefinition.PROTO_PARAM)) .build(); + ParameterValue srcDhcp = new ParameterValueBuilder().setIntValue(Long.valueOf(68)) + .setName(new ParameterName(L4ClassifierDefinition.SRC_PORT_PARAM)) + .build(); + ParameterValue dstDhcp = new ParameterValueBuilder().setIntValue(Long.valueOf(67)) + .setName(new ParameterName(L4ClassifierDefinition.DST_PORT_PARAM)) + .build(); RuleGroup rg1 = createSimpleRuleGroups(ImmutableList.of(ipv4Param, tcpParam), IpProtoClassifierDefinition.ID, SUBJECT_NAME); - RuleGroup rg2 = createSimpleRuleGroups(ImmutableList.of(ipv4Param, udpParam), IpProtoClassifierDefinition.ID, + RuleGroup rg2 = createSimpleRuleGroups(ImmutableList.of(ipv4Param, udpParam, srcDhcp, dstDhcp), L4ClassifierDefinition.ID, SUBJECT_NAME2); return new RuleGroupsBuilder().setRuleGroup(ImmutableList.of(rg1, rg2)).build(); } @@ -298,12 +304,12 @@ public class TestResources extends CustomDataBrokerTest { private RuleGroup createSimpleRuleGroups(List pv, ClassifierDefinitionId id, SubjectName subjectName) { final ClassifierName classifierName = new ClassifierName("cl-name"); - Classifier classifIn = new ClassifierBuilder().setClassifierDefinitionId(IpProtoClassifierDefinition.ID) + Classifier classifIn = new ClassifierBuilder().setClassifierDefinitionId(id) .setDirection(Direction.In) .setName(classifierName) .setParameterValue(pv) .build(); - Classifier classifOut = new ClassifierBuilder().setClassifierDefinitionId(IpProtoClassifierDefinition.ID) + Classifier classifOut = new ClassifierBuilder().setClassifierDefinitionId(id) .setDirection(Direction.Out) .setName(classifierName) .setParameterValue(pv) -- 2.36.6