Bulk merge of l2gw changes
[netvirt.git] / elanmanager / impl / src / main / java / org / opendaylight / netvirt / elan / l2gw / utils / L2GatewayConnectionUtils.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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
9 package org.opendaylight.netvirt.elan.l2gw.utils;
10
11 import static java.util.Collections.emptyMap;
12 import static org.opendaylight.netvirt.elan.utils.ElanUtils.isVxlanNetworkOrVxlanSegment;
13
14 import com.google.common.collect.Lists;
15 import com.google.common.util.concurrent.FluentFuture;
16 import com.google.common.util.concurrent.FutureCallback;
17 import com.google.common.util.concurrent.Futures;
18 import com.google.common.util.concurrent.MoreExecutors;
19 import com.google.common.util.concurrent.SettableFuture;
20 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.Objects;
24 import java.util.Optional;
25 import java.util.Set;
26 import java.util.concurrent.CopyOnWriteArrayList;
27 import java.util.concurrent.ExecutionException;
28 import javax.annotation.PreDestroy;
29 import javax.inject.Inject;
30 import javax.inject.Singleton;
31 import org.eclipse.jdt.annotation.NonNull;
32 import org.eclipse.jdt.annotation.Nullable;
33 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
34 import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundUtils;
35 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
36 import org.opendaylight.mdsal.binding.api.DataBroker;
37 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
38 import org.opendaylight.netvirt.elan.cache.ElanInstanceCache;
39 import org.opendaylight.netvirt.elan.l2gw.jobs.AssociateHwvtepToElanJob;
40 import org.opendaylight.netvirt.elan.l2gw.jobs.DisAssociateHwvtepFromElanJob;
41 import org.opendaylight.netvirt.elan.l2gw.listeners.LocalUcastMacListener;
42 import org.opendaylight.netvirt.elan.utils.ElanClusterUtils;
43 import org.opendaylight.netvirt.elan.utils.Scheduler;
44 import org.opendaylight.netvirt.elanmanager.utils.ElanL2GwCacheUtils;
45 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayCache;
46 import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.connections.attributes.L2gatewayConnections;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.connections.attributes.l2gatewayconnections.L2gatewayConnection;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateways.attributes.L2gateways;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateways.attributes.l2gateways.L2gateway;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateways.attributes.l2gateways.L2gatewayKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
59 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
60 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
61 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
62 import org.slf4j.Logger;
63 import org.slf4j.LoggerFactory;
64
65 @Singleton
66 public class L2GatewayConnectionUtils implements AutoCloseable {
67     private static final Logger LOG = LoggerFactory.getLogger(L2GatewayConnectionUtils.class);
68
69     private final DataBroker broker;
70     private final ElanL2GatewayUtils elanL2GatewayUtils;
71     private final ElanClusterUtils elanClusterUtils;
72     private final ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils;
73     private final ElanL2GatewayBcGroupUtils elanL2GatewayBcGroupUtils;
74     private final Scheduler scheduler;
75     private final JobCoordinator jobCoordinator;
76     private final L2GatewayCache l2GatewayCache;
77     private final ElanInstanceCache elanInstanceCache;
78     private final List<AutoCloseable> closeables = new CopyOnWriteArrayList<>();
79     private final LocalUcastMacListener localUcastMacListener;
80
81     @Inject
82     public L2GatewayConnectionUtils(DataBroker dataBroker,
83                                     ElanClusterUtils elanClusterUtils, ElanL2GatewayUtils elanL2GatewayUtils,
84                                     JobCoordinator jobCoordinator,
85                                     ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils,
86                                     ElanL2GatewayBcGroupUtils elanL2GatewayBcGroupUtils, Scheduler scheduler,
87                                     L2GatewayCache l2GatewayCache,
88                                     ElanInstanceCache elanInstanceCache,
89                                     LocalUcastMacListener localUcastMacListener) {
90         this.broker = dataBroker;
91         this.elanL2GatewayUtils = elanL2GatewayUtils;
92         this.elanClusterUtils = elanClusterUtils;
93         this.elanL2GatewayMulticastUtils = elanL2GatewayMulticastUtils;
94         this.elanL2GatewayBcGroupUtils = elanL2GatewayBcGroupUtils;
95         this.scheduler = scheduler;
96         this.jobCoordinator = jobCoordinator;
97         this.l2GatewayCache = l2GatewayCache;
98         this.elanInstanceCache = elanInstanceCache;
99         this.localUcastMacListener = localUcastMacListener;
100     }
101
102     @Override
103     @PreDestroy
104     @SuppressWarnings("checkstyle:IllegalCatch")
105     public void close() {
106         closeables.forEach(c -> {
107             try {
108                 c.close();
109             } catch (Exception e) {
110                 LOG.warn("Error closing {}", c, e);
111             }
112         });
113     }
114
115     public static boolean isGatewayAssociatedToL2Device(L2GatewayDevice l2GwDevice) {
116         return !l2GwDevice.getHwvtepNodeId().isEmpty();
117     }
118
119     @Nullable
120     public static L2gateway getNeutronL2gateway(DataBroker broker, Uuid l2GatewayId) {
121         if (l2GatewayId != null) {
122             LOG.debug("getNeutronL2gateway for {}", l2GatewayId.getValue());
123             InstanceIdentifier<L2gateway> inst = InstanceIdentifier.create(Neutron.class).child(L2gateways.class)
124                     .child(L2gateway.class, new L2gatewayKey(l2GatewayId));
125             try {
126                 return SingleTransactionDataBroker
127                     .syncReadOptional(broker, LogicalDatastoreType.CONFIGURATION, inst)
128                     .orElse(null);
129             } catch (ExecutionException | InterruptedException e) {
130                 LOG.error("getNeutronL2gateway: Exception while reading L2gateway DS for the ID {}", l2GatewayId, e);
131             }
132             return null;
133         }
134
135         return null;
136     }
137
138     @NonNull
139     public static List<L2gateway> getL2gatewayList(DataBroker broker) {
140         InstanceIdentifier<L2gateways> inst = InstanceIdentifier.create(Neutron.class).child(L2gateways.class);
141         try {
142             return new ArrayList<>((SingleTransactionDataBroker.syncReadOptional(broker,
143                     LogicalDatastoreType.CONFIGURATION, inst).map(L2gateways::nonnullL2gateway)
144                     .orElse(emptyMap())).values());
145         } catch (ExecutionException | InterruptedException e) {
146             LOG.error("getNeutronL2gateway: Exception while reading L2gateway DS", e);
147         }
148         return null;
149     }
150
151     @NonNull
152     public static List<L2gatewayConnection> getAllL2gatewayConnections(DataBroker broker) {
153         InstanceIdentifier<L2gatewayConnections> inst = InstanceIdentifier.create(Neutron.class)
154                 .child(L2gatewayConnections.class);
155         try {
156             return new ArrayList<>((SingleTransactionDataBroker.syncReadOptional(broker,
157                     LogicalDatastoreType.CONFIGURATION, inst).map(L2gatewayConnections::nonnullL2gatewayConnection)
158                     .orElse(emptyMap())).values());
159         } catch (ExecutionException | InterruptedException e) {
160             LOG.error("getNeutronL2gateway: Exception while reading L2gateway DS", e);
161         }
162         return null;
163     }
164
165     /**
166      * Gets the associated l2 gw connections.
167      *
168      * @param broker
169      *            the broker
170      * @param l2GatewayIds
171      *            the l2 gateway ids
172      * @return the associated l2 gw connections
173      */
174     @NonNull
175     public static List<L2gatewayConnection> getAssociatedL2GwConnections(DataBroker broker, Set<Uuid> l2GatewayIds) {
176         List<L2gatewayConnection> allL2GwConns = getAllL2gatewayConnections(broker);
177         List<L2gatewayConnection> l2GwConnections = new ArrayList<>();
178         for (Uuid l2GatewayId : l2GatewayIds) {
179             for (L2gatewayConnection l2GwConn : allL2GwConns) {
180                 if (l2GwConn.getL2gatewayId() != null) {
181                     if (Objects.equals(l2GwConn.getL2gatewayId(), l2GatewayId)) {
182                         l2GwConnections.add(l2GwConn);
183                     }
184                 }
185                 else {
186                     LOG.warn("No l2gatewayId for l2gatewayconnection {} ", l2GwConn.key().getUuid());
187                 }
188
189             }
190         }
191         return l2GwConnections;
192     }
193
194     /**
195      * Gets the associated l2 gw connections.
196      *
197      * @param broker
198      *            the broker
199      * @param elanName
200      *            the elan Name
201      * @return the associated l2 gw connection with elan
202      */
203     @NonNull
204     public static List<L2gatewayConnection> getL2GwConnectionsByElanName(DataBroker broker, String elanName) {
205         List<L2gatewayConnection> allL2GwConns = getAllL2gatewayConnections(broker);
206         List<L2gatewayConnection> elanL2GateWayConnections = new ArrayList<>();
207         for (L2gatewayConnection l2GwConn : allL2GwConns) {
208             if (l2GwConn.getNetworkId().getValue().equalsIgnoreCase(elanName)) {
209                 elanL2GateWayConnections.add(l2GwConn);
210             }
211         }
212         return elanL2GateWayConnections;
213     }
214
215     public void addL2GatewayConnection(L2gatewayConnection input) {
216         addL2GatewayConnection(input, null/*deviceName*/, null);
217     }
218
219     public void addL2GatewayConnection(final L2gatewayConnection input,
220                                        final String l2GwDeviceName) {
221         addL2GatewayConnection(input, l2GwDeviceName, null);
222     }
223
224     public void addL2GatewayConnection(final L2gatewayConnection input,
225                                        @Nullable final String l2GwDeviceName ,
226                                        @Nullable L2gateway l2Gateway) {
227         LOG.info("Adding L2gateway Connection:{} vlan: {} device name {}",
228             input.key().getUuid(), input.getSegmentId(), l2GwDeviceName);
229
230         Uuid networkUuid = input.getNetworkId();
231
232         // Taking cluster reboot scenario , if Elan instance is not available when l2GatewayConnection add events
233         // comes we need to wait for elaninstance to resolve. Hence updating the map with the runnable .
234         // When elanInstance add comes , it look in to the map and run the associated runnable associated with it.
235         ElanInstance elanInstance = elanInstanceCache.get(networkUuid.getValue(),
236             () -> addL2GatewayConnection(input, l2GwDeviceName)).orElse(null);
237         if (elanInstance == null) {
238             return;
239         }
240
241         if (!isVxlanNetworkOrVxlanSegment(elanInstance)) {
242             LOG.error("Neutron network with id {} is not VxlanNetwork", networkUuid.getValue());
243         } else {
244             Uuid l2GatewayId = input.getL2gatewayId();
245             if (l2Gateway == null) {
246                 l2Gateway = getNeutronL2gateway(broker, l2GatewayId);
247             }
248             if (l2Gateway == null) {
249                 LOG.error("L2Gateway with id {} is not present", l2GatewayId);
250             } else {
251                 associateHwvtepsToElan(elanInstance, l2Gateway, input, l2GwDeviceName);
252             }
253         }
254     }
255
256     public void deleteL2GatewayConnection(L2gatewayConnection input) {
257         LOG.info("Deleting L2gateway Connection with ID: {} vlan : {}",
258             input.key().getUuid(), input.getSegmentId());
259
260         Uuid networkUuid = input.getNetworkId();
261         String elanName = networkUuid.getValue();
262         disAssociateHwvtepsFromElan(elanName, input);
263     }
264
265     private void disAssociateHwvtepsFromElan(String elanName, L2gatewayConnection input) {
266         Integer defaultVlan = input.getSegmentId();
267         List<L2GatewayDevice> l2Devices = ElanL2GwCacheUtils.getAllElanDevicesFromCache();
268         List<Devices> l2gwDevicesToBeDeleted = new ArrayList<>();
269         for (L2GatewayDevice elanL2gwDevice : l2Devices) {
270             if (elanL2gwDevice.getL2GatewayIds().contains(input.key().getUuid())) {
271                 l2gwDevicesToBeDeleted.addAll(elanL2gwDevice.getDevicesForL2gwConnectionId(input.key().getUuid()));
272             }
273         }
274         if (l2gwDevicesToBeDeleted.isEmpty()) {
275             //delete logical switch
276             Uuid l2GatewayId = input.getL2gatewayId();
277             L2gateway l2Gateway = L2GatewayConnectionUtils.getNeutronL2gateway(broker, l2GatewayId);
278             if (l2Gateway == null) {
279                 LOG.error("Failed to find the l2gateway for the connection {}", input.getUuid());
280                 return;
281             } else if (l2Gateway.nonnullDevices() != null) {
282                 l2gwDevicesToBeDeleted.addAll(l2Gateway.nonnullDevices().values());
283             }
284         }
285         for (Devices l2Device : l2gwDevicesToBeDeleted) {
286             String l2DeviceName = l2Device.getDeviceName();
287             L2GatewayDevice l2GatewayDevice = l2GatewayCache.get(l2DeviceName);
288             String hwvtepNodeId = l2GatewayDevice.getHwvtepNodeId();
289             if (hwvtepNodeId == null) {
290                 LOG.error("Could not disassociate failed to get node id {}", l2DeviceName);
291                 continue;
292             }
293             boolean isLastL2GwConnDeleted = false;
294             L2GatewayDevice elanL2GwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elanName, hwvtepNodeId);
295             if (elanL2GwDevice != null && isLastL2GwConnBeingDeleted(elanL2GwDevice)) {
296                 // Delete L2 Gateway device from 'ElanL2GwDevice' cache
297                 LOG.debug("Elan L2Gw Conn cache removed for id {}", hwvtepNodeId);
298                 ElanL2GwCacheUtils.removeL2GatewayDeviceFromCache(elanName, hwvtepNodeId);
299                 isLastL2GwConnDeleted = true;
300             } else {
301                 Uuid l2GwConnId = input.key().getUuid();
302                 LOG.debug("Elan L2Gw Conn cache with id {} is being referred by other L2Gw Conns; so only "
303                         + "L2 Gw Conn {} reference is removed", hwvtepNodeId, l2GwConnId);
304                 if (elanL2GwDevice != null) {
305                     elanL2GwDevice.removeL2GatewayId(l2GwConnId);
306                 } else {
307                     isLastL2GwConnDeleted = true;
308                 }
309             }
310
311             DisAssociateHwvtepFromElanJob disAssociateHwvtepToElanJob =
312                     new DisAssociateHwvtepFromElanJob(elanL2GatewayUtils, elanL2GatewayMulticastUtils,
313                             elanL2GatewayBcGroupUtils, elanClusterUtils, scheduler, jobCoordinator,
314                             elanL2GwDevice, elanName, l2Device, defaultVlan, hwvtepNodeId, isLastL2GwConnDeleted);
315             elanClusterUtils.runOnlyInOwnerNode(disAssociateHwvtepToElanJob.getJobKey(), "remove l2gw connection job",
316                     disAssociateHwvtepToElanJob);
317         }
318     }
319
320     private void associateHwvtepsToElan(ElanInstance elanInstance,
321             L2gateway l2Gateway, L2gatewayConnection input, String l2GwDeviceName) {
322         String elanName = elanInstance.getElanInstanceName();
323         Integer defaultVlan = input.getSegmentId();
324         Uuid l2GwConnId = input.key().getUuid();
325         List<Devices> l2Devices =  new ArrayList<>(l2Gateway.nonnullDevices().values());
326
327         LOG.trace("Associating ELAN {} with L2Gw Conn Id {} having below L2Gw devices {}", elanName, l2GwConnId,
328                 l2Devices);
329
330         for (Devices l2Device : l2Devices) {
331             String l2DeviceName = l2Device.getDeviceName();
332             // L2gateway can have more than one L2 Gw devices. Configure Logical Switch, VLAN mappings,...
333             // only on the switch which has come up just now and exclude all other devices from
334             // preprovisioning/re-provisioning
335             if (l2GwDeviceName != null && !l2GwDeviceName.equals(l2DeviceName)) {
336                 LOG.debug("Associating Hwvtep to ELAN is not been processed for {}; as only {} got connected now!",
337                         l2DeviceName, l2GwDeviceName);
338                 continue;
339             }
340             L2GatewayDevice l2GatewayDevice = l2GatewayCache.get(l2DeviceName);
341             if (isL2GwDeviceConnected(l2GatewayDevice)) {
342                 NodeId hwvtepNodeId = new NodeId(l2GatewayDevice.getHwvtepNodeId());
343
344                 // Delete pending delete logical switch task if scheduled
345                 elanL2GatewayUtils.cancelDeleteLogicalSwitch(hwvtepNodeId,
346                         ElanL2GatewayUtils.getLogicalSwitchFromElan(elanName));
347
348                 // Add L2 Gateway device to 'ElanL2GwDevice' cache
349                 addL2DeviceToElanL2GwCache(elanName, l2GatewayDevice, l2GwConnId, l2Device);
350                 AssociateHwvtepToElanJob associateHwvtepToElanJob = new AssociateHwvtepToElanJob(broker,
351                         elanL2GatewayUtils, elanL2GatewayMulticastUtils, elanL2GatewayBcGroupUtils,
352                         l2GatewayDevice, elanInstance, l2Device, defaultVlan);
353
354                 elanClusterUtils.runOnlyInOwnerNode(associateHwvtepToElanJob.getJobKey(),
355                         "create logical switch in hwvtep topo", associateHwvtepToElanJob);
356
357             } else {
358                 LOG.error("L2GwConn create is not handled for device with id {} as it's not connected {}",
359                         l2DeviceName, input);
360             }
361         }
362     }
363
364     public L2GatewayDevice addL2DeviceToElanL2GwCache(String elanName, L2GatewayDevice l2GatewayDevice, Uuid l2GwConnId,
365             Devices l2Device) {
366         String l2gwDeviceNodeId = l2GatewayDevice.getHwvtepNodeId();
367         L2GatewayDevice elanL2GwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elanName, l2gwDeviceNodeId);
368         if (elanL2GwDevice == null) {
369             elanL2GwDevice = new L2GatewayDevice(l2GatewayDevice.getDeviceName());
370             elanL2GwDevice.setHwvtepNodeId(l2gwDeviceNodeId);
371             elanL2GwDevice.setTunnelIps(l2GatewayDevice.getTunnelIps());
372             ElanL2GwCacheUtils.addL2GatewayDeviceToCache(elanName, elanL2GwDevice);
373             LOG.debug("Elan L2GwConn cache created for hwvtep id {}", l2gwDeviceNodeId);
374         } else {
375             LOG.debug("Elan L2GwConn cache already exists for hwvtep id {}; updating L2GwConn id {} to it",
376                     l2gwDeviceNodeId, l2GwConnId);
377         }
378         elanL2GwDevice.addL2GatewayId(l2GwConnId);
379         elanL2GwDevice.addL2gwConnectionIdToDevice(l2GwConnId, l2Device);
380
381         //incase of cluster reboot scenario southbound device would have added more macs
382         //while odl is down, pull them now
383         readAndCopyLocalUcastMacsToCache(elanName, l2GatewayDevice);
384
385         LOG.info("Elan L2GwConn cache updated with below details: {}", elanL2GwDevice);
386         return elanL2GwDevice;
387     }
388
389     private static boolean isL2GwDeviceConnected(L2GatewayDevice l2GwDevice) {
390         return l2GwDevice != null && l2GwDevice.getHwvtepNodeId() != null;
391     }
392
393     protected static boolean isLastL2GwConnBeingDeleted(@NonNull L2GatewayDevice l2GwDevice) {
394         return l2GwDevice.getL2GatewayIds().size() == 1;
395     }
396
397     private void readAndCopyLocalUcastMacsToCache(final String elanName, final L2GatewayDevice l2GatewayDevice) {
398         final InstanceIdentifier<Node> nodeIid = HwvtepSouthboundUtils.createInstanceIdentifier(
399                 new NodeId(l2GatewayDevice.getHwvtepNodeId()));
400         jobCoordinator.enqueueJob(elanName + ":" + l2GatewayDevice.getDeviceName(), () -> {
401             final SettableFuture settableFuture = SettableFuture.create();
402             FluentFuture<Optional<Node>> fluentFuture = broker.newReadOnlyTransaction().read(
403                 LogicalDatastoreType.OPERATIONAL, nodeIid);
404             Futures.addCallback(fluentFuture, new FutureCallback<Optional<Node>>() {
405                     @Override
406                     public void onSuccess(@NonNull Optional<Node> resultNode) {
407                         Optional<Node> nodeOptional = resultNode;
408                         if (nodeOptional.isPresent()) {
409                             Node node = nodeOptional.get();
410                             if (node.augmentation(HwvtepGlobalAugmentation.class) != null) {
411                                 List<LocalUcastMacs> localUcastMacs = new ArrayList<>(
412                                         node.augmentation(HwvtepGlobalAugmentation.class)
413                                             .nonnullLocalUcastMacs().values());
414                                 if (localUcastMacs == null) {
415                                     return;
416                                 }
417                                 localUcastMacs.stream()
418                                         .filter(mac -> macBelongsToLogicalSwitch(mac, elanName))
419                                         .forEach(mac -> {
420                                             InstanceIdentifier<LocalUcastMacs> macIid = getMacIid(nodeIid, mac);
421                                             localUcastMacListener.added(macIid, mac);
422                                         });
423                             }
424                         }
425                     }
426
427                     @Override
428                     public void onFailure(Throwable throwable) {
429                     }
430                 }, MoreExecutors.directExecutor());
431             return Lists.newArrayList(fluentFuture);
432         });
433     }
434
435     /**
436      * Gets the associated l2 gw connections.
437      *
438      * @param l2GatewayId the l2 gateway id
439      *
440      * @return the associated l2 gw connections
441      */
442     public List<L2gatewayConnection> getL2GwConnectionsByL2GatewayId(Uuid l2GatewayId) {
443         List<L2gatewayConnection> l2GwConnections = new ArrayList<>();
444         List<L2gatewayConnection> allL2GwConns = getAllL2gatewayConnections(broker);
445         for (L2gatewayConnection l2GwConn : allL2GwConns) {
446             if (l2GwConn.getL2gatewayId() != null &&  Objects.equals(l2GwConn.getL2gatewayId(), l2GatewayId)) {
447                 l2GwConnections.add(l2GwConn);
448             }
449         }
450         return l2GwConnections;
451     }
452
453     @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
454             justification = "https://github.com/spotbugs/spotbugs/issues/811")
455     private static boolean macBelongsToLogicalSwitch(LocalUcastMacs mac, String logicalSwitchName) {
456         InstanceIdentifier<LogicalSwitches> iid = (InstanceIdentifier<LogicalSwitches>)
457                 mac.getLogicalSwitchRef().getValue();
458         return iid.firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue().equals(logicalSwitchName);
459     }
460
461     static InstanceIdentifier<LocalUcastMacs> getMacIid(InstanceIdentifier<Node> nodeIid, LocalUcastMacs mac) {
462         return nodeIid.augmentation(HwvtepGlobalAugmentation.class).child(LocalUcastMacs.class, mac.key());
463     }
464 }