Bug 8400 - ACL changes doesn't affect the existing connections
[netvirt.git] / vpnservice / 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 java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Map.Entry;
18 import java.util.Set;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.genius.mdsalutil.ActionInfo;
21 import org.opendaylight.genius.mdsalutil.FlowEntity;
22 import org.opendaylight.genius.mdsalutil.InstructionInfo;
23 import org.opendaylight.genius.mdsalutil.MDSALUtil;
24 import org.opendaylight.genius.mdsalutil.MatchInfoBase;
25 import org.opendaylight.genius.mdsalutil.NwConstants;
26 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
27 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
28 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
29 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
30 import org.opendaylight.netvirt.aclservice.api.AclInterfaceCache;
31 import org.opendaylight.netvirt.aclservice.api.AclServiceListener;
32 import org.opendaylight.netvirt.aclservice.api.AclServiceManager.Action;
33 import org.opendaylight.netvirt.aclservice.api.utils.AclInterface;
34 import org.opendaylight.netvirt.aclservice.utils.AclDataUtil;
35 import org.opendaylight.netvirt.aclservice.utils.AclServiceUtils;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.Acl;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.AccessListEntries;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160218.access.lists.acl.access.list.entries.Ace;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeBase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeEgress;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.SecurityRuleAttr;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 public abstract class AbstractAclServiceImpl implements AclServiceListener {
48
49     private static final Logger LOG = LoggerFactory.getLogger(AbstractAclServiceImpl.class);
50
51     protected final IMdsalApiManager mdsalManager;
52     protected final DataBroker dataBroker;
53     protected final Class<? extends ServiceModeBase> serviceMode;
54     protected final AclDataUtil aclDataUtil;
55     protected final AclServiceUtils aclServiceUtils;
56     protected final JobCoordinator jobCoordinator;
57     protected final AclInterfaceCache aclInterfaceCache;
58
59     /**
60      * Initialize the member variables.
61      */
62     public AbstractAclServiceImpl(Class<? extends ServiceModeBase> serviceMode, DataBroker dataBroker,
63             IMdsalApiManager mdsalManager, AclDataUtil aclDataUtil, AclServiceUtils aclServiceUtils,
64             JobCoordinator jobCoordinator, AclInterfaceCache aclInterfaceCache) {
65         this.dataBroker = dataBroker;
66         this.mdsalManager = mdsalManager;
67         this.serviceMode = serviceMode;
68         this.aclDataUtil = aclDataUtil;
69         this.aclServiceUtils = aclServiceUtils;
70         this.jobCoordinator = jobCoordinator;
71         this.aclInterfaceCache = aclInterfaceCache;
72     }
73
74     @Override
75     public boolean applyAcl(AclInterface port) {
76         if (port == null) {
77             LOG.error("port cannot be null");
78             return false;
79         }
80         if (port.getSecurityGroups() == null) {
81             LOG.info("Port {} without SGs", port.getInterfaceId());
82             return false;
83         }
84         BigInteger dpId = port.getDpId();
85         if (dpId == null || port.getLPortTag() == null) {
86             LOG.error("Unable to find DpId from ACL interface with id {}", port.getInterfaceId());
87             return false;
88         }
89         LOG.debug("Applying ACL on port {} with DpId {}", port, dpId);
90         programAclWithAllowedAddress(port, port.getAllowedAddressPairs(), Action.ADD, NwConstants.ADD_FLOW);
91         updateRemoteAclFilterTable(port, NwConstants.ADD_FLOW);
92         return true;
93     }
94
95     @Override
96     public boolean bindAcl(AclInterface port) {
97         if (port == null || port.getSecurityGroups() == null) {
98             LOG.error("Port and port security groups cannot be null for binding ACL service, port={}", port);
99             return false;
100         }
101         bindService(port);
102         if (port.getDpId() != null) {
103             updateRemoteAclFilterTable(port, NwConstants.ADD_FLOW);
104         }
105         return true;
106     }
107
108     @Override
109     public boolean unbindAcl(AclInterface port) {
110         if (port == null) {
111             LOG.error("Port cannot be null for unbinding ACL service");
112             return false;
113         }
114         unbindService(port);
115         updateRemoteAclFilterTable(port, NwConstants.DEL_FLOW);
116         return true;
117     }
118
119     @Override
120     public boolean updateAcl(AclInterface portBefore, AclInterface portAfter) {
121         // this check is to avoid situations of port update coming before interface state is up
122         if (portAfter.getDpId() == null || portAfter.getLPortTag() == null) {
123             LOG.debug("Unable to find DpId from ACL interface with id {} and lport {}", portAfter.getInterfaceId(),
124                     portAfter.getLPortTag());
125             return false;
126         }
127         boolean result = true;
128         boolean isPortSecurityEnable = portAfter.isPortSecurityEnabled();
129         boolean isPortSecurityEnableBefore = portBefore.isPortSecurityEnabled();
130         // if port security is changed, apply/remove Acls
131         if (isPortSecurityEnableBefore != isPortSecurityEnable) {
132             LOG.debug("On ACL update, Port security is {} for {}", isPortSecurityEnable ? "Enabled" :
133                     "Disabled", portAfter.getInterfaceId());
134             if (isPortSecurityEnable) {
135                 result = applyAcl(portAfter);
136             } else {
137                 result = removeAcl(portBefore);
138             }
139         } else if (isPortSecurityEnable) {
140             // Acls has been updated, find added/removed Acls and act accordingly.
141             processInterfaceUpdate(portBefore, portAfter);
142             LOG.debug("On ACL update, ACL has been updated for {}", portAfter.getInterfaceId());
143         }
144
145         return result;
146     }
147
148     private void processInterfaceUpdate(AclInterface portBefore, AclInterface portAfter) {
149         BigInteger dpId = portAfter.getDpId();
150         List<AllowedAddressPairs> addedAllowedAddressPairs =
151                 AclServiceUtils.getUpdatedAllowedAddressPairs(portAfter.getAllowedAddressPairs(),
152                         portBefore.getAllowedAddressPairs());
153         List<AllowedAddressPairs> deletedAllowedAddressPairs =
154                 AclServiceUtils.getUpdatedAllowedAddressPairs(portBefore.getAllowedAddressPairs(),
155                         portAfter.getAllowedAddressPairs());
156         if (deletedAllowedAddressPairs != null && !deletedAllowedAddressPairs.isEmpty()) {
157             programAclWithAllowedAddress(portAfter, deletedAllowedAddressPairs, Action.UPDATE, NwConstants.DEL_FLOW);
158         }
159         if (addedAllowedAddressPairs != null && !addedAllowedAddressPairs.isEmpty()) {
160             programAclWithAllowedAddress(portAfter, addedAllowedAddressPairs, Action.UPDATE, NwConstants.ADD_FLOW);
161         }
162         updateArpForAllowedAddressPairs(dpId, portAfter.getLPortTag(), deletedAllowedAddressPairs,
163                 portAfter.getAllowedAddressPairs());
164         if (portAfter.getSubnetIpPrefixes() != null && portBefore.getSubnetIpPrefixes() == null) {
165             programBroadcastRules(portAfter, NwConstants.ADD_FLOW);
166         }
167
168         updateAclInterfaceInCache(portBefore);
169         // Have to delete and add all rules because there can be following scenario: Interface1 with SG1, Interface2
170         // with SG2 (which has ACE with remote SG1). Now When we add SG3 to Interface1, the rule for Interface2 which
171         // match the IP of Interface1 will not be installed (but it have to be because Interface1 has more than one SG).
172         // So we need to remove all rules and install them from 0, and we cannot handle only the delta.
173         updateCustomRules(portBefore, portBefore.getSecurityGroups(), NwConstants.MOD_FLOW,
174                 portAfter.getAllowedAddressPairs());
175         updateRemoteAclFilterTable(portBefore, NwConstants.DEL_FLOW);
176
177         updateAclInterfaceInCache(portAfter);
178
179         updateCustomRules(portAfter, portAfter.getSecurityGroups(), NwConstants.ADD_FLOW,
180                 portAfter.getAllowedAddressPairs());
181         updateRemoteAclFilterTable(portAfter, NwConstants.ADD_FLOW);
182     }
183
184     private void updateAclInterfaceInCache(AclInterface aclInterfaceNew) {
185         aclDataUtil.addOrUpdateAclInterfaceMap(aclInterfaceNew.getSecurityGroups(), aclInterfaceNew);
186     }
187
188     private void updateCustomRules(AclInterface port, List<Uuid> aclUuidList, int action,
189             List<AllowedAddressPairs> syncAllowedAddresses) {
190         programAclRules(port, aclUuidList, action);
191         syncRemoteAclRules(aclUuidList, action, port.getInterfaceId(), syncAllowedAddresses);
192     }
193
194     private void syncRemoteAclRules(List<Uuid> aclUuidList, int action, String currentPortId,
195             List<AllowedAddressPairs> syncAllowedAddresses) {
196         if (aclUuidList == null) {
197             LOG.warn("security groups are null");
198             return;
199         }
200
201         for (Uuid remoteAclId : aclUuidList) {
202             Map<String, Set<AclInterface>> mapAclWithPortSet = aclDataUtil.getRemoteAclInterfaces(remoteAclId);
203             if (mapAclWithPortSet == null) {
204                 continue;
205             }
206             for (Entry<String, Set<AclInterface>> entry : mapAclWithPortSet.entrySet()) {
207                 String aclName = entry.getKey();
208                 for (AclInterface port : entry.getValue()) {
209                     if (currentPortId.equals(port.getInterfaceId())
210                             || port.getSecurityGroups() != null && port.getSecurityGroups().size() == 1) {
211                         continue;
212                     }
213                     List<Ace> remoteAceList = AclServiceUtils.getAceWithRemoteAclId(dataBroker, port, remoteAclId);
214                     for (Ace ace : remoteAceList) {
215                         programAceRule(port, action, aclName, ace, syncAllowedAddresses);
216                     }
217                 }
218             }
219         }
220     }
221
222     private void programAclWithAllowedAddress(AclInterface port, List<AllowedAddressPairs> allowedAddresses,
223             Action action, int addOrRemove) {
224         BigInteger dpId = port.getDpId();
225         int lportTag = port.getLPortTag();
226         LOG.debug("Applying ACL Allowed Address on DpId {}, lportTag {}, Action {}", dpId, lportTag, action);
227         List<Uuid> aclUuidList = port.getSecurityGroups();
228         String portId = port.getInterfaceId();
229         programGeneralFixedRules(port, "", allowedAddresses, action, addOrRemove);
230         programSpecificFixedRules(dpId, "", allowedAddresses, lportTag, portId, action, addOrRemove);
231         if (action == Action.ADD || action == Action.REMOVE) {
232             programAclRules(port, aclUuidList, addOrRemove);
233         }
234         syncRemoteAclRules(aclUuidList, addOrRemove, portId, allowedAddresses);
235     }
236
237
238     @Override
239     public boolean removeAcl(AclInterface port) {
240         BigInteger dpId = port.getDpId();
241         if (dpId == null) {
242             LOG.error("Unable to find DP Id from ACL interface with id {}", port.getInterfaceId());
243             return false;
244         }
245         programAclWithAllowedAddress(port, port.getAllowedAddressPairs(), Action.REMOVE, NwConstants.DEL_FLOW);
246         updateRemoteAclFilterTable(port, NwConstants.DEL_FLOW, true);
247         return true;
248     }
249
250     @Override
251     public boolean applyAce(AclInterface port, String aclName, Ace ace) {
252         if (!port.isPortSecurityEnabled() || port.getDpId() == null) {
253             return false;
254         }
255         programAceRule(port, NwConstants.ADD_FLOW, aclName, ace, null);
256         updateRemoteAclFilterTable(port, NwConstants.ADD_FLOW);
257         return true;
258     }
259
260     @Override
261     public boolean removeAce(AclInterface port, String aclName, Ace ace) {
262         if (!port.isPortSecurityEnabled() || port.getDpId() == null) {
263             return false;
264         }
265         programAceRule(port, NwConstants.MOD_FLOW, aclName, ace, null);
266         updateRemoteAclFilterTable(port, NwConstants.DEL_FLOW);
267         return true;
268     }
269
270     /**
271      * Bind service.
272      *
273      * @param aclInterface the acl interface
274      */
275     public abstract void bindService(AclInterface aclInterface);
276
277     /**
278      * Unbind service.
279      *
280      * @param aclInterface the acl interface
281      */
282     protected abstract void unbindService(AclInterface aclInterface);
283
284     /**
285      * Program the default anti-spoofing rules.
286      *
287      * @param port the acl interface
288      * @param dhcpMacAddress the dhcp mac address.
289      * @param allowedAddresses the allowed addresses
290      * @param action add/modify/remove action
291      * @param addOrRemove addorRemove
292      */
293     protected abstract void programGeneralFixedRules(AclInterface port, String dhcpMacAddress,
294             List<AllowedAddressPairs> allowedAddresses, Action action, int addOrRemove);
295
296     /**
297      * Update arp for allowed address pairs.
298      *
299      * @param dpId the dp id
300      * @param lportTag the lport tag
301      * @param deletedAAP the deleted allowed address pairs
302      * @param addedAAP the added allowed address pairs
303      */
304     protected abstract void updateArpForAllowedAddressPairs(BigInteger dpId, int lportTag,
305             List<AllowedAddressPairs> deletedAAP, List<AllowedAddressPairs> addedAAP);
306
307     /**
308      * Program the default specific rules.
309      *
310      * @param dpid the dpid
311      * @param dhcpMacAddress the dhcp mac address.
312      * @param allowedAddresses the allowed addresses
313      * @param lportTag the lport tag
314      * @param portId the port id
315      * @param action add/modify/remove action
316      * @param addOrRemove addorRemove
317      */
318     protected abstract void programSpecificFixedRules(BigInteger dpid, String dhcpMacAddress,
319             List<AllowedAddressPairs> allowedAddresses, int lportTag, String portId, Action action, int addOrRemove);
320
321     /**
322      * Programs the acl custom rules.
323      *
324      * @param port acl interface
325      * @param aclUuidList the list of acl uuid to be applied
326      * @param addOrRemove whether to delete or add flow
327      * @return program succeeded
328      */
329     protected abstract boolean programAclRules(AclInterface port, List<Uuid> aclUuidList, int addOrRemove);
330
331     /**
332      * Programs the ace custom rule.
333      *
334      * @param port acl interface
335      * @param addOrRemove whether to delete or add flow
336      * @param aclName the acl name
337      * @param ace rule to be program
338      * @param syncAllowedAddresses the allowed addresses
339      */
340     protected abstract void programAceRule(AclInterface port, int addOrRemove, String aclName, Ace ace,
341             List<AllowedAddressPairs> syncAllowedAddresses);
342
343     /**
344      * Programs broadcast rules.
345      *
346      * @param port the Acl Interface port
347      * @param addOrRemove whether to delete or add flow
348      */
349     protected abstract void programBroadcastRules(AclInterface port, int addOrRemove);
350
351     /**
352      * Writes/remove the flow to/from the datastore.
353      *
354      * @param dpId
355      *            the dpId
356      * @param tableId
357      *            the tableId
358      * @param flowId
359      *            the flowId
360      * @param priority
361      *            the priority
362      * @param flowName
363      *            the flow name
364      * @param idleTimeOut
365      *            the idle timeout
366      * @param hardTimeOut
367      *            the hard timeout
368      * @param cookie
369      *            the cookie
370      * @param matches
371      *            the list of matches to be writted
372      * @param instructions
373      *            the list of instruction to be written.
374      * @param addOrRemove
375      *            add or remove the entries.
376      */
377     protected void syncFlow(BigInteger dpId, short tableId, String flowId, int priority, String flowName,
378             int idleTimeOut, int hardTimeOut, BigInteger cookie, List<? extends MatchInfoBase> matches,
379             List<InstructionInfo> instructions, int addOrRemove) {
380         jobCoordinator.enqueueJob(flowName, () -> {
381             if (addOrRemove == NwConstants.DEL_FLOW) {
382                 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority, flowName,
383                         idleTimeOut, hardTimeOut, cookie, matches, null);
384                 LOG.trace("Removing Acl Flow DpnId {}, flowId {}", dpId, flowId);
385
386                 return Collections.singletonList(mdsalManager.removeFlow(dpId, flowEntity));
387
388             } else {
389                 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, flowId, priority, flowName,
390                         idleTimeOut, hardTimeOut, cookie, matches, instructions);
391                 LOG.trace("Installing DpnId {}, flowId {}", dpId, flowId);
392                 return Collections.singletonList(mdsalManager.installFlow(dpId, flowEntity));
393             }
394         });
395     }
396
397     /**
398      * Gets the dispatcher table resubmit instructions based on ingress/egress service mode w.r.t switch.
399      *
400      * @param actionsInfos
401      *            the actions infos
402      * @return the instructions for dispatcher table resubmit
403      */
404     protected List<InstructionInfo> getDispatcherTableResubmitInstructions(List<ActionInfo> actionsInfos) {
405         short dispatcherTableId = NwConstants.LPORT_DISPATCHER_TABLE;
406         if (ServiceModeEgress.class.equals(this.serviceMode)) {
407             dispatcherTableId = NwConstants.EGRESS_LPORT_DISPATCHER_TABLE;
408         }
409
410         List<InstructionInfo> instructions = new ArrayList<>();
411         actionsInfos.add(new ActionNxResubmit(dispatcherTableId));
412         instructions.add(new InstructionApplyActions(actionsInfos));
413         return instructions;
414     }
415
416     private void updateRemoteAclFilterTable(AclInterface port, int addOrRemove) {
417         updateRemoteAclFilterTable(port, addOrRemove, false);
418     }
419
420     private void updateRemoteAclFilterTable(AclInterface port, int addOrRemove, boolean isAclDeleted) {
421         if (port.getSecurityGroups() == null) {
422             LOG.debug("Port {} without SGs", port.getInterfaceId());
423             return;
424         }
425
426         if (AclServiceUtils.exactlyOneAcl(port)) {
427             Uuid acl = port.getSecurityGroups().get(0);
428             BigInteger aclId = aclServiceUtils.buildAclId(acl);
429             if (aclDataUtil.getRemoteAcl(acl) != null) {
430                 Map<String, Set<AclInterface>> mapAclWithPortSet = aclDataUtil.getRemoteAclInterfaces(acl);
431                 Set<BigInteger> dpns = collectDpns(mapAclWithPortSet);
432
433                 for (AllowedAddressPairs ip : port.getAllowedAddressPairs()) {
434                     if (!AclServiceUtils.isNotIpv4AllNetwork(ip)) {
435                         continue;
436                     }
437                     for (BigInteger dpId : dpns) {
438                         updateRemoteAclTableForPort(port, acl, addOrRemove, ip, aclId, dpId);
439                     }
440                 }
441                 syncRemoteAclTableFromOtherDpns(port, acl, aclId, addOrRemove);
442             } else {
443                 LOG.debug("Port {} with more than one SG ({}). Don't change ACL filter table", port.getInterfaceId(),
444                         port.getSecurityGroups().size());
445             }
446         } else if (port.getSecurityGroups() != null && port.getSecurityGroups().size() > 1) {
447             updateRemoteAclTableForMultipleAcls(port, addOrRemove, port.getInterfaceId());
448         }
449         syncRemoteAclTable(port, addOrRemove, port.getInterfaceId(), isAclDeleted);
450     }
451
452     private void syncRemoteAclTableFromOtherDpns(AclInterface port, Uuid acl, BigInteger aclId, int addOrRemove) {
453         Collection<AclInterface> aclInterfaces = aclDataUtil.getInterfaceList(acl);
454         BigInteger dpId = port.getDpId();
455         boolean isFirstPortInDpn = true;
456         if (aclInterfaces != null) {
457             for (AclInterface aclInterface : aclInterfaces) {
458                 if (port.getInterfaceId().equals(aclInterface.getInterfaceId())) {
459                     continue;
460                 }
461                 if (dpId.equals(aclInterface.getDpId())) {
462                     isFirstPortInDpn = false;
463                     break;
464                 }
465             }
466             if (isFirstPortInDpn) {
467                 for (AclInterface aclInterface : aclInterfaces) {
468                     if (port.getInterfaceId().equals(aclInterface.getInterfaceId())) {
469                         continue;
470                     }
471                     for (AllowedAddressPairs ip : aclInterface.getAllowedAddressPairs()) {
472                         updateRemoteAclTableForPort(aclInterface, acl, addOrRemove, ip, aclId, port.getDpId());
473                     }
474                 }
475             }
476         }
477     }
478
479     private void syncRemoteAclTable(AclInterface port, int addOrRemove, String ignorePort, boolean isAclDeleted) {
480         for (Uuid aclUuid : port.getSecurityGroups()) {
481             if (aclDataUtil.getRemoteAcl(aclUuid) == null) {
482                 continue;
483             }
484             Collection<AclInterface> aclInterfaces = aclDataUtil.getInterfaceList(aclUuid);
485             if (aclInterfaces != null) {
486                 for (AclInterface aclInterface : aclInterfaces) {
487                     if (aclInterface.getInterfaceId().equals(port.getInterfaceId())
488                             || AclServiceUtils.exactlyOneAcl(aclInterface)) {
489                         continue;
490                     }
491                     boolean allMultipleAcls = true;
492                     List<Uuid> remoteInterfaceRemoteAcls = aclInterface.getSecurityGroups();
493                     if (remoteInterfaceRemoteAcls != null) {
494                         for (Uuid remoteInterfaceRemoteAcl : remoteInterfaceRemoteAcls) {
495                             if (aclDataUtil.getRemoteAcl(remoteInterfaceRemoteAcl) == null) {
496                                 continue;
497                             }
498                             Collection<AclInterface> aclInterfaces2 =
499                                     aclDataUtil.getInterfaceList(remoteInterfaceRemoteAcl);
500                             if (aclInterfaces2 != null) {
501                                 for (AclInterface aclInterface2 : aclInterfaces2) {
502                                     if (aclInterface2.getInterfaceId().equals(aclInterface.getInterfaceId())) {
503                                         continue;
504                                     }
505                                     if (aclInterface2.getSecurityGroups().size() == 1) {
506                                         allMultipleAcls = false;
507                                         break;
508                                     }
509                                 }
510                             }
511                         }
512                     }
513                     int addRremove = allMultipleAcls ? NwConstants.DEL_FLOW : NwConstants.ADD_FLOW;
514                     addRremove = isAclDeleted ? NwConstants.DEL_FLOW : addRremove;
515                     for (AllowedAddressPairs ip : aclInterface.getAllowedAddressPairs()) {
516                         if (!AclServiceUtils.isNotIpv4AllNetwork(ip)) {
517                             continue;
518                         }
519                         updateRemoteAclTableForPort(aclInterface, aclUuid, addRremove, ip,
520                                 aclServiceUtils.buildAclId(aclUuid), aclInterface.getDpId());
521                     }
522                 }
523             }
524         }
525     }
526
527     private void updateRemoteAclTableForMultipleAcls(AclInterface port, int addOrRemove, String ignorePort) {
528         for (Uuid aclUuid : port.getSecurityGroups()) {
529             if (aclDataUtil.getRemoteAcl(aclUuid) == null) {
530                 continue;
531             }
532             Acl acl = AclServiceUtils.getAcl(dataBroker, aclUuid.getValue());
533             if (null == acl) {
534                 LOG.debug("The ACL {} is empty", aclUuid);
535                 return;
536             }
537
538             Map<String, Set<AclInterface>> mapAclWithPortSet = aclDataUtil.getRemoteAclInterfaces(aclUuid);
539             Set<BigInteger> dpns = collectDpns(mapAclWithPortSet);
540
541             AccessListEntries accessListEntries = acl.getAccessListEntries();
542             List<Ace> aceList = accessListEntries.getAce();
543             for (Ace ace : aceList) {
544                 SecurityRuleAttr aceAttr = AclServiceUtils.getAccesssListAttributes(ace);
545                 if (aceAttr.getRemoteGroupId() == null) {
546                     continue;
547                 }
548                 Collection<AclInterface> interfaceList = aclDataUtil.getInterfaceList(aceAttr.getRemoteGroupId());
549                 if (interfaceList == null) {
550                     continue;
551                 }
552
553                 for (AclInterface inter : interfaceList) {
554                     if (ignorePort.equals(inter.getInterfaceId())) {
555                         continue;
556                     }
557                     if (inter.getSecurityGroups() != null && inter.getSecurityGroups().size() == 1) {
558                         BigInteger aclId = aclServiceUtils.buildAclId(aceAttr.getRemoteGroupId());
559                         for (AllowedAddressPairs ip : port.getAllowedAddressPairs()) {
560                             if (!AclServiceUtils.isNotIpv4AllNetwork(ip)) {
561                                 continue;
562                             }
563                             for (BigInteger dpnId : dpns) {
564                                 updateRemoteAclTableForPort(port, aceAttr.getRemoteGroupId(), addOrRemove, ip, aclId,
565                                         dpnId);
566                             }
567                         }
568                         syncRemoteAclTableFromOtherDpns(port, aclUuid, aclId, addOrRemove);
569                     }
570                 }
571             }
572         }
573     }
574
575     protected abstract void updateRemoteAclTableForPort(AclInterface port, Uuid acl, int addOrRemove,
576             AllowedAddressPairs ip, BigInteger aclId, BigInteger dpId);
577
578     protected String getOperAsString(int flowOper) {
579         String oper;
580         switch (flowOper) {
581             case NwConstants.ADD_FLOW:
582                 oper = "Add";
583                 break;
584             case NwConstants.DEL_FLOW:
585                 oper = "Del";
586                 break;
587             case NwConstants.MOD_FLOW:
588                 oper = "Mod";
589                 break;
590             default:
591                 oper = "UNKNOWN";
592         }
593         return oper;
594     }
595
596     protected Set<BigInteger> collectDpns(Map<String, Set<AclInterface>> mapAclWithPortSet) {
597         Set<BigInteger> dpns = new HashSet<>();
598         if (mapAclWithPortSet == null) {
599             return dpns;
600         }
601         for (Set<AclInterface> innerSet : mapAclWithPortSet.values()) {
602             if (innerSet == null) {
603                 continue;
604             }
605             for (AclInterface inter : innerSet) {
606                 dpns.add(inter.getDpId());
607             }
608         }
609         return dpns;
610     }
611
612     /**
613      * Gets the priority of acl flow which is to be either removed or added.
614      *
615      * @param poolName
616      *            the acl pool name
617      * @param flowName
618      *            the flow name
619      * @param addOrRemove
620      *            add or remove the entries.
621      * @return the acl flow priority
622      */
623     protected int getAclFlowPriority(String poolName, String flowName, int addOrRemove) {
624         int priority;
625         if (addOrRemove == NwConstants.DEL_FLOW || addOrRemove == NwConstants.MOD_FLOW) {
626             priority = aclServiceUtils.releaseAndRemoveFlowPriorityFromCache(poolName, flowName);
627         } else {
628             priority = aclServiceUtils.allocateAndSaveFlowPriorityInCache(poolName, flowName);
629         }
630         return priority;
631     }
632
633     protected Long getElanIdFromAclInterface(String elanInterfaceName) {
634         AclInterface aclInterface = aclInterfaceCache.get(elanInterfaceName);
635         if (null != aclInterface) {
636             return aclInterface.getElanId();
637         }
638         return null;
639     }
640 }