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