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