2 * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.aclservice;
10 import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
12 import com.google.common.collect.Lists;
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.HashSet;
19 import java.util.List;
21 import java.util.Map.Entry;
23 import java.util.SortedSet;
24 import java.util.concurrent.ConcurrentMap;
25 import java.util.stream.Collectors;
26 import org.eclipse.jdt.annotation.Nullable;
27 import org.opendaylight.genius.mdsalutil.ActionInfo;
28 import org.opendaylight.genius.mdsalutil.FlowEntity;
29 import org.opendaylight.genius.mdsalutil.InstructionInfo;
30 import org.opendaylight.genius.mdsalutil.MDSALUtil;
31 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
32 import org.opendaylight.genius.mdsalutil.NwConstants;
33 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack;
34 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack.NxCtAction;
35 import org.opendaylight.genius.mdsalutil.actions.ActionNxCtClear;
36 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
37 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
38 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
39 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
40 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
41 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchCtState;
42 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
43 import org.opendaylight.mdsal.binding.api.DataBroker;
44 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
45 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
46 import org.opendaylight.netvirt.aclservice.api.AclInterfaceCache;
47 import org.opendaylight.netvirt.aclservice.api.AclServiceListener;
48 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.Action;
49 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
50 import org.opendaylight.netvirt.aclservice.utils.AclConntrackClassifierType;
51 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
52 import org.opendaylight.netvirt.aclservice.utils.AclDataUtil;
53 import org.opendaylight.netvirt.aclservice.utils.AclServiceOFFlowBuilder;
54 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.Matches;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.AceIp;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.ace.matches.ace.type.ace.ip.ace.ip.version.AceIpv4;
60 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionIngress;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl.InterfaceType;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.SubnetInfo;
70 import org.opendaylight.yangtools.yang.common.Uint64;
71 import org.slf4j.Logger;
72 import org.slf4j.LoggerFactory;
74 public abstract class AbstractAclServiceImpl implements AclServiceListener {
76 private static final Logger LOG = LoggerFactory.getLogger(AbstractAclServiceImpl.class);
78 protected final IMdsalApiManager mdsalManager;
79 protected final ManagedNewTransactionRunner txRunner;
80 protected final Class<? extends ServiceModeBase> serviceMode;
81 protected final AclDataUtil aclDataUtil;
82 protected final AclServiceUtils aclServiceUtils;
83 protected final JobCoordinator jobCoordinator;
84 protected final AclInterfaceCache aclInterfaceCache;
86 protected final Class<? extends DirectionBase> direction;
87 protected final String directionString;
90 * Initialize the member variables.
92 * @param serviceMode the service mode
93 * @param dataBroker the data broker instance.
94 * @param mdsalManager the mdsal manager instance.
95 * @param aclDataUtil the acl data util.
96 * @param aclServiceUtils the acl service util.
97 * @param jobCoordinator the job coordinator
98 * @param aclInterfaceCache the acl interface cache
100 public AbstractAclServiceImpl(Class<? extends ServiceModeBase> serviceMode, DataBroker dataBroker,
101 IMdsalApiManager mdsalManager, AclDataUtil aclDataUtil, AclServiceUtils aclServiceUtils,
102 JobCoordinator jobCoordinator, AclInterfaceCache aclInterfaceCache) {
103 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
104 this.mdsalManager = mdsalManager;
105 this.serviceMode = serviceMode;
106 this.aclDataUtil = aclDataUtil;
107 this.aclServiceUtils = aclServiceUtils;
108 this.jobCoordinator = jobCoordinator;
109 this.aclInterfaceCache = aclInterfaceCache;
112 this.serviceMode.equals(ServiceModeEgress.class) ? DirectionIngress.class : DirectionEgress.class;
113 this.directionString = this.direction.equals(DirectionEgress.class) ? "Egress" : "Ingress";
117 public boolean applyAcl(AclInterface port) {
119 LOG.error("port cannot be null");
122 BigInteger dpId = port.getDpId();
123 String portId = port.getInterfaceId();
124 if (dpId == null || port.getLPortTag() == null) {
125 LOG.error("Unable to find DpId from ACL interface with id {}", portId);
129 LOG.debug("Applying ACL on port {} with DpId {}", port, dpId);
130 List<FlowEntity> flowEntries = new ArrayList<>();
131 if (port.getInterfaceType() == InterfaceType.DhcpService) {
132 programDhcpService(flowEntries, port, Action.ADD, NwConstants.ADD_FLOW);
134 if (port.getSecurityGroups() == null) {
135 LOG.info("Port {} without SGs", portId);
138 programAclWithAllowedAddress(flowEntries, port, port.getAllowedAddressPairs(),
139 Action.ADD, NwConstants.ADD_FLOW);
140 updateRemoteAclFilterTable(port, NwConstants.ADD_FLOW);
142 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + portId, flowEntries, NwConstants.ADD_FLOW);
147 public boolean bindAcl(AclInterface port) {
149 LOG.error("Port cannot be null for binding ACL service");
157 public boolean unbindAcl(AclInterface port) {
159 LOG.error("Port cannot be null for unbinding ACL service");
162 if (port.getDpId() != null) {
169 public boolean updateAcl(AclInterface portBefore, AclInterface portAfter) {
170 // this check is to avoid situations of port update coming before interface state is up
171 if (portAfter.getDpId() == null || portAfter.getLPortTag() == null) {
172 LOG.debug("Unable to find DpId from ACL interface with id {} and lport {}", portAfter.getInterfaceId(),
173 portAfter.getLPortTag());
176 boolean result = true;
177 boolean isPortSecurityEnable = portAfter.isPortSecurityEnabled();
178 boolean isPortSecurityEnableBefore = portBefore.isPortSecurityEnabled();
179 // if port security is changed, apply/remove Acls
180 if (isPortSecurityEnableBefore != isPortSecurityEnable) {
181 LOG.debug("On ACL update, Port security is {} for {}", isPortSecurityEnable ? "Enabled" :
182 "Disabled", portAfter.getInterfaceId());
183 if (isPortSecurityEnable) {
184 result = applyAcl(portAfter);
186 result = removeAcl(portBefore);
188 } else if (isPortSecurityEnable) {
189 // Acls has been updated, find added/removed Acls and act accordingly.
190 processInterfaceUpdate(portBefore, portAfter);
191 LOG.debug("On ACL update, ACL has been updated for {}", portAfter.getInterfaceId());
192 } else if (portAfter.getInterfaceType() == InterfaceType.DhcpService) {
193 processDhcpServiceInterfaceUpdate(portBefore, portAfter);
199 private void processDhcpServiceInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
200 List<FlowEntity> addFlowEntries = new ArrayList<>();
201 List<FlowEntity> deleteFlowEntries = new ArrayList<>();
202 List<AllowedAddressPairs> addedAaps = AclServiceUtils
203 .getUpdatedAllowedAddressPairs(portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs());
204 List<AllowedAddressPairs> deletedAaps = AclServiceUtils
205 .getUpdatedAllowedAddressPairs(portBefore.getAllowedAddressPairs(), portAfter.getAllowedAddressPairs());
206 if (!deletedAaps.isEmpty()) {
207 processDhcpServiceUpdate(deleteFlowEntries, portBefore, deletedAaps, NwConstants.DEL_FLOW);
209 if (!addedAaps.isEmpty()) {
210 processDhcpServiceUpdate(addFlowEntries, portAfter, addedAaps, NwConstants.ADD_FLOW);
212 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + portAfter.getInterfaceId(), deleteFlowEntries,
213 NwConstants.DEL_FLOW);
214 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + portAfter.getInterfaceId(), addFlowEntries,
215 NwConstants.ADD_FLOW);
218 private void processInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
219 List<FlowEntity> addFlowEntries = new ArrayList<>();
220 List<FlowEntity> deleteFlowEntries = new ArrayList<>();
221 List<AllowedAddressPairs> addedAaps = AclServiceUtils
222 .getUpdatedAllowedAddressPairs(portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs());
223 List<AllowedAddressPairs> deletedAaps = AclServiceUtils
224 .getUpdatedAllowedAddressPairs(portBefore.getAllowedAddressPairs(), portAfter.getAllowedAddressPairs());
225 if (!deletedAaps.isEmpty()) {
226 programAclWithAllowedAddress(deleteFlowEntries, portBefore, deletedAaps, Action.UPDATE,
227 NwConstants.DEL_FLOW);
228 updateRemoteAclFilterTable(portBefore, portBefore.getSecurityGroups(), deletedAaps, NwConstants.DEL_FLOW);
230 if (!addedAaps.isEmpty()) {
231 programAclWithAllowedAddress(addFlowEntries, portAfter, addedAaps, Action.UPDATE, NwConstants.ADD_FLOW);
232 updateRemoteAclFilterTable(portAfter, portAfter.getSecurityGroups(), addedAaps, NwConstants.ADD_FLOW);
234 if (portAfter.getSubnetInfo() != null && portBefore.getSubnetInfo() == null) {
235 programBroadcastRules(addFlowEntries, portAfter, Action.UPDATE, NwConstants.ADD_FLOW);
237 handleSubnetChange(portBefore, portAfter, addFlowEntries, deleteFlowEntries);
239 List<Uuid> addedAcls = AclServiceUtils.getUpdatedAclList(portAfter.getSecurityGroups(),
240 portBefore.getSecurityGroups());
241 List<Uuid> deletedAcls = AclServiceUtils.getUpdatedAclList(portBefore.getSecurityGroups(),
242 portAfter.getSecurityGroups());
243 if (!deletedAcls.isEmpty() || !addedAcls.isEmpty()) {
244 handleAclChange(deleteFlowEntries, portBefore, deletedAcls, NwConstants.DEL_FLOW);
245 handleAclChange(addFlowEntries, portAfter, addedAcls, NwConstants.ADD_FLOW);
248 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + portAfter.getInterfaceId(), deleteFlowEntries,
249 NwConstants.DEL_FLOW);
250 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + portAfter.getInterfaceId(), addFlowEntries,
251 NwConstants.ADD_FLOW);
254 private void handleSubnetChange(AclInterface portBefore, AclInterface portAfter,
255 List<FlowEntity> addFlowEntries, List<FlowEntity> deleteFlowEntries) {
256 List<SubnetInfo> deletedSubnets =
257 AclServiceUtils.getSubnetDiff(portBefore.getSubnetInfo(), portAfter.getSubnetInfo());
258 List<SubnetInfo> addedSubnets =
259 AclServiceUtils.getSubnetDiff(portAfter.getSubnetInfo(), portBefore.getSubnetInfo());
261 if (deletedSubnets != null && !deletedSubnets.isEmpty()) {
262 programIcmpv6RARule(deleteFlowEntries, portAfter, deletedSubnets, NwConstants.DEL_FLOW);
263 programSubnetBroadcastRules(deleteFlowEntries, portAfter, deletedSubnets, NwConstants.DEL_FLOW);
265 if (addedSubnets != null && !addedSubnets.isEmpty()) {
266 programIcmpv6RARule(addFlowEntries, portAfter, addedSubnets, NwConstants.ADD_FLOW);
267 programSubnetBroadcastRules(addFlowEntries, portAfter, addedSubnets, NwConstants.ADD_FLOW);
271 private void handleAclChange(List<FlowEntity> flowEntries, AclInterface port, List<Uuid> aclList,
273 int operationForAclRules = addOrRemove == NwConstants.DEL_FLOW ? NwConstants.MOD_FLOW : addOrRemove;
274 programAclRules(flowEntries, port, aclList, operationForAclRules);
275 updateRemoteAclFilterTable(port, aclList, port.getAllowedAddressPairs(), addOrRemove);
276 programAclDispatcherTable(flowEntries, port, addOrRemove);
279 protected SortedSet<Integer> getRemoteAclTags(AclInterface port) {
280 return this.direction == DirectionIngress.class ? port.getIngressRemoteAclTags()
281 : port.getEgressRemoteAclTags();
284 protected void programAclDispatcherTable(List<FlowEntity> flowEntries, AclInterface port, int addOrRemove) {
285 SortedSet<Integer> remoteAclTags = getRemoteAclTags(port);
286 if (remoteAclTags.isEmpty()) {
287 LOG.debug("No {} rules with remote group id for port={}", this.directionString, port.getInterfaceId());
290 Integer firstRemoteAclTag = remoteAclTags.first();
291 Integer lastRemoteAclTag = remoteAclTags.last();
293 programFirstRemoteAclEntryInDispatcherTable(flowEntries, port, firstRemoteAclTag, addOrRemove);
294 programLastRemoteAclEntryInDispatcherTable(flowEntries, port, lastRemoteAclTag, addOrRemove);
296 Integer previousRemoteAclTag = firstRemoteAclTag;
297 for (Integer remoteAclTag : remoteAclTags) {
298 if (remoteAclTag.equals(firstRemoteAclTag)) {
301 List<MatchInfoBase> matches = new ArrayList<>();
302 matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(),
303 previousRemoteAclTag, serviceMode));
304 String flowId = this.directionString + "_ACL_Dispatcher_" + port.getDpId() + "_" + port.getLPortTag() + "_"
307 List<InstructionInfo> instructions =
308 AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRuleBasedFilterTable());
309 instructions.add(AclServiceUtils.getWriteMetadataForRemoteAclTag(remoteAclTag));
310 addFlowEntryToList(flowEntries, Uint64.valueOf(port.getDpId()), getAclFilterCumDispatcherTable(), flowId,
311 AclConstants.ACE_GOTO_NEXT_REMOTE_ACL_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
312 instructions, addOrRemove);
314 previousRemoteAclTag = remoteAclTag;
318 protected void programFirstRemoteAclEntryInDispatcherTable(List<FlowEntity> flowEntries, AclInterface port,
319 Integer firstRemoteAclTag, int addOrRemove) {
320 List<MatchInfoBase> matches = new ArrayList<>();
321 matches.add(AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode));
322 String flowId = this.directionString + "_ACL_Dispatcher_First_" + port.getDpId() + "_" + port.getLPortTag()
323 + "_" + firstRemoteAclTag;
325 List<InstructionInfo> instructions =
326 AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRuleBasedFilterTable());
327 instructions.add(AclServiceUtils.getWriteMetadataForRemoteAclTag(firstRemoteAclTag));
328 addFlowEntryToList(flowEntries, Uint64.valueOf(port.getDpId()), getAclFilterCumDispatcherTable(), flowId,
329 AclConstants.ACE_FIRST_REMOTE_ACL_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions,
333 protected void programLastRemoteAclEntryInDispatcherTable(List<FlowEntity> flowEntries, AclInterface port,
334 Integer lastRemoteAclTag, int addOrRemove) {
335 List<MatchInfoBase> matches = new ArrayList<>();
336 matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(), lastRemoteAclTag,
338 String flowId = this.directionString + "_ACL_Dispatcher_Last_" + port.getDpId() + "_" + port.getLPortTag() + "_"
341 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
342 addFlowEntryToList(flowEntries, Uint64.valueOf(port.getDpId()), getAclFilterCumDispatcherTable(), flowId,
343 AclConstants.ACE_LAST_REMOTE_ACL_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(port.getLPortTag()),
344 matches, instructions, addOrRemove);
347 private void programAclWithAllowedAddress(List<FlowEntity> flowEntries, AclInterface port,
348 List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove) {
349 Uint64 dpId = Uint64.valueOf(port.getDpId());
350 int lportTag = port.getLPortTag();
351 LOG.debug("Applying ACL Allowed Address on DpId {}, lportTag {}, Action {}", dpId, lportTag, action);
352 String portId = port.getInterfaceId();
353 programAntiSpoofingRules(flowEntries, port, allowedAddresses, action, addOrRemove);
354 programAclPortSpecificFixedRules(flowEntries, dpId, allowedAddresses, lportTag, portId, action, addOrRemove);
355 if (action == Action.ADD || action == Action.REMOVE) {
356 programAclRules(flowEntries, port, port.getSecurityGroups(), addOrRemove);
357 programAclDispatcherTable(flowEntries, port, addOrRemove);
362 * Programs the acl custom rules.
364 * @param flowEntries the flow entries
365 * @param port acl interface
366 * @param aclUuidList the list of acl uuid to be applied
367 * @param addOrRemove whether to delete or add flow
368 * @return program succeeded
370 protected boolean programAclRules(List<FlowEntity> flowEntries, AclInterface port, List<Uuid> aclUuidList,
372 BigInteger dpId = port.getDpId();
373 LOG.debug("Applying custom rules on DpId {}, lportTag {}", dpId, port.getLPortTag());
374 if (aclUuidList == null || dpId == null) {
375 LOG.warn("{} ACL parameters can not be null. dpId={}, aclUuidList={}", this.directionString, dpId,
379 for (Uuid aclUuid : aclUuidList) {
380 Acl acl = this.aclDataUtil.getAcl(aclUuid.getValue());
382 LOG.warn("The ACL {} not found in cache", aclUuid.getValue());
385 for (Ace ace : AclServiceUtils.aceList(acl)) {
386 programAceRule(flowEntries, port, aclUuid.getValue(), ace, addOrRemove);
393 * Programs the ace specific rule.
395 * @param flowEntries flow entries
396 * @param port acl interface
397 * @param aclName the acl name
398 * @param ace rule to be program
399 * @param addOrRemove whether to delete or add flow
401 protected void programAceRule(List<FlowEntity> flowEntries, AclInterface port, String aclName, Ace ace,
403 SecurityRuleAttr aceAttr = AclServiceUtils.getAccessListAttributes(ace);
404 if (aceAttr == null) {
405 LOG.error("Ace {} of Acl {} is either null or not having SecurityRuleAttr",
406 ace == null ? null : ace.getRuleName(), aclName);
409 if (addOrRemove == NwConstants.ADD_FLOW && aceAttr.isDeleted()) {
410 LOG.trace("Ignoring {} rule which is already deleted", ace.getRuleName());
413 if (!isValidDirection(aceAttr.getDirection())) {
414 LOG.trace("Ignoring {} direction while processing for {} ACE Rule {}", aceAttr.getDirection(),
415 this.directionString, ace.getRuleName());
418 LOG.debug("Program {} ACE rule for dpId={}, lportTag={}, addOrRemove={}, ace={}, portId={}",
419 this.directionString, port.getDpId(), port.getLPortTag(), addOrRemove, ace.getRuleName(),
420 port.getInterfaceId());
422 Matches matches = ace.getMatches();
423 if (matches != null && matches.getAceType() instanceof AceIp) {
424 Map<String, List<MatchInfoBase>> flowMap = AclServiceOFFlowBuilder.programIpFlow(matches);
425 if (!AclServiceUtils.doesAceHaveRemoteGroupId(aceAttr)) {
426 // programming for ACE which doesn't have any remote group Id
427 programForAceNotHavingRemoteAclId(flowEntries, port, aclName, ace, flowMap, addOrRemove);
429 Uuid remoteAclId = aceAttr.getRemoteGroupId();
430 // programming for ACE which have remote group Id
431 programAceSpecificFlows(flowEntries, port, aclName, ace, flowMap, remoteAclId, addOrRemove);
436 protected void programForAceNotHavingRemoteAclId(List<FlowEntity> flowEntries, AclInterface port, String aclName,
437 Ace ace, @Nullable Map<String, List<MatchInfoBase>> flowMap, int addOrRemove) {
438 if (null == flowMap) {
441 MatchInfoBase lportTagMatch = AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode);
442 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclCommitterTable());
443 Integer flowPriority = this.aclServiceUtils.getAceFlowPriority(aclName);
445 for (Entry<String, List<MatchInfoBase>> entry : flowMap.entrySet()) {
446 String flowName = entry.getKey();
447 List<MatchInfoBase> matches = entry.getValue();
448 matches.add(lportTagMatch);
449 String flowId = flowName + this.directionString + "_" + port.getDpId() + "_" + port.getLPortTag() + "_"
450 + ace.key().getRuleName();
452 int operation = addOrRemove == NwConstants.MOD_FLOW ? NwConstants.DEL_FLOW : addOrRemove;
453 addFlowEntryToList(flowEntries, Uint64.valueOf(port.getDpId()), getAclFilterCumDispatcherTable(),
454 flowId, flowPriority, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, operation);
456 if (addOrRemove != NwConstants.DEL_FLOW) {
457 programAclForExistingTrafficTable(port, ace, addOrRemove, flowName, matches, flowPriority);
462 protected void programAceSpecificFlows(List<FlowEntity> flowEntries, AclInterface port, String aclName, Ace ace,
463 @Nullable Map<String, List<MatchInfoBase>> flowMap, Uuid remoteAclId, int addOrRemove) {
464 if (null == flowMap) {
467 Integer remoteAclTag = this.aclServiceUtils.getAclTag(remoteAclId);
468 if (remoteAclTag == null || remoteAclTag == AclConstants.INVALID_ACL_TAG) {
469 LOG.error("remoteAclTag={} is null or invalid for remoteAclId={}", remoteAclTag, remoteAclId);
472 List<MatchInfoBase> lportAndAclMatches =
473 AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(), remoteAclTag, serviceMode);
474 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRemoteAclTable());
475 Integer flowPriority = this.aclServiceUtils.getAceFlowPriority(aclName);
477 for (Entry<String, List<MatchInfoBase>> entry : flowMap.entrySet()) {
478 String flowName = entry.getKey();
479 List<MatchInfoBase> matches = entry.getValue();
480 matches.addAll(lportAndAclMatches);
481 String flowId = flowName + this.directionString + "_" + port.getDpId() + "_" + port.getLPortTag() + "_"
482 + ace.key().getRuleName();
484 int operation = addOrRemove == NwConstants.MOD_FLOW ? NwConstants.DEL_FLOW : addOrRemove;
485 addFlowEntryToList(flowEntries, Uint64.valueOf(port.getDpId()), getAclRuleBasedFilterTable(), flowId,
486 flowPriority, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, operation);
488 if (addOrRemove != NwConstants.DEL_FLOW) {
489 programAclForExistingTrafficTable(port, ace, addOrRemove, flowName, matches, flowPriority);
494 private void programAclForExistingTrafficTable(AclInterface port, Ace ace, int addOrRemove, String flowName,
495 List<MatchInfoBase> matches, Integer priority) {
496 if (port == null || port.getElanId() == null) {
497 LOG.debug("Acl interface or elan id is null, No need to update traffic flow table.");
501 AceIp acl = (AceIp) ace.getMatches().getAceType();
502 final String newFlowName = flowName + this.directionString + "_" + port.getDpId() + "_" + port.getLPortTag()
503 + "_" + (acl.getAceIpVersion() instanceof AceIpv4 ? "_IPv4" : "_IPv6") + "_FlowAfterRuleDeleted";
505 final List<MatchInfoBase> newMatches =
506 matches.stream().filter(obj -> !(obj instanceof NxMatchCtState || obj instanceof MatchMetadata))
507 .collect(Collectors.toList());
508 newMatches.add(AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode));
509 newMatches.add(new NxMatchCtState(AclConstants.TRACKED_RPL_CT_STATE, AclConstants.TRACKED_RPL_CT_STATE_MASK));
511 List<InstructionInfo> instructions =
512 AclServiceUtils.createCtMarkInstructionForNewState(getAclFilterCumDispatcherTable(), port.getElanId());
513 // Reversing the flow add/delete operation for this table.
514 List<FlowEntity> flowEntries = new ArrayList<>();
515 int operation = addOrRemove == NwConstants.ADD_FLOW ? NwConstants.DEL_FLOW : NwConstants.ADD_FLOW;
516 addFlowEntryToList(flowEntries, Uint64.valueOf(port.getDpId()), getAclForExistingTrafficTable(), newFlowName,
517 priority, 0, AclServiceUtils.getHardTimoutForApplyStatefulChangeOnExistingTraffic(ace, aclServiceUtils),
518 AclConstants.COOKIE_ACL_BASE, newMatches, instructions, operation);
519 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, operation);
523 public boolean removeAcl(AclInterface port) {
524 if (port.getDpId() == null) {
525 LOG.warn("Unable to find DP Id from ACL interface with id {}", port.getInterfaceId());
528 List<FlowEntity> flowEntries = new ArrayList<>();
529 if (port.getInterfaceType() == InterfaceType.DhcpService) {
530 programDhcpService(flowEntries, port, Action.REMOVE, NwConstants.DEL_FLOW);
532 programAclWithAllowedAddress(flowEntries, port, port.getAllowedAddressPairs(),
533 Action.REMOVE, NwConstants.DEL_FLOW);
534 updateRemoteAclFilterTable(port, NwConstants.DEL_FLOW);
536 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, NwConstants.DEL_FLOW);
541 public boolean applyAce(AclInterface port, String aclName, Ace ace) {
542 if (!port.isPortSecurityEnabled() || port.getDpId() == null) {
545 List<FlowEntity> flowEntries = new ArrayList<>();
546 programAceRule(flowEntries, port, aclName, ace, NwConstants.ADD_FLOW);
547 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, NwConstants.ADD_FLOW);
552 public boolean removeAce(AclInterface port, String aclName, Ace ace) {
553 if (!port.isPortSecurityEnabled() || port.getDpId() == null) {
556 List<FlowEntity> flowEntries = new ArrayList<>();
557 programAceRule(flowEntries, port, aclName, ace, NwConstants.MOD_FLOW);
558 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, NwConstants.DEL_FLOW);
563 public void updateRemoteAcl(Acl aclBefore, Acl aclAfter, Collection<AclInterface> portsBefore) {
564 handleRemoteAclUpdate(aclBefore, aclAfter, portsBefore);
570 * @param aclInterface the acl interface
572 public abstract void bindService(AclInterface aclInterface);
577 * @param aclInterface the acl interface
579 protected abstract void unbindService(AclInterface aclInterface);
582 * Programs DHCP Service flows.
584 * @param flowEntries the flow entries
585 * @param port the acl interface
586 * @param action add/modify/remove action
587 * @param addOrRemove addorRemove
589 protected abstract void programDhcpService(List<FlowEntity> flowEntries, AclInterface port,
590 Action action, int addOrRemove);
593 * Programs DHCP service flows.
595 * @param flowEntries the flow entries
596 * @param port the acl interface
597 * @param allowedAddresses the allowed addresses
598 * @param addOrRemove addorRemove
600 protected abstract void processDhcpServiceUpdate(List<FlowEntity> flowEntries, AclInterface port,
601 List<AllowedAddressPairs> allowedAddresses, int addOrRemove);
604 * Programs the anti-spoofing rules.
606 * @param flowEntries the flow entries
607 * @param port the acl interface
608 * @param allowedAddresses the allowed addresses
609 * @param action add/modify/remove action
610 * @param addOrRemove addorRemove
612 protected abstract void programAntiSpoofingRules(List<FlowEntity> flowEntries, AclInterface port,
613 List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove);
616 * Programs broadcast rules.
618 * @param flowEntries the flow entries
619 * @param port the Acl Interface port
620 * @param addOrRemove whether to delete or add flow
622 protected abstract void programBroadcastRules(List<FlowEntity> flowEntries, AclInterface port, Action action,
626 * Programs broadcast rules.
628 * @param flowEntries the flow entries
629 * @param port the Acl Interface port
630 * @param subnetInfoList the port subnet info list
631 * @param addOrRemove whether to delete or add flow
633 protected abstract void programSubnetBroadcastRules(List<FlowEntity> flowEntries, AclInterface port,
634 List<SubnetInfo> subnetInfoList, int addOrRemove);
636 protected abstract void programIcmpv6RARule(List<FlowEntity> flowEntries, AclInterface port,
637 List<SubnetInfo> subnets, int addOrRemove);
657 * the list of matches to be writted
658 * @param instructions
659 * the list of instruction to be written.
661 * add or remove the entries.
663 protected void addFlowEntryToList(List<FlowEntity> flowEntries, Uint64 dpId, short tableId, String flowId,
664 int priority, int idleTimeOut, int hardTimeOut, Uint64 cookie, List<? extends MatchInfoBase> matches,
665 List<InstructionInfo> instructions, int addOrRemove) {
666 List<InstructionInfo> instructionInfos = null;
667 if (addOrRemove == NwConstants.ADD_FLOW) {
668 instructionInfos = instructions;
670 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority,
671 flowId, idleTimeOut, hardTimeOut, cookie, matches, instructionInfos);
672 LOG.trace("Adding flow to list: DpnId {}, flowId {}", dpId, flowId);
673 flowEntries.add(flowEntity);
676 protected void programFlows(String jobName, List<FlowEntity> flowEntries, int addOrRemove) {
677 List<List<FlowEntity>> flowEntityParts = Lists.partition(flowEntries, AclConstants.FLOWS_PER_TRANSACTION);
678 for (List<FlowEntity> part : flowEntityParts) {
679 jobCoordinator.enqueueJob(jobName,
680 () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
682 if (addOrRemove == NwConstants.ADD_FLOW) {
683 for (FlowEntity flowEntity: part) {
684 mdsalManager.addFlow(tx, flowEntity);
687 for (FlowEntity flowEntity: part) {
688 mdsalManager.removeFlow(tx, flowEntity);
691 })), AclConstants.JOB_MAX_RETRIES);
695 protected List<InstructionInfo> getDispatcherTableResubmitInstructions() {
696 return getDispatcherTableResubmitInstructions(new ArrayList<>());
700 * Gets the dispatcher table resubmit instructions based on ingress/egress service mode w.r.t switch.
702 * @param actionsInfos
704 * @return the instructions for dispatcher table resubmit
706 protected List<InstructionInfo> getDispatcherTableResubmitInstructions(List<ActionInfo> actionsInfos) {
707 short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
708 if (ServiceModeEgress.class.equals(this.serviceMode)) {
709 dispatcherTableId = NwConstants.EGRESS_LPORT_DISPATCHER_TABLE;
712 List<InstructionInfo> instructions = new ArrayList<>();
713 actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
714 instructions.add(new InstructionApplyActions(actionsInfos));
718 protected void handleRemoteAclUpdate(Acl aclBefore, Acl aclAfter, Collection<AclInterface> portsBefore) {
719 String aclName = aclAfter.getAclName();
720 Collection<AclInterface> interfaceList = aclDataUtil.getInterfaceList(new Uuid(aclName));
721 if (interfaceList.isEmpty()) {
722 LOG.trace("handleRemoteAclUpdate: No interfaces found with ACL={}", aclName);
725 Set<Uuid> remoteAclsBefore = AclServiceUtils.getRemoteAclIdsByDirection(aclBefore, this.direction);
726 Set<Uuid> remoteAclsAfter = AclServiceUtils.getRemoteAclIdsByDirection(aclAfter, this.direction);
728 Set<Uuid> remoteAclsAdded = new HashSet<>(remoteAclsAfter);
729 remoteAclsAdded.removeAll(remoteAclsBefore);
731 Set<Uuid> remoteAclsDeleted = new HashSet<>(remoteAclsBefore);
732 remoteAclsDeleted.removeAll(remoteAclsAfter);
734 List<FlowEntity> addFlowEntries = new ArrayList<>();
735 List<FlowEntity> deleteFlowEntries = new ArrayList<>();
736 if (!remoteAclsAdded.isEmpty() || !remoteAclsDeleted.isEmpty()) {
737 // delete and add flows in ACL dispatcher table for all applicable ports
738 for (AclInterface portBefore : portsBefore) {
739 if (portBefore.getDpId() != null) {
740 programAclDispatcherTable(deleteFlowEntries, portBefore, NwConstants.DEL_FLOW);
742 LOG.debug("Skip ACL dispatcher table update as DP ID for interface {} is not present.",
743 portBefore.getInterfaceId());
746 for (AclInterface port : interfaceList) {
747 programAclDispatcherTable(addFlowEntries, port, NwConstants.ADD_FLOW);
750 Set<BigInteger> dpns = interfaceList.stream().filter(port -> {
751 if (port.getDpId() == null) {
752 LOG.debug("Skip remote ACL table update as DP ID for interface {} is not present.",
753 port.getInterfaceId());
757 }).map(AclInterface::getDpId).collect(Collectors.toSet());
759 programRemoteAclTable(deleteFlowEntries, aclName, remoteAclsDeleted, dpns, NwConstants.DEL_FLOW);
760 programRemoteAclTable(addFlowEntries, aclName, remoteAclsAdded, dpns, NwConstants.ADD_FLOW);
762 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + aclName, deleteFlowEntries, NwConstants.DEL_FLOW);
763 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + aclName, addFlowEntries, NwConstants.ADD_FLOW);
766 private void programRemoteAclTable(List<FlowEntity> flowEntries, String aclName, Set<Uuid> remoteAclIds,
767 Set<BigInteger> dpns, int addOrRemove) {
768 for (Uuid remoteAclId : remoteAclIds) {
769 Collection<AclInterface> remoteAclInterfaces = aclDataUtil.getInterfaceList(remoteAclId);
770 if (remoteAclInterfaces.isEmpty()) {
773 Set<AllowedAddressPairs> aaps =
774 remoteAclInterfaces.stream().map(AclInterface::getAllowedAddressPairs).flatMap(List::stream)
775 .filter(AclServiceUtils::isNotIpAllNetwork).collect(Collectors.toSet());
777 Integer aclTag = aclServiceUtils.getAclTag(remoteAclId);
778 if (aclTag == null || aclTag == AclConstants.INVALID_ACL_TAG) {
779 LOG.error("aclTag={} is null or invalid for remoteAclId={}", aclTag, remoteAclId);
782 if (addOrRemove == NwConstants.ADD_FLOW) {
783 for (BigInteger dpn : dpns) {
784 for (AllowedAddressPairs aap : aaps) {
785 programRemoteAclTableFlow(flowEntries, Uint64.valueOf(dpn), aclTag, aap, addOrRemove);
788 } else if (addOrRemove == NwConstants.DEL_FLOW) {
789 Set<BigInteger> remoteAclDpns = new HashSet<>();
790 Map<String, Set<AclInterface>> mapAclWithPortSet =
791 aclDataUtil.getRemoteAclInterfaces(remoteAclId, this.direction);
792 if (mapAclWithPortSet != null) {
793 Map<String, Set<AclInterface>> copyOfMapAclWithPortSet = new HashMap<>(mapAclWithPortSet);
794 copyOfMapAclWithPortSet.remove(aclName);
795 remoteAclDpns = collectDpns(copyOfMapAclWithPortSet);
797 Set<BigInteger> dpnsToOperate = new HashSet<>(dpns);
798 dpnsToOperate.removeAll(remoteAclDpns);
800 "Deleting flows in Remote ACL table for remoteAclId={}, direction={}, dpnsToOperate={}, "
801 + "remoteAclDpns={}, dpns={}",
802 remoteAclId.getValue(), directionString, dpnsToOperate, remoteAclDpns, dpns);
804 for (BigInteger dpn : dpnsToOperate) {
805 for (AllowedAddressPairs aap : aaps) {
806 programRemoteAclTableFlow(flowEntries, Uint64.valueOf(dpn), aclTag, aap, addOrRemove);
813 private void updateRemoteAclFilterTable(AclInterface port, int addOrRemove) {
814 updateRemoteAclFilterTable(port, port.getSecurityGroups(), port.getAllowedAddressPairs(), addOrRemove);
817 private void updateRemoteAclFilterTable(AclInterface port, List<Uuid> aclList, List<AllowedAddressPairs> aaps,
819 if (aclList == null) {
820 LOG.debug("Port {} without SGs", port.getInterfaceId());
823 String portId = port.getInterfaceId();
824 LOG.trace("updateRemoteAclFilterTable for portId={}, aclList={}, aaps={}, addOrRemove={}", portId, aclList,
827 ConcurrentMap<Uuid, Map<String, Set<AclInterface>>> mapOfAclWithInterfacesList =
828 aclDataUtil.getRemoteAclInterfaces(aclList, this.direction);
829 for (Uuid aclId : aclList) {
830 Map<String, Set<AclInterface>> mapAclWithPortSet = mapOfAclWithInterfacesList.get(aclId);
831 if (aclDataUtil.getRemoteAcl(aclId, this.direction) != null) {
832 Integer aclTag = aclServiceUtils.getAclTag(aclId);
833 if (aclTag == null || aclTag == AclConstants.INVALID_ACL_TAG) {
834 LOG.error("aclTag={} is null or invalid for aclId={}", aclTag, aclId);
837 jobCoordinator.enqueueJob(aclId.getValue().intern(), () -> {
838 List<FlowEntity> flowEntries = new ArrayList<>();
839 syncRemoteAclTable(flowEntries, portId, aclId, aclTag, aaps, mapAclWithPortSet, addOrRemove);
840 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + aclId.getValue(), flowEntries, addOrRemove);
841 return Collections.emptyList();
845 Set<Uuid> remoteAclIds = aclServiceUtils.getRemoteAclIdsByDirection(aclList, direction);
846 for (Uuid remoteAclId : remoteAclIds) {
847 List<Uuid> aclIds = new ArrayList<Uuid>(port.getSecurityGroups());
848 aclIds.removeAll(aclList);
849 if (addOrRemove == NwConstants.DEL_FLOW && aclServiceUtils.doesRemoteAclIdExistsInAcls(aclIds, remoteAclId,
851 LOG.debug("Skipping delete as remoteAclId {} is used with other ACE configured with port {}",
852 remoteAclId, portId);
855 List<FlowEntity> flowEntries = new ArrayList<>();
856 syncRemoteAclTableFromOtherDpns(flowEntries, port, remoteAclId, addOrRemove);
857 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + remoteAclId.getValue(), flowEntries, addOrRemove);
861 private void syncRemoteAclTable(List<FlowEntity> flowEntries, String portId, Uuid acl, Integer aclTag,
862 List<AllowedAddressPairs> aaps, Map<String, Set<AclInterface>> mapAclWithPortSet, int addOrRemove) {
863 Set<BigInteger> dpns = collectDpns(mapAclWithPortSet);
864 for (AllowedAddressPairs aap : aaps) {
865 if (!AclServiceUtils.isNotIpAllNetwork(aap)) {
868 if (aclServiceUtils.skipDeleteInCaseOfOverlappingIP(portId, acl, aap.getIpAddress(),
870 LOG.debug("Skipping delete of IP={} in remote ACL table for remoteAclId={}, portId={}",
871 aap.getIpAddress(), portId, acl.getValue());
874 for (BigInteger dpId : dpns) {
875 programRemoteAclTableFlow(flowEntries, Uint64.valueOf(dpId), aclTag, aap, addOrRemove);
880 private void syncRemoteAclTableFromOtherDpns(List<FlowEntity> flowEntries, AclInterface port, Uuid remoteAclId,
882 Collection<AclInterface> aclInterfaces = aclDataUtil.getInterfaceList(remoteAclId);
884 if (!aclInterfaces.isEmpty() && isFirstPortInDpnWithRemoteAclId(port, remoteAclId)) {
885 Integer aclTag = aclServiceUtils.getAclTag(remoteAclId);
886 if (aclTag == null || aclTag == AclConstants.INVALID_ACL_TAG) {
887 LOG.error("aclTag={} is null or invalid for remoteAclId={}", aclTag, remoteAclId);
890 for (AclInterface aclInterface : aclInterfaces) {
891 if (port.getInterfaceId().equals(aclInterface.getInterfaceId())) {
894 for (AllowedAddressPairs aap : aclInterface.getAllowedAddressPairs()) {
895 if (AclServiceUtils.isNotIpAllNetwork(aap)) {
896 programRemoteAclTableFlow(flowEntries, Uint64.valueOf(port.getDpId()),
897 aclTag, aap, addOrRemove);
904 private boolean isFirstPortInDpnWithRemoteAclId(AclInterface port, Uuid remoteAclId) {
905 String portId = port.getInterfaceId();
906 BigInteger dpId = port.getDpId();
907 Map<String, Set<AclInterface>> remoteAclInterfacesMap =
908 aclDataUtil.getRemoteAclInterfaces(remoteAclId, direction);
909 if (remoteAclInterfacesMap != null) {
910 for (Set<AclInterface> interfaceSet : remoteAclInterfacesMap.values()) {
911 for (AclInterface aclInterface : interfaceSet) {
912 if (portId.equals(aclInterface.getInterfaceId())) {
915 if (dpId.equals(aclInterface.getDpId())) {
924 protected abstract void programRemoteAclTableFlow(List<FlowEntity> flowEntries, Uint64 dpId, Integer aclTag,
925 AllowedAddressPairs aap, int addOrRemove);
927 protected Set<BigInteger> collectDpns(@Nullable Map<String, Set<AclInterface>> mapAclWithPortSet) {
928 Set<BigInteger> dpns = new HashSet<>();
929 if (mapAclWithPortSet == null) {
932 for (Set<AclInterface> innerSet : mapAclWithPortSet.values()) {
933 if (innerSet == null) {
936 for (AclInterface inter : innerSet) {
937 dpns.add(inter.getDpId());
944 * Programs the port specific fixed rules.
946 * @param flowEntries the flow entries
947 * @param dpId the dp id
948 * @param allowedAddresses the allowed addresses
949 * @param lportTag the lport tag
950 * @param portId the portId
951 * @param action the action
952 * @param write whether to add or remove the flow.
954 protected void programAclPortSpecificFixedRules(List<FlowEntity> flowEntries, Uint64 dpId,
955 List<AllowedAddressPairs> allowedAddresses, int lportTag, String portId, Action action, int write) {
956 programGotoClassifierTableRules(flowEntries, dpId, allowedAddresses, lportTag, write);
957 if (action == Action.ADD || action == Action.REMOVE) {
958 programConntrackRecircRules(flowEntries, dpId, allowedAddresses, lportTag, portId, write);
959 programPortSpecificDropRules(flowEntries, dpId, lportTag, write);
960 programAclCommitRules(flowEntries, dpId, lportTag, portId, write);
962 LOG.info("programAclPortSpecificFixedRules: flows for dpId={}, lportId={}, action={}, write={}", dpId, lportTag,
966 protected abstract void programGotoClassifierTableRules(List<FlowEntity> flowEntries, Uint64 dpId,
967 List<AllowedAddressPairs> aaps, int lportTag, int addOrRemove);
970 * Adds the rule to send the packet to the netfilter to check whether it is a known packet.
972 * @param flowEntries the flow entries
973 * @param dpId the dpId
974 * @param aaps the allowed address pairs
975 * @param lportTag the lport tag
976 * @param portId the portId
977 * @param addOrRemove whether to add or remove the flow
979 protected void programConntrackRecircRules(List<FlowEntity> flowEntries, Uint64 dpId,
980 List<AllowedAddressPairs> aaps, int lportTag, String portId, int addOrRemove) {
981 if (AclServiceUtils.doesIpv4AddressExists(aaps)) {
982 programConntrackRecircRule(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV4, addOrRemove);
984 if (AclServiceUtils.doesIpv6AddressExists(aaps)) {
985 programConntrackRecircRule(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV6, addOrRemove);
989 protected void programConntrackRecircRule(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
990 String portId, MatchEthernetType matchEtherType, int addOrRemove) {
991 List<MatchInfoBase> matches = new ArrayList<>();
992 matches.add(matchEtherType);
993 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
995 List<InstructionInfo> instructions = new ArrayList<>();
996 if (addOrRemove == NwConstants.ADD_FLOW) {
997 Long elanTag = getElanIdFromAclInterface(portId);
998 if (elanTag == null) {
999 LOG.error("ElanId not found for portId={}; Context: dpId={}, lportTag={}, addOrRemove={},", portId,
1000 dpId, lportTag, addOrRemove);
1003 List<ActionInfo> actionsInfos = new ArrayList<>();
1004 actionsInfos.add(new ActionNxConntrack(2, 0, 0, elanTag.intValue(), getAclForExistingTrafficTable()));
1005 instructions.add(new InstructionApplyActions(actionsInfos));
1009 this.directionString + "_Fixed_Conntrk_" + dpId + "_"
1010 + lportTag + "_" + matchEtherType + "_Recirc";
1011 addFlowEntryToList(flowEntries, dpId, getAclConntrackSenderTable(), flowName,
1012 AclConstants.ACL_DEFAULT_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions,
1017 * Adds the rules to drop the unknown/invalid packets .
1019 * @param flowEntries the flow entries
1020 * @param dpId the dpId
1021 * @param lportTag the lport tag
1022 * @param addOrRemove whether to add or remove the flow
1024 protected void programPortSpecificDropRules(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
1026 LOG.debug("Programming Drop Rules: DpId={}, lportTag={}, addOrRemove={}", dpId, lportTag, addOrRemove);
1027 programConntrackInvalidDropRule(flowEntries, dpId, lportTag, addOrRemove);
1028 programAclRuleMissDropRule(flowEntries, dpId, lportTag, addOrRemove);
1032 * Adds the rule to drop the conntrack invalid packets .
1034 * @param flowEntries the flow entries
1035 * @param dpId the dpId
1036 * @param lportTag the lport tag
1037 * @param addOrRemove whether to add or remove the flow
1039 protected void programConntrackInvalidDropRule(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
1041 List<MatchInfoBase> matches = AclServiceOFFlowBuilder.addLPortTagMatches(lportTag,
1042 AclConstants.TRACKED_INV_CT_STATE, AclConstants.TRACKED_INV_CT_STATE_MASK, serviceMode);
1043 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
1045 String flowId = this.directionString + "_Fixed_Conntrk_Drop" + dpId.toString()
1046 + "_" + lportTag + "_Tracked_Invalid";
1047 addFlowEntryToList(flowEntries, dpId, getAclFilterCumDispatcherTable(), flowId,
1048 AclConstants.CT_STATE_TRACKED_INVALID_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(lportTag),
1049 matches, instructions, addOrRemove);
1053 * Program ACL rule miss drop rule for a port.
1055 * @param flowEntries the flow entries
1056 * @param dpId the dp id
1057 * @param lportTag the lport tag
1058 * @param addOrRemove the add or remove
1060 protected void programAclRuleMissDropRule(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
1062 List<MatchInfoBase> matches = new ArrayList<>();
1063 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
1064 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
1066 String flowId = this.directionString + "_Fixed_Acl_Rule_Miss_Drop_" + dpId.toString() + "_" + lportTag;
1067 addFlowEntryToList(flowEntries, dpId, getAclFilterCumDispatcherTable(), flowId,
1068 AclConstants.ACL_PORT_SPECIFIC_DROP_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(lportTag),
1069 matches, instructions, addOrRemove);
1073 * Program acl commit rules.
1075 * @param flowEntries the flow entries
1076 * @param dpId the dp id
1077 * @param lportTag the lport tag
1078 * @param portId the port id
1079 * @param addOrRemove the add or remove
1081 protected void programAclCommitRules(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag, String portId,
1083 programAclCommitRuleForConntrack(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV4, addOrRemove);
1084 programAclCommitRuleForConntrack(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV6, addOrRemove);
1085 programAclCommitRuleForNonConntrack(flowEntries, dpId, lportTag, addOrRemove);
1089 * Program acl commit rule for conntrack.
1091 * @param flowEntries the flow entries
1092 * @param dpId the dp id
1093 * @param lportTag the lport tag
1094 * @param portId the port id
1095 * @param matchEtherType the match ether type
1096 * @param addOrRemove the add or remove
1098 protected void programAclCommitRuleForConntrack(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
1099 String portId, MatchEthernetType matchEtherType, int addOrRemove) {
1100 List<MatchInfoBase> matches = new ArrayList<>();
1101 matches.add(matchEtherType);
1102 matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndConntrackClassifierType(lportTag,
1103 AclConntrackClassifierType.CONNTRACK_SUPPORTED, serviceMode));
1105 List<ActionInfo> actionsInfos = new ArrayList<>();
1106 if (addOrRemove == NwConstants.ADD_FLOW) {
1107 Long elanId = getElanIdFromAclInterface(portId);
1108 if (elanId == null) {
1109 LOG.error("ElanId not found for portId={}; Context: dpId={}, lportTag={}, addOrRemove={}", portId, dpId,
1110 lportTag, addOrRemove);
1113 List<NxCtAction> ctActionsList =
1114 Lists.newArrayList(new ActionNxConntrack.NxCtMark(AclConstants.CT_MARK_EST_STATE));
1115 actionsInfos.add(new ActionNxConntrack(2, 1, 0, elanId.intValue(), (short) 255, ctActionsList));
1116 actionsInfos.add(new ActionNxCtClear());
1118 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions(actionsInfos);
1120 String flowName = directionString + "_Acl_Commit_Conntrack_" + dpId.toString()
1121 + "_" + lportTag + "_" + matchEtherType;
1122 // Flow for conntrack traffic to commit and resubmit to dispatcher
1123 addFlowEntryToList(flowEntries, dpId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY,
1124 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
1128 * Program acl commit rule for non conntrack.
1130 * @param flowEntries the flow entries
1131 * @param dpId the dp id
1132 * @param lportTag the lport tag
1133 * @param addOrRemove the add or remove
1135 protected void programAclCommitRuleForNonConntrack(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
1137 List<MatchInfoBase> matches = new ArrayList<>();
1138 matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndConntrackClassifierType(lportTag,
1139 AclConntrackClassifierType.NON_CONNTRACK_SUPPORTED, serviceMode));
1141 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
1142 String flowName = this.directionString + "_Acl_Commit_Non_Conntrack_" + dpId + "_" + lportTag;
1143 // Flow for non-conntrack traffic to resubmit to dispatcher
1144 addFlowEntryToList(flowEntries, dpId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY,
1145 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
1149 protected Long getElanIdFromAclInterface(String elanInterfaceName) {
1150 AclInterface aclInterface = aclInterfaceCache.get(elanInterfaceName);
1151 if (null != aclInterface) {
1152 return aclInterface.getElanId();
1157 protected abstract boolean isValidDirection(Class<? extends DirectionBase> direction);
1159 protected abstract short getAclConntrackSenderTable();
1161 protected abstract short getAclForExistingTrafficTable();
1163 protected abstract short getAclFilterCumDispatcherTable();
1165 protected abstract short getAclRuleBasedFilterTable();
1167 protected abstract short getAclRemoteAclTable();
1169 protected abstract short getAclCommitterTable();