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