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