Fix logging issues in aclservice
[netvirt.git] / aclservice / impl / src / main / java / org / opendaylight / netvirt / aclservice / AbstractAclServiceImpl.java
1 /*
2  * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.aclservice;
9
10 import com.google.common.collect.Lists;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.Collections;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Map.Entry;
20 import java.util.Set;
21 import java.util.SortedSet;
22 import java.util.stream.Collectors;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
25 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
26 import org.opendaylight.genius.mdsalutil.ActionInfo;
27 import org.opendaylight.genius.mdsalutil.FlowEntity;
28 import org.opendaylight.genius.mdsalutil.InstructionInfo;
29 import org.opendaylight.genius.mdsalutil.MDSALUtil;
30 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
31 import org.opendaylight.genius.mdsalutil.NwConstants;
32 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack;
33 import org.opendaylight.genius.mdsalutil.actions.ActionNxConntrack.NxCtAction;
34 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
35 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
36 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
37 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
38 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
39 import org.opendaylight.genius.mdsalutil.nxmatches.NxMatchCtState;
40 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
41 import org.opendaylight.netvirt.aclservice.api.AclInterfaceCache;
42 import org.opendaylight.netvirt.aclservice.api.AclServiceListener;
43 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.Action;
44 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
45 import org.opendaylight.netvirt.aclservice.utils.AclConntrackClassifierType;
46 import org.opendaylight.netvirt.aclservice.utils.AclConstants;
47 import org.opendaylight.netvirt.aclservice.utils.AclDataUtil;
48 import org.opendaylight.netvirt.aclservice.utils.AclServiceOFFlowBuilder;
49 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntries;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
53 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;
54 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;
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.matches.ace.type.ace.ip.ace.ip.version.AceIpv4;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionBase;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionEgress;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.DirectionIngress;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
66
67 public abstract class AbstractAclServiceImpl implements AclServiceListener {
68
69     private static final Logger LOG = LoggerFactory.getLogger(AbstractAclServiceImpl.class);
70
71     protected final IMdsalApiManager mdsalManager;
72     protected final DataBroker dataBroker;
73     protected final ManagedNewTransactionRunner txRunner;
74     protected final Class<? extends ServiceModeBase> serviceMode;
75     protected final AclDataUtil aclDataUtil;
76     protected final AclServiceUtils aclServiceUtils;
77     protected final JobCoordinator jobCoordinator;
78     protected final AclInterfaceCache aclInterfaceCache;
79
80     protected final Class<? extends DirectionBase> direction;
81     protected final String directionString;
82
83     /**
84      * Initialize the member variables.
85      *
86      * @param serviceMode the service mode
87      * @param dataBroker the data broker instance.
88      * @param mdsalManager the mdsal manager instance.
89      * @param aclDataUtil the acl data util.
90      * @param aclServiceUtils the acl service util.
91      * @param jobCoordinator the job coordinator
92      * @param aclInterfaceCache the acl interface cache
93      */
94     public AbstractAclServiceImpl(Class<? extends ServiceModeBase> serviceMode, DataBroker dataBroker,
95             IMdsalApiManager mdsalManager, AclDataUtil aclDataUtil, AclServiceUtils aclServiceUtils,
96             JobCoordinator jobCoordinator, AclInterfaceCache aclInterfaceCache) {
97         this.dataBroker = dataBroker;
98         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
99         this.mdsalManager = mdsalManager;
100         this.serviceMode = serviceMode;
101         this.aclDataUtil = aclDataUtil;
102         this.aclServiceUtils = aclServiceUtils;
103         this.jobCoordinator = jobCoordinator;
104         this.aclInterfaceCache = aclInterfaceCache;
105
106         this.direction =
107                 this.serviceMode.equals(ServiceModeEgress.class) ? DirectionIngress.class : DirectionEgress.class;
108         this.directionString = this.direction.equals(DirectionEgress.class) ? "Egress" : "Ingress";
109     }
110
111     @Override
112     public boolean applyAcl(AclInterface port) {
113         if (port == null) {
114             LOG.error("port cannot be null");
115             return false;
116         }
117         if (port.getSecurityGroups() == null) {
118             LOG.info("Port {} without SGs", port.getInterfaceId());
119             return false;
120         }
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());
124             return false;
125         }
126         LOG.debug("Applying ACL on port {} with DpId {}", port, dpId);
127         programAcl(port, Action.ADD, NwConstants.ADD_FLOW);
128         updateRemoteAclFilterTable(port, NwConstants.ADD_FLOW);
129         return true;
130     }
131
132     @Override
133     public boolean bindAcl(AclInterface port) {
134         if (port == null || port.getSecurityGroups() == null) {
135             LOG.error("Port and port security groups cannot be null for binding ACL service, port={}", port);
136             return false;
137         }
138         bindService(port);
139         if (port.getDpId() != null) {
140             updateRemoteAclFilterTable(port, NwConstants.ADD_FLOW);
141         }
142         return true;
143     }
144
145     @Override
146     public boolean unbindAcl(AclInterface port) {
147         if (port == null) {
148             LOG.error("Port cannot be null for unbinding ACL service");
149             return false;
150         }
151         if (port.getDpId() != null) {
152             unbindService(port);
153             updateRemoteAclFilterTable(port, NwConstants.DEL_FLOW);
154         }
155         return true;
156     }
157
158     @Override
159     public boolean updateAcl(AclInterface portBefore, AclInterface portAfter) {
160         // this check is to avoid situations of port update coming before interface state is up
161         if (portAfter.getDpId() == null || portAfter.getLPortTag() == null) {
162             LOG.debug("Unable to find DpId from ACL interface with id {} and lport {}", portAfter.getInterfaceId(),
163                     portAfter.getLPortTag());
164             return false;
165         }
166         boolean result = true;
167         boolean isPortSecurityEnable = portAfter.isPortSecurityEnabled();
168         boolean isPortSecurityEnableBefore = portBefore.isPortSecurityEnabled();
169         // if port security is changed, apply/remove Acls
170         if (isPortSecurityEnableBefore != isPortSecurityEnable) {
171             LOG.debug("On ACL update, Port security is {} for {}", isPortSecurityEnable ? "Enabled" :
172                     "Disabled", portAfter.getInterfaceId());
173             if (isPortSecurityEnable) {
174                 result = applyAcl(portAfter);
175             } else {
176                 result = removeAcl(portBefore);
177             }
178         } else if (isPortSecurityEnable) {
179             // Acls has been updated, find added/removed Acls and act accordingly.
180             processInterfaceUpdate(portBefore, portAfter);
181             LOG.debug("On ACL update, ACL has been updated for {}", portAfter.getInterfaceId());
182         }
183
184         return result;
185     }
186
187     private void processInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
188         List<AllowedAddressPairs> addedAaps = AclServiceUtils
189                 .getUpdatedAllowedAddressPairs(portAfter.getAllowedAddressPairs(), portBefore.getAllowedAddressPairs());
190         List<AllowedAddressPairs> deletedAaps = AclServiceUtils
191                 .getUpdatedAllowedAddressPairs(portBefore.getAllowedAddressPairs(), portAfter.getAllowedAddressPairs());
192         if (deletedAaps != null && !deletedAaps.isEmpty()) {
193             programAclWithAllowedAddress(portBefore, deletedAaps, Action.UPDATE, NwConstants.DEL_FLOW);
194             updateRemoteAclFilterTable(portBefore, portBefore.getSecurityGroups(), deletedAaps, NwConstants.DEL_FLOW);
195         }
196         if (addedAaps != null && !addedAaps.isEmpty()) {
197             programAclWithAllowedAddress(portAfter, addedAaps, Action.UPDATE, NwConstants.ADD_FLOW);
198             updateRemoteAclFilterTable(portAfter, portAfter.getSecurityGroups(), addedAaps, NwConstants.ADD_FLOW);
199         }
200         if (portAfter.getSubnetIpPrefixes() != null && portBefore.getSubnetIpPrefixes() == null) {
201             programBroadcastRules(portAfter, NwConstants.ADD_FLOW);
202         }
203
204         List<Uuid> addedAcls = AclServiceUtils.getUpdatedAclList(portAfter.getSecurityGroups(),
205                 portBefore.getSecurityGroups());
206         List<Uuid> deletedAcls = AclServiceUtils.getUpdatedAclList(portBefore.getSecurityGroups(),
207                 portAfter.getSecurityGroups());
208         if (deletedAcls.isEmpty() && addedAcls.isEmpty()) {
209             LOG.trace("No change w.r.t ACL list for port={}", portAfter.getInterfaceId());
210             return;
211         }
212
213         handleAclChange(portBefore, deletedAcls, NwConstants.DEL_FLOW);
214         handleAclChange(portAfter, addedAcls, NwConstants.ADD_FLOW);
215     }
216
217     private void handleAclChange(AclInterface port, List<Uuid> aclList, int addOrRemove) {
218         int operationForAclRules = (addOrRemove == NwConstants.DEL_FLOW) ? NwConstants.MOD_FLOW : addOrRemove;
219         programAclRules(port, aclList, operationForAclRules);
220         updateRemoteAclFilterTable(port, aclList, port.getAllowedAddressPairs(), addOrRemove);
221         programAclDispatcherTable(port, addOrRemove);
222     }
223
224     protected SortedSet<Integer> getRemoteAclTags(AclInterface port) {
225         return this.direction == DirectionIngress.class ? port.getIngressRemoteAclTags()
226                 : port.getEgressRemoteAclTags();
227     }
228
229     protected void programAclDispatcherTable(AclInterface port, int addOrRemove) {
230         SortedSet<Integer> remoteAclTags = getRemoteAclTags(port);
231         if (remoteAclTags.isEmpty()) {
232             LOG.debug("No {} rules with remote group id for port={}", this.directionString, port.getInterfaceId());
233             return;
234         }
235         Integer firstRemoteAclTag = remoteAclTags.first();
236         Integer lastRemoteAclTag = remoteAclTags.last();
237
238         programFirstRemoteAclEntryInDispatcherTable(port, firstRemoteAclTag, addOrRemove);
239         programLastRemoteAclEntryInDispatcherTable(port, lastRemoteAclTag, addOrRemove);
240
241         Integer previousRemoteAclTag = firstRemoteAclTag;
242         for (Integer remoteAclTag : remoteAclTags) {
243             if (remoteAclTag.equals(firstRemoteAclTag)) {
244                 continue;
245             }
246             List<MatchInfoBase> matches = new ArrayList<>();
247             matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(),
248                     previousRemoteAclTag, serviceMode));
249             String flowId = this.directionString + "_ACL_Dispatcher_" + port.getDpId() + "_" + port.getLPortTag() + "_"
250                     + remoteAclTag;
251
252             List<InstructionInfo> instructions =
253                     AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRuleBasedFilterTable());
254             instructions.add(AclServiceUtils.getWriteMetadataForRemoteAclTag(remoteAclTag));
255             syncFlow(port.getDpId(), getAclFilterCumDispatcherTable(), flowId,
256                     AclConstants.ACE_GOTO_NEXT_REMOTE_ACL_PRIORITY, "ACL", 0, 0, AclConstants.COOKIE_ACL_BASE, matches,
257                     instructions, addOrRemove);
258
259             previousRemoteAclTag = remoteAclTag;
260         }
261     }
262
263     protected void programFirstRemoteAclEntryInDispatcherTable(AclInterface port, Integer firstRemoteAclTag,
264             int addOrRemove) {
265         List<MatchInfoBase> matches = new ArrayList<>();
266         matches.add(AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode));
267         String flowId = this.directionString + "_ACL_Dispatcher_First_" + port.getDpId() + "_" + port.getLPortTag()
268                 + "_" + firstRemoteAclTag;
269
270         List<InstructionInfo> instructions =
271                 AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRuleBasedFilterTable());
272         instructions.add(AclServiceUtils.getWriteMetadataForRemoteAclTag(firstRemoteAclTag));
273         syncFlow(port.getDpId(), getAclFilterCumDispatcherTable(), flowId, AclConstants.ACE_FIRST_REMOTE_ACL_PRIORITY,
274                 "ACL", 0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
275     }
276
277     protected void programLastRemoteAclEntryInDispatcherTable(AclInterface port, Integer lastRemoteAclTag,
278             int addOrRemove) {
279         List<MatchInfoBase> matches = new ArrayList<>();
280         matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(), lastRemoteAclTag,
281                 serviceMode));
282         String flowId = this.directionString + "_ACL_Dispatcher_Last_" + port.getDpId() + "_" + port.getLPortTag() + "_"
283                 + lastRemoteAclTag;
284
285         List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
286         syncFlow(port.getDpId(), getAclFilterCumDispatcherTable(), flowId, AclConstants.ACE_LAST_REMOTE_ACL_PRIORITY,
287                 "ACL", 0, 0, AclConstants.COOKIE_ACL_DROP_FLOW, matches, instructions, addOrRemove);
288     }
289
290     private void programAcl(AclInterface port, Action action, int addOrRemove) {
291         programAclWithAllowedAddress(port, port.getAllowedAddressPairs(), action, addOrRemove);
292     }
293
294     private void programAclWithAllowedAddress(AclInterface port, List<AllowedAddressPairs> allowedAddresses,
295             Action action, int addOrRemove) {
296         BigInteger dpId = port.getDpId();
297         int lportTag = port.getLPortTag();
298         LOG.debug("Applying ACL Allowed Address on DpId {}, lportTag {}, Action {}", dpId, lportTag, action);
299         String portId = port.getInterfaceId();
300         programAntiSpoofingRules(port, allowedAddresses, action, addOrRemove);
301         programAclPortSpecificFixedRules(dpId, allowedAddresses, lportTag, portId, action, addOrRemove);
302         if (action == Action.ADD || action == Action.REMOVE) {
303             programAclRules(port, port.getSecurityGroups(), addOrRemove);
304             programAclDispatcherTable(port, addOrRemove);
305         }
306     }
307
308     /**
309      * Programs the acl custom rules.
310      *
311      * @param port acl interface
312      * @param aclUuidList the list of acl uuid to be applied
313      * @param addOrRemove whether to delete or add flow
314      * @return program succeeded
315      */
316     protected boolean programAclRules(AclInterface port, List<Uuid> aclUuidList, int addOrRemove) {
317         BigInteger dpId = port.getDpId();
318         LOG.debug("Applying custom rules on DpId {}, lportTag {}", dpId, port.getLPortTag());
319         if (aclUuidList == null || dpId == null) {
320             LOG.warn("{} ACL parameters can not be null. dpId={}, aclUuidList={}", this.directionString, dpId,
321                     aclUuidList);
322             return false;
323         }
324         for (Uuid aclUuid : aclUuidList) {
325             Acl acl = this.aclDataUtil.getAcl(aclUuid.getValue());
326             if (null == acl) {
327                 LOG.warn("The ACL {} not found in cache", aclUuid.getValue());
328                 continue;
329             }
330             AccessListEntries accessListEntries = acl.getAccessListEntries();
331             List<Ace> aceList = accessListEntries.getAce();
332             for (Ace ace: aceList) {
333                 programAceRule(port, aclUuid.getValue(), ace, addOrRemove);
334             }
335         }
336         return true;
337     }
338
339     /**
340      * Programs the ace specific rule.
341      *
342      * @param port acl interface
343      * @param aclName the acl name
344      * @param ace rule to be program
345      * @param addOrRemove whether to delete or add flow
346      */
347     protected void programAceRule(AclInterface port, String aclName, Ace ace, int addOrRemove) {
348         SecurityRuleAttr aceAttr = AclServiceUtils.getAccesssListAttributes(ace);
349         if (!isValidDirection(aceAttr.getDirection())) {
350             LOG.trace("Ignoring {} direction while processing for {} ACE Rule {}", aceAttr.getDirection(),
351                     this.directionString, ace.getRuleName());
352             return;
353         }
354         LOG.debug("Program {} ACE rule for dpId={}, lportTag={}, addOrRemove={}, ace={}, portId={}",
355                 this.directionString, port.getDpId(), port.getLPortTag(), addOrRemove, ace.getRuleName(),
356                 port.getInterfaceId());
357
358         Matches matches = ace.getMatches();
359         Map<String, List<MatchInfoBase>> flowMap = null;
360         if (matches.getAceType() instanceof AceIp) {
361             flowMap = AclServiceOFFlowBuilder.programIpFlow(matches);
362             if (!AclServiceUtils.doesAceHaveRemoteGroupId(aceAttr)) {
363                 // programming for ACE which doesn't have any remote group Id
364                 programForAceNotHavingRemoteAclId(port, aclName, ace, flowMap, addOrRemove);
365             } else {
366                 Uuid remoteAclId = aceAttr.getRemoteGroupId();
367                 // programming for ACE which have remote group Id
368                 programAceSpecificFlows(port, aclName, ace, flowMap, remoteAclId, addOrRemove);
369             }
370         }
371     }
372
373     protected void programForAceNotHavingRemoteAclId(AclInterface port, String aclName, Ace ace,
374             Map<String, List<MatchInfoBase>> flowMap, int addOrRemove) {
375         if (null == flowMap) {
376             return;
377         }
378         MatchInfoBase lportTagMatch = AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode);
379         List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclCommitterTable());
380         Integer flowPriority = this.aclServiceUtils.getAceFlowPriority(aclName);
381
382         for (Entry<String, List<MatchInfoBase>> entry : flowMap.entrySet()) {
383             String flowName = entry.getKey();
384             List<MatchInfoBase> matches = entry.getValue();
385             matches.add(lportTagMatch);
386             String flowId = flowName + this.directionString + "_" + port.getDpId() + "_" + port.getLPortTag() + "_"
387                     + ace.getKey().getRuleName();
388
389             int operation = addOrRemove == NwConstants.MOD_FLOW ? NwConstants.DEL_FLOW : addOrRemove;
390             syncFlow(port.getDpId(), getAclFilterCumDispatcherTable(), flowId, flowPriority, "ACL", 0, 0,
391                     AclConstants.COOKIE_ACL_BASE, matches, instructions, operation);
392
393             if (addOrRemove != NwConstants.DEL_FLOW) {
394                 programAclForExistingTrafficTable(port, ace, addOrRemove, flowName, matches, flowPriority);
395             }
396         }
397     }
398
399     protected void programAceSpecificFlows(AclInterface port, String aclName, Ace ace,
400             Map<String, List<MatchInfoBase>> flowMap, Uuid remoteAclId, int addOrRemove) {
401         if (null == flowMap) {
402             return;
403         }
404         Integer remoteAclTag = this.aclServiceUtils.getAclTag(remoteAclId);
405         if (remoteAclTag == null || remoteAclTag == AclConstants.INVALID_ACL_TAG) {
406             LOG.error("remoteAclTag={} is null or invalid for remoteAclId={}", remoteAclTag, remoteAclId);
407             return;
408         }
409         List<MatchInfoBase> lportAndAclMatches =
410                 AclServiceUtils.buildMatchesForLPortTagAndRemoteAclTag(port.getLPortTag(), remoteAclTag, serviceMode);
411         List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getGotoInstructionInfo(getAclRemoteAclTable());
412         Integer flowPriority = this.aclServiceUtils.getAceFlowPriority(aclName);
413
414         for (Entry<String, List<MatchInfoBase>> entry : flowMap.entrySet()) {
415             String flowName = entry.getKey();
416             List<MatchInfoBase> matches = entry.getValue();
417             matches.addAll(lportAndAclMatches);
418             String flowId = flowName + this.directionString + "_" + port.getDpId() + "_" + port.getLPortTag() + "_"
419                     + ace.getKey().getRuleName();
420
421             int operation = addOrRemove == NwConstants.MOD_FLOW ? NwConstants.DEL_FLOW : addOrRemove;
422             syncFlow(port.getDpId(), getAclRuleBasedFilterTable(), flowId, flowPriority, "ACL", 0, 0,
423                     AclConstants.COOKIE_ACL_BASE, matches, instructions, operation);
424
425             if (addOrRemove != NwConstants.DEL_FLOW) {
426                 programAclForExistingTrafficTable(port, ace, addOrRemove, flowName, matches,
427                         flowPriority);
428             }
429         }
430     }
431
432     private void programAclForExistingTrafficTable(AclInterface port, Ace ace, int addOrRemove, String flowName,
433             List<MatchInfoBase> matches, Integer priority) {
434         AceIp acl = (AceIp) ace.getMatches().getAceType();
435         final String newFlowName = flowName + this.directionString + "_" + port.getDpId() + "_" + port.getLPortTag()
436                 + "_" + ((acl.getAceIpVersion() instanceof AceIpv4) ? "_IPv4" : "_IPv6") + "_FlowAfterRuleDeleted";
437
438         final List<MatchInfoBase> newMatches =
439                 matches.stream().filter(obj -> !(obj instanceof NxMatchCtState || obj instanceof MatchMetadata))
440                         .collect(Collectors.toList());
441         newMatches.add(AclServiceUtils.buildLPortTagMatch(port.getLPortTag(), serviceMode));
442         newMatches.add(new NxMatchCtState(AclConstants.TRACKED_RPL_CT_STATE, AclConstants.TRACKED_RPL_CT_STATE_MASK));
443
444         List<InstructionInfo> instructions =
445                 AclServiceUtils.createCtMarkInstructionForNewState(getAclFilterCumDispatcherTable(), port.getElanId());
446         // Reversing the flow add/delete operation for this table.
447         int operation = (addOrRemove == NwConstants.ADD_FLOW) ? NwConstants.DEL_FLOW : NwConstants.ADD_FLOW;
448         syncFlow(port.getDpId(), getAclForExistingTrafficTable(), newFlowName, priority, "ACL", 0,
449                 AclServiceUtils.getHardTimoutForApplyStatefulChangeOnExistingTraffic(ace, aclServiceUtils),
450                 AclConstants.COOKIE_ACL_BASE, newMatches, instructions, operation);
451     }
452
453     @Override
454     public boolean removeAcl(AclInterface port) {
455         if (port.getDpId() == null) {
456             LOG.warn("Unable to find DP Id from ACL interface with id {}", port.getInterfaceId());
457             return false;
458         }
459         programAcl(port, Action.REMOVE, NwConstants.DEL_FLOW);
460         updateRemoteAclFilterTable(port, NwConstants.DEL_FLOW);
461         return true;
462     }
463
464     @Override
465     public boolean applyAce(AclInterface port, String aclName, Ace ace) {
466         if (!port.isPortSecurityEnabled() || port.getDpId() == null) {
467             return false;
468         }
469         programAceRule(port, aclName, ace, NwConstants.ADD_FLOW);
470         return true;
471     }
472
473     @Override
474     public boolean removeAce(AclInterface port, String aclName, Ace ace) {
475         if (!port.isPortSecurityEnabled() || port.getDpId() == null) {
476             return false;
477         }
478         programAceRule(port, aclName, ace, NwConstants.MOD_FLOW);
479         return true;
480     }
481
482     @Override
483     public void updateRemoteAcl(Acl aclBefore, Acl aclAfter, Collection<AclInterface> portsBefore) {
484         handleRemoteAclUpdate(aclBefore, aclAfter, portsBefore);
485     }
486
487     /**
488      * Bind service.
489      *
490      * @param aclInterface the acl interface
491      */
492     public abstract void bindService(AclInterface aclInterface);
493
494     /**
495      * Unbind service.
496      *
497      * @param aclInterface the acl interface
498      */
499     protected abstract void unbindService(AclInterface aclInterface);
500
501     /**
502      * Programs the anti-spoofing rules.
503      *
504      * @param port the acl interface
505      * @param allowedAddresses the allowed addresses
506      * @param action add/modify/remove action
507      * @param addOrRemove addorRemove
508      */
509     protected abstract void programAntiSpoofingRules(AclInterface port, List<AllowedAddressPairs> allowedAddresses,
510             Action action, int addOrRemove);
511
512     /**
513      * Programs broadcast rules.
514      *
515      * @param port the Acl Interface port
516      * @param addOrRemove whether to delete or add flow
517      */
518     protected abstract void programBroadcastRules(AclInterface port, int addOrRemove);
519
520     /**
521      * Writes/remove the flow to/from the datastore.
522      *
523      * @param dpId
524      *            the dpId
525      * @param tableId
526      *            the tableId
527      * @param flowId
528      *            the flowId
529      * @param priority
530      *            the priority
531      * @param flowName
532      *            the flow name
533      * @param idleTimeOut
534      *            the idle timeout
535      * @param hardTimeOut
536      *            the hard timeout
537      * @param cookie
538      *            the cookie
539      * @param matches
540      *            the list of matches to be writted
541      * @param instructions
542      *            the list of instruction to be written.
543      * @param addOrRemove
544      *            add or remove the entries.
545      */
546     protected void syncFlow(BigInteger dpId, short tableId, String flowId, int priority, String flowName,
547             int idleTimeOut, int hardTimeOut, BigInteger cookie, List<? extends MatchInfoBase> matches,
548             List<InstructionInfo> instructions, int addOrRemove) {
549         jobCoordinator.enqueueJob(flowName, () -> {
550             if (addOrRemove == NwConstants.DEL_FLOW) {
551                 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority, flowName,
552                         idleTimeOut, hardTimeOut, cookie, matches, null);
553                 LOG.trace("Removing Acl Flow DpnId {}, flowId {}", dpId, flowId);
554
555                 return Collections.singletonList(mdsalManager.removeFlow(dpId, flowEntity));
556
557             } else {
558                 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority, flowName,
559                         idleTimeOut, hardTimeOut, cookie, matches, instructions);
560                 LOG.trace("Installing DpnId {}, flowId {}", dpId, flowId);
561                 return Collections.singletonList(mdsalManager.installFlow(dpId, flowEntity));
562             }
563         });
564     }
565
566     protected List<InstructionInfo> getDispatcherTableResubmitInstructions() {
567         return getDispatcherTableResubmitInstructions(new ArrayList<>());
568     }
569
570     /**
571      * Gets the dispatcher table resubmit instructions based on ingress/egress service mode w.r.t switch.
572      *
573      * @param actionsInfos
574      *            the actions infos
575      * @return the instructions for dispatcher table resubmit
576      */
577     protected List<InstructionInfo> getDispatcherTableResubmitInstructions(List<ActionInfo> actionsInfos) {
578         short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
579         if (ServiceModeEgress.class.equals(this.serviceMode)) {
580             dispatcherTableId = NwConstants.EGRESS_LPORT_DISPATCHER_TABLE;
581         }
582
583         List<InstructionInfo> instructions = new ArrayList<>();
584         actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
585         instructions.add(new InstructionApplyActions(actionsInfos));
586         return instructions;
587     }
588
589     protected void handleRemoteAclUpdate(Acl aclBefore, Acl aclAfter, Collection<AclInterface> portsBefore) {
590         String aclName = aclAfter.getAclName();
591         Collection<AclInterface> interfaceList = aclDataUtil.getInterfaceList(new Uuid(aclName));
592         if (interfaceList == null || interfaceList.isEmpty()) {
593             LOG.trace("handleRemoteAclUpdate: No interfaces found with ACL={}", aclName);
594             return;
595         }
596         Set<Uuid> remoteAclsBefore = AclServiceUtils.getRemoteAclIdsByDirection(aclBefore, this.direction);
597         Set<Uuid> remoteAclsAfter = AclServiceUtils.getRemoteAclIdsByDirection(aclAfter, this.direction);
598
599         Set<Uuid> remoteAclsAdded = new HashSet<>(remoteAclsAfter);
600         remoteAclsAdded.removeAll(remoteAclsBefore);
601
602         Set<Uuid> remoteAclsDeleted = new HashSet<>(remoteAclsBefore);
603         remoteAclsDeleted.removeAll(remoteAclsAfter);
604
605         if (!remoteAclsAdded.isEmpty() || !remoteAclsDeleted.isEmpty()) {
606             // delete and add flows in ACL dispatcher table for all applicable
607             // ports
608             for (AclInterface portBefore : portsBefore) {
609                 programAclDispatcherTable(portBefore, NwConstants.DEL_FLOW);
610             }
611             for (AclInterface port : interfaceList) {
612                 programAclDispatcherTable(port, NwConstants.ADD_FLOW);
613             }
614         }
615         Set<BigInteger> dpns = interfaceList.stream().map(port -> port.getDpId()).collect(Collectors.toSet());
616
617         programRemoteAclTable(aclName, remoteAclsDeleted, dpns, NwConstants.DEL_FLOW);
618         programRemoteAclTable(aclName, remoteAclsAdded, dpns, NwConstants.ADD_FLOW);
619     }
620
621     private void programRemoteAclTable(String aclName, Set<Uuid> remoteAclIds, Set<BigInteger> dpns, int addOrRemove) {
622         for (Uuid remoteAclId : remoteAclIds) {
623             Collection<AclInterface> remoteAclInterfaces = aclDataUtil.getInterfaceList(remoteAclId);
624             if (remoteAclInterfaces == null || remoteAclInterfaces.isEmpty()) {
625                 continue;
626             }
627             Set<AllowedAddressPairs> aaps =
628                     remoteAclInterfaces.stream().map(port -> port.getAllowedAddressPairs()).flatMap(List::stream)
629                             .filter(aap -> AclServiceUtils.isNotIpAllNetwork(aap)).collect(Collectors.toSet());
630
631             Integer aclTag = aclServiceUtils.getAclTag(remoteAclId);
632             if (addOrRemove == NwConstants.ADD_FLOW) {
633                 for (BigInteger dpn : dpns) {
634                     for (AllowedAddressPairs aap : aaps) {
635                         programRemoteAclTableFlow(dpn, aclTag, aap, addOrRemove);
636                     }
637                 }
638             } else if (addOrRemove == NwConstants.DEL_FLOW) {
639                 Set<BigInteger> remoteAclDpns = new HashSet<>();
640                 Map<String, Set<AclInterface>> mapAclWithPortSet =
641                         aclDataUtil.getRemoteAclInterfaces(remoteAclId, this.direction);
642                 if (mapAclWithPortSet != null) {
643                     Map<String, Set<AclInterface>> copyOfMapAclWithPortSet = new HashMap<>(mapAclWithPortSet);
644                     copyOfMapAclWithPortSet.remove(aclName);
645                     remoteAclDpns = collectDpns(copyOfMapAclWithPortSet);
646                 }
647                 Set<BigInteger> dpnsToOperate = new HashSet<>(dpns);
648                 dpnsToOperate.removeAll(remoteAclDpns);
649                 LOG.debug(
650                         "Deleting flows in Remote ACL table for remoteAclId={}, direction={}, dpnsToOperate={}, "
651                                 + "remoteAclDpns={}, dpns={}",
652                         remoteAclId.getValue(), directionString, dpnsToOperate, remoteAclDpns, dpns);
653
654                 for (BigInteger dpn : dpnsToOperate) {
655                     for (AllowedAddressPairs aap : aaps) {
656                         programRemoteAclTableFlow(dpn, aclTag, aap, addOrRemove);
657                     }
658                 }
659             }
660         }
661     }
662
663     private void updateRemoteAclFilterTable(AclInterface port, int addOrRemove) {
664         updateRemoteAclFilterTable(port, port.getSecurityGroups(), port.getAllowedAddressPairs(), addOrRemove);
665     }
666
667     private void updateRemoteAclFilterTable(AclInterface port, List<Uuid> aclList, List<AllowedAddressPairs> aaps,
668             int addOrRemove) {
669         if (aclList == null) {
670             LOG.debug("Port {} without SGs", port.getInterfaceId());
671             return;
672         }
673         String portId = port.getInterfaceId();
674         LOG.trace("updateRemoteAclFilterTable for portId={}, aclList={}, aaps={}, addOrRemove={}", portId, aclList,
675                 aaps, addOrRemove);
676         for (Uuid aclId : aclList) {
677             if (aclDataUtil.getRemoteAcl(aclId, this.direction) != null) {
678                 Integer aclTag = aclServiceUtils.getAclTag(aclId);
679                 if (addOrRemove == NwConstants.ADD_FLOW) {
680                     syncRemoteAclTable(portId, aclId, aclTag, aaps, addOrRemove);
681                 } else if (addOrRemove == NwConstants.DEL_FLOW) {
682                     // Synchronizing during delete operation as there are
683                     // look-ups for AclPortsLookup data.
684                     synchronized (aclId.getValue().intern()) {
685                         syncRemoteAclTable(portId, aclId, aclTag, aaps, addOrRemove);
686                     }
687                 }
688             }
689         }
690         Set<Uuid> remoteAclIds = aclServiceUtils.getRemoteAclIdsByDirection(aclList, direction);
691         for (Uuid remoteAclId : remoteAclIds) {
692             syncRemoteAclTableFromOtherDpns(port, remoteAclId, addOrRemove);
693         }
694     }
695
696     private void syncRemoteAclTable(String portId, Uuid acl, Integer aclTag, List<AllowedAddressPairs> aaps,
697             int addOrRemove) {
698         Map<String, Set<AclInterface>> mapAclWithPortSet = aclDataUtil.getRemoteAclInterfaces(acl, this.direction);
699         Set<BigInteger> dpns = collectDpns(mapAclWithPortSet);
700         for (AllowedAddressPairs aap : aaps) {
701             if (!AclServiceUtils.isNotIpAllNetwork(aap)) {
702                 continue;
703             }
704             if (aclServiceUtils.skipDeleteInCaseOfOverlappingIP(portId, acl, aap.getIpAddress(),
705                     addOrRemove)) {
706                 LOG.debug("Skipping delete of IP={} in remote ACL table for remoteAclId={}, portId={}",
707                         aap.getIpAddress(), portId, acl.getValue());
708                 continue;
709             }
710             for (BigInteger dpId : dpns) {
711                 programRemoteAclTableFlow(dpId, aclTag, aap, addOrRemove);
712             }
713         }
714     }
715
716     private void syncRemoteAclTableFromOtherDpns(AclInterface port, Uuid remoteAclId, int addOrRemove) {
717         Collection<AclInterface> aclInterfaces = aclDataUtil.getInterfaceList(remoteAclId);
718
719         if (aclInterfaces != null && !aclInterfaces.isEmpty() && isFirstPortInDpnWithRemoteAclId(port, remoteAclId)) {
720             Integer aclTag = aclServiceUtils.getAclTag(remoteAclId);
721             for (AclInterface aclInterface : aclInterfaces) {
722                 if (port.getInterfaceId().equals(aclInterface.getInterfaceId())) {
723                     continue;
724                 }
725                 for (AllowedAddressPairs aap : aclInterface.getAllowedAddressPairs()) {
726                     if (AclServiceUtils.isNotIpAllNetwork(aap)) {
727                         programRemoteAclTableFlow(port.getDpId(), aclTag, aap, addOrRemove);
728                     }
729                 }
730             }
731         }
732     }
733
734     private boolean isFirstPortInDpnWithRemoteAclId(AclInterface port, Uuid remoteAclId) {
735         String portId = port.getInterfaceId();
736         BigInteger dpId = port.getDpId();
737         Map<String, Set<AclInterface>> remoteAclInterfacesMap =
738                 aclDataUtil.getRemoteAclInterfaces(remoteAclId, direction);
739         if (remoteAclInterfacesMap != null) {
740             for (Set<AclInterface> interfaceSet : remoteAclInterfacesMap.values()) {
741                 for (AclInterface aclInterface : interfaceSet) {
742                     if (portId.equals(aclInterface.getInterfaceId())) {
743                         continue;
744                     }
745                     if (dpId.equals(aclInterface.getDpId())) {
746                         return false;
747                     }
748                 }
749             }
750         }
751         return true;
752     }
753
754     protected abstract void programRemoteAclTableFlow(BigInteger dpId, Integer aclTag, AllowedAddressPairs aap,
755             int addOrRemove);
756
757     protected String getOperAsString(int flowOper) {
758         String oper;
759         switch (flowOper) {
760             case NwConstants.ADD_FLOW:
761                 oper = "Add";
762                 break;
763             case NwConstants.DEL_FLOW:
764                 oper = "Del";
765                 break;
766             case NwConstants.MOD_FLOW:
767                 oper = "Mod";
768                 break;
769             default:
770                 oper = "UNKNOWN";
771         }
772         return oper;
773     }
774
775     protected Set<BigInteger> collectDpns(Map<String, Set<AclInterface>> mapAclWithPortSet) {
776         Set<BigInteger> dpns = new HashSet<>();
777         if (mapAclWithPortSet == null) {
778             return dpns;
779         }
780         for (Set<AclInterface> innerSet : mapAclWithPortSet.values()) {
781             if (innerSet == null) {
782                 continue;
783             }
784             for (AclInterface inter : innerSet) {
785                 dpns.add(inter.getDpId());
786             }
787         }
788         return dpns;
789     }
790
791     /**
792      * Programs the port specific fixed rules.
793      *
794      * @param dpId the dp id
795      * @param allowedAddresses the allowed addresses
796      * @param lportTag the lport tag
797      * @param portId the portId
798      * @param action the action
799      * @param write whether to add or remove the flow.
800      */
801     protected void programAclPortSpecificFixedRules(BigInteger dpId, List<AllowedAddressPairs> allowedAddresses,
802             int lportTag, String portId, Action action, int write) {
803         programGotoClassifierTableRules(dpId, allowedAddresses, lportTag, write);
804         if (action == Action.ADD || action == Action.REMOVE) {
805             programConntrackRecircRules(dpId, allowedAddresses, lportTag, portId, write);
806             programPortSpecificDropRules(dpId, lportTag, write);
807             programAclCommitRules(dpId, lportTag, portId, write);
808         }
809         LOG.info("programAclPortSpecificFixedRules: flows for dpId={}, lportId={}, action={}, write={}", dpId, lportTag,
810                 action, write);
811     }
812
813     protected abstract void programGotoClassifierTableRules(BigInteger dpId, List<AllowedAddressPairs> aaps,
814             int lportTag, int addOrRemove);
815
816     /**
817      * Adds the rule to send the packet to the netfilter to check whether it is a known packet.
818      *
819      * @param dpId the dpId
820      * @param aaps the allowed address pairs
821      * @param lportTag the lport tag
822      * @param portId the portId
823      * @param addOrRemove whether to add or remove the flow
824      */
825     protected void programConntrackRecircRules(BigInteger dpId, List<AllowedAddressPairs> aaps, int lportTag,
826             String portId, int addOrRemove) {
827         if (AclServiceUtils.doesIpv4AddressExists(aaps)) {
828             programConntrackRecircRule(dpId, lportTag, portId, MatchEthernetType.IPV4, addOrRemove);
829         }
830         if (AclServiceUtils.doesIpv6AddressExists(aaps)) {
831             programConntrackRecircRule(dpId, lportTag, portId, MatchEthernetType.IPV6, addOrRemove);
832         }
833     }
834
835     protected void programConntrackRecircRule(BigInteger dpId, int lportTag, String portId,
836             MatchEthernetType matchEtherType, int addOrRemove) {
837         List<MatchInfoBase> matches = new ArrayList<>();
838         matches.add(matchEtherType);
839         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
840
841         List<InstructionInfo> instructions = new ArrayList<>();
842         if (addOrRemove == NwConstants.ADD_FLOW) {
843             Long elanTag = getElanIdFromAclInterface(portId);
844             if (elanTag == null) {
845                 LOG.error("ElanId not found for portId={}; Context: dpId={}, lportTag={}, addOrRemove={},", portId,
846                         dpId, lportTag, addOrRemove);
847                 return;
848             }
849             List<ActionInfo> actionsInfos = new ArrayList<>();
850             actionsInfos.add(new ActionNxConntrack(2, 0, 0, elanTag.intValue(), getAclForExistingTrafficTable()));
851             instructions.add(new InstructionApplyActions(actionsInfos));
852         }
853
854         String flowName =
855                 this.directionString + "_Fixed_Conntrk_" + dpId + "_" + lportTag + "_" + matchEtherType + "_Recirc";
856         syncFlow(dpId, getAclConntrackSenderTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY, "ACL", 0, 0,
857                 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
858     }
859
860     /**
861      * Adds the rules to drop the unknown/invalid packets .
862      *
863      * @param dpId the dpId
864      * @param lportTag the lport tag
865      * @param addOrRemove whether to add or remove the flow
866      */
867     protected void programPortSpecificDropRules(BigInteger dpId, int lportTag, int addOrRemove) {
868         LOG.debug("Programming Drop Rules: DpId={}, lportTag={}, addOrRemove={}", dpId, lportTag, addOrRemove);
869         programConntrackInvalidDropRule(dpId, lportTag, addOrRemove);
870         programAclRuleMissDropRule(dpId, lportTag, addOrRemove);
871     }
872
873     /**
874      * Adds the rule to drop the conntrack invalid packets .
875      *
876      * @param dpId the dpId
877      * @param lportTag the lport tag
878      * @param addOrRemove whether to add or remove the flow
879      */
880     protected void programConntrackInvalidDropRule(BigInteger dpId, int lportTag, int addOrRemove) {
881         List<MatchInfoBase> matches = AclServiceOFFlowBuilder.addLPortTagMatches(lportTag,
882                 AclConstants.TRACKED_INV_CT_STATE, AclConstants.TRACKED_INV_CT_STATE_MASK, serviceMode);
883         List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
884
885         String flowId = this.directionString + "_Fixed_Conntrk_Drop" + dpId + "_" + lportTag + "_Tracked_Invalid";
886         syncFlow(dpId, getAclFilterCumDispatcherTable(), flowId, AclConstants.CT_STATE_TRACKED_INVALID_PRIORITY, "ACL",
887                 0, 0, AclConstants.COOKIE_ACL_DROP_FLOW, matches, instructions, addOrRemove);
888     }
889
890     /**
891      * Program ACL rule miss drop rule for a port.
892      *
893      * @param dpId the dp id
894      * @param lportTag the lport tag
895      * @param addOrRemove the add or remove
896      */
897     protected void programAclRuleMissDropRule(BigInteger dpId, int lportTag, int addOrRemove) {
898         List<MatchInfoBase> matches = new ArrayList<>();
899         matches.add(AclServiceUtils.buildLPortTagMatch(lportTag, serviceMode));
900         List<InstructionInfo> instructions = AclServiceOFFlowBuilder.getDropInstructionInfo();
901
902         String flowId = this.directionString + "_Fixed_Acl_Rule_Miss_Drop_" + dpId + "_" + lportTag;
903         syncFlow(dpId, getAclFilterCumDispatcherTable(), flowId, AclConstants.ACL_PORT_SPECIFIC_DROP_PRIORITY, "ACL", 0,
904                 0, AclConstants.COOKIE_ACL_DROP_FLOW, matches, instructions, addOrRemove);
905     }
906
907     /**
908      * Program acl commit rules.
909      *
910      * @param dpId the dp id
911      * @param lportTag the lport tag
912      * @param portId the port id
913      * @param addOrRemove the add or remove
914      */
915     protected void programAclCommitRules(BigInteger dpId, int lportTag, String portId, int addOrRemove) {
916         programAclCommitRuleForConntrack(dpId, lportTag, portId, MatchEthernetType.IPV4, addOrRemove);
917         programAclCommitRuleForConntrack(dpId, lportTag, portId, MatchEthernetType.IPV6, addOrRemove);
918         programAclCommitRuleForNonConntrack(dpId, lportTag, addOrRemove);
919     }
920
921     /**
922      * Program acl commit rule for conntrack.
923      *
924      * @param dpId the dp id
925      * @param lportTag the lport tag
926      * @param portId the port id
927      * @param matchEtherType the match ether type
928      * @param addOrRemove the add or remove
929      */
930     protected void programAclCommitRuleForConntrack(BigInteger dpId, int lportTag, String portId,
931             MatchEthernetType matchEtherType, int addOrRemove) {
932         List<MatchInfoBase> matches = new ArrayList<>();
933         matches.add(matchEtherType);
934         matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndConntrackClassifierType(lportTag,
935                 AclConntrackClassifierType.CONNTRACK_SUPPORTED, serviceMode));
936
937         List<ActionInfo> actionsInfos = new ArrayList<>();
938         if (addOrRemove == NwConstants.ADD_FLOW) {
939             Long elanId = getElanIdFromAclInterface(portId);
940             if (elanId == null) {
941                 LOG.error("ElanId not found for portId={}; Context: dpId={}, lportTag={}, addOrRemove={}", portId, dpId,
942                         lportTag, addOrRemove);
943                 return;
944             }
945             List<NxCtAction> ctActionsList =
946                     Lists.newArrayList(new ActionNxConntrack.NxCtMark(AclConstants.CT_MARK_EST_STATE));
947             actionsInfos.add(new ActionNxConntrack(2, 1, 0, elanId.intValue(), (short) 255, ctActionsList));
948         }
949         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions(actionsInfos);
950
951         String flowName = directionString + "_Acl_Commit_Conntrack_" + dpId + "_" + lportTag + "_" + matchEtherType;
952         // Flow for conntrack traffic to commit and resubmit to dispatcher
953         syncFlow(dpId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY, "ACL", 0, 0,
954                 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
955     }
956
957     /**
958      * Program acl commit rule for non conntrack.
959      *
960      * @param dpId the dp id
961      * @param lportTag the lport tag
962      * @param addOrRemove the add or remove
963      */
964     protected void programAclCommitRuleForNonConntrack(BigInteger dpId, int lportTag, int addOrRemove) {
965         List<MatchInfoBase> matches = new ArrayList<>();
966         matches.addAll(AclServiceUtils.buildMatchesForLPortTagAndConntrackClassifierType(lportTag,
967                 AclConntrackClassifierType.NON_CONNTRACK_SUPPORTED, serviceMode));
968
969         List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
970         String flowName = this.directionString + "_Acl_Commit_Non_Conntrack_" + dpId + "_" + lportTag;
971         // Flow for non-conntrack traffic to resubmit to dispatcher
972         syncFlow(dpId, getAclCommitterTable(), flowName, AclConstants.ACL_DEFAULT_PRIORITY, "ACL", 0, 0,
973                 AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
974     }
975
976     protected Long getElanIdFromAclInterface(String elanInterfaceName) {
977         AclInterface aclInterface = aclInterfaceCache.get(elanInterfaceName);
978         if (null != aclInterface) {
979             return aclInterface.getElanId();
980         }
981         return null;
982     }
983
984     protected abstract boolean isValidDirection(Class<? extends DirectionBase> direction);
985
986     protected abstract short getAclAntiSpoofingTable();
987
988     protected abstract short getAclConntrackClassifierTable();
989
990     protected abstract short getAclConntrackSenderTable();
991
992     protected abstract short getAclForExistingTrafficTable();
993
994     protected abstract short getAclFilterCumDispatcherTable();
995
996     protected abstract short getAclRuleBasedFilterTable();
997
998     protected abstract short getAclRemoteAclTable();
999
1000     protected abstract short getAclCommitterTable();
1001 }