2 * Copyright © 2015, 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
8 package org.opendaylight.netvirt.neutronvpn;
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
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;
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.eclipse.jdt.annotation.Nullable;
32 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
33 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
34 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
35 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
36 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
37 import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
38 import org.opendaylight.genius.infra.Datastore;
39 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
40 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
41 import org.opendaylight.genius.infra.TypedWriteTransaction;
42 import org.opendaylight.genius.mdsalutil.MDSALUtil;
43 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
44 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
45 import org.opendaylight.netvirt.elanmanager.api.IElanService;
46 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
47 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
48 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.L2vlan;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlanBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefsBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.SplitHorizon;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.SplitHorizonBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAclBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntries;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingKey;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.port.id.subport.data.PortIdToSubport;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.hostconfig.rev150712.hostconfig.attributes.hostconfigs.Hostconfig;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
83 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
84 import org.slf4j.Logger;
85 import org.slf4j.LoggerFactory;
88 public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase<Port, NeutronPortChangeListener> {
89 private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChangeListener.class);
90 private final DataBroker dataBroker;
91 private final ManagedNewTransactionRunner txRunner;
92 private final NeutronvpnManager nvpnManager;
93 private final NeutronvpnNatManager nvpnNatManager;
94 private final NeutronSubnetGwMacResolver gwMacResolver;
95 private final IElanService elanService;
96 private final JobCoordinator jobCoordinator;
97 private final NeutronvpnUtils neutronvpnUtils;
98 private final HostConfigCache hostConfigCache;
99 private final DataTreeEventCallbackRegistrar eventCallbacks;
100 private final NeutronvpnConfig neutronvpnConfig;
102 public NeutronPortChangeListener(final DataBroker dataBroker,
103 final NeutronvpnManager neutronvpnManager,
104 final NeutronvpnNatManager neutronvpnNatManager,
105 final NeutronSubnetGwMacResolver gwMacResolver,
106 final IElanService elanService,
107 final JobCoordinator jobCoordinator,
108 final NeutronvpnUtils neutronvpnUtils,
109 final HostConfigCache hostConfigCache,
110 final DataTreeEventCallbackRegistrar dataTreeEventCallbackRegistrar,
111 final NeutronvpnConfig neutronvpnConfig) {
112 super(Port.class, NeutronPortChangeListener.class);
113 this.dataBroker = dataBroker;
114 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
115 nvpnManager = neutronvpnManager;
116 nvpnNatManager = neutronvpnNatManager;
117 this.gwMacResolver = gwMacResolver;
118 this.elanService = elanService;
119 this.jobCoordinator = jobCoordinator;
120 this.neutronvpnUtils = neutronvpnUtils;
121 this.hostConfigCache = hostConfigCache;
122 this.eventCallbacks = dataTreeEventCallbackRegistrar;
123 this.neutronvpnConfig = neutronvpnConfig;
130 LOG.info("{} init", getClass().getSimpleName());
131 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
135 protected InstanceIdentifier<Port> getWildCardPath() {
136 return InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class);
140 protected NeutronPortChangeListener getDataTreeChangeListener() {
141 return NeutronPortChangeListener.this;
146 protected void add(InstanceIdentifier<Port> identifier, Port input) {
147 LOG.trace("Received port add event: port={}", input);
148 String portName = input.getUuid().getValue();
149 LOG.trace("Adding Port : key: {}, value={}", identifier, input);
150 Network network = neutronvpnUtils.getNeutronNetwork(input.getNetworkId());
151 if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
152 LOG.warn("neutron vpn received a port add() for a network without a provider extension augmentation "
153 + "or with an unsupported network type for the port {} which is part of network {}",
158 neutronvpnUtils.addToPortCache(input);
159 String portStatus = NeutronUtils.PORT_STATUS_DOWN;
160 if (!Strings.isNullOrEmpty(input.getDeviceOwner()) && !Strings.isNullOrEmpty(input.getDeviceId())) {
161 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(input.getDeviceOwner())) {
162 handleRouterInterfaceAdded(input);
163 NeutronUtils.createPortStatus(input.getUuid().getValue(), NeutronUtils.PORT_STATUS_ACTIVE, dataBroker);
166 if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(input.getDeviceOwner())) {
167 handleRouterGatewayUpdated(input, false);
168 portStatus = NeutronUtils.PORT_STATUS_ACTIVE;
169 } else if (NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(input.getDeviceOwner())) {
170 handleFloatingIpPortUpdated(null, input);
171 portStatus = NeutronUtils.PORT_STATUS_ACTIVE;
174 // Switchdev ports need to be bounded to a host before creation
175 // in order to validate the supported vnic types from the hostconfig
176 if (input.getFixedIps() != null
177 && !input.getFixedIps().isEmpty()
178 && !(isPortTypeSwitchdev(input) && !isPortBound(input))) {
179 handleNeutronPortCreated(input);
181 NeutronUtils.createPortStatus(input.getUuid().getValue(), portStatus, dataBroker);
185 protected void remove(InstanceIdentifier<Port> identifier, Port input) {
186 LOG.trace("Removing Port : key: {}, value={}", identifier, input);
187 Network network = neutronvpnUtils.getNeutronNetwork(input.getNetworkId());
188 // need to proceed with deletion in case network is null for a case where v2 sync happens and a read for
189 // network from NN returns null, but the deletion process for port needs to continue
190 if (network != null && !NeutronvpnUtils.isNetworkTypeSupported(network)) {
191 String portName = input.getUuid().getValue();
192 LOG.warn("neutron vpn received a port remove() for a network without a provider extension augmentation "
193 + "or with an unsupported network type for the port {} which is part of network {}",
197 neutronvpnUtils.removeFromPortCache(input);
198 NeutronUtils.deletePortStatus(input.getUuid().getValue(), dataBroker);
200 if (!Strings.isNullOrEmpty(input.getDeviceOwner()) && !Strings.isNullOrEmpty(input.getDeviceId())) {
201 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(input.getDeviceOwner())) {
202 handleRouterInterfaceRemoved(input);
203 /* nothing else to do here */
205 } else if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(input.getDeviceOwner())
206 || NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(input.getDeviceOwner())) {
207 handleRouterGatewayUpdated(input, true);
208 elanService.removeKnownL3DmacAddress(input.getMacAddress().getValue(), input.getNetworkId().getValue());
211 if (input.getFixedIps() != null) {
212 handleNeutronPortDeleted(input);
217 protected void update(InstanceIdentifier<Port> identifier, Port original, Port update) {
218 LOG.trace("Received port update event: original={}, update={}", original, update);
219 // Switchdev ports need to be bounded to a host before creation
220 // in order to validate the supported vnic types from the hostconfig
221 if (isPortTypeSwitchdev(original)
222 && !isPortBound(original)
223 && isPortBound(update)) {
224 handleNeutronPortCreated(update);
226 final String portName = update.getUuid().getValue();
227 Network network = neutronvpnUtils.getNeutronNetwork(update.getNetworkId());
228 LOG.info("Update port {} from network {}", portName, update.getNetworkId().toString());
229 if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
230 LOG.warn("neutron vpn received a port update() for a network without a provider extension augmentation "
231 + "or with an unsupported network type for the port {} which is part of network {}",
235 neutronvpnUtils.addToPortCache(update);
237 if ((Strings.isNullOrEmpty(original.getDeviceOwner()) || Strings.isNullOrEmpty(original.getDeviceId())
238 || NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING.equalsIgnoreCase(original.getDeviceId()))
239 && !Strings.isNullOrEmpty(update.getDeviceOwner()) && !Strings.isNullOrEmpty(update.getDeviceId())) {
240 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(update.getDeviceOwner())) {
241 handleRouterInterfaceAdded(update);
244 if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(update.getDeviceOwner())) {
245 handleRouterGatewayUpdated(update, false);
246 } else if (NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(update.getDeviceOwner())) {
247 handleFloatingIpPortUpdated(original, update);
250 Set<FixedIps> oldIPs = getFixedIpSet(original.getFixedIps());
251 Set<FixedIps> newIPs = getFixedIpSet(update.getFixedIps());
252 if (!oldIPs.equals(newIPs)) {
253 handleNeutronPortUpdated(original, update);
257 // check if port security enabled/disabled as part of port update
258 boolean origSecurityEnabled = NeutronvpnUtils.getPortSecurityEnabled(original);
259 boolean updatedSecurityEnabled = NeutronvpnUtils.getPortSecurityEnabled(update);
260 boolean isDhcpServerPort = neutronvpnConfig.isLimitBumtrafficToDhcpserver()
261 && NeutronvpnUtils.isDhcpServerPort(update);
262 if (origSecurityEnabled || updatedSecurityEnabled || isDhcpServerPort) {
263 InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(portName);
264 jobCoordinator.enqueueJob("PORT- " + portName,
265 () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
267 Optional<Interface> optionalInf =
268 confTx.read(interfaceIdentifier).get();
269 if (optionalInf.isPresent()) {
270 InterfaceBuilder interfaceBuilder = new InterfaceBuilder(optionalInf.get());
271 if (origSecurityEnabled || updatedSecurityEnabled) {
272 InterfaceAcl infAcl = handlePortSecurityUpdated(original, update, origSecurityEnabled,
273 updatedSecurityEnabled, interfaceBuilder).build();
274 interfaceBuilder.addAugmentation(InterfaceAcl.class, infAcl);
275 } else if (isDhcpServerPort) {
276 Set<FixedIps> oldIPs = getFixedIpSet(original.getFixedIps());
277 Set<FixedIps> newIPs = getFixedIpSet(update.getFixedIps());
278 if (!oldIPs.equals(newIPs)) {
279 InterfaceAcl infAcl = neutronvpnUtils.getDhcpInterfaceAcl(update);
280 interfaceBuilder.addAugmentation(InterfaceAcl.class, infAcl);
283 LOG.info("update: Of-port-interface updation for port {}", portName);
284 // Update OFPort interface for this neutron port
285 confTx.put(interfaceIdentifier, interfaceBuilder.build());
287 LOG.warn("update: Interface {} is not present", portName);
293 private void handleFloatingIpPortUpdated(@Nullable Port original, Port update) {
294 if ((original == null || NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING.equals(original.getDeviceId()))
295 && !NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING.equals(update.getDeviceId())) {
296 // populate floating-ip uuid and floating-ip port attributes (uuid, mac and subnet id for the ONLY
297 // fixed IP) to be used by NAT, depopulated in NATService once mac is retrieved in the removal path
298 addToFloatingIpPortInfo(new Uuid(update.getDeviceId()), update.getUuid(), update.getFixedIps().get(0)
299 .getSubnetId(), update.getMacAddress().getValue());
300 elanService.addKnownL3DmacAddress(update.getMacAddress().getValue(), update.getNetworkId().getValue());
304 private void handleRouterInterfaceAdded(Port routerPort) {
305 if (routerPort.getDeviceId() != null) {
306 Uuid routerId = new Uuid(routerPort.getDeviceId());
307 Uuid infNetworkId = routerPort.getNetworkId();
308 Uuid existingVpnId = neutronvpnUtils.getVpnForNetwork(infNetworkId);
310 elanService.addKnownL3DmacAddress(routerPort.getMacAddress().getValue(), infNetworkId.getValue());
311 if (existingVpnId == null) {
312 Set<Uuid> listVpnIds = new HashSet<>();
313 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
317 listVpnIds.add(vpnId);
318 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
319 List<Subnetmap> subnetMapList = new ArrayList<>();
320 boolean portIsIpv6 = false;
321 for (FixedIps portIP : routerPort.nonnullFixedIps()) {
322 // NOTE: Please donot change the order of calls to updateSubnetNodeWithFixedIP
323 // and addSubnetToVpn here
324 if (internetVpnId != null
325 && portIP.getIpAddress().getIpv6Address() != null) {
328 String ipValue = portIP.getIpAddress().stringValue();
329 Uuid subnetId = portIP.getSubnetId();
330 nvpnManager.updateSubnetNodeWithFixedIp(subnetId, routerId,
331 routerPort.getUuid(), ipValue, routerPort.getMacAddress().getValue(), vpnId);
332 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
333 subnetMapList.add(sn);
336 listVpnIds.add(internetVpnId);
337 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(
338 IpVersionChoice.IPV6, routerId, true)) {
339 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6,
341 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
344 if (! subnetMapList.isEmpty()) {
345 nvpnManager.createVpnInterface(listVpnIds, routerPort, null);
347 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
348 for (FixedIps portIP : routerPort.nonnullFixedIps()) {
349 String ipValue = portIP.getIpAddress().stringValue();
350 ipVersion = NeutronvpnUtils.getIpVersionFromString(ipValue);
351 if (ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
352 nvpnManager.addSubnetToVpn(vpnId, portIP.getSubnetId(),
353 null /* internet-vpn-id */);
355 nvpnManager.addSubnetToVpn(vpnId, portIP.getSubnetId(), internetVpnId);
357 LOG.trace("NeutronPortChangeListener Add Subnet Gateway IP {} MAC {} Interface {} VPN {}",
358 ipValue, routerPort.getMacAddress(),
359 routerPort.getUuid().getValue(), vpnId.getValue());
361 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(ipVersion, routerId, true)) {
362 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}",
363 ipVersion, vpnId.getValue());
364 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
366 nvpnManager.addToNeutronRouterInterfacesMap(routerId, routerPort.getUuid().getValue());
367 jobCoordinator.enqueueJob(routerId.toString(), () -> {
368 nvpnNatManager.handleSubnetsForExternalRouter(routerId);
369 return Collections.emptyList();
371 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
373 String portInterfaceName = createOfPortInterface(routerPort, confTx);
374 createElanInterface(routerPort, portInterfaceName, confTx);
375 }), LOG, "Error creating ELAN interface for {}", routerPort);
377 LOG.error("Neutron network {} corresponding to router interface port {} for neutron router {}"
378 + " already associated to VPN {}", infNetworkId.getValue(), routerPort.getUuid().getValue(),
379 routerId.getValue(), existingVpnId.getValue());
384 private void handleRouterInterfaceRemoved(Port routerPort) {
385 if (routerPort.getDeviceId() != null) {
386 Uuid routerId = new Uuid(routerPort.getDeviceId());
387 Uuid infNetworkId = routerPort.getNetworkId();
388 elanService.removeKnownL3DmacAddress(routerPort.getMacAddress().getValue(), infNetworkId.getValue());
389 Uuid vpnId = ObjectUtils.defaultIfNull(neutronvpnUtils.getVpnForRouter(routerId, true),
391 List<FixedIps> portIps = routerPort.nonnullFixedIps();
392 boolean vpnInstanceInternetIpVersionRemoved = false;
393 Uuid vpnInstanceInternetUuid = null;
394 for (FixedIps portIP : portIps) {
395 // Internet VPN : flush InternetVPN first
396 Uuid subnetId = portIP.getSubnetId();
397 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
398 if (sn != null && sn.getInternetVpnId() != null) {
399 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sn, sn.getInternetVpnId())) {
400 vpnInstanceInternetIpVersionRemoved = true;
401 vpnInstanceInternetUuid = sn.getInternetVpnId();
403 nvpnManager.updateVpnInternetForSubnet(sn, sn.getInternetVpnId(), false);
406 /* Remove ping responder for router interfaces
407 * A router interface reference in a VPN will have to be removed before the host interface references
408 * for that subnet in the VPN are removed. This is to ensure that the FIB Entry of the router interface
409 * is not the last entry to be removed for that subnet in the VPN.
410 * If router interface FIB entry is the last to be removed for a subnet in a VPN , then all the host
411 * interface references in the vpn will already have been cleared, which will cause failures in
412 * cleanup of router interface flows*/
413 nvpnManager.deleteVpnInterface(routerPort.getUuid().getValue(),
414 null /* vpn-id */, null /* wrtConfigTxn*/);
415 final Uuid internetVpnId = vpnInstanceInternetUuid;
416 // update RouterInterfaces map
417 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
419 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
420 for (FixedIps portIP : portIps) {
421 Subnetmap sn = neutronvpnUtils.getSubnetmap(portIP.getSubnetId());
422 // router Port have either IPv4 or IPv6, never both
423 ipVersion = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
424 String ipValue = portIP.getIpAddress().stringValue();
425 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(), ipValue, confTx);
426 // NOTE: Please donot change the order of calls to removeSubnetFromVpn and
427 // and updateSubnetNodeWithFixedIP
428 nvpnManager.removeSubnetFromVpn(vpnId, portIP.getSubnetId(), internetVpnId);
429 nvpnManager.updateSubnetNodeWithFixedIp(portIP.getSubnetId(), null, null,
432 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, routerPort.getUuid().getValue());
433 deleteElanInterface(routerPort.getUuid().getValue(), confTx);
434 deleteOfPortInterface(routerPort, confTx);
435 jobCoordinator.enqueueJob(routerId.toString(), () -> {
436 nvpnNatManager.handleSubnetsForExternalRouter(routerId);
437 return Collections.emptyList();
439 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(ipVersion, routerId, false)) {
440 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}",
441 ipVersion, vpnId.getValue());
442 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
444 }), LOG, "Error handling interface removal");
445 if (vpnInstanceInternetIpVersionRemoved) {
446 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnInstanceInternetUuid.getValue(),
447 IpVersionChoice.IPV6, false);
448 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, vpnInstanceInternetUuid, false);
453 private void handleRouterGatewayUpdated(Port routerGwPort, boolean isRtrGwRemoved) {
454 Uuid routerId = new Uuid(routerGwPort.getDeviceId());
455 Uuid networkId = routerGwPort.getNetworkId();
456 Network network = neutronvpnUtils.getNeutronNetwork(networkId);
457 if (network == null) {
460 boolean isExternal = NeutronvpnUtils.getIsExternal(network);
462 Uuid vpnInternetId = neutronvpnUtils.getVpnForNetwork(networkId);
463 if (vpnInternetId != null) {
464 if (!isRtrGwRemoved) {
465 nvpnManager.updateVpnMaps(vpnInternetId, null, routerId, null, null);
467 List<Subnetmap> snList = neutronvpnUtils.getNeutronRouterSubnetMaps(routerId);
468 for (Subnetmap sn : snList) {
469 if (sn.getNetworkId() == networkId) {
472 if (NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()) != IpVersionChoice.IPV6) {
475 if (isRtrGwRemoved) {
476 nvpnManager.removeV6PrivateSubnetToExtNetwork(routerId, vpnInternetId, sn);
478 nvpnManager.addV6PrivateSubnetToExtNetwork(routerId, vpnInternetId, sn);
481 //Update Internet BGP-VPN
482 if (isRtrGwRemoved) {
483 nvpnManager.updateVpnMaps(vpnInternetId, null, null, null, null);
487 elanService.addKnownL3DmacAddress(routerGwPort.getMacAddress().getValue(), networkId.getValue());
489 Router router = neutronvpnUtils.getNeutronRouter(routerId);
490 if (router == null) {
491 LOG.warn("No router found for router GW port {} for router {}", routerGwPort.getUuid().getValue(),
492 routerId.getValue());
494 eventCallbacks.onAddOrUpdate(LogicalDatastoreType.CONFIGURATION,
495 neutronvpnUtils.getNeutronRouterIid(routerId), (unused, newRouter) -> {
496 setupGwMac(newRouter, routerGwPort, routerId);
497 return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
498 }, Duration.ofSeconds(3), iid -> {
499 LOG.error("GwPort {} added without Router", routerGwPort.getUuid().getValue());
503 setupGwMac(router, routerGwPort, routerId);
506 private void setupGwMac(Router router, Port routerGwPort, Uuid routerId) {
507 gwMacResolver.sendArpRequestsToExtGateways(router);
508 jobCoordinator.enqueueJob(routerId.toString(), () -> {
509 setExternalGwMac(routerGwPort, routerId);
510 return Collections.emptyList();
514 private void setExternalGwMac(Port routerGwPort, Uuid routerId) {
515 // During full-sync networking-odl syncs routers before ports. As such,
516 // the MAC of the router's gw port is not available to be set when the
517 // router is written. We catch that here.
518 InstanceIdentifier<Routers> routersId = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
519 Optional<Routers> optionalRouter = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId);
520 if (!optionalRouter.isPresent()) {
524 Routers extRouters = optionalRouter.get();
525 if (extRouters.getExtGwMacAddress() != null) {
529 RoutersBuilder builder = new RoutersBuilder(extRouters);
530 builder.setExtGwMacAddress(routerGwPort.getMacAddress().getValue());
531 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId, builder.build());
535 private String getPortHostId(final Port port) {
537 PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class);
538 if (portBinding != null) {
539 return portBinding.getHostId();
546 private Hostconfig getHostConfig(final Port port) {
547 String hostId = getPortHostId(port);
548 if (hostId == null) {
551 Optional<Hostconfig> hostConfig;
553 hostConfig = this.hostConfigCache.get(hostId);
554 } catch (ReadFailedException e) {
555 LOG.error("failed to read host config from host {}", hostId, e);
558 return hostConfig.orNull();
561 private boolean isPortBound(final Port port) {
562 String hostId = getPortHostId(port);
563 return hostId != null && !hostId.isEmpty();
566 private boolean isPortVnicTypeDirect(Port port) {
567 PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class);
568 if (portBinding == null || portBinding.getVnicType() == null) {
569 // By default, VNIC_TYPE is NORMAL
572 String vnicType = portBinding.getVnicType().trim().toLowerCase(Locale.getDefault());
573 return vnicType.equals(NeutronConstants.VNIC_TYPE_DIRECT);
576 private boolean isSupportedVnicTypeByHost(final Port port, final String vnicType) {
577 Hostconfig hostConfig = getHostConfig(port);
578 String supportStr = String.format("\"vnic_type\": \"%s\"", vnicType);
579 if (hostConfig != null && hostConfig.getConfig().contains(supportStr)) {
586 private Map<String, JsonElement> unmarshal(final String profile) {
587 if (null == profile) {
590 Gson gson = new Gson();
591 JsonObject jsonObject = gson.fromJson(profile, JsonObject.class);
592 Map<String, JsonElement> map = new HashMap<>();
593 for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
594 map.put(entry.getKey(), entry.getValue());
599 private boolean isPortTypeSwitchdev(final Port port) {
600 if (!isPortVnicTypeDirect(port)) {
604 PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class);
605 String profile = portBinding.getProfile();
606 if (profile == null || profile.isEmpty()) {
607 LOG.debug("Port {} has no binding:profile values", port.getUuid());
611 Map<String, JsonElement> mapProfile = unmarshal(profile);
612 JsonElement capabilities = mapProfile.get(NeutronConstants.BINDING_PROFILE_CAPABILITIES);
613 LOG.debug("Port {} capabilities: {}", port.getUuid(), capabilities);
614 if (capabilities == null || !capabilities.isJsonArray()) {
615 LOG.debug("binding profile capabilities not in array format: {}", capabilities);
619 JsonArray capabilitiesArray = capabilities.getAsJsonArray();
620 Gson gson = new Gson();
621 JsonElement switchdevElement = gson.fromJson(NeutronConstants.SWITCHDEV, JsonElement.class);
622 return capabilitiesArray.contains(switchdevElement);
626 private void handleNeutronPortCreated(final Port port) {
627 final String portName = port.getUuid().getValue();
628 final Uuid portId = port.getUuid();
629 final List<FixedIps> portIpAddrsList = port.nonnullFixedIps();
630 if (NeutronConstants.IS_ODL_DHCP_PORT.test(port)) {
633 jobCoordinator.enqueueJob("PORT- " + portName, () -> {
634 // add direct port to subnetMaps config DS
635 if (!(NeutronUtils.isPortVnicTypeNormal(port)
636 || isPortTypeSwitchdev(port)
637 && isSupportedVnicTypeByHost(port, NeutronConstants.VNIC_TYPE_DIRECT))) {
638 for (FixedIps ip: portIpAddrsList) {
639 nvpnManager.updateSubnetmapNodeWithPorts(ip.getSubnetId(), null, portId);
641 LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;"
642 + "OF Port interfaces are not created", portName);
643 return Collections.emptyList();
645 return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
646 LOG.info("Of-port-interface creation for port {}", portName);
647 // Create of-port interface for this neutron port
648 String portInterfaceName = createOfPortInterface(port, tx);
649 LOG.debug("Creating ELAN Interface for port {}", portName);
650 createElanInterface(port, portInterfaceName, tx);
651 Set<Uuid> vpnIdList = new HashSet<>();
652 Set<Uuid> routerIds = new HashSet<>();
653 for (FixedIps ip: portIpAddrsList) {
654 Subnetmap subnetMap = nvpnManager.updateSubnetmapNodeWithPorts(ip.getSubnetId(), portId, null);
655 if (subnetMap != null && subnetMap.getInternetVpnId() != null) {
656 if (!vpnIdList.contains(subnetMap.getInternetVpnId())) {
657 vpnIdList.add(subnetMap.getInternetVpnId());
660 if (subnetMap != null && subnetMap.getVpnId() != null) {
661 // can't use NeutronvpnUtils.getVpnForNetwork to optimise here, because it gives BGPVPN id
662 // obtained subnetMaps belongs to one network => vpnId must be the same for each port Ip
663 Uuid vpnId = subnetMap.getVpnId();
665 vpnIdList.add(vpnId);
668 if (subnetMap != null && subnetMap.getRouterId() != null) {
669 routerIds.add(subnetMap.getRouterId());
672 if (!vpnIdList.isEmpty()) {
673 // create new vpn-interface for neutron port
674 LOG.debug("handleNeutronPortCreated: Adding VPN Interface for port {} from network {}", portName,
675 port.getNetworkId().toString());
676 nvpnManager.createVpnInterface(vpnIdList, port, tx);
677 if (!routerIds.isEmpty()) {
678 for (Uuid routerId : routerIds) {
679 nvpnManager.addToNeutronRouterInterfacesMap(routerId,port.getUuid().getValue());
687 private void handleNeutronPortDeleted(final Port port) {
688 final String portName = port.getUuid().getValue();
689 final Uuid portId = port.getUuid();
690 final List<FixedIps> portIpsList = port.nonnullFixedIps();
691 jobCoordinator.enqueueJob("PORT- " + portName,
692 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
693 if (!(NeutronUtils.isPortVnicTypeNormal(port) || isPortTypeSwitchdev(port))) {
694 for (FixedIps ip : portIpsList) {
695 // remove direct port from subnetMaps config DS
696 nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), null, portId);
698 LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;"
699 + "Skipping OF Port interfaces removal", portName);
703 Set<Uuid> routerIds = new HashSet<>();
704 Uuid internetVpnId = null;
705 for (FixedIps ip : portIpsList) {
706 Subnetmap subnetMap = nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), portId, null);
707 if (subnetMap == null) {
710 if (subnetMap.getVpnId() != null) {
711 // can't use NeutronvpnUtils.getVpnForNetwork to optimise here, because it gives BGPVPN id
712 // obtained subnetMaps belongs to one network => vpnId must be the same for each port Ip
713 vpnId = subnetMap.getVpnId();
715 if (subnetMap.getRouterId() != null) {
716 routerIds.add(subnetMap.getRouterId());
718 internetVpnId = subnetMap.getInternetVpnId();
720 if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(port.getDeviceOwner())
721 || NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(port.getDeviceOwner())) {
722 String ipAddress = ip.getIpAddress().stringValue();
724 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(), ipAddress, confTx);
726 if (internetVpnId != null) {
727 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
732 if (vpnId != null || internetVpnId != null) {
733 // remove vpn-interface for this neutron port
734 LOG.debug("removing VPN Interface for port {}", portName);
735 if (!routerIds.isEmpty()) {
736 for (Uuid routerId : routerIds) {
737 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, portName);
740 nvpnManager.deleteVpnInterface(portName, null /* vpn-id */, confTx);
742 // Remove of-port interface for this neutron port
743 // ELAN interface is also implicitly deleted as part of this operation
744 LOG.debug("Of-port-interface removal for port {}", portName);
745 deleteOfPortInterface(port, confTx);
746 //dissociate fixedIP from floatingIP if associated
747 nvpnManager.dissociatefixedIPFromFloatingIP(port.getUuid().getValue());
752 private void handleNeutronPortUpdated(final Port portoriginal, final Port portupdate) {
753 final List<FixedIps> portoriginalIps = portoriginal.getFixedIps();
754 final List<FixedIps> portupdateIps = portupdate.getFixedIps();
755 if (portoriginalIps == null || portoriginalIps.isEmpty()) {
756 handleNeutronPortCreated(portupdate);
760 if (portupdateIps == null || portupdateIps.isEmpty()) {
761 LOG.info("Ignoring portUpdate (fixed_ip removal) for port {} as this case is handled "
762 + "during subnet deletion event.", portupdate.getUuid().getValue());
766 if (NeutronConstants.IS_ODL_DHCP_PORT.test(portupdate)) {
770 jobCoordinator.enqueueJob("PORT- " + portupdate.getUuid().getValue(),
771 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
772 final List<Uuid> originalSnMapsIds = portoriginalIps.stream().map(FixedIps::getSubnetId)
773 .collect(Collectors.toList());
774 final List<Uuid> updateSnMapsIds = portupdateIps.stream().map(FixedIps::getSubnetId)
775 .collect(Collectors.toList());
776 Set<Uuid> originalRouterIds = new HashSet<>();
777 Set<Uuid> oldVpnIds = new HashSet<>();
778 for (Uuid snId: originalSnMapsIds) {
779 if (!updateSnMapsIds.remove(snId)) {
780 // snId was present in originalSnMapsIds, but not in updateSnMapsIds
781 Subnetmap subnetMapOld = nvpnManager.removePortsFromSubnetmapNode(snId, portoriginal.getUuid(),
783 if (subnetMapOld != null && subnetMapOld.getVpnId() != null) {
784 oldVpnIds.add(subnetMapOld.getVpnId());
786 if (subnetMapOld != null && subnetMapOld.getInternetVpnId() != null) {
787 oldVpnIds.add(subnetMapOld.getInternetVpnId());
789 if (subnetMapOld != null && subnetMapOld.getRouterId() != null) {
790 originalRouterIds.add(subnetMapOld.getRouterId());
794 Set<Uuid> newVpnIds = new HashSet<>();
795 Set<Uuid> newRouterIds = new HashSet<>();
796 for (Uuid snId: updateSnMapsIds) {
797 Subnetmap subnetMapNew = nvpnManager.updateSubnetmapNodeWithPorts(snId, portupdate.getUuid(), null);
798 if (subnetMapNew != null) {
799 if (subnetMapNew.getVpnId() != null) {
800 newVpnIds.add(subnetMapNew.getVpnId());
802 if (subnetMapNew.getInternetVpnId() != null) {
803 newVpnIds.add(subnetMapNew.getInternetVpnId());
805 if (subnetMapNew.getRouterId() != null) {
806 newRouterIds.add(subnetMapNew.getRouterId());
810 if (!oldVpnIds.isEmpty()) {
811 LOG.info("removing VPN Interface for port {}", portoriginal.getUuid().getValue());
812 if (!originalRouterIds.isEmpty()) {
813 for (Uuid routerId : originalRouterIds) {
814 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId,
815 portoriginal.getUuid().getValue());
818 nvpnManager.deleteVpnInterface(portoriginal.getUuid().getValue(),
819 null /* vpn-id */, confTx);
821 if (!newVpnIds.isEmpty()) {
822 LOG.info("Adding VPN Interface for port {}", portupdate.getUuid().getValue());
823 nvpnManager.createVpnInterface(newVpnIds, portupdate, confTx);
824 if (!newRouterIds.isEmpty()) {
825 for (Uuid routerId : newRouterIds) {
826 nvpnManager.addToNeutronRouterInterfacesMap(routerId,portupdate.getUuid().getValue());
834 private InterfaceAclBuilder handlePortSecurityUpdated(Port portOriginal,
835 Port portUpdated, boolean origSecurityEnabled, boolean updatedSecurityEnabled,
836 InterfaceBuilder interfaceBuilder) {
837 InterfaceAclBuilder interfaceAclBuilder = null;
838 if (origSecurityEnabled != updatedSecurityEnabled) {
839 interfaceAclBuilder = new InterfaceAclBuilder();
840 interfaceAclBuilder.setPortSecurityEnabled(updatedSecurityEnabled);
841 if (updatedSecurityEnabled) {
842 // Handle security group enabled
843 neutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, portUpdated);
845 // Handle security group disabled
846 interfaceAclBuilder.setSecurityGroups(new ArrayList<>());
847 interfaceAclBuilder.setAllowedAddressPairs(new ArrayList<>());
848 interfaceAclBuilder.setSubnetInfo(new ArrayList<>());
851 if (updatedSecurityEnabled) {
852 // handle SG add/delete delta
853 InterfaceAcl interfaceAcl = interfaceBuilder.augmentation(InterfaceAcl.class);
854 interfaceAclBuilder = new InterfaceAclBuilder(interfaceAcl);
855 interfaceAclBuilder.setSecurityGroups(
856 NeutronvpnUtils.getUpdatedSecurityGroups(interfaceAcl.getSecurityGroups(),
857 portOriginal.getSecurityGroups(), portUpdated.getSecurityGroups()));
858 List<AllowedAddressPairs> updatedAddressPairs = NeutronvpnUtils.getUpdatedAllowedAddressPairs(
859 interfaceAcl.getAllowedAddressPairs(), portOriginal.getAllowedAddressPairs(),
860 portUpdated.getAllowedAddressPairs());
861 interfaceAclBuilder.setAllowedAddressPairs(NeutronvpnUtils.getAllowedAddressPairsForFixedIps(
862 updatedAddressPairs, portOriginal.getMacAddress(), portOriginal.getFixedIps(),
863 portUpdated.getFixedIps()));
865 if (portOriginal.getFixedIps() != null
866 && !portOriginal.getFixedIps().equals(portUpdated.getFixedIps())) {
867 neutronvpnUtils.populateSubnetInfo(interfaceAclBuilder, portUpdated);
871 return interfaceAclBuilder;
874 private String createOfPortInterface(Port port, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
875 Interface inf = createInterface(port);
876 String infName = inf.getName();
878 InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(infName);
880 Optional<Interface> optionalInf =
881 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
882 interfaceIdentifier);
883 if (!optionalInf.isPresent()) {
884 wrtConfigTxn.put(interfaceIdentifier, inf);
886 LOG.warn("Interface {} is already present", infName);
888 } catch (ReadFailedException e) {
889 LOG.error("failed to create interface {}", infName, e);
894 private Interface createInterface(Port port) {
895 String interfaceName = port.getUuid().getValue();
896 IfL2vlan.L2vlanMode l2VlanMode = IfL2vlan.L2vlanMode.Trunk;
897 InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
898 IfL2vlanBuilder ifL2vlanBuilder = new IfL2vlanBuilder();
900 Network network = neutronvpnUtils.getNeutronNetwork(port.getNetworkId());
901 Boolean isVlanTransparent = network.isVlanTransparent();
902 if (isVlanTransparent != null && isVlanTransparent) {
903 l2VlanMode = IfL2vlan.L2vlanMode.Transparent;
905 PortIdToSubport portIdToSubport = neutronvpnUtils.getPortIdToSubport(port.getUuid());
906 if (portIdToSubport != null) {
907 l2VlanMode = IfL2vlan.L2vlanMode.TrunkMember;
908 ifL2vlanBuilder.setVlanId(new VlanId(portIdToSubport.getVlanId().intValue()));
909 String parentRefName = portIdToSubport.getTrunkPortId().getValue();
910 ParentRefsBuilder parentRefsBuilder = new ParentRefsBuilder().setParentInterface(parentRefName);
911 interfaceBuilder.addAugmentation(ParentRefs.class, parentRefsBuilder.build());
912 SplitHorizon splitHorizon =
913 new SplitHorizonBuilder().setOverrideSplitHorizonProtection(true).build();
914 interfaceBuilder.addAugmentation(SplitHorizon.class, splitHorizon);
918 ifL2vlanBuilder.setL2vlanMode(l2VlanMode);
920 interfaceBuilder.setEnabled(true).setName(interfaceName).setType(L2vlan.class)
921 .addAugmentation(IfL2vlan.class, ifL2vlanBuilder.build());
923 if (NeutronvpnUtils.getPortSecurityEnabled(port)) {
924 InterfaceAclBuilder interfaceAclBuilder = new InterfaceAclBuilder();
925 interfaceAclBuilder.setPortSecurityEnabled(true);
926 neutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, port);
927 interfaceBuilder.addAugmentation(InterfaceAcl.class, interfaceAclBuilder.build());
928 } else if (neutronvpnConfig.isLimitBumtrafficToDhcpserver() && NeutronvpnUtils.isDhcpServerPort(port)) {
929 interfaceBuilder.addAugmentation(InterfaceAcl.class, neutronvpnUtils.getDhcpInterfaceAcl(port));
931 return interfaceBuilder.build();
934 private void deleteOfPortInterface(Port port, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
935 String name = port.getUuid().getValue();
936 LOG.debug("Removing OFPort Interface {}", name);
937 InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
939 Optional<Interface> optionalInf =
940 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
941 interfaceIdentifier);
942 if (optionalInf.isPresent()) {
943 wrtConfigTxn.delete(interfaceIdentifier);
945 LOG.warn("deleteOfPortInterface: Interface {} is not present", name);
947 } catch (ReadFailedException e) {
948 LOG.error("deleteOfPortInterface: Failed to delete interface {}", name, e);
952 private void createElanInterface(Port port, String name,
953 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
954 String elanInstanceName = port.getNetworkId().getValue();
955 List<StaticMacEntries> staticMacEntries = NeutronvpnUtils.buildStaticMacEntry(port);
957 InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
958 .class, new ElanInterfaceKey(name)).build();
959 ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
960 .setName(name).setStaticMacEntries(staticMacEntries).withKey(new ElanInterfaceKey(name)).build();
961 wrtConfigTxn.put(id, elanInterface);
962 LOG.debug("Creating new ELan Interface {}", elanInterface);
965 private void deleteElanInterface(String name, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
966 InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
967 .class, new ElanInterfaceKey(name)).build();
968 wrtConfigTxn.delete(id);
971 // TODO Clean up the exception handling
972 @SuppressWarnings("checkstyle:IllegalCatch")
973 private void addToFloatingIpPortInfo(Uuid floatingIpId, Uuid floatingIpPortId, Uuid floatingIpPortSubnetId, String
974 floatingIpPortMacAddress) {
975 InstanceIdentifier id = NeutronvpnUtils.buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
977 FloatingIpIdToPortMappingBuilder floatingipIdToPortMacMappingBuilder = new
978 FloatingIpIdToPortMappingBuilder().withKey(new FloatingIpIdToPortMappingKey(floatingIpId))
979 .setFloatingIpId(floatingIpId).setFloatingIpPortId(floatingIpPortId)
980 .setFloatingIpPortSubnetId(floatingIpPortSubnetId)
981 .setFloatingIpPortMacAddress(floatingIpPortMacAddress);
982 LOG.debug("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
983 + " Port Info Config DS", floatingIpId.getValue(), floatingIpPortId.getValue());
984 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
985 floatingipIdToPortMacMappingBuilder.build());
986 } catch (Exception e) {
987 LOG.error("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
988 + " Port Info Config DS failed", floatingIpId.getValue(), floatingIpPortId.getValue(), e);
992 private Set<FixedIps> getFixedIpSet(List<FixedIps> fixedIps) {
993 return fixedIps != null ? new HashSet<>(fixedIps) : Collections.emptySet();