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 java.util.Collections.singletonList;
11 import static org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker.syncReadOptional;
12 import static org.opendaylight.mdsal.binding.util.Datastore.CONFIGURATION;
14 import com.google.common.base.Preconditions;
15 import com.google.common.util.concurrent.FutureCallback;
16 import com.google.common.util.concurrent.Futures;
17 import com.google.common.util.concurrent.JdkFutureAdapters;
18 import com.google.common.util.concurrent.ListenableFuture;
19 import com.google.common.util.concurrent.MoreExecutors;
20 import com.google.common.util.concurrent.SettableFuture;
21 import edu.umd.cs.findbugs.annotations.CheckReturnValue;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.EventListener;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Iterator;
29 import java.util.List;
31 import java.util.Map.Entry;
32 import java.util.Objects;
33 import java.util.Optional;
35 import java.util.concurrent.ConcurrentHashMap;
36 import java.util.concurrent.ConcurrentMap;
37 import java.util.concurrent.ExecutionException;
38 import java.util.concurrent.Future;
39 import java.util.concurrent.TimeUnit;
40 import java.util.concurrent.locks.ReentrantLock;
41 import java.util.function.Consumer;
42 import java.util.stream.Collectors;
43 import javax.annotation.PreDestroy;
44 import javax.inject.Inject;
45 import javax.inject.Singleton;
46 import org.eclipse.jdt.annotation.NonNull;
47 import org.eclipse.jdt.annotation.Nullable;
48 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
49 import org.opendaylight.genius.mdsalutil.NwConstants;
50 import org.opendaylight.genius.utils.JvmGlobalLocks;
51 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
52 import org.opendaylight.infrautils.utils.concurrent.LoggingFutures;
53 import org.opendaylight.infrautils.utils.concurrent.NamedLocks;
54 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.AcquireResult;
55 import org.opendaylight.mdsal.binding.api.DataBroker;
56 import org.opendaylight.mdsal.binding.util.Datastore.Configuration;
57 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
58 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
59 import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
60 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
61 import org.opendaylight.mdsal.common.api.OptimisticLockFailedException;
62 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
63 import org.opendaylight.netvirt.alarm.NeutronvpnAlarms;
64 import org.opendaylight.netvirt.elanmanager.api.IElanService;
65 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
66 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
67 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
68 import org.opendaylight.netvirt.neutronvpn.evpn.manager.NeutronEvpnManager;
69 import org.opendaylight.netvirt.neutronvpn.evpn.utils.NeutronEvpnUtils;
70 import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
71 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
72 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
73 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ProviderTypes;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.config.rev160806.NeutronvpnConfig;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.Adjacencies;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.AdjacenciesBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInstances;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.VpnInterfaces;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.Adjacency.AdjacencyType;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.adjacency.list.AdjacencyKey;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstance;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.VpnInstanceKey;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargets;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.VpnTargetsBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTarget;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.instances.vpn.instance.vpntargets.VpnTargetKey;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterface;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.VpnInterfaceKey;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNames.AssociatedSubnetType;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.l3vpn.rev200204.vpn.interfaces.vpn._interface.VpnInstanceNamesKey;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksInput;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateNetworksOutputBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterInput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutput;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.AssociateRouterOutputBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNInput;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateEVPNOutput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNInput;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.CreateL3VPNOutputBuilder;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNInput;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteEVPNOutput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNInput;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DeleteL3VPNOutputBuilder;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksInput;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutput;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateNetworksOutputBuilder;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterInput;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutput;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.DissociateRouterOutputBuilder;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNInput;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetEVPNOutput;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortInput;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutputBuilder;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInput;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNInputBuilder;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutput;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.GetL3VPNOutputBuilder;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.RouterInterfacesMap;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.createl3vpn.input.L3vpn;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.getl3vpn.output.L3vpnInstancesBuilder;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesBuilder;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMap;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.VpnMapKey;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIds;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsBuilder;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpnmaps.vpnmap.RouterIdsKey;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInputBuilder;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInput;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.RemoveStaticRouteInputBuilder;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.BgpvpnVni;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.OperationalPortStatus;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.Features;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.Feature;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureBuilder;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.extensions.rev160617.service.provider.features.attributes.features.FeatureKey;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIpsKey;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
178 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
179 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
180 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
181 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
182 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
183 import org.opendaylight.yangtools.yang.common.RpcError;
184 import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
185 import org.opendaylight.yangtools.yang.common.RpcResult;
186 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
187 import org.slf4j.Logger;
188 import org.slf4j.LoggerFactory;
189 import org.slf4j.helpers.FormattingTuple;
190 import org.slf4j.helpers.MessageFormatter;
193 public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, EventListener {
195 private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnManager.class);
196 private static final long LOCK_WAIT_TIME = 10L;
198 private final DataBroker dataBroker;
199 private final ManagedNewTransactionRunner txRunner;
200 private final VpnRpcService vpnRpcService;
201 private final NeutronFloatingToFixedIpMappingChangeListener floatingIpMapListener;
202 private final IElanService elanService;
203 private final NeutronvpnConfig neutronvpnConfig;
204 private final NeutronEvpnManager neutronEvpnManager;
205 private final NeutronEvpnUtils neutronEvpnUtils;
206 private final JobCoordinator jobCoordinator;
207 private final NeutronvpnUtils neutronvpnUtils;
208 private final IVpnManager vpnManager;
209 private final ConcurrentHashMap<Uuid, Uuid> unprocessedPortsMap = new ConcurrentHashMap<>();
210 private final NeutronvpnAlarms neutronvpnAlarm = new NeutronvpnAlarms();
211 private final NamedLocks<Uuid> vpnLock = new NamedLocks<>();
212 private final NamedLocks<String> interfaceLock = new NamedLocks<>();
215 public NeutronvpnManager(
216 final DataBroker dataBroker,
217 final VpnRpcService vpnRpcSrv, final IElanService elanService,
218 final NeutronFloatingToFixedIpMappingChangeListener neutronFloatingToFixedIpMappingChangeListener,
219 final NeutronvpnConfig neutronvpnConfig, final IVpnManager vpnManager,
220 final JobCoordinator jobCoordinator,
221 final NeutronvpnUtils neutronvpnUtils) throws TransactionCommitFailedException {
222 this.dataBroker = dataBroker;
223 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
224 vpnRpcService = vpnRpcSrv;
225 this.elanService = elanService;
226 floatingIpMapListener = neutronFloatingToFixedIpMappingChangeListener;
227 this.neutronvpnConfig = neutronvpnConfig;
228 neutronEvpnManager = new NeutronEvpnManager(dataBroker, this, neutronvpnUtils);
229 neutronEvpnUtils = new NeutronEvpnUtils(dataBroker, vpnManager, jobCoordinator);
230 this.jobCoordinator = jobCoordinator;
231 this.neutronvpnUtils = neutronvpnUtils;
232 this.vpnManager = vpnManager;
239 public void close() {
240 LOG.info("{} close", getClass().getSimpleName());
243 private void configureFeatures() throws TransactionCommitFailedException {
244 InstanceIdentifier<Feature> iid = InstanceIdentifier.builder(
245 Neutron.class).child(Features.class).child(
246 Feature.class, new FeatureKey(OperationalPortStatus.class)).build();
247 Feature feature = new FeatureBuilder().withKey(new FeatureKey(OperationalPortStatus.class)).build();
249 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, iid, feature);
250 } catch (OptimisticLockFailedException e) {
251 LOG.debug("Optimistic lock failed exception while configuring feature {}", feature, e);
253 InstanceIdentifier<Feature> bgpvpnVniIid = InstanceIdentifier.builder(
254 Neutron.class).child(Features.class).child(
255 Feature.class, new FeatureKey(BgpvpnVni.class)).build();
256 Feature bgpvpnVniFeature = new FeatureBuilder().withKey(new FeatureKey(BgpvpnVni.class)).build();
258 SingleTransactionDataBroker.syncWrite(
259 dataBroker, LogicalDatastoreType.OPERATIONAL, bgpvpnVniIid, bgpvpnVniFeature);
260 } catch (OptimisticLockFailedException e) {
261 LOG.debug("Optimistic lock failed exception while configuring feature {}", bgpvpnVniFeature, e);
265 public String getOpenDaylightVniRangesConfig() {
266 return neutronvpnConfig.getOpendaylightVniRanges();
269 // TODO Clean up the exception handling
270 @SuppressWarnings("checkstyle:IllegalCatch")
271 protected void createSubnetmapNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId,
272 NetworkAttributes.@Nullable NetworkType networkType, long segmentationId,
273 boolean isExternalNw) {
275 InstanceIdentifier<Subnetmap> subnetMapIdentifier = NeutronvpnUtils.buildSubnetMapIdentifier(subnetId);
276 final ReentrantLock lock = lockForUuid(subnetId);
279 LOG.info("createSubnetmapNode: subnet ID {}", subnetId.getValue());
280 Optional<Subnetmap> sn = SingleTransactionDataBroker.syncReadOptional(dataBroker,
281 LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
282 if (sn.isPresent()) {
283 LOG.error("createSubnetmapNode: Subnetmap node for subnet ID {} already exists, returning",
284 subnetId.getValue());
287 SubnetmapBuilder subnetmapBuilder = new SubnetmapBuilder().withKey(new SubnetmapKey(subnetId))
288 .setId(subnetId).setSubnetIp(subnetIp).setTenantId(tenantId).setNetworkId(networkId)
289 .setNetworkType(networkType).setSegmentationId(segmentationId).setExternal(isExternalNw);
290 LOG.debug("createSubnetmapNode: Adding a new subnet node in Subnetmaps DS for subnet {}",
291 subnetId.getValue());
292 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
293 subnetMapIdentifier, subnetmapBuilder.build());
297 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
298 LOG.error("createSubnetmapNode: Creating subnetmap node failed for subnet {}", subnetId.getValue());
300 // check if there are ports to update for already created Subnetmap node
301 LOG.debug("createSubnetmapNode: Update created Subnetmap for subnet {} with ports", subnetId.getValue());
302 for (Map.Entry<Uuid, Uuid> entry : unprocessedPortsMap.entrySet()) {
303 if (entry.getValue().getValue().equals(subnetId.getValue())) {
304 updateSubnetmapNodeWithPorts(subnetId, entry.getKey(), null);
305 unprocessedPortsMap.remove(entry.getKey());
311 protected Subnetmap updateSubnetNode(Uuid subnetId, @Nullable Uuid routerId, Uuid vpnId,
312 @Nullable Uuid internetvpnId) {
313 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
314 .child(Subnetmap.class, new SubnetmapKey(subnetId))
316 final ReentrantLock lock = lockForUuid(subnetId);
319 Optional<Subnetmap> sn =
320 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
321 if (!sn.isPresent()) {
322 LOG.error("subnetmap node for subnet {} does not exist, returning", subnetId.getValue());
325 LOG.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
326 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
327 if (routerId != null) {
328 builder.setRouterId(routerId);
331 builder.setVpnId(vpnId);
333 if (NeutronvpnUtils.getIpVersionFromString(sn.get().getSubnetIp()) == IpVersionChoice.IPV6) {
334 builder.setInternetVpnId(internetvpnId);
336 Subnetmap subnetmap = builder.build();
337 LOG.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
338 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
340 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
341 LOG.error("Subnet map update failed for node {}", subnetId.getValue(), e);
348 protected void updateSubnetNodeWithFixedIp(Uuid subnetId, @Nullable Uuid routerId,
349 @Nullable Uuid routerInterfacePortId, @Nullable String fixedIp,
350 @Nullable String routerIntfMacAddress, @Nullable Uuid vpnId) {
351 InstanceIdentifier<Subnetmap> id =
352 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
353 final ReentrantLock lock = lockForUuid(subnetId);
356 Optional<Subnetmap> sn =
357 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
358 if (!sn.isPresent()) {
359 LOG.error("updateSubnetNodeWithFixedIp: subnetmap node for subnet {} does not exist, returning ",
360 subnetId.getValue());
363 LOG.debug("updateSubnetNodeWithFixedIp: Updating existing subnetmap node for subnet ID {}",
364 subnetId.getValue());
365 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
366 builder.setRouterId(routerId);
367 builder.setRouterInterfacePortId(routerInterfacePortId);
368 builder.setRouterIntfMacAddress(routerIntfMacAddress);
369 builder.setRouterInterfaceFixedIp(fixedIp);
371 builder.setVpnId(vpnId);
373 Subnetmap subnetmap = builder.build();
374 LOG.debug("WithRouterFixedIP Creating/Updating subnetMap node for Router FixedIp: {} ",
375 subnetId.getValue());
376 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
377 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
378 LOG.error("updateSubnetNodeWithFixedIp: subnet map for Router FixedIp failed for node {}",
379 subnetId.getValue(), e);
385 protected Subnetmap updateSubnetmapNodeWithPorts(Uuid subnetId, @Nullable Uuid portId,
386 @Nullable Uuid directPortId) {
387 Subnetmap subnetmap = null;
388 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
389 new SubnetmapKey(subnetId)).build();
390 LOG.info("updateSubnetmapNodeWithPorts: Updating subnetMap with portList for subnetId {}", subnetId.getValue());
391 final ReentrantLock lock = lockForUuid(subnetId);
394 Optional<Subnetmap> sn =
395 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
397 if (sn.isPresent()) {
398 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
399 if (null != portId) {
400 List<Uuid> existingPortList = builder.getPortList();
401 List<Uuid> portList = new ArrayList<>();
402 if (null != existingPortList) {
403 portList.addAll(existingPortList);
405 portList.add(portId);
406 builder.setPortList(portList);
407 LOG.debug("updateSubnetmapNodeWithPorts: Updating existing subnetmap node {} with port {}",
408 subnetId.getValue(), portId.getValue());
410 if (null != directPortId) {
411 List<Uuid> existingDirectPortList = builder.getDirectPortList();
412 List<Uuid> directPortList = new ArrayList<>();
413 if (null != existingDirectPortList) {
414 directPortList.addAll(existingDirectPortList);
416 directPortList.add(directPortId);
417 builder.setDirectPortList(directPortList);
418 LOG.debug("Updating existing subnetmap node {} with port {}", subnetId.getValue(),
419 directPortId.getValue());
421 subnetmap = builder.build();
422 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
425 LOG.info("updateSubnetmapNodeWithPorts: Subnetmap node is not ready {}, put port {} in unprocessed "
426 + "cache ", subnetId.getValue(), portId.getValue());
427 unprocessedPortsMap.put(portId, subnetId);
429 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
430 LOG.error("Updating port list of a given subnetMap failed for node: {}", subnetId.getValue(), e);
437 protected Subnetmap removeFromSubnetNode(Uuid subnetId, @Nullable Uuid networkId, @Nullable Uuid routerId,
438 Uuid vpnId, @Nullable Uuid portId) {
439 Subnetmap subnetmap = null;
440 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
441 .child(Subnetmap.class, new SubnetmapKey(subnetId))
443 final ReentrantLock lock = lockForUuid(subnetId);
446 Optional<Subnetmap> sn =
447 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
449 if (sn.isPresent()) {
450 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
451 if (routerId != null) {
452 builder.setRouterId(null);
454 if (networkId != null) {
455 builder.setNetworkId(null);
458 builder.setVpnId(null);
460 builder.setInternetVpnId(null);
461 if (portId != null && builder.getPortList() != null) {
462 List<Uuid> portList = new ArrayList<>(builder.getPortList());
463 portList.remove(portId);
464 builder.setPortList(portList);
467 subnetmap = builder.build();
468 LOG.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
469 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
472 LOG.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
474 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
475 LOG.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
483 protected Subnetmap removePortsFromSubnetmapNode(Uuid subnetId, @Nullable Uuid portId,
484 @Nullable Uuid directPortId) {
485 Subnetmap subnetmap = null;
486 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class,
487 new SubnetmapKey(subnetId)).build();
488 final ReentrantLock lock = lockForUuid(subnetId);
491 Optional<Subnetmap> sn =
492 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
494 if (sn.isPresent()) {
495 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
496 if (null != portId && null != builder.getPortList() && !builder.getPortList().isEmpty()) {
497 List<Uuid> portList = new ArrayList<>(builder.getPortList());
498 portList.remove(portId);
499 builder.setPortList(portList);
500 LOG.debug("Removing port {} from existing subnetmap node: {} ", portId.getValue(),
501 subnetId.getValue());
503 if (null != directPortId && null != builder.getDirectPortList()
504 && !builder.getDirectPortList().isEmpty()) {
505 List<Uuid> directPortList = new ArrayList<>(builder.getDirectPortList());
506 directPortList.remove(directPortId);
507 builder.setDirectPortList(directPortList);
508 LOG.debug("Removing direct port {} from existing subnetmap node: {} ", directPortId
509 .getValue(), subnetId.getValue());
511 subnetmap = builder.build();
512 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id,
515 LOG.info("Trying to remove port from non-existing subnetmap node {}", subnetId.getValue());
517 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
518 LOG.error("Removing a port from port list of a subnetmap failed for node: {}",
519 subnetId.getValue(), e);
526 // TODO Clean up the exception handling
527 @SuppressWarnings("checkstyle:IllegalCatch")
528 protected void deleteSubnetMapNode(Uuid subnetId) {
529 InstanceIdentifier<Subnetmap> subnetMapIdentifier =
530 InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
531 LOG.debug("removing subnetMap node: {} ", subnetId.getValue());
532 final ReentrantLock lock = lockForUuid(subnetId);
535 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
536 } catch (TransactionCommitFailedException e) {
537 LOG.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
543 public void updateVpnInstanceWithRDs(String vpnInstanceId, final List<String> rds) {
544 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
545 .child(VpnInstance.class, new VpnInstanceKey(vpnInstanceId)).build();
547 Optional<VpnInstance> vpnInstanceConfig =
548 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
550 if (!vpnInstanceConfig.isPresent()) {
551 LOG.debug("updateVpnInstanceWithRDs: "
552 + "No VpnInstance present under config vpnInstance:{}", vpnInstanceId);
555 VpnInstance vpnInstance = vpnInstanceConfig.get();
556 VpnInstanceBuilder updateVpnInstanceBuilder = new VpnInstanceBuilder(vpnInstance);
557 updateVpnInstanceBuilder.setRouteDistinguisher(rds);
558 LOG.debug("updateVpnInstanceWithRDs: "
559 + "Updating Config vpn-instance: {} with the list of RDs: {}", vpnInstanceId, rds);
560 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
561 updateVpnInstanceBuilder.build());
562 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
563 LOG.warn("updateVpnInstanceWithRDs: Error configuring vpn-instance: {} with "
564 + "the list of RDs: {}", vpnInstanceId, rds, ex);
568 private void updateVpnInstanceNode(Uuid vpnId, List<String> rd, List<String> irt, List<String> ert,
569 boolean isL2Vpn, long l3vni, IpVersionChoice ipVersion) {
570 String vpnName = vpnId.getValue();
571 VpnInstanceBuilder builder = null;
572 List<VpnTarget> vpnTargetList = new ArrayList<>();
573 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
574 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
575 Optional<VpnInstance> optionalVpn;
577 optionalVpn = SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
579 } catch (ExecutionException | InterruptedException e) {
580 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
584 LOG.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
585 if (optionalVpn.isPresent()) {
586 builder = new VpnInstanceBuilder(optionalVpn.get());
587 LOG.debug("updating existing vpninstance node");
589 builder = new VpnInstanceBuilder().withKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName)
590 .setL2vpn(isL2Vpn).setL3vni(l3vni).setBgpvpnType(VpnInstance.BgpvpnType.InternalVPN);
592 if (irt != null && !irt.isEmpty()) {
593 if (ert != null && !ert.isEmpty()) {
594 List<String> commonRT = new ArrayList<>(irt);
595 commonRT.retainAll(ert);
597 for (String common : commonRT) {
600 VpnTarget vpnTarget =
601 new VpnTargetBuilder().withKey(new VpnTargetKey(common)).setVrfRTValue(common)
602 .setVrfRTType(VpnTarget.VrfRTType.Both).build();
603 vpnTargetList.add(vpnTarget);
606 for (String importRT : irt) {
607 VpnTarget vpnTarget =
608 new VpnTargetBuilder().withKey(new VpnTargetKey(importRT)).setVrfRTValue(importRT)
609 .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
610 vpnTargetList.add(vpnTarget);
614 if (ert != null && !ert.isEmpty()) {
615 for (String exportRT : ert) {
616 VpnTarget vpnTarget =
617 new VpnTargetBuilder().withKey(new VpnTargetKey(exportRT)).setVrfRTValue(exportRT)
618 .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
619 vpnTargetList.add(vpnTarget);
623 VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
624 if (rd != null && !rd.isEmpty()) {
625 builder.setRouteDistinguisher(rd).setVpnTargets(vpnTargets).setBgpvpnType(VpnInstance.BgpvpnType.BGPVPN);
628 builder.setIpAddressFamilyConfigured(VpnInstance.IpAddressFamilyConfigured.forValue(ipVersion.choice));
629 VpnInstance newVpn = builder.build();
630 try (AcquireResult lock = tryVpnLock(vpnId)) {
631 if (!lock.wasAcquired()) {
632 // FIXME: why do we even bother with locking if we do not honor it?!
633 logTryLockFailure(vpnId);
636 LOG.debug("Creating/Updating vpn-instance for {} ", vpnName);
638 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier,
640 } catch (TransactionCommitFailedException e) {
641 LOG.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
646 private void deleteVpnMapsNode(Uuid vpnId) {
647 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
648 .child(VpnMap.class, new VpnMapKey(vpnId))
650 LOG.debug("removing vpnMaps node: {} ", vpnId.getValue());
651 try (AcquireResult lock = tryVpnLock(vpnId)) {
652 if (!lock.wasAcquired()) {
653 // FIXME: why do we even bother with locking if we do not honor it?!
654 logTryLockFailure(vpnId);
658 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
660 } catch (TransactionCommitFailedException e) {
661 LOG.error("Delete vpnMaps node failed for vpn : {} ", vpnId.getValue());
666 protected void updateVpnMaps(Uuid vpnId, @Nullable String name, @Nullable Uuid router, @Nullable Uuid tenantId,
667 @Nullable List<Uuid> networks) {
668 VpnMapBuilder builder;
669 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
670 .child(VpnMap.class, new VpnMapKey(vpnId))
673 Optional<VpnMap> optionalVpnMap =
674 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
676 if (optionalVpnMap.isPresent()) {
677 builder = new VpnMapBuilder(optionalVpnMap.get());
679 builder = new VpnMapBuilder().withKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
683 builder.setName(name);
685 if (tenantId != null) {
686 builder.setTenantId(tenantId);
688 if (router != null) {
689 RouterIds vpnRouterId = new RouterIdsBuilder().setRouterId(router).build();
690 List<RouterIds> rtrIds = builder.getRouterIds() != null
691 ? new ArrayList<>(builder.getRouterIds().values()) : null;
692 if (rtrIds == null) {
693 rtrIds = Collections.singletonList(vpnRouterId);
695 //Add vpnRouterId to rtrIds list only if update routerId is not existing in the VpnMap already
696 for (RouterIds routerId: rtrIds) {
697 if (!Objects.equals(routerId, vpnRouterId)) {
698 rtrIds.add(vpnRouterId);
702 builder.setRouterIds(rtrIds);
704 if (networks != null) {
705 List<Uuid> nwList = builder.getNetworkIds() != null
706 ? new ArrayList<>(builder.getNetworkIds()) : new ArrayList<>();
707 nwList.addAll(networks);
708 builder.setNetworkIds(nwList);
711 try (AcquireResult lock = tryVpnLock(vpnId)) {
712 if (!lock.wasAcquired()) {
713 // FIXME: why do we even bother with locking if we do not honor it?!
714 logTryLockFailure(vpnId);
717 LOG.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
718 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier,
720 LOG.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
722 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
723 LOG.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
727 private void clearFromVpnMaps(Uuid vpnId, @Nullable Uuid routerId, @Nullable List<Uuid> networkIds) {
728 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
729 .child(VpnMap.class, new VpnMapKey(vpnId))
731 Optional<VpnMap> optionalVpnMap;
734 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
736 } catch (ExecutionException | InterruptedException e) {
737 LOG.error("Error reading the VPN map for {}", vpnMapIdentifier, e);
740 if (optionalVpnMap.isPresent()) {
741 VpnMap vpnMap = optionalVpnMap.get();
742 VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
743 List<RouterIds> rtrIds = new ArrayList<>(vpnMap.nonnullRouterIds().values());
744 if (rtrIds == null) {
745 rtrIds = new ArrayList<>();
747 if (routerId != null) {
748 if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
749 rtrIds.add(new RouterIdsBuilder().setRouterId(routerId).build());
750 vpnMapBuilder.setRouterIds(rtrIds);
752 try (AcquireResult lock = tryVpnLock(vpnId)) {
753 if (!lock.wasAcquired()) {
754 // FIXME: why do we even bother with locking if we do not honor it?!
755 logTryLockFailure(vpnId);
758 LOG.debug("removing vpnMaps node: {} ", vpnId);
760 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
762 } catch (TransactionCommitFailedException e) {
763 LOG.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
767 } else if (vpnMap.getNetworkIds() == null && !routerId.equals(vpnMap.getVpnId())) {
768 rtrIds.remove(new RouterIdsBuilder().setRouterId(routerId).build());
769 vpnMapBuilder.setRouterIds(rtrIds);
770 LOG.debug("Removing routerId {} in vpnMaps for the vpn {}", routerId, vpnId.getValue());
773 if (networkIds != null) {
774 List<Uuid> vpnNw = vpnMap.getNetworkIds() != null
775 ? new ArrayList<>(vpnMap.getNetworkIds()) : new ArrayList<>();
776 vpnNw.removeAll(networkIds);
777 if (vpnNw.isEmpty()) {
778 LOG.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
779 vpnMapBuilder.setNetworkIds(null);
781 vpnMapBuilder.setNetworkIds(vpnNw);
785 try (AcquireResult lock = tryVpnLock(vpnId)) {
786 if (!lock.wasAcquired()) {
787 // FIXME: why do we even bother with locking if we do not honor it?!
788 logTryLockFailure(vpnId);
791 LOG.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
793 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
794 vpnMapIdentifier, vpnMapBuilder.build());
795 } catch (TransactionCommitFailedException e) {
796 LOG.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
800 LOG.error("VPN : {} not found", vpnId.getValue());
802 LOG.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
805 private void deleteVpnInstance(Uuid vpnId) {
806 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
807 .child(VpnInstance.class,
808 new VpnInstanceKey(vpnId.getValue()))
811 try (AcquireResult lock = tryVpnLock(vpnId)) {
812 if (!lock.wasAcquired()) {
813 // FIXME: why do we even bother with locking if we do not honor it?!
814 logTryLockFailure(vpnId);
817 LOG.debug("Deleting vpnInstance {}", vpnId.getValue());
819 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
820 } catch (TransactionCommitFailedException e) {
821 LOG.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
826 protected Adjacencies createPortIpAdjacencies(Port port, Boolean isRouterInterface,
827 TypedWriteTransaction<Configuration> wrtConfigTxn,
828 @Nullable VpnInterface vpnIface) {
829 List<Adjacency> adjList = new ArrayList<>();
830 if (vpnIface != null) {
831 adjList = new ArrayList<Adjacency>(vpnIface.augmentation(Adjacencies.class).getAdjacency().values());
833 String infName = port.getUuid().getValue();
834 LOG.trace("neutronVpnManager: create config adjacencies for Port: {}", infName);
835 for (FixedIps ip : port.nonnullFixedIps().values()) {
836 String ipValue = ip.getIpAddress().stringValue();
837 String ipPrefix = ip.getIpAddress().getIpv4Address() != null ? ipValue + "/32" : ipValue + "/128";
838 Subnetmap snTemp = neutronvpnUtils.getSubnetmap(ip.getSubnetId());
839 if (snTemp != null && !FibHelper.doesPrefixBelongToSubnet(ipPrefix,
840 snTemp.getSubnetIp(), false)) {
843 Uuid vpnId = snTemp != null ? snTemp.getVpnId() : null;
845 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue,
846 infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
847 //Create Neutron port adjacency if VPN presence is existing for subnet
848 Adjacency vmAdj = new AdjacencyBuilder().withKey(new AdjacencyKey(ipPrefix)).setIpAddress(ipPrefix)
849 .setMacAddress(port.getMacAddress().getValue()).setAdjacencyType(AdjacencyType.PrimaryAdjacency)
850 .setSubnetId(ip.getSubnetId()).build();
851 if (!adjList.contains(vmAdj)) {
855 Uuid routerId = snTemp != null ? snTemp.getRouterId() : null;
856 if (snTemp != null && snTemp.getInternetVpnId() != null) {
857 neutronvpnUtils.createVpnPortFixedIpToPort(snTemp.getInternetVpnId().getValue(),
858 ipValue, infName, port.getMacAddress().getValue(), isRouterInterface, wrtConfigTxn);
860 if (routerId != null) {
861 Router rtr = neutronvpnUtils.getNeutronRouter(routerId);
862 if (rtr != null && rtr.getRoutes() != null) {
863 List<Routes> routeList = new ArrayList<Routes>(rtr.getRoutes().values());
864 // create extraroute Adjacence for each ipValue,
865 // because router can have IPv4 and IPv6 subnet ports, or can have
866 // more that one IPv4 subnet port or more than one IPv6 subnet port
867 List<Adjacency> erAdjList = getAdjacencyforExtraRoute(routeList, ipValue);
868 if (!erAdjList.isEmpty()) {
869 adjList.addAll(erAdjList);
874 return new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(adjList)).build();
877 private Map<AdjacencyKey, Adjacency> getAdjacencyMap(List<Adjacency> adjList) {
878 //convert to set to remove duplicates.
879 Set<Adjacency> adjset = adjList.stream().collect(Collectors.toSet());
880 Map<AdjacencyKey, Adjacency> adjacencyMap = new HashMap<>();
881 for (Adjacency adj : adjset) {
882 adjacencyMap.put(new AdjacencyKey(adj.getIpAddress()), adj);
887 protected void createVpnInterface(Collection<Uuid> vpnIds, Port port,
888 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
889 boolean isRouterInterface = false;
890 if (port.getDeviceOwner() != null) {
891 isRouterInterface = NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner());
893 String infName = port.getUuid().getValue();
894 // Handling cluster reboot scenario where VpnInterface already exists in datastore.
895 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, infName);
896 Adjacencies adjs = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn, vpnIface);
897 LOG.trace("createVpnInterface for Port: {}, isRouterInterface: {}", infName, isRouterInterface);
898 writeVpnInterfaceToDs(vpnIds, infName, adjs, port.getNetworkId(), isRouterInterface, wrtConfigTxn);
901 protected void withdrawPortIpFromVpnIface(Uuid vpnId, Uuid internetVpnId,
902 Port port, Subnetmap sn, TypedWriteTransaction<Configuration> wrtConfigTxn) {
903 String infName = port.getUuid().getValue();
904 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
905 Optional<VpnInterface> optionalVpnInterface = null;
906 LOG.debug("withdrawPortIpFromVpnIface vpn {} internetVpn {} Port {}",
907 vpnId, internetVpnId, infName);
909 optionalVpnInterface = SingleTransactionDataBroker
910 .syncReadOptional(dataBroker, LogicalDatastoreType
911 .CONFIGURATION, vpnIfIdentifier);
912 } catch (ExecutionException | InterruptedException e) {
913 LOG.error("withdrawPortIpFromVpnIface: Error reading the VPN interface for {}", vpnIfIdentifier, e);
916 if (!optionalVpnInterface.isPresent()) {
919 LOG.trace("withdraw adjacencies for Port: {} subnet {}", port.getUuid().getValue(),
920 sn != null ? sn.getSubnetIp() : "null");
921 Map<AdjacencyKey, Adjacency> keyAdjacencyMap
922 = optionalVpnInterface.get().augmentation(Adjacencies.class).nonnullAdjacency();
923 List<Adjacency> updatedAdjsList = new ArrayList<>();
924 boolean isIpFromAnotherSubnet = false;
925 for (Adjacency adj : keyAdjacencyMap.values()) {
926 String adjString = FibHelper.getIpFromPrefix(adj.getIpAddress());
927 if (sn == null || !Objects.equals(adj.getSubnetId(), sn.getId())) {
928 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
929 isIpFromAnotherSubnet = true;
931 updatedAdjsList.add(adj);
934 if (adj.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
935 LOG.error("withdrawPortIpFromVpnIface: suppressing primaryAdjacency {} FixedIp for vpnId {}",
938 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
939 String.valueOf(adjString), wrtConfigTxn);
941 if (internetVpnId != null) {
942 neutronvpnUtils.removeVpnPortFixedIpToPort(internetVpnId.getValue(),
943 String.valueOf(adjString), wrtConfigTxn);
946 if (NeutronConstants.DEVICE_OWNER_ROUTER_INF.equals(port.getDeviceOwner())
947 && sn.getRouterId() != null) {
948 Router rtr = neutronvpnUtils.getNeutronRouter(sn.getRouterId());
949 if (rtr != null && rtr.getRoutes() != null) {
950 List<Routes> extraRoutesToRemove = new ArrayList<>();
951 for (Routes rt: rtr.getRoutes().values()) {
952 if (rt.getNexthop().toString().equals(adjString)) {
953 extraRoutesToRemove.add(rt);
957 LOG.error("withdrawPortIpFromVpnIface: suppressing extraRoute {} for vpnId {}",
958 extraRoutesToRemove, vpnId);
959 removeAdjacencyforExtraRoute(vpnId, extraRoutesToRemove);
961 /* removeAdjacencyforExtraRoute done also for internet-vpn-id, in previous call */
966 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(updatedAdjsList)).build();
968 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, wrtConfigTxn);
970 if (!isIpFromAnotherSubnet) {
971 // no more subnetworks for neutron port
972 if (sn != null && sn.getRouterId() != null) {
973 removeFromNeutronRouterInterfacesMap(sn.getRouterId(), port.getUuid().getValue());
975 deleteVpnInterface(infName, null /* vpn-id */, wrtConfigTxn);
981 // TODO Clean up the exception handling
982 @SuppressWarnings("checkstyle:IllegalCatch")
983 protected void deleteVpnInterface(String infName, @Nullable String vpnId,
984 @Nullable TypedWriteTransaction<Configuration> wrtConfigTxn) {
985 if (wrtConfigTxn == null) {
986 LoggingFutures.addErrorLogging(
987 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
988 tx -> deleteVpnInterface(infName, vpnId, tx)),
989 LOG, "Error deleting VPN interface {} {}", infName, vpnId);
993 InstanceIdentifier<VpnInterface> vpnIfIdentifier =
994 NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
995 Optional<VpnInterface> optionalVpnInterface;
997 optionalVpnInterface =
998 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1000 } catch (ExecutionException | InterruptedException ex) {
1001 LOG.error("Error during deletion of vpninterface {}", infName, ex);
1004 if (!optionalVpnInterface.isPresent()) {
1005 LOG.warn("Deletion of vpninterface {}, optionalVpnInterface is not present()", infName);
1008 if (vpnId != null) {
1009 VpnInterface vpnInterface = optionalVpnInterface.get();
1010 Map<VpnInstanceNamesKey, VpnInstanceNames> keyVpnInstanceNamesMap = vpnInterface.getVpnInstanceNames();
1011 if (keyVpnInstanceNamesMap != null
1012 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId,
1013 new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()))) {
1014 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId,
1015 new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()));
1016 if (!keyVpnInstanceNamesMap.isEmpty()) {
1017 LOG.debug("Deleting vpn interface {} not immediately since vpnInstanceName "
1018 + "List not empty", infName);
1021 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1022 .setVpnInstanceNames(keyVpnInstanceNamesMap);
1023 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder
1027 LOG.debug("Deleting vpn interface {}", infName);
1028 wrtConfigTxn.delete(vpnIfIdentifier);
1031 protected void removeInternetVpnFromVpnInterface(Uuid vpnId, Port port,
1032 TypedWriteTransaction<Configuration> writeConfigTxn,
1034 if (vpnId == null || port == null) {
1037 String infName = port.getUuid().getValue();
1038 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1040 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
1041 .syncReadOptional(dataBroker, LogicalDatastoreType
1042 .CONFIGURATION, vpnIfIdentifier);
1043 if (optionalVpnInterface.isPresent()) {
1044 Map<VpnInstanceNamesKey, VpnInstanceNames> keyVpnInstanceNamesMap
1045 = optionalVpnInterface.get().getVpnInstanceNames();
1046 if (keyVpnInstanceNamesMap != null
1047 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(),
1048 new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()))) {
1049 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(vpnId.getValue(),
1050 new ArrayList<VpnInstanceNames>(keyVpnInstanceNamesMap.values()));
1052 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1053 .setVpnInstanceNames(keyVpnInstanceNamesMap);
1054 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1055 LOG.debug("Updating vpn interface {}", infName);
1056 Map<AdjacencyKey, Adjacency> keyAdjacencyMap = adjs != null ? adjs.getAdjacency() : new HashMap<>();
1057 Iterator<Adjacency> adjacencyIter = keyAdjacencyMap.values().iterator();
1058 while (adjacencyIter.hasNext()) {
1059 Adjacency adjacency = adjacencyIter.next();
1060 if (adjacency.getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
1063 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1064 InstanceIdentifier<LearntVpnVipToPort> id =
1065 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(vpnId.getValue(), mipToQuery);
1066 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1067 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1068 LogicalDatastoreType.OPERATIONAL, id);
1069 if (optionalVpnVipToPort.isPresent()) {
1070 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {}",
1072 if (keyVpnInstanceNamesMap == null || keyVpnInstanceNamesMap.isEmpty()) {
1073 adjacencyIter.remove();
1075 neutronvpnUtils.removeLearntVpnVipToPort(vpnId.getValue(), mipToQuery);
1076 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortFixedIPToPortData",
1077 mipToQuery, infName, vpnId.getValue());
1080 for (FixedIps ip : port.nonnullFixedIps().values()) {
1081 String ipValue = ip.getIpAddress().stringValue();
1083 if (!NeutronvpnUtils.getIpVersionFromString(ipValue).isIpVersionChosen(IpVersionChoice.IPV6)) {
1086 neutronvpnUtils.removeVpnPortFixedIpToPort(vpnId.getValue(),
1087 ipValue, writeConfigTxn);
1089 if (keyVpnInstanceNamesMap == null || keyVpnInstanceNamesMap.isEmpty()) {
1090 if (sm != null && sm.getRouterId() != null) {
1091 removeFromNeutronRouterInterfacesMap(sm.getRouterId(), port.getUuid().getValue());
1093 deleteVpnInterface(port.getUuid().getValue(), null /* vpn-id */, writeConfigTxn);
1095 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1098 LOG.info("removeVpnFromVpnInterface: VPN Interface {} not found", infName);
1100 } catch (ExecutionException | InterruptedException ex) {
1101 LOG.error("Update of vpninterface {} failed", infName, ex);
1105 protected void updateVpnInterface(Uuid vpnId, @Nullable Uuid oldVpnId, Port port, boolean isBeingAssociated,
1107 TypedWriteTransaction<Configuration> writeConfigTxn,
1108 boolean isInternetVpn) {
1109 if (vpnId == null || port == null) {
1112 String infName = port.getUuid().getValue();
1113 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
1115 try (AcquireResult lock = tryInterfaceLock(infName)) {
1116 if (!lock.wasAcquired()) {
1117 // FIXME: why do we even bother with locking if we do not honor it?!
1118 logTryLockFailure(infName);
1122 Optional<VpnInterface> optionalVpnInterface =
1123 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1125 if (optionalVpnInterface.isPresent()) {
1126 VpnInstanceNames vpnInstance = VpnHelper
1127 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
1128 List<VpnInstanceNames> listVpn = new ArrayList<>(optionalVpnInterface.get()
1129 .getVpnInstanceNames().values());
1130 if (oldVpnId != null
1131 && VpnHelper.doesVpnInterfaceBelongToVpnInstance(oldVpnId.getValue(), listVpn)) {
1132 VpnHelper.removeVpnInterfaceVpnInstanceNamesFromList(oldVpnId.getValue(), listVpn);
1134 if (vpnId.getValue() != null
1135 && !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpn)) {
1136 listVpn.add(vpnInstance);
1138 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get())
1139 .setVpnInstanceNames(listVpn);
1140 LOG.debug("Updating vpn interface {}", infName);
1141 if (!isBeingAssociated) {
1142 Adjacencies adjs = vpnIfBuilder.augmentation(Adjacencies.class);
1143 Map<AdjacencyKey, Adjacency> keyAdjacencyMap = adjs != null ? adjs.getAdjacency()
1144 : new HashMap<AdjacencyKey, Adjacency>();
1145 Iterator<Adjacency> adjacencyIter = keyAdjacencyMap.values().iterator();
1146 while (adjacencyIter.hasNext()) {
1147 Adjacency adjacency = adjacencyIter.next();
1148 String mipToQuery = adjacency.getIpAddress().split("/")[0];
1149 InstanceIdentifier<LearntVpnVipToPort> id =
1150 NeutronvpnUtils.buildLearntVpnVipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1151 Optional<LearntVpnVipToPort> optionalVpnVipToPort =
1152 SingleTransactionDataBroker.syncReadOptional(dataBroker,
1153 LogicalDatastoreType.OPERATIONAL, id);
1154 if (optionalVpnVipToPort.isPresent()
1155 && optionalVpnVipToPort.get().getPortName().equals(infName)) {
1156 LOG.trace("Removing adjacencies from vpninterface {} upon dissociation of router {} "
1157 + "from VPN {}", infName, vpnId, oldVpnId);
1158 adjacencyIter.remove();
1159 neutronvpnUtils.removeLearntVpnVipToPort(oldVpnId.getValue(), mipToQuery);
1161 "Entry for fixedIP {} for port {} on VPN {} removed from LearntVpnVipToPort",
1162 mipToQuery, infName, vpnId.getValue());
1164 InstanceIdentifier<VpnPortipToPort> build =
1165 NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), mipToQuery);
1166 Optional<VpnPortipToPort> persistedIp = SingleTransactionDataBroker.syncReadOptional(
1167 dataBroker, LogicalDatastoreType.OPERATIONAL, build);
1168 if (persistedIp.isPresent() && persistedIp.get().getPortName().equals(infName)) {
1169 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(), mipToQuery, null);
1170 LOG.trace("Entry for fixedIP {} for port {} on VPN {} removed from VpnPortipToPort",
1171 mipToQuery, infName, vpnId.getValue());
1174 Adjacencies adjacencies = new AdjacenciesBuilder().setAdjacency(keyAdjacencyMap).build();
1175 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
1177 for (FixedIps ip : port.nonnullFixedIps().values()) {
1178 String ipValue = ip.getIpAddress().stringValue();
1179 if (oldVpnId != null) {
1180 neutronvpnUtils.removeVpnPortFixedIpToPort(oldVpnId.getValue(),
1181 ipValue, writeConfigTxn);
1183 if (NeutronvpnUtils.getIpVersionFromString(ipValue) != IpVersionChoice.IPV6
1184 && isInternetVpn == true) {
1188 neutronvpnUtils.createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, infName, port
1189 .getMacAddress().getValue(), isSubnetIp, writeConfigTxn);
1191 writeConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
1193 LOG.error("VPN Interface {} not found", infName);
1195 } catch (ExecutionException | InterruptedException ex) {
1196 LOG.error("Updation of vpninterface {} failed", infName, ex);
1201 public void createL3InternalVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1202 List<String> ertList, Uuid routerId, List<Uuid> networksList) {
1204 IpVersionChoice ipVersChoices = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1206 // Update VPN Instance node
1207 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, false /*isL2Vpn*/, 0 /*l3vni*/, ipVersChoices);
1209 // Update local vpn-subnet DS
1210 updateVpnMaps(vpnId, name, routerId, tenantId, networksList);
1212 if (routerId != null) {
1213 Uuid existingVpn = neutronvpnUtils.getVpnForRouter(routerId, true);
1214 if (existingVpn != null) {
1215 // use case when a cluster is rebooted and router add DCN is received, triggering #createL3InternalVpn
1216 // if before reboot, router was already associated to VPN, should not proceed associating router to
1217 // internal VPN. Adding to RouterInterfacesMap is also not needed since it's a config DS and will be
1218 // preserved upon reboot.
1219 // For a non-reboot case #associateRouterToInternalVPN already takes care of adding to
1220 // RouterInterfacesMap via #createVPNInterface call.
1221 LOG.info("Associating router to Internal VPN skipped for VPN {} due to router {} already associated "
1222 + "to external VPN {}", vpnId.getValue(), routerId.getValue(), existingVpn.getValue());
1225 associateRouterToInternalVpn(vpnId, routerId);
1230 * Performs the creation of a Neutron L3VPN, associating the new VPN to the
1231 * specified Neutron Networks and Routers.
1233 * @param vpnId Uuid of the VPN tp be created
1234 * @param name Representative name of the new VPN
1235 * @param tenantId Uuid of the Tenant under which the VPN is going to be created
1236 * @param rdList Route-distinguisher for the VPN
1237 * @param irtList A list of Import Route Targets
1238 * @param ertList A list of Export Route Targets
1239 * @param routerIdsList ist of neutron router Id to associate with created VPN
1240 * @param networkList UUID of the neutron network the VPN may be associated to
1241 * @param isL2Vpn True if VPN Instance is of type L2, false if L3
1242 * @param l3vni L3VNI for the VPN Instance using VxLAN as the underlay
1243 * @throws Exception if association of L3VPN failed
1245 public void createVpn(Uuid vpnId, String name, Uuid tenantId, List<String> rdList, List<String> irtList,
1246 List<String> ertList, @Nullable List<Uuid> routerIdsList, @Nullable List<Uuid> networkList,
1247 boolean isL2Vpn, long l3vni) throws Exception {
1249 IpVersionChoice ipVersChoices = IpVersionChoice.UNDEFINED;
1251 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1252 for (Uuid routerId : routerIdsList) {
1253 IpVersionChoice vers = neutronvpnUtils.getIpVersionChoicesFromRouterUuid(routerId);
1254 ipVersChoices = ipVersChoices.addVersion(vers);
1257 updateVpnInstanceNode(vpnId, rdList, irtList, ertList, isL2Vpn, l3vni, ipVersChoices);
1259 // Please note that router and networks will be filled into VPNMaps
1260 // by subsequent calls here to associateRouterToVpn and
1261 // associateNetworksToVpn
1262 updateVpnMaps(vpnId, name, null, tenantId, null);
1263 LOG.debug("Created L3VPN with ID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, routerIdsList {}, "
1264 + "networkList {}", vpnId.getValue(), name, tenantId, rdList, irtList, ertList, routerIdsList,
1267 if (routerIdsList != null && !routerIdsList.isEmpty()) {
1268 for (Uuid routerId : routerIdsList) {
1269 associateRouterToVpn(vpnId, routerId);
1272 if (networkList != null) {
1273 List<String> failStrings = associateNetworksToVpn(vpnId, networkList);
1274 if (!failStrings.isEmpty()) {
1275 LOG.error("VPN {} association to networks failed for networks: {}. ",
1276 vpnId.getValue(), failStrings);
1277 throw new Exception(failStrings.toString());
1283 * It handles the invocations to the createVPN RPC method.
1286 // TODO Clean up the exception handling
1287 @SuppressWarnings("checkstyle:IllegalCatch")
1288 public ListenableFuture<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
1290 CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
1291 SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
1292 List<RpcError> errorList = new ArrayList<>();
1293 int failurecount = 0;
1294 int warningcount = 0;
1296 List<L3vpn> vpns = input.getL3vpn();
1298 vpns = Collections.emptyList();
1300 for (L3vpn vpn : vpns) {
1301 if (neutronvpnUtils.doesVpnExist(vpn.getId())) {
1302 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1303 formatAndLog(LOG::warn,
1304 "Creation of L3VPN failed for VPN {} due to VPN with the same ID already present",
1305 vpn.getId().getValue())));
1309 if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
1310 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1311 formatAndLog(LOG::warn,
1312 "Creation of L3VPN failed for VPN {} due to absence of RD/iRT/eRT input",
1313 vpn.getId().getValue())));
1318 if (vpn.getL3vni() != null) {
1319 l3vni = vpn.getL3vni().toJava();
1322 List<String> existingRDs = neutronvpnUtils.getExistingRDs();
1323 if (existingRDs.contains(vpn.getRouteDistinguisher().get(0))) {
1324 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1325 formatAndLog(LOG::warn,
1326 "Creation of L3VPN failed for VPN {} as another VPN with the same RD {} "
1327 + "is already configured",
1328 vpn.getId().getValue(), vpn.getRouteDistinguisher().get(0))));
1332 Optional<String> operationalVpn = getExistingOperationalVpn(vpn.getRouteDistinguisher().get(0));
1333 if (operationalVpn.isPresent()) {
1334 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION, "application-error",
1335 formatAndLog(LOG::error,
1336 "Creation of L3VPN failed for VPN {} as another VPN {} with the same RD {} "
1337 + "is still available. Please retry creation of a new vpn with the same RD"
1338 + " after a couple of minutes.", vpn.getId().getValue(), operationalVpn.get(),
1339 vpn.getRouteDistinguisher().get(0))));
1343 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1344 Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt
1345 .neutronvpn.rev150602.vpn.instance.RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight
1346 .netvirt.neutronvpn.rev150602.vpn.instance.RouterIds> keyRouterIdsMap = vpn.getRouterIds();
1347 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1348 routerId : keyRouterIdsMap.values()) {
1349 if (neutronvpnUtils.getNeutronRouter(routerId.getRouterId()) == null) {
1350 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1351 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to absense of routers"
1352 + "{}", vpn.getId(), routerId.getRouterId())));
1356 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
1357 if (vpnId != null) {
1358 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1359 formatAndLog(LOG::warn, "Creation of L3VPN failed for VPN {} due to router {} already "
1360 + "associated to another VPN {}", vpn.getId(), routerId.getRouterId(),
1361 vpnId.getValue())));
1367 if (vpn.getNetworkIds() != null) {
1368 int initialWarningCount = warningcount;
1369 for (Uuid nw : vpn.getNetworkIds()) {
1370 Network network = neutronvpnUtils.getNeutronNetwork(nw);
1371 Uuid vpnId = neutronvpnUtils.getVpnForNetwork(nw);
1372 if (network == null) {
1373 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1374 formatAndLog(LOG::warn,
1375 "Creation of L3VPN failed for VPN {} due to network not found {}",
1376 vpn.getId().getValue(), nw.getValue())));
1378 } else if (vpnId != null) {
1379 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input",
1380 formatAndLog(LOG::warn,
1381 "Creation of L3VPN failed for VPN {} due to network {} already associated"
1382 + " to another VPN {}", vpn.getId().getValue(), nw.getValue(),
1383 vpnId.getValue())));
1387 if (warningcount != initialWarningCount) {
1391 List<Uuid> rtrIdsList = new ArrayList<>();
1392 if (vpn.getRouterIds() != null && !vpn.getRouterIds().isEmpty()) {
1393 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.vpn.instance.RouterIds
1394 rtrId : vpn.getRouterIds().values()) {
1395 rtrIdsList.add(rtrId.getRouterId());
1399 LOG.debug("L3VPN add RPC: VpnID {}, name {}, tenantID {}, RDList {}, iRTList {}, eRTList{}, "
1400 + "routerIdList {}, networksList {}", vpn.getId().getValue(), vpn.getName(),
1401 vpn.getTenantId(), vpn.getRouteDistinguisher(), vpn.getImportRT(),
1402 vpn.getExportRT(), rtrIdsList, vpn.getNetworkIds());
1404 List<String> rdList = vpn.getRouteDistinguisher() != null
1405 ? new ArrayList<>(vpn.getRouteDistinguisher()) : new ArrayList<>();
1406 List<String> importRdList = vpn.getImportRT() != null
1407 ? new ArrayList<>(vpn.getImportRT()) : new ArrayList<>();
1408 List<String> exportRdList = vpn.getExportRT() != null
1409 ? new ArrayList<>(vpn.getExportRT()) : new ArrayList<>();
1411 createVpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), rdList,
1412 importRdList, exportRdList, rtrIdsList, vpn.getNetworkIds(), false /*isL2Vpn*/, l3vni);
1413 } catch (Exception ex) {
1414 LOG.error("VPN Creation exception :", ex);
1415 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1416 formatAndLog(LOG::error, "Creation of VPN failed for VPN {}", vpn.getId().getValue(), ex),
1421 // if at least one succeeds; result is success
1422 // if none succeeds; result is failure
1423 if (failurecount + warningcount == vpns.size()) {
1424 result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
1426 List<String> errorResponseList = new ArrayList<>();
1427 if (!errorList.isEmpty()) {
1428 for (RpcError rpcError : errorList) {
1429 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1430 + ", ErrorMessage: " + rpcError.getMessage());
1433 errorResponseList.add("Operation successful with no errors");
1435 opBuilder.setResponse(errorResponseList);
1436 result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
1442 * It handles the invocations to the neutronvpn:getL3VPN RPC method.
1445 public ListenableFuture<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
1447 GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
1448 SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
1449 Uuid inputVpnId = input.getId();
1450 List<VpnInstance> vpns = new ArrayList<>();
1451 List<L3vpnInstances> l3vpnList = new ArrayList<>();
1454 if (inputVpnId == null) {
1456 InstanceIdentifier<VpnInstances> vpnsIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1458 Optional<VpnInstances> optionalVpns =
1459 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1461 if (optionalVpns.isPresent() && !optionalVpns.get().getVpnInstance().isEmpty()) {
1462 for (VpnInstance vpn : optionalVpns.get().nonnullVpnInstance().values()) {
1463 // eliminating implicitly created (router and VLAN provider external network specific) VPNs
1464 // from getL3VPN output
1465 if (vpn.getRouteDistinguisher() != null) {
1471 opBuilder.setL3vpnInstances(l3vpnList);
1472 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1476 String name = inputVpnId.getValue();
1477 InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class)
1478 .child(VpnInstance.class, new VpnInstanceKey(name)).build();
1479 // read VpnInstance Info
1480 Optional<VpnInstance> optionalVpn =
1481 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1483 // eliminating implicitly created (router or VLAN provider external network specific) VPN from
1485 if (optionalVpn.isPresent() && optionalVpn.get().getRouteDistinguisher() != null) {
1486 vpns.add(optionalVpn.get());
1489 RpcResultBuilder.<GetL3VPNOutput>failed().withWarning(ErrorType.PROTOCOL, "invalid-value",
1490 formatAndLog(LOG::error, "GetL3VPN failed because VPN {} is not present",
1494 for (VpnInstance vpnInstance : vpns) {
1495 Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
1496 // create VpnMaps id
1497 L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
1498 List<String> rd = Collections.EMPTY_LIST;
1499 if (vpnInstance.getRouteDistinguisher() != null) {
1500 rd = vpnInstance.getRouteDistinguisher();
1502 List<String> ertList = new ArrayList<>();
1503 List<String> irtList = new ArrayList<>();
1505 if (vpnInstance.getVpnTargets() != null) {
1506 Map<VpnTargetKey, VpnTarget> keyVpnTargetMap = Collections.EMPTY_MAP;
1507 if (!vpnInstance.getVpnTargets().getVpnTarget().isEmpty()) {
1508 keyVpnTargetMap = vpnInstance.getVpnTargets().getVpnTarget();
1510 if (!keyVpnTargetMap.isEmpty()) {
1511 for (VpnTarget vpnTarget : keyVpnTargetMap.values()) {
1512 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
1513 ertList.add(vpnTarget.getVrfRTValue());
1515 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
1516 irtList.add(vpnTarget.getVrfRTValue());
1518 if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
1519 ertList.add(vpnTarget.getVrfRTValue());
1520 irtList.add(vpnTarget.getVrfRTValue());
1526 l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
1528 if (vpnInstance.getL3vni() != null) {
1529 l3vpn.setL3vni(vpnInstance.getL3vni());
1531 InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
1532 .class, new VpnMapKey(vpnId)).build();
1533 Optional<VpnMap> optionalVpnMap =
1534 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1536 if (optionalVpnMap.isPresent()) {
1537 VpnMap vpnMap = optionalVpnMap.get();
1538 List<Uuid> rtrIds = new ArrayList<>();
1539 if (vpnMap.getRouterIds() != null && !vpnMap.getRouterIds().isEmpty()) {
1540 for (RouterIds rtrId : vpnMap.getRouterIds().values()) {
1541 rtrIds.add(rtrId.getRouterId());
1544 l3vpn.setRouterIds(NeutronvpnUtils.getVpnInstanceRouterIdsList(rtrIds))
1545 .setNetworkIds(vpnMap.getNetworkIds()).setTenantId(vpnMap.getTenantId())
1546 .setName(vpnMap.getName());
1549 l3vpnList.add(l3vpn.build());
1552 opBuilder.setL3vpnInstances(l3vpnList);
1553 result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
1555 } catch (ExecutionException | InterruptedException ex) {
1556 result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION,
1557 formatAndLog(LOG::error, "GetVPN failed due to {}", ex.getMessage())).build());
1563 * It handles the invocations to the neutronvpn:deleteL3VPN RPC method.
1566 public ListenableFuture<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
1568 DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
1569 SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
1570 List<RpcError> errorList = new ArrayList<>();
1572 int failurecount = 0;
1573 int warningcount = 0;
1574 List<Uuid> vpns = input.getId() != null ? input.getId() : Collections.emptyList();
1575 for (Uuid vpn : vpns) {
1577 LOG.debug("L3VPN delete RPC: VpnID {}", vpn.getValue());
1578 InstanceIdentifier<VpnInstance> vpnIdentifier =
1579 InstanceIdentifier.builder(VpnInstances.class)
1580 .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
1581 Optional<VpnInstance> optionalVpn =
1582 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1584 if (optionalVpn.isPresent()) {
1587 errorList.add(RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value",
1588 formatAndLog(LOG::warn, "VPN with vpnid: {} does not exist", vpn.getValue())));
1591 } catch (ExecutionException | InterruptedException ex) {
1592 errorList.add(RpcResultBuilder.newError(ErrorType.APPLICATION,
1593 formatAndLog(LOG::error, "Deletion of L3VPN failed when deleting for uuid {}", vpn.getValue()),
1598 // if at least one succeeds; result is success
1599 // if none succeeds; result is failure
1600 if (failurecount + warningcount == vpns.size()) {
1601 result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
1603 List<String> errorResponseList = new ArrayList<>();
1604 if (!errorList.isEmpty()) {
1605 for (RpcError rpcError : errorList) {
1606 errorResponseList.add("ErrorType: " + rpcError.getErrorType() + ", ErrorTag: " + rpcError.getTag()
1607 + ", ErrorMessage: " + rpcError.getMessage());
1610 errorResponseList.add("Operation successful with no errors");
1612 opBuilder.setResponse(errorResponseList);
1613 result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
1618 public void createVpnInstanceForSubnet(Uuid subnetId) {
1619 LOG.debug("Creating/Updating L3 internalVPN for subnetID {} ", subnetId);
1620 createL3InternalVpn(subnetId, subnetId.getValue(), null, null, null, null, null, null);
1623 public void removeVpnInstanceForSubnet(Uuid subnetId) {
1624 LOG.debug("Removing vpn-instance for subnetID {} ", subnetId);
1625 removeVpn(subnetId);
1628 protected void addSubnetToVpn(@Nullable final Uuid vpnId, Uuid subnet, @Nullable final Uuid internetVpnId) {
1629 LOG.debug("addSubnetToVpn: Adding subnet {} to vpn {}", subnet.getValue(),
1630 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1631 Subnetmap sn = updateSubnetNode(subnet, null, vpnId, internetVpnId);
1633 LOG.error("addSubnetToVpn: subnetmap is null, cannot add subnet {} to VPN {}", subnet.getValue(),
1634 vpnId != null ? vpnId.getValue() : internetVpnId.getValue());
1637 if (vpnId != null) {
1638 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1639 if (vpnMap == null) {
1640 LOG.error("addSubnetToVpn: No vpnMap for vpnId {},"
1641 + " cannot add subnet {} to VPN", vpnId.getValue(),
1645 final VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1646 LOG.debug("addSubnetToVpn: VpnInstance {}", vpnInstance);
1647 if (isVpnOfTypeL2(vpnInstance)) {
1648 neutronEvpnUtils.updateElanAndVpn(vpnInstance, sn.getNetworkId().getValue(),
1649 NeutronEvpnUtils.Operation.ADD);
1652 if (internetVpnId != null) {
1653 VpnMap vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1654 if (vpnMap == null) {
1655 LOG.error("addSubnetToVpn: No vpnMap for InternetVpnId {}, cannot add "
1656 + "subnet {} to VPN", internetVpnId.getValue(),
1661 final Uuid internetId = internetVpnId;
1662 // Check if there are ports on this subnet and add corresponding vpn-interfaces
1663 List<Uuid> portList = sn.getPortList();
1664 if (portList != null) {
1665 for (final Uuid portId : portList) {
1666 String vpnInfName = portId.getValue();
1667 VpnInterface vpnIface = VpnHelper.getVpnInterface(dataBroker, vpnInfName);
1668 Port port = neutronvpnUtils.getNeutronPort(portId);
1670 LOG.error("addSubnetToVpn: Cannot proceed with addSubnetToVpn for port {} in subnet {} "
1671 + "since port is absent in Neutron config DS", portId.getValue(), subnet.getValue());
1674 final Boolean isRouterInterface = port.getDeviceOwner()
1675 .equals(NeutronConstants.DEVICE_OWNER_ROUTER_INF) ? true : false;
1676 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1677 ListenableFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1679 Adjacencies portAdj = createPortIpAdjacencies(port, isRouterInterface, wrtConfigTxn,
1681 if (vpnIface == null) {
1682 LOG.trace("addSubnetToVpn: create new VpnInterface for Port {}", vpnInfName);
1683 Set<Uuid> listVpn = new HashSet<>();
1684 if (vpnId != null) {
1687 if (internetId != null) {
1688 listVpn.add(internetId);
1690 writeVpnInterfaceToDs(listVpn, vpnInfName, portAdj, port.getNetworkId(),
1691 isRouterInterface, wrtConfigTxn);
1692 if (sn.getRouterId() != null) {
1693 addToNeutronRouterInterfacesMap(sn.getRouterId(), portId.getValue());
1696 LOG.trace("update VpnInterface for Port {} with adj {}", vpnInfName, portAdj);
1697 if (vpnId != null) {
1698 updateVpnInterfaceWithAdjacencies(vpnId, vpnInfName, portAdj, wrtConfigTxn);
1700 if (internetId != null) {
1701 updateVpnInterfaceWithAdjacencies(internetId, vpnInfName, portAdj, wrtConfigTxn);
1705 LoggingFutures.addErrorLogging(future, LOG,
1706 "addSubnetToVpn: Failed while creating VPN interface for vpnId {}, portId {}"
1707 + "{}, subnetId {}", vpnId.getValue(), portId, subnet.getValue());
1708 return Collections.singletonList(future);
1714 protected void removeSubnetFromVpn(final Uuid vpnId, Subnetmap subnetmap, @Nullable Uuid internetVpnId) {
1715 Preconditions.checkArgument(vpnId != null || internetVpnId != null,
1716 "removeSubnetFromVpn: at least one VPN must be not null");
1717 Uuid subnetId = subnetmap.getId();
1718 LOG.debug("Removing subnet {} from vpn {}/{}", subnetId.getValue(),
1719 vpnId, internetVpnId);
1720 LOG.error("removeSubnetFromVpn: Subnetmap for subnet {} not found", subnetId.getValue());
1721 VpnMap vpnMap = null;
1722 VpnInstance vpnInstance = null;
1723 if (vpnId != null) {
1724 vpnMap = neutronvpnUtils.getVpnMap(vpnId);
1725 if (vpnMap == null) {
1726 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {} from VPN",
1727 vpnId.getValue(), subnetId.getValue());
1730 vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
1732 if (internetVpnId == null) {
1733 internetVpnId = subnetmap.getInternetVpnId();
1735 if (internetVpnId != null) {
1736 vpnMap = neutronvpnUtils.getVpnMap(internetVpnId);
1737 if (vpnMap == null) {
1738 LOG.error("No vpnMap for vpnId {}, cannot remove subnet {}"
1739 + " from Internet VPN",
1740 internetVpnId.getValue(), subnetId.getValue());
1744 if (vpnInstance != null && isVpnOfTypeL2(vpnInstance)) {
1745 neutronEvpnUtils.updateElanAndVpn(vpnInstance, subnetmap.getNetworkId().getValue(),
1746 NeutronEvpnUtils.Operation.DELETE);
1748 boolean subnetVpnAssociation = false;
1749 if (vpnId != null && subnetmap.getVpnId() != null
1750 && subnetmap.getVpnId().getValue().equals(vpnId.getValue())) {
1751 subnetVpnAssociation = true;
1752 } else if (internetVpnId != null && subnetmap.getInternetVpnId() != null
1753 && subnetmap.getInternetVpnId().getValue().matches(internetVpnId.getValue())) {
1754 subnetVpnAssociation = true;
1756 if (subnetVpnAssociation == false) {
1757 LOG.error("Removing subnet : Subnetmap is not in VPN {}/{}, owns {} and {}",
1758 vpnId, internetVpnId, subnetmap.getVpnId(), subnetmap.getInternetVpnId());
1761 // Check if there are ports on this subnet; remove corresponding vpn-interfaces
1762 List<Uuid> portList = subnetmap.getPortList();
1763 final Uuid internetId = internetVpnId;
1764 if (portList != null) {
1765 for (final Uuid portId : portList) {
1766 LOG.debug("withdrawing subnet IP {} from vpn-interface {}", subnetmap.getSubnetIp(), portId.getValue());
1767 final Port port = neutronvpnUtils.getNeutronPort(portId);
1768 jobCoordinator.enqueueJob("PORT-" + portId.getValue(), () -> {
1769 List<ListenableFuture<?>> futures = new ArrayList<>();
1770 ListenableFuture<?> future = txRunner.callWithNewWriteOnlyTransactionAndSubmit(
1771 CONFIGURATION, tx -> {
1773 withdrawPortIpFromVpnIface(vpnId, internetId, port, subnetmap, tx);
1775 LOG.warn("Cannot proceed with withdrawPortIpFromVpnIface for port {} in subnet {} since"
1776 + " port is absent in Neutron config DS", portId.getValue(),
1777 subnetId.getValue());
1780 LoggingFutures.addErrorLogging(future, LOG,
1781 "removeSubnetFromVpn: Exception while processing deletion of VPN interfaces for port {}"
1782 + " belonging to subnet {} and vpnId {}",
1783 portId.getValue(), subnetId.getValue(), vpnId.getValue());
1784 futures.add(future);
1789 //update subnet-vpn association
1790 removeFromSubnetNode(subnetId, null, null, vpnId, null);
1793 protected void updateVpnInternetForSubnet(Subnetmap sm, Uuid vpn, boolean isBeingAssociated) {
1794 LOG.debug("updateVpnInternetForSubnet: {} subnet {} with BGPVPN Internet {} ",
1795 isBeingAssociated ? "associating" : "dissociating", sm.getSubnetIp(),
1797 Uuid internalVpnId = sm.getVpnId();
1798 if (internalVpnId == null) {
1799 LOG.error("updateVpnInternetForSubnet: can not find Internal or BGPVPN Id for subnet {}, bailing out",
1800 sm.getId().getValue());
1803 if (isBeingAssociated) {
1804 updateSubnetNode(sm.getId(), null, sm.getVpnId(), vpn);
1806 updateSubnetNode(sm.getId(), null, sm.getVpnId(), null);
1809 jobCoordinator.enqueueJob("VPN-" + vpn.getValue(), () -> singletonList(
1810 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, wrtConfigTxn -> {
1811 if (isBeingAssociated) {
1812 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(
1813 sm.getRouterInterfacePortId()), true, true, wrtConfigTxn, true);
1815 removeInternetVpnFromVpnInterface(vpn,
1816 neutronvpnUtils.getNeutronPort(sm.getRouterInterfacePortId()), wrtConfigTxn, sm);
1821 // Check for ports on this subnet and update association of
1822 // corresponding vpn-interfaces to internet vpn
1823 List<Uuid> portList = sm.getPortList();
1824 if (portList != null) {
1825 for (Uuid port : portList) {
1826 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1827 port.getValue(), isBeingAssociated);
1828 jobCoordinator.enqueueJob("PORT-" + port.getValue(),
1829 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1831 if (isBeingAssociated) {
1832 updateVpnInterface(vpn, null, neutronvpnUtils.getNeutronPort(port),
1833 true, false, tx, true);
1835 removeInternetVpnFromVpnInterface(vpn, neutronvpnUtils.getNeutronPort(port), tx, sm);
1843 private Subnetmap updateVpnForSubnet(Uuid oldVpnId, Uuid newVpnId, Uuid subnet, boolean isBeingAssociated) {
1844 LOG.debug("Moving subnet {} from oldVpn {} to newVpn {} ", subnet.getValue(),
1845 oldVpnId.getValue(), newVpnId.getValue());
1846 Uuid networkUuid = neutronvpnUtils.getSubnetmap(subnet).getNetworkId();
1847 Network network = neutronvpnUtils.getNeutronNetwork(networkUuid);
1848 boolean netIsExternal = NeutronvpnUtils.getIsExternal(network);
1849 Uuid vpnExtUuid = netIsExternal ? null
1850 : neutronvpnUtils.getInternetvpnUuidBoundToSubnetRouter(subnet);
1851 Subnetmap sn = updateSubnetNode(subnet, null, newVpnId, vpnExtUuid);
1853 LOG.error("Updating subnet {} with newVpn {} failed", subnet.getValue(), newVpnId.getValue());
1856 /* vpnExtUuid will contain the value only on if the subnet is V6 and it is already been
1857 * associated with internet BGP-VPN.
1859 if (vpnExtUuid != null) {
1860 /* Update V6 Internet default route match with new VPN metadata.
1861 * isBeingAssociated = true means oldVpnId is same as routerId
1862 * isBeingAssociated = false means newVpnId is same as routerId
1864 if (isBeingAssociated) {
1865 neutronvpnUtils.updateVpnInstanceWithFallback(oldVpnId, vpnExtUuid, true);
1867 neutronvpnUtils.updateVpnInstanceWithFallback(newVpnId, vpnExtUuid, true);
1870 //Update Router Interface first synchronously.
1871 //CAUTION: Please DONOT make the router interface VPN Movement as an asynchronous commit again !
1872 ListenableFuture<?> future =
1873 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1874 tx -> updateVpnInterface(newVpnId, oldVpnId,
1875 neutronvpnUtils.getNeutronPort(sn.getRouterInterfacePortId()),
1876 isBeingAssociated, true, tx, false));
1877 Futures.addCallback(future, new FutureCallback<Object>() {
1879 public void onSuccess(Object result) {
1880 // Check for ports on this subnet and update association of
1881 // corresponding vpn-interfaces to external vpn
1882 List<Uuid> portList = sn.getPortList();
1883 if (portList != null) {
1884 for (Uuid port : portList) {
1885 LOG.debug("Updating vpn-interface for port {} isBeingAssociated {}",
1886 port.getValue(), isBeingAssociated);
1887 jobCoordinator.enqueueJob("PORT-" + port.getValue(), () -> Collections.singletonList(
1888 txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
1889 tx -> updateVpnInterface(newVpnId, oldVpnId,
1890 neutronvpnUtils.getNeutronPort(port), isBeingAssociated, false,
1897 public void onFailure(Throwable throwable) {
1899 "Failed to update router interface {} in subnet {} from oldVpnId {} to newVpnId {}, "
1901 sn.getRouterInterfacePortId().getValue(), subnet.getValue(), oldVpnId, newVpnId, throwable);
1903 }, MoreExecutors.directExecutor());
1908 public InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
1909 return InstanceIdentifier.builder(RouterInterfacesMap.class)
1910 .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
1913 protected void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1914 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1915 final ReentrantLock lock = lockForUuid(routerId);
1918 Optional<RouterInterfaces> optRouterInterfaces =
1919 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1920 routerInterfacesId);
1921 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1922 .setInterfaceId(interfaceName).build();
1923 if (optRouterInterfaces.isPresent()) {
1924 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1925 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
1927 RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
1928 List<Interfaces> interfaces = new ArrayList<>();
1929 interfaces.add(routerInterface);
1930 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
1931 routerInterfacesId, builder.setInterfaces(interfaces).build());
1933 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
1934 LOG.error("Error reading router interfaces for {}", routerInterfacesId, e);
1940 protected void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
1941 final InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
1942 final ReentrantLock lock = lockForUuid(routerId);
1945 Optional<RouterInterfaces> optRouterInterfaces =
1946 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
1947 routerInterfacesId);
1948 Interfaces routerInterface = new InterfacesBuilder().withKey(new InterfacesKey(interfaceName))
1949 .setInterfaceId(interfaceName).build();
1950 if (optRouterInterfaces.isPresent()) {
1951 RouterInterfaces routerInterfaces = optRouterInterfaces.get();
1952 List<Interfaces> interfaces = new ArrayList<>(routerInterfaces.nonnullInterfaces().values());
1953 if (interfaces != null && interfaces.remove(routerInterface)) {
1954 if (interfaces.isEmpty()) {
1955 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1956 routerInterfacesId);
1958 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
1959 routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
1963 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
1964 LOG.error("Error reading the router interfaces for {}", routerInterfacesId, e);
1971 * Creates the corresponding static routes in the specified VPN. These static routes must be point to an
1972 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink. Otherwise the
1973 * route will be ignored.
1975 * @param vpnName the VPN identifier
1976 * @param interVpnLinkRoutes The list of static routes
1977 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
1979 public void addInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
1980 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
1981 for (Routes route : interVpnLinkRoutes) {
1982 String nexthop = route.getNexthop().stringValue();
1983 String destination = route.getDestination().stringValue();
1984 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
1985 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
1986 AddStaticRouteInput rpcInput =
1987 new AddStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
1988 .setVpnInstanceName(vpnName.getValue())
1990 Future<RpcResult<AddStaticRouteOutput>> labelOuputFtr = vpnRpcService.addStaticRoute(rpcInput);
1991 RpcResult<AddStaticRouteOutput> rpcResult;
1993 rpcResult = labelOuputFtr.get();
1994 if (rpcResult.isSuccessful()) {
1995 LOG.debug("Label generated for destination {} is: {}",
1996 destination, rpcResult.getResult().getLabel());
1998 LOG.error("RPC call to add a static Route to {} with nexthop {} returned with errors {}",
1999 destination, nexthop, rpcResult.getErrors());
2001 } catch (InterruptedException | ExecutionException e) {
2002 LOG.error("Error happened while invoking addStaticRoute RPC for nexthop {} with destination {} "
2003 + "for VPN {}", nexthop, destination, vpnName.getValue(), e);
2006 // Any other case is a fault.
2007 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2008 route.getDestination().stringValue(), nexthop);
2015 * Removes the corresponding static routes from the specified VPN. These static routes point to an
2016 * InterVpnLink endpoint and the specified VPN must be the other end of the InterVpnLink.
2018 * @param vpnName the VPN identifier
2019 * @param interVpnLinkRoutes The list of static routes
2020 * @param nexthopsXinterVpnLinks A Map with the correspondence nextHop-InterVpnLink
2022 public void removeInterVpnRoutes(Uuid vpnName, List<Routes> interVpnLinkRoutes,
2023 HashMap<String, InterVpnLink> nexthopsXinterVpnLinks) {
2024 for (Routes route : interVpnLinkRoutes) {
2025 String nexthop = route.getNexthop().stringValue();
2026 String destination = route.getDestination().stringValue();
2027 InterVpnLink interVpnLink = nexthopsXinterVpnLinks.get(nexthop);
2028 if (isNexthopTheOtherVpnLinkEndpoint(nexthop, vpnName.getValue(), interVpnLink)) {
2029 RemoveStaticRouteInput rpcInput =
2030 new RemoveStaticRouteInputBuilder().setDestination(destination).setNexthop(nexthop)
2031 .setVpnInstanceName(vpnName.getValue())
2034 LoggingFutures.addErrorLogging(JdkFutureAdapters.listenInPoolThread(
2035 vpnRpcService.removeStaticRoute(rpcInput)), LOG, "Remove VPN routes");
2037 // Any other case is a fault.
2038 LOG.warn("route with destination {} and nexthop {} does not apply to any InterVpnLink",
2039 route.getDestination().stringValue(), nexthop);
2046 * Returns true if the specified nexthop is the other endpoint in an
2047 * InterVpnLink, regarding one of the VPN's point of view.
2049 private static boolean isNexthopTheOtherVpnLinkEndpoint(String nexthop, String thisVpnUuid,
2050 InterVpnLink interVpnLink) {
2052 interVpnLink != null
2053 && (interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2054 && interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nexthop)
2055 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(thisVpnUuid)
2056 && interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(nexthop));
2060 protected List<Adjacency> getAdjacencyforExtraRoute(List<Routes> routeList, String fixedIp) {
2061 List<Adjacency> adjList = new ArrayList<>();
2062 Map<String, List<String>> adjMap = new HashMap<>();
2063 for (Routes route : routeList) {
2064 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2065 LOG.error("Incorrect input received for extra route. {}", route);
2067 String nextHop = route.getNexthop().stringValue();
2068 String destination = route.getDestination().stringValue();
2069 if (!nextHop.equals(fixedIp)) {
2070 LOG.trace("FixedIP {} is not extra route nexthop for destination {}", fixedIp, destination);
2073 LOG.trace("Adding extra route for destination {} with nexthop {} ", destination,
2075 List<String> hops = adjMap.computeIfAbsent(destination, k -> new ArrayList<>());
2076 if (!hops.contains(nextHop)) {
2082 for (Entry<String, List<String>> entry : adjMap.entrySet()) {
2083 final String destination = entry.getKey();
2084 final List<String> ipList = entry.getValue();
2085 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2086 .setAdjacencyType(AdjacencyType.ExtraRoute).setNextHopIpList(ipList)
2087 .withKey(new AdjacencyKey(destination)).build();
2093 protected void updateVpnInterfaceWithExtraRouteAdjacency(Uuid vpnId, List<Routes> routeList) {
2094 checkAlarmExtraRoutes(vpnId, routeList);
2096 for (Routes route : routeList) {
2097 if (route == null || route.getNexthop() == null || route.getDestination() == null) {
2098 LOG.error("Incorrect input received for extra route. {}", route);
2100 String nextHop = route.getNexthop().stringValue();
2101 String destination = route.getDestination().stringValue();
2102 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2104 if (infName != null) {
2105 LOG.trace("Updating extra route for destination {} onto vpn {} with nexthop {} and infName {}",
2106 destination, vpnId.getValue(), nextHop, infName);
2107 boolean isLockAcquired = false;
2109 InstanceIdentifier<VpnInterface> identifier = InstanceIdentifier.builder(VpnInterfaces.class)
2110 .child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2111 InstanceIdentifier<Adjacency> path = identifier.augmentation(Adjacencies.class)
2112 .child(Adjacency.class, new AdjacencyKey(destination));
2113 Optional<Adjacency> existingAdjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2114 LogicalDatastoreType.CONFIGURATION, path);
2115 if (existingAdjacency.isPresent()
2116 && existingAdjacency.get().getAdjacencyType() == AdjacencyType.PrimaryAdjacency) {
2117 LOG.error("The route with destination {} nextHop {} is already present as"
2118 + " a primary adjacency for interface {}. Skipping adjacency addition.",
2119 destination, nextHop, infName);
2122 Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination)
2123 .setNextHopIpList(Collections.singletonList(nextHop)).withKey(new AdjacencyKey(destination))
2124 .setAdjacencyType(AdjacencyType.ExtraRoute).build();
2126 try (AcquireResult lock = tryInterfaceLock(infName)) {
2127 if (!lock.wasAcquired()) {
2128 // FIXME: why do we even bother with locking if we do not honor it?!
2129 logTryLockFailure(infName);
2132 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
2135 } catch (TransactionCommitFailedException e) {
2136 LOG.error("exception in adding extra route with destination: {}, next hop: {}",
2137 destination, nextHop, e);
2138 } catch (ExecutionException | InterruptedException e) {
2139 LOG.error("Exception on reading data-store ", e);
2142 LOG.error("Unable to find VPN NextHop interface to apply extra-route destination {} on VPN {} "
2143 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2150 * This method setup or down an alarm about extra route fault.
2151 * When extra routes are configured, through a router, if the number of nexthops is greater than the number of
2152 * available RDs, then an alarm and an error is generated.<br>
2153 * <b>Be careful</b> the routeList could be changed.
2155 * @param vpnId the vpnId of vpn to control.
2156 * @param routeList the list of router to check, it could be modified.
2158 private void checkAlarmExtraRoutes(Uuid vpnId, List<Routes> routeList) {
2159 if (!neutronvpnAlarm.isAlarmEnabled()) {
2160 LOG.debug("checkAlarmExtraRoutes is not enable for vpnId {} routeList {}", vpnId, routeList);
2163 VpnInstance vpnInstance = neutronvpnUtils.getVpnInstance(dataBroker, vpnId);
2164 if (vpnInstance == null || routeList == null || routeList.isEmpty() || !neutronvpnAlarm.isAlarmEnabled()) {
2165 LOG.debug("checkAlarmExtraRoutes have args null as following : vpnId {} routeList {}",
2169 String primaryRd = neutronvpnUtils.getVpnRd(vpnId.getValue());
2170 if (primaryRd == null || primaryRd.equals(vpnId.getValue())) {
2171 LOG.debug("checkAlarmExtraRoutes. vpn {} is not a BGPVPN. cancel checkExtraRoute",
2175 for (Routes route : routeList) {
2176 // count the number of nexthops for each same route.getDestingation().getValue()
2177 String destination = route.getDestination().stringValue();
2178 String nextHop = route.getNexthop().stringValue();
2179 List<String> nextHopList = new ArrayList<>();
2180 nextHopList.add(nextHop);
2182 for (Routes routeTmp : routeList) {
2183 String routeDest = routeTmp.getDestination().stringValue();
2184 if (!destination.equals(routeDest)) {
2187 String routeNextH = routeTmp.getNexthop().stringValue();
2188 if (nextHop.equals(routeNextH)) {
2192 nextHopList.add(routeTmp.getNexthop().stringValue());
2194 final List<String> rdList = new ArrayList<>();
2195 if (vpnInstance != null
2196 && vpnInstance.getRouteDistinguisher() != null) {
2197 vpnInstance.getRouteDistinguisher().forEach(rd -> {
2203 // 1. VPN Instance Name
2204 String typeAlarm = "for vpnId: " + vpnId + " have exceeded next hops for prefixe";
2207 List<Uuid> routerUuidList = neutronvpnUtils.getRouterIdListforVpn(vpnId);
2208 Uuid routerUuid = routerUuidList.get(0);
2209 StringBuilder detailsAlarm = new StringBuilder("routerUuid: ");
2210 detailsAlarm.append(routerUuid == null ? vpnId.toString() : routerUuid.getValue());
2212 // 3. List of RDs associated with the VPN
2213 detailsAlarm.append(" List of RDs associated with the VPN: ");
2214 for (String s : rdList) {
2215 detailsAlarm.append(s);
2216 detailsAlarm.append(", ");
2219 // 4. Prefix in question
2220 detailsAlarm.append(" for prefix: ");
2221 detailsAlarm.append(route.getDestination().stringValue());
2223 // 5. List of NHs for the prefix
2224 detailsAlarm.append(" for nextHops: ");
2225 for (String s : nextHopList) {
2226 detailsAlarm.append(s);
2227 detailsAlarm.append(", ");
2230 if (rdList.size() < nbNextHops) {
2231 neutronvpnAlarm.raiseNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2233 neutronvpnAlarm.clearNeutronvpnAlarm(typeAlarm, detailsAlarm.toString());
2238 // TODO Clean up the exception handling
2239 @SuppressWarnings("checkstyle:IllegalCatch")
2240 protected void removeAdjacencyforExtraRoute(Uuid vpnId, List<Routes> routeList) {
2241 for (Routes route : routeList) {
2242 if (route != null && route.getNexthop() != null && route.getDestination() != null) {
2243 String nextHop = route.getNexthop().stringValue();
2244 String destination = route.getDestination().stringValue();
2245 String infName = neutronvpnUtils.getNeutronPortNameFromVpnPortFixedIp(vpnId.getValue(),
2247 if (infName == null) {
2248 LOG.error("Unable to find VPN NextHop interface to remove extra-route destination {} on VPN {} "
2249 + "with nexthop {}", destination, vpnId.getValue(), nextHop);
2250 // Proceed to remove the next extra-route
2253 LOG.trace("Removing extra route for destination {} on vpn {} with nexthop {} and infName {}",
2254 destination, vpnId.getValue(), nextHop, infName);
2256 InstanceIdentifier<Adjacency> adjacencyIdentifier =
2257 InstanceIdentifier.builder(VpnInterfaces.class)
2258 .child(VpnInterface.class, new VpnInterfaceKey(infName))
2259 .augmentation(Adjacencies.class)
2260 .child(Adjacency.class, new AdjacencyKey(destination))
2264 // Looking for existing prefix in MDSAL database
2265 Optional<Adjacency> adjacency = SingleTransactionDataBroker.syncReadOptional(dataBroker,
2266 LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
2267 boolean updateNextHops = false;
2268 List<String> nextHopList = new ArrayList<>();
2269 if (adjacency.isPresent()) {
2270 List<String> nhListRead = adjacency.get().getNextHopIpList();
2271 if (nhListRead.size() > 1) { // ECMP case
2272 for (String nextHopRead : nhListRead) {
2273 if (nextHopRead.equals(nextHop)) {
2274 updateNextHops = true;
2276 nextHopList.add(nextHopRead);
2282 try (AcquireResult lock = tryInterfaceLock(infName)) {
2283 if (!lock.wasAcquired()) {
2284 // FIXME: why do we even bother with locking if we do not honor it?!
2285 logTryLockFailure(infName);
2288 if (updateNextHops) {
2289 // An update must be done, not including the current next hop
2290 InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(
2291 VpnInterfaces.class).child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
2292 Adjacency newAdj = new AdjacencyBuilder(adjacency.get()).setIpAddress(destination)
2293 .setNextHopIpList(nextHopList)
2294 .withKey(new AdjacencyKey(destination))
2296 List<Adjacency> newAdjList = Collections.singletonList(newAdj);
2297 Adjacencies erAdjs =
2298 new AdjacenciesBuilder().setAdjacency(getAdjacencyMap(newAdjList)).build();
2299 VpnInterface vpnIf = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
2300 .addAugmentation(Adjacencies.class, erAdjs).build();
2301 SingleTransactionDataBroker.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION,
2302 vpnIfIdentifier, vpnIf);
2304 // Remove the whole route
2305 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
2306 adjacencyIdentifier);
2307 LOG.trace("extra route {} deleted successfully", route);
2310 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException e) {
2311 LOG.error("exception in deleting extra route with destination {} for interface {}",
2312 destination, infName, e);
2315 LOG.error("Incorrect input received for extra route: {}", route);
2320 public void removeVpn(Uuid vpnId) {
2322 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2323 if (vpnMap != null) {
2324 Map<RouterIdsKey, RouterIds> keyRouterIdsMap = vpnMap.getRouterIds();
2325 List<Uuid> routerUuidList = new ArrayList<>();
2326 // dissociate router
2327 if (keyRouterIdsMap != null && !keyRouterIdsMap.isEmpty()) {
2328 for (RouterIds router : keyRouterIdsMap.values()) {
2329 Uuid routerId = router.getRouterId();
2330 routerUuidList.add(routerId);
2331 dissociateRouterFromVpn(vpnId, routerId);
2334 if (!routerUuidList.contains(vpnId) && vpnMap.getNetworkIds() != null) {
2335 dissociateNetworksFromVpn(vpnId, vpnMap.getNetworkIds());
2338 LOG.error("removeVpn: vpnMap is null for vpn {}", vpnId.getValue());
2340 // remove entire vpnMaps node
2341 deleteVpnMapsNode(vpnId);
2343 // remove vpn-instance
2344 deleteVpnInstance(vpnId);
2345 LOG.debug("Deleted L3VPN with ID {}", vpnId.getValue());
2348 private boolean isVpnOfTypeL2(VpnInstance vpnInstance) {
2349 return vpnInstance != null && vpnInstance.isL2vpn();
2352 // TODO Clean up the exception handling
2353 @SuppressWarnings("checkstyle:IllegalCatch")
2354 protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
2355 updateVpnMaps(vpnId, null, routerId, null, null);
2356 LOG.debug("associateRouterToVpn: Updating association of subnets to external vpn {}", vpnId.getValue());
2357 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2358 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2359 for (Subnetmap sn : subMapList) {
2360 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2361 if (!ipVersion.isIpVersionChosen(ipVers)) {
2362 ipVersion = ipVersion.addVersion(ipVers);
2365 if (ipVersion != IpVersionChoice.UNDEFINED) {
2366 LOG.debug("associateRouterToVpn: Updating vpnInstance ip address family {} for VPN {} ",
2368 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2370 for (Subnetmap sn : subMapList) {
2371 updateVpnForSubnet(routerId, vpnId, sn.getId(), true);
2375 protected void associateRouterToInternalVpn(Uuid vpnId, Uuid routerId) {
2376 List<Uuid> routerSubnets = neutronvpnUtils.getNeutronRouterSubnetIds(routerId);
2377 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
2378 LOG.debug("Adding subnets to internal vpn {}", vpnId.getValue());
2379 for (Uuid subnet : routerSubnets) {
2380 IpVersionChoice version = NeutronvpnUtils
2381 .getIpVersionFromSubnet(neutronvpnUtils.getSubnetmap(subnet));
2382 if (version.isIpVersionChosen(IpVersionChoice.IPV4)) {
2383 addSubnetToVpn(vpnId, subnet, null);
2385 addSubnetToVpn(vpnId, subnet, internetVpnId);
2390 // TODO Clean up the exception handling
2391 @SuppressWarnings("checkstyle:IllegalCatch")
2392 protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
2394 clearFromVpnMaps(vpnId, routerId, null);
2395 List<Subnetmap> subMapList = neutronvpnUtils.getNeutronRouterSubnetMapList(routerId);
2396 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2397 for (Subnetmap sn : subMapList) {
2398 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sn.getSubnetIp());
2399 if (ipVersion.isIpVersionChosen(ipVers)) {
2400 ipVersion = ipVersion.addVersion(ipVers);
2402 LOG.debug("dissociateRouterFromVpn: Updating association of subnets to internal vpn {}",
2403 routerId.getValue());
2404 updateVpnForSubnet(vpnId, routerId, sn.getId(), false);
2406 if (ipVersion != IpVersionChoice.UNDEFINED) {
2407 LOG.debug("dissociateRouterFromVpn; Updating vpnInstance with ip address family {} for VPN {} ",
2409 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion,
2415 * Parses and associates networks list with given VPN.
2417 * @param vpnId Uuid of given VPN.
2418 * @param networkList List list of network Ids (Uuid), which will be associated.
2419 * @return list of formatted strings with detailed error messages.
2422 protected List<String> associateNetworksToVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2423 List<String> failedNwList = new ArrayList<>();
2424 HashSet<Uuid> passedNwList = new HashSet<>();
2425 ConcurrentMap<Uuid, Network> extNwMap = new ConcurrentHashMap<>();
2426 boolean isExternalNetwork = false;
2427 if (networkList.isEmpty()) {
2428 LOG.error("associateNetworksToVpn: Failed as given networks list is empty, VPN Id: {}", vpnId.getValue());
2429 failedNwList.add(String.format("Failed to associate networks with VPN %s as given networks list is empty",
2431 return failedNwList;
2433 VpnInstance vpnInstance = VpnHelper.getVpnInstance(dataBroker, vpnId.getValue());
2434 if (vpnInstance == null) {
2435 LOG.error("associateNetworksToVpn: Can not find vpnInstance for VPN {} in ConfigDS", vpnId.getValue());
2436 failedNwList.add(String.format("Failed to associate network: can not found vpnInstance for VPN %s "
2437 + "in ConfigDS", vpnId.getValue()));
2438 return failedNwList;
2441 if (isVpnOfTypeL2(vpnInstance) && neutronEvpnUtils.isVpnAssociatedWithNetwork(vpnInstance)) {
2442 LOG.error("associateNetworksToVpn: EVPN {} supports only one network to be associated with",
2444 failedNwList.add(String.format("Failed to associate network: EVPN %s supports only one network to be "
2445 + "associated with", vpnId.getValue()));
2446 return failedNwList;
2448 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2449 boolean isIpFamilyUpdated = false;
2450 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2451 for (Uuid nw : networkList) {
2452 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2453 if (network == null) {
2454 LOG.error("associateNetworksToVpn: Network {} not found in ConfigDS", nw.getValue());
2455 failedNwList.add(String.format("Failed to associate network: network %s not found in ConfigDS",
2459 NetworkProviderExtension providerExtension = network.augmentation(NetworkProviderExtension.class);
2460 if (providerExtension.getSegments() != null && providerExtension.getSegments().size() > 1) {
2461 LOG.error("associateNetworksToVpn: MultiSegmented network {} not supported in BGPVPN {}",
2462 nw.getValue(), vpnId.getValue());
2463 failedNwList.add(String.format("Failed to associate multisegmented network %s with BGPVPN %s",
2464 nw.getValue(), vpnId.getValue()));
2467 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2468 if (networkVpnId != null) {
2469 LOG.error("associateNetworksToVpn: Network {} already associated with another VPN {}",
2470 nw.getValue(), networkVpnId.getValue());
2471 failedNwList.add(String.format("Failed to associate network %s as it is already associated to "
2472 + "another VPN %s", nw.getValue(), networkVpnId.getValue()));
2475 /* Handle association of external network(s) to Internet BGP-VPN use case outside of the
2476 * networkList iteration
2478 if (neutronvpnUtils.getIsExternal(network)) {
2479 extNwMap.put(nw, network);
2480 isExternalNetwork = true;
2481 //Check whether router-gw is set with external network before external network to BGPVPN association
2482 List<Uuid> routerList = neutronvpnUtils.getRouterIdsForExtNetwork(nw);
2483 if (!routerList.isEmpty()) {
2484 for (Uuid routerId : routerList) {
2485 //If v6 subnet was already added to router means it requires IPv6 AddrFamily in VpnInstance
2486 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
2487 ipVersion = ipVersion.addVersion(IpVersionChoice.IPV6);
2488 LOG.debug("associateNetworksToVpn: External network {} is already associated with "
2489 + "router(router-gw) {} and V6 subnet is part of that router. Hence Set IPv6 "
2490 + "address family type in Internet VPN Instance {}", network, routerId, vpnId);
2496 List<Subnetmap> subnetmapList = neutronvpnUtils.getSubnetmapListFromNetworkId(nw);
2497 if (subnetmapList == null || subnetmapList.isEmpty()) {
2498 passedNwList.add(nw);
2501 if (vpnManager.checkForOverlappingSubnets(nw, subnetmapList, vpnId, routeTargets, failedNwList)) {
2504 for (Subnetmap subnetmap : subnetmapList) {
2505 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2506 if (!ipVersion.isIpVersionChosen(ipVers)) {
2507 ipVersion = ipVersion.addVersion(ipVers);
2510 //Update vpnInstance for IP address family
2511 if (ipVersion != IpVersionChoice.UNDEFINED && !isIpFamilyUpdated) {
2512 LOG.debug("associateNetworksToVpn: Updating vpnInstance with ip address family {}"
2513 + " for VPN {} ", ipVersion, vpnId);
2514 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, true);
2515 isIpFamilyUpdated = true;
2517 for (Subnetmap subnetmap : subnetmapList) {
2518 Uuid subnetId = subnetmap.getId();
2519 Uuid subnetVpnId = neutronvpnUtils.getVpnForSubnet(subnetId);
2520 if (subnetVpnId != null) {
2521 LOG.error("associateNetworksToVpn: Failed to associate subnet {} with VPN {}"
2522 + " as it is already associated", subnetId.getValue(), subnetVpnId.getValue());
2523 failedNwList.add(String.format("Failed to associate subnet %s with VPN %s"
2524 + " as it is already associated", subnetId.getValue(), vpnId.getValue()));
2527 if (!NeutronvpnUtils.getIsExternal(network)) {
2528 LOG.debug("associateNetworksToVpn: Add subnet {} to VPN {}", subnetId.getValue(),
2530 addSubnetToVpn(vpnId, subnetId, null);
2531 vpnManager.updateRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2533 passedNwList.add(nw);
2536 passedNwList.add(nw);
2537 //Handle association of external network(s) to Internet BGP-VPN Instance use case
2538 if (!extNwMap.isEmpty() || extNwMap != null) {
2539 for (Network extNw : extNwMap.values()) {
2540 if (!associateExtNetworkToVpn(vpnId, extNw, vpnInstance.getBgpvpnType())) {
2541 LOG.error("associateNetworksToVpn: Failed to associate Provider External Network {} with "
2542 + "VPN {}", extNw, vpnId.getValue());
2543 failedNwList.add(String.format("Failed to associate Provider External Network %s with "
2544 + "VPN %s", extNw, vpnId.getValue()));
2550 } catch (ExecutionException | InterruptedException e) {
2551 LOG.error("associateNetworksToVpn: Failed to associate VPN {} with networks {}: ", vpnId.getValue(),
2553 failedNwList.add(String.format("Failed to associate VPN %s with networks %s: %s", vpnId.getValue(),
2556 //VpnMap update for ext-nw is already done in associateExtNetworkToVpn() method.
2557 if (!isExternalNetwork) {
2558 updateVpnMaps(vpnId, null, null, null, new ArrayList<>(passedNwList));
2560 LOG.info("Network(s) {} associated to L3VPN {} successfully", passedNwList, vpnId.getValue());
2561 return failedNwList;
2564 private boolean associateExtNetworkToVpn(@NonNull Uuid vpnId, @NonNull Network extNet,
2565 VpnInstance.BgpvpnType bgpVpnType) {
2566 if (!addExternalNetworkToVpn(extNet, vpnId)) {
2569 if (!bgpVpnType.equals(VpnInstance.BgpvpnType.InternetBGPVPN)) {
2570 LOG.info("associateExtNetworkToVpn: External network {} is associated to VPN {}."
2571 + "Hence set vpnInstance type to {} from {} ", extNet.key().getUuid().getValue(),
2572 vpnId.getValue(), VpnInstance.BgpvpnType.InternetBGPVPN.getName(),
2573 VpnInstance.BgpvpnType.BGPVPN.getName());
2574 neutronvpnUtils.updateVpnInstanceWithBgpVpnType(VpnInstance.BgpvpnType.InternetBGPVPN, vpnId);
2576 //Update VpnMap with ext-nw is needed first before processing V6 internet default fallback flows
2577 List<Uuid> extNwList = Collections.singletonList(extNet.key().getUuid());
2578 updateVpnMaps(vpnId, null, null, null, extNwList);
2579 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2580 for (Uuid snId: neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2581 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2583 LOG.error("associateExtNetworkToVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2586 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2587 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2590 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2591 updateVpnInternetForSubnet(sm, vpnId, true);
2593 if (!ipVersion.isIpVersionChosen(ipVers)) {
2594 ipVersion = ipVersion.addVersion(ipVers);
2597 if (ipVersion != IpVersionChoice.UNDEFINED) {
2598 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, true);
2599 LOG.info("associateExtNetworkToVpn: add IPv6 Internet default route in VPN {}", vpnId.getValue());
2600 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, true);
2606 * Parses and disassociates networks list from given VPN.
2608 * @param vpnId Uuid of given VPN.
2609 * @param networkList List list of network Ids (Uuid), which will be disassociated.
2610 * @return list of formatted strings with detailed error messages.
2613 protected List<String> dissociateNetworksFromVpn(@NonNull Uuid vpnId, @NonNull List<Uuid> networkList) {
2614 List<String> failedNwList = new ArrayList<>();
2615 HashSet<Uuid> passedNwList = new HashSet<>();
2616 ConcurrentMap<Uuid, Network> extNwMap = new ConcurrentHashMap<>();
2617 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2618 if (networkList.isEmpty()) {
2619 LOG.error("dissociateNetworksFromVpn: Failed as networks list is empty");
2620 failedNwList.add(String.format("Failed to disassociate networks from VPN %s as networks list is empty",
2622 return failedNwList;
2624 for (Uuid nw : networkList) {
2625 List<Uuid> networkSubnets = neutronvpnUtils.getSubnetIdsFromNetworkId(nw);
2626 if (networkSubnets == null) {
2627 passedNwList.add(nw);
2630 Network network = neutronvpnUtils.getNeutronNetwork(nw);
2631 if (network == null) {
2632 LOG.error("dissociateNetworksFromVpn: Network {} not found in ConfigDS", nw.getValue());
2633 failedNwList.add(String.format("Failed to disassociate network %s as is not found in ConfigDS",
2637 Uuid networkVpnId = neutronvpnUtils.getVpnForNetwork(nw);
2638 if (networkVpnId == null) {
2639 LOG.error("dissociateNetworksFromVpn: Network {} is not associated to any VPN", nw.getValue());
2640 failedNwList.add(String.format("Failed to disassociate network %s as is not associated to any VPN",
2644 if (!vpnId.equals(networkVpnId)) {
2645 LOG.error("dissociateNetworksFromVpn: Network {} is associated to another VPN {} instead of given {}",
2646 nw.getValue(), networkVpnId.getValue(), vpnId.getValue());
2647 failedNwList.add(String.format("Failed to disassociate network %s as it is associated to another "
2648 + "vpn %s instead of given %s", nw.getValue(), networkVpnId.getValue(),
2652 /* Handle disassociation of external network(s) from Internet BGP-VPN use case outside of the
2653 * networkList iteration
2655 if (neutronvpnUtils.getIsExternal(network)) {
2656 extNwMap.put(nw, network);
2657 //Handle external-Nw to BGPVPN Disassociation and still ext-router is being set with external-Nw
2658 List<Uuid> routerList = neutronvpnUtils.getRouterIdsForExtNetwork(nw);
2659 if (!routerList.isEmpty()) {
2660 for (Uuid routerId : routerList) {
2661 //If v6 subnet was already added to router means it requires IPv6 AddrFamily in VpnInstance
2662 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
2663 ipVersion = ipVersion.addVersion(IpVersionChoice.IPV6);
2664 LOG.debug("dissociateNetworksFromVpn: External network {} is still associated with "
2665 + "router(router-gw) {} and V6 subnet is part of that router. Hence Set IPv6 "
2666 + "address family type in Internet VPN Instance {}", network, routerId, vpnId);
2672 for (Uuid subnet : networkSubnets) {
2673 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnet);
2674 if (subnetmap == null) {
2675 failedNwList.add(String.format("subnetmap %s not found for network %s",
2676 subnet.getValue(), nw.getValue()));
2677 LOG.error("dissociateNetworksFromVpn: Subnetmap for subnet {} not found when "
2678 + "dissociating network {} from VPN {}", subnet.getValue(), nw.getValue(),
2682 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(subnetmap.getSubnetIp());
2683 if (!ipVersion.isIpVersionChosen(ipVers)) {
2684 ipVersion = ipVersion.addVersion(ipVers);
2686 if (!NeutronvpnUtils.getIsExternal(network)) {
2687 LOG.debug("dissociateNetworksFromVpn: Withdraw subnet {} from VPN {}", subnet.getValue(),
2689 removeSubnetFromVpn(vpnId, subnetmap, null);
2690 Set<VpnTarget> routeTargets = vpnManager.getRtListForVpn(vpnId.getValue());
2691 vpnManager.removeRouteTargetsToSubnetAssociation(routeTargets, subnetmap.getSubnetIp(),
2693 passedNwList.add(nw);
2696 if (ipVersion != IpVersionChoice.UNDEFINED) {
2697 LOG.debug("dissociateNetworksFromVpn: Updating vpnInstance with ip address family {}"
2698 + " for VPN {}", ipVersion, vpnId);
2699 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), ipVersion, false);
2702 //Handle disassociation of external network(s) from Internet BGP-VPN Instance use case
2703 if (!extNwMap.isEmpty() || extNwMap != null) {
2704 for (Network extNw : extNwMap.values()) {
2705 if (disassociateExtNetworkFromVpn(vpnId, extNw)) {
2706 passedNwList.add(extNw.getUuid());
2708 LOG.error("dissociateNetworksFromVpn: Failed to withdraw External Provider Network {} from VPN {}",
2709 extNw, vpnId.getValue());
2710 failedNwList.add(String.format("Failed to withdraw External Provider Network %s from VPN %s",
2711 extNw, vpnId.getValue()));
2716 clearFromVpnMaps(vpnId, null, new ArrayList<>(passedNwList));
2717 LOG.info("dissociateNetworksFromVpn: Network(s) {} disassociated from L3VPN {} successfully",
2718 passedNwList, vpnId.getValue());
2719 return failedNwList;
2722 private boolean disassociateExtNetworkFromVpn(@NonNull Uuid vpnId, @NonNull Network extNet) {
2723 if (!removeExternalNetworkFromVpn(extNet)) {
2726 // check, if there is another Provider Networks associated with given VPN
2727 List<Uuid> vpnNets = getNetworksForVpn(vpnId);
2728 if (vpnNets != null) {
2729 //Remove currently disassociated network from the list
2730 vpnNets.remove(extNet.getUuid());
2731 for (Uuid netId : vpnNets) {
2732 if (NeutronvpnUtils.getIsExternal(getNeutronNetwork(netId))) {
2733 LOG.error("dissociateExtNetworkFromVpn: Internet VPN {} is still associated with Provider Network "
2734 + "{}", vpnId.getValue(), netId.getValue());
2739 ///Set VPN Type is BGPVPN from InternetBGPVPN
2740 LOG.info("disassociateExtNetworkFromVpn: Set BGP-VPN type with {} for VPN {} and update IPv6 address family. "
2741 + "Since external network is disassociated from VPN {}",
2742 VpnInstance.BgpvpnType.BGPVPN, extNet, vpnId.getValue());
2743 neutronvpnUtils.updateVpnInstanceWithBgpVpnType(VpnInstance.BgpvpnType.BGPVPN, vpnId);
2744 IpVersionChoice ipVersion = IpVersionChoice.UNDEFINED;
2745 for (Uuid snId : neutronvpnUtils.getPrivateSubnetsToExport(extNet, vpnId)) {
2746 Subnetmap sm = neutronvpnUtils.getSubnetmap(snId);
2748 LOG.error("disassociateExtNetworkFromVpn: can not find subnet with Id {} in ConfigDS", snId.getValue());
2751 IpVersionChoice ipVers = NeutronvpnUtils.getIpVersionFromString(sm.getSubnetIp());
2752 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV4)) {
2755 if (ipVers.isIpVersionChosen(IpVersionChoice.IPV6)) {
2756 updateVpnInternetForSubnet(sm, vpnId, false);
2758 if (!ipVersion.isIpVersionChosen(ipVers)) {
2759 ipVersion = ipVersion.addVersion(ipVers);
2762 if (ipVersion != IpVersionChoice.UNDEFINED) {
2763 neutronvpnUtils.updateVpnInstanceWithIpFamily(vpnId.getValue(), IpVersionChoice.IPV6, false);
2764 LOG.info("disassociateExtNetworkFromVpn: withdraw IPv6 Internet default route from VPN {}",
2766 neutronvpnUtils.updateVpnInstanceWithFallback(/*routerId*/ null, vpnId, false);
2772 * It handles the invocations to the neutronvpn:associateNetworks RPC method.
2775 // TODO Clean up the exception handling
2776 @SuppressWarnings("checkstyle:IllegalCatch")
2777 public ListenableFuture<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
2779 AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
2780 SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
2781 StringBuilder returnMsg = new StringBuilder();
2782 Uuid vpnId = input.getVpnId();
2785 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2786 LOG.debug("associateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2787 input.getNetworkId());
2788 List<Uuid> netIds = input.getNetworkId();
2789 if (netIds != null && !netIds.isEmpty()) {
2790 List<String> failed = associateNetworksToVpn(vpnId, netIds);
2791 if (!failed.isEmpty()) {
2792 returnMsg.append(failed);
2796 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2798 if (returnMsg.length() != 0) {
2799 opBuilder.setResponse(
2800 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2801 "associate Networks to vpn {} failed due to {}", vpnId.getValue(), returnMsg));
2802 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
2804 result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
2806 } catch (Exception ex) {
2807 LOG.error("associate Networks to vpn failed {}", input.getVpnId().getValue(), ex);
2808 result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2809 formatAndLog(LOG::error, "associate Networks to vpn {} failed due to {}",
2810 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2812 LOG.debug("associateNetworks returns..");
2817 * It handles the invocations to the neutronvpn:associateRouter RPC method.
2820 public ListenableFuture<RpcResult<AssociateRouterOutput>> associateRouter(AssociateRouterInput input) {
2822 SettableFuture<RpcResult<AssociateRouterOutput>> result = SettableFuture.create();
2823 LOG.debug("associateRouter {}", input);
2824 StringBuilder returnMsg = new StringBuilder();
2825 Uuid vpnId = input.getVpnId();
2826 Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter
2827 .input.RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
2828 .associaterouter.input.RouterIds> keyRouterIdsMap = input.nonnullRouterIds();
2829 Preconditions.checkArgument(!keyRouterIdsMap.isEmpty(), "associateRouter: RouterIds list is empty!");
2830 Preconditions.checkNotNull(vpnId, "associateRouter; VpnId not found!");
2831 Preconditions.checkNotNull(vpnId, "associateRouter; RouterIds not found!");
2832 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.associaterouter.input
2833 .RouterIds routerId : keyRouterIdsMap.values()) {
2834 VpnMap vpnMap = neutronvpnUtils.getVpnMap(vpnId);
2835 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2836 if (vpnMap != null) {
2838 Uuid extVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2839 if (vpnMap.getRouterIds() != null && vpnMap.getRouterIds().size() > 1) {
2840 returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
2841 .append(routerId.getRouterId());
2842 } else if (extVpnId != null) {
2843 returnMsg.append("router ").append(routerId.getRouterId()).append(" already associated to "
2844 + "another VPN ").append(extVpnId.getValue());
2846 LOG.debug("associateRouter RPC: VpnId {}, routerId {}", vpnId.getValue(),
2847 routerId.getRouterId());
2848 associateRouterToVpn(vpnId, routerId.getRouterId());
2851 returnMsg.append("router not found : ").append(routerId.getRouterId());
2854 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2856 if (returnMsg.length() != 0) {
2857 result.set(RpcResultBuilder.<AssociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
2858 "invalid-value", formatAndLog(LOG::error, "associate router to vpn {} failed "
2859 + "due to {}", routerId.getRouterId(), returnMsg)).build());
2861 result.set(RpcResultBuilder.success(new AssociateRouterOutputBuilder().build()).build());
2864 LOG.debug("associateRouter returns..");
2869 * It handles the invocations to the neutronvpn:getFixedIPsForNeutronPort RPC method.
2872 // TODO Clean up the exception handling
2873 @SuppressWarnings("checkstyle:IllegalCatch")
2874 public ListenableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(
2875 GetFixedIPsForNeutronPortInput input) {
2876 GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
2877 SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
2878 Uuid portId = input.getPortId();
2879 StringBuilder returnMsg = new StringBuilder();
2881 List<String> fixedIPList = new ArrayList<>();
2882 Port port = neutronvpnUtils.getNeutronPort(portId);
2884 for (FixedIps ip : port.nonnullFixedIps().values()) {
2885 fixedIPList.add(ip.getIpAddress().stringValue());
2888 returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
2890 if (returnMsg.length() != 0) {
2891 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
2893 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port failed due to {}",
2894 returnMsg)).build());
2896 opBuilder.setFixedIPs(fixedIPList);
2897 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
2899 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
2901 } catch (Exception ex) {
2902 result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
2903 formatAndLog(LOG::error, "Retrieval of FixedIPList for neutron port {} failed due to {}",
2904 portId.getValue(), ex.getMessage(), ex)).build());
2910 * It handles the invocations to the neutronvpn:dissociateNetworks RPC method.
2913 // TODO Clean up the exception handling
2914 @SuppressWarnings("checkstyle:IllegalCatch")
2915 public ListenableFuture<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
2917 DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
2918 SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
2920 LOG.debug("dissociateNetworks {}", input);
2921 StringBuilder returnMsg = new StringBuilder();
2922 Uuid vpnId = input.getVpnId();
2925 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2926 LOG.debug("dissociateNetworks RPC: VpnId {}, networkList {}", vpnId.getValue(),
2927 input.getNetworkId());
2928 List<Uuid> netIds = input.getNetworkId();
2929 if (netIds != null && !netIds.isEmpty()) {
2930 List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
2931 if (!failed.isEmpty()) {
2932 returnMsg.append(failed);
2936 returnMsg.append("VPN not found : ").append(vpnId.getValue());
2938 if (returnMsg.length() != 0) {
2939 opBuilder.setResponse(
2940 "ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " + formatAndLog(LOG::error,
2941 "dissociate Networks to vpn {} failed due to {}", vpnId.getValue(),
2943 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
2945 result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
2947 } catch (Exception ex) {
2948 result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION,
2949 formatAndLog(LOG::error, "dissociate Networks to vpn {} failed due to {}",
2950 input.getVpnId().getValue(), ex.getMessage(), ex)).build());
2952 LOG.debug("dissociateNetworks returns..");
2957 * It handles the invocations to the neutronvpn:dissociateRouter RPC method.
2960 // TODO Clean up the exception handling
2961 @SuppressWarnings("checkstyle:IllegalCatch")
2962 public ListenableFuture<RpcResult<DissociateRouterOutput>> dissociateRouter(DissociateRouterInput input) {
2964 SettableFuture<RpcResult<DissociateRouterOutput>> result = SettableFuture.create();
2966 LOG.debug("dissociateRouter {}", input);
2967 StringBuilder returnMsg = new StringBuilder();
2968 Uuid vpnId = input.getVpnId();
2969 Map<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2970 .RouterIdsKey, org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602
2971 .dissociaterouter.input.RouterIds> keyRouterIdsMap = input.nonnullRouterIds();
2972 String routerIdsString = "";
2973 Preconditions.checkArgument(!keyRouterIdsMap.isEmpty(), "dissociateRouter: RouterIds list is empty!");
2974 Preconditions.checkNotNull(vpnId, "dissociateRouter: vpnId not found!");
2975 Preconditions.checkNotNull(keyRouterIdsMap, "dissociateRouter: keyRouterIdsMap not found!");
2976 if (neutronvpnUtils.getVpnMap(vpnId) != null) {
2977 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.dissociaterouter.input
2978 .RouterIds routerId : keyRouterIdsMap.values()) {
2980 if (routerId != null) {
2981 routerIdsString += routerId.getRouterId() + ", ";
2982 Router rtr = neutronvpnUtils.getNeutronRouter(routerId.getRouterId());
2984 Uuid routerVpnId = neutronvpnUtils.getVpnForRouter(routerId.getRouterId(), true);
2985 if (routerVpnId == null) {
2986 returnMsg.append("input router ").append(routerId.getRouterId())
2987 .append(" not associated to any vpn yet");
2988 } else if (vpnId.equals(routerVpnId)) {
2989 dissociateRouterFromVpn(vpnId, routerId.getRouterId());
2991 returnMsg.append("input router ").append(routerId.getRouterId())
2992 .append(" associated to vpn ")
2993 .append(routerVpnId.getValue()).append("instead of the vpn given as input");
2996 returnMsg.append("router not found : ").append(routerId.getRouterId());
2999 if (returnMsg.length() != 0) {
3000 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withWarning(ErrorType.PROTOCOL,
3001 "invalid-value", formatAndLog(LOG::error, "dissociate router {} to "
3002 + "vpn {} failed due to {}", routerId.getRouterId(), vpnId.getValue(),
3003 returnMsg)).build());
3005 result.set(RpcResultBuilder.success(new DissociateRouterOutputBuilder().build()).build());
3007 } catch (Exception ex) {
3008 result.set(RpcResultBuilder.<DissociateRouterOutput>failed().withError(ErrorType.APPLICATION,
3009 formatAndLog(LOG::error, "disssociate router {} to vpn {} failed due to {}",
3010 routerId.getRouterId(), vpnId.getValue(), ex.getMessage(), ex)).build());
3014 returnMsg.append("VPN not found : ").append(vpnId.getValue());
3017 LOG.debug("dissociateRouter returns..");
3021 protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
3022 // check if the router is associated to some VPN
3023 Uuid vpnId = neutronvpnUtils.getVpnForRouter(routerId, true);
3024 Uuid internetVpnId = neutronvpnUtils.getInternetvpnUuidBoundToRouterId(routerId);
3025 if (vpnId != null) {
3026 // remove existing external vpn interfaces
3027 for (Uuid subnetId : routerSubnetIds) {
3028 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId);
3029 if (subnetmap != null) {
3030 removeSubnetFromVpn(vpnId, subnetmap, internetVpnId);
3032 LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}",
3033 subnetId, routerId.getValue());
3036 clearFromVpnMaps(vpnId, routerId, null);
3038 // remove existing internal vpn interfaces
3039 for (Uuid subnetId : routerSubnetIds) {
3040 Subnetmap subnetmap = neutronvpnUtils.getSubnetmap(subnetId);
3041 if (subnetmap != null) {
3042 removeSubnetFromVpn(routerId, subnetmap, internetVpnId);
3044 LOG.error("handleNeutronRouterDeleted: Subnetmap for subnet {} not found when deleting router {}",
3045 subnetId, routerId.getValue());
3049 // delete entire vpnMaps node for internal VPN
3050 deleteVpnMapsNode(routerId);
3052 // delete vpn-instance for internal VPN
3053 deleteVpnInstance(routerId);
3056 protected Subnet getNeutronSubnet(Uuid subnetId) {
3057 return neutronvpnUtils.getNeutronSubnet(subnetId);
3061 protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
3062 Subnet sn = neutronvpnUtils.getNeutronSubnet(subnetId);
3064 return sn.getGatewayIp();
3070 protected Network getNeutronNetwork(Uuid networkId) {
3071 return neutronvpnUtils.getNeutronNetwork(networkId);
3074 protected Port getNeutronPort(String name) {
3075 return neutronvpnUtils.getNeutronPort(new Uuid(name));
3078 protected Port getNeutronPort(Uuid portId) {
3079 return neutronvpnUtils.getNeutronPort(portId);
3082 protected Uuid getNetworkForSubnet(Uuid subnetId) {
3083 return neutronvpnUtils.getNetworkForSubnet(subnetId);
3086 protected List<Uuid> getNetworksForVpn(Uuid vpnId) {
3087 return neutronvpnUtils.getNetworksForVpn(vpnId);
3091 * Implementation of the "vpnservice:neutron-ports-show" Karaf CLI command.
3093 * @return a List of String to be printed on screen
3094 * @throws ExecutionException or InterruptedException if there was a problem reading from the data store
3096 public List<String> showNeutronPortsCLI() throws ExecutionException, InterruptedException {
3097 List<String> result = new ArrayList<>();
3098 result.add(String.format(" %-36s %-19s %-13s %-20s ", "Port ID", "Mac Address", "Prefix Length",
3100 result.add("-------------------------------------------------------------------------------------------");
3101 InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
3103 Optional<Ports> ports = syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION, portidentifier);
3104 if (ports.isPresent() && ports.get().getPort() != null) {
3105 for (Port port : ports.get().nonnullPort().values()) {
3106 Map<FixedIpsKey, FixedIps> keyFixedIpsMap = port.getFixedIps();
3107 if (keyFixedIpsMap != null && !keyFixedIpsMap.isEmpty()) {
3108 List<String> ipList = new ArrayList<>();
3109 for (FixedIps fixedIp : keyFixedIpsMap.values()) {
3110 IpAddress ipAddress = fixedIp.getIpAddress();
3111 if (ipAddress.getIpv4Address() != null) {
3112 ipList.add(ipAddress.getIpv4Address().getValue());
3114 ipList.add(ipAddress.getIpv6Address().getValue());
3117 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3118 .getMacAddress().getValue(), neutronvpnUtils.getIPPrefixFromPort(port),
3119 ipList.toString()));
3121 result.add(String.format(" %-36s %-19s %-13s %-20s ", port.getUuid().getValue(), port
3122 .getMacAddress().getValue(), "Not Assigned", "Not Assigned"));
3131 * Implementation of the "vpnservice:l3vpn-config-show" karaf CLI command.
3133 * @param vpnuuid Uuid of the VPN whose config must be shown
3134 * @return formatted output list
3135 * @throws InterruptedException if there was a thread related problem getting the data to display
3136 * @throws ExecutionException if there was any other problem getting the data to display
3138 public List<String> showVpnConfigCLI(Uuid vpnuuid) throws InterruptedException, ExecutionException {
3139 List<String> result = new ArrayList<>();
3140 if (vpnuuid == null) {
3142 result.add("Displaying VPN config for all VPNs");
3143 result.add("To display VPN config for a particular VPN, use the following syntax");
3144 result.add(getshowVpnConfigCLIHelp());
3146 RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
3147 if (rpcResult.isSuccessful()) {
3149 result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
3151 result.add(String.format(" %-80s ", "Import-RTs"));
3153 result.add(String.format(" %-80s ", "Export-RTs"));
3155 result.add(String.format(" %-76s ", "Subnet IDs"));
3157 result.add("------------------------------------------------------------------------------------");
3159 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnInstance vpn :
3160 rpcResult.getResult().nonnullL3vpnInstances()) {
3161 String tenantId = vpn.getTenantId() != null ? vpn.getTenantId().getValue()
3163 result.add(String.format(" %-37s %-37s %-7s ", vpn.getId().getValue(), tenantId,
3164 vpn.getRouteDistinguisher()));
3166 result.add(String.format(" %-80s ", vpn.getImportRT()));
3168 result.add(String.format(" %-80s ", vpn.getExportRT()));
3171 Uuid vpnid = vpn.getId();
3172 List<Uuid> subnetList = neutronvpnUtils.getSubnetsforVpn(vpnid);
3173 if (!subnetList.isEmpty()) {
3174 for (Uuid subnetuuid : subnetList) {
3175 result.add(String.format(" %-76s ", subnetuuid.getValue()));
3178 result.add(String.format(" %-76s ", "\" \""));
3181 result.add("----------------------------------------");
3185 String errortag = rpcResult.getErrors().iterator().next().getTag();
3186 if (Objects.equals(errortag, "")) {
3188 result.add("No VPN has been configured yet");
3189 } else if (Objects.equals(errortag, "invalid-value")) {
3191 result.add("VPN " + vpnuuid.getValue() + " is not present");
3193 result.add("error getting VPN info : " + rpcResult.getErrors());
3194 result.add(getshowVpnConfigCLIHelp());
3200 protected void createExternalVpnInterfaces(Uuid extNetId) {
3201 if (extNetId == null) {
3202 LOG.error("createExternalVpnInterfaces: external network is null");
3206 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3207 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3208 LOG.error("No external ports attached to external network {}", extNetId.getValue());
3212 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3213 for (String elanInterface : extElanInterfaces) {
3214 createExternalVpnInterface(extNetId, elanInterface, tx);
3216 }), LOG, "Error creating external VPN interfaces for {}", extNetId);
3219 // TODO Clean up the exception handling
3220 @SuppressWarnings("checkstyle:IllegalCatch")
3221 protected void removeExternalVpnInterfaces(Uuid extNetId) {
3222 Collection<String> extElanInterfaces = elanService.getExternalElanInterfaces(extNetId.getValue());
3223 if (extElanInterfaces == null || extElanInterfaces.isEmpty()) {
3224 LOG.error("No external ports attached for external network {}", extNetId.getValue());
3227 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3228 for (String elanInterface : extElanInterfaces) {
3229 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils
3230 .buildVpnInterfaceIdentifier(elanInterface);
3231 LOG.info("Removing vpn interface {}", elanInterface);
3232 tx.delete(vpnIfIdentifier);
3234 }), LOG, "Error removing external VPN interfaces for {}", extNetId);
3237 private void createExternalVpnInterface(Uuid vpnId, String infName,
3238 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3239 writeVpnInterfaceToDs(Collections.singletonList(vpnId), infName, null, vpnId /* external network id */,
3240 false /* not a router iface */, wrtConfigTxn);
3243 // TODO Clean up the exception handling
3244 @SuppressWarnings("checkstyle:IllegalCatch")
3245 private void writeVpnInterfaceToDs(@NonNull Collection<Uuid> vpnIdList, String infName,
3246 @Nullable Adjacencies adjacencies, Uuid networkUuid, Boolean isRouterInterface,
3247 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3248 if (vpnIdList.isEmpty() || infName == null) {
3249 LOG.error("vpnid is empty or interface({}) is null", infName);
3252 if (wrtConfigTxn == null) {
3253 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION,
3254 tx -> writeVpnInterfaceToDs(vpnIdList, infName, adjacencies, networkUuid, isRouterInterface, tx)), LOG,
3255 "Error writing VPN interface");
3258 List<VpnInstanceNames> vpnIdListStruct = new ArrayList<>();
3259 for (Uuid vpnId: vpnIdList) {
3260 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3261 AssociatedSubnetType.V4AndV6Subnets);
3262 vpnIdListStruct.add(vpnInstance);
3265 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3266 VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(infName))
3268 .setVpnInstanceNames(vpnIdListStruct)
3269 .setRouterInterface(isRouterInterface);
3270 LOG.info("Network Id is {}", networkUuid);
3271 if (networkUuid != null) {
3272 Network portNetwork = neutronvpnUtils.getNeutronNetwork(networkUuid);
3273 ProviderTypes providerType = NeutronvpnUtils.getProviderNetworkType(portNetwork);
3274 NetworkAttributes.NetworkType networkType = providerType != null
3275 ? NetworkAttributes.NetworkType.valueOf(providerType.getName()) : null;
3276 String segmentationId = NeutronvpnUtils.getSegmentationIdFromNeutronNetwork(portNetwork);
3277 vpnb.setNetworkId(networkUuid).setNetworkType(networkType)
3278 .setSegmentationId(segmentationId != null ? Long.parseLong(segmentationId) : 0L);
3281 if (adjacencies != null) {
3282 vpnb.addAugmentation(Adjacencies.class, adjacencies);
3284 VpnInterface vpnIf = vpnb.build();
3286 LOG.info("Creating vpn interface {}", vpnIf);
3287 wrtConfigTxn.put(vpnIfIdentifier, vpnIf);
3288 } catch (Exception ex) {
3289 LOG.error("Creation of vpninterface {} failed", infName, ex);
3293 private void updateVpnInterfaceWithAdjacencies(Uuid vpnId, String infName, Adjacencies adjacencies,
3294 TypedWriteTransaction<Configuration> wrtConfigTxn) {
3295 if (vpnId == null || infName == null) {
3296 LOG.error("vpn id or interface is null");
3299 if (wrtConfigTxn == null) {
3300 LOG.error("updateVpnInterfaceWithAdjancies called with wrtConfigTxn as null");
3301 LoggingFutures.addErrorLogging(txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, tx -> {
3302 updateVpnInterfaceWithAdjacencies(vpnId, infName, adjacencies, tx);
3303 }), LOG, "Error updating VPN interface with adjacencies");
3307 InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
3309 try (AcquireResult lock = tryInterfaceLock(infName)) {
3310 if (!lock.wasAcquired()) {
3311 // FIXME: why do we even bother with locking if we do not honor it?!
3312 logTryLockFailure(infName);
3316 Optional<VpnInterface> optionalVpnInterface = SingleTransactionDataBroker
3317 .syncReadOptional(dataBroker, LogicalDatastoreType
3318 .CONFIGURATION, vpnIfIdentifier);
3319 if (optionalVpnInterface.isPresent()) {
3320 VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
3321 LOG.debug("Updating vpn interface {} with new adjacencies", infName);
3323 if (adjacencies == null) {
3326 vpnIfBuilder.addAugmentation(Adjacencies.class, adjacencies);
3327 if (optionalVpnInterface.get().getVpnInstanceNames() != null) {
3328 List<VpnInstanceNames> listVpnInstances = new ArrayList<>(
3329 optionalVpnInterface.get().getVpnInstanceNames().values());
3330 if (listVpnInstances.isEmpty()
3331 || !VpnHelper.doesVpnInterfaceBelongToVpnInstance(vpnId.getValue(), listVpnInstances)) {
3332 VpnInstanceNames vpnInstance = VpnHelper.getVpnInterfaceVpnInstanceNames(vpnId.getValue(),
3333 AssociatedSubnetType.V4AndV6Subnets);
3334 listVpnInstances.add(vpnInstance);
3335 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3338 VpnInstanceNames vpnInstance = VpnHelper
3339 .getVpnInterfaceVpnInstanceNames(vpnId.getValue(), AssociatedSubnetType.V4AndV6Subnets);
3340 List<VpnInstanceNames> listVpnInstances = new ArrayList<>();
3341 listVpnInstances.add(vpnInstance);
3342 vpnIfBuilder.setVpnInstanceNames(listVpnInstances);
3344 LOG.info("Updating vpn interface {} with new adjacencies", infName);
3345 wrtConfigTxn.put(vpnIfIdentifier, vpnIfBuilder.build());
3347 } catch (IllegalStateException | ExecutionException | InterruptedException ex) {
3348 // FIXME: why are we catching IllegalStateException here?
3349 LOG.error("Update of vpninterface {} failed", infName, ex);
3354 private String getshowVpnConfigCLIHelp() {
3355 StringBuilder help = new StringBuilder("Usage:");
3356 help.append("display vpn-config [-vid/--vpnid <id>]");
3357 return help.toString();
3360 protected void dissociatefixedIPFromFloatingIP(String fixedNeutronPortName) {
3361 floatingIpMapListener.dissociatefixedIPFromFloatingIP(fixedNeutronPortName);
3365 public ListenableFuture<RpcResult<CreateEVPNOutput>> createEVPN(CreateEVPNInput input) {
3366 return neutronEvpnManager.createEVPN(input);
3370 public ListenableFuture<RpcResult<GetEVPNOutput>> getEVPN(GetEVPNInput input) {
3371 return neutronEvpnManager.getEVPN(input);
3375 public ListenableFuture<RpcResult<DeleteEVPNOutput>> deleteEVPN(DeleteEVPNInput input) {
3376 return neutronEvpnManager.deleteEVPN(input);
3379 private boolean addExternalNetworkToVpn(Network extNet, Uuid vpnId) {
3380 Uuid extNetId = extNet.getUuid();
3381 InstanceIdentifier<Networks> extNetIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
3382 .child(Networks.class, new NetworksKey(extNetId)).build();
3385 Optional<Networks> optionalExtNets =
3386 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3388 if (!optionalExtNets.isPresent()) {
3389 LOG.error("addExternalNetworkToVpn: Provider Network {} is not present in ConfigDS",
3390 extNetId.getValue());
3393 NetworksBuilder builder = new NetworksBuilder(optionalExtNets.get());
3394 builder.setVpnid(vpnId);
3395 Networks networks = builder.build();
3396 // Add Networks object to the ExternalNetworks list
3397 LOG.trace("addExternalNetworkToVpn: Set VPN Id {} for Provider Network {}", vpnId.getValue(),
3398 extNetId.getValue());
3399 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetIdentifier,
3402 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
3403 LOG.error("addExternalNetworkToVpn: Failed to set VPN Id {} to Provider Network {}: ", vpnId.getValue(),
3404 extNetId.getValue(), ex);
3409 private boolean removeExternalNetworkFromVpn(Network extNet) {
3410 Uuid extNetId = extNet.getUuid();
3411 InstanceIdentifier<Networks> extNetsId = InstanceIdentifier.builder(ExternalNetworks.class)
3412 .child(Networks.class, new NetworksKey(extNetId)).build();
3414 Optional<Networks> optionalNets =
3415 SingleTransactionDataBroker.syncReadOptional(dataBroker, LogicalDatastoreType.CONFIGURATION,
3417 NetworksBuilder builder = null;
3418 if (optionalNets.isPresent()) {
3419 builder = new NetworksBuilder(optionalNets.get());
3421 LOG.error("removeExternalNetworkFromVpn: Provider Network {} is not present in the ConfigDS",
3422 extNetId.getValue());
3425 builder.setVpnid(null);
3426 Networks networks = builder.build();
3427 LOG.info("removeExternalNetworkFromVpn: Withdraw VPN Id from Provider Network {} node",
3428 extNetId.getValue());
3429 SingleTransactionDataBroker.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, extNetsId, networks);
3431 } catch (TransactionCommitFailedException | ExecutionException | InterruptedException ex) {
3432 LOG.error("removeExternalNetworkFromVpn: Failed to withdraw VPN Id from Provider Network node {}: ",
3433 extNetId.getValue(), ex);
3438 private Optional<String> getExistingOperationalVpn(String primaryRd) {
3439 Optional<String> existingVpnName = Optional.of(primaryRd);
3440 Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataOptional;
3442 vpnInstanceOpDataOptional = syncReadOptional(dataBroker, LogicalDatastoreType.OPERATIONAL,
3443 neutronvpnUtils.getVpnOpDataIdentifier(primaryRd));
3444 } catch (ExecutionException | InterruptedException e) {
3445 LOG.error("getExistingOperationalVpn: Exception while checking operational status of vpn with rd {}",
3447 /*Read failed. We don't know if a VPN exists or not.
3448 * Return primaryRd to halt caller execution, to be safe.*/
3449 return existingVpnName;
3451 if (vpnInstanceOpDataOptional.isPresent()) {
3452 existingVpnName = Optional.of(vpnInstanceOpDataOptional.get().getVpnInstanceName());
3454 existingVpnName = Optional.empty();
3456 return existingVpnName;
3459 private static String formatAndLog(Consumer<String> logger, String template, Object arg) {
3460 return logAndReturnMessage(logger, MessageFormatter.format(template, arg));
3463 private static String formatAndLog(Consumer<String> logger, String template, Object arg1, Object arg2) {
3464 return logAndReturnMessage(logger, MessageFormatter.format(template, arg1, arg2));
3467 private static String formatAndLog(Consumer<String> logger, String template, Object... args) {
3468 return logAndReturnMessage(logger, MessageFormatter.arrayFormat(template, args));
3471 private static String logAndReturnMessage(Consumer<String> logger, FormattingTuple tuple) {
3472 String message = tuple.getMessage();
3473 logger.accept(message);
3477 protected void addV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3478 @NonNull Subnetmap subnetMap) {
3479 updateVpnInternetForSubnet(subnetMap, internetVpnId, true);
3480 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, true);
3481 if (neutronvpnUtils.shouldVpnHandleIpVersionChoiceChange(IpVersionChoice.IPV6, routerId, true)) {
3482 neutronvpnUtils.updateVpnInstanceWithIpFamily(internetVpnId.getValue(), IpVersionChoice.IPV6, true);
3483 LOG.info("addV6PrivateSubnetToExtNetwork: Advertise IPv6 Private Subnet {} to Internet VPN {}",
3484 subnetMap.getId().getValue(), internetVpnId.getValue());
3488 protected void removeV6PrivateSubnetToExtNetwork(@NonNull Uuid routerId, @NonNull Uuid internetVpnId,
3489 @NonNull Subnetmap subnetMap) {
3490 updateVpnInternetForSubnet(subnetMap, internetVpnId, false);
3491 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, false);
3494 protected void programV6InternetFallbackFlow(Uuid routerId, Uuid internetVpnId, int addOrRemove) {
3495 if (neutronvpnUtils.isV6SubnetPartOfRouter(routerId)) {
3496 LOG.debug("processV6InternetFlowsForRtr: Successfully {} V6 internet vpn {} default fallback rule "
3497 + "for the router {}", addOrRemove == NwConstants.ADD_FLOW ? "added" : "removed",
3498 internetVpnId.getValue(), routerId.getValue());
3499 neutronvpnUtils.updateVpnInstanceWithFallback(routerId, internetVpnId, addOrRemove == NwConstants.ADD_FLOW
3505 private AcquireResult tryInterfaceLock(final String infName) {
3506 return interfaceLock.tryAcquire(infName, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3510 private AcquireResult tryVpnLock(final Uuid vpnId) {
3511 return vpnLock.tryAcquire(vpnId, LOCK_WAIT_TIME, TimeUnit.SECONDS);
3514 private static ReentrantLock lockForUuid(Uuid uuid) {
3515 // FIXME: prove that this locks only on Uuids and not some other entity or create a separate lock domain
3516 return JvmGlobalLocks.getLockForString(uuid.getValue());
3519 private static void logTryLockFailure(Object objectId) {
3520 LOG.warn("Lock for {} was not acquired, continuing anyway", objectId, new Throwable());