2 * Copyright © 2015, 2018 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.neutronvpn;
10 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
12 import com.google.common.base.Optional;
13 import com.google.common.base.Strings;
14 import com.google.gson.Gson;
15 import com.google.gson.JsonArray;
16 import com.google.gson.JsonElement;
17 import com.google.gson.JsonObject;
18 import java.time.Duration;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Locale;
27 import java.util.stream.Collectors;
28 import javax.annotation.PostConstruct;
29 import javax.inject.Singleton;
30 import org.apache.commons.lang3.ObjectUtils;
31 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
32 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
33 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
34 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
35 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
36 import org.opendaylight.genius.datastoreutils.listeners.DataTreeEventCallbackRegistrar;
37 import org.opendaylight.genius.infra.Datastore;
38 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
39 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
40 import org.opendaylight.genius.infra.TypedWriteTransaction;
41 import org.opendaylight.genius.mdsalutil.MDSALUtil;
42 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
43 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
44 import org.opendaylight.netvirt.elanmanager.api.IElanService;
45 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
46 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
47 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlan;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlanBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAclBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.elan._interface.StaticMacEntries;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.hostconfig.rev150712.hostconfig.attributes.hostconfigs.Hostconfig;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
76 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
77 import org.slf4j.Logger;
78 import org.slf4j.LoggerFactory;
81 public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase<Port, NeutronPortChangeListener> {
82 private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChangeListener.class);
83 private final DataBroker dataBroker;
84 private final ManagedNewTransactionRunner txRunner;
85 private final NeutronvpnManager nvpnManager;
86 private final NeutronvpnNatManager nvpnNatManager;
87 private final NeutronSubnetGwMacResolver gwMacResolver;
88 private final IElanService elanService;
89 private final JobCoordinator jobCoordinator;
90 private final NeutronvpnUtils neutronvpnUtils;
91 private final HostConfigCache hostConfigCache;
92 private final DataTreeEventCallbackRegistrar eventCallbacks;
94 public NeutronPortChangeListener(final DataBroker dataBroker,
95 final NeutronvpnManager neutronvpnManager,
96 final NeutronvpnNatManager neutronvpnNatManager,
97 final NeutronSubnetGwMacResolver gwMacResolver,
98 final IElanService elanService,
99 final JobCoordinator jobCoordinator,
100 final NeutronvpnUtils neutronvpnUtils,
101 final HostConfigCache hostConfigCache,
102 final DataTreeEventCallbackRegistrar dataTreeEventCallbackRegistrar) {
103 super(Port.class, NeutronPortChangeListener.class);
104 this.dataBroker = dataBroker;
105 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
106 nvpnManager = neutronvpnManager;
107 nvpnNatManager = neutronvpnNatManager;
108 this.gwMacResolver = gwMacResolver;
109 this.elanService = elanService;
110 this.jobCoordinator = jobCoordinator;
111 this.neutronvpnUtils = neutronvpnUtils;
112 this.hostConfigCache = hostConfigCache;
113 this.eventCallbacks = dataTreeEventCallbackRegistrar;
119 LOG.info("{} init", getClass().getSimpleName());
120 registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
124 protected InstanceIdentifier<Port> getWildCardPath() {
125 return InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class);
129 protected NeutronPortChangeListener getDataTreeChangeListener() {
130 return NeutronPortChangeListener.this;
135 protected void add(InstanceIdentifier<Port> identifier, Port input) {
136 String portName = input.getUuid().getValue();
137 LOG.trace("Adding Port : key: {}, value={}", identifier, input);
138 Network network = neutronvpnUtils.getNeutronNetwork(input.getNetworkId());
139 if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
140 LOG.warn("neutron vpn received a port add() for a network without a provider extension augmentation "
141 + "or with an unsupported network type for the port {} which is part of network {}",
146 neutronvpnUtils.addToPortCache(input);
147 String portStatus = NeutronUtils.PORT_STATUS_DOWN;
148 if (!Strings.isNullOrEmpty(input.getDeviceOwner()) && !Strings.isNullOrEmpty(input.getDeviceId())) {
149 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(input.getDeviceOwner())) {
150 handleRouterInterfaceAdded(input);
151 NeutronUtils.createPortStatus(input.getUuid().getValue(), NeutronUtils.PORT_STATUS_ACTIVE, dataBroker);
154 if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(input.getDeviceOwner())) {
155 handleRouterGatewayUpdated(input, false);
156 portStatus = NeutronUtils.PORT_STATUS_ACTIVE;
157 } else if (NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(input.getDeviceOwner())) {
158 handleFloatingIpPortUpdated(null, input);
159 portStatus = NeutronUtils.PORT_STATUS_ACTIVE;
162 // Switchdev ports need to be bounded to a host before creation
163 // in order to validate the supported vnic types from the hostconfig
164 if (input.getFixedIps() != null
165 && !input.getFixedIps().isEmpty()
166 && !(isPortTypeSwitchdev(input) && !isPortBound(input))) {
167 handleNeutronPortCreated(input);
169 NeutronUtils.createPortStatus(input.getUuid().getValue(), portStatus, dataBroker);
173 protected void remove(InstanceIdentifier<Port> identifier, Port input) {
174 LOG.trace("Removing Port : key: {}, value={}", identifier, input);
175 Network network = neutronvpnUtils.getNeutronNetwork(input.getNetworkId());
176 // need to proceed with deletion in case network is null for a case where v2 sync happens and a read for
177 // network from NN returns null, but the deletion process for port needs to continue
178 if (network != null && !NeutronvpnUtils.isNetworkTypeSupported(network)) {
179 String portName = input.getUuid().getValue();
180 LOG.warn("neutron vpn received a port remove() for a network without a provider extension augmentation "
181 + "or with an unsupported network type for the port {} which is part of network {}",
185 neutronvpnUtils.removeFromPortCache(input);
186 NeutronUtils.deletePortStatus(input.getUuid().getValue(), dataBroker);
188 if (!Strings.isNullOrEmpty(input.getDeviceOwner()) && !Strings.isNullOrEmpty(input.getDeviceId())) {
189 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(input.getDeviceOwner())) {
190 handleRouterInterfaceRemoved(input);
191 /* nothing else to do here */
193 } else if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(input.getDeviceOwner())
194 || NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(input.getDeviceOwner())) {
195 handleRouterGatewayUpdated(input, true);
196 elanService.removeKnownL3DmacAddress(input.getMacAddress().getValue(), input.getNetworkId().getValue());
199 if (input.getFixedIps() != null) {
200 handleNeutronPortDeleted(input);
205 protected void update(InstanceIdentifier<Port> identifier, Port original, Port update) {
206 // Switchdev ports need to be bounded to a host before creation
207 // in order to validate the supported vnic types from the hostconfig
208 if (isPortTypeSwitchdev(original)
209 && !isPortBound(original)
210 && isPortBound(update)) {
211 handleNeutronPortCreated(update);
213 final String portName = update.getUuid().getValue();
214 Network network = neutronvpnUtils.getNeutronNetwork(update.getNetworkId());
215 LOG.info("Update port {} from network {}", portName, update.getNetworkId().toString());
216 if (network == null || !NeutronvpnUtils.isNetworkTypeSupported(network)) {
217 LOG.warn("neutron vpn received a port update() for a network without a provider extension augmentation "
218 + "or with an unsupported network type for the port {} which is part of network {}",
222 neutronvpnUtils.addToPortCache(update);
224 if ((Strings.isNullOrEmpty(original.getDeviceOwner()) || Strings.isNullOrEmpty(original.getDeviceId())
225 || NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING.equalsIgnoreCase(original.getDeviceId()))
226 && !Strings.isNullOrEmpty(update.getDeviceOwner()) && !Strings.isNullOrEmpty(update.getDeviceId())) {
227 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(update.getDeviceOwner())) {
228 handleRouterInterfaceAdded(update);
231 if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(update.getDeviceOwner())) {
232 handleRouterGatewayUpdated(update, false);
233 } else if (NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(update.getDeviceOwner())) {
234 handleFloatingIpPortUpdated(original, update);
237 Set<FixedIps> oldIPs = getFixedIpSet(original.getFixedIps());
238 Set<FixedIps> newIPs = getFixedIpSet(update.getFixedIps());
239 if (!oldIPs.equals(newIPs)) {
240 handleNeutronPortUpdated(original, update);
244 // check if port security enabled/disabled as part of port update
245 boolean origSecurityEnabled = NeutronvpnUtils.getPortSecurityEnabled(original);
246 boolean updatedSecurityEnabled = NeutronvpnUtils.getPortSecurityEnabled(update);
248 if (origSecurityEnabled || updatedSecurityEnabled) {
249 InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(portName);
250 jobCoordinator.enqueueJob("PORT- " + portName,
251 () -> Collections.singletonList(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION,
253 Optional<Interface> optionalInf =
254 confTx.read(interfaceIdentifier).get();
255 if (optionalInf.isPresent()) {
256 InterfaceBuilder interfaceBuilder = new InterfaceBuilder(optionalInf.get());
257 InterfaceAcl infAcl = handlePortSecurityUpdated(original, update,
258 origSecurityEnabled, updatedSecurityEnabled, interfaceBuilder).build();
259 interfaceBuilder.addAugmentation(InterfaceAcl.class, infAcl);
260 LOG.info("update: Of-port-interface updation for port {}", portName);
261 // Update OFPort interface for this neutron port
262 confTx.put(interfaceIdentifier, interfaceBuilder.build());
264 LOG.warn("update: Interface {} is not present", portName);
270 private void handleFloatingIpPortUpdated(Port original, Port update) {
271 if ((original == null || original.getDeviceId().equals(NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING))
272 && !update.getDeviceId().equals(NeutronConstants.FLOATING_IP_DEVICE_ID_PENDING)) {
273 // populate floating-ip uuid and floating-ip port attributes (uuid, mac and subnet id for the ONLY
274 // fixed IP) to be used by NAT, depopulated in NATService once mac is retrieved in the removal path
275 addToFloatingIpPortInfo(new Uuid(update.getDeviceId()), update.getUuid(), update.getFixedIps().get(0)
276 .getSubnetId(), update.getMacAddress().getValue());
277 elanService.addKnownL3DmacAddress(update.getMacAddress().getValue(), update.getNetworkId().getValue());
281 private void handleRouterInterfaceAdded(Port routerPort) {
282 if (routerPort.getDeviceId() != null) {
283 Uuid routerId = new Uuid(routerPort.getDeviceId());
284 Uuid infNetworkId = routerPort.getNetworkId();
285 Uuid existingVpnId = neutronvpnUtils.getVpnForNetwork(infNetworkId);
287 elanService.addKnownL3DmacAddress(routerPort.getMacAddress().getValue(), infNetworkId.getValue());
288 if (existingVpnId == null) {
289 Set<Uuid> listVpnIds = new HashSet<>();
290 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
294 listVpnIds.add(vpnId);
295 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
296 List<Subnetmap> subnetMapList = new ArrayList<>();
297 List<FixedIps> portIps = routerPort.getFixedIps();
298 boolean portIsIpv6 = false;
299 for (FixedIps portIP : portIps) {
300 // NOTE: Please donot change the order of calls to updateSubnetNodeWithFixedIP
301 // and addSubnetToVpn here
302 if (internetVpnId != null
303 && portIP.getIpAddress().getIpv6Address() != null) {
306 String ipValue = portIP.getIpAddress().stringValue();
307 Uuid subnetId = portIP.getSubnetId();
308 nvpnManager.updateSubnetNodeWithFixedIp(subnetId, routerId,
309 routerPort.getUuid(), ipValue, routerPort.getMacAddress().getValue(), vpnId);
310 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
311 subnetMapList.add(sn);
314 listVpnIds.add(internetVpnId);
315 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(
316 IpVersionChoice.IPV6, routerId, true)) {
317 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6,
319 neutronvpnUtils.updateVpnInstanceWithFallback(internetVpnId, true);
322 if (! subnetMapList.isEmpty()) {
323 nvpnManager.createVpnInterface(listVpnIds, routerPort, null);
325 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
326 for (FixedIps portIP : routerPort.getFixedIps()) {
327 String ipValue = portIP.getIpAddress().stringValue();
328 ipVersion = NeutronvpnUtils.getIpVersionFromString(ipValue);
329 if (ipVersion.isIpVersionChosen(IpVersionChoice.IPV4)) {
330 nvpnManager.addSubnetToVpn(vpnId, portIP.getSubnetId(),
331 null /* internet-vpn-id */);
333 nvpnManager.addSubnetToVpn(vpnId, portIP.getSubnetId(), internetVpnId);
335 LOG.trace("NeutronPortChangeListener Add Subnet Gateway IP {} MAC {} Interface {} VPN {}",
336 ipValue, routerPort.getMacAddress(),
337 routerPort.getUuid().getValue(), vpnId.getValue());
339 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(ipVersion, routerId, true)) {
340 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}",
341 ipVersion, vpnId.getValue());
342 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
344 nvpnManager.addToNeutronRouterInterfacesMap(routerId, routerPort.getUuid().getValue());
345 jobCoordinator.enqueueJob(routerId.toString(), () -> {
346 nvpnNatManager.handleSubnetsForExternalRouter(routerId);
347 return Collections.emptyList();
349 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
351 String portInterfaceName = createOfPortInterface(routerPort, confTx);
352 createElanInterface(routerPort, portInterfaceName, confTx);
353 }), LOG, "Error creating ELAN interface for {}", routerPort);
355 LOG.error("Neutron network {} corresponding to router interface port {} for neutron router {}"
356 + " already associated to VPN {}", infNetworkId.getValue(), routerPort.getUuid().getValue(),
357 routerId.getValue(), existingVpnId.getValue());
362 private void handleRouterInterfaceRemoved(Port routerPort) {
363 if (routerPort.getDeviceId() != null) {
364 Uuid routerId = new Uuid(routerPort.getDeviceId());
365 Uuid infNetworkId = routerPort.getNetworkId();
366 elanService.removeKnownL3DmacAddress(routerPort.getMacAddress().getValue(), infNetworkId.getValue());
367 Uuid vpnId = ObjectUtils.defaultIfNull(neutronvpnUtils.getVpnForRouter(routerId, true),
369 List<FixedIps> portIps = routerPort.getFixedIps();
370 boolean vpnInstanceInternetIpVersionRemoved = false;
371 Uuid vpnInstanceInternetUuid = null;
372 for (FixedIps portIP : portIps) {
373 // Internet VPN : flush InternetVPN first
374 Uuid subnetId = portIP.getSubnetId();
375 Subnetmap sn = neutronvpnUtils.getSubnetmap(subnetId);
376 if (sn != null && sn.getInternetVpnId() != null) {
377 if (neutronvpnUtils.shouldVpnHandleIpVersionChangeToRemove(sn, sn.getInternetVpnId())) {
378 vpnInstanceInternetIpVersionRemoved = true;
379 vpnInstanceInternetUuid = sn.getInternetVpnId();
381 nvpnManager.updateVpnInternetForSubnet(sn, sn.getInternetVpnId(), false);
384 /* Remove ping responder for router interfaces
385 * A router interface reference in a VPN will have to be removed before the host interface references
386 * for that subnet in the VPN are removed. This is to ensure that the FIB Entry of the router interface
387 * is not the last entry to be removed for that subnet in the VPN.
388 * If router interface FIB entry is the last to be removed for a subnet in a VPN , then all the host
389 * interface references in the vpn will already have been cleared, which will cause failures in
390 * cleanup of router interface flows*/
391 nvpnManager.deleteVpnInterface(routerPort.getUuid().getValue(),
392 null /* vpn-id */, null /* wrtConfigTxn*/);
393 final Uuid internetVpnId = vpnInstanceInternetUuid;
394 // update RouterInterfaces map
395 ListenableFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
397 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
398 for (FixedIps portIP : portIps) {
399 Subnetmap sn = neutronvpnUtils.getSubnetmap(portIP.getSubnetId());
400 // router Port have either IPv4 or IPv6, never both
401 ipVersion = neutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
402 String ipValue = portIP.getIpAddress().stringValue();
403 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(), ipValue, confTx);
404 // NOTE: Please donot change the order of calls to removeSubnetFromVpn and
405 // and updateSubnetNodeWithFixedIP
406 nvpnManager.removeSubnetFromVpn(vpnId, portIP.getSubnetId(), internetVpnId);
407 nvpnManager.updateSubnetNodeWithFixedIp(portIP.getSubnetId(), null, null,
410 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, routerPort.getUuid().getValue());
411 deleteElanInterface(routerPort.getUuid().getValue(), confTx);
412 deleteOfPortInterface(routerPort, confTx);
413 jobCoordinator.enqueueJob(routerId.toString(), () -> {
414 nvpnNatManager.handleSubnetsForExternalRouter(routerId);
415 return Collections.emptyList();
417 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(ipVersion, routerId, false)) {
418 LOG.debug("vpnInstanceOpDataEntry is getting update with ip address family {} for VPN {}",
419 ipVersion, vpnId.getValue());
420 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
422 }), LOG, "Error handling interface removal");
423 if (vpnInstanceInternetIpVersionRemoved) {
424 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnInstanceInternetUuid.getValue(),
425 IpVersionChoice.IPV6, false);
426 neutronvpnUtils.updateVpnInstanceWithFallback(vpnInstanceInternetUuid, false);
431 private void handleRouterGatewayUpdated(Port routerGwPort, boolean isRtrGwRemoved) {
432 Uuid routerId = new Uuid(routerGwPort.getDeviceId());
433 Uuid networkId = routerGwPort.getNetworkId();
434 Network network = neutronvpnUtils.getNeutronNetwork(networkId);
435 if (network == null) {
438 boolean isExternal = NeutronvpnUtils.getIsExternal(network);
440 Uuid vpnInternetId = neutronvpnUtils.getVpnForNetwork(networkId);
441 if (vpnInternetId != null) {
442 if (isRtrGwRemoved) {
443 //Set VPN type BGPVPNExternal from BGPVPNInternet for removal case
444 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNExternal,
447 //Set VPN type BGPVPNInternet from BGPVPNExternal for add case
448 neutronvpnUtils.updateVpnInstanceOpWithType(VpnInstanceOpDataEntry.BgpvpnType.BGPVPNInternet,
450 nvpnManager.updateVpnMaps(vpnInternetId, null, routerId, null, null);
452 List<Subnetmap> snList = neutronvpnUtils.getNeutronRouterSubnetMaps(routerId);
453 for (Subnetmap sn : snList) {
454 if (sn.getNetworkId() == networkId) {
457 if (NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp()) != IpVersionChoice.IPV6) {
460 if (isRtrGwRemoved) {
461 nvpnManager.removeV6PrivateSubnetToExtNetwork(routerId, vpnInternetId, sn);
463 nvpnManager.addV6PrivateSubnetToExtNetwork(routerId, vpnInternetId, sn);
466 //Update Internet BGP-VPN
467 if (isRtrGwRemoved) {
468 nvpnManager.updateVpnMaps(vpnInternetId, null, null, null, null);
472 elanService.addKnownL3DmacAddress(routerGwPort.getMacAddress().getValue(), networkId.getValue());
474 Router router = neutronvpnUtils.getNeutronRouter(routerId);
475 if (router == null) {
476 LOG.warn("No router found for router GW port {} for router {}", routerGwPort.getUuid().getValue(),
477 routerId.getValue());
479 eventCallbacks.onAddOrUpdate(LogicalDatastoreType.CONFIGURATION,
480 neutronvpnUtils.getNeutronRouterIid(routerId), (unused, newRouter) -> {
481 setupGwMac(newRouter, routerGwPort, routerId);
482 return DataTreeEventCallbackRegistrar.NextAction.UNREGISTER;
483 }, Duration.ofSeconds(3), iid -> {
484 LOG.error("GwPort {} added without Router", routerGwPort.getUuid().getValue());
488 setupGwMac(router, routerGwPort, routerId);
491 private void setupGwMac(Router router, Port routerGwPort, Uuid routerId) {
492 gwMacResolver.sendArpRequestsToExtGateways(router);
493 jobCoordinator.enqueueJob(routerId.toString(), () -> {
494 setExternalGwMac(routerGwPort, routerId);
495 return Collections.emptyList();
499 private void setExternalGwMac(Port routerGwPort, Uuid routerId) {
500 // During full-sync networking-odl syncs routers before ports. As such,
501 // the MAC of the router's gw port is not available to be set when the
502 // router is written. We catch that here.
503 InstanceIdentifier<Routers> routersId = NeutronvpnUtils.buildExtRoutersIdentifier(routerId);
504 Optional<Routers> optionalRouter = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId);
505 if (!optionalRouter.isPresent()) {
509 Routers extRouters = optionalRouter.get();
510 if (extRouters.getExtGwMacAddress() != null) {
514 RoutersBuilder builder = new RoutersBuilder(extRouters);
515 builder.setExtGwMacAddress(routerGwPort.getMacAddress().getValue());
516 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, routersId, builder.build());
519 private String getPortHostId(final Port port) {
521 PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class);
522 if (portBinding != null) {
523 return portBinding.getHostId();
529 private Hostconfig getHostConfig(final Port port) {
530 String hostId = getPortHostId(port);
531 if (hostId == null) {
534 Optional<Hostconfig> hostConfig;
536 hostConfig = this.hostConfigCache.get(hostId);
537 } catch (ReadFailedException e) {
538 LOG.error("failed to read host config from host {}", hostId, e);
541 return hostConfig.isPresent() ? hostConfig.get() : null;
544 private boolean isPortBound(final Port port) {
545 String hostId = getPortHostId(port);
546 return hostId != null && !hostId.isEmpty();
549 private boolean isPortVnicTypeDirect(Port port) {
550 PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class);
551 if (portBinding == null || portBinding.getVnicType() == null) {
552 // By default, VNIC_TYPE is NORMAL
555 String vnicType = portBinding.getVnicType().trim().toLowerCase(Locale.getDefault());
556 return vnicType.equals(NeutronConstants.VNIC_TYPE_DIRECT);
559 private boolean isSupportedVnicTypeByHost(final Port port, final String vnicType) {
560 Hostconfig hostConfig = getHostConfig(port);
561 String supportStr = String.format("\"vnic_type\": \"%s\"", vnicType);
562 if (hostConfig != null && hostConfig.getConfig().contains(supportStr)) {
568 private Map<String, JsonElement> unmarshal(final String profile) {
569 if (null == profile) {
572 Gson gson = new Gson();
573 JsonObject jsonObject = gson.fromJson(profile, JsonObject.class);
574 Map<String, JsonElement> map = new HashMap();
575 for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
576 map.put(entry.getKey(), entry.getValue());
581 private boolean isPortTypeSwitchdev(final Port port) {
582 if (!isPortVnicTypeDirect(port)) {
586 PortBindingExtension portBinding = port.augmentation(PortBindingExtension.class);
587 String profile = portBinding.getProfile();
588 if (profile == null || profile.isEmpty()) {
589 LOG.debug("Port {} has no binding:profile values", port.getUuid());
593 Map<String, JsonElement> mapProfile = unmarshal(profile);
594 JsonElement capabilities = mapProfile.get(NeutronConstants.BINDING_PROFILE_CAPABILITIES);
595 LOG.debug("Port {} capabilities: {}", port.getUuid(), capabilities);
596 if (capabilities == null || !capabilities.isJsonArray()) {
597 LOG.debug("binding profile capabilities not in array format: {}", capabilities);
601 JsonArray capabilitiesArray = capabilities.getAsJsonArray();
602 Gson gson = new Gson();
603 JsonElement switchdevElement = gson.fromJson(NeutronConstants.SWITCHDEV, JsonElement.class);
604 return capabilitiesArray.contains(switchdevElement);
608 private void handleNeutronPortCreated(final Port port) {
609 final String portName = port.getUuid().getValue();
610 final Uuid portId = port.getUuid();
611 final List<FixedIps> portIpAddrsList = port.getFixedIps();
612 if (NeutronConstants.IS_ODL_DHCP_PORT.test(port)) {
615 jobCoordinator.enqueueJob("PORT- " + portName, () -> {
616 // add direct port to subnetMaps config DS
617 if (!(NeutronUtils.isPortVnicTypeNormal(port)
618 || isPortTypeSwitchdev(port)
619 && isSupportedVnicTypeByHost(port, NeutronConstants.VNIC_TYPE_DIRECT))) {
620 for (FixedIps ip: portIpAddrsList) {
621 nvpnManager.updateSubnetmapNodeWithPorts(ip.getSubnetId(), null, portId);
623 LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;"
624 + "OF Port interfaces are not created", portName);
625 return Collections.emptyList();
627 return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
628 LOG.info("Of-port-interface creation for port {}", portName);
629 // Create of-port interface for this neutron port
630 String portInterfaceName = createOfPortInterface(port, tx);
631 LOG.debug("Creating ELAN Interface for port {}", portName);
632 createElanInterface(port, portInterfaceName, tx);
633 Set<Uuid> vpnIdList = new HashSet<>();
634 Set<Uuid> routerIds = new HashSet<>();
635 for (FixedIps ip: portIpAddrsList) {
636 Subnetmap subnetMap = nvpnManager.updateSubnetmapNodeWithPorts(ip.getSubnetId(), portId, null);
637 if (subnetMap != null && subnetMap.getInternetVpnId() != null) {
638 if (!vpnIdList.contains(subnetMap.getInternetVpnId())) {
639 vpnIdList.add(subnetMap.getInternetVpnId());
642 if (subnetMap != null && subnetMap.getVpnId() != null) {
643 // can't use NeutronvpnUtils.getVpnForNetwork to optimise here, because it gives BGPVPN id
644 // obtained subnetMaps belongs to one network => vpnId must be the same for each port Ip
645 Uuid vpnId = subnetMap.getVpnId();
647 vpnIdList.add(vpnId);
650 if (subnetMap != null && subnetMap.getRouterId() != null) {
651 routerIds.add(subnetMap.getRouterId());
654 if (!vpnIdList.isEmpty()) {
655 // create new vpn-interface for neutron port
656 LOG.debug("handleNeutronPortCreated: Adding VPN Interface for port {} from network {}", portName,
657 port.getNetworkId().toString());
658 nvpnManager.createVpnInterface(vpnIdList, port, tx);
659 if (!routerIds.isEmpty()) {
660 for (Uuid routerId : routerIds) {
661 nvpnManager.addToNeutronRouterInterfacesMap(routerId,port.getUuid().getValue());
669 private void handleNeutronPortDeleted(final Port port) {
670 final String portName = port.getUuid().getValue();
671 final Uuid portId = port.getUuid();
672 final List<FixedIps> portIpsList = port.getFixedIps();
673 jobCoordinator.enqueueJob("PORT- " + portName,
674 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
675 if (!(NeutronUtils.isPortVnicTypeNormal(port) || isPortTypeSwitchdev(port))) {
676 for (FixedIps ip : portIpsList) {
677 // remove direct port from subnetMaps config DS
678 nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), null, portId);
680 LOG.info("Port {} is not a normal and not a direct with switchdev VNIC type ;"
681 + "Skipping OF Port interfaces removal", portName);
685 Set<Uuid> routerIds = new HashSet<>();
686 Uuid internetVpnId = null;
687 for (FixedIps ip : portIpsList) {
688 Subnetmap subnetMap = nvpnManager.removePortsFromSubnetmapNode(ip.getSubnetId(), portId, null);
689 if (subnetMap == null) {
692 if (subnetMap.getVpnId() != null) {
693 // can't use NeutronvpnUtils.getVpnForNetwork to optimise here, because it gives BGPVPN id
694 // obtained subnetMaps belongs to one network => vpnId must be the same for each port Ip
695 vpnId = subnetMap.getVpnId();
697 if (subnetMap.getRouterId() != null) {
698 routerIds.add(subnetMap.getRouterId());
700 internetVpnId = subnetMap.getInternetVpnId();
702 if (NeutronConstants.DEVICE_OWNER_GATEWAY_INF.equals(port.getDeviceOwner())
703 || NeutronConstants.DEVICE_OWNER_FLOATING_IP.equals(port.getDeviceOwner())) {
704 String ipAddress = ip.getIpAddress().stringValue();
706 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(), ipAddress, confTx);
708 if (internetVpnId != null) {
709 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
714 if (vpnId != null || internetVpnId != null) {
715 // remove vpn-interface for this neutron port
716 LOG.debug("removing VPN Interface for port {}", portName);
717 if (!routerIds.isEmpty()) {
718 for (Uuid routerId : routerIds) {
719 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, portName);
722 nvpnManager.deleteVpnInterface(portName, null /* vpn-id */, confTx);
724 // Remove of-port interface for this neutron port
725 // ELAN interface is also implicitly deleted as part of this operation
726 LOG.debug("Of-port-interface removal for port {}", portName);
727 deleteOfPortInterface(port, confTx);
728 //dissociate fixedIP from floatingIP if associated
729 nvpnManager.dissociatefixedIPFromFloatingIP(port.getUuid().getValue());
734 private void handleNeutronPortUpdated(final Port portoriginal, final Port portupdate) {
735 final List<FixedIps> portoriginalIps = portoriginal.getFixedIps();
736 final List<FixedIps> portupdateIps = portupdate.getFixedIps();
737 if (portoriginalIps == null || portoriginalIps.isEmpty()) {
738 handleNeutronPortCreated(portupdate);
742 if (portupdateIps == null || portupdateIps.isEmpty()) {
743 LOG.info("Ignoring portUpdate (fixed_ip removal) for port {} as this case is handled "
744 + "during subnet deletion event.", portupdate.getUuid().getValue());
748 if (NeutronConstants.IS_ODL_DHCP_PORT.test(portupdate)) {
752 jobCoordinator.enqueueJob("PORT- " + portupdate.getUuid().getValue(),
753 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, confTx -> {
754 final List<Uuid> originalSnMapsIds = portoriginalIps.stream().map(FixedIps::getSubnetId)
755 .collect(Collectors.toList());
756 final List<Uuid> updateSnMapsIds = portupdateIps.stream().map(FixedIps::getSubnetId)
757 .collect(Collectors.toList());
758 Set<Uuid> originalRouterIds = new HashSet<>();
759 Set<Uuid> oldVpnIds = new HashSet<>();
760 for (Uuid snId: originalSnMapsIds) {
761 if (!updateSnMapsIds.remove(snId)) {
762 // snId was present in originalSnMapsIds, but not in updateSnMapsIds
763 Subnetmap subnetMapOld = nvpnManager.removePortsFromSubnetmapNode(snId, portoriginal.getUuid(),
765 if (subnetMapOld != null && subnetMapOld.getVpnId() != null) {
766 oldVpnIds.add(subnetMapOld.getVpnId());
768 if (subnetMapOld != null && subnetMapOld.getInternetVpnId() != null) {
769 oldVpnIds.add(subnetMapOld.getInternetVpnId());
771 if (subnetMapOld != null && subnetMapOld.getRouterId() != null) {
772 originalRouterIds.add(subnetMapOld.getRouterId());
776 Set<Uuid> newVpnIds = new HashSet<>();
777 Set<Uuid> newRouterIds = new HashSet<>();
778 for (Uuid snId: updateSnMapsIds) {
779 Subnetmap subnetMapNew = nvpnManager.updateSubnetmapNodeWithPorts(snId, portupdate.getUuid(), null);
780 if (subnetMapNew != null) {
781 if (subnetMapNew.getVpnId() != null) {
782 newVpnIds.add(subnetMapNew.getVpnId());
784 if (subnetMapNew.getInternetVpnId() != null) {
785 newVpnIds.add(subnetMapNew.getInternetVpnId());
787 if (subnetMapNew.getRouterId() != null) {
788 newRouterIds.add(subnetMapNew.getRouterId());
792 if (!oldVpnIds.isEmpty()) {
793 LOG.info("removing VPN Interface for port {}", portoriginal.getUuid().getValue());
794 if (!originalRouterIds.isEmpty()) {
795 for (Uuid routerId : originalRouterIds) {
796 nvpnManager.removeFromNeutronRouterInterfacesMap(routerId,
797 portoriginal.getUuid().getValue());
800 nvpnManager.deleteVpnInterface(portoriginal.getUuid().getValue(),
801 null /* vpn-id */, confTx);
803 if (!newVpnIds.isEmpty()) {
804 LOG.info("Adding VPN Interface for port {}", portupdate.getUuid().getValue());
805 nvpnManager.createVpnInterface(newVpnIds, portupdate, confTx);
806 if (!newRouterIds.isEmpty()) {
807 for (Uuid routerId : newRouterIds) {
808 nvpnManager.addToNeutronRouterInterfacesMap(routerId,portupdate.getUuid().getValue());
815 private InterfaceAclBuilder handlePortSecurityUpdated(Port portOriginal,
816 Port portUpdated, boolean origSecurityEnabled, boolean updatedSecurityEnabled,
817 InterfaceBuilder interfaceBuilder) {
818 InterfaceAclBuilder interfaceAclBuilder = null;
819 if (origSecurityEnabled != updatedSecurityEnabled) {
820 interfaceAclBuilder = new InterfaceAclBuilder();
821 interfaceAclBuilder.setPortSecurityEnabled(updatedSecurityEnabled);
822 if (updatedSecurityEnabled) {
823 // Handle security group enabled
824 NeutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, portUpdated);
825 neutronvpnUtils.populateSubnetInfo(portUpdated);
827 // Handle security group disabled
828 interfaceAclBuilder.setSecurityGroups(new ArrayList<>());
829 interfaceAclBuilder.setAllowedAddressPairs(new ArrayList<>());
832 if (updatedSecurityEnabled) {
833 // handle SG add/delete delta
834 InterfaceAcl interfaceAcl = interfaceBuilder.augmentation(InterfaceAcl.class);
835 interfaceAclBuilder = new InterfaceAclBuilder(interfaceAcl);
836 interfaceAclBuilder.setSecurityGroups(
837 NeutronvpnUtils.getUpdatedSecurityGroups(interfaceAcl.getSecurityGroups(),
838 portOriginal.getSecurityGroups(), portUpdated.getSecurityGroups()));
839 List<AllowedAddressPairs> updatedAddressPairs = NeutronvpnUtils.getUpdatedAllowedAddressPairs(
840 interfaceAcl.getAllowedAddressPairs(), portOriginal.getAllowedAddressPairs(),
841 portUpdated.getAllowedAddressPairs());
842 interfaceAclBuilder.setAllowedAddressPairs(NeutronvpnUtils.getAllowedAddressPairsForFixedIps(
843 updatedAddressPairs, portOriginal.getMacAddress(), portOriginal.getFixedIps(),
844 portUpdated.getFixedIps()));
846 if (portOriginal.getFixedIps() != null
847 && !portOriginal.getFixedIps().equals(portUpdated.getFixedIps())) {
848 neutronvpnUtils.populateSubnetInfo(portUpdated);
852 return interfaceAclBuilder;
855 private String createOfPortInterface(Port port, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
856 Interface inf = createInterface(port);
857 String infName = inf.getName();
859 InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(infName);
861 Optional<Interface> optionalInf =
862 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
863 interfaceIdentifier);
864 if (!optionalInf.isPresent()) {
865 wrtConfigTxn.put(interfaceIdentifier, inf);
867 LOG.warn("Interface {} is already present", infName);
869 } catch (ReadFailedException e) {
870 LOG.error("failed to create interface {}", infName, e);
875 private Interface createInterface(Port port) {
876 String interfaceName = port.getUuid().getValue();
877 IfL2vlan.L2vlanMode l2VlanMode = IfL2vlan.L2vlanMode.Trunk;
878 InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
879 IfL2vlanBuilder ifL2vlanBuilder = new IfL2vlanBuilder();
881 Network network = neutronvpnUtils.getNeutronNetwork(port.getNetworkId());
882 Boolean isVlanTransparent = network.isVlanTransparent();
883 if (isVlanTransparent != null && isVlanTransparent) {
884 l2VlanMode = IfL2vlan.L2vlanMode.Transparent;
887 ifL2vlanBuilder.setL2vlanMode(l2VlanMode);
889 interfaceBuilder.setEnabled(true).setName(interfaceName).setType(L2vlan.class)
890 .addAugmentation(IfL2vlan.class, ifL2vlanBuilder.build());
892 if (NeutronvpnUtils.getPortSecurityEnabled(port)) {
893 InterfaceAclBuilder interfaceAclBuilder = new InterfaceAclBuilder();
894 interfaceAclBuilder.setPortSecurityEnabled(true);
895 NeutronvpnUtils.populateInterfaceAclBuilder(interfaceAclBuilder, port);
896 interfaceBuilder.addAugmentation(InterfaceAcl.class, interfaceAclBuilder.build());
897 neutronvpnUtils.populateSubnetInfo(port);
899 return interfaceBuilder.build();
902 private void deleteOfPortInterface(Port port, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
903 String name = port.getUuid().getValue();
904 LOG.debug("Removing OFPort Interface {}", name);
905 InstanceIdentifier<Interface> interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
907 Optional<Interface> optionalInf =
908 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
909 interfaceIdentifier);
910 if (optionalInf.isPresent()) {
911 wrtConfigTxn.delete(interfaceIdentifier);
913 LOG.warn("deleteOfPortInterface: Interface {} is not present", name);
915 } catch (ReadFailedException e) {
916 LOG.error("deleteOfPortInterface: Failed to delete interface {}", name, e);
920 private void createElanInterface(Port port, String name,
921 TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
922 String elanInstanceName = port.getNetworkId().getValue();
923 List<StaticMacEntries> staticMacEntries = NeutronvpnUtils.buildStaticMacEntry(port);
925 InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
926 .class, new ElanInterfaceKey(name)).build();
927 ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
928 .setName(name).setStaticMacEntries(staticMacEntries).withKey(new ElanInterfaceKey(name)).build();
929 wrtConfigTxn.put(id, elanInterface);
930 LOG.debug("Creating new ELan Interface {}", elanInterface);
933 private void deleteElanInterface(String name, TypedWriteTransaction<Datastore.Configuration> wrtConfigTxn) {
934 InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
935 .class, new ElanInterfaceKey(name)).build();
936 wrtConfigTxn.delete(id);
939 // TODO Clean up the exception handling
940 @SuppressWarnings("checkstyle:IllegalCatch")
941 private void addToFloatingIpPortInfo(Uuid floatingIpId, Uuid floatingIpPortId, Uuid floatingIpPortSubnetId, String
942 floatingIpPortMacAddress) {
943 InstanceIdentifier id = NeutronvpnUtils.buildfloatingIpIdToPortMappingIdentifier(floatingIpId);
945 FloatingIpIdToPortMappingBuilder floatingipIdToPortMacMappingBuilder = new
946 FloatingIpIdToPortMappingBuilder().withKey(new FloatingIpIdToPortMappingKey(floatingIpId))
947 .setFloatingIpId(floatingIpId).setFloatingIpPortId(floatingIpPortId)
948 .setFloatingIpPortSubnetId(floatingIpPortSubnetId)
949 .setFloatingIpPortMacAddress(floatingIpPortMacAddress);
950 LOG.debug("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
951 + " Port Info Config DS", floatingIpId.getValue(), floatingIpPortId.getValue());
952 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
953 floatingipIdToPortMacMappingBuilder.build());
954 } catch (Exception e) {
955 LOG.error("Creating floating IP UUID {} to Floating IP neutron port {} mapping in Floating IP"
956 + " Port Info Config DS failed", floatingIpId.getValue(), floatingIpPortId.getValue(), e);
960 private Set<FixedIps> getFixedIpSet(List<FixedIps> fixedIps) {
961 return fixedIps != null ? new HashSet<>(fixedIps) : Collections.emptySet();