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.common.util.concurrent.ListenableFuture;
15 import com.google.gson.Gson;
16 import com.google.gson.JsonArray;
17 import com.google.gson.JsonElement;
18 import com.google.gson.JsonObject;
19 import java.time.Duration;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Locale;
28 import java.util.stream.Collectors;
29 import javax.annotation.PostConstruct;
30 import javax.inject.Singleton;
31 import org.apache.commons.lang3.ObjectUtils;
32 import org.eclipse.jdt.annotation.Nullable;
33 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
34 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
35 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
36 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
37 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
38 import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
39 import org.opendaylight.genius.infra.Datastore;
40 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
41 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
42 import org.opendaylight.genius.infra.TypedWriteTransaction;
43 import org.opendaylight.genius.mdsalutil.MDSALUtil;
44 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
45 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
46 import org.opendaylight.netvirt.elanmanager.api.IElanService;
47 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
48 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
49 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.L2vlan;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlanBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefsBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.SplitHorizon;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.SplitHorizonBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAclBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntries;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingKey;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.port.id.subport.data.PortIdToSubport;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.hostconfig.rev150712.hostconfig.attributes.hostconfigs.Hostconfig;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
84 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
85 import org.slf4j.Logger;
86 import org.slf4j.LoggerFactory;
89 public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase<Port, NeutronPortChangeListener> {
90 private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChangeListener.class);
91 private final DataBroker dataBroker;
92 private final ManagedNewTransactionRunner txRunner;
93 private final NeutronvpnManager nvpnManager;
94 private final NeutronvpnNatManager nvpnNatManager;
95 private final NeutronSubnetGwMacResolver gwMacResolver;
96 private final IElanService elanService;
97 private final JobCoordinator jobCoordinator;
98 private final NeutronvpnUtils neutronvpnUtils;
99 private final HostConfigCache hostConfigCache;
100 private final DataTreeEventCallbackRegistrar eventCallbacks;
101 private final NeutronvpnConfig neutronvpnConfig;
103 public NeutronPortChangeListener(final DataBroker dataBroker,
104 final NeutronvpnManager neutronvpnManager,
105 final NeutronvpnNatManager neutronvpnNatManager,
106 final NeutronSubnetGwMacResolver gwMacResolver,
107 final IElanService elanService,
108 final JobCoordinator jobCoordinator,
109 final NeutronvpnUtils neutronvpnUtils,
110 final HostConfigCache hostConfigCache,
111 final DataTreeEventCallbackRegistrar dataTreeEventCallbackRegistrar,
112 final NeutronvpnConfig neutronvpnConfig) {
113 super(Port.class, NeutronPortChangeListener.class);
114 this.dataBroker = dataBroker;
115 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
116 nvpnManager = neutronvpnManager;
117 nvpnNatManager = neutronvpnNatManager;
118 this.gwMacResolver = gwMacResolver;
119 this.elanService = elanService;
120 this.jobCoordinator = jobCoordinator;
121 this.neutronvpnUtils = neutronvpnUtils;
122 this.hostConfigCache = hostConfigCache;
123 this.eventCallbacks = dataTreeEventCallbackRegistrar;
124 this.neutronvpnConfig = neutronvpnConfig;
131 LOG.info("{} init", getClass().getSimpleName());
132 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
136 protected InstanceIdentifier<Port> getWildCardPath() {
137 return InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class);
141 protected NeutronPortChangeListener getDataTreeChangeListener() {
142 return NeutronPortChangeListener.this;
147 protected void add(InstanceIdentifier<Port> identifier, Port input) {
148 LOG.trace("Received port add event: port={}", input);
149 String portName = input.getUuid().getValue();
150 LOG.trace("Adding Port : key: {}, value={}", identifier, input);
151 Network network = neutronvpnUtils.getNeutronNetwork(input.getNetworkId());
152 if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
153 LOG.warn("neutron vpn received a port add() for a network without a provider extension augmentation "
154 + "or with an unsupported network type for the port {} which is part of network {}",
159 neutronvpnUtils.addToPortCache(input);
160 String portStatus = NeutronUtils.PORT_STATUS_DOWN;
161 if (!Strings.isNullOrEmpty(input.getDeviceOwner()) && !Strings.isNullOrEmpty(input.getDeviceId())) {
162 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(input.getDeviceOwner())) {
163 handleRouterInterfaceAdded(input);
164 NeutronUtils.createPortStatus(input.getUuid().getValue(), NeutronUtils.PORT_STATUS_ACTIVE, dataBroker);
167 if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(input.getDeviceOwner())) {
168 handleRouterGatewayUpdated(input, false);
169 portStatus = NeutronUtils.PORT_STATUS_ACTIVE;
170 } else if (NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(input.getDeviceOwner())) {
171 handleFloatingIpPortUpdated(null, input);
172 portStatus = NeutronUtils.PORT_STATUS_ACTIVE;
175 // Switchdev ports need to be bounded to a host before creation
176 // in order to validate the supported vnic types from the hostconfig
177 if (input.getFixedIps() != null
178 && !input.getFixedIps().isEmpty()
179 && !(isPortTypeSwitchdev(input) && !isPortBound(input))) {
180 handleNeutronPortCreated(input);
182 NeutronUtils.createPortStatus(input.getUuid().getValue(), portStatus, dataBroker);
186 protected void remove(InstanceIdentifier<Port> identifier, Port input) {
187 LOG.trace("Removing Port : key: {}, value={}", identifier, input);
188 Network network = neutronvpnUtils.getNeutronNetwork(input.getNetworkId());
189 // need to proceed with deletion in case network is null for a case where v2 sync happens and a read for
190 // network from NN returns null, but the deletion process for port needs to continue
191 if (network != null && !NeutronvpnUtils.isNetworkTypeSupported(network)) {
192 String portName = input.getUuid().getValue();
193 LOG.warn("neutron vpn received a port remove() for a network without a provider extension augmentation "
194 + "or with an unsupported network type for the port {} which is part of network {}",
198 neutronvpnUtils.removeFromPortCache(input);
199 NeutronUtils.deletePortStatus(input.getUuid().getValue(), dataBroker);
201 if (!Strings.isNullOrEmpty(input.getDeviceOwner()) && !Strings.isNullOrEmpty(input.getDeviceId())) {
202 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(input.getDeviceOwner())) {
203 handleRouterInterfaceRemoved(input);
204 /* nothing else to do here */
206 } else if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(input.getDeviceOwner())
207 || NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(input.getDeviceOwner())) {
208 handleRouterGatewayUpdated(input, true);
209 elanService.removeKnownL3DmacAddress(input.getMacAddress().getValue(), input.getNetworkId().getValue());
212 if (input.getFixedIps() != null) {
213 handleNeutronPortDeleted(input);
218 protected void update(InstanceIdentifier<Port> identifier, Port original, Port update) {
219 LOG.trace("Received port update event: original={}, update={}", original, update);
220 // Switchdev ports need to be bounded to a host before creation
221 // in order to validate the supported vnic types from the hostconfig
222 if (isPortTypeSwitchdev(original)
223 && !isPortBound(original)
224 && isPortBound(update)) {
225 handleNeutronPortCreated(update);
227 final String portName = update.getUuid().getValue();
228 Network network = neutronvpnUtils.getNeutronNetwork(update.getNetworkId());
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 ListenableFuture<Void> future = txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
267 Optional<Interface> optionalInf = 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);
289 ListenableFutures.addErrorLogging(future, LOG,
290 "update: Failed to update interface {} with networkId {}", portName, network);
291 return Collections.singletonList(future);
296 private void handleFloatingIpPortUpdated(@Nullable Port original, Port update) {
297 if ((original == null || NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING.equals(original.getDeviceId())
298 && !NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING.equals(update.getDeviceId()))) {
299 // populate floating-ip uuid and floating-ip port attributes (uuid, mac and subnet id for the ONLY
300 // fixed IP) to be used by NAT, depopulated in NATService once mac is retrieved in the removal path
301 addToFloatingIpPortInfo(new Uuid(update.getDeviceId()), update.getUuid(), update.getFixedIps().get(0)
302 .getSubnetId(), update.getMacAddress().getValue());
303 elanService.addKnownL3DmacAddress(update.getMacAddress().getValue(), update.getNetworkId().getValue());
307 private void handleRouterInterfaceAdded(Port routerPort) {
308 if (routerPort.getDeviceId() != null) {
309 Uuid routerId = new Uuid(routerPort.getDeviceId());
310 Uuid infNetworkId = routerPort.getNetworkId();
311 Uuid existingVpnId = neutronvpnUtils.getVpnForNetwork(infNetworkId);
313 elanService.addKnownL3DmacAddress(routerPort.getMacAddress().getValue(), infNetworkId.getValue());
314 if (existingVpnId == null) {
315 Set<Uuid> listVpnIds = new HashSet<>();
316 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
320 listVpnIds.add(vpnId);
321 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
322 List<Subnetmap> subnetMapList = new ArrayList<>();
323 boolean portIsIpv6 = false;
324 for (FixedIps portIP : routerPort.nonnullFixedIps()) {
325 // NOTE: Please donot change the order of calls to updateSubnetNodeWithFixedIP
326 // and addSubnetToVpn here
327 if (internetVpnId != null
328 && portIP.getIpAddress().getIpv6Address() != null) {
331 String ipValue = portIP.getIpAddress().stringValue();
332 Uuid subnetId = portIP.getSubnetId();
333 nvpnManager.updateSubnetNodeWithFixedIp(subnetId, routerId,
334 routerPort.getUuid(), ipValue, routerPort.getMacAddress().getValue(), vpnId);
335 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
336 subnetMapList.add(sn);
339 listVpnIds.add(internetVpnId);
340 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(
341 IpVersionChoice.IPV6, routerId, true)) {
342 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6,
344 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
347 if (! subnetMapList.isEmpty()) {
348 nvpnManager.createVpnInterface(listVpnIds, routerPort, null);
350 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
351 for (FixedIps portIP : routerPort.nonnullFixedIps()) {
352 String ipValue = portIP.getIpAddress().stringValue();
353 ipVersion = NeutronvpnUtils.getIpVersionFromString(ipValue);
354 if (ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
355 nvpnManager.addSubnetToVpn(vpnId, portIP.getSubnetId(),
356 null /* internet-vpn-id */);
358 nvpnManager.addSubnetToVpn(vpnId, portIP.getSubnetId(), internetVpnId);
360 LOG.trace("NeutronPortChangeListener Add Subnet Gateway IP {} MAC {} Interface {} VPN {}",
361 ipValue, routerPort.getMacAddress(),
362 routerPort.getUuid().getValue(), vpnId.getValue());
364 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(ipVersion, routerId, true)) {
365 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}",
366 ipVersion, vpnId.getValue());
367 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
369 nvpnManager.addToNeutronRouterInterfacesMap(routerId, routerPort.getUuid().getValue());
370 jobCoordinator.enqueueJob(routerId.toString(), () -> {
371 nvpnNatManager.handleSubnetsForExternalRouter(routerId);
372 return Collections.emptyList();
374 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
376 String portInterfaceName = createOfPortInterface(routerPort, confTx);
377 createElanInterface(routerPort, portInterfaceName, confTx);
378 }), LOG, "Error creating ELAN interface for {}", routerPort);
380 LOG.error("Neutron network {} corresponding to router interface port {} for neutron router {}"
381 + " already associated to VPN {}", infNetworkId.getValue(), routerPort.getUuid().getValue(),
382 routerId.getValue(), existingVpnId.getValue());
387 private void handleRouterInterfaceRemoved(Port routerPort) {
388 if (routerPort.getDeviceId() != null) {
389 Uuid routerId = new Uuid(routerPort.getDeviceId());
390 Uuid infNetworkId = routerPort.getNetworkId();
391 elanService.removeKnownL3DmacAddress(routerPort.getMacAddress().getValue(), infNetworkId.getValue());
392 Uuid vpnId = ObjectUtils.defaultIfNull(neutronvpnUtils.getVpnForRouter(routerId, true),
394 List<FixedIps> portIps = routerPort.nonnullFixedIps();
395 boolean vpnInstanceInternetIpVersionRemoved = false;
396 Uuid vpnInstanceInternetUuid = null;
397 for (FixedIps portIP : portIps) {
398 // Internet VPN : flush InternetVPN first
399 Uuid subnetId = portIP.getSubnetId();
400 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
401 if (sn != null && sn.getInternetVpnId() != null) {
402 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sn, sn.getInternetVpnId())) {
403 vpnInstanceInternetIpVersionRemoved = true;
404 vpnInstanceInternetUuid = sn.getInternetVpnId();
406 nvpnManager.updateVpnInternetForSubnet(sn, sn.getInternetVpnId(), false);
409 /* Remove ping responder for router interfaces
410 * A router interface reference in a VPN will have to be removed before the host interface references
411 * for that subnet in the VPN are removed. This is to ensure that the FIB Entry of the router interface
412 * is not the last entry to be removed for that subnet in the VPN.
413 * If router interface FIB entry is the last to be removed for a subnet in a VPN , then all the host
414 * interface references in the vpn will already have been cleared, which will cause failures in
415 * cleanup of router interface flows*/
416 nvpnManager.deleteVpnInterface(routerPort.getUuid().getValue(),
417 null /* vpn-id */, null /* wrtConfigTxn*/);
418 final Uuid internetVpnId = vpnInstanceInternetUuid;
419 // update RouterInterfaces map
420 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
422 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
423 for (FixedIps portIP : portIps) {
424 Subnetmap sn = neutronvpnUtils.getSubnetmap(portIP.getSubnetId());
425 // router Port have either IPv4 or IPv6, never both
426 ipVersion = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
427 String ipValue = portIP.getIpAddress().stringValue();
428 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(), ipValue, confTx);
429 // NOTE: Please donot change the order of calls to removeSubnetFromVpn and
430 // and updateSubnetNodeWithFixedIP
431 nvpnManager.removeSubnetFromVpn(vpnId, portIP.getSubnetId(), internetVpnId);
432 nvpnManager.updateSubnetNodeWithFixedIp(portIP.getSubnetId(), null, null,
435 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, routerPort.getUuid().getValue());
436 deleteElanInterface(routerPort.getUuid().getValue(), confTx);
437 deleteOfPortInterface(routerPort, confTx);
438 jobCoordinator.enqueueJob(routerId.toString(), () -> {
439 nvpnNatManager.handleSubnetsForExternalRouter(routerId);
440 return Collections.emptyList();
442 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(ipVersion, routerId, false)) {
443 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}",
444 ipVersion, vpnId.getValue());
445 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
447 }), LOG, "Error handling interface removal");
448 if (vpnInstanceInternetIpVersionRemoved) {
449 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnInstanceInternetUuid.getValue(),
450 IpVersionChoice.IPV6, false);
451 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, vpnInstanceInternetUuid, false);
456 private void handleRouterGatewayUpdated(Port routerGwPort, boolean isRtrGwRemoved) {
457 Uuid routerId = new Uuid(routerGwPort.getDeviceId());
458 Uuid networkId = routerGwPort.getNetworkId();
459 Network network = neutronvpnUtils.getNeutronNetwork(networkId);
460 if (network == null) {
463 boolean isExternal = NeutronvpnUtils.getIsExternal(network);
465 Uuid vpnInternetId = neutronvpnUtils.getVpnForNetwork(networkId);
466 if (vpnInternetId != null) {
467 if (!isRtrGwRemoved) {
468 nvpnManager.updateVpnMaps(vpnInternetId, null, routerId, null, null);
470 List<Subnetmap> snList = neutronvpnUtils.getNeutronRouterSubnetMaps(routerId);
471 for (Subnetmap sn : snList) {
472 if (sn.getNetworkId() == networkId) {
475 if (NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()) != IpVersionChoice.IPV6) {
478 if (isRtrGwRemoved) {
479 nvpnManager.removeV6PrivateSubnetToExtNetwork(routerId, vpnInternetId, sn);
481 nvpnManager.addV6PrivateSubnetToExtNetwork(routerId, vpnInternetId, sn);
484 //Update Internet BGP-VPN
485 if (isRtrGwRemoved) {
486 nvpnManager.updateVpnMaps(vpnInternetId, null, null, null, null);
490 elanService.addKnownL3DmacAddress(routerGwPort.getMacAddress().getValue(), networkId.getValue());
492 Router router = neutronvpnUtils.getNeutronRouter(routerId);
493 if (router == null) {
494 LOG.warn("No router found for router GW port {} for router {}", routerGwPort.getUuid().getValue(),
495 routerId.getValue());
497 eventCallbacks.onAddOrUpdate(LogicalDatastoreType.CONFIGURATION,
498 neutronvpnUtils.getNeutronRouterIid(routerId), (unused, newRouter) -> {
499 setupGwMac(newRouter, routerGwPort, routerId);
500 return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
501 }, Duration.ofSeconds(3), iid -> {
502 LOG.error("GwPort {} added without Router", routerGwPort.getUuid().getValue());
506 setupGwMac(router, routerGwPort, routerId);
509 private void setupGwMac(Router router, Port routerGwPort, Uuid routerId) {
510 gwMacResolver.sendArpRequestsToExtGateways(router);
511 jobCoordinator.enqueueJob(routerId.toString(), () -> {
512 setExternalGwMac(routerGwPort, routerId);
513 return Collections.emptyList();
517 private void setExternalGwMac(Port routerGwPort, Uuid routerId) {
518 // During full-sync networking-odl syncs routers before ports. As such,
519 // the MAC of the router's gw port is not available to be set when the
520 // router is written. We catch that here.
521 InstanceIdentifier<Routers> routersId = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
522 Optional<Routers> optionalRouter = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId);
523 if (!optionalRouter.isPresent()) {
527 Routers extRouters = optionalRouter.get();
528 if (extRouters.getExtGwMacAddress() != null) {
532 RoutersBuilder builder = new RoutersBuilder(extRouters);
533 builder.setExtGwMacAddress(routerGwPort.getMacAddress().getValue());
534 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId, builder.build());
538 private String getPortHostId(final Port port) {
540 PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class);
541 if (portBinding != null) {
542 return portBinding.getHostId();
549 private Hostconfig getHostConfig(final Port port) {
550 String hostId = getPortHostId(port);
551 if (hostId == null) {
554 Optional<Hostconfig> hostConfig;
556 hostConfig = this.hostConfigCache.get(hostId);
557 } catch (ReadFailedException e) {
558 LOG.error("failed to read host config from host {}", hostId, e);
561 return hostConfig.orNull();
564 private boolean isPortBound(final Port port) {
565 String hostId = getPortHostId(port);
566 return hostId != null && !hostId.isEmpty();
569 private boolean isPortVnicTypeDirect(Port port) {
570 PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class);
571 if (portBinding == null || portBinding.getVnicType() == null) {
572 // By default, VNIC_TYPE is NORMAL
575 String vnicType = portBinding.getVnicType().trim().toLowerCase(Locale.getDefault());
576 return NeutronConstants.VNIC_TYPE_DIRECT.equals(vnicType);
579 private boolean isSupportedVnicTypeByHost(final Port port, final String vnicType) {
580 Hostconfig hostConfig = getHostConfig(port);
581 String supportStr = String.format("\"vnic_type\": \"%s\"", vnicType);
582 if (hostConfig != null && hostConfig.getConfig().contains(supportStr)) {
589 private Map<String, JsonElement> unmarshal(final String profile) {
590 if (null == profile) {
593 Gson gson = new Gson();
594 JsonObject jsonObject = gson.fromJson(profile, JsonObject.class);
595 Map<String, JsonElement> map = new HashMap<>();
596 for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
597 map.put(entry.getKey(), entry.getValue());
602 private boolean isPortTypeSwitchdev(final Port port) {
603 if (!isPortVnicTypeDirect(port)) {
607 PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class);
608 String profile = portBinding.getProfile();
609 if (profile == null || profile.isEmpty()) {
610 LOG.debug("Port {} has no binding:profile values", port.getUuid());
614 Map<String, JsonElement> mapProfile = unmarshal(profile);
615 JsonElement capabilities = mapProfile.get(NeutronConstants.BINDING_PROFILE_CAPABILITIES);
616 LOG.debug("Port {} capabilities: {}", port.getUuid(), capabilities);
617 if (capabilities == null || !capabilities.isJsonArray()) {
618 LOG.debug("binding profile capabilities not in array format: {}", capabilities);
622 JsonArray capabilitiesArray = capabilities.getAsJsonArray();
623 Gson gson = new Gson();
624 JsonElement switchdevElement = gson.fromJson(NeutronConstants.SWITCHDEV, JsonElement.class);
625 return capabilitiesArray.contains(switchdevElement);
629 private void handleNeutronPortCreated(final Port port) {
630 final String portName = port.getUuid().getValue();
631 final Uuid portId = port.getUuid();
632 final String networkId = port.getNetworkId().getValue();
633 final List<FixedIps> portIpAddrsList = port.nonnullFixedIps();
634 if (NeutronConstants.IS_ODL_DHCP_PORT.test(port)) {
637 if (!(NeutronUtils.isPortVnicTypeNormal(port)
638 || isPortTypeSwitchdev(port)
639 && isSupportedVnicTypeByHost(port, NeutronConstants.VNIC_TYPE_DIRECT))) {
640 for (FixedIps ip: portIpAddrsList) {
641 nvpnManager.updateSubnetmapNodeWithPorts(ip.getSubnetId(), null, portId);
643 LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;"
644 + "OF Port interfaces are not created", portName);
647 jobCoordinator.enqueueJob("PORT- " + portName, () -> {
648 // add direct port to subnetMaps config DS
649 // TODO: for direct port as well, operations should be carried out per subnet based on port IP
651 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
652 LOG.info("Of-port-interface creation for port {}", portName);
653 // Create of-port interface for this neutron port
654 String portInterfaceName = createOfPortInterface(port, tx);
655 LOG.debug("Creating ELAN Interface for port {}", portName);
656 createElanInterface(port, portInterfaceName, tx);
657 Set<Uuid> vpnIdList = new HashSet<>();
658 Set<Uuid> routerIds = new HashSet<>();
659 for (FixedIps ip: portIpAddrsList) {
660 Subnetmap subnetMap = nvpnManager.updateSubnetmapNodeWithPorts(ip.getSubnetId(), portId, null);
661 if (subnetMap != null && subnetMap.getInternetVpnId() != null) {
662 if (!vpnIdList.contains(subnetMap.getInternetVpnId())) {
663 vpnIdList.add(subnetMap.getInternetVpnId());
666 if (subnetMap != null && subnetMap.getVpnId() != null) {
667 // can't use NeutronvpnUtils.getVpnForNetwork to optimise here, because it gives BGPVPN id
668 // obtained subnetMaps belongs to one network => vpnId must be the same for each port Ip
669 Uuid vpnId = subnetMap.getVpnId();
671 vpnIdList.add(vpnId);
674 if (subnetMap != null && subnetMap.getRouterId() != null) {
675 routerIds.add(subnetMap.getRouterId());
678 if (!vpnIdList.isEmpty()) {
679 // create new vpn-interface for neutron port
680 LOG.debug("handleNeutronPortCreated: Adding VPN Interface for port {} from network {}", portName,
682 nvpnManager.createVpnInterface(vpnIdList, port, tx);
683 for (Uuid routerId : routerIds) {
684 nvpnManager.addToNeutronRouterInterfacesMap(routerId,port.getUuid().getValue());
688 ListenableFutures.addErrorLogging(future, LOG,
689 "handleNeutronPortCreated: Failed for port {} with networkId {}", portName, networkId);
690 return Collections.singletonList(future);
694 private void handleNeutronPortDeleted(final Port port) {
695 final String portName = port.getUuid().getValue();
696 final Uuid portId = port.getUuid();
697 final List<FixedIps> portIpsList = port.nonnullFixedIps();
698 if (!(NeutronUtils.isPortVnicTypeNormal(port) || isPortTypeSwitchdev(port))) {
699 for (FixedIps ip : portIpsList) {
700 // remove direct port from subnetMaps config DS
701 // TODO: for direct port as well, operations should be carried out per subnet based on port IP
702 nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), null, portId);
704 LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;"
705 + "Skipping OF Port interfaces removal", portName);
708 jobCoordinator.enqueueJob("PORT- " + portName, () -> {
709 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
712 Set<Uuid> routerIds = new HashSet<>();
713 Uuid internetVpnId = null;
714 for (FixedIps ip : portIpsList) {
715 Subnetmap subnetMap = nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), portId, null);
716 if (subnetMap == null) {
719 if (subnetMap.getVpnId() != null) {
720 // can't use NeutronvpnUtils.getVpnForNetwork to optimise here, because it gives BGPVPN id
721 // obtained subnetMaps belongs to one network => vpnId must be the same for each port Ip
722 vpnId = subnetMap.getVpnId();
724 if (subnetMap.getRouterId() != null) {
725 routerIds.add(subnetMap.getRouterId());
727 internetVpnId = subnetMap.getInternetVpnId();
729 if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(port.getDeviceOwner())
730 || NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(port.getDeviceOwner())) {
731 String ipAddress = ip.getIpAddress().stringValue();
733 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(), ipAddress, confTx);
735 if (internetVpnId != null) {
736 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
741 if (vpnId != null || internetVpnId != null) {
742 // remove vpn-interface for this neutron port
743 LOG.debug("removing VPN Interface for port {}", portName);
744 if (!routerIds.isEmpty()) {
745 for (Uuid routerId : routerIds) {
746 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, portName);
749 nvpnManager.deleteVpnInterface(portName, null /* vpn-id */, confTx);
751 // Remove of-port interface for this neutron port
752 // ELAN interface is also implicitly deleted as part of this operation
753 LOG.debug("Of-port-interface removal for port {}", portName);
754 deleteOfPortInterface(port, confTx);
755 //dissociate fixedIP from floatingIP if associated
756 nvpnManager.dissociatefixedIPFromFloatingIP(port.getUuid().getValue());
758 ListenableFutures.addErrorLogging(future, LOG,
759 "handleNeutronPortDeleted: Failed to update interface {} with networkId", portName,
760 port.getNetworkId().getValue());
761 return Collections.singletonList(future);
766 private void handleNeutronPortUpdated(final Port portoriginal, final Port portupdate) {
767 final List<FixedIps> portoriginalIps = portoriginal.getFixedIps();
768 final List<FixedIps> portupdateIps = portupdate.getFixedIps();
769 if (portoriginalIps == null || portoriginalIps.isEmpty()) {
770 handleNeutronPortCreated(portupdate);
774 if (portupdateIps == null || portupdateIps.isEmpty()) {
775 LOG.info("Ignoring portUpdate (fixed_ip removal) for port {} as this case is handled "
776 + "during subnet deletion event.", portupdate.getUuid().getValue());
780 if (NeutronConstants.IS_ODL_DHCP_PORT.test(portupdate)) {
784 jobCoordinator.enqueueJob("PORT- " + portupdate.getUuid().getValue(),
785 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
786 final List<Uuid> originalSnMapsIds = portoriginalIps.stream().map(FixedIps::getSubnetId)
787 .collect(Collectors.toList());
788 final List<Uuid> updateSnMapsIds = portupdateIps.stream().map(FixedIps::getSubnetId)
789 .collect(Collectors.toList());
790 Set<Uuid> originalRouterIds = new HashSet<>();
791 Set<Uuid> oldVpnIds = new HashSet<>();
792 for (Uuid snId: originalSnMapsIds) {
793 if (!updateSnMapsIds.remove(snId)) {
794 // snId was present in originalSnMapsIds, but not in updateSnMapsIds
795 Subnetmap subnetMapOld = nvpnManager.removePortsFromSubnetmapNode(snId, portoriginal.getUuid(),
797 if (subnetMapOld != null && subnetMapOld.getVpnId() != null) {
798 oldVpnIds.add(subnetMapOld.getVpnId());
800 if (subnetMapOld != null && subnetMapOld.getInternetVpnId() != null) {
801 oldVpnIds.add(subnetMapOld.getInternetVpnId());
803 if (subnetMapOld != null && subnetMapOld.getRouterId() != null) {
804 originalRouterIds.add(subnetMapOld.getRouterId());
808 Set<Uuid> newVpnIds = new HashSet<>();
809 Set<Uuid> newRouterIds = new HashSet<>();
810 for (Uuid snId: updateSnMapsIds) {
811 Subnetmap subnetMapNew = nvpnManager.updateSubnetmapNodeWithPorts(snId, portupdate.getUuid(), null);
812 if (subnetMapNew != null) {
813 if (subnetMapNew.getVpnId() != null) {
814 newVpnIds.add(subnetMapNew.getVpnId());
816 if (subnetMapNew.getInternetVpnId() != null) {
817 newVpnIds.add(subnetMapNew.getInternetVpnId());
819 if (subnetMapNew.getRouterId() != null) {
820 newRouterIds.add(subnetMapNew.getRouterId());
824 if (!oldVpnIds.isEmpty()) {
825 LOG.info("removing VPN Interface for port {}", portoriginal.getUuid().getValue());
826 if (!originalRouterIds.isEmpty()) {
827 for (Uuid routerId : originalRouterIds) {
828 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId,
829 portoriginal.getUuid().getValue());
832 nvpnManager.deleteVpnInterface(portoriginal.getUuid().getValue(),
833 null /* vpn-id */, confTx);
835 if (!newVpnIds.isEmpty()) {
836 LOG.info("Adding VPN Interface for port {}", portupdate.getUuid().getValue());
837 nvpnManager.createVpnInterface(newVpnIds, portupdate, confTx);
838 if (!newRouterIds.isEmpty()) {
839 for (Uuid routerId : newRouterIds) {
840 nvpnManager.addToNeutronRouterInterfacesMap(routerId,portupdate.getUuid().getValue());
848 private InterfaceAclBuilder handlePortSecurityUpdated(Port portOriginal,
849 Port portUpdated, boolean origSecurityEnabled, boolean updatedSecurityEnabled,
850 InterfaceBuilder interfaceBuilder) {
851 InterfaceAclBuilder interfaceAclBuilder = null;
852 if (origSecurityEnabled != updatedSecurityEnabled) {
853 interfaceAclBuilder = new InterfaceAclBuilder();
854 interfaceAclBuilder.setPortSecurityEnabled(updatedSecurityEnabled);
855 if (updatedSecurityEnabled) {
856 // Handle security group enabled
857 neutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, portUpdated);
859 // Handle security group disabled
860 interfaceAclBuilder.setSecurityGroups(new ArrayList<>());
861 interfaceAclBuilder.setAllowedAddressPairs(new ArrayList<>());
862 interfaceAclBuilder.setSubnetInfo(new ArrayList<>());
865 if (updatedSecurityEnabled) {
866 // handle SG add/delete delta
867 InterfaceAcl interfaceAcl = interfaceBuilder.augmentation(InterfaceAcl.class);
868 interfaceAclBuilder = new InterfaceAclBuilder(interfaceAcl);
869 interfaceAclBuilder.setSecurityGroups(
870 NeutronvpnUtils.getUpdatedSecurityGroups(interfaceAcl.getSecurityGroups(),
871 portOriginal.getSecurityGroups(), portUpdated.getSecurityGroups()));
872 List<AllowedAddressPairs> updatedAddressPairs = NeutronvpnUtils.getUpdatedAllowedAddressPairs(
873 interfaceAcl.getAllowedAddressPairs(), portOriginal.getAllowedAddressPairs(),
874 portUpdated.getAllowedAddressPairs());
875 interfaceAclBuilder.setAllowedAddressPairs(NeutronvpnUtils.getAllowedAddressPairsForFixedIps(
876 updatedAddressPairs, portOriginal.getMacAddress(), portOriginal.getFixedIps(),
877 portUpdated.getFixedIps()));
879 if (portOriginal.getFixedIps() != null
880 && !portOriginal.getFixedIps().equals(portUpdated.getFixedIps())) {
881 neutronvpnUtils.populateSubnetInfo(interfaceAclBuilder, portUpdated);
885 return interfaceAclBuilder;
888 private String createOfPortInterface(Port port, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
889 Interface inf = createInterface(port);
890 String infName = inf.getName();
892 InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(infName);
894 Optional<Interface> optionalInf =
895 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
896 interfaceIdentifier);
897 if (!optionalInf.isPresent()) {
898 wrtConfigTxn.put(interfaceIdentifier, inf);
900 LOG.warn("Interface {} is already present", infName);
902 } catch (ReadFailedException e) {
903 LOG.error("failed to create interface {}", infName, e);
908 private Interface createInterface(Port port) {
909 String interfaceName = port.getUuid().getValue();
910 IfL2vlan.L2vlanMode l2VlanMode = IfL2vlan.L2vlanMode.Trunk;
911 InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
912 IfL2vlanBuilder ifL2vlanBuilder = new IfL2vlanBuilder();
914 Network network = neutronvpnUtils.getNeutronNetwork(port.getNetworkId());
915 Boolean isVlanTransparent = network.isVlanTransparent();
916 if (isVlanTransparent != null && isVlanTransparent) {
917 l2VlanMode = IfL2vlan.L2vlanMode.Transparent;
919 PortIdToSubport portIdToSubport = neutronvpnUtils.getPortIdToSubport(port.getUuid());
920 if (portIdToSubport != null) {
921 l2VlanMode = IfL2vlan.L2vlanMode.TrunkMember;
922 ifL2vlanBuilder.setVlanId(new VlanId(portIdToSubport.getVlanId().intValue()));
923 String parentRefName = portIdToSubport.getTrunkPortId().getValue();
924 ParentRefsBuilder parentRefsBuilder = new ParentRefsBuilder().setParentInterface(parentRefName);
925 interfaceBuilder.addAugmentation(ParentRefs.class, parentRefsBuilder.build());
926 SplitHorizon splitHorizon =
927 new SplitHorizonBuilder().setOverrideSplitHorizonProtection(true).build();
928 interfaceBuilder.addAugmentation(SplitHorizon.class, splitHorizon);
932 ifL2vlanBuilder.setL2vlanMode(l2VlanMode);
934 interfaceBuilder.setEnabled(true).setName(interfaceName).setType(L2vlan.class)
935 .addAugmentation(IfL2vlan.class, ifL2vlanBuilder.build());
937 if (NeutronvpnUtils.getPortSecurityEnabled(port)) {
938 InterfaceAclBuilder interfaceAclBuilder = new InterfaceAclBuilder();
939 interfaceAclBuilder.setPortSecurityEnabled(true);
940 neutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, port);
941 interfaceBuilder.addAugmentation(InterfaceAcl.class, interfaceAclBuilder.build());
942 } else if (neutronvpnConfig.isLimitBumtrafficToDhcpserver() && NeutronvpnUtils.isDhcpServerPort(port)) {
943 interfaceBuilder.addAugmentation(InterfaceAcl.class, neutronvpnUtils.getDhcpInterfaceAcl(port));
945 return interfaceBuilder.build();
948 private void deleteOfPortInterface(Port port, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
949 String name = port.getUuid().getValue();
950 LOG.debug("Removing OFPort Interface {}", name);
951 InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
953 Optional<Interface> optionalInf =
954 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
955 interfaceIdentifier);
956 if (optionalInf.isPresent()) {
957 wrtConfigTxn.delete(interfaceIdentifier);
959 LOG.warn("deleteOfPortInterface: Interface {} is not present", name);
961 } catch (ReadFailedException e) {
962 LOG.error("deleteOfPortInterface: Failed to delete interface {}", name, e);
966 private void createElanInterface(Port port, String name,
967 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
968 String elanInstanceName = port.getNetworkId().getValue();
969 List<StaticMacEntries> staticMacEntries = NeutronvpnUtils.buildStaticMacEntry(port);
971 InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
972 .class, new ElanInterfaceKey(name)).build();
973 ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
974 .setName(name).setStaticMacEntries(staticMacEntries).withKey(new ElanInterfaceKey(name)).build();
975 wrtConfigTxn.put(id, elanInterface);
976 LOG.debug("Creating new ELan Interface {}", elanInterface);
979 private void deleteElanInterface(String name, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
980 InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
981 .class, new ElanInterfaceKey(name)).build();
982 wrtConfigTxn.delete(id);
985 // TODO Clean up the exception handling
986 @SuppressWarnings("checkstyle:IllegalCatch")
987 private void addToFloatingIpPortInfo(Uuid floatingIpId, Uuid floatingIpPortId, Uuid floatingIpPortSubnetId, String
988 floatingIpPortMacAddress) {
989 InstanceIdentifier id = NeutronvpnUtils.buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
991 FloatingIpIdToPortMappingBuilder floatingipIdToPortMacMappingBuilder = new
992 FloatingIpIdToPortMappingBuilder().withKey(new FloatingIpIdToPortMappingKey(floatingIpId))
993 .setFloatingIpId(floatingIpId).setFloatingIpPortId(floatingIpPortId)
994 .setFloatingIpPortSubnetId(floatingIpPortSubnetId)
995 .setFloatingIpPortMacAddress(floatingIpPortMacAddress);
996 LOG.debug("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
997 + " Port Info Config DS", floatingIpId.getValue(), floatingIpPortId.getValue());
998 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
999 floatingipIdToPortMacMappingBuilder.build());
1000 } catch (Exception e) {
1001 LOG.error("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
1002 + " Port Info Config DS failed", floatingIpId.getValue(), floatingIpPortId.getValue(), e);
1006 private Set<FixedIps> getFixedIpSet(List<FixedIps> fixedIps) {
1007 return fixedIps != null ? new HashSet<>(fixedIps) : Collections.emptySet();