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 // update RouterInterfaces map
419 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
421 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
422 for (FixedIps portIP : portIps) {
423 Subnetmap sn = neutronvpnUtils.getSubnetmap(portIP.getSubnetId());
425 LOG.error("Subnetmap for subnet {} not found", portIP.getSubnetId().getValue());
428 // router Port have either IPv4 or IPv6, never both
429 ipVersion = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
430 String ipValue = portIP.getIpAddress().stringValue();
431 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(), ipValue, confTx);
432 // NOTE: Please donot change the order of calls to removeSubnetFromVpn and
433 // and updateSubnetNodeWithFixedIP
434 nvpnManager.removeSubnetFromVpn(vpnId, sn, sn.getInternetVpnId());
435 nvpnManager.updateSubnetNodeWithFixedIp(portIP.getSubnetId(), null, null,
438 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, routerPort.getUuid().getValue());
439 deleteElanInterface(routerPort.getUuid().getValue(), confTx);
440 deleteOfPortInterface(routerPort, confTx);
441 jobCoordinator.enqueueJob(routerId.toString(), () -> {
442 nvpnNatManager.handleSubnetsForExternalRouter(routerId);
443 return Collections.emptyList();
445 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(ipVersion, routerId, false)) {
446 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}",
447 ipVersion, vpnId.getValue());
448 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
450 }), LOG, "Error handling interface removal");
451 if (vpnInstanceInternetIpVersionRemoved) {
452 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnInstanceInternetUuid.getValue(),
453 IpVersionChoice.IPV6, false);
454 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, vpnInstanceInternetUuid, false);
459 private void handleRouterGatewayUpdated(Port routerGwPort, boolean isRtrGwRemoved) {
460 Uuid routerId = new Uuid(routerGwPort.getDeviceId());
461 Uuid networkId = routerGwPort.getNetworkId();
462 Network network = neutronvpnUtils.getNeutronNetwork(networkId);
463 if (network == null) {
466 boolean isExternal = NeutronvpnUtils.getIsExternal(network);
468 Uuid vpnInternetId = neutronvpnUtils.getVpnForNetwork(networkId);
469 if (vpnInternetId != null) {
470 if (!isRtrGwRemoved) {
471 nvpnManager.updateVpnMaps(vpnInternetId, null, routerId, null, null);
473 List<Subnetmap> snList = neutronvpnUtils.getNeutronRouterSubnetMaps(routerId);
474 for (Subnetmap sn : snList) {
475 if (sn.getNetworkId() == networkId) {
478 if (NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()) != IpVersionChoice.IPV6) {
481 if (isRtrGwRemoved) {
482 nvpnManager.removeV6PrivateSubnetToExtNetwork(routerId, vpnInternetId, sn);
484 nvpnManager.addV6PrivateSubnetToExtNetwork(routerId, vpnInternetId, sn);
487 //Update Internet BGP-VPN
488 if (isRtrGwRemoved) {
489 nvpnManager.updateVpnMaps(vpnInternetId, null, null, null, null);
493 elanService.addKnownL3DmacAddress(routerGwPort.getMacAddress().getValue(), networkId.getValue());
495 Router router = neutronvpnUtils.getNeutronRouter(routerId);
496 if (router == null) {
497 LOG.warn("No router found for router GW port {} for router {}", routerGwPort.getUuid().getValue(),
498 routerId.getValue());
500 eventCallbacks.onAddOrUpdate(LogicalDatastoreType.CONFIGURATION,
501 neutronvpnUtils.getNeutronRouterIid(routerId), (unused, newRouter) -> {
502 setupGwMac(newRouter, routerGwPort, routerId);
503 return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
504 }, Duration.ofSeconds(3), iid -> {
505 LOG.error("GwPort {} added without Router", routerGwPort.getUuid().getValue());
509 setupGwMac(router, routerGwPort, routerId);
512 private void setupGwMac(Router router, Port routerGwPort, Uuid routerId) {
513 gwMacResolver.sendArpRequestsToExtGateways(router);
514 jobCoordinator.enqueueJob(routerId.toString(), () -> {
515 setExternalGwMac(routerGwPort, routerId);
516 return Collections.emptyList();
520 private void setExternalGwMac(Port routerGwPort, Uuid routerId) {
521 // During full-sync networking-odl syncs routers before ports. As such,
522 // the MAC of the router's gw port is not available to be set when the
523 // router is written. We catch that here.
524 InstanceIdentifier<Routers> routersId = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
525 Optional<Routers> optionalRouter = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId);
526 if (!optionalRouter.isPresent()) {
530 Routers extRouters = optionalRouter.get();
531 if (extRouters.getExtGwMacAddress() != null) {
535 RoutersBuilder builder = new RoutersBuilder(extRouters);
536 builder.setExtGwMacAddress(routerGwPort.getMacAddress().getValue());
537 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId, builder.build());
541 private String getPortHostId(final Port port) {
543 PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class);
544 if (portBinding != null) {
545 return portBinding.getHostId();
552 private Hostconfig getHostConfig(final Port port) {
553 String hostId = getPortHostId(port);
554 if (hostId == null) {
557 Optional<Hostconfig> hostConfig;
559 hostConfig = this.hostConfigCache.get(hostId);
560 } catch (ReadFailedException e) {
561 LOG.error("failed to read host config from host {}", hostId, e);
564 return hostConfig.orNull();
567 private boolean isPortBound(final Port port) {
568 String hostId = getPortHostId(port);
569 return hostId != null && !hostId.isEmpty();
572 private boolean isPortVnicTypeDirect(Port port) {
573 PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class);
574 if (portBinding == null || portBinding.getVnicType() == null) {
575 // By default, VNIC_TYPE is NORMAL
578 String vnicType = portBinding.getVnicType().trim().toLowerCase(Locale.getDefault());
579 return NeutronConstants.VNIC_TYPE_DIRECT.equals(vnicType);
582 private boolean isSupportedVnicTypeByHost(final Port port, final String vnicType) {
583 Hostconfig hostConfig = getHostConfig(port);
584 String supportStr = String.format("\"vnic_type\": \"%s\"", vnicType);
585 if (hostConfig != null && hostConfig.getConfig().contains(supportStr)) {
592 private Map<String, JsonElement> unmarshal(final String profile) {
593 if (null == profile) {
596 Gson gson = new Gson();
597 JsonObject jsonObject = gson.fromJson(profile, JsonObject.class);
598 Map<String, JsonElement> map = new HashMap<>();
599 for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
600 map.put(entry.getKey(), entry.getValue());
605 private boolean isPortTypeSwitchdev(final Port port) {
606 if (!isPortVnicTypeDirect(port)) {
610 PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class);
611 String profile = portBinding.getProfile();
612 if (profile == null || profile.isEmpty()) {
613 LOG.debug("Port {} has no binding:profile values", port.getUuid());
617 Map<String, JsonElement> mapProfile = unmarshal(profile);
618 JsonElement capabilities = mapProfile.get(NeutronConstants.BINDING_PROFILE_CAPABILITIES);
619 LOG.debug("Port {} capabilities: {}", port.getUuid(), capabilities);
620 if (capabilities == null || !capabilities.isJsonArray()) {
621 LOG.debug("binding profile capabilities not in array format: {}", capabilities);
625 JsonArray capabilitiesArray = capabilities.getAsJsonArray();
626 Gson gson = new Gson();
627 JsonElement switchdevElement = gson.fromJson(NeutronConstants.SWITCHDEV, JsonElement.class);
628 return capabilitiesArray.contains(switchdevElement);
632 private void handleNeutronPortCreated(final Port port) {
633 final String portName = port.getUuid().getValue();
634 final Uuid portId = port.getUuid();
635 final String networkId = port.getNetworkId().getValue();
636 final List<FixedIps> portIpAddrsList = port.nonnullFixedIps();
637 if (NeutronConstants.IS_ODL_DHCP_PORT.test(port)) {
640 if (!(NeutronUtils.isPortVnicTypeNormal(port)
641 || isPortTypeSwitchdev(port)
642 && isSupportedVnicTypeByHost(port, NeutronConstants.VNIC_TYPE_DIRECT))) {
643 for (FixedIps ip: portIpAddrsList) {
644 nvpnManager.updateSubnetmapNodeWithPorts(ip.getSubnetId(), null, portId);
646 LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;"
647 + "OF Port interfaces are not created", portName);
650 jobCoordinator.enqueueJob("PORT- " + portName, () -> {
651 // add direct port to subnetMaps config DS
652 // TODO: for direct port as well, operations should be carried out per subnet based on port IP
654 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
655 LOG.info("Of-port-interface creation for port {}", portName);
656 // Create of-port interface for this neutron port
657 String portInterfaceName = createOfPortInterface(port, tx);
658 LOG.debug("Creating ELAN Interface for port {}", portName);
659 createElanInterface(port, portInterfaceName, tx);
660 Set<Uuid> vpnIdList = new HashSet<>();
661 Set<Uuid> routerIds = new HashSet<>();
662 for (FixedIps ip: portIpAddrsList) {
663 Subnetmap subnetMap = nvpnManager.updateSubnetmapNodeWithPorts(ip.getSubnetId(), portId, null);
664 if (subnetMap != null && subnetMap.getInternetVpnId() != null) {
665 if (!vpnIdList.contains(subnetMap.getInternetVpnId())) {
666 vpnIdList.add(subnetMap.getInternetVpnId());
669 if (subnetMap != null && subnetMap.getVpnId() != null) {
670 // can't use NeutronvpnUtils.getVpnForNetwork to optimise here, because it gives BGPVPN id
671 // obtained subnetMaps belongs to one network => vpnId must be the same for each port Ip
672 Uuid vpnId = subnetMap.getVpnId();
674 vpnIdList.add(vpnId);
677 if (subnetMap != null && subnetMap.getRouterId() != null) {
678 routerIds.add(subnetMap.getRouterId());
681 if (!vpnIdList.isEmpty()) {
682 // create new vpn-interface for neutron port
683 LOG.debug("handleNeutronPortCreated: Adding VPN Interface for port {} from network {}", portName,
685 nvpnManager.createVpnInterface(vpnIdList, port, tx);
686 for (Uuid routerId : routerIds) {
687 nvpnManager.addToNeutronRouterInterfacesMap(routerId,port.getUuid().getValue());
691 ListenableFutures.addErrorLogging(future, LOG,
692 "handleNeutronPortCreated: Failed for port {} with networkId {}", portName, networkId);
693 return Collections.singletonList(future);
697 private void handleNeutronPortDeleted(final Port port) {
698 final String portName = port.getUuid().getValue();
699 final Uuid portId = port.getUuid();
700 final List<FixedIps> portIpsList = port.nonnullFixedIps();
701 if (!(NeutronUtils.isPortVnicTypeNormal(port) || isPortTypeSwitchdev(port))) {
702 for (FixedIps ip : portIpsList) {
703 // remove direct port from subnetMaps config DS
704 // TODO: for direct port as well, operations should be carried out per subnet based on port IP
705 nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), null, portId);
707 LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;"
708 + "Skipping OF Port interfaces removal", portName);
711 jobCoordinator.enqueueJob("PORT- " + portName, () -> {
712 ListenableFuture<Void> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
715 Set<Uuid> routerIds = new HashSet<>();
716 Uuid internetVpnId = null;
717 for (FixedIps ip : portIpsList) {
718 Subnetmap subnetMap = nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), portId, null);
719 if (subnetMap == null) {
722 if (subnetMap.getVpnId() != null) {
723 // can't use NeutronvpnUtils.getVpnForNetwork to optimise here, because it gives BGPVPN id
724 // obtained subnetMaps belongs to one network => vpnId must be the same for each port Ip
725 vpnId = subnetMap.getVpnId();
727 if (subnetMap.getRouterId() != null) {
728 routerIds.add(subnetMap.getRouterId());
730 internetVpnId = subnetMap.getInternetVpnId();
732 if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(port.getDeviceOwner())
733 || NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(port.getDeviceOwner())) {
734 String ipAddress = ip.getIpAddress().stringValue();
736 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(), ipAddress, confTx);
738 if (internetVpnId != null) {
739 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
744 if (vpnId != null || internetVpnId != null) {
745 // remove vpn-interface for this neutron port
746 LOG.debug("removing VPN Interface for port {}", portName);
747 if (!routerIds.isEmpty()) {
748 for (Uuid routerId : routerIds) {
749 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, portName);
752 nvpnManager.deleteVpnInterface(portName, null /* vpn-id */, confTx);
754 // Remove of-port interface for this neutron port
755 // ELAN interface is also implicitly deleted as part of this operation
756 LOG.debug("Of-port-interface removal for port {}", portName);
757 deleteOfPortInterface(port, confTx);
758 //dissociate fixedIP from floatingIP if associated
759 nvpnManager.dissociatefixedIPFromFloatingIP(port.getUuid().getValue());
761 ListenableFutures.addErrorLogging(future, LOG,
762 "handleNeutronPortDeleted: Failed to update interface {} with networkId", portName,
763 port.getNetworkId().getValue());
764 return Collections.singletonList(future);
769 private void handleNeutronPortUpdated(final Port portoriginal, final Port portupdate) {
770 final List<FixedIps> portoriginalIps = portoriginal.getFixedIps();
771 final List<FixedIps> portupdateIps = portupdate.getFixedIps();
772 if (portoriginalIps == null || portoriginalIps.isEmpty()) {
773 handleNeutronPortCreated(portupdate);
777 if (portupdateIps == null || portupdateIps.isEmpty()) {
778 LOG.info("Ignoring portUpdate (fixed_ip removal) for port {} as this case is handled "
779 + "during subnet deletion event.", portupdate.getUuid().getValue());
783 if (NeutronConstants.IS_ODL_DHCP_PORT.test(portupdate)) {
787 jobCoordinator.enqueueJob("PORT- " + portupdate.getUuid().getValue(),
788 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
789 final List<Uuid> originalSnMapsIds = portoriginalIps.stream().map(FixedIps::getSubnetId)
790 .collect(Collectors.toList());
791 final List<Uuid> updateSnMapsIds = portupdateIps.stream().map(FixedIps::getSubnetId)
792 .collect(Collectors.toList());
793 Set<Uuid> originalRouterIds = new HashSet<>();
794 Set<Uuid> oldVpnIds = new HashSet<>();
795 for (Uuid snId: originalSnMapsIds) {
796 if (!updateSnMapsIds.remove(snId)) {
797 // snId was present in originalSnMapsIds, but not in updateSnMapsIds
798 Subnetmap subnetMapOld = nvpnManager.removePortsFromSubnetmapNode(snId, portoriginal.getUuid(),
800 if (subnetMapOld != null && subnetMapOld.getVpnId() != null) {
801 oldVpnIds.add(subnetMapOld.getVpnId());
803 if (subnetMapOld != null && subnetMapOld.getInternetVpnId() != null) {
804 oldVpnIds.add(subnetMapOld.getInternetVpnId());
806 if (subnetMapOld != null && subnetMapOld.getRouterId() != null) {
807 originalRouterIds.add(subnetMapOld.getRouterId());
811 Set<Uuid> newVpnIds = new HashSet<>();
812 Set<Uuid> newRouterIds = new HashSet<>();
813 for (Uuid snId: updateSnMapsIds) {
814 Subnetmap subnetMapNew = nvpnManager.updateSubnetmapNodeWithPorts(snId, portupdate.getUuid(), null);
815 if (subnetMapNew != null) {
816 if (subnetMapNew.getVpnId() != null) {
817 newVpnIds.add(subnetMapNew.getVpnId());
819 if (subnetMapNew.getInternetVpnId() != null) {
820 newVpnIds.add(subnetMapNew.getInternetVpnId());
822 if (subnetMapNew.getRouterId() != null) {
823 newRouterIds.add(subnetMapNew.getRouterId());
827 if (!oldVpnIds.isEmpty()) {
828 LOG.info("removing VPN Interface for port {}", portoriginal.getUuid().getValue());
829 if (!originalRouterIds.isEmpty()) {
830 for (Uuid routerId : originalRouterIds) {
831 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId,
832 portoriginal.getUuid().getValue());
835 nvpnManager.deleteVpnInterface(portoriginal.getUuid().getValue(),
836 null /* vpn-id */, confTx);
838 if (!newVpnIds.isEmpty()) {
839 LOG.info("Adding VPN Interface for port {}", portupdate.getUuid().getValue());
840 nvpnManager.createVpnInterface(newVpnIds, portupdate, confTx);
841 if (!newRouterIds.isEmpty()) {
842 for (Uuid routerId : newRouterIds) {
843 nvpnManager.addToNeutronRouterInterfacesMap(routerId,portupdate.getUuid().getValue());
851 private InterfaceAclBuilder handlePortSecurityUpdated(Port portOriginal,
852 Port portUpdated, boolean origSecurityEnabled, boolean updatedSecurityEnabled,
853 InterfaceBuilder interfaceBuilder) {
854 InterfaceAclBuilder interfaceAclBuilder = null;
855 if (origSecurityEnabled != updatedSecurityEnabled) {
856 interfaceAclBuilder = new InterfaceAclBuilder();
857 interfaceAclBuilder.setPortSecurityEnabled(updatedSecurityEnabled);
858 if (updatedSecurityEnabled) {
859 // Handle security group enabled
860 neutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, portUpdated);
862 // Handle security group disabled
863 interfaceAclBuilder.setSecurityGroups(new ArrayList<>());
864 interfaceAclBuilder.setAllowedAddressPairs(new ArrayList<>());
865 interfaceAclBuilder.setSubnetInfo(new ArrayList<>());
868 if (updatedSecurityEnabled) {
869 // handle SG add/delete delta
870 InterfaceAcl interfaceAcl = interfaceBuilder.augmentation(InterfaceAcl.class);
871 interfaceAclBuilder = new InterfaceAclBuilder(interfaceAcl);
872 interfaceAclBuilder.setSecurityGroups(
873 NeutronvpnUtils.getUpdatedSecurityGroups(interfaceAcl.getSecurityGroups(),
874 portOriginal.getSecurityGroups(), portUpdated.getSecurityGroups()));
875 List<AllowedAddressPairs> updatedAddressPairs = NeutronvpnUtils.getUpdatedAllowedAddressPairs(
876 interfaceAcl.getAllowedAddressPairs(), portOriginal.getAllowedAddressPairs(),
877 portUpdated.getAllowedAddressPairs());
878 interfaceAclBuilder.setAllowedAddressPairs(NeutronvpnUtils.getAllowedAddressPairsForFixedIps(
879 updatedAddressPairs, portOriginal.getMacAddress(), portOriginal.getFixedIps(),
880 portUpdated.getFixedIps()));
882 if (portOriginal.getFixedIps() != null
883 && !portOriginal.getFixedIps().equals(portUpdated.getFixedIps())) {
884 neutronvpnUtils.populateSubnetInfo(interfaceAclBuilder, portUpdated);
888 return interfaceAclBuilder;
891 private String createOfPortInterface(Port port, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
892 Interface inf = createInterface(port);
893 String infName = inf.getName();
895 InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(infName);
897 Optional<Interface> optionalInf =
898 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
899 interfaceIdentifier);
900 if (!optionalInf.isPresent()) {
901 wrtConfigTxn.put(interfaceIdentifier, inf);
902 } else if (isInterfaceUpdated(inf, optionalInf.get())) {
904 Case where an update DTCN wasn't received by this class due to node going down
905 upon cluster reboot or any other unknown reason
906 In such a case, updates contained in the missed DTCN won't be processed and have to be handled
908 Update of subports (vlanId, splithorizon tag) is handled here
909 Update of portSecurity (PortSecurityEnabled, SecurityGroups, AllowedAddressPairs) add is handled
910 Update of portSecurity update/removed is not handled
911 Update of parentrefs is not handled as parentrefs updation is handled by IFM Oxygen onwards
913 wrtConfigTxn.put(interfaceIdentifier, inf);
914 LOG.error("Interface {} is already present and is updated", infName);
916 LOG.warn("Interface {} is already present", infName);
918 } catch (ReadFailedException e) {
919 LOG.error("failed to create interface {}", infName, e);
924 // Not for generic use. For a special case where update DTCN isn't received
925 private static boolean isInterfaceUpdated(Interface newInterface, Interface oldInterface) {
926 if (newInterface.augmentation(SplitHorizon.class) != null) {
927 if (oldInterface.augmentation(SplitHorizon.class) == null) {
930 if (!newInterface.augmentation(SplitHorizon.class).equals(oldInterface
931 .augmentation(SplitHorizon.class))) {
935 if (!newInterface.augmentation(IfL2vlan.class).equals(oldInterface.augmentation(IfL2vlan.class))) {
938 if (newInterface.augmentation(InterfaceAcl.class) != null && oldInterface
939 .augmentation(InterfaceAcl.class) == null) {
945 private Interface createInterface(Port port) {
946 String interfaceName = port.getUuid().getValue();
947 IfL2vlan.L2vlanMode l2VlanMode = IfL2vlan.L2vlanMode.Trunk;
948 InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
949 IfL2vlanBuilder ifL2vlanBuilder = new IfL2vlanBuilder();
951 Network network = neutronvpnUtils.getNeutronNetwork(port.getNetworkId());
952 Boolean isVlanTransparent = network.isVlanTransparent();
953 if (isVlanTransparent != null && isVlanTransparent) {
954 l2VlanMode = IfL2vlan.L2vlanMode.Transparent;
956 PortIdToSubport portIdToSubport = neutronvpnUtils.getPortIdToSubport(port.getUuid());
957 if (portIdToSubport != null) {
958 l2VlanMode = IfL2vlan.L2vlanMode.TrunkMember;
959 ifL2vlanBuilder.setVlanId(new VlanId(portIdToSubport.getVlanId().intValue()));
960 String parentRefName = portIdToSubport.getTrunkPortId().getValue();
961 ParentRefsBuilder parentRefsBuilder = new ParentRefsBuilder().setParentInterface(parentRefName);
962 interfaceBuilder.addAugmentation(ParentRefs.class, parentRefsBuilder.build());
963 SplitHorizon splitHorizon =
964 new SplitHorizonBuilder().setOverrideSplitHorizonProtection(true).build();
965 interfaceBuilder.addAugmentation(SplitHorizon.class, splitHorizon);
969 ifL2vlanBuilder.setL2vlanMode(l2VlanMode);
971 interfaceBuilder.setEnabled(true).setName(interfaceName).setType(L2vlan.class)
972 .addAugmentation(IfL2vlan.class, ifL2vlanBuilder.build());
974 if (NeutronvpnUtils.getPortSecurityEnabled(port)) {
975 InterfaceAclBuilder interfaceAclBuilder = new InterfaceAclBuilder();
976 interfaceAclBuilder.setPortSecurityEnabled(true);
977 neutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, port);
978 interfaceBuilder.addAugmentation(InterfaceAcl.class, interfaceAclBuilder.build());
979 } else if (neutronvpnConfig.isLimitBumtrafficToDhcpserver() && NeutronvpnUtils.isDhcpServerPort(port)) {
980 interfaceBuilder.addAugmentation(InterfaceAcl.class, neutronvpnUtils.getDhcpInterfaceAcl(port));
982 return interfaceBuilder.build();
985 private void deleteOfPortInterface(Port port, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
986 String name = port.getUuid().getValue();
987 LOG.debug("Removing OFPort Interface {}", name);
988 InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
990 Optional<Interface> optionalInf =
991 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
992 interfaceIdentifier);
993 if (optionalInf.isPresent()) {
994 wrtConfigTxn.delete(interfaceIdentifier);
996 LOG.warn("deleteOfPortInterface: Interface {} is not present", name);
998 } catch (ReadFailedException e) {
999 LOG.error("deleteOfPortInterface: Failed to delete interface {}", name, e);
1003 private void createElanInterface(Port port, String name,
1004 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
1005 String elanInstanceName = port.getNetworkId().getValue();
1006 List<StaticMacEntries> staticMacEntries = NeutronvpnUtils.buildStaticMacEntry(port);
1008 InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
1009 .class, new ElanInterfaceKey(name)).build();
1010 ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
1011 .setName(name).setStaticMacEntries(staticMacEntries).withKey(new ElanInterfaceKey(name)).build();
1012 wrtConfigTxn.put(id, elanInterface);
1013 LOG.debug("Creating new ELan Interface {}", elanInterface);
1016 private void deleteElanInterface(String name, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
1017 InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
1018 .class, new ElanInterfaceKey(name)).build();
1019 wrtConfigTxn.delete(id);
1022 // TODO Clean up the exception handling
1023 @SuppressWarnings("checkstyle:IllegalCatch")
1024 private void addToFloatingIpPortInfo(Uuid floatingIpId, Uuid floatingIpPortId, Uuid floatingIpPortSubnetId, String
1025 floatingIpPortMacAddress) {
1026 InstanceIdentifier id = NeutronvpnUtils.buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
1028 FloatingIpIdToPortMappingBuilder floatingipIdToPortMacMappingBuilder = new
1029 FloatingIpIdToPortMappingBuilder().withKey(new FloatingIpIdToPortMappingKey(floatingIpId))
1030 .setFloatingIpId(floatingIpId).setFloatingIpPortId(floatingIpPortId)
1031 .setFloatingIpPortSubnetId(floatingIpPortSubnetId)
1032 .setFloatingIpPortMacAddress(floatingIpPortMacAddress);
1033 LOG.debug("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
1034 + " Port Info Config DS", floatingIpId.getValue(), floatingIpPortId.getValue());
1035 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
1036 floatingipIdToPortMacMappingBuilder.build());
1037 } catch (Exception e) {
1038 LOG.error("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
1039 + " Port Info Config DS failed", floatingIpId.getValue(), floatingIpPortId.getValue(), e);
1043 private Set<FixedIps> getFixedIpSet(List<FixedIps> fixedIps) {
1044 return fixedIps != null ? new HashSet<>(fixedIps) : Collections.emptySet();