Drop unnecessary explicit types
[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 static 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             } else {
771                 // Handle security group disabled
772                 interfaceAclBuilder.setSecurityGroups(new ArrayList<>());
773                 interfaceAclBuilder.setAllowedAddressPairs(new ArrayList<>());
774             }
775         } else {
776             if (updatedSecurityEnabled) {
777                 // handle SG add/delete delta
778                 InterfaceAcl interfaceAcl = interfaceBuilder.getAugmentation(InterfaceAcl.class);
779                 interfaceAclBuilder = new InterfaceAclBuilder(interfaceAcl);
780                 interfaceAclBuilder.setSecurityGroups(
781                         NeutronvpnUtils.getUpdatedSecurityGroups(interfaceAcl.getSecurityGroups(),
782                                 portOriginal.getSecurityGroups(), portUpdated.getSecurityGroups()));
783                 List<AllowedAddressPairs> updatedAddressPairs = NeutronvpnUtils.getUpdatedAllowedAddressPairs(
784                         interfaceAcl.getAllowedAddressPairs(), portOriginal.getAllowedAddressPairs(),
785                         portUpdated.getAllowedAddressPairs());
786                 interfaceAclBuilder.setAllowedAddressPairs(NeutronvpnUtils.getAllowedAddressPairsForFixedIps(
787                         updatedAddressPairs, portOriginal.getMacAddress(), portOriginal.getFixedIps(),
788                         portUpdated.getFixedIps()));
789             }
790         }
791         return interfaceAclBuilder;
792     }
793
794     private String createOfPortInterface(Port port, WriteTransaction wrtConfigTxn) {
795         Interface inf = createInterface(port);
796         String infName = inf.getName();
797
798         InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(infName);
799         try {
800             Optional<Interface> optionalInf =
801                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
802                             interfaceIdentifier);
803             if (!optionalInf.isPresent()) {
804                 wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, inf);
805             } else {
806                 LOG.warn("Interface {} is already present", infName);
807             }
808         } catch (ReadFailedException e) {
809             LOG.error("failed to create interface {}", infName, e);
810         }
811         return infName;
812     }
813
814     private Interface createInterface(Port port) {
815         String interfaceName = port.getUuid().getValue();
816         IfL2vlan.L2vlanMode l2VlanMode = IfL2vlan.L2vlanMode.Trunk;
817         InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
818         IfL2vlanBuilder ifL2vlanBuilder = new IfL2vlanBuilder();
819         ifL2vlanBuilder.setL2vlanMode(l2VlanMode);
820
821         interfaceBuilder.setEnabled(true).setName(interfaceName).setType(L2vlan.class)
822                 .addAugmentation(IfL2vlan.class, ifL2vlanBuilder.build());
823
824         if (NeutronvpnUtils.getPortSecurityEnabled(port)) {
825             InterfaceAclBuilder interfaceAclBuilder = new InterfaceAclBuilder();
826             interfaceAclBuilder.setPortSecurityEnabled(true);
827             NeutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, port);
828             interfaceBuilder.addAugmentation(InterfaceAcl.class, interfaceAclBuilder.build());
829             neutronvpnUtils.populateSubnetIpPrefixes(port);
830         }
831         return interfaceBuilder.build();
832     }
833
834     private void deleteOfPortInterface(Port port, WriteTransaction wrtConfigTxn) {
835         String name = port.getUuid().getValue();
836         LOG.debug("Removing OFPort Interface {}", name);
837         InstanceIdentifier<Interface>  interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
838         try {
839             Optional<Interface> optionalInf =
840                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
841                             interfaceIdentifier);
842             if (optionalInf.isPresent()) {
843                 wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, interfaceIdentifier);
844             } else {
845                 LOG.warn("deleteOfPortInterface: Interface {} is not present", name);
846             }
847         } catch (ReadFailedException e) {
848             LOG.error("deleteOfPortInterface: Failed to delete interface {}", name, e);
849         }
850     }
851
852     private void createElanInterface(Port port, String name, WriteTransaction wrtConfigTxn) {
853         String elanInstanceName = port.getNetworkId().getValue();
854         List<StaticMacEntries> staticMacEntries = NeutronvpnUtils.buildStaticMacEntry(port);
855
856         InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
857                 .class, new ElanInterfaceKey(name)).build();
858         ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
859                 .setName(name).setStaticMacEntries(staticMacEntries).setKey(new ElanInterfaceKey(name)).build();
860         wrtConfigTxn.put(LogicalDatastoreType.CONFIGURATION, id, elanInterface);
861         LOG.debug("Creating new ELan Interface {}", elanInterface);
862     }
863
864     private void deleteElanInterface(String name, WriteTransaction wrtConfigTxn) {
865         InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
866                 .class, new ElanInterfaceKey(name)).build();
867         wrtConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, id);
868     }
869
870     // TODO Clean up the exception handling
871     @SuppressWarnings("checkstyle:IllegalCatch")
872     private void addToFloatingIpPortInfo(Uuid floatingIpId, Uuid floatingIpPortId, Uuid floatingIpPortSubnetId, String
873                                          floatingIpPortMacAddress) {
874         InstanceIdentifier id = buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
875         try {
876             FloatingIpIdToPortMappingBuilder floatingipIdToPortMacMappingBuilder = new
877                 FloatingIpIdToPortMappingBuilder().setKey(new FloatingIpIdToPortMappingKey(floatingIpId))
878                 .setFloatingIpId(floatingIpId).setFloatingIpPortId(floatingIpPortId)
879                 .setFloatingIpPortSubnetId(floatingIpPortSubnetId)
880                 .setFloatingIpPortMacAddress(floatingIpPortMacAddress);
881             LOG.debug("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
882                 + " Port Info Config DS", floatingIpId.getValue(), floatingIpPortId.getValue());
883             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
884                 floatingipIdToPortMacMappingBuilder.build());
885         } catch (Exception e) {
886             LOG.error("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
887                 + " Port Info Config DS failed", floatingIpId.getValue(), floatingIpPortId.getValue(), e);
888         }
889     }
890
891     private Set<FixedIps> getFixedIpSet(List<FixedIps> fixedIps) {
892         return fixedIps != null ? new HashSet<>(fixedIps) : Collections.emptySet();
893     }
894 }