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