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.genius.infra.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.stream.Collectors;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
27 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
28 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
29 import org.opendaylight.genius.mdsalutil.ActionInfo;
30 import org.opendaylight.genius.mdsalutil.FlowEntity;
31 import org.opendaylight.genius.mdsalutil.InstructionInfo;
32 import org.opendaylight.genius.mdsalutil.MDSALUtil;
33 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
34 import org.opendaylight.genius.mdsalutil.NwConstants;
35 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack;
36 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack.NxCtAction;
37 import org.opendaylight.genius.mdsalutil.actions.ActionNxCtClear;
38 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
39 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
40 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
41 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
42 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
43 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchCtState;
44 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
45 import org.opendaylight.netvirt.aclservice.api.AclInterfaceCache;
46 import org.opendaylight.netvirt.aclservice.api.AclServiceListener;
47 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.Action;
48 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
49 import org.opendaylight.netvirt.aclservice.utils.AclConntrackClassifierType;
50 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
51 import org.opendaylight.netvirt.aclservice.utils.AclDataUtil;
52 import org.opendaylight.netvirt.aclservice.utils.AclServiceOFFlowBuilder;
53 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntries;
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.SecurityRuleAttr;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.SubnetInfo;
69 import org.slf4j.Logger;
70 import org.slf4j.LoggerFactory;
72 public abstract class AbstractAclServiceImpl implements AclServiceListener {
74 private static final Logger LOG = LoggerFactory.getLogger(AbstractAclServiceImpl.class);
76 protected final IMdsalApiManager mdsalManager;
77 protected final ManagedNewTransactionRunner txRunner;
78 protected final Class<? extends ServiceModeBase> serviceMode;
79 protected final AclDataUtil aclDataUtil;
80 protected final AclServiceUtils aclServiceUtils;
81 protected final JobCoordinator jobCoordinator;
82 protected final AclInterfaceCache aclInterfaceCache;
84 protected final Class<? extends DirectionBase> direction;
85 protected final String directionString;
88 * Initialize the member variables.
90 * @param serviceMode the service mode
91 * @param dataBroker the data broker instance.
92 * @param mdsalManager the mdsal manager instance.
93 * @param aclDataUtil the acl data util.
94 * @param aclServiceUtils the acl service util.
95 * @param jobCoordinator the job coordinator
96 * @param aclInterfaceCache the acl interface cache
98 public AbstractAclServiceImpl(Class<? extends ServiceModeBase> serviceMode, DataBroker dataBroker,
99 IMdsalApiManager mdsalManager, AclDataUtil aclDataUtil, AclServiceUtils aclServiceUtils,
100 JobCoordinator jobCoordinator, AclInterfaceCache aclInterfaceCache) {
101 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
102 this.mdsalManager = mdsalManager;
103 this.serviceMode = serviceMode;
104 this.aclDataUtil = aclDataUtil;
105 this.aclServiceUtils = aclServiceUtils;
106 this.jobCoordinator = jobCoordinator;
107 this.aclInterfaceCache = aclInterfaceCache;
110 this.serviceMode.equals(ServiceModeEgress.class) ? DirectionIngress.class : DirectionEgress.class;
111 this.directionString = this.direction.equals(DirectionEgress.class) ? "Egress" : "Ingress";
115 public boolean applyAcl(AclInterface port) {
117 LOG.error("port cannot be null");
120 if (port.getSecurityGroups() == null) {
121 LOG.info("Port {} without SGs", port.getInterfaceId());
124 BigInteger dpId = port.getDpId();
125 if (dpId == null || port.getLPortTag() == null) {
126 LOG.error("Unable to find DpId from ACL interface with id {}", port.getInterfaceId());
129 LOG.debug("Applying ACL on port {} with DpId {}", port, dpId);
130 List<FlowEntity> flowEntries = new ArrayList<>();
131 programAcl(flowEntries, port, Action.ADD, NwConstants.ADD_FLOW);
132 updateRemoteAclFilterTable(flowEntries, port, NwConstants.ADD_FLOW);
133 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, NwConstants.ADD_FLOW);
138 public boolean bindAcl(AclInterface port) {
139 if (port == null || port.getSecurityGroups() == null) {
140 LOG.error("Port and port security groups cannot be null for binding ACL service, port={}", port);
148 public boolean unbindAcl(AclInterface port) {
150 LOG.error("Port cannot be null for unbinding ACL service");
153 if (port.getDpId() != null) {
160 public boolean updateAcl(AclInterface portBefore, AclInterface portAfter) {
161 // this check is to avoid situations of port update coming before interface state is up
162 if (portAfter.getDpId() == null || portAfter.getLPortTag() == null) {
163 LOG.debug("Unable to find DpId from ACL interface with id {} and lport {}", portAfter.getInterfaceId(),
164 portAfter.getLPortTag());
167 boolean result = true;
168 boolean isPortSecurityEnable = portAfter.isPortSecurityEnabled();
169 boolean isPortSecurityEnableBefore = portBefore.isPortSecurityEnabled();
170 // if port security is changed, apply/remove Acls
171 if (isPortSecurityEnableBefore != isPortSecurityEnable) {
172 LOG.debug("On ACL update, Port security is {} for {}", isPortSecurityEnable ? "Enabled" :
173 "Disabled", portAfter.getInterfaceId());
174 if (isPortSecurityEnable) {
175 result = applyAcl(portAfter);
177 result = removeAcl(portBefore);
179 } else if (isPortSecurityEnable) {
180 // Acls has been updated, find added/removed Acls and act accordingly.
181 processInterfaceUpdate(portBefore, portAfter);
182 LOG.debug("On ACL update, ACL has been updated for {}", portAfter.getInterfaceId());
188 private void processInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
189 List<FlowEntity> addFlowEntries = new ArrayList<>();
190 List<FlowEntity> deleteFlowEntries = new ArrayList<>();
191 List<AllowedAddressPairs> addedAaps = AclServiceUtils
192 .getUpdatedAllowedAddressPairs(portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs());
193 List<AllowedAddressPairs> deletedAaps = AclServiceUtils
194 .getUpdatedAllowedAddressPairs(portBefore.getAllowedAddressPairs(), portAfter.getAllowedAddressPairs());
195 if (deletedAaps != null && !deletedAaps.isEmpty()) {
196 programAclWithAllowedAddress(deleteFlowEntries, portBefore, deletedAaps, Action.UPDATE,
197 NwConstants.DEL_FLOW);
198 updateRemoteAclFilterTable(deleteFlowEntries, portBefore, portBefore.getSecurityGroups(), deletedAaps,
199 NwConstants.DEL_FLOW);
201 if (addedAaps != null && !addedAaps.isEmpty()) {
202 programAclWithAllowedAddress(addFlowEntries, portAfter, addedAaps, Action.UPDATE, NwConstants.ADD_FLOW);
203 updateRemoteAclFilterTable(addFlowEntries, portAfter, portAfter.getSecurityGroups(), addedAaps,
204 NwConstants.ADD_FLOW);
206 if (portAfter.getSubnetInfo() != null && portBefore.getSubnetInfo() == null) {
207 programBroadcastRules(addFlowEntries, portAfter, Action.UPDATE, NwConstants.ADD_FLOW);
209 handleSubnetChange(portBefore, portAfter, addFlowEntries, deleteFlowEntries);
211 List<Uuid> addedAcls = AclServiceUtils.getUpdatedAclList(portAfter.getSecurityGroups(),
212 portBefore.getSecurityGroups());
213 List<Uuid> deletedAcls = AclServiceUtils.getUpdatedAclList(portBefore.getSecurityGroups(),
214 portAfter.getSecurityGroups());
215 if (!deletedAcls.isEmpty() || !addedAcls.isEmpty()) {
216 handleAclChange(deleteFlowEntries, portBefore, deletedAcls, NwConstants.DEL_FLOW);
217 handleAclChange(addFlowEntries, portAfter, addedAcls, NwConstants.ADD_FLOW);
220 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + portAfter.getInterfaceId(), deleteFlowEntries,
221 NwConstants.DEL_FLOW);
222 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + portAfter.getInterfaceId(), addFlowEntries,
223 NwConstants.ADD_FLOW);
226 private void handleSubnetChange(AclInterface portBefore, AclInterface portAfter,
227 List<FlowEntity> addFlowEntries, List<FlowEntity> deleteFlowEntries) {
228 List<SubnetInfo> deletedSubnets =
229 AclServiceUtils.getSubnetDiff(portBefore.getSubnetInfo(), portAfter.getSubnetInfo());
230 List<SubnetInfo> addedSubnets =
231 AclServiceUtils.getSubnetDiff(portAfter.getSubnetInfo(), portBefore.getSubnetInfo());
233 if (deletedSubnets != null && !deletedSubnets.isEmpty()) {
234 programIcmpv6RARule(deleteFlowEntries, portAfter, deletedSubnets, NwConstants.DEL_FLOW);
235 programSubnetBroadcastRules(deleteFlowEntries, portAfter, deletedSubnets, NwConstants.DEL_FLOW);
237 if (addedSubnets != null && !addedSubnets.isEmpty()) {
238 programIcmpv6RARule(addFlowEntries, portAfter, addedSubnets, NwConstants.ADD_FLOW);
239 programSubnetBroadcastRules(addFlowEntries, portAfter, addedSubnets, NwConstants.ADD_FLOW);
243 private void handleAclChange(List<FlowEntity> flowEntries, AclInterface port, List<Uuid> aclList,
245 int operationForAclRules = addOrRemove == NwConstants.DEL_FLOW ? NwConstants.MOD_FLOW : addOrRemove;
246 programAclRules(flowEntries, port, aclList, operationForAclRules);
247 updateRemoteAclFilterTable(flowEntries, port, aclList, port.getAllowedAddressPairs(), addOrRemove);
248 programAclDispatcherTable(flowEntries, port, addOrRemove);
251 protected SortedSet<Integer> getRemoteAclTags(AclInterface port) {
252 return this.direction == DirectionIngress.class ? port.getIngressRemoteAclTags()
253 : port.getEgressRemoteAclTags();
256 protected void programAclDispatcherTable(List<FlowEntity> flowEntries, AclInterface port, int addOrRemove) {
257 SortedSet<Integer> remoteAclTags = getRemoteAclTags(port);
258 if (remoteAclTags.isEmpty()) {
259 LOG.debug("No {} rules with remote group id for port={}", this.directionString, port.getInterfaceId());
262 Integer firstRemoteAclTag = remoteAclTags.first();
263 Integer lastRemoteAclTag = remoteAclTags.last();
265 programFirstRemoteAclEntryInDispatcherTable(flowEntries, port, firstRemoteAclTag, addOrRemove);
266 programLastRemoteAclEntryInDispatcherTable(flowEntries, port, lastRemoteAclTag, addOrRemove);
268 Integer previousRemoteAclTag = firstRemoteAclTag;
269 for (Integer remoteAclTag : remoteAclTags) {
270 if (remoteAclTag.equals(firstRemoteAclTag)) {
273 List<MatchInfoBase> matches = new ArrayList<>();
274 matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(),
275 previousRemoteAclTag, serviceMode));
276 String flowId = this.directionString + "_ACL_Dispatcher_" + port.getDpId() + "_" + port.getLPortTag() + "_"
279 List<InstructionInfo> instructions =
280 AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRuleBasedFilterTable());
281 instructions.add(AclServiceUtils.getWriteMetadataForRemoteAclTag(remoteAclTag));
282 addFlowEntryToList(flowEntries, port.getDpId(), getAclFilterCumDispatcherTable(), flowId,
283 AclConstants.ACE_GOTO_NEXT_REMOTE_ACL_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
284 instructions, addOrRemove);
286 previousRemoteAclTag = remoteAclTag;
290 protected void programFirstRemoteAclEntryInDispatcherTable(List<FlowEntity> flowEntries, AclInterface port,
291 Integer firstRemoteAclTag, int addOrRemove) {
292 List<MatchInfoBase> matches = new ArrayList<>();
293 matches.add(AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode));
294 String flowId = this.directionString + "_ACL_Dispatcher_First_" + port.getDpId() + "_" + port.getLPortTag()
295 + "_" + firstRemoteAclTag;
297 List<InstructionInfo> instructions =
298 AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRuleBasedFilterTable());
299 instructions.add(AclServiceUtils.getWriteMetadataForRemoteAclTag(firstRemoteAclTag));
300 addFlowEntryToList(flowEntries, port.getDpId(), getAclFilterCumDispatcherTable(), flowId,
301 AclConstants.ACE_FIRST_REMOTE_ACL_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions,
305 protected void programLastRemoteAclEntryInDispatcherTable(List<FlowEntity> flowEntries, AclInterface port,
306 Integer lastRemoteAclTag, int addOrRemove) {
307 List<MatchInfoBase> matches = new ArrayList<>();
308 matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(), lastRemoteAclTag,
310 String flowId = this.directionString + "_ACL_Dispatcher_Last_" + port.getDpId() + "_" + port.getLPortTag() + "_"
313 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
314 addFlowEntryToList(flowEntries, port.getDpId(), getAclFilterCumDispatcherTable(), flowId,
315 AclConstants.ACE_LAST_REMOTE_ACL_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(port.getLPortTag()),
316 matches, instructions, addOrRemove);
319 private void programAcl(List<FlowEntity> flowEntries, AclInterface port, Action action, int addOrRemove) {
320 programAclWithAllowedAddress(flowEntries, port, port.getAllowedAddressPairs(), action, addOrRemove);
323 private void programAclWithAllowedAddress(List<FlowEntity> flowEntries, AclInterface port,
324 List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove) {
325 BigInteger dpId = port.getDpId();
326 int lportTag = port.getLPortTag();
327 LOG.debug("Applying ACL Allowed Address on DpId {}, lportTag {}, Action {}", dpId, lportTag, action);
328 String portId = port.getInterfaceId();
329 programAntiSpoofingRules(flowEntries, port, allowedAddresses, action, addOrRemove);
330 programAclPortSpecificFixedRules(flowEntries, dpId, allowedAddresses, lportTag, portId, action, addOrRemove);
331 if (action == Action.ADD || action == Action.REMOVE) {
332 programAclRules(flowEntries, port, port.getSecurityGroups(), addOrRemove);
333 programAclDispatcherTable(flowEntries, port, addOrRemove);
338 * Programs the acl custom rules.
340 * @param flowEntries the flow entries
341 * @param port acl interface
342 * @param aclUuidList the list of acl uuid to be applied
343 * @param addOrRemove whether to delete or add flow
344 * @return program succeeded
346 protected boolean programAclRules(List<FlowEntity> flowEntries, AclInterface port, List<Uuid> aclUuidList,
348 BigInteger dpId = port.getDpId();
349 LOG.debug("Applying custom rules on DpId {}, lportTag {}", dpId, port.getLPortTag());
350 if (aclUuidList == null || dpId == null) {
351 LOG.warn("{} ACL parameters can not be null. dpId={}, aclUuidList={}", this.directionString, dpId,
355 for (Uuid aclUuid : aclUuidList) {
356 Acl acl = this.aclDataUtil.getAcl(aclUuid.getValue());
358 LOG.warn("The ACL {} not found in cache", aclUuid.getValue());
361 AccessListEntries accessListEntries = acl.getAccessListEntries();
362 if (accessListEntries != null && accessListEntries.getAce() != null) {
363 for (Ace ace: accessListEntries.getAce()) {
364 programAceRule(flowEntries, port, aclUuid.getValue(), ace, addOrRemove);
372 * Programs the ace specific rule.
374 * @param flowEntries flow entries
375 * @param port acl interface
376 * @param aclName the acl name
377 * @param ace rule to be program
378 * @param addOrRemove whether to delete or add flow
380 protected void programAceRule(List<FlowEntity> flowEntries, AclInterface port, String aclName, Ace ace,
382 SecurityRuleAttr aceAttr = AclServiceUtils.getAccessListAttributes(ace);
383 if (aceAttr == null) {
384 LOG.error("Ace {} of Acl {} is either null or not having SecurityRuleAttr",
385 ((ace == null) ? null : ace.getRuleName()), aclName);
388 if (addOrRemove == NwConstants.ADD_FLOW && aceAttr.isDeleted()) {
389 LOG.trace("Ignoring {} rule which is already deleted", ace.getRuleName());
392 if (!isValidDirection(aceAttr.getDirection())) {
393 LOG.trace("Ignoring {} direction while processing for {} ACE Rule {}", aceAttr.getDirection(),
394 this.directionString, ace.getRuleName());
397 LOG.debug("Program {} ACE rule for dpId={}, lportTag={}, addOrRemove={}, ace={}, portId={}",
398 this.directionString, port.getDpId(), port.getLPortTag(), addOrRemove, ace.getRuleName(),
399 port.getInterfaceId());
401 Matches matches = ace.getMatches();
402 if (matches != null && matches.getAceType() instanceof AceIp) {
403 Map<String, List<MatchInfoBase>> flowMap = AclServiceOFFlowBuilder.programIpFlow(matches);
404 if (!AclServiceUtils.doesAceHaveRemoteGroupId(aceAttr)) {
405 // programming for ACE which doesn't have any remote group Id
406 programForAceNotHavingRemoteAclId(flowEntries, port, aclName, ace, flowMap, addOrRemove);
408 Uuid remoteAclId = aceAttr.getRemoteGroupId();
409 // programming for ACE which have remote group Id
410 programAceSpecificFlows(flowEntries, port, aclName, ace, flowMap, remoteAclId, addOrRemove);
415 protected void programForAceNotHavingRemoteAclId(List<FlowEntity> flowEntries, AclInterface port, String aclName,
416 Ace ace, @Nullable Map<String, List<MatchInfoBase>> flowMap, int addOrRemove) {
417 if (null == flowMap) {
420 MatchInfoBase lportTagMatch = AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode);
421 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclCommitterTable());
422 Integer flowPriority = this.aclServiceUtils.getAceFlowPriority(aclName);
424 for (Entry<String, List<MatchInfoBase>> entry : flowMap.entrySet()) {
425 String flowName = entry.getKey();
426 List<MatchInfoBase> matches = entry.getValue();
427 matches.add(lportTagMatch);
428 String flowId = flowName + this.directionString + "_" + port.getDpId() + "_" + port.getLPortTag() + "_"
429 + ace.key().getRuleName();
431 int operation = addOrRemove == NwConstants.MOD_FLOW ? NwConstants.DEL_FLOW : addOrRemove;
432 addFlowEntryToList(flowEntries, port.getDpId(), getAclFilterCumDispatcherTable(), flowId, flowPriority,
433 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, operation);
435 if (addOrRemove != NwConstants.DEL_FLOW) {
436 programAclForExistingTrafficTable(port, ace, addOrRemove, flowName, matches, flowPriority);
441 protected void programAceSpecificFlows(List<FlowEntity> flowEntries, AclInterface port, String aclName, Ace ace,
442 @Nullable Map<String, List<MatchInfoBase>> flowMap, Uuid remoteAclId, int addOrRemove) {
443 if (null == flowMap) {
446 Integer remoteAclTag = this.aclServiceUtils.getAclTag(remoteAclId);
447 if (remoteAclTag == null || remoteAclTag == AclConstants.INVALID_ACL_TAG) {
448 LOG.error("remoteAclTag={} is null or invalid for remoteAclId={}", remoteAclTag, remoteAclId);
451 List<MatchInfoBase> lportAndAclMatches =
452 AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(), remoteAclTag, serviceMode);
453 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRemoteAclTable());
454 Integer flowPriority = this.aclServiceUtils.getAceFlowPriority(aclName);
456 for (Entry<String, List<MatchInfoBase>> entry : flowMap.entrySet()) {
457 String flowName = entry.getKey();
458 List<MatchInfoBase> matches = entry.getValue();
459 matches.addAll(lportAndAclMatches);
460 String flowId = flowName + this.directionString + "_" + port.getDpId() + "_" + port.getLPortTag() + "_"
461 + ace.key().getRuleName();
463 int operation = addOrRemove == NwConstants.MOD_FLOW ? NwConstants.DEL_FLOW : addOrRemove;
464 addFlowEntryToList(flowEntries, port.getDpId(), getAclRuleBasedFilterTable(), flowId, flowPriority, 0, 0,
465 AclConstants.COOKIE_ACL_BASE, matches, instructions, operation);
467 if (addOrRemove != NwConstants.DEL_FLOW) {
468 programAclForExistingTrafficTable(port, ace, addOrRemove, flowName, matches, flowPriority);
473 private void programAclForExistingTrafficTable(AclInterface port, Ace ace, int addOrRemove, String flowName,
474 List<MatchInfoBase> matches, Integer priority) {
475 AceIp acl = (AceIp) ace.getMatches().getAceType();
476 final String newFlowName = flowName + this.directionString + "_" + port.getDpId() + "_" + port.getLPortTag()
477 + "_" + (acl.getAceIpVersion() instanceof AceIpv4 ? "_IPv4" : "_IPv6") + "_FlowAfterRuleDeleted";
479 final List<MatchInfoBase> newMatches =
480 matches.stream().filter(obj -> !(obj instanceof NxMatchCtState || obj instanceof MatchMetadata))
481 .collect(Collectors.toList());
482 newMatches.add(AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode));
483 newMatches.add(new NxMatchCtState(AclConstants.TRACKED_RPL_CT_STATE, AclConstants.TRACKED_RPL_CT_STATE_MASK));
485 List<InstructionInfo> instructions =
486 AclServiceUtils.createCtMarkInstructionForNewState(getAclFilterCumDispatcherTable(), port.getElanId());
487 // Reversing the flow add/delete operation for this table.
488 List<FlowEntity> flowEntries = new ArrayList<>();
489 int operation = addOrRemove == NwConstants.ADD_FLOW ? NwConstants.DEL_FLOW : NwConstants.ADD_FLOW;
490 addFlowEntryToList(flowEntries, port.getDpId(), getAclForExistingTrafficTable(), newFlowName, priority, 0,
491 AclServiceUtils.getHardTimoutForApplyStatefulChangeOnExistingTraffic(ace, aclServiceUtils),
492 AclConstants.COOKIE_ACL_BASE, newMatches, instructions, operation);
493 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, operation);
497 public boolean removeAcl(AclInterface port) {
498 if (port.getDpId() == null) {
499 LOG.warn("Unable to find DP Id from ACL interface with id {}", port.getInterfaceId());
502 List<FlowEntity> flowEntries = new ArrayList<>();
503 programAcl(flowEntries, port, Action.REMOVE, NwConstants.DEL_FLOW);
504 updateRemoteAclFilterTable(flowEntries, port, NwConstants.DEL_FLOW);
505 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, NwConstants.DEL_FLOW);
510 public boolean applyAce(AclInterface port, String aclName, Ace ace) {
511 if (!port.isPortSecurityEnabled() || port.getDpId() == null) {
514 List<FlowEntity> flowEntries = new ArrayList<>();
515 programAceRule(flowEntries, port, aclName, ace, NwConstants.ADD_FLOW);
516 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, NwConstants.ADD_FLOW);
521 public boolean removeAce(AclInterface port, String aclName, Ace ace) {
522 if (!port.isPortSecurityEnabled() || port.getDpId() == null) {
525 List<FlowEntity> flowEntries = new ArrayList<>();
526 programAceRule(flowEntries, port, aclName, ace, NwConstants.MOD_FLOW);
527 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, NwConstants.DEL_FLOW);
532 public void updateRemoteAcl(Acl aclBefore, Acl aclAfter, Collection<AclInterface> portsBefore) {
533 handleRemoteAclUpdate(aclBefore, aclAfter, portsBefore);
539 * @param aclInterface the acl interface
541 public abstract void bindService(AclInterface aclInterface);
546 * @param aclInterface the acl interface
548 protected abstract void unbindService(AclInterface aclInterface);
551 * Programs the anti-spoofing rules.
553 * @param flowEntries the flow entries
554 * @param port the acl interface
555 * @param allowedAddresses the allowed addresses
556 * @param action add/modify/remove action
557 * @param addOrRemove addorRemove
559 protected abstract void programAntiSpoofingRules(List<FlowEntity> flowEntries, AclInterface port,
560 List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove);
563 * Programs broadcast rules.
565 * @param flowEntries the flow entries
566 * @param port the Acl Interface port
567 * @param addOrRemove whether to delete or add flow
569 protected abstract void programBroadcastRules(List<FlowEntity> flowEntries, AclInterface port, Action action,
573 * Programs broadcast rules.
575 * @param flowEntries the flow entries
576 * @param port the Acl Interface port
577 * @param subnetInfoList the port subnet info list
578 * @param addOrRemove whether to delete or add flow
580 protected abstract void programSubnetBroadcastRules(List<FlowEntity> flowEntries, AclInterface port,
581 List<SubnetInfo> subnetInfoList, int addOrRemove);
583 protected abstract void programIcmpv6RARule(List<FlowEntity> flowEntries, AclInterface port,
584 List<SubnetInfo> subnets, int addOrRemove);
604 * the list of matches to be writted
605 * @param instructions
606 * the list of instruction to be written.
608 * add or remove the entries.
610 protected void addFlowEntryToList(List<FlowEntity> flowEntries, BigInteger dpId, short tableId, String flowId,
611 int priority, int idleTimeOut, int hardTimeOut, BigInteger cookie, List<? extends MatchInfoBase> matches,
612 List<InstructionInfo> instructions, int addOrRemove) {
613 List<InstructionInfo> instructionInfos = null;
614 if (addOrRemove == NwConstants.ADD_FLOW) {
615 instructionInfos = instructions;
617 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority,
618 flowId, idleTimeOut, hardTimeOut, cookie, matches, instructionInfos);
619 LOG.trace("Adding flow to list: DpnId {}, flowId {}", dpId, flowId);
620 flowEntries.add(flowEntity);
623 protected void programFlows(String jobName, List<FlowEntity> flowEntries, int addOrRemove) {
624 List<List<FlowEntity>> flowEntityParts = Lists.partition(flowEntries, AclConstants.FLOWS_PER_TRANSACTION);
625 for (List<FlowEntity> part : flowEntityParts) {
626 jobCoordinator.enqueueJob(jobName,
627 () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
629 if (addOrRemove == NwConstants.ADD_FLOW) {
630 for (FlowEntity flowEntity: part) {
631 mdsalManager.addFlow(tx, flowEntity);
634 for (FlowEntity flowEntity: part) {
635 mdsalManager.removeFlow(tx, flowEntity);
638 })), AclConstants.JOB_MAX_RETRIES);
642 protected List<InstructionInfo> getDispatcherTableResubmitInstructions() {
643 return getDispatcherTableResubmitInstructions(new ArrayList<>());
647 * Gets the dispatcher table resubmit instructions based on ingress/egress service mode w.r.t switch.
649 * @param actionsInfos
651 * @return the instructions for dispatcher table resubmit
653 protected List<InstructionInfo> getDispatcherTableResubmitInstructions(List<ActionInfo> actionsInfos) {
654 short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
655 if (ServiceModeEgress.class.equals(this.serviceMode)) {
656 dispatcherTableId = NwConstants.EGRESS_LPORT_DISPATCHER_TABLE;
659 List<InstructionInfo> instructions = new ArrayList<>();
660 actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
661 instructions.add(new InstructionApplyActions(actionsInfos));
665 protected void handleRemoteAclUpdate(Acl aclBefore, Acl aclAfter, Collection<AclInterface> portsBefore) {
666 String aclName = aclAfter.getAclName();
667 Collection<AclInterface> interfaceList = aclDataUtil.getInterfaceList(new Uuid(aclName));
668 if (interfaceList.isEmpty()) {
669 LOG.trace("handleRemoteAclUpdate: No interfaces found with ACL={}", aclName);
672 Set<Uuid> remoteAclsBefore = AclServiceUtils.getRemoteAclIdsByDirection(aclBefore, this.direction);
673 Set<Uuid> remoteAclsAfter = AclServiceUtils.getRemoteAclIdsByDirection(aclAfter, this.direction);
675 Set<Uuid> remoteAclsAdded = new HashSet<>(remoteAclsAfter);
676 remoteAclsAdded.removeAll(remoteAclsBefore);
678 Set<Uuid> remoteAclsDeleted = new HashSet<>(remoteAclsBefore);
679 remoteAclsDeleted.removeAll(remoteAclsAfter);
681 List<FlowEntity> addFlowEntries = new ArrayList<>();
682 List<FlowEntity> deleteFlowEntries = new ArrayList<>();
683 if (!remoteAclsAdded.isEmpty() || !remoteAclsDeleted.isEmpty()) {
684 // delete and add flows in ACL dispatcher table for all applicable
686 for (AclInterface portBefore : portsBefore) {
687 programAclDispatcherTable(deleteFlowEntries, portBefore, NwConstants.DEL_FLOW);
689 for (AclInterface port : interfaceList) {
690 programAclDispatcherTable(addFlowEntries, port, NwConstants.ADD_FLOW);
693 Set<BigInteger> dpns = interfaceList.stream().map(AclInterface::getDpId).collect(Collectors.toSet());
695 programRemoteAclTable(deleteFlowEntries, aclName, remoteAclsDeleted, dpns, NwConstants.DEL_FLOW);
696 programRemoteAclTable(addFlowEntries, aclName, remoteAclsAdded, dpns, NwConstants.ADD_FLOW);
698 programFlows(aclName, deleteFlowEntries, NwConstants.DEL_FLOW);
699 programFlows(aclName, addFlowEntries, NwConstants.ADD_FLOW);
702 private void programRemoteAclTable(List<FlowEntity> flowEntries, String aclName, Set<Uuid> remoteAclIds,
703 Set<BigInteger> dpns, int addOrRemove) {
704 for (Uuid remoteAclId : remoteAclIds) {
705 Collection<AclInterface> remoteAclInterfaces = aclDataUtil.getInterfaceList(remoteAclId);
706 if (remoteAclInterfaces.isEmpty()) {
709 Set<AllowedAddressPairs> aaps =
710 remoteAclInterfaces.stream().map(AclInterface::getAllowedAddressPairs).flatMap(List::stream)
711 .filter(AclServiceUtils::isNotIpAllNetwork).collect(Collectors.toSet());
713 Integer aclTag = aclServiceUtils.getAclTag(remoteAclId);
714 if (addOrRemove == NwConstants.ADD_FLOW) {
715 for (BigInteger dpn : dpns) {
716 for (AllowedAddressPairs aap : aaps) {
717 programRemoteAclTableFlow(flowEntries, dpn, aclTag, aap, addOrRemove);
720 } else if (addOrRemove == NwConstants.DEL_FLOW) {
721 Set<BigInteger> remoteAclDpns = new HashSet<>();
722 Map<String, Set<AclInterface>> mapAclWithPortSet =
723 aclDataUtil.getRemoteAclInterfaces(remoteAclId, this.direction);
724 if (mapAclWithPortSet != null) {
725 Map<String, Set<AclInterface>> copyOfMapAclWithPortSet = new HashMap<>(mapAclWithPortSet);
726 copyOfMapAclWithPortSet.remove(aclName);
727 remoteAclDpns = collectDpns(copyOfMapAclWithPortSet);
729 Set<BigInteger> dpnsToOperate = new HashSet<>(dpns);
730 dpnsToOperate.removeAll(remoteAclDpns);
732 "Deleting flows in Remote ACL table for remoteAclId={}, direction={}, dpnsToOperate={}, "
733 + "remoteAclDpns={}, dpns={}",
734 remoteAclId.getValue(), directionString, dpnsToOperate, remoteAclDpns, dpns);
736 for (BigInteger dpn : dpnsToOperate) {
737 for (AllowedAddressPairs aap : aaps) {
738 programRemoteAclTableFlow(flowEntries, dpn, aclTag, aap, addOrRemove);
745 private void updateRemoteAclFilterTable(List<FlowEntity> flowEntries, AclInterface port, int addOrRemove) {
746 updateRemoteAclFilterTable(flowEntries, port, port.getSecurityGroups(), port.getAllowedAddressPairs(),
750 private void updateRemoteAclFilterTable(List<FlowEntity> flowEntries, AclInterface port, List<Uuid> aclList,
751 List<AllowedAddressPairs> aaps, int addOrRemove) {
752 if (aclList == null) {
753 LOG.debug("Port {} without SGs", port.getInterfaceId());
756 String portId = port.getInterfaceId();
757 LOG.trace("updateRemoteAclFilterTable for portId={}, aclList={}, aaps={}, addOrRemove={}", portId, aclList,
759 for (Uuid aclId : aclList) {
760 if (aclDataUtil.getRemoteAcl(aclId, this.direction) != null) {
761 Integer aclTag = aclServiceUtils.getAclTag(aclId);
762 if (addOrRemove == NwConstants.ADD_FLOW) {
763 syncRemoteAclTable(flowEntries, portId, aclId, aclTag, aaps, addOrRemove);
765 else if (addOrRemove == NwConstants.DEL_FLOW) {
766 jobCoordinator.enqueueJob(aclId.getValue(), () -> {
767 List<FlowEntity> remoteTableFlowEntries = new ArrayList<>();
768 syncRemoteAclTable(remoteTableFlowEntries, portId, aclId, aclTag, aaps, addOrRemove);
769 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + aclId.getValue(),
770 remoteTableFlowEntries, NwConstants.DEL_FLOW);
771 return Collections.emptyList();
776 Set<Uuid> remoteAclIds = aclServiceUtils.getRemoteAclIdsByDirection(aclList, direction);
777 for (Uuid remoteAclId : remoteAclIds) {
778 syncRemoteAclTableFromOtherDpns(flowEntries, port, remoteAclId, addOrRemove);
782 private void syncRemoteAclTable(List<FlowEntity> flowEntries, String portId, Uuid acl, Integer aclTag,
783 List<AllowedAddressPairs> aaps, int addOrRemove) {
784 Map<String, Set<AclInterface>> mapAclWithPortSet = aclDataUtil.getRemoteAclInterfaces(acl, this.direction);
785 Set<BigInteger> dpns = collectDpns(mapAclWithPortSet);
786 for (AllowedAddressPairs aap : aaps) {
787 if (!AclServiceUtils.isNotIpAllNetwork(aap)) {
790 if (aclServiceUtils.skipDeleteInCaseOfOverlappingIP(portId, acl, aap.getIpAddress(),
792 LOG.debug("Skipping delete of IP={} in remote ACL table for remoteAclId={}, portId={}",
793 aap.getIpAddress(), portId, acl.getValue());
796 for (BigInteger dpId : dpns) {
797 programRemoteAclTableFlow(flowEntries, dpId, aclTag, aap, addOrRemove);
802 private void syncRemoteAclTableFromOtherDpns(List<FlowEntity> flowEntries, AclInterface port, Uuid remoteAclId,
804 Collection<AclInterface> aclInterfaces = aclDataUtil.getInterfaceList(remoteAclId);
806 if (!aclInterfaces.isEmpty() && isFirstPortInDpnWithRemoteAclId(port, remoteAclId)) {
807 Integer aclTag = aclServiceUtils.getAclTag(remoteAclId);
808 for (AclInterface aclInterface : aclInterfaces) {
809 if (port.getInterfaceId().equals(aclInterface.getInterfaceId())) {
812 for (AllowedAddressPairs aap : aclInterface.getAllowedAddressPairs()) {
813 if (AclServiceUtils.isNotIpAllNetwork(aap)) {
814 programRemoteAclTableFlow(flowEntries, port.getDpId(), aclTag, aap, addOrRemove);
821 private boolean isFirstPortInDpnWithRemoteAclId(AclInterface port, Uuid remoteAclId) {
822 String portId = port.getInterfaceId();
823 BigInteger dpId = port.getDpId();
824 Map<String, Set<AclInterface>> remoteAclInterfacesMap =
825 aclDataUtil.getRemoteAclInterfaces(remoteAclId, direction);
826 if (remoteAclInterfacesMap != null) {
827 for (Set<AclInterface> interfaceSet : remoteAclInterfacesMap.values()) {
828 for (AclInterface aclInterface : interfaceSet) {
829 if (portId.equals(aclInterface.getInterfaceId())) {
832 if (dpId.equals(aclInterface.getDpId())) {
841 protected abstract void programRemoteAclTableFlow(List<FlowEntity> flowEntries, BigInteger dpId, Integer aclTag,
842 AllowedAddressPairs aap, int addOrRemove);
844 protected Set<BigInteger> collectDpns(@Nullable Map<String, Set<AclInterface>> mapAclWithPortSet) {
845 Set<BigInteger> dpns = new HashSet<>();
846 if (mapAclWithPortSet == null) {
849 for (Set<AclInterface> innerSet : mapAclWithPortSet.values()) {
850 if (innerSet == null) {
853 for (AclInterface inter : innerSet) {
854 dpns.add(inter.getDpId());
861 * Programs the port specific fixed rules.
863 * @param flowEntries the flow entries
864 * @param dpId the dp id
865 * @param allowedAddresses the allowed addresses
866 * @param lportTag the lport tag
867 * @param portId the portId
868 * @param action the action
869 * @param write whether to add or remove the flow.
871 protected void programAclPortSpecificFixedRules(List<FlowEntity> flowEntries, BigInteger dpId,
872 List<AllowedAddressPairs> allowedAddresses, int lportTag, String portId, Action action, int write) {
873 programGotoClassifierTableRules(flowEntries, dpId, allowedAddresses, lportTag, write);
874 if (action == Action.ADD || action == Action.REMOVE) {
875 programConntrackRecircRules(flowEntries, dpId, allowedAddresses, lportTag, portId, write);
876 programPortSpecificDropRules(flowEntries, dpId, lportTag, write);
877 programAclCommitRules(flowEntries, dpId, lportTag, portId, write);
879 LOG.info("programAclPortSpecificFixedRules: flows for dpId={}, lportId={}, action={}, write={}", dpId, lportTag,
883 protected abstract void programGotoClassifierTableRules(List<FlowEntity> flowEntries, BigInteger dpId,
884 List<AllowedAddressPairs> aaps, int lportTag, int addOrRemove);
887 * Adds the rule to send the packet to the netfilter to check whether it is a known packet.
889 * @param flowEntries the flow entries
890 * @param dpId the dpId
891 * @param aaps the allowed address pairs
892 * @param lportTag the lport tag
893 * @param portId the portId
894 * @param addOrRemove whether to add or remove the flow
896 protected void programConntrackRecircRules(List<FlowEntity> flowEntries, BigInteger dpId,
897 List<AllowedAddressPairs> aaps, int lportTag, String portId, int addOrRemove) {
898 if (AclServiceUtils.doesIpv4AddressExists(aaps)) {
899 programConntrackRecircRule(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV4, addOrRemove);
901 if (AclServiceUtils.doesIpv6AddressExists(aaps)) {
902 programConntrackRecircRule(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV6, addOrRemove);
906 protected void programConntrackRecircRule(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
907 String portId, MatchEthernetType matchEtherType, int addOrRemove) {
908 List<MatchInfoBase> matches = new ArrayList<>();
909 matches.add(matchEtherType);
910 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
912 List<InstructionInfo> instructions = new ArrayList<>();
913 if (addOrRemove == NwConstants.ADD_FLOW) {
914 Long elanTag = getElanIdFromAclInterface(portId);
915 if (elanTag == null) {
916 LOG.error("ElanId not found for portId={}; Context: dpId={}, lportTag={}, addOrRemove={},", portId,
917 dpId, lportTag, addOrRemove);
920 List<ActionInfo> actionsInfos = new ArrayList<>();
921 actionsInfos.add(new ActionNxConntrack(2, 0, 0, elanTag.intValue(), getAclForExistingTrafficTable()));
922 instructions.add(new InstructionApplyActions(actionsInfos));
926 this.directionString + "_Fixed_Conntrk_" + dpId + "_" + lportTag + "_" + matchEtherType + "_Recirc";
927 addFlowEntryToList(flowEntries, dpId, getAclConntrackSenderTable(), flowName,
928 AclConstants.ACL_DEFAULT_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions,
933 * Adds the rules to drop the unknown/invalid packets .
935 * @param flowEntries the flow entries
936 * @param dpId the dpId
937 * @param lportTag the lport tag
938 * @param addOrRemove whether to add or remove the flow
940 protected void programPortSpecificDropRules(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
942 LOG.debug("Programming Drop Rules: DpId={}, lportTag={}, addOrRemove={}", dpId, lportTag, addOrRemove);
943 programConntrackInvalidDropRule(flowEntries, dpId, lportTag, addOrRemove);
944 programAclRuleMissDropRule(flowEntries, dpId, lportTag, addOrRemove);
948 * Adds the rule to drop the conntrack invalid packets .
950 * @param flowEntries the flow entries
951 * @param dpId the dpId
952 * @param lportTag the lport tag
953 * @param addOrRemove whether to add or remove the flow
955 protected void programConntrackInvalidDropRule(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
957 List<MatchInfoBase> matches = AclServiceOFFlowBuilder.addLPortTagMatches(lportTag,
958 AclConstants.TRACKED_INV_CT_STATE, AclConstants.TRACKED_INV_CT_STATE_MASK, serviceMode);
959 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
961 String flowId = this.directionString + "_Fixed_Conntrk_Drop" + dpId + "_" + lportTag + "_Tracked_Invalid";
962 addFlowEntryToList(flowEntries, dpId, getAclFilterCumDispatcherTable(), flowId,
963 AclConstants.CT_STATE_TRACKED_INVALID_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(lportTag),
964 matches, instructions, addOrRemove);
968 * Program ACL rule miss drop rule for a port.
970 * @param flowEntries the flow entries
971 * @param dpId the dp id
972 * @param lportTag the lport tag
973 * @param addOrRemove the add or remove
975 protected void programAclRuleMissDropRule(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
977 List<MatchInfoBase> matches = new ArrayList<>();
978 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
979 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
981 String flowId = this.directionString + "_Fixed_Acl_Rule_Miss_Drop_" + dpId + "_" + lportTag;
982 addFlowEntryToList(flowEntries, dpId, getAclFilterCumDispatcherTable(), flowId,
983 AclConstants.ACL_PORT_SPECIFIC_DROP_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(lportTag),
984 matches, instructions, addOrRemove);
988 * Program acl commit rules.
990 * @param flowEntries the flow entries
991 * @param dpId the dp id
992 * @param lportTag the lport tag
993 * @param portId the port id
994 * @param addOrRemove the add or remove
996 protected void programAclCommitRules(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag, String portId,
998 programAclCommitRuleForConntrack(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV4, addOrRemove);
999 programAclCommitRuleForConntrack(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV6, addOrRemove);
1000 programAclCommitRuleForNonConntrack(flowEntries, dpId, lportTag, addOrRemove);
1004 * Program acl commit rule for conntrack.
1006 * @param flowEntries the flow entries
1007 * @param dpId the dp id
1008 * @param lportTag the lport tag
1009 * @param portId the port id
1010 * @param matchEtherType the match ether type
1011 * @param addOrRemove the add or remove
1013 protected void programAclCommitRuleForConntrack(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
1014 String portId, MatchEthernetType matchEtherType, int addOrRemove) {
1015 List<MatchInfoBase> matches = new ArrayList<>();
1016 matches.add(matchEtherType);
1017 matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndConntrackClassifierType(lportTag,
1018 AclConntrackClassifierType.CONNTRACK_SUPPORTED, serviceMode));
1020 List<ActionInfo> actionsInfos = new ArrayList<>();
1021 if (addOrRemove == NwConstants.ADD_FLOW) {
1022 Long elanId = getElanIdFromAclInterface(portId);
1023 if (elanId == null) {
1024 LOG.error("ElanId not found for portId={}; Context: dpId={}, lportTag={}, addOrRemove={}", portId, dpId,
1025 lportTag, addOrRemove);
1028 List<NxCtAction> ctActionsList =
1029 Lists.newArrayList(new ActionNxConntrack.NxCtMark(AclConstants.CT_MARK_EST_STATE));
1030 actionsInfos.add(new ActionNxConntrack(2, 1, 0, elanId.intValue(), (short) 255, ctActionsList));
1031 actionsInfos.add(new ActionNxCtClear());
1033 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions(actionsInfos);
1035 String flowName = directionString + "_Acl_Commit_Conntrack_" + dpId + "_" + lportTag + "_" + matchEtherType;
1036 // Flow for conntrack traffic to commit and resubmit to dispatcher
1037 addFlowEntryToList(flowEntries, dpId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY,
1038 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
1042 * Program acl commit rule for non conntrack.
1044 * @param flowEntries the flow entries
1045 * @param dpId the dp id
1046 * @param lportTag the lport tag
1047 * @param addOrRemove the add or remove
1049 protected void programAclCommitRuleForNonConntrack(List<FlowEntity> flowEntries, BigInteger dpId, int lportTag,
1051 List<MatchInfoBase> matches = new ArrayList<>();
1052 matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndConntrackClassifierType(lportTag,
1053 AclConntrackClassifierType.NON_CONNTRACK_SUPPORTED, serviceMode));
1055 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
1056 String flowName = this.directionString + "_Acl_Commit_Non_Conntrack_" + dpId + "_" + lportTag;
1057 // Flow for non-conntrack traffic to resubmit to dispatcher
1058 addFlowEntryToList(flowEntries, dpId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY,
1059 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
1063 protected Long getElanIdFromAclInterface(String elanInterfaceName) {
1064 AclInterface aclInterface = aclInterfaceCache.get(elanInterfaceName);
1065 if (null != aclInterface) {
1066 return aclInterface.getElanId();
1071 protected abstract boolean isValidDirection(Class<? extends DirectionBase> direction);
1073 protected abstract short getAclConntrackSenderTable();
1075 protected abstract short getAclForExistingTrafficTable();
1077 protected abstract short getAclFilterCumDispatcherTable();
1079 protected abstract short getAclRuleBasedFilterTable();
1081 protected abstract short getAclRemoteAclTable();
1083 protected abstract short getAclCommitterTable();