NETVIRT-1193: ACL dropping IPv6 RA packets from external router.
[netvirt.git] / neutronvpn / impl / src / main / java / org / opendaylight / netvirt / neutronvpn / NeutronPortChangeListener.java
1 /*
2  * Copyright © 2015, 2017 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 package org.opendaylight.netvirt.neutronvpn;
9
10 import static org.opendaylight.netvirt.neutronvpn.NeutronvpnUtils.buildfloatingIpIdToPortMappingIdentifier;
11
12 import com.google.common.base.Optional;
13 import com.google.common.base.Strings;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import com.google.gson.Gson;
16 import com.google.gson.JsonArray;
17 import com.google.gson.JsonElement;
18 import com.google.gson.JsonObject;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Locale;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.stream.Collectors;
28 import javax.annotation.PostConstruct;
29 import javax.inject.Singleton;
30 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
31 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
32 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
33 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
34 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
35 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
36 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
37 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
38 import org.opendaylight.genius.mdsalutil.MDSALUtil;
39 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
40 import org.opendaylight.netvirt.elanmanager.api.IElanService;
41 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
42 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
43 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
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.genius.interfacemanager.rev160406.IfL2vlan;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlanBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAclBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntries;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.hostconfig.rev150712.hostconfig.attributes.hostconfigs.Hostconfig;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
71 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
72 import org.slf4j.Logger;
73 import org.slf4j.LoggerFactory;
74
75 @Singleton
76 public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase<Port, NeutronPortChangeListener> {
77     private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChangeListener.class);
78     private final DataBroker dataBroker;
79     private final ManagedNewTransactionRunner txRunner;
80     private final NeutronvpnManager nvpnManager;
81     private final NeutronvpnNatManager nvpnNatManager;
82     private final NeutronSubnetGwMacResolver gwMacResolver;
83     private final IElanService elanService;
84     private final JobCoordinator jobCoordinator;
85     private final NeutronvpnUtils neutronvpnUtils;
86     private final HostConfigCache hostConfigCache;
87
88     public NeutronPortChangeListener(final DataBroker dataBroker,
89                                      final NeutronvpnManager neutronvpnManager,
90                                      final NeutronvpnNatManager neutronvpnNatManager,
91                                      final NeutronSubnetGwMacResolver gwMacResolver,
92                                      final IElanService elanService,
93                                      final JobCoordinator jobCoordinator,
94                                      final NeutronvpnUtils neutronvpnUtils,
95                                      final HostConfigCache hostConfigCache) {
96         super(Port.class, NeutronPortChangeListener.class);
97         this.dataBroker = dataBroker;
98         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
99         nvpnManager = neutronvpnManager;
100         nvpnNatManager = neutronvpnNatManager;
101         this.gwMacResolver = gwMacResolver;
102         this.elanService = elanService;
103         this.jobCoordinator = jobCoordinator;
104         this.neutronvpnUtils = neutronvpnUtils;
105         this.hostConfigCache = hostConfigCache;
106     }
107
108     @Override
109     @PostConstruct
110     public void init() {
111         LOG.info("{} init", getClass().getSimpleName());
112         registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
113     }
114
115     @Override
116     protected InstanceIdentifier<Port> getWildCardPath() {
117         return InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class);
118     }
119
120     @Override
121     protected NeutronPortChangeListener getDataTreeChangeListener() {
122         return NeutronPortChangeListener.this;
123     }
124
125
126     @Override
127     protected void add(InstanceIdentifier<Port> identifier, Port input) {
128         String portName = input.getUuid().getValue();
129         LOG.trace("Adding Port : key: {}, value={}", identifier, input);
130         Network network = neutronvpnUtils.getNeutronNetwork(input.getNetworkId());
131         if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
132             LOG.warn("neutron vpn received a port add() for a network without a provider extension augmentation "
133                             + "or with an unsupported network type for the port {} which is part of network {}",
134                     portName, network);
135             return;
136         }
137         neutronvpnUtils.addToPortCache(input);
138         String portStatus = NeutronUtils.PORT_STATUS_DOWN;
139         if (!Strings.isNullOrEmpty(input.getDeviceOwner()) && !Strings.isNullOrEmpty(input.getDeviceId())) {
140             if (input.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF)) {
141                 handleRouterInterfaceAdded(input);
142                 NeutronUtils.createPortStatus(input.getUuid().getValue(), NeutronUtils.PORT_STATUS_ACTIVE, dataBroker);
143                 return;
144             }
145             if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(input.getDeviceOwner())) {
146                 handleRouterGatewayUpdated(input);
147                 portStatus = NeutronUtils.PORT_STATUS_ACTIVE;
148             } else if (NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(input.getDeviceOwner())) {
149                 handleFloatingIpPortUpdated(null, input);
150                 portStatus = NeutronUtils.PORT_STATUS_ACTIVE;
151             }
152         }
153         // Switchdev ports need to be bounded to a host before creation
154         // in order to validate the supported vnic types from the hostconfig
155         if (input.getFixedIps() != null
156             && !input.getFixedIps().isEmpty()
157             && !(isPortTypeSwitchdev(input) && !isPortBound(input))) {
158             handleNeutronPortCreated(input);
159         }
160         NeutronUtils.createPortStatus(input.getUuid().getValue(), portStatus, dataBroker);
161     }
162
163     @Override
164     protected void remove(InstanceIdentifier<Port> identifier, Port input) {
165         LOG.trace("Removing Port : key: {}, value={}", identifier, input);
166         Network network = neutronvpnUtils.getNeutronNetwork(input.getNetworkId());
167         if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
168             String portName = input.getUuid().getValue();
169             LOG.warn("neutron vpn received a port remove() for a network without a provider extension augmentation "
170                             + "or with an unsupported network type for the port {} which is part of network {}",
171                     portName, network);
172             return;
173         }
174         neutronvpnUtils.removeFromPortCache(input);
175         NeutronUtils.deletePortStatus(input.getUuid().getValue(), dataBroker);
176
177         if (!Strings.isNullOrEmpty(input.getDeviceOwner()) && !Strings.isNullOrEmpty(input.getDeviceId())) {
178             if (input.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF)) {
179                 handleRouterInterfaceRemoved(input);
180                 /* nothing else to do here */
181                 return;
182             } else if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(input.getDeviceOwner())
183                     || NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(input.getDeviceOwner())) {
184                 elanService.removeKnownL3DmacAddress(input.getMacAddress().getValue(), input.getNetworkId().getValue());
185             }
186         }
187         if (input.getFixedIps() != null) {
188             handleNeutronPortDeleted(input);
189         }
190     }
191
192     @Override
193     protected void update(InstanceIdentifier<Port> identifier, Port original, Port update) {
194         // Switchdev ports need to be bounded to a host before creation
195         // in order to validate the supported vnic types from the hostconfig
196         if (isPortTypeSwitchdev(original)
197             && !isPortBound(original)
198             && isPortBound(update)) {
199             handleNeutronPortCreated(update);
200         }
201         final String portName = update.getUuid().getValue();
202         Network network = neutronvpnUtils.getNeutronNetwork(update.getNetworkId());
203         LOG.info("Update port {} from network {}", portName, update.getNetworkId().toString());
204         if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
205             LOG.error("neutron vpn received a port update() for a network without a provider extension augmentation "
206                     + "or with an unsupported network type for the port {} which is part of network {}",
207                     portName, network);
208             return;
209         }
210         neutronvpnUtils.addToPortCache(update);
211
212         if ((Strings.isNullOrEmpty(original.getDeviceOwner()) || Strings.isNullOrEmpty(original.getDeviceId())
213                 || NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING.equalsIgnoreCase(original.getDeviceId()))
214                 && !Strings.isNullOrEmpty(update.getDeviceOwner()) && !Strings.isNullOrEmpty(update.getDeviceId())) {
215             if (update.getDeviceOwner().equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF)) {
216                 handleRouterInterfaceAdded(update);
217                 return;
218             }
219             if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(update.getDeviceOwner())) {
220                 handleRouterGatewayUpdated(update);
221             } else if (NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(update.getDeviceOwner())) {
222                 handleFloatingIpPortUpdated(original, update);
223             }
224         } else {
225             Set<FixedIps> oldIPs = getFixedIpSet(original.getFixedIps());
226             Set<FixedIps> newIPs = getFixedIpSet(update.getFixedIps());
227             if (!oldIPs.equals(newIPs)) {
228                 handleNeutronPortUpdated(original, update);
229             }
230         }
231
232         // check if port security enabled/disabled as part of port update
233         boolean origSecurityEnabled = NeutronvpnUtils.getPortSecurityEnabled(original);
234         boolean updatedSecurityEnabled = NeutronvpnUtils.getPortSecurityEnabled(update);
235
236         if (origSecurityEnabled || updatedSecurityEnabled) {
237             InstanceIdentifier<Interface>  interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(portName);
238             jobCoordinator.enqueueJob("PORT- " + portName, () -> {
239                 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
240                 try {
241                     Optional<Interface> optionalInf =
242                             SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
243                                     interfaceIdentifier);
244                     if (optionalInf.isPresent()) {
245                         InterfaceBuilder interfaceBuilder = new InterfaceBuilder(optionalInf.get());
246                         InterfaceAcl infAcl = handlePortSecurityUpdated(original, update,
247                                 origSecurityEnabled, updatedSecurityEnabled, interfaceBuilder).build();
248                         interfaceBuilder.addAugmentation(InterfaceAcl.class, infAcl);
249                         LOG.info("update: Of-port-interface updation for port {}", portName);
250                         // Update OFPort interface for this neutron port
251                         wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier,
252                                 interfaceBuilder.build());
253                     } else {
254                         LOG.warn("update: Interface {} is not present", portName);
255                     }
256                 } catch (ReadFailedException e) {
257                     LOG.error("update: Failed to update interface {}", portName, e);
258                 }
259                 List<ListenableFuture<Void>> futures = new ArrayList<>();
260                 futures.add(wrtConfigTxn.submit());
261                 return futures;
262             });
263         }
264     }
265
266     private void handleFloatingIpPortUpdated(Port original, Port update) {
267         if ((original == null || original.getDeviceId().equals(NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING))
268             && !update.getDeviceId().equals(NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING)) {
269             // populate floating-ip uuid and floating-ip port attributes (uuid, mac and subnet id for the ONLY
270             // fixed IP) to be used by NAT, depopulated in NATService once mac is retrieved in the removal path
271             addToFloatingIpPortInfo(new Uuid(update.getDeviceId()), update.getUuid(), update.getFixedIps().get(0)
272                     .getSubnetId(), update.getMacAddress().getValue());
273             elanService.addKnownL3DmacAddress(update.getMacAddress().getValue(), update.getNetworkId().getValue());
274         }
275     }
276
277     private void handleRouterInterfaceAdded(Port routerPort) {
278         if (routerPort.getDeviceId() != null) {
279             Uuid routerId = new Uuid(routerPort.getDeviceId());
280             Uuid infNetworkId = routerPort.getNetworkId();
281             Uuid existingVpnId = neutronvpnUtils.getVpnForNetwork(infNetworkId);
282
283             elanService.addKnownL3DmacAddress(routerPort.getMacAddress().getValue(), infNetworkId.getValue());
284             if (existingVpnId == null) {
285                 Set<Uuid> listVpnIds = new HashSet<>();
286                 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
287                 if (vpnId == null) {
288                     vpnId = routerId;
289                 }
290                 listVpnIds.add(vpnId);
291                 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
292                 List<Subnetmap> subnetMapList = new ArrayList<>();
293                 List<FixedIps> portIps = routerPort.getFixedIps();
294                 boolean portIsIpv6 = false;
295                 for (FixedIps portIP : portIps) {
296                     // NOTE:  Please donot change the order of calls to updateSubnetNodeWithFixedIP
297                     // and addSubnetToVpn here
298                     if (internetVpnId != null
299                         && portIP.getIpAddress().getIpv6Address() != null) {
300                         portIsIpv6 = true;
301                     }
302                     String ipValue = String.valueOf(portIP.getIpAddress().getValue());
303                     Uuid subnetId = portIP.getSubnetId();
304                     nvpnManager.updateSubnetNodeWithFixedIp(subnetId, routerId,
305                             routerPort.getUuid(), ipValue, routerPort.getMacAddress().getValue(), vpnId);
306                     Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
307                     subnetMapList.add(sn);
308                 }
309                 if (portIsIpv6) {
310                     listVpnIds.add(internetVpnId);
311                     if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChangeToAdd(
312                                      IpVersionChoice.IPV6, internetVpnId)) {
313                         neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(),
314                                                                      IpVersionChoice.IPV6, true);
315                         neutronvpnUtils.updateVpnInstanceWithFallback(internetVpnId.getValue(), true);
316                     }
317                 }
318                 if (! subnetMapList.isEmpty()) {
319                     nvpnManager.createVpnInterface(listVpnIds, routerPort, null);
320                 }
321                 for (FixedIps portIP : routerPort.getFixedIps()) {
322                     String ipValue = String.valueOf(portIP.getIpAddress().getValue());
323                     IpVersionChoice version = neutronvpnUtils.getIpVersionFromString(ipValue);
324                     if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChangeToAdd(version, vpnId)) {
325                         neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(),
326                                version, true);
327                     }
328                     if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
329                         nvpnManager.addSubnetToVpn(vpnId, portIP.getSubnetId(),
330                                                         null /* internet-vpn-id */);
331                     } else {
332                         nvpnManager.addSubnetToVpn(vpnId, portIP.getSubnetId(), internetVpnId);
333                     }
334                     LOG.trace("NeutronPortChangeListener Add Subnet Gateway IP {} MAC {} Interface {} VPN {}",
335                             ipValue, routerPort.getMacAddress(),
336                             routerPort.getUuid().getValue(), vpnId.getValue());
337                 }
338                 nvpnManager.addToNeutronRouterInterfacesMap(routerId, routerPort.getUuid().getValue());
339                 nvpnNatManager.handleSubnetsForExternalRouter(routerId);
340                 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
341                 String portInterfaceName = createOfPortInterface(routerPort, wrtConfigTxn);
342                 createElanInterface(routerPort, portInterfaceName, wrtConfigTxn);
343                 wrtConfigTxn.submit();
344             } else {
345                 LOG.error("Neutron network {} corresponding to router interface port {} for neutron router {}"
346                     + " already associated to VPN {}", infNetworkId.getValue(), routerPort.getUuid().getValue(),
347                     routerId.getValue(), existingVpnId.getValue());
348             }
349         }
350     }
351
352     private void handleRouterInterfaceRemoved(Port routerPort) {
353         if (routerPort.getDeviceId() != null) {
354             Uuid routerId = new Uuid(routerPort.getDeviceId());
355             Uuid infNetworkId = routerPort.getNetworkId();
356             elanService.removeKnownL3DmacAddress(routerPort.getMacAddress().getValue(), infNetworkId.getValue());
357             Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
358             if (vpnId == null) {
359                 vpnId = routerId;
360             }
361             List<FixedIps> portIps = routerPort.getFixedIps();
362             boolean vpnInstanceInternetIpVersionRemoved = false;
363             Uuid vpnInstanceInternetUuid = null;
364             for (FixedIps portIP : portIps) {
365                 // Internet VPN : flush InternetVPN first
366                 Uuid subnetId = portIP.getSubnetId();
367                 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
368                 if (sn != null && sn.getInternetVpnId() != null) {
369                     if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sn, sn.getInternetVpnId())) {
370                         vpnInstanceInternetIpVersionRemoved = true;
371                         vpnInstanceInternetUuid = sn.getInternetVpnId();
372                     }
373                     nvpnManager.updateVpnInternetForSubnet(sn, sn.getInternetVpnId(), false);
374                 }
375             }
376             /* Remove ping responder for router interfaces
377              *  A router interface reference in a VPN will have to be removed before the host interface references
378              * for that subnet in the VPN are removed. This is to ensure that the FIB Entry of the router interface
379              *  is not the last entry to be removed for that subnet in the VPN.
380              *  If router interface FIB entry is the last to be removed for a subnet in a VPN , then all the host
381              *  interface references in the vpn will already have been cleared, which will cause failures in
382              *  cleanup of router interface flows*/
383             nvpnManager.deleteVpnInterface(routerPort.getUuid().getValue(),
384                                            null /* vpn-id */, null /* wrtConfigTxn*/);
385             // update RouterInterfaces map
386             WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
387             boolean vpnInstanceIpVersionRemoved = false;
388             IpVersionChoice vpnInstanceIpVersionToRemove = IpVersionChoice.UNDEFINED;
389             for (FixedIps portIP : portIps) {
390                 Subnetmap sn = neutronvpnUtils.getSubnetmap(portIP.getSubnetId());
391                 // router Port have either IPv4 or IPv6, never both
392                 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sn, vpnId)) {
393                     vpnInstanceIpVersionRemoved = true;
394                     vpnInstanceIpVersionToRemove = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
395                 }
396                 String ipValue = String.valueOf(portIP.getIpAddress().getValue());
397                 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(), ipValue, wrtConfigTxn);
398                 // NOTE:  Please donot change the order of calls to removeSubnetFromVpn and
399                 // and updateSubnetNodeWithFixedIP
400                 nvpnManager.removeSubnetFromVpn(vpnId, portIP.getSubnetId(), sn != null ? sn.getInternetVpnId() : null);
401                 nvpnManager.updateSubnetNodeWithFixedIp(portIP.getSubnetId(), null, null, null, null, null);
402             }
403             nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, routerPort.getUuid().getValue());
404             deleteElanInterface(routerPort.getUuid().getValue(), wrtConfigTxn);
405             deleteOfPortInterface(routerPort, wrtConfigTxn);
406             wrtConfigTxn.submit();
407             nvpnNatManager.handleSubnetsForExternalRouter(routerId);
408             if (vpnInstanceIpVersionRemoved) {
409                 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), vpnInstanceIpVersionToRemove,
410                           false);
411             }
412             if (vpnInstanceInternetIpVersionRemoved) {
413                 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnInstanceInternetUuid.getValue(),
414                                                              IpVersionChoice.IPV6, false);
415                 neutronvpnUtils.updateVpnInstanceWithFallback(vpnInstanceInternetUuid.getValue(), false);
416             }
417         }
418     }
419
420     private void handleRouterGatewayUpdated(Port routerGwPort) {
421         Uuid routerId = new Uuid(routerGwPort.getDeviceId());
422         Uuid networkId = routerGwPort.getNetworkId();
423         Network network = neutronvpnUtils.getNeutronNetwork(networkId);
424         if (network == null) {
425             return;
426         }
427         boolean isExternal = neutronvpnUtils.getIsExternal(network);
428         if (isExternal) {
429             Uuid vpnInternetId = neutronvpnUtils.getVpnForNetwork(networkId);
430             if (vpnInternetId != null) {
431                 List<Subnetmap> snList = neutronvpnUtils.getNeutronRouterSubnetMaps(routerId);
432                 for (Subnetmap sn : snList) {
433                     if (sn.getNetworkId() == networkId) {
434                         continue;
435                     }
436                     if (neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()) != IpVersionChoice.IPV6) {
437                         continue;
438                     }
439                     nvpnManager.addSubnetToVpn(null, sn.getId(), vpnInternetId);
440                 }
441             }
442         }
443         elanService.addKnownL3DmacAddress(routerGwPort.getMacAddress().getValue(), networkId.getValue());
444
445         Router router = neutronvpnUtils.getNeutronRouter(routerId);
446         if (router == null) {
447             LOG.warn("No router found for router GW port {} for router {}", routerGwPort.getUuid().getValue(),
448                     routerId.getValue());
449             return;
450         }
451         gwMacResolver.sendArpRequestsToExtGateways(router);
452
453         setExternalGwMac(routerGwPort, routerId);
454     }
455
456     private void setExternalGwMac(Port routerGwPort, Uuid routerId) {
457         // During full-sync networking-odl syncs routers before ports. As such,
458         // the MAC of the router's gw port is not available to be set when the
459         // router is written. We catch that here.
460         InstanceIdentifier<Routers> routersId = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
461         Optional<Routers> optionalRouter = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId);
462         if (!optionalRouter.isPresent()) {
463             return;
464         }
465
466         Routers extRouters = optionalRouter.get();
467         if (extRouters.getExtGwMacAddress() != null) {
468             return;
469         }
470
471         RoutersBuilder builder = new RoutersBuilder(extRouters);
472         builder.setExtGwMacAddress(routerGwPort.getMacAddress().getValue());
473         MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId, builder.build());
474     }
475
476     private String getPortHostId(final Port port) {
477         if (port != null) {
478             PortBindingExtension portBinding = port.getAugmentation(PortBindingExtension.class);
479             if (portBinding != null) {
480                 return portBinding.getHostId();
481             }
482         }
483         return null;
484     }
485
486     private Hostconfig getHostConfig(final Port port) {
487         String hostId = getPortHostId(port);
488         if (hostId == null) {
489             return null;
490         }
491         Optional<Hostconfig> hostConfig;
492         try {
493             hostConfig = this.hostConfigCache.get(hostId);
494         } catch (ReadFailedException e) {
495             LOG.error("failed to read host config from host {}", hostId, e);
496             return null;
497         }
498         return hostConfig.isPresent() ? hostConfig.get() : null;
499     }
500
501     private boolean isPortBound(final Port port) {
502         String hostId = getPortHostId(port);
503         return hostId != null && !hostId.isEmpty();
504     }
505
506     private boolean isPortVnicTypeDirect(Port port) {
507         PortBindingExtension portBinding = port.getAugmentation(PortBindingExtension.class);
508         if (portBinding == null || portBinding.getVnicType() == null) {
509             // By default, VNIC_TYPE is NORMAL
510             return false;
511         }
512         String vnicType = portBinding.getVnicType().trim().toLowerCase(Locale.getDefault());
513         return vnicType.equals(NeutronConstants.VNIC_TYPE_DIRECT);
514     }
515
516     private boolean isSupportedVnicTypeByHost(final Port port, final String vnicType) {
517         Hostconfig hostConfig = getHostConfig(port);
518         String supportStr = String.format("\"vnic_type\": \"%s\"", vnicType);
519         if (hostConfig != null && hostConfig.getConfig().contains(supportStr)) {
520             return true;
521         }
522         return false;
523     }
524
525     private Map<String, JsonElement> unmarshal(final String profile) {
526         if (null == profile) {
527             return null;
528         }
529         Gson gson = new Gson();
530         JsonObject jsonObject = gson.fromJson(profile, JsonObject.class);
531         Map<String, JsonElement> map = new HashMap();
532         for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
533             map.put(entry.getKey(), entry.getValue());
534         }
535         return map;
536     }
537
538     private boolean isPortTypeSwitchdev(final Port port) {
539         if (!isPortVnicTypeDirect(port)) {
540             return false;
541         }
542
543         PortBindingExtension portBinding = port.getAugmentation(PortBindingExtension.class);
544         String profile = portBinding.getProfile();
545         if (profile == null || profile.isEmpty()) {
546             LOG.debug("Port {} has no binding:profile values", port.getUuid());
547             return false;
548         }
549
550         Map<String, JsonElement> mapProfile = unmarshal(profile);
551         JsonElement capabilities = mapProfile.get(NeutronConstants.BINDING_PROFILE_CAPABILITIES);
552         LOG.debug("Port {} capabilities: {}", port.getUuid(), capabilities);
553         if (capabilities == null || !capabilities.isJsonArray()) {
554             LOG.debug("binding profile capabilities not in array format: {}", capabilities);
555             return false;
556         }
557
558         JsonArray capabilitiesArray = capabilities.getAsJsonArray();
559         Gson gson = new Gson();
560         JsonElement switchdevElement = gson.fromJson(NeutronConstants.SWITCHDEV, JsonElement.class);
561         return capabilitiesArray.contains(switchdevElement);
562     }
563
564
565     private void handleNeutronPortCreated(final Port port) {
566         final String portName = port.getUuid().getValue();
567         final Uuid portId = port.getUuid();
568         final List<FixedIps> portIpAddrsList = port.getFixedIps();
569         if (NeutronConstants.IS_ODL_DHCP_PORT.test(port)) {
570             return;
571         }
572         jobCoordinator.enqueueJob("PORT- " + portName, () -> {
573             // add direct port to subnetMaps config DS
574             if (!(NeutronUtils.isPortVnicTypeNormal(port)
575                 || (isPortTypeSwitchdev(port)
576                 && isSupportedVnicTypeByHost(port, NeutronConstants.VNIC_TYPE_DIRECT)))) {
577                 for (FixedIps ip: portIpAddrsList) {
578                     nvpnManager.updateSubnetmapNodeWithPorts(ip.getSubnetId(), null, portId);
579                 }
580                 LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;"
581                          + "OF Port interfaces are not created", portName);
582                 return Collections.emptyList();
583             }
584             return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
585                 LOG.info("Of-port-interface creation for port {}", portName);
586                 // Create of-port interface for this neutron port
587                 String portInterfaceName = createOfPortInterface(port, tx);
588                 LOG.debug("Creating ELAN Interface for port {}", portName);
589                 createElanInterface(port, portInterfaceName, tx);
590                 Set<Uuid> vpnIdList =  new HashSet<>();
591                 Set<Uuid> routerIds = new HashSet<>();
592                 for (FixedIps ip: portIpAddrsList) {
593                     Subnetmap subnetMap = nvpnManager.updateSubnetmapNodeWithPorts(ip.getSubnetId(), portId, null);
594                     if (subnetMap != null && subnetMap.getInternetVpnId() != null) {
595                         if (!vpnIdList.contains(subnetMap.getInternetVpnId())) {
596                             vpnIdList.add(subnetMap.getInternetVpnId());
597                         }
598                     }
599                     if (subnetMap != null && subnetMap.getVpnId() != null) {
600                         // can't use NeutronvpnUtils.getVpnForNetwork to optimise here, because it gives BGPVPN id
601                         // obtained subnetMaps belongs to one network => vpnId must be the same for each port Ip
602                         Uuid vpnId = subnetMap.getVpnId();
603                         if (vpnId != null) {
604                             vpnIdList.add(vpnId);
605                         }
606                     }
607                     if (subnetMap != null && subnetMap.getRouterId() != null) {
608                         routerIds.add(subnetMap.getRouterId());
609                     }
610                 }
611                 if (!vpnIdList.isEmpty()) {
612                     // create new vpn-interface for neutron port
613                     LOG.debug("handleNeutronPortCreated: Adding VPN Interface for port {} from network {}", portName,
614                             port.getNetworkId().toString());
615                     nvpnManager.createVpnInterface(vpnIdList, port, tx);
616                     if (!routerIds.isEmpty()) {
617                         for (Uuid routerId : routerIds) {
618                             nvpnManager.addToNeutronRouterInterfacesMap(routerId,port.getUuid().getValue());
619                         }
620                     }
621                 }
622             }));
623         });
624     }
625
626     private void handleNeutronPortDeleted(final Port port) {
627         final String portName = port.getUuid().getValue();
628         final Uuid portId = port.getUuid();
629         final List<FixedIps> portIpsList = port.getFixedIps();
630         jobCoordinator.enqueueJob("PORT- " + portName, () -> {
631             WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
632             List<ListenableFuture<Void>> futures = new ArrayList<>();
633             if (!(NeutronUtils.isPortVnicTypeNormal(port) || isPortTypeSwitchdev(port))) {
634                 for (FixedIps ip: portIpsList) {
635                     // remove direct port from subnetMaps config DS
636                     nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), null, portId);
637                 }
638                 LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;"
639                          + "Skipping OF Port interfaces removal", portName);
640                 return futures;
641             }
642             Uuid vpnId = null;
643             Set<Uuid> routerIds = new HashSet<>();
644             Uuid internetVpnId = null;
645             for (FixedIps ip: portIpsList) {
646                 Subnetmap subnetMap = nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), portId, null);
647                 if (subnetMap == null) {
648                     continue;
649                 }
650                 if (subnetMap.getVpnId() != null) {
651                     // can't use NeutronvpnUtils.getVpnForNetwork to optimise here, because it gives BGPVPN id
652                     // obtained subnetMaps belongs to one network => vpnId must be the same for each port Ip
653                     vpnId = subnetMap.getVpnId();
654                 }
655                 if (subnetMap.getRouterId() != null) {
656                     routerIds.add(subnetMap.getRouterId());
657                 }
658                 internetVpnId = subnetMap.getInternetVpnId();
659             }
660             if (vpnId != null || internetVpnId != null) {
661                 // remove vpn-interface for this neutron port
662                 LOG.debug("removing VPN Interface for port {}", portName);
663                 if (!routerIds.isEmpty()) {
664                     for (Uuid routerId : routerIds) {
665                         nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, portName);
666                     }
667                 }
668                 nvpnManager.deleteVpnInterface(portName, null /* vpn-id */, wrtConfigTxn);
669             }
670             // Remove of-port interface for this neutron port
671             // ELAN interface is also implicitly deleted as part of this operation
672             LOG.debug("Of-port-interface removal for port {}", portName);
673             deleteOfPortInterface(port, wrtConfigTxn);
674             //dissociate fixedIP from floatingIP if associated
675             nvpnManager.dissociatefixedIPFromFloatingIP(port.getUuid().getValue());
676             futures.add(wrtConfigTxn.submit());
677             return futures;
678         });
679     }
680
681
682     private void handleNeutronPortUpdated(final Port portoriginal, final Port portupdate) {
683         final List<FixedIps> portoriginalIps = portoriginal.getFixedIps();
684         final List<FixedIps> portupdateIps = portupdate.getFixedIps();
685         if (portoriginalIps == null || portoriginalIps.isEmpty()) {
686             handleNeutronPortCreated(portupdate);
687             return;
688         }
689
690         if (portupdateIps == null || portupdateIps.isEmpty()) {
691             LOG.info("Ignoring portUpdate (fixed_ip removal) for port {} as this case is handled "
692                       + "during subnet deletion event.", portupdate.getUuid().getValue());
693             return;
694         }
695         jobCoordinator.enqueueJob("PORT- " + portupdate.getUuid().getValue(),
696             () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
697                 final List<Uuid> originalSnMapsIds = portoriginalIps.stream().map(FixedIps::getSubnetId)
698                         .collect(Collectors.toList());
699                 final List<Uuid> updateSnMapsIds = portupdateIps.stream().map(FixedIps::getSubnetId)
700                         .collect(Collectors.toList());
701                 Set<Uuid> originalRouterIds = new HashSet<>();
702                 Set<Uuid> oldVpnIds = new HashSet<>();
703                 Uuid oldRouterId = null;
704                 for (Uuid snId: originalSnMapsIds) {
705                     if (!updateSnMapsIds.remove(snId)) {
706                         // snId was present in originalSnMapsIds, but not in updateSnMapsIds
707                         Subnetmap subnetMapOld = nvpnManager.removePortsFromSubnetmapNode(snId, portoriginal.getUuid(),
708                                 null);
709                         if (subnetMapOld != null && subnetMapOld.getVpnId() != null) {
710                             oldVpnIds.add(subnetMapOld.getVpnId());
711                         }
712                         if (subnetMapOld != null && subnetMapOld.getInternetVpnId() != null) {
713                             oldVpnIds.add(subnetMapOld.getInternetVpnId());
714                         }
715                         if (subnetMapOld != null && subnetMapOld.getRouterId() != null) {
716                             originalRouterIds.add(subnetMapOld.getRouterId());
717                         }
718                     }
719                 }
720                 Set<Uuid> newVpnIds = new HashSet();
721                 Set<Uuid> newRouterIds = new HashSet<>();
722                 for (Uuid snId: updateSnMapsIds) {
723                     Subnetmap subnetMapNew = nvpnManager.updateSubnetmapNodeWithPorts(snId, portupdate.getUuid(), null);
724                     if (subnetMapNew != null) {
725                         if (subnetMapNew.getVpnId() != null) {
726                             newVpnIds.add(subnetMapNew.getVpnId());
727                         }
728                         if (subnetMapNew.getInternetVpnId() != null) {
729                             newVpnIds.add(subnetMapNew.getInternetVpnId());
730                         }
731                         if (subnetMapNew.getRouterId() != null) {
732                             newRouterIds.add(subnetMapNew.getRouterId());
733                         }
734                     }
735                 }
736                 WriteTransaction wrtConfigTxn = dataBroker.newWriteOnlyTransaction();
737                 if (!oldVpnIds.isEmpty()) {
738                     LOG.info("removing VPN Interface for port {}", portoriginal.getUuid().getValue());
739                     if (!originalRouterIds.isEmpty()) {
740                         for (Uuid routerId : originalRouterIds) {
741                             nvpnManager.removeFromNeutronRouterInterfacesMap(routerId,
742                                     portoriginal.getUuid().getValue());
743                         }
744                     }
745                     nvpnManager.deleteVpnInterface(portoriginal.getUuid().getValue(),
746                                                    null /* vpn-id */, wrtConfigTxn);
747                 }
748                 if (!newVpnIds.isEmpty()) {
749                     LOG.info("Adding VPN Interface for port {}", portupdate.getUuid().getValue());
750                     nvpnManager.createVpnInterface(newVpnIds, portupdate, wrtConfigTxn);
751                     if (!newRouterIds.isEmpty()) {
752                         for (Uuid routerId : newRouterIds) {
753                             nvpnManager.addToNeutronRouterInterfacesMap(routerId,portupdate.getUuid().getValue());
754                         }
755                     }
756                 }
757             })));
758     }
759
760     private InterfaceAclBuilder handlePortSecurityUpdated(Port portOriginal,
761             Port portUpdated, boolean origSecurityEnabled, boolean updatedSecurityEnabled,
762             InterfaceBuilder interfaceBuilder) {
763         InterfaceAclBuilder interfaceAclBuilder = null;
764         if (origSecurityEnabled != updatedSecurityEnabled) {
765             interfaceAclBuilder = new InterfaceAclBuilder();
766             interfaceAclBuilder.setPortSecurityEnabled(updatedSecurityEnabled);
767             if (updatedSecurityEnabled) {
768                 // Handle security group enabled
769                 NeutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, portUpdated);
770                 neutronvpnUtils.populateSubnetInfo(portUpdated);
771             } else {
772                 // Handle security group disabled
773                 interfaceAclBuilder.setSecurityGroups(new ArrayList<>());
774                 interfaceAclBuilder.setAllowedAddressPairs(new ArrayList<>());
775             }
776         } else {
777             if (updatedSecurityEnabled) {
778                 // handle SG add/delete delta
779                 InterfaceAcl interfaceAcl = interfaceBuilder.getAugmentation(InterfaceAcl.class);
780                 interfaceAclBuilder = new InterfaceAclBuilder(interfaceAcl);
781                 interfaceAclBuilder.setSecurityGroups(
782                         NeutronvpnUtils.getUpdatedSecurityGroups(interfaceAcl.getSecurityGroups(),
783                                 portOriginal.getSecurityGroups(), portUpdated.getSecurityGroups()));
784                 List<AllowedAddressPairs> updatedAddressPairs = NeutronvpnUtils.getUpdatedAllowedAddressPairs(
785                         interfaceAcl.getAllowedAddressPairs(), portOriginal.getAllowedAddressPairs(),
786                         portUpdated.getAllowedAddressPairs());
787                 interfaceAclBuilder.setAllowedAddressPairs(NeutronvpnUtils.getAllowedAddressPairsForFixedIps(
788                         updatedAddressPairs, portOriginal.getMacAddress(), portOriginal.getFixedIps(),
789                         portUpdated.getFixedIps()));
790
791                 if (portOriginal.getFixedIps() != null
792                         && !portOriginal.getFixedIps().equals(portUpdated.getFixedIps())) {
793                     neutronvpnUtils.populateSubnetInfo(portUpdated);
794                 }
795             }
796         }
797         return interfaceAclBuilder;
798     }
799
800     private String createOfPortInterface(Port port, WriteTransaction wrtConfigTxn) {
801         Interface inf = createInterface(port);
802         String infName = inf.getName();
803
804         InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(infName);
805         try {
806             Optional<Interface> optionalInf =
807                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
808                             interfaceIdentifier);
809             if (!optionalInf.isPresent()) {
810                 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, inf);
811             } else {
812                 LOG.warn("Interface {} is already present", infName);
813             }
814         } catch (ReadFailedException e) {
815             LOG.error("failed to create interface {}", infName, e);
816         }
817         return infName;
818     }
819
820     private Interface createInterface(Port port) {
821         String interfaceName = port.getUuid().getValue();
822         IfL2vlan.L2vlanMode l2VlanMode = IfL2vlan.L2vlanMode.Trunk;
823         InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
824         IfL2vlanBuilder ifL2vlanBuilder = new IfL2vlanBuilder();
825         ifL2vlanBuilder.setL2vlanMode(l2VlanMode);
826
827         interfaceBuilder.setEnabled(true).setName(interfaceName).setType(L2vlan.class)
828                 .addAugmentation(IfL2vlan.class, ifL2vlanBuilder.build());
829
830         if (NeutronvpnUtils.getPortSecurityEnabled(port)) {
831             InterfaceAclBuilder interfaceAclBuilder = new InterfaceAclBuilder();
832             interfaceAclBuilder.setPortSecurityEnabled(true);
833             NeutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, port);
834             interfaceBuilder.addAugmentation(InterfaceAcl.class, interfaceAclBuilder.build());
835             neutronvpnUtils.populateSubnetInfo(port);
836         }
837         return interfaceBuilder.build();
838     }
839
840     private void deleteOfPortInterface(Port port, WriteTransaction wrtConfigTxn) {
841         String name = port.getUuid().getValue();
842         LOG.debug("Removing OFPort Interface {}", name);
843         InstanceIdentifier<Interface>  interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
844         try {
845             Optional<Interface> optionalInf =
846                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
847                             interfaceIdentifier);
848             if (optionalInf.isPresent()) {
849                 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier);
850             } else {
851                 LOG.warn("deleteOfPortInterface: Interface {} is not present", name);
852             }
853         } catch (ReadFailedException e) {
854             LOG.error("deleteOfPortInterface: Failed to delete interface {}", name, e);
855         }
856     }
857
858     private void createElanInterface(Port port, String name, WriteTransaction wrtConfigTxn) {
859         String elanInstanceName = port.getNetworkId().getValue();
860         List<StaticMacEntries> staticMacEntries = NeutronvpnUtils.buildStaticMacEntry(port);
861
862         InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
863                 .class, new ElanInterfaceKey(name)).build();
864         ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
865                 .setName(name).setStaticMacEntries(staticMacEntries).setKey(new ElanInterfaceKey(name)).build();
866         wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, id, elanInterface);
867         LOG.debug("Creating new ELan Interface {}", elanInterface);
868     }
869
870     private void deleteElanInterface(String name, WriteTransaction wrtConfigTxn) {
871         InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
872                 .class, new ElanInterfaceKey(name)).build();
873         wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, id);
874     }
875
876     // TODO Clean up the exception handling
877     @SuppressWarnings("checkstyle:IllegalCatch")
878     private void addToFloatingIpPortInfo(Uuid floatingIpId, Uuid floatingIpPortId, Uuid floatingIpPortSubnetId, String
879                                          floatingIpPortMacAddress) {
880         InstanceIdentifier id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
881         try {
882             FloatingIpIdToPortMappingBuilder floatingipIdToPortMacMappingBuilder = new
883                 FloatingIpIdToPortMappingBuilder().setKey(new FloatingIpIdToPortMappingKey(floatingIpId))
884                 .setFloatingIpId(floatingIpId).setFloatingIpPortId(floatingIpPortId)
885                 .setFloatingIpPortSubnetId(floatingIpPortSubnetId)
886                 .setFloatingIpPortMacAddress(floatingIpPortMacAddress);
887             LOG.debug("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
888                 + " Port Info Config DS", floatingIpId.getValue(), floatingIpPortId.getValue());
889             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
890                 floatingipIdToPortMacMappingBuilder.build());
891         } catch (Exception e) {
892             LOG.error("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
893                 + " Port Info Config DS failed", floatingIpId.getValue(), floatingIpPortId.getValue(), e);
894         }
895     }
896
897     private Set<FixedIps> getFixedIpSet(List<FixedIps> fixedIps) {
898         return fixedIps != null ? new HashSet<>(fixedIps) : Collections.emptySet();
899     }
900 }