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 if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
229 LOG.warn("neutron vpn received a port update() for a network without a provider extension augmentation "
230 + "or with an unsupported network type for the port {} which is part of network {}",
234 neutronvpnUtils.addToPortCache(update);
236 if ((Strings.isNullOrEmpty(original.getDeviceOwner()) || Strings.isNullOrEmpty(original.getDeviceId())
237 || NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING.equalsIgnoreCase(original.getDeviceId()))
238 && !Strings.isNullOrEmpty(update.getDeviceOwner()) && !Strings.isNullOrEmpty(update.getDeviceId())) {
239 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(update.getDeviceOwner())) {
240 handleRouterInterfaceAdded(update);
243 if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(update.getDeviceOwner())) {
244 handleRouterGatewayUpdated(update, false);
245 } else if (NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(update.getDeviceOwner())) {
246 handleFloatingIpPortUpdated(original, update);
249 Set<FixedIps> oldIPs = getFixedIpSet(original.getFixedIps());
250 Set<FixedIps> newIPs = getFixedIpSet(update.getFixedIps());
251 if (!oldIPs.equals(newIPs)) {
252 handleNeutronPortUpdated(original, update);
256 // check if port security enabled/disabled as part of port update
257 boolean origSecurityEnabled = NeutronvpnUtils.getPortSecurityEnabled(original);
258 boolean updatedSecurityEnabled = NeutronvpnUtils.getPortSecurityEnabled(update);
259 boolean isDhcpServerPort = neutronvpnConfig.isLimitBumtrafficToDhcpserver()
260 && NeutronvpnUtils.isDhcpServerPort(update);
261 if (origSecurityEnabled || updatedSecurityEnabled || isDhcpServerPort) {
262 InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(portName);
263 jobCoordinator.enqueueJob("PORT- " + portName,
264 () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
266 Optional<Interface> optionalInf =
267 confTx.read(interfaceIdentifier).get();
268 if (optionalInf.isPresent()) {
269 InterfaceBuilder interfaceBuilder = new InterfaceBuilder(optionalInf.get());
270 if (origSecurityEnabled || updatedSecurityEnabled) {
271 InterfaceAcl infAcl = handlePortSecurityUpdated(original, update, origSecurityEnabled,
272 updatedSecurityEnabled, interfaceBuilder).build();
273 interfaceBuilder.addAugmentation(InterfaceAcl.class, infAcl);
274 } else if (isDhcpServerPort) {
275 Set<FixedIps> oldIPs = getFixedIpSet(original.getFixedIps());
276 Set<FixedIps> newIPs = getFixedIpSet(update.getFixedIps());
277 if (!oldIPs.equals(newIPs)) {
278 InterfaceAcl infAcl = neutronvpnUtils.getDhcpInterfaceAcl(update);
279 interfaceBuilder.addAugmentation(InterfaceAcl.class, infAcl);
282 LOG.info("update: Of-port-interface updation for port {}", portName);
283 // Update OFPort interface for this neutron port
284 confTx.put(interfaceIdentifier, interfaceBuilder.build());
286 LOG.warn("update: Interface {} is not present", portName);
292 private void handleFloatingIpPortUpdated(@Nullable Port original, Port update) {
293 if ((original == null || NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING.equals(original.getDeviceId())
294 && !NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING.equals(update.getDeviceId()))) {
295 // populate floating-ip uuid and floating-ip port attributes (uuid, mac and subnet id for the ONLY
296 // fixed IP) to be used by NAT, depopulated in NATService once mac is retrieved in the removal path
297 addToFloatingIpPortInfo(new Uuid(update.getDeviceId()), update.getUuid(), update.getFixedIps().get(0)
298 .getSubnetId(), update.getMacAddress().getValue());
299 elanService.addKnownL3DmacAddress(update.getMacAddress().getValue(), update.getNetworkId().getValue());
303 private void handleRouterInterfaceAdded(Port routerPort) {
304 if (routerPort.getDeviceId() != null) {
305 Uuid routerId = new Uuid(routerPort.getDeviceId());
306 Uuid infNetworkId = routerPort.getNetworkId();
307 Uuid existingVpnId = neutronvpnUtils.getVpnForNetwork(infNetworkId);
309 elanService.addKnownL3DmacAddress(routerPort.getMacAddress().getValue(), infNetworkId.getValue());
310 if (existingVpnId == null) {
311 Set<Uuid> listVpnIds = new HashSet<>();
312 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
316 listVpnIds.add(vpnId);
317 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
318 List<Subnetmap> subnetMapList = new ArrayList<>();
319 boolean portIsIpv6 = false;
320 for (FixedIps portIP : routerPort.nonnullFixedIps()) {
321 // NOTE: Please donot change the order of calls to updateSubnetNodeWithFixedIP
322 // and addSubnetToVpn here
323 if (internetVpnId != null
324 && portIP.getIpAddress().getIpv6Address() != null) {
327 String ipValue = portIP.getIpAddress().stringValue();
328 Uuid subnetId = portIP.getSubnetId();
329 nvpnManager.updateSubnetNodeWithFixedIp(subnetId, routerId,
330 routerPort.getUuid(), ipValue, routerPort.getMacAddress().getValue(), vpnId);
331 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
332 subnetMapList.add(sn);
335 listVpnIds.add(internetVpnId);
336 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(
337 IpVersionChoice.IPV6, routerId, true)) {
338 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6,
340 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
343 if (! subnetMapList.isEmpty()) {
344 nvpnManager.createVpnInterface(listVpnIds, routerPort, null);
346 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
347 for (FixedIps portIP : routerPort.nonnullFixedIps()) {
348 String ipValue = portIP.getIpAddress().stringValue();
349 ipVersion = NeutronvpnUtils.getIpVersionFromString(ipValue);
350 if (ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
351 nvpnManager.addSubnetToVpn(vpnId, portIP.getSubnetId(),
352 null /* internet-vpn-id */);
354 nvpnManager.addSubnetToVpn(vpnId, portIP.getSubnetId(), internetVpnId);
356 LOG.trace("NeutronPortChangeListener Add Subnet Gateway IP {} MAC {} Interface {} VPN {}",
357 ipValue, routerPort.getMacAddress(),
358 routerPort.getUuid().getValue(), vpnId.getValue());
360 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(ipVersion, routerId, true)) {
361 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}",
362 ipVersion, vpnId.getValue());
363 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
365 nvpnManager.addToNeutronRouterInterfacesMap(routerId, routerPort.getUuid().getValue());
366 jobCoordinator.enqueueJob(routerId.toString(), () -> {
367 nvpnNatManager.handleSubnetsForExternalRouter(routerId);
368 return Collections.emptyList();
370 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
372 String portInterfaceName = createOfPortInterface(routerPort, confTx);
373 createElanInterface(routerPort, portInterfaceName, confTx);
374 }), LOG, "Error creating ELAN interface for {}", routerPort);
376 LOG.error("Neutron network {} corresponding to router interface port {} for neutron router {}"
377 + " already associated to VPN {}", infNetworkId.getValue(), routerPort.getUuid().getValue(),
378 routerId.getValue(), existingVpnId.getValue());
383 private void handleRouterInterfaceRemoved(Port routerPort) {
384 if (routerPort.getDeviceId() != null) {
385 Uuid routerId = new Uuid(routerPort.getDeviceId());
386 Uuid infNetworkId = routerPort.getNetworkId();
387 elanService.removeKnownL3DmacAddress(routerPort.getMacAddress().getValue(), infNetworkId.getValue());
388 Uuid vpnId = ObjectUtils.defaultIfNull(neutronvpnUtils.getVpnForRouter(routerId, true),
390 List<FixedIps> portIps = routerPort.nonnullFixedIps();
391 boolean vpnInstanceInternetIpVersionRemoved = false;
392 Uuid vpnInstanceInternetUuid = null;
393 for (FixedIps portIP : portIps) {
394 // Internet VPN : flush InternetVPN first
395 Uuid subnetId = portIP.getSubnetId();
396 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
397 if (sn != null && sn.getInternetVpnId() != null) {
398 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sn, sn.getInternetVpnId())) {
399 vpnInstanceInternetIpVersionRemoved = true;
400 vpnInstanceInternetUuid = sn.getInternetVpnId();
402 nvpnManager.updateVpnInternetForSubnet(sn, sn.getInternetVpnId(), false);
405 /* Remove ping responder for router interfaces
406 * A router interface reference in a VPN will have to be removed before the host interface references
407 * for that subnet in the VPN are removed. This is to ensure that the FIB Entry of the router interface
408 * is not the last entry to be removed for that subnet in the VPN.
409 * If router interface FIB entry is the last to be removed for a subnet in a VPN , then all the host
410 * interface references in the vpn will already have been cleared, which will cause failures in
411 * cleanup of router interface flows*/
412 nvpnManager.deleteVpnInterface(routerPort.getUuid().getValue(),
413 null /* vpn-id */, null /* wrtConfigTxn*/);
414 final Uuid internetVpnId = vpnInstanceInternetUuid;
415 // update RouterInterfaces map
416 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
418 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
419 for (FixedIps portIP : portIps) {
420 Subnetmap sn = neutronvpnUtils.getSubnetmap(portIP.getSubnetId());
421 // router Port have either IPv4 or IPv6, never both
422 ipVersion = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
423 String ipValue = portIP.getIpAddress().stringValue();
424 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(), ipValue, confTx);
425 // NOTE: Please donot change the order of calls to removeSubnetFromVpn and
426 // and updateSubnetNodeWithFixedIP
427 nvpnManager.removeSubnetFromVpn(vpnId, portIP.getSubnetId(), internetVpnId);
428 nvpnManager.updateSubnetNodeWithFixedIp(portIP.getSubnetId(), null, null,
431 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, routerPort.getUuid().getValue());
432 deleteElanInterface(routerPort.getUuid().getValue(), confTx);
433 deleteOfPortInterface(routerPort, confTx);
434 jobCoordinator.enqueueJob(routerId.toString(), () -> {
435 nvpnNatManager.handleSubnetsForExternalRouter(routerId);
436 return Collections.emptyList();
438 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(ipVersion, routerId, false)) {
439 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}",
440 ipVersion, vpnId.getValue());
441 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
443 }), LOG, "Error handling interface removal");
444 if (vpnInstanceInternetIpVersionRemoved) {
445 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnInstanceInternetUuid.getValue(),
446 IpVersionChoice.IPV6, false);
447 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, vpnInstanceInternetUuid, false);
452 private void handleRouterGatewayUpdated(Port routerGwPort, boolean isRtrGwRemoved) {
453 Uuid routerId = new Uuid(routerGwPort.getDeviceId());
454 Uuid networkId = routerGwPort.getNetworkId();
455 Network network = neutronvpnUtils.getNeutronNetwork(networkId);
456 if (network == null) {
459 boolean isExternal = NeutronvpnUtils.getIsExternal(network);
461 Uuid vpnInternetId = neutronvpnUtils.getVpnForNetwork(networkId);
462 if (vpnInternetId != null) {
463 if (!isRtrGwRemoved) {
464 nvpnManager.updateVpnMaps(vpnInternetId, null, routerId, null, null);
466 List<Subnetmap> snList = neutronvpnUtils.getNeutronRouterSubnetMaps(routerId);
467 for (Subnetmap sn : snList) {
468 if (sn.getNetworkId() == networkId) {
471 if (NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()) != IpVersionChoice.IPV6) {
474 if (isRtrGwRemoved) {
475 nvpnManager.removeV6PrivateSubnetToExtNetwork(routerId, vpnInternetId, sn);
477 nvpnManager.addV6PrivateSubnetToExtNetwork(routerId, vpnInternetId, sn);
480 //Update Internet BGP-VPN
481 if (isRtrGwRemoved) {
482 nvpnManager.updateVpnMaps(vpnInternetId, null, null, null, null);
486 elanService.addKnownL3DmacAddress(routerGwPort.getMacAddress().getValue(), networkId.getValue());
488 Router router = neutronvpnUtils.getNeutronRouter(routerId);
489 if (router == null) {
490 LOG.warn("No router found for router GW port {} for router {}", routerGwPort.getUuid().getValue(),
491 routerId.getValue());
493 eventCallbacks.onAddOrUpdate(LogicalDatastoreType.CONFIGURATION,
494 neutronvpnUtils.getNeutronRouterIid(routerId), (unused, newRouter) -> {
495 setupGwMac(newRouter, routerGwPort, routerId);
496 return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
497 }, Duration.ofSeconds(3), iid -> {
498 LOG.error("GwPort {} added without Router", routerGwPort.getUuid().getValue());
502 setupGwMac(router, routerGwPort, routerId);
505 private void setupGwMac(Router router, Port routerGwPort, Uuid routerId) {
506 gwMacResolver.sendArpRequestsToExtGateways(router);
507 jobCoordinator.enqueueJob(routerId.toString(), () -> {
508 setExternalGwMac(routerGwPort, routerId);
509 return Collections.emptyList();
513 private void setExternalGwMac(Port routerGwPort, Uuid routerId) {
514 // During full-sync networking-odl syncs routers before ports. As such,
515 // the MAC of the router's gw port is not available to be set when the
516 // router is written. We catch that here.
517 InstanceIdentifier<Routers> routersId = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
518 Optional<Routers> optionalRouter = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId);
519 if (!optionalRouter.isPresent()) {
523 Routers extRouters = optionalRouter.get();
524 if (extRouters.getExtGwMacAddress() != null) {
528 RoutersBuilder builder = new RoutersBuilder(extRouters);
529 builder.setExtGwMacAddress(routerGwPort.getMacAddress().getValue());
530 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId, builder.build());
534 private String getPortHostId(final Port port) {
536 PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class);
537 if (portBinding != null) {
538 return portBinding.getHostId();
545 private Hostconfig getHostConfig(final Port port) {
546 String hostId = getPortHostId(port);
547 if (hostId == null) {
550 Optional<Hostconfig> hostConfig;
552 hostConfig = this.hostConfigCache.get(hostId);
553 } catch (ReadFailedException e) {
554 LOG.error("failed to read host config from host {}", hostId, e);
557 return hostConfig.orNull();
560 private boolean isPortBound(final Port port) {
561 String hostId = getPortHostId(port);
562 return hostId != null && !hostId.isEmpty();
565 private boolean isPortVnicTypeDirect(Port port) {
566 PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class);
567 if (portBinding == null || portBinding.getVnicType() == null) {
568 // By default, VNIC_TYPE is NORMAL
571 String vnicType = portBinding.getVnicType().trim().toLowerCase(Locale.getDefault());
572 return NeutronConstants.VNIC_TYPE_DIRECT.equals(vnicType);
575 private boolean isSupportedVnicTypeByHost(final Port port, final String vnicType) {
576 Hostconfig hostConfig = getHostConfig(port);
577 String supportStr = String.format("\"vnic_type\": \"%s\"", vnicType);
578 if (hostConfig != null && hostConfig.getConfig().contains(supportStr)) {
585 private Map<String, JsonElement> unmarshal(final String profile) {
586 if (null == profile) {
589 Gson gson = new Gson();
590 JsonObject jsonObject = gson.fromJson(profile, JsonObject.class);
591 Map<String, JsonElement> map = new HashMap<>();
592 for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
593 map.put(entry.getKey(), entry.getValue());
598 private boolean isPortTypeSwitchdev(final Port port) {
599 if (!isPortVnicTypeDirect(port)) {
603 PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class);
604 String profile = portBinding.getProfile();
605 if (profile == null || profile.isEmpty()) {
606 LOG.debug("Port {} has no binding:profile values", port.getUuid());
610 Map<String, JsonElement> mapProfile = unmarshal(profile);
611 JsonElement capabilities = mapProfile.get(NeutronConstants.BINDING_PROFILE_CAPABILITIES);
612 LOG.debug("Port {} capabilities: {}", port.getUuid(), capabilities);
613 if (capabilities == null || !capabilities.isJsonArray()) {
614 LOG.debug("binding profile capabilities not in array format: {}", capabilities);
618 JsonArray capabilitiesArray = capabilities.getAsJsonArray();
619 Gson gson = new Gson();
620 JsonElement switchdevElement = gson.fromJson(NeutronConstants.SWITCHDEV, JsonElement.class);
621 return capabilitiesArray.contains(switchdevElement);
625 private void handleNeutronPortCreated(final Port port) {
626 final String portName = port.getUuid().getValue();
627 final Uuid portId = port.getUuid();
628 final List<FixedIps> portIpAddrsList = port.nonnullFixedIps();
629 if (NeutronConstants.IS_ODL_DHCP_PORT.test(port)) {
632 jobCoordinator.enqueueJob("PORT- " + portName, () -> {
633 // add direct port to subnetMaps config DS
634 if (!(NeutronUtils.isPortVnicTypeNormal(port)
635 || isPortTypeSwitchdev(port)
636 && isSupportedVnicTypeByHost(port, NeutronConstants.VNIC_TYPE_DIRECT))) {
637 for (FixedIps ip: portIpAddrsList) {
638 nvpnManager.updateSubnetmapNodeWithPorts(ip.getSubnetId(), null, portId);
640 LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;"
641 + "OF Port interfaces are not created", portName);
642 return Collections.emptyList();
644 return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
645 LOG.info("Of-port-interface creation for port {}", portName);
646 // Create of-port interface for this neutron port
647 String portInterfaceName = createOfPortInterface(port, tx);
648 LOG.debug("Creating ELAN Interface for port {}", portName);
649 createElanInterface(port, portInterfaceName, tx);
650 Set<Uuid> vpnIdList = new HashSet<>();
651 Set<Uuid> routerIds = new HashSet<>();
652 for (FixedIps ip: portIpAddrsList) {
653 Subnetmap subnetMap = nvpnManager.updateSubnetmapNodeWithPorts(ip.getSubnetId(), portId, null);
654 if (subnetMap != null && subnetMap.getInternetVpnId() != null) {
655 if (!vpnIdList.contains(subnetMap.getInternetVpnId())) {
656 vpnIdList.add(subnetMap.getInternetVpnId());
659 if (subnetMap != null && subnetMap.getVpnId() != null) {
660 // can't use NeutronvpnUtils.getVpnForNetwork to optimise here, because it gives BGPVPN id
661 // obtained subnetMaps belongs to one network => vpnId must be the same for each port Ip
662 Uuid vpnId = subnetMap.getVpnId();
664 vpnIdList.add(vpnId);
667 if (subnetMap != null && subnetMap.getRouterId() != null) {
668 routerIds.add(subnetMap.getRouterId());
671 if (!vpnIdList.isEmpty()) {
672 // create new vpn-interface for neutron port
673 LOG.debug("handleNeutronPortCreated: Adding VPN Interface for port {} from network {}", portName,
674 port.getNetworkId().toString());
675 nvpnManager.createVpnInterface(vpnIdList, port, tx);
676 if (!routerIds.isEmpty()) {
677 for (Uuid routerId : routerIds) {
678 nvpnManager.addToNeutronRouterInterfacesMap(routerId,port.getUuid().getValue());
686 private void handleNeutronPortDeleted(final Port port) {
687 final String portName = port.getUuid().getValue();
688 final Uuid portId = port.getUuid();
689 final List<FixedIps> portIpsList = port.nonnullFixedIps();
690 jobCoordinator.enqueueJob("PORT- " + portName,
691 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
692 if (!(NeutronUtils.isPortVnicTypeNormal(port) || isPortTypeSwitchdev(port))) {
693 for (FixedIps ip : portIpsList) {
694 // remove direct port from subnetMaps config DS
695 nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), null, portId);
697 LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;"
698 + "Skipping OF Port interfaces removal", portName);
702 Set<Uuid> routerIds = new HashSet<>();
703 Uuid internetVpnId = null;
704 for (FixedIps ip : portIpsList) {
705 Subnetmap subnetMap = nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), portId, null);
706 if (subnetMap == null) {
709 if (subnetMap.getVpnId() != null) {
710 // can't use NeutronvpnUtils.getVpnForNetwork to optimise here, because it gives BGPVPN id
711 // obtained subnetMaps belongs to one network => vpnId must be the same for each port Ip
712 vpnId = subnetMap.getVpnId();
714 if (subnetMap.getRouterId() != null) {
715 routerIds.add(subnetMap.getRouterId());
717 internetVpnId = subnetMap.getInternetVpnId();
719 if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(port.getDeviceOwner())
720 || NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(port.getDeviceOwner())) {
721 String ipAddress = ip.getIpAddress().stringValue();
723 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(), ipAddress, confTx);
725 if (internetVpnId != null) {
726 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
731 if (vpnId != null || internetVpnId != null) {
732 // remove vpn-interface for this neutron port
733 LOG.debug("removing VPN Interface for port {}", portName);
734 if (!routerIds.isEmpty()) {
735 for (Uuid routerId : routerIds) {
736 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, portName);
739 nvpnManager.deleteVpnInterface(portName, null /* vpn-id */, confTx);
741 // Remove of-port interface for this neutron port
742 // ELAN interface is also implicitly deleted as part of this operation
743 LOG.debug("Of-port-interface removal for port {}", portName);
744 deleteOfPortInterface(port, confTx);
745 //dissociate fixedIP from floatingIP if associated
746 nvpnManager.dissociatefixedIPFromFloatingIP(port.getUuid().getValue());
751 private void handleNeutronPortUpdated(final Port portoriginal, final Port portupdate) {
752 final List<FixedIps> portoriginalIps = portoriginal.getFixedIps();
753 final List<FixedIps> portupdateIps = portupdate.getFixedIps();
754 if (portoriginalIps == null || portoriginalIps.isEmpty()) {
755 handleNeutronPortCreated(portupdate);
759 if (portupdateIps == null || portupdateIps.isEmpty()) {
760 LOG.info("Ignoring portUpdate (fixed_ip removal) for port {} as this case is handled "
761 + "during subnet deletion event.", portupdate.getUuid().getValue());
765 if (NeutronConstants.IS_ODL_DHCP_PORT.test(portupdate)) {
769 jobCoordinator.enqueueJob("PORT- " + portupdate.getUuid().getValue(),
770 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
771 final List<Uuid> originalSnMapsIds = portoriginalIps.stream().map(FixedIps::getSubnetId)
772 .collect(Collectors.toList());
773 final List<Uuid> updateSnMapsIds = portupdateIps.stream().map(FixedIps::getSubnetId)
774 .collect(Collectors.toList());
775 Set<Uuid> originalRouterIds = new HashSet<>();
776 Set<Uuid> oldVpnIds = new HashSet<>();
777 for (Uuid snId: originalSnMapsIds) {
778 if (!updateSnMapsIds.remove(snId)) {
779 // snId was present in originalSnMapsIds, but not in updateSnMapsIds
780 Subnetmap subnetMapOld = nvpnManager.removePortsFromSubnetmapNode(snId, portoriginal.getUuid(),
782 if (subnetMapOld != null && subnetMapOld.getVpnId() != null) {
783 oldVpnIds.add(subnetMapOld.getVpnId());
785 if (subnetMapOld != null && subnetMapOld.getInternetVpnId() != null) {
786 oldVpnIds.add(subnetMapOld.getInternetVpnId());
788 if (subnetMapOld != null && subnetMapOld.getRouterId() != null) {
789 originalRouterIds.add(subnetMapOld.getRouterId());
793 Set<Uuid> newVpnIds = new HashSet<>();
794 Set<Uuid> newRouterIds = new HashSet<>();
795 for (Uuid snId: updateSnMapsIds) {
796 Subnetmap subnetMapNew = nvpnManager.updateSubnetmapNodeWithPorts(snId, portupdate.getUuid(), null);
797 if (subnetMapNew != null) {
798 if (subnetMapNew.getVpnId() != null) {
799 newVpnIds.add(subnetMapNew.getVpnId());
801 if (subnetMapNew.getInternetVpnId() != null) {
802 newVpnIds.add(subnetMapNew.getInternetVpnId());
804 if (subnetMapNew.getRouterId() != null) {
805 newRouterIds.add(subnetMapNew.getRouterId());
809 if (!oldVpnIds.isEmpty()) {
810 LOG.info("removing VPN Interface for port {}", portoriginal.getUuid().getValue());
811 if (!originalRouterIds.isEmpty()) {
812 for (Uuid routerId : originalRouterIds) {
813 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId,
814 portoriginal.getUuid().getValue());
817 nvpnManager.deleteVpnInterface(portoriginal.getUuid().getValue(),
818 null /* vpn-id */, confTx);
820 if (!newVpnIds.isEmpty()) {
821 LOG.info("Adding VPN Interface for port {}", portupdate.getUuid().getValue());
822 nvpnManager.createVpnInterface(newVpnIds, portupdate, confTx);
823 if (!newRouterIds.isEmpty()) {
824 for (Uuid routerId : newRouterIds) {
825 nvpnManager.addToNeutronRouterInterfacesMap(routerId,portupdate.getUuid().getValue());
833 private InterfaceAclBuilder handlePortSecurityUpdated(Port portOriginal,
834 Port portUpdated, boolean origSecurityEnabled, boolean updatedSecurityEnabled,
835 InterfaceBuilder interfaceBuilder) {
836 InterfaceAclBuilder interfaceAclBuilder = null;
837 if (origSecurityEnabled != updatedSecurityEnabled) {
838 interfaceAclBuilder = new InterfaceAclBuilder();
839 interfaceAclBuilder.setPortSecurityEnabled(updatedSecurityEnabled);
840 if (updatedSecurityEnabled) {
841 // Handle security group enabled
842 neutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, portUpdated);
844 // Handle security group disabled
845 interfaceAclBuilder.setSecurityGroups(new ArrayList<>());
846 interfaceAclBuilder.setAllowedAddressPairs(new ArrayList<>());
847 interfaceAclBuilder.setSubnetInfo(new ArrayList<>());
850 if (updatedSecurityEnabled) {
851 // handle SG add/delete delta
852 InterfaceAcl interfaceAcl = interfaceBuilder.augmentation(InterfaceAcl.class);
853 interfaceAclBuilder = new InterfaceAclBuilder(interfaceAcl);
854 interfaceAclBuilder.setSecurityGroups(
855 NeutronvpnUtils.getUpdatedSecurityGroups(interfaceAcl.getSecurityGroups(),
856 portOriginal.getSecurityGroups(), portUpdated.getSecurityGroups()));
857 List<AllowedAddressPairs> updatedAddressPairs = NeutronvpnUtils.getUpdatedAllowedAddressPairs(
858 interfaceAcl.getAllowedAddressPairs(), portOriginal.getAllowedAddressPairs(),
859 portUpdated.getAllowedAddressPairs());
860 interfaceAclBuilder.setAllowedAddressPairs(NeutronvpnUtils.getAllowedAddressPairsForFixedIps(
861 updatedAddressPairs, portOriginal.getMacAddress(), portOriginal.getFixedIps(),
862 portUpdated.getFixedIps()));
864 if (portOriginal.getFixedIps() != null
865 && !portOriginal.getFixedIps().equals(portUpdated.getFixedIps())) {
866 neutronvpnUtils.populateSubnetInfo(interfaceAclBuilder, portUpdated);
870 return interfaceAclBuilder;
873 private String createOfPortInterface(Port port, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
874 Interface inf = createInterface(port);
875 String infName = inf.getName();
877 InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(infName);
879 Optional<Interface> optionalInf =
880 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
881 interfaceIdentifier);
882 if (!optionalInf.isPresent()) {
883 wrtConfigTxn.put(interfaceIdentifier, inf);
885 LOG.warn("Interface {} is already present", infName);
887 } catch (ReadFailedException e) {
888 LOG.error("failed to create interface {}", infName, e);
893 private Interface createInterface(Port port) {
894 String interfaceName = port.getUuid().getValue();
895 IfL2vlan.L2vlanMode l2VlanMode = IfL2vlan.L2vlanMode.Trunk;
896 InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
897 IfL2vlanBuilder ifL2vlanBuilder = new IfL2vlanBuilder();
899 Network network = neutronvpnUtils.getNeutronNetwork(port.getNetworkId());
900 Boolean isVlanTransparent = network.isVlanTransparent();
901 if (isVlanTransparent != null && isVlanTransparent) {
902 l2VlanMode = IfL2vlan.L2vlanMode.Transparent;
904 PortIdToSubport portIdToSubport = neutronvpnUtils.getPortIdToSubport(port.getUuid());
905 if (portIdToSubport != null) {
906 l2VlanMode = IfL2vlan.L2vlanMode.TrunkMember;
907 ifL2vlanBuilder.setVlanId(new VlanId(portIdToSubport.getVlanId().intValue()));
908 String parentRefName = portIdToSubport.getTrunkPortId().getValue();
909 ParentRefsBuilder parentRefsBuilder = new ParentRefsBuilder().setParentInterface(parentRefName);
910 interfaceBuilder.addAugmentation(ParentRefs.class, parentRefsBuilder.build());
911 SplitHorizon splitHorizon =
912 new SplitHorizonBuilder().setOverrideSplitHorizonProtection(true).build();
913 interfaceBuilder.addAugmentation(SplitHorizon.class, splitHorizon);
917 ifL2vlanBuilder.setL2vlanMode(l2VlanMode);
919 interfaceBuilder.setEnabled(true).setName(interfaceName).setType(L2vlan.class)
920 .addAugmentation(IfL2vlan.class, ifL2vlanBuilder.build());
922 if (NeutronvpnUtils.getPortSecurityEnabled(port)) {
923 InterfaceAclBuilder interfaceAclBuilder = new InterfaceAclBuilder();
924 interfaceAclBuilder.setPortSecurityEnabled(true);
925 neutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, port);
926 interfaceBuilder.addAugmentation(InterfaceAcl.class, interfaceAclBuilder.build());
927 } else if (neutronvpnConfig.isLimitBumtrafficToDhcpserver() && NeutronvpnUtils.isDhcpServerPort(port)) {
928 interfaceBuilder.addAugmentation(InterfaceAcl.class, neutronvpnUtils.getDhcpInterfaceAcl(port));
930 return interfaceBuilder.build();
933 private void deleteOfPortInterface(Port port, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
934 String name = port.getUuid().getValue();
935 LOG.debug("Removing OFPort Interface {}", name);
936 InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
938 Optional<Interface> optionalInf =
939 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
940 interfaceIdentifier);
941 if (optionalInf.isPresent()) {
942 wrtConfigTxn.delete(interfaceIdentifier);
944 LOG.warn("deleteOfPortInterface: Interface {} is not present", name);
946 } catch (ReadFailedException e) {
947 LOG.error("deleteOfPortInterface: Failed to delete interface {}", name, e);
951 private void createElanInterface(Port port, String name,
952 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
953 String elanInstanceName = port.getNetworkId().getValue();
954 List<StaticMacEntries> staticMacEntries = NeutronvpnUtils.buildStaticMacEntry(port);
956 InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
957 .class, new ElanInterfaceKey(name)).build();
958 ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
959 .setName(name).setStaticMacEntries(staticMacEntries).withKey(new ElanInterfaceKey(name)).build();
960 wrtConfigTxn.put(id, elanInterface);
961 LOG.debug("Creating new ELan Interface {}", elanInterface);
964 private void deleteElanInterface(String name, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
965 InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
966 .class, new ElanInterfaceKey(name)).build();
967 wrtConfigTxn.delete(id);
970 // TODO Clean up the exception handling
971 @SuppressWarnings("checkstyle:IllegalCatch")
972 private void addToFloatingIpPortInfo(Uuid floatingIpId, Uuid floatingIpPortId, Uuid floatingIpPortSubnetId, String
973 floatingIpPortMacAddress) {
974 InstanceIdentifier id = NeutronvpnUtils.buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
976 FloatingIpIdToPortMappingBuilder floatingipIdToPortMacMappingBuilder = new
977 FloatingIpIdToPortMappingBuilder().withKey(new FloatingIpIdToPortMappingKey(floatingIpId))
978 .setFloatingIpId(floatingIpId).setFloatingIpPortId(floatingIpPortId)
979 .setFloatingIpPortSubnetId(floatingIpPortSubnetId)
980 .setFloatingIpPortMacAddress(floatingIpPortMacAddress);
981 LOG.debug("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
982 + " Port Info Config DS", floatingIpId.getValue(), floatingIpPortId.getValue());
983 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
984 floatingipIdToPortMacMappingBuilder.build());
985 } catch (Exception e) {
986 LOG.error("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
987 + " Port Info Config DS failed", floatingIpId.getValue(), floatingIpPortId.getValue(), e);
991 private Set<FixedIps> getFixedIpSet(List<FixedIps> fixedIps) {
992 return fixedIps != null ? new HashSet<>(fixedIps) : Collections.emptySet();