38113ad0ab4f1431c14f364d699907bcf9f8c629
[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         jobCoordinator.enqueueJob("PORT- " + portupdate.getUuid().getValue(),
728             () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
729                 final List<Uuid> originalSnMapsIds = portoriginalIps.stream().map(FixedIps::getSubnetId)
730                         .collect(Collectors.toList());
731                 final List<Uuid> updateSnMapsIds = portupdateIps.stream().map(FixedIps::getSubnetId)
732                         .collect(Collectors.toList());
733                 Set<Uuid> originalRouterIds = new HashSet<>();
734                 Set<Uuid> oldVpnIds = new HashSet<>();
735                 for (Uuid snId: originalSnMapsIds) {
736                     if (!updateSnMapsIds.remove(snId)) {
737                         // snId was present in originalSnMapsIds, but not in updateSnMapsIds
738                         Subnetmap subnetMapOld = nvpnManager.removePortsFromSubnetmapNode(snId, portoriginal.getUuid(),
739                                 null);
740                         if (subnetMapOld != null && subnetMapOld.getVpnId() != null) {
741                             oldVpnIds.add(subnetMapOld.getVpnId());
742                         }
743                         if (subnetMapOld != null && subnetMapOld.getInternetVpnId() != null) {
744                             oldVpnIds.add(subnetMapOld.getInternetVpnId());
745                         }
746                         if (subnetMapOld != null && subnetMapOld.getRouterId() != null) {
747                             originalRouterIds.add(subnetMapOld.getRouterId());
748                         }
749                     }
750                 }
751                 Set<Uuid> newVpnIds = new HashSet<>();
752                 Set<Uuid> newRouterIds = new HashSet<>();
753                 for (Uuid snId: updateSnMapsIds) {
754                     Subnetmap subnetMapNew = nvpnManager.updateSubnetmapNodeWithPorts(snId, portupdate.getUuid(), null);
755                     if (subnetMapNew != null) {
756                         if (subnetMapNew.getVpnId() != null) {
757                             newVpnIds.add(subnetMapNew.getVpnId());
758                         }
759                         if (subnetMapNew.getInternetVpnId() != null) {
760                             newVpnIds.add(subnetMapNew.getInternetVpnId());
761                         }
762                         if (subnetMapNew.getRouterId() != null) {
763                             newRouterIds.add(subnetMapNew.getRouterId());
764                         }
765                     }
766                 }
767                 if (!oldVpnIds.isEmpty()) {
768                     LOG.info("removing VPN Interface for port {}", portoriginal.getUuid().getValue());
769                     if (!originalRouterIds.isEmpty()) {
770                         for (Uuid routerId : originalRouterIds) {
771                             nvpnManager.removeFromNeutronRouterInterfacesMap(routerId,
772                                     portoriginal.getUuid().getValue());
773                         }
774                     }
775                     nvpnManager.deleteVpnInterface(portoriginal.getUuid().getValue(),
776                                                    null /* vpn-id */, confTx);
777                 }
778                 if (!newVpnIds.isEmpty()) {
779                     LOG.info("Adding VPN Interface for port {}", portupdate.getUuid().getValue());
780                     nvpnManager.createVpnInterface(newVpnIds, portupdate, confTx);
781                     if (!newRouterIds.isEmpty()) {
782                         for (Uuid routerId : newRouterIds) {
783                             nvpnManager.addToNeutronRouterInterfacesMap(routerId,portupdate.getUuid().getValue());
784                         }
785                     }
786                 }
787             })));
788     }
789
790     private InterfaceAclBuilder handlePortSecurityUpdated(Port portOriginal,
791             Port portUpdated, boolean origSecurityEnabled, boolean updatedSecurityEnabled,
792             InterfaceBuilder interfaceBuilder) {
793         InterfaceAclBuilder interfaceAclBuilder = null;
794         if (origSecurityEnabled != updatedSecurityEnabled) {
795             interfaceAclBuilder = new InterfaceAclBuilder();
796             interfaceAclBuilder.setPortSecurityEnabled(updatedSecurityEnabled);
797             if (updatedSecurityEnabled) {
798                 // Handle security group enabled
799                 NeutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, portUpdated);
800                 neutronvpnUtils.populateSubnetInfo(portUpdated);
801             } else {
802                 // Handle security group disabled
803                 interfaceAclBuilder.setSecurityGroups(new ArrayList<>());
804                 interfaceAclBuilder.setAllowedAddressPairs(new ArrayList<>());
805             }
806         } else {
807             if (updatedSecurityEnabled) {
808                 // handle SG add/delete delta
809                 InterfaceAcl interfaceAcl = interfaceBuilder.augmentation(InterfaceAcl.class);
810                 interfaceAclBuilder = new InterfaceAclBuilder(interfaceAcl);
811                 interfaceAclBuilder.setSecurityGroups(
812                         NeutronvpnUtils.getUpdatedSecurityGroups(interfaceAcl.getSecurityGroups(),
813                                 portOriginal.getSecurityGroups(), portUpdated.getSecurityGroups()));
814                 List<AllowedAddressPairs> updatedAddressPairs = NeutronvpnUtils.getUpdatedAllowedAddressPairs(
815                         interfaceAcl.getAllowedAddressPairs(), portOriginal.getAllowedAddressPairs(),
816                         portUpdated.getAllowedAddressPairs());
817                 interfaceAclBuilder.setAllowedAddressPairs(NeutronvpnUtils.getAllowedAddressPairsForFixedIps(
818                         updatedAddressPairs, portOriginal.getMacAddress(), portOriginal.getFixedIps(),
819                         portUpdated.getFixedIps()));
820
821                 if (portOriginal.getFixedIps() != null
822                         && !portOriginal.getFixedIps().equals(portUpdated.getFixedIps())) {
823                     neutronvpnUtils.populateSubnetInfo(portUpdated);
824                 }
825             }
826         }
827         return interfaceAclBuilder;
828     }
829
830     private String createOfPortInterface(Port port, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
831         Interface inf = createInterface(port);
832         String infName = inf.getName();
833
834         InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(infName);
835         try {
836             Optional<Interface> optionalInf =
837                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
838                             interfaceIdentifier);
839             if (!optionalInf.isPresent()) {
840                 wrtConfigTxn.put(interfaceIdentifier, inf);
841             } else {
842                 LOG.warn("Interface {} is already present", infName);
843             }
844         } catch (ReadFailedException e) {
845             LOG.error("failed to create interface {}", infName, e);
846         }
847         return infName;
848     }
849
850     private Interface createInterface(Port port) {
851         String interfaceName = port.getUuid().getValue();
852         IfL2vlan.L2vlanMode l2VlanMode = IfL2vlan.L2vlanMode.Trunk;
853         InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
854         IfL2vlanBuilder ifL2vlanBuilder = new IfL2vlanBuilder();
855
856         Network network = neutronvpnUtils.getNeutronNetwork(port.getNetworkId());
857         Boolean isVlanTransparent = network.isVlanTransparent();
858         if (isVlanTransparent != null && isVlanTransparent) {
859             l2VlanMode = IfL2vlan.L2vlanMode.Transparent;
860         }
861
862         ifL2vlanBuilder.setL2vlanMode(l2VlanMode);
863
864         interfaceBuilder.setEnabled(true).setName(interfaceName).setType(L2vlan.class)
865                 .addAugmentation(IfL2vlan.class, ifL2vlanBuilder.build());
866
867         if (NeutronvpnUtils.getPortSecurityEnabled(port)) {
868             InterfaceAclBuilder interfaceAclBuilder = new InterfaceAclBuilder();
869             interfaceAclBuilder.setPortSecurityEnabled(true);
870             NeutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, port);
871             interfaceBuilder.addAugmentation(InterfaceAcl.class, interfaceAclBuilder.build());
872             neutronvpnUtils.populateSubnetInfo(port);
873         }
874         return interfaceBuilder.build();
875     }
876
877     private void deleteOfPortInterface(Port port, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
878         String name = port.getUuid().getValue();
879         LOG.debug("Removing OFPort Interface {}", name);
880         InstanceIdentifier<Interface>  interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
881         try {
882             Optional<Interface> optionalInf =
883                     SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
884                             interfaceIdentifier);
885             if (optionalInf.isPresent()) {
886                 wrtConfigTxn.delete(interfaceIdentifier);
887             } else {
888                 LOG.warn("deleteOfPortInterface: Interface {} is not present", name);
889             }
890         } catch (ReadFailedException e) {
891             LOG.error("deleteOfPortInterface: Failed to delete interface {}", name, e);
892         }
893     }
894
895     private void createElanInterface(Port port, String name,
896                                      TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
897         String elanInstanceName = port.getNetworkId().getValue();
898         List<StaticMacEntries> staticMacEntries = NeutronvpnUtils.buildStaticMacEntry(port);
899
900         InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
901                 .class, new ElanInterfaceKey(name)).build();
902         ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
903                 .setName(name).setStaticMacEntries(staticMacEntries).withKey(new ElanInterfaceKey(name)).build();
904         wrtConfigTxn.put(id, elanInterface);
905         LOG.debug("Creating new ELan Interface {}", elanInterface);
906     }
907
908     private void deleteElanInterface(String name, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
909         InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
910                 .class, new ElanInterfaceKey(name)).build();
911         wrtConfigTxn.delete(id);
912     }
913
914     // TODO Clean up the exception handling
915     @SuppressWarnings("checkstyle:IllegalCatch")
916     private void addToFloatingIpPortInfo(Uuid floatingIpId, Uuid floatingIpPortId, Uuid floatingIpPortSubnetId, String
917                                          floatingIpPortMacAddress) {
918         InstanceIdentifier id = NeutronvpnUtils.buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
919         try {
920             FloatingIpIdToPortMappingBuilder floatingipIdToPortMacMappingBuilder = new
921                 FloatingIpIdToPortMappingBuilder().withKey(new FloatingIpIdToPortMappingKey(floatingIpId))
922                 .setFloatingIpId(floatingIpId).setFloatingIpPortId(floatingIpPortId)
923                 .setFloatingIpPortSubnetId(floatingIpPortSubnetId)
924                 .setFloatingIpPortMacAddress(floatingIpPortMacAddress);
925             LOG.debug("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
926                 + " Port Info Config DS", floatingIpId.getValue(), floatingIpPortId.getValue());
927             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
928                 floatingipIdToPortMacMappingBuilder.build());
929         } catch (Exception e) {
930             LOG.error("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
931                 + " Port Info Config DS failed", floatingIpId.getValue(), floatingIpPortId.getValue(), e);
932         }
933     }
934
935     private Set<FixedIps> getFixedIpSet(List<FixedIps> fixedIps) {
936         return fixedIps != null ? new HashSet<>(fixedIps) : Collections.emptySet();
937     }
938 }