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 if (!routerIds.isEmpty()) {
684 for (Uuid routerId : routerIds) {
685 nvpnManager.addToNeutronRouterInterfacesMap(routerId,port.getUuid().getValue());
690 ListenableFutures.addErrorLogging(future, LOG,
691 "handleNeutronPortCreated: Failed for port {} with networkId {}", portName, networkId);
692 return Collections.singletonList(future);
696 private void handleNeutronPortDeleted(final Port port) {
697 final String portName = port.getUuid().getValue();
698 final Uuid portId = port.getUuid();
699 final List<FixedIps> portIpsList = port.nonnullFixedIps();
700 if (!(NeutronUtils.isPortVnicTypeNormal(port) || isPortTypeSwitchdev(port))) {
701 for (FixedIps ip : portIpsList) {
702 // remove direct port from subnetMaps config DS
703 // TODO: for direct port as well, operations should be carried out per subnet based on port IP
704 nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), null, portId);
706 LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;"
707 + "Skipping OF Port interfaces removal", portName);
710 jobCoordinator.enqueueJob("PORT- " + portName, () -> {
711 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
714 Set<Uuid> routerIds = new HashSet<>();
715 Uuid internetVpnId = null;
716 for (FixedIps ip : portIpsList) {
717 Subnetmap subnetMap = nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), portId, null);
718 if (subnetMap == null) {
721 if (subnetMap.getVpnId() != null) {
722 // can't use NeutronvpnUtils.getVpnForNetwork to optimise here, because it gives BGPVPN id
723 // obtained subnetMaps belongs to one network => vpnId must be the same for each port Ip
724 vpnId = subnetMap.getVpnId();
726 if (subnetMap.getRouterId() != null) {
727 routerIds.add(subnetMap.getRouterId());
729 internetVpnId = subnetMap.getInternetVpnId();
731 if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(port.getDeviceOwner())
732 || NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(port.getDeviceOwner())) {
733 String ipAddress = ip.getIpAddress().stringValue();
735 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(), ipAddress, confTx);
737 if (internetVpnId != null) {
738 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
743 if (vpnId != null || internetVpnId != null) {
744 // remove vpn-interface for this neutron port
745 LOG.debug("removing VPN Interface for port {}", portName);
746 if (!routerIds.isEmpty()) {
747 for (Uuid routerId : routerIds) {
748 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, portName);
751 nvpnManager.deleteVpnInterface(portName, null /* vpn-id */, confTx);
753 // Remove of-port interface for this neutron port
754 // ELAN interface is also implicitly deleted as part of this operation
755 LOG.debug("Of-port-interface removal for port {}", portName);
756 deleteOfPortInterface(port, confTx);
757 //dissociate fixedIP from floatingIP if associated
758 nvpnManager.dissociatefixedIPFromFloatingIP(port.getUuid().getValue());
760 ListenableFutures.addErrorLogging(future, LOG,
761 "handleNeutronPortDeleted: Failed to update interface {} with networkId", portName,
762 port.getNetworkId().getValue());
763 return Collections.singletonList(future);
768 private void handleNeutronPortUpdated(final Port portoriginal, final Port portupdate) {
769 final List<FixedIps> portoriginalIps = portoriginal.getFixedIps();
770 final List<FixedIps> portupdateIps = portupdate.getFixedIps();
771 if (portoriginalIps == null || portoriginalIps.isEmpty()) {
772 handleNeutronPortCreated(portupdate);
776 if (portupdateIps == null || portupdateIps.isEmpty()) {
777 LOG.info("Ignoring portUpdate (fixed_ip removal) for port {} as this case is handled "
778 + "during subnet deletion event.", portupdate.getUuid().getValue());
782 if (NeutronConstants.IS_ODL_DHCP_PORT.test(portupdate)) {
786 jobCoordinator.enqueueJob("PORT- " + portupdate.getUuid().getValue(),
787 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
788 final List<Uuid> originalSnMapsIds = portoriginalIps.stream().map(FixedIps::getSubnetId)
789 .collect(Collectors.toList());
790 final List<Uuid> updateSnMapsIds = portupdateIps.stream().map(FixedIps::getSubnetId)
791 .collect(Collectors.toList());
792 Set<Uuid> originalRouterIds = new HashSet<>();
793 Set<Uuid> oldVpnIds = new HashSet<>();
794 for (Uuid snId: originalSnMapsIds) {
795 if (!updateSnMapsIds.remove(snId)) {
796 // snId was present in originalSnMapsIds, but not in updateSnMapsIds
797 Subnetmap subnetMapOld = nvpnManager.removePortsFromSubnetmapNode(snId, portoriginal.getUuid(),
799 if (subnetMapOld != null && subnetMapOld.getVpnId() != null) {
800 oldVpnIds.add(subnetMapOld.getVpnId());
802 if (subnetMapOld != null && subnetMapOld.getInternetVpnId() != null) {
803 oldVpnIds.add(subnetMapOld.getInternetVpnId());
805 if (subnetMapOld != null && subnetMapOld.getRouterId() != null) {
806 originalRouterIds.add(subnetMapOld.getRouterId());
810 Set<Uuid> newVpnIds = new HashSet<>();
811 Set<Uuid> newRouterIds = new HashSet<>();
812 for (Uuid snId: updateSnMapsIds) {
813 Subnetmap subnetMapNew = nvpnManager.updateSubnetmapNodeWithPorts(snId, portupdate.getUuid(), null);
814 if (subnetMapNew != null) {
815 if (subnetMapNew.getVpnId() != null) {
816 newVpnIds.add(subnetMapNew.getVpnId());
818 if (subnetMapNew.getInternetVpnId() != null) {
819 newVpnIds.add(subnetMapNew.getInternetVpnId());
821 if (subnetMapNew.getRouterId() != null) {
822 newRouterIds.add(subnetMapNew.getRouterId());
826 if (!oldVpnIds.isEmpty()) {
827 LOG.info("removing VPN Interface for port {}", portoriginal.getUuid().getValue());
828 if (!originalRouterIds.isEmpty()) {
829 for (Uuid routerId : originalRouterIds) {
830 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId,
831 portoriginal.getUuid().getValue());
834 nvpnManager.deleteVpnInterface(portoriginal.getUuid().getValue(),
835 null /* vpn-id */, confTx);
837 if (!newVpnIds.isEmpty()) {
838 LOG.info("Adding VPN Interface for port {}", portupdate.getUuid().getValue());
839 nvpnManager.createVpnInterface(newVpnIds, portupdate, confTx);
840 if (!newRouterIds.isEmpty()) {
841 for (Uuid routerId : newRouterIds) {
842 nvpnManager.addToNeutronRouterInterfacesMap(routerId,portupdate.getUuid().getValue());
850 private InterfaceAclBuilder handlePortSecurityUpdated(Port portOriginal,
851 Port portUpdated, boolean origSecurityEnabled, boolean updatedSecurityEnabled,
852 InterfaceBuilder interfaceBuilder) {
853 InterfaceAclBuilder interfaceAclBuilder = null;
854 if (origSecurityEnabled != updatedSecurityEnabled) {
855 interfaceAclBuilder = new InterfaceAclBuilder();
856 interfaceAclBuilder.setPortSecurityEnabled(updatedSecurityEnabled);
857 if (updatedSecurityEnabled) {
858 // Handle security group enabled
859 neutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, portUpdated);
861 // Handle security group disabled
862 interfaceAclBuilder.setSecurityGroups(new ArrayList<>());
863 interfaceAclBuilder.setAllowedAddressPairs(new ArrayList<>());
864 interfaceAclBuilder.setSubnetInfo(new ArrayList<>());
867 if (updatedSecurityEnabled) {
868 // handle SG add/delete delta
869 InterfaceAcl interfaceAcl = interfaceBuilder.augmentation(InterfaceAcl.class);
870 interfaceAclBuilder = new InterfaceAclBuilder(interfaceAcl);
871 interfaceAclBuilder.setSecurityGroups(
872 NeutronvpnUtils.getUpdatedSecurityGroups(interfaceAcl.getSecurityGroups(),
873 portOriginal.getSecurityGroups(), portUpdated.getSecurityGroups()));
874 List<AllowedAddressPairs> updatedAddressPairs = NeutronvpnUtils.getUpdatedAllowedAddressPairs(
875 interfaceAcl.getAllowedAddressPairs(), portOriginal.getAllowedAddressPairs(),
876 portUpdated.getAllowedAddressPairs());
877 interfaceAclBuilder.setAllowedAddressPairs(NeutronvpnUtils.getAllowedAddressPairsForFixedIps(
878 updatedAddressPairs, portOriginal.getMacAddress(), portOriginal.getFixedIps(),
879 portUpdated.getFixedIps()));
881 if (portOriginal.getFixedIps() != null
882 && !portOriginal.getFixedIps().equals(portUpdated.getFixedIps())) {
883 neutronvpnUtils.populateSubnetInfo(interfaceAclBuilder, portUpdated);
887 return interfaceAclBuilder;
890 private String createOfPortInterface(Port port, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
891 Interface inf = createInterface(port);
892 String infName = inf.getName();
894 InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(infName);
896 Optional<Interface> optionalInf =
897 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
898 interfaceIdentifier);
899 if (!optionalInf.isPresent()) {
900 wrtConfigTxn.put(interfaceIdentifier, inf);
902 LOG.warn("Interface {} is already present", infName);
904 } catch (ReadFailedException e) {
905 LOG.error("failed to create interface {}", infName, e);
910 private Interface createInterface(Port port) {
911 String interfaceName = port.getUuid().getValue();
912 IfL2vlan.L2vlanMode l2VlanMode = IfL2vlan.L2vlanMode.Trunk;
913 InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
914 IfL2vlanBuilder ifL2vlanBuilder = new IfL2vlanBuilder();
916 Network network = neutronvpnUtils.getNeutronNetwork(port.getNetworkId());
917 Boolean isVlanTransparent = network.isVlanTransparent();
918 if (isVlanTransparent != null && isVlanTransparent) {
919 l2VlanMode = IfL2vlan.L2vlanMode.Transparent;
921 PortIdToSubport portIdToSubport = neutronvpnUtils.getPortIdToSubport(port.getUuid());
922 if (portIdToSubport != null) {
923 l2VlanMode = IfL2vlan.L2vlanMode.TrunkMember;
924 ifL2vlanBuilder.setVlanId(new VlanId(portIdToSubport.getVlanId().intValue()));
925 String parentRefName = portIdToSubport.getTrunkPortId().getValue();
926 ParentRefsBuilder parentRefsBuilder = new ParentRefsBuilder().setParentInterface(parentRefName);
927 interfaceBuilder.addAugmentation(ParentRefs.class, parentRefsBuilder.build());
928 SplitHorizon splitHorizon =
929 new SplitHorizonBuilder().setOverrideSplitHorizonProtection(true).build();
930 interfaceBuilder.addAugmentation(SplitHorizon.class, splitHorizon);
934 ifL2vlanBuilder.setL2vlanMode(l2VlanMode);
936 interfaceBuilder.setEnabled(true).setName(interfaceName).setType(L2vlan.class)
937 .addAugmentation(IfL2vlan.class, ifL2vlanBuilder.build());
939 if (NeutronvpnUtils.getPortSecurityEnabled(port)) {
940 InterfaceAclBuilder interfaceAclBuilder = new InterfaceAclBuilder();
941 interfaceAclBuilder.setPortSecurityEnabled(true);
942 neutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, port);
943 interfaceBuilder.addAugmentation(InterfaceAcl.class, interfaceAclBuilder.build());
944 } else if (neutronvpnConfig.isLimitBumtrafficToDhcpserver() && NeutronvpnUtils.isDhcpServerPort(port)) {
945 interfaceBuilder.addAugmentation(InterfaceAcl.class, neutronvpnUtils.getDhcpInterfaceAcl(port));
947 return interfaceBuilder.build();
950 private void deleteOfPortInterface(Port port, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
951 String name = port.getUuid().getValue();
952 LOG.debug("Removing OFPort Interface {}", name);
953 InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
955 Optional<Interface> optionalInf =
956 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
957 interfaceIdentifier);
958 if (optionalInf.isPresent()) {
959 wrtConfigTxn.delete(interfaceIdentifier);
961 LOG.warn("deleteOfPortInterface: Interface {} is not present", name);
963 } catch (ReadFailedException e) {
964 LOG.error("deleteOfPortInterface: Failed to delete interface {}", name, e);
968 private void createElanInterface(Port port, String name,
969 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
970 String elanInstanceName = port.getNetworkId().getValue();
971 List<StaticMacEntries> staticMacEntries = NeutronvpnUtils.buildStaticMacEntry(port);
973 InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
974 .class, new ElanInterfaceKey(name)).build();
975 ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
976 .setName(name).setStaticMacEntries(staticMacEntries).withKey(new ElanInterfaceKey(name)).build();
977 wrtConfigTxn.put(id, elanInterface);
978 LOG.debug("Creating new ELan Interface {}", elanInterface);
981 private void deleteElanInterface(String name, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
982 InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
983 .class, new ElanInterfaceKey(name)).build();
984 wrtConfigTxn.delete(id);
987 // TODO Clean up the exception handling
988 @SuppressWarnings("checkstyle:IllegalCatch")
989 private void addToFloatingIpPortInfo(Uuid floatingIpId, Uuid floatingIpPortId, Uuid floatingIpPortSubnetId, String
990 floatingIpPortMacAddress) {
991 InstanceIdentifier id = NeutronvpnUtils.buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
993 FloatingIpIdToPortMappingBuilder floatingipIdToPortMacMappingBuilder = new
994 FloatingIpIdToPortMappingBuilder().withKey(new FloatingIpIdToPortMappingKey(floatingIpId))
995 .setFloatingIpId(floatingIpId).setFloatingIpPortId(floatingIpPortId)
996 .setFloatingIpPortSubnetId(floatingIpPortSubnetId)
997 .setFloatingIpPortMacAddress(floatingIpPortMacAddress);
998 LOG.debug("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
999 + " Port Info Config DS", floatingIpId.getValue(), floatingIpPortId.getValue());
1000 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
1001 floatingipIdToPortMacMappingBuilder.build());
1002 } catch (Exception e) {
1003 LOG.error("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
1004 + " Port Info Config DS failed", floatingIpId.getValue(), floatingIpPortId.getValue(), e);
1008 private Set<FixedIps> getFixedIpSet(List<FixedIps> fixedIps) {
1009 return fixedIps != null ? new HashSet<>(fixedIps) : Collections.emptySet();