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.access.list.entries.Ace;
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.Matches;
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.ace.type.AceIp;
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.ace.ip.ace.ip.version.AceIpv4;
59 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionIngress;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl.InterfaceType;
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.opendaylight.yangtools.yang.common.Uint64;
70 import org.slf4j.Logger;
71 import org.slf4j.LoggerFactory;
73 public abstract class AbstractAclServiceImpl implements AclServiceListener {
75 private static final Logger LOG = LoggerFactory.getLogger(AbstractAclServiceImpl.class);
77 protected final IMdsalApiManager mdsalManager;
78 protected final ManagedNewTransactionRunner txRunner;
79 protected final Class<? extends ServiceModeBase> serviceMode;
80 protected final AclDataUtil aclDataUtil;
81 protected final AclServiceUtils aclServiceUtils;
82 protected final JobCoordinator jobCoordinator;
83 protected final AclInterfaceCache aclInterfaceCache;
85 protected final Class<? extends DirectionBase> direction;
86 protected final String directionString;
89 * Initialize the member variables.
91 * @param serviceMode the service mode
92 * @param dataBroker the data broker instance.
93 * @param mdsalManager the mdsal manager instance.
94 * @param aclDataUtil the acl data util.
95 * @param aclServiceUtils the acl service util.
96 * @param jobCoordinator the job coordinator
97 * @param aclInterfaceCache the acl interface cache
99 public AbstractAclServiceImpl(Class<? extends ServiceModeBase> serviceMode, DataBroker dataBroker,
100 IMdsalApiManager mdsalManager, AclDataUtil aclDataUtil, AclServiceUtils aclServiceUtils,
101 JobCoordinator jobCoordinator, AclInterfaceCache aclInterfaceCache) {
102 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
103 this.mdsalManager = mdsalManager;
104 this.serviceMode = serviceMode;
105 this.aclDataUtil = aclDataUtil;
106 this.aclServiceUtils = aclServiceUtils;
107 this.jobCoordinator = jobCoordinator;
108 this.aclInterfaceCache = aclInterfaceCache;
111 this.serviceMode.equals(ServiceModeEgress.class) ? DirectionIngress.class : DirectionEgress.class;
112 this.directionString = this.direction.equals(DirectionEgress.class) ? "Egress" : "Ingress";
116 public boolean applyAcl(AclInterface port) {
118 LOG.error("port cannot be null");
121 BigInteger dpId = port.getDpId();
122 if (dpId == null || port.getLPortTag() == null) {
123 LOG.error("Unable to find DpId from ACL interface with id {}", port.getInterfaceId());
127 LOG.debug("Applying ACL on port {} with DpId {}", port, dpId);
128 List<FlowEntity> flowEntries = new ArrayList<>();
129 if (port.getInterfaceType() == InterfaceType.DhcpService) {
130 programDhcpService(flowEntries, port, Action.ADD, NwConstants.ADD_FLOW);
132 if (port.getSecurityGroups() == null) {
133 LOG.info("Port {} without SGs", port.getInterfaceId());
136 programAcl(flowEntries, port, Action.ADD, NwConstants.ADD_FLOW);
137 updateRemoteAclFilterTable(flowEntries, port, NwConstants.ADD_FLOW);
139 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, NwConstants.ADD_FLOW);
144 public boolean bindAcl(AclInterface port) {
146 LOG.error("Port cannot be null for binding ACL service");
154 public boolean unbindAcl(AclInterface port) {
156 LOG.error("Port cannot be null for unbinding ACL service");
159 if (port.getDpId() != null) {
166 public boolean updateAcl(AclInterface portBefore, AclInterface portAfter) {
167 // this check is to avoid situations of port update coming before interface state is up
168 if (portAfter.getDpId() == null || portAfter.getLPortTag() == null) {
169 LOG.debug("Unable to find DpId from ACL interface with id {} and lport {}", portAfter.getInterfaceId(),
170 portAfter.getLPortTag());
173 boolean result = true;
174 boolean isPortSecurityEnable = portAfter.isPortSecurityEnabled();
175 boolean isPortSecurityEnableBefore = portBefore.isPortSecurityEnabled();
176 // if port security is changed, apply/remove Acls
177 if (isPortSecurityEnableBefore != isPortSecurityEnable) {
178 LOG.debug("On ACL update, Port security is {} for {}", isPortSecurityEnable ? "Enabled" :
179 "Disabled", portAfter.getInterfaceId());
180 if (isPortSecurityEnable) {
181 result = applyAcl(portAfter);
183 result = removeAcl(portBefore);
185 } else if (isPortSecurityEnable) {
186 // Acls has been updated, find added/removed Acls and act accordingly.
187 processInterfaceUpdate(portBefore, portAfter);
188 LOG.debug("On ACL update, ACL has been updated for {}", portAfter.getInterfaceId());
189 } else if (portAfter.getInterfaceType() == InterfaceType.DhcpService) {
190 processDhcpServiceInterfaceUpdate(portBefore, portAfter);
196 private void processDhcpServiceInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
197 List<FlowEntity> addFlowEntries = new ArrayList<>();
198 List<FlowEntity> deleteFlowEntries = new ArrayList<>();
199 List<AllowedAddressPairs> addedAaps = AclServiceUtils
200 .getUpdatedAllowedAddressPairs(portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs());
201 List<AllowedAddressPairs> deletedAaps = AclServiceUtils
202 .getUpdatedAllowedAddressPairs(portBefore.getAllowedAddressPairs(), portAfter.getAllowedAddressPairs());
203 if (!deletedAaps.isEmpty()) {
204 processDhcpServiceUpdate(deleteFlowEntries, portBefore, deletedAaps, NwConstants.DEL_FLOW);
206 if (!addedAaps.isEmpty()) {
207 processDhcpServiceUpdate(addFlowEntries, portAfter, addedAaps, NwConstants.ADD_FLOW);
209 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + portAfter.getInterfaceId(), deleteFlowEntries,
210 NwConstants.DEL_FLOW);
211 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + portAfter.getInterfaceId(), addFlowEntries,
212 NwConstants.ADD_FLOW);
215 private void processInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
216 List<FlowEntity> addFlowEntries = new ArrayList<>();
217 List<FlowEntity> deleteFlowEntries = new ArrayList<>();
218 List<AllowedAddressPairs> addedAaps = AclServiceUtils
219 .getUpdatedAllowedAddressPairs(portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs());
220 List<AllowedAddressPairs> deletedAaps = AclServiceUtils
221 .getUpdatedAllowedAddressPairs(portBefore.getAllowedAddressPairs(), portAfter.getAllowedAddressPairs());
222 if (!deletedAaps.isEmpty()) {
223 programAclWithAllowedAddress(deleteFlowEntries, portBefore, deletedAaps, Action.UPDATE,
224 NwConstants.DEL_FLOW);
225 updateRemoteAclFilterTable(deleteFlowEntries, portBefore, portBefore.getSecurityGroups(), deletedAaps,
226 NwConstants.DEL_FLOW);
228 if (!addedAaps.isEmpty()) {
229 programAclWithAllowedAddress(addFlowEntries, portAfter, addedAaps, Action.UPDATE, NwConstants.ADD_FLOW);
230 updateRemoteAclFilterTable(addFlowEntries, portAfter, portAfter.getSecurityGroups(), addedAaps,
231 NwConstants.ADD_FLOW);
233 if (portAfter.getSubnetInfo() != null && portBefore.getSubnetInfo() == null) {
234 programBroadcastRules(addFlowEntries, portAfter, Action.UPDATE, NwConstants.ADD_FLOW);
236 handleSubnetChange(portBefore, portAfter, addFlowEntries, deleteFlowEntries);
238 List<Uuid> addedAcls = AclServiceUtils.getUpdatedAclList(portAfter.getSecurityGroups(),
239 portBefore.getSecurityGroups());
240 List<Uuid> deletedAcls = AclServiceUtils.getUpdatedAclList(portBefore.getSecurityGroups(),
241 portAfter.getSecurityGroups());
242 if (!deletedAcls.isEmpty() || !addedAcls.isEmpty()) {
243 handleAclChange(deleteFlowEntries, portBefore, deletedAcls, NwConstants.DEL_FLOW);
244 handleAclChange(addFlowEntries, portAfter, addedAcls, NwConstants.ADD_FLOW);
247 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + portAfter.getInterfaceId(), deleteFlowEntries,
248 NwConstants.DEL_FLOW);
249 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + portAfter.getInterfaceId(), addFlowEntries,
250 NwConstants.ADD_FLOW);
253 private void handleSubnetChange(AclInterface portBefore, AclInterface portAfter,
254 List<FlowEntity> addFlowEntries, List<FlowEntity> deleteFlowEntries) {
255 List<SubnetInfo> deletedSubnets =
256 AclServiceUtils.getSubnetDiff(portBefore.getSubnetInfo(), portAfter.getSubnetInfo());
257 List<SubnetInfo> addedSubnets =
258 AclServiceUtils.getSubnetDiff(portAfter.getSubnetInfo(), portBefore.getSubnetInfo());
260 if (deletedSubnets != null && !deletedSubnets.isEmpty()) {
261 programIcmpv6RARule(deleteFlowEntries, portAfter, deletedSubnets, NwConstants.DEL_FLOW);
262 programSubnetBroadcastRules(deleteFlowEntries, portAfter, deletedSubnets, NwConstants.DEL_FLOW);
264 if (addedSubnets != null && !addedSubnets.isEmpty()) {
265 programIcmpv6RARule(addFlowEntries, portAfter, addedSubnets, NwConstants.ADD_FLOW);
266 programSubnetBroadcastRules(addFlowEntries, portAfter, addedSubnets, NwConstants.ADD_FLOW);
270 private void handleAclChange(List<FlowEntity> flowEntries, AclInterface port, List<Uuid> aclList,
272 int operationForAclRules = addOrRemove == NwConstants.DEL_FLOW ? NwConstants.MOD_FLOW : addOrRemove;
273 programAclRules(flowEntries, port, aclList, operationForAclRules);
274 updateRemoteAclFilterTable(flowEntries, port, aclList, port.getAllowedAddressPairs(), addOrRemove);
275 programAclDispatcherTable(flowEntries, port, addOrRemove);
278 protected SortedSet<Integer> getRemoteAclTags(AclInterface port) {
279 return this.direction == DirectionIngress.class ? port.getIngressRemoteAclTags()
280 : port.getEgressRemoteAclTags();
283 protected void programAclDispatcherTable(List<FlowEntity> flowEntries, AclInterface port, int addOrRemove) {
284 SortedSet<Integer> remoteAclTags = getRemoteAclTags(port);
285 if (remoteAclTags.isEmpty()) {
286 LOG.debug("No {} rules with remote group id for port={}", this.directionString, port.getInterfaceId());
289 Integer firstRemoteAclTag = remoteAclTags.first();
290 Integer lastRemoteAclTag = remoteAclTags.last();
292 programFirstRemoteAclEntryInDispatcherTable(flowEntries, port, firstRemoteAclTag, addOrRemove);
293 programLastRemoteAclEntryInDispatcherTable(flowEntries, port, lastRemoteAclTag, addOrRemove);
295 Integer previousRemoteAclTag = firstRemoteAclTag;
296 for (Integer remoteAclTag : remoteAclTags) {
297 if (remoteAclTag.equals(firstRemoteAclTag)) {
300 List<MatchInfoBase> matches = new ArrayList<>();
301 matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(),
302 previousRemoteAclTag, serviceMode));
303 String flowId = this.directionString + "_ACL_Dispatcher_" + port.getDpId() + "_" + port.getLPortTag() + "_"
306 List<InstructionInfo> instructions =
307 AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRuleBasedFilterTable());
308 instructions.add(AclServiceUtils.getWriteMetadataForRemoteAclTag(remoteAclTag));
309 addFlowEntryToList(flowEntries, Uint64.valueOf(port.getDpId()), getAclFilterCumDispatcherTable(), flowId,
310 AclConstants.ACE_GOTO_NEXT_REMOTE_ACL_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
311 instructions, addOrRemove);
313 previousRemoteAclTag = remoteAclTag;
317 protected void programFirstRemoteAclEntryInDispatcherTable(List<FlowEntity> flowEntries, AclInterface port,
318 Integer firstRemoteAclTag, int addOrRemove) {
319 List<MatchInfoBase> matches = new ArrayList<>();
320 matches.add(AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode));
321 String flowId = this.directionString + "_ACL_Dispatcher_First_" + port.getDpId() + "_" + port.getLPortTag()
322 + "_" + firstRemoteAclTag;
324 List<InstructionInfo> instructions =
325 AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRuleBasedFilterTable());
326 instructions.add(AclServiceUtils.getWriteMetadataForRemoteAclTag(firstRemoteAclTag));
327 addFlowEntryToList(flowEntries, Uint64.valueOf(port.getDpId()), getAclFilterCumDispatcherTable(), flowId,
328 AclConstants.ACE_FIRST_REMOTE_ACL_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions,
332 protected void programLastRemoteAclEntryInDispatcherTable(List<FlowEntity> flowEntries, AclInterface port,
333 Integer lastRemoteAclTag, int addOrRemove) {
334 List<MatchInfoBase> matches = new ArrayList<>();
335 matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(), lastRemoteAclTag,
337 String flowId = this.directionString + "_ACL_Dispatcher_Last_" + port.getDpId() + "_" + port.getLPortTag() + "_"
340 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
341 addFlowEntryToList(flowEntries, Uint64.valueOf(port.getDpId()), getAclFilterCumDispatcherTable(), flowId,
342 AclConstants.ACE_LAST_REMOTE_ACL_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(port.getLPortTag()),
343 matches, instructions, addOrRemove);
346 private void programAcl(List<FlowEntity> flowEntries, AclInterface port, Action action, int addOrRemove) {
347 programAclWithAllowedAddress(flowEntries, port, port.getAllowedAddressPairs(), action, addOrRemove);
350 private void programAclWithAllowedAddress(List<FlowEntity> flowEntries, AclInterface port,
351 List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove) {
352 Uint64 dpId = Uint64.valueOf(port.getDpId());
353 int lportTag = port.getLPortTag();
354 LOG.debug("Applying ACL Allowed Address on DpId {}, lportTag {}, Action {}", dpId, lportTag, action);
355 String portId = port.getInterfaceId();
356 programAntiSpoofingRules(flowEntries, port, allowedAddresses, action, addOrRemove);
357 programAclPortSpecificFixedRules(flowEntries, dpId, allowedAddresses, lportTag, portId, action, addOrRemove);
358 if (action == Action.ADD || action == Action.REMOVE) {
359 programAclRules(flowEntries, port, port.getSecurityGroups(), addOrRemove);
360 programAclDispatcherTable(flowEntries, port, addOrRemove);
365 * Programs the acl custom rules.
367 * @param flowEntries the flow entries
368 * @param port acl interface
369 * @param aclUuidList the list of acl uuid to be applied
370 * @param addOrRemove whether to delete or add flow
371 * @return program succeeded
373 protected boolean programAclRules(List<FlowEntity> flowEntries, AclInterface port, List<Uuid> aclUuidList,
375 BigInteger dpId = port.getDpId();
376 LOG.debug("Applying custom rules on DpId {}, lportTag {}", dpId, port.getLPortTag());
377 if (aclUuidList == null || dpId == null) {
378 LOG.warn("{} ACL parameters can not be null. dpId={}, aclUuidList={}", this.directionString, dpId,
382 for (Uuid aclUuid : aclUuidList) {
383 Acl acl = this.aclDataUtil.getAcl(aclUuid.getValue());
385 LOG.warn("The ACL {} not found in cache", aclUuid.getValue());
388 for (Ace ace : AclServiceUtils.aceList(acl)) {
389 programAceRule(flowEntries, port, aclUuid.getValue(), ace, addOrRemove);
396 * Programs the ace specific rule.
398 * @param flowEntries flow entries
399 * @param port acl interface
400 * @param aclName the acl name
401 * @param ace rule to be program
402 * @param addOrRemove whether to delete or add flow
404 protected void programAceRule(List<FlowEntity> flowEntries, AclInterface port, String aclName, Ace ace,
406 SecurityRuleAttr aceAttr = AclServiceUtils.getAccessListAttributes(ace);
407 if (aceAttr == null) {
408 LOG.error("Ace {} of Acl {} is either null or not having SecurityRuleAttr",
409 ace == null ? null : ace.getRuleName(), aclName);
412 if (addOrRemove == NwConstants.ADD_FLOW && aceAttr.isDeleted()) {
413 LOG.trace("Ignoring {} rule which is already deleted", ace.getRuleName());
416 if (!isValidDirection(aceAttr.getDirection())) {
417 LOG.trace("Ignoring {} direction while processing for {} ACE Rule {}", aceAttr.getDirection(),
418 this.directionString, ace.getRuleName());
421 LOG.debug("Program {} ACE rule for dpId={}, lportTag={}, addOrRemove={}, ace={}, portId={}",
422 this.directionString, port.getDpId(), port.getLPortTag(), addOrRemove, ace.getRuleName(),
423 port.getInterfaceId());
425 Matches matches = ace.getMatches();
426 if (matches != null && matches.getAceType() instanceof AceIp) {
427 Map<String, List<MatchInfoBase>> flowMap = AclServiceOFFlowBuilder.programIpFlow(matches);
428 if (!AclServiceUtils.doesAceHaveRemoteGroupId(aceAttr)) {
429 // programming for ACE which doesn't have any remote group Id
430 programForAceNotHavingRemoteAclId(flowEntries, port, aclName, ace, flowMap, addOrRemove);
432 Uuid remoteAclId = aceAttr.getRemoteGroupId();
433 // programming for ACE which have remote group Id
434 programAceSpecificFlows(flowEntries, port, aclName, ace, flowMap, remoteAclId, addOrRemove);
439 protected void programForAceNotHavingRemoteAclId(List<FlowEntity> flowEntries, AclInterface port, String aclName,
440 Ace ace, @Nullable Map<String, List<MatchInfoBase>> flowMap, int addOrRemove) {
441 if (null == flowMap) {
444 MatchInfoBase lportTagMatch = AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode);
445 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclCommitterTable());
446 Integer flowPriority = this.aclServiceUtils.getAceFlowPriority(aclName);
448 for (Entry<String, List<MatchInfoBase>> entry : flowMap.entrySet()) {
449 String flowName = entry.getKey();
450 List<MatchInfoBase> matches = entry.getValue();
451 matches.add(lportTagMatch);
452 String flowId = flowName + this.directionString + "_" + port.getDpId() + "_" + port.getLPortTag() + "_"
453 + ace.key().getRuleName();
455 int operation = addOrRemove == NwConstants.MOD_FLOW ? NwConstants.DEL_FLOW : addOrRemove;
456 addFlowEntryToList(flowEntries, Uint64.valueOf(port.getDpId()), getAclFilterCumDispatcherTable(),
457 flowId, flowPriority, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, operation);
459 if (addOrRemove != NwConstants.DEL_FLOW) {
460 programAclForExistingTrafficTable(port, ace, addOrRemove, flowName, matches, flowPriority);
465 protected void programAceSpecificFlows(List<FlowEntity> flowEntries, AclInterface port, String aclName, Ace ace,
466 @Nullable Map<String, List<MatchInfoBase>> flowMap, Uuid remoteAclId, int addOrRemove) {
467 if (null == flowMap) {
470 Integer remoteAclTag = this.aclServiceUtils.getAclTag(remoteAclId);
471 if (remoteAclTag == null || remoteAclTag == AclConstants.INVALID_ACL_TAG) {
472 LOG.error("remoteAclTag={} is null or invalid for remoteAclId={}", remoteAclTag, remoteAclId);
475 List<MatchInfoBase> lportAndAclMatches =
476 AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(), remoteAclTag, serviceMode);
477 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRemoteAclTable());
478 Integer flowPriority = this.aclServiceUtils.getAceFlowPriority(aclName);
480 for (Entry<String, List<MatchInfoBase>> entry : flowMap.entrySet()) {
481 String flowName = entry.getKey();
482 List<MatchInfoBase> matches = entry.getValue();
483 matches.addAll(lportAndAclMatches);
484 String flowId = flowName + this.directionString + "_" + port.getDpId() + "_" + port.getLPortTag() + "_"
485 + ace.key().getRuleName();
487 int operation = addOrRemove == NwConstants.MOD_FLOW ? NwConstants.DEL_FLOW : addOrRemove;
488 addFlowEntryToList(flowEntries, Uint64.valueOf(port.getDpId()), getAclRuleBasedFilterTable(), flowId,
489 flowPriority, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, operation);
491 if (addOrRemove != NwConstants.DEL_FLOW) {
492 programAclForExistingTrafficTable(port, ace, addOrRemove, flowName, matches, flowPriority);
497 private void programAclForExistingTrafficTable(AclInterface port, Ace ace, int addOrRemove, String flowName,
498 List<MatchInfoBase> matches, Integer priority) {
499 if (port == null || port.getElanId() == null) {
500 LOG.debug("Acl interface or elan id is null, No need to update traffic flow table.");
504 AceIp acl = (AceIp) ace.getMatches().getAceType();
505 final String newFlowName = flowName + this.directionString + "_" + port.getDpId() + "_" + port.getLPortTag()
506 + "_" + (acl.getAceIpVersion() instanceof AceIpv4 ? "_IPv4" : "_IPv6") + "_FlowAfterRuleDeleted";
508 final List<MatchInfoBase> newMatches =
509 matches.stream().filter(obj -> !(obj instanceof NxMatchCtState || obj instanceof MatchMetadata))
510 .collect(Collectors.toList());
511 newMatches.add(AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode));
512 newMatches.add(new NxMatchCtState(AclConstants.TRACKED_RPL_CT_STATE, AclConstants.TRACKED_RPL_CT_STATE_MASK));
514 List<InstructionInfo> instructions =
515 AclServiceUtils.createCtMarkInstructionForNewState(getAclFilterCumDispatcherTable(), port.getElanId());
516 // Reversing the flow add/delete operation for this table.
517 List<FlowEntity> flowEntries = new ArrayList<>();
518 int operation = addOrRemove == NwConstants.ADD_FLOW ? NwConstants.DEL_FLOW : NwConstants.ADD_FLOW;
519 addFlowEntryToList(flowEntries, Uint64.valueOf(port.getDpId()), getAclForExistingTrafficTable(), newFlowName,
520 priority, 0, AclServiceUtils.getHardTimoutForApplyStatefulChangeOnExistingTraffic(ace, aclServiceUtils),
521 AclConstants.COOKIE_ACL_BASE, newMatches, instructions, operation);
522 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, operation);
526 public boolean removeAcl(AclInterface port) {
527 if (port.getDpId() == null) {
528 LOG.warn("Unable to find DP Id from ACL interface with id {}", port.getInterfaceId());
531 List<FlowEntity> flowEntries = new ArrayList<>();
532 if (port.getInterfaceType() == InterfaceType.DhcpService) {
533 programDhcpService(flowEntries, port, Action.REMOVE, NwConstants.DEL_FLOW);
535 programAcl(flowEntries, port, Action.REMOVE, NwConstants.DEL_FLOW);
536 updateRemoteAclFilterTable(flowEntries, port, NwConstants.DEL_FLOW);
538 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, NwConstants.DEL_FLOW);
543 public boolean applyAce(AclInterface port, String aclName, Ace ace) {
544 if (!port.isPortSecurityEnabled() || port.getDpId() == null) {
547 List<FlowEntity> flowEntries = new ArrayList<>();
548 programAceRule(flowEntries, port, aclName, ace, NwConstants.ADD_FLOW);
549 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, NwConstants.ADD_FLOW);
554 public boolean removeAce(AclInterface port, String aclName, Ace ace) {
555 if (!port.isPortSecurityEnabled() || port.getDpId() == null) {
558 List<FlowEntity> flowEntries = new ArrayList<>();
559 programAceRule(flowEntries, port, aclName, ace, NwConstants.MOD_FLOW);
560 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + port.getInterfaceId(), flowEntries, NwConstants.DEL_FLOW);
565 public void updateRemoteAcl(Acl aclBefore, Acl aclAfter, Collection<AclInterface> portsBefore) {
566 handleRemoteAclUpdate(aclBefore, aclAfter, portsBefore);
572 * @param aclInterface the acl interface
574 public abstract void bindService(AclInterface aclInterface);
579 * @param aclInterface the acl interface
581 protected abstract void unbindService(AclInterface aclInterface);
584 * Programs DHCP Service flows.
586 * @param flowEntries the flow entries
587 * @param port the acl interface
588 * @param action add/modify/remove action
589 * @param addOrRemove addorRemove
591 protected abstract void programDhcpService(List<FlowEntity> flowEntries, AclInterface port,
592 Action action, int addOrRemove);
595 * Programs DHCP service flows.
597 * @param flowEntries the flow entries
598 * @param port the acl interface
599 * @param allowedAddresses the allowed addresses
600 * @param addOrRemove addorRemove
602 protected abstract void processDhcpServiceUpdate(List<FlowEntity> flowEntries, AclInterface port,
603 List<AllowedAddressPairs> allowedAddresses, int addOrRemove);
606 * Programs the anti-spoofing rules.
608 * @param flowEntries the flow entries
609 * @param port the acl interface
610 * @param allowedAddresses the allowed addresses
611 * @param action add/modify/remove action
612 * @param addOrRemove addorRemove
614 protected abstract void programAntiSpoofingRules(List<FlowEntity> flowEntries, AclInterface port,
615 List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove);
618 * Programs broadcast rules.
620 * @param flowEntries the flow entries
621 * @param port the Acl Interface port
622 * @param addOrRemove whether to delete or add flow
624 protected abstract void programBroadcastRules(List<FlowEntity> flowEntries, AclInterface port, Action action,
628 * Programs broadcast rules.
630 * @param flowEntries the flow entries
631 * @param port the Acl Interface port
632 * @param subnetInfoList the port subnet info list
633 * @param addOrRemove whether to delete or add flow
635 protected abstract void programSubnetBroadcastRules(List<FlowEntity> flowEntries, AclInterface port,
636 List<SubnetInfo> subnetInfoList, int addOrRemove);
638 protected abstract void programIcmpv6RARule(List<FlowEntity> flowEntries, AclInterface port,
639 List<SubnetInfo> subnets, int addOrRemove);
659 * the list of matches to be writted
660 * @param instructions
661 * the list of instruction to be written.
663 * add or remove the entries.
665 protected void addFlowEntryToList(List<FlowEntity> flowEntries, Uint64 dpId, short tableId, String flowId,
666 int priority, int idleTimeOut, int hardTimeOut, Uint64 cookie, List<? extends MatchInfoBase> matches,
667 List<InstructionInfo> instructions, int addOrRemove) {
668 List<InstructionInfo> instructionInfos = null;
669 if (addOrRemove == NwConstants.ADD_FLOW) {
670 instructionInfos = instructions;
672 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority,
673 flowId, idleTimeOut, hardTimeOut, cookie, matches, instructionInfos);
674 LOG.trace("Adding flow to list: DpnId {}, flowId {}", dpId, flowId);
675 flowEntries.add(flowEntity);
678 protected void programFlows(String jobName, List<FlowEntity> flowEntries, int addOrRemove) {
679 List<List<FlowEntity>> flowEntityParts = Lists.partition(flowEntries, AclConstants.FLOWS_PER_TRANSACTION);
680 for (List<FlowEntity> part : flowEntityParts) {
681 jobCoordinator.enqueueJob(jobName,
682 () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
684 if (addOrRemove == NwConstants.ADD_FLOW) {
685 for (FlowEntity flowEntity: part) {
686 mdsalManager.addFlow(tx, flowEntity);
689 for (FlowEntity flowEntity: part) {
690 mdsalManager.removeFlow(tx, flowEntity);
693 })), AclConstants.JOB_MAX_RETRIES);
697 protected List<InstructionInfo> getDispatcherTableResubmitInstructions() {
698 return getDispatcherTableResubmitInstructions(new ArrayList<>());
702 * Gets the dispatcher table resubmit instructions based on ingress/egress service mode w.r.t switch.
704 * @param actionsInfos
706 * @return the instructions for dispatcher table resubmit
708 protected List<InstructionInfo> getDispatcherTableResubmitInstructions(List<ActionInfo> actionsInfos) {
709 short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
710 if (ServiceModeEgress.class.equals(this.serviceMode)) {
711 dispatcherTableId = NwConstants.EGRESS_LPORT_DISPATCHER_TABLE;
714 List<InstructionInfo> instructions = new ArrayList<>();
715 actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
716 instructions.add(new InstructionApplyActions(actionsInfos));
720 protected void handleRemoteAclUpdate(Acl aclBefore, Acl aclAfter, Collection<AclInterface> portsBefore) {
721 String aclName = aclAfter.getAclName();
722 Collection<AclInterface> interfaceList = aclDataUtil.getInterfaceList(new Uuid(aclName));
723 if (interfaceList.isEmpty()) {
724 LOG.trace("handleRemoteAclUpdate: No interfaces found with ACL={}", aclName);
727 Set<Uuid> remoteAclsBefore = AclServiceUtils.getRemoteAclIdsByDirection(aclBefore, this.direction);
728 Set<Uuid> remoteAclsAfter = AclServiceUtils.getRemoteAclIdsByDirection(aclAfter, this.direction);
730 Set<Uuid> remoteAclsAdded = new HashSet<>(remoteAclsAfter);
731 remoteAclsAdded.removeAll(remoteAclsBefore);
733 Set<Uuid> remoteAclsDeleted = new HashSet<>(remoteAclsBefore);
734 remoteAclsDeleted.removeAll(remoteAclsAfter);
736 List<FlowEntity> addFlowEntries = new ArrayList<>();
737 List<FlowEntity> deleteFlowEntries = new ArrayList<>();
738 if (!remoteAclsAdded.isEmpty() || !remoteAclsDeleted.isEmpty()) {
739 // delete and add flows in ACL dispatcher table for all applicable
741 for (AclInterface portBefore : portsBefore) {
742 programAclDispatcherTable(deleteFlowEntries, portBefore, NwConstants.DEL_FLOW);
744 for (AclInterface port : interfaceList) {
745 programAclDispatcherTable(addFlowEntries, port, NwConstants.ADD_FLOW);
748 Set<BigInteger> dpns = interfaceList.stream().map(AclInterface::getDpId).collect(Collectors.toSet());
750 programRemoteAclTable(deleteFlowEntries, aclName, remoteAclsDeleted, dpns, NwConstants.DEL_FLOW);
751 programRemoteAclTable(addFlowEntries, aclName, remoteAclsAdded, dpns, NwConstants.ADD_FLOW);
753 programFlows(aclName, deleteFlowEntries, NwConstants.DEL_FLOW);
754 programFlows(aclName, addFlowEntries, NwConstants.ADD_FLOW);
757 private void programRemoteAclTable(List<FlowEntity> flowEntries, String aclName, Set<Uuid> remoteAclIds,
758 Set<BigInteger> dpns, int addOrRemove) {
759 for (Uuid remoteAclId : remoteAclIds) {
760 Collection<AclInterface> remoteAclInterfaces = aclDataUtil.getInterfaceList(remoteAclId);
761 if (remoteAclInterfaces.isEmpty()) {
764 Set<AllowedAddressPairs> aaps =
765 remoteAclInterfaces.stream().map(AclInterface::getAllowedAddressPairs).flatMap(List::stream)
766 .filter(AclServiceUtils::isNotIpAllNetwork).collect(Collectors.toSet());
768 Integer aclTag = aclServiceUtils.getAclTag(remoteAclId);
769 if (addOrRemove == NwConstants.ADD_FLOW) {
770 for (BigInteger dpn : dpns) {
771 for (AllowedAddressPairs aap : aaps) {
772 programRemoteAclTableFlow(flowEntries, Uint64.valueOf(dpn), aclTag, aap, addOrRemove);
775 } else if (addOrRemove == NwConstants.DEL_FLOW) {
776 Set<BigInteger> remoteAclDpns = new HashSet<>();
777 Map<String, Set<AclInterface>> mapAclWithPortSet =
778 aclDataUtil.getRemoteAclInterfaces(remoteAclId, this.direction);
779 if (mapAclWithPortSet != null) {
780 Map<String, Set<AclInterface>> copyOfMapAclWithPortSet = new HashMap<>(mapAclWithPortSet);
781 copyOfMapAclWithPortSet.remove(aclName);
782 remoteAclDpns = collectDpns(copyOfMapAclWithPortSet);
784 Set<BigInteger> dpnsToOperate = new HashSet<>(dpns);
785 dpnsToOperate.removeAll(remoteAclDpns);
787 "Deleting flows in Remote ACL table for remoteAclId={}, direction={}, dpnsToOperate={}, "
788 + "remoteAclDpns={}, dpns={}",
789 remoteAclId.getValue(), directionString, dpnsToOperate, remoteAclDpns, dpns);
791 for (BigInteger dpn : dpnsToOperate) {
792 for (AllowedAddressPairs aap : aaps) {
793 programRemoteAclTableFlow(flowEntries, Uint64.valueOf(dpn), aclTag, aap, addOrRemove);
800 private void updateRemoteAclFilterTable(List<FlowEntity> flowEntries, AclInterface port, int addOrRemove) {
801 updateRemoteAclFilterTable(flowEntries, port, port.getSecurityGroups(), port.getAllowedAddressPairs(),
805 private void updateRemoteAclFilterTable(List<FlowEntity> flowEntries, AclInterface port, List<Uuid> aclList,
806 List<AllowedAddressPairs> aaps, int addOrRemove) {
807 if (aclList == null) {
808 LOG.debug("Port {} without SGs", port.getInterfaceId());
811 String portId = port.getInterfaceId();
812 LOG.trace("updateRemoteAclFilterTable for portId={}, aclList={}, aaps={}, addOrRemove={}", portId, aclList,
814 for (Uuid aclId : aclList) {
815 if (aclDataUtil.getRemoteAcl(aclId, this.direction) != null) {
816 Integer aclTag = aclServiceUtils.getAclTag(aclId);
817 if (addOrRemove == NwConstants.ADD_FLOW) {
818 syncRemoteAclTable(flowEntries, portId, aclId, aclTag, aaps, addOrRemove);
820 else if (addOrRemove == NwConstants.DEL_FLOW) {
821 jobCoordinator.enqueueJob(aclId.getValue(), () -> {
822 List<FlowEntity> remoteTableFlowEntries = new ArrayList<>();
823 syncRemoteAclTable(remoteTableFlowEntries, portId, aclId, aclTag, aaps, addOrRemove);
824 programFlows(AclConstants.ACL_JOB_KEY_PREFIX + aclId.getValue(),
825 remoteTableFlowEntries, NwConstants.DEL_FLOW);
826 return Collections.emptyList();
831 Set<Uuid> remoteAclIds = aclServiceUtils.getRemoteAclIdsByDirection(aclList, direction);
832 for (Uuid remoteAclId : remoteAclIds) {
833 syncRemoteAclTableFromOtherDpns(flowEntries, port, remoteAclId, addOrRemove);
837 private void syncRemoteAclTable(List<FlowEntity> flowEntries, String portId, Uuid acl, Integer aclTag,
838 List<AllowedAddressPairs> aaps, int addOrRemove) {
839 Map<String, Set<AclInterface>> mapAclWithPortSet = aclDataUtil.getRemoteAclInterfaces(acl, this.direction);
840 Set<BigInteger> dpns = collectDpns(mapAclWithPortSet);
841 for (AllowedAddressPairs aap : aaps) {
842 if (!AclServiceUtils.isNotIpAllNetwork(aap)) {
845 if (aclServiceUtils.skipDeleteInCaseOfOverlappingIP(portId, acl, aap.getIpAddress(),
847 LOG.debug("Skipping delete of IP={} in remote ACL table for remoteAclId={}, portId={}",
848 aap.getIpAddress(), portId, acl.getValue());
851 for (BigInteger dpId : dpns) {
852 programRemoteAclTableFlow(flowEntries, Uint64.valueOf(dpId), aclTag, aap, addOrRemove);
857 private void syncRemoteAclTableFromOtherDpns(List<FlowEntity> flowEntries, AclInterface port, Uuid remoteAclId,
859 Collection<AclInterface> aclInterfaces = aclDataUtil.getInterfaceList(remoteAclId);
861 if (!aclInterfaces.isEmpty() && isFirstPortInDpnWithRemoteAclId(port, remoteAclId)) {
862 Integer aclTag = aclServiceUtils.getAclTag(remoteAclId);
863 for (AclInterface aclInterface : aclInterfaces) {
864 if (port.getInterfaceId().equals(aclInterface.getInterfaceId())) {
867 for (AllowedAddressPairs aap : aclInterface.getAllowedAddressPairs()) {
868 if (AclServiceUtils.isNotIpAllNetwork(aap)) {
869 programRemoteAclTableFlow(flowEntries, Uint64.valueOf(port.getDpId()),
870 aclTag, aap, addOrRemove);
877 private boolean isFirstPortInDpnWithRemoteAclId(AclInterface port, Uuid remoteAclId) {
878 String portId = port.getInterfaceId();
879 BigInteger dpId = port.getDpId();
880 Map<String, Set<AclInterface>> remoteAclInterfacesMap =
881 aclDataUtil.getRemoteAclInterfaces(remoteAclId, direction);
882 if (remoteAclInterfacesMap != null) {
883 for (Set<AclInterface> interfaceSet : remoteAclInterfacesMap.values()) {
884 for (AclInterface aclInterface : interfaceSet) {
885 if (portId.equals(aclInterface.getInterfaceId())) {
888 if (dpId.equals(aclInterface.getDpId())) {
897 protected abstract void programRemoteAclTableFlow(List<FlowEntity> flowEntries, Uint64 dpId, Integer aclTag,
898 AllowedAddressPairs aap, int addOrRemove);
900 protected Set<BigInteger> collectDpns(@Nullable Map<String, Set<AclInterface>> mapAclWithPortSet) {
901 Set<BigInteger> dpns = new HashSet<>();
902 if (mapAclWithPortSet == null) {
905 for (Set<AclInterface> innerSet : mapAclWithPortSet.values()) {
906 if (innerSet == null) {
909 for (AclInterface inter : innerSet) {
910 dpns.add(inter.getDpId());
917 * Programs the port specific fixed rules.
919 * @param flowEntries the flow entries
920 * @param dpId the dp id
921 * @param allowedAddresses the allowed addresses
922 * @param lportTag the lport tag
923 * @param portId the portId
924 * @param action the action
925 * @param write whether to add or remove the flow.
927 protected void programAclPortSpecificFixedRules(List<FlowEntity> flowEntries, Uint64 dpId,
928 List<AllowedAddressPairs> allowedAddresses, int lportTag, String portId, Action action, int write) {
929 programGotoClassifierTableRules(flowEntries, dpId, allowedAddresses, lportTag, write);
930 if (action == Action.ADD || action == Action.REMOVE) {
931 programConntrackRecircRules(flowEntries, dpId, allowedAddresses, lportTag, portId, write);
932 programPortSpecificDropRules(flowEntries, dpId, lportTag, write);
933 programAclCommitRules(flowEntries, dpId, lportTag, portId, write);
935 LOG.info("programAclPortSpecificFixedRules: flows for dpId={}, lportId={}, action={}, write={}", dpId, lportTag,
939 protected abstract void programGotoClassifierTableRules(List<FlowEntity> flowEntries, Uint64 dpId,
940 List<AllowedAddressPairs> aaps, int lportTag, int addOrRemove);
943 * Adds the rule to send the packet to the netfilter to check whether it is a known packet.
945 * @param flowEntries the flow entries
946 * @param dpId the dpId
947 * @param aaps the allowed address pairs
948 * @param lportTag the lport tag
949 * @param portId the portId
950 * @param addOrRemove whether to add or remove the flow
952 protected void programConntrackRecircRules(List<FlowEntity> flowEntries, Uint64 dpId,
953 List<AllowedAddressPairs> aaps, int lportTag, String portId, int addOrRemove) {
954 if (AclServiceUtils.doesIpv4AddressExists(aaps)) {
955 programConntrackRecircRule(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV4, addOrRemove);
957 if (AclServiceUtils.doesIpv6AddressExists(aaps)) {
958 programConntrackRecircRule(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV6, addOrRemove);
962 protected void programConntrackRecircRule(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
963 String portId, MatchEthernetType matchEtherType, int addOrRemove) {
964 List<MatchInfoBase> matches = new ArrayList<>();
965 matches.add(matchEtherType);
966 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
968 List<InstructionInfo> instructions = new ArrayList<>();
969 if (addOrRemove == NwConstants.ADD_FLOW) {
970 Long elanTag = getElanIdFromAclInterface(portId);
971 if (elanTag == null) {
972 LOG.error("ElanId not found for portId={}; Context: dpId={}, lportTag={}, addOrRemove={},", portId,
973 dpId, lportTag, addOrRemove);
976 List<ActionInfo> actionsInfos = new ArrayList<>();
977 actionsInfos.add(new ActionNxConntrack(2, 0, 0, elanTag.intValue(), getAclForExistingTrafficTable()));
978 instructions.add(new InstructionApplyActions(actionsInfos));
982 this.directionString + "_Fixed_Conntrk_" + dpId.toString() + "_"
983 + lportTag + "_" + matchEtherType + "_Recirc";
984 addFlowEntryToList(flowEntries, dpId, getAclConntrackSenderTable(), flowName,
985 AclConstants.ACL_DEFAULT_PRIORITY, 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions,
990 * Adds the rules to drop the unknown/invalid packets .
992 * @param flowEntries the flow entries
993 * @param dpId the dpId
994 * @param lportTag the lport tag
995 * @param addOrRemove whether to add or remove the flow
997 protected void programPortSpecificDropRules(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
999 LOG.debug("Programming Drop Rules: DpId={}, lportTag={}, addOrRemove={}", dpId, lportTag, addOrRemove);
1000 programConntrackInvalidDropRule(flowEntries, dpId, lportTag, addOrRemove);
1001 programAclRuleMissDropRule(flowEntries, dpId, lportTag, addOrRemove);
1005 * Adds the rule to drop the conntrack invalid packets .
1007 * @param flowEntries the flow entries
1008 * @param dpId the dpId
1009 * @param lportTag the lport tag
1010 * @param addOrRemove whether to add or remove the flow
1012 protected void programConntrackInvalidDropRule(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
1014 List<MatchInfoBase> matches = AclServiceOFFlowBuilder.addLPortTagMatches(lportTag,
1015 AclConstants.TRACKED_INV_CT_STATE, AclConstants.TRACKED_INV_CT_STATE_MASK, serviceMode);
1016 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
1018 String flowId = this.directionString + "_Fixed_Conntrk_Drop" + dpId.toString()
1019 + "_" + lportTag + "_Tracked_Invalid";
1020 addFlowEntryToList(flowEntries, dpId, getAclFilterCumDispatcherTable(), flowId,
1021 AclConstants.CT_STATE_TRACKED_INVALID_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(lportTag),
1022 matches, instructions, addOrRemove);
1026 * Program ACL rule miss drop rule for a port.
1028 * @param flowEntries the flow entries
1029 * @param dpId the dp id
1030 * @param lportTag the lport tag
1031 * @param addOrRemove the add or remove
1033 protected void programAclRuleMissDropRule(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
1035 List<MatchInfoBase> matches = new ArrayList<>();
1036 matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
1037 List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
1039 String flowId = this.directionString + "_Fixed_Acl_Rule_Miss_Drop_" + dpId.toString() + "_" + lportTag;
1040 addFlowEntryToList(flowEntries, dpId, getAclFilterCumDispatcherTable(), flowId,
1041 AclConstants.ACL_PORT_SPECIFIC_DROP_PRIORITY, 0, 0, AclServiceUtils.getDropFlowCookie(lportTag),
1042 matches, instructions, addOrRemove);
1046 * Program acl commit rules.
1048 * @param flowEntries the flow entries
1049 * @param dpId the dp id
1050 * @param lportTag the lport tag
1051 * @param portId the port id
1052 * @param addOrRemove the add or remove
1054 protected void programAclCommitRules(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag, String portId,
1056 programAclCommitRuleForConntrack(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV4, addOrRemove);
1057 programAclCommitRuleForConntrack(flowEntries, dpId, lportTag, portId, MatchEthernetType.IPV6, addOrRemove);
1058 programAclCommitRuleForNonConntrack(flowEntries, dpId, lportTag, addOrRemove);
1062 * Program acl commit rule for conntrack.
1064 * @param flowEntries the flow entries
1065 * @param dpId the dp id
1066 * @param lportTag the lport tag
1067 * @param portId the port id
1068 * @param matchEtherType the match ether type
1069 * @param addOrRemove the add or remove
1071 protected void programAclCommitRuleForConntrack(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
1072 String portId, MatchEthernetType matchEtherType, int addOrRemove) {
1073 List<MatchInfoBase> matches = new ArrayList<>();
1074 matches.add(matchEtherType);
1075 matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndConntrackClassifierType(lportTag,
1076 AclConntrackClassifierType.CONNTRACK_SUPPORTED, serviceMode));
1078 List<ActionInfo> actionsInfos = new ArrayList<>();
1079 if (addOrRemove == NwConstants.ADD_FLOW) {
1080 Long elanId = getElanIdFromAclInterface(portId);
1081 if (elanId == null) {
1082 LOG.error("ElanId not found for portId={}; Context: dpId={}, lportTag={}, addOrRemove={}", portId, dpId,
1083 lportTag, addOrRemove);
1086 List<NxCtAction> ctActionsList =
1087 Lists.newArrayList(new ActionNxConntrack.NxCtMark(AclConstants.CT_MARK_EST_STATE));
1088 actionsInfos.add(new ActionNxConntrack(2, 1, 0, elanId.intValue(), (short) 255, ctActionsList));
1089 actionsInfos.add(new ActionNxCtClear());
1091 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions(actionsInfos);
1093 String flowName = directionString + "_Acl_Commit_Conntrack_" + dpId.toString()
1094 + "_" + lportTag + "_" + matchEtherType;
1095 // Flow for conntrack traffic to commit and resubmit to dispatcher
1096 addFlowEntryToList(flowEntries, dpId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY,
1097 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
1101 * Program acl commit rule for non conntrack.
1103 * @param flowEntries the flow entries
1104 * @param dpId the dp id
1105 * @param lportTag the lport tag
1106 * @param addOrRemove the add or remove
1108 protected void programAclCommitRuleForNonConntrack(List<FlowEntity> flowEntries, Uint64 dpId, int lportTag,
1110 List<MatchInfoBase> matches = new ArrayList<>();
1111 matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndConntrackClassifierType(lportTag,
1112 AclConntrackClassifierType.NON_CONNTRACK_SUPPORTED, serviceMode));
1114 List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
1115 String flowName = this.directionString + "_Acl_Commit_Non_Conntrack_" + dpId + "_" + lportTag;
1116 // Flow for non-conntrack traffic to resubmit to dispatcher
1117 addFlowEntryToList(flowEntries, dpId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY,
1118 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
1122 protected Long getElanIdFromAclInterface(String elanInterfaceName) {
1123 AclInterface aclInterface = aclInterfaceCache.get(elanInterfaceName);
1124 if (null != aclInterface) {
1125 return aclInterface.getElanId();
1130 protected abstract boolean isValidDirection(Class<? extends DirectionBase> direction);
1132 protected abstract short getAclConntrackSenderTable();
1134 protected abstract short getAclForExistingTrafficTable();
1136 protected abstract short getAclFilterCumDispatcherTable();
1138 protected abstract short getAclRuleBasedFilterTable();
1140 protected abstract short getAclRemoteAclTable();
1142 protected abstract short getAclCommitterTable();