2 * Copyright (c) 2016 Hewlett Packard Enterprise, Co. 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
9 package org.opendaylight.unimgr.mef.netvirt;
11 import java.util.ArrayList;
12 import java.util.Arrays;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.UUID;
17 import org.apache.commons.net.util.SubnetUtils;
18 import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
21 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
22 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
23 import org.opendaylight.genius.mdsalutil.MDSALUtil;
24 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
25 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
26 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
27 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
28 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
29 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
30 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
31 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
32 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
33 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
34 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpRequestInput;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpRequestInputBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.interfaces.InterfaceAddress;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.interfaces.InterfaceAddressBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.LearntVpnVipToPortData;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPortKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkMaps;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetAddedToVpnBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetDeletedFromVpnBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.IpVersionV4;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
79 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
80 import org.slf4j.Logger;
81 import org.slf4j.LoggerFactory;
83 import com.google.common.base.Optional;
85 public class NetvirtVpnUtils {
86 private static final Logger logger = LoggerFactory.getLogger(NetvirtVpnUtils.class);
87 private final static String ELAN_PREFIX = "elan.";
88 private final static String IP_ADDR_SUFFIX = "/32";
89 private final static String IP_MUSK_SEPARATOR = "/";
91 public static void createVpnInstance(DataBroker dataBroker, String instanceName) {
92 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
93 createVpnInstance(instanceName, tx);
94 MdsalUtils.commitTransaction(tx);
97 public static void createVpnInstance(String instanceName, WriteTransaction tx) {
98 VpnInstanceBuilder builder = new VpnInstanceBuilder();
99 builder.setVpnInstanceName(instanceName);
100 Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder();
101 VpnTargetsBuilder vpnTargetsB = new VpnTargetsBuilder();
102 vpnTargetsB.setVpnTarget(new ArrayList<VpnTarget>());
103 ipv4FamilyBuilder.setVpnTargets(vpnTargetsB.build());
105 // WA till netvirt will allow creation of VPN without RD
106 UUID vpnId = UUID.fromString(instanceName);
107 String rd = String.valueOf(Math.abs(vpnId.getLeastSignificantBits()));
108 ipv4FamilyBuilder.setRouteDistinguisher(rd);
109 builder.setIpv4Family(ipv4FamilyBuilder.build());
111 tx.put(LogicalDatastoreType.CONFIGURATION, getVpnInstanceInstanceIdentifier(instanceName), builder.build());
114 public static void removeVpnInstance(String instanceName, WriteTransaction tx) {
115 tx.delete(LogicalDatastoreType.CONFIGURATION, getVpnInstanceInstanceIdentifier(instanceName));
118 private static InstanceIdentifier<VpnInstance> getVpnInstanceInstanceIdentifier(String instanceName) {
119 return InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class, new VpnInstanceKey(instanceName))
123 static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> getVpnInstanceToVpnIdIdentifier(
125 return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
126 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
127 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(
132 public static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
133 return InstanceIdentifier.builder(VpnInstanceOpData.class)
134 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
137 public static void createUpdateVpnInterface(DataBroker dataBroker, String vpnName, String interfaceName,
138 String ifAddr, String macAddress, boolean primary, String gwIpAddress, String directSubnetId) {
139 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
140 createUpdateVpnInterface(vpnName, interfaceName, ifAddr, macAddress, primary, gwIpAddress, directSubnetId, tx);
141 MdsalUtils.commitTransaction(tx);
144 public static void createUpdateVpnInterface(String vpnName, String interfaceName, IpPrefix ifPrefix,
145 String macAddress, boolean primary, IpPrefix gwIpAddress, String directSubnetId, WriteTransaction tx) {
146 synchronized (interfaceName.intern()) {
147 String ipAddress = null;
148 String nextHopIp = null;
150 ipAddress = getAddressFromSubnet(ipPrefixToString(ifPrefix));
152 ipAddress = ipPrefixToString(ifPrefix);
153 nextHopIp = getIpAddressFromPrefix(ipPrefixToString(gwIpAddress));
155 createUpdateVpnInterface(vpnName, interfaceName, ipAddress, macAddress, primary, nextHopIp, directSubnetId,
160 public static void createUpdateVpnInterface(String vpnName, String interfaceName, String ipAddress,
161 String macAddress, boolean primary, String nextHopIp, String subnetId, WriteTransaction tx) {
162 synchronized (interfaceName.intern()) {
163 Adjacencies adjancencies = buildInterfaceAdjacency(ipAddress, macAddress, primary, nextHopIp, subnetId);
164 VpnInterfaceBuilder einterfaceBuilder = createVpnInterface(vpnName, interfaceName, adjancencies);
166 tx.merge(LogicalDatastoreType.CONFIGURATION, getVpnInterfaceInstanceIdentifier(interfaceName),
167 einterfaceBuilder.build());
171 private static VpnInterfaceBuilder createVpnInterface(String instanceName, String interfaceName,
172 Adjacencies adjacencies) {
173 VpnInterfaceBuilder einterfaceBuilder = new VpnInterfaceBuilder();
174 einterfaceBuilder.setVpnInstanceName(instanceName);
175 einterfaceBuilder.setName(interfaceName);
176 einterfaceBuilder.addAugmentation(Adjacencies.class, adjacencies);
177 return einterfaceBuilder;
180 private static Adjacencies buildInterfaceAdjacency(String ipAddress, String macAddress, boolean primary,
181 String nextHopIp, String subnetId) {
182 AdjacenciesBuilder builder = new AdjacenciesBuilder();
183 List<Adjacency> list = new ArrayList<>();
185 AdjacencyBuilder aBuilder = new AdjacencyBuilder();
186 aBuilder.setIpAddress(ipAddress);
187 if (macAddress != null) {
188 aBuilder.setMacAddress(macAddress);
190 aBuilder.setPrimaryAdjacency(primary);
191 if (subnetId != null) {
192 aBuilder.setSubnetId(new Uuid(subnetId));
194 if (nextHopIp != null) {
195 aBuilder.setNextHopIpList(Arrays.asList(nextHopIp));
197 list.add(aBuilder.build());
199 builder.setAdjacency(list);
200 return builder.build();
203 public static void removeVpnInterface(String interfaceName, WriteTransaction tx) {
204 synchronized (interfaceName.intern()) {
205 tx.delete(LogicalDatastoreType.CONFIGURATION, getVpnInterfaceInstanceIdentifier(interfaceName));
209 public static void removeVpnInterfaceAdjacencies(DataBroker dataBroker, String vpnName, String interfaceName) {
211 InstanceIdentifier<VpnInterface> identifier = getVpnInterfaceInstanceIdentifier(interfaceName);
212 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
214 Optional<Adjacencies> adjacencies = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
215 List<Adjacency> adjacenciesList = adjacencies.isPresent() && adjacencies.get().getAdjacency() != null
216 ? adjacencies.get().getAdjacency() : Collections.emptyList();
217 adjacenciesList.forEach(a -> {
218 String ipStr = getIpAddressFromPrefix(a.getIpAddress());
219 InstanceIdentifier<LearntVpnVipToPort> id = getLearntVpnVipToPortIdentifier(vpnName, ipStr);
220 MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
222 int waitCount = (adjacenciesList.isEmpty()) ? 2 : 2 * adjacenciesList.size();
224 AdjacenciesBuilder builder = new AdjacenciesBuilder();
225 List<Adjacency> list = new ArrayList<>();
226 builder.setAdjacency(list);
227 VpnInterfaceBuilder einterfaceBuilder = createVpnInterface(vpnName, interfaceName, builder.build());
228 MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, identifier, einterfaceBuilder.build());
230 final DataWaitGetter<Adjacencies> getData = vpnint -> {
231 if (vpnint.getAdjacency() == null)
233 return vpnint.getAdjacency().stream().filter(a -> !a.isPrimaryAdjacency());
236 @SuppressWarnings("resource") // AutoCloseable
237 DataWaitListener<Adjacencies> vpnIntWaiter = new DataWaitListener<Adjacencies>(dataBroker, path, waitCount,
238 LogicalDatastoreType.OPERATIONAL, getData);
239 if (!vpnIntWaiter.waitForClean()) {
240 logger.error("Fail to wait for VPN interface clean-up {} {}", vpnName, interfaceName);
245 public static void removeVpnInterfaceAdjacency(DataBroker dataBroker, String interfaceName, IpPrefix ifPrefix) {
246 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
247 String ipAddress = ipPrefixToString(ifPrefix);
248 removeVpnInterfaceAdjacency(interfaceName, ipAddress, tx);
249 MdsalUtils.commitTransaction(tx);
252 public static void removeVpnInterfaceAdjacency(DataBroker dataBroker, String interfaceName, IpAddress ifAddress) {
253 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
254 String ifAddressStr = getAddressFromSubnet(ipAddressToString(ifAddress));
255 removeVpnInterfaceAdjacency(interfaceName, ifAddressStr, tx);
256 MdsalUtils.commitTransaction(tx);
259 private static void removeVpnInterfaceAdjacency(String interfaceName, String ipAddress, WriteTransaction tx) {
260 synchronized (interfaceName.intern()) {
262 InstanceIdentifier<Adjacency> adjacencyIdentifier = InstanceIdentifier.builder(VpnInterfaces.class)
263 .child(VpnInterface.class, new VpnInterfaceKey(interfaceName)).augmentation(Adjacencies.class)
264 .child(Adjacency.class, new AdjacencyKey(ipAddress)).build();
266 tx.delete(LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
270 private static InstanceIdentifier<VpnInterface> getVpnInterfaceInstanceIdentifier(String interfaceName) {
271 return InstanceIdentifier.builder(VpnInterfaces.class)
272 .child(VpnInterface.class, new VpnInterfaceKey(interfaceName)).build();
275 public static void createVpnPortFixedIp(DataBroker dataBroker, String vpnName, String portName, IpPrefix ipAddress,
276 MacAddress macAddress) {
277 String fixedIpPrefix = ipPrefixToString(ipAddress);
278 String fixedIp = getIpAddressFromPrefix(fixedIpPrefix);
280 WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
281 createVpnPortFixedIp(vpnName, portName, fixedIp, macAddress, tx);
282 MdsalUtils.commitTransaction(tx);
285 private static void createVpnPortFixedIp(String vpnName, String portName, String fixedIp, MacAddress macAddress,
286 WriteTransaction tx) {
287 synchronized ((vpnName + fixedIp).intern()) {
288 InstanceIdentifier<VpnPortipToPort> id = getVpnPortipToPortIdentifier(vpnName, fixedIp);
289 VpnPortipToPortBuilder builder = new VpnPortipToPortBuilder()
290 .setKey(new VpnPortipToPortKey(fixedIp, vpnName)).setVpnName(vpnName).setPortFixedip(fixedIp)
291 .setPortName(portName).setMacAddress(macAddress.getValue()).setSubnetIp(true);
292 tx.put(LogicalDatastoreType.CONFIGURATION, id, builder.build());
294 "Interface to fixedIp added: {}, vpn {}, interface {}, mac {} added to " + "VpnPortipToPort DS",
295 fixedIp, vpnName, portName, macAddress);
299 public static VpnPortipToPort getVpnPortFixedIp(DataBroker dataBroker, String vpnName, String fixedIp) {
300 InstanceIdentifier<VpnPortipToPort> id = getVpnPortipToPortIdentifier(vpnName, fixedIp);
301 Optional<VpnPortipToPort> opt = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
302 return opt != null && opt.isPresent() ? opt.get() : null;
305 public static LearntVpnVipToPort getLearntVpnVipToPort(DataBroker dataBroker, String vpnName, String fixedIp) {
306 InstanceIdentifier<LearntVpnVipToPort> id = getLearntVpnVipToPortIdentifier(vpnName, fixedIp);
307 Optional<LearntVpnVipToPort> opt = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
308 return opt != null && opt.isPresent() ? opt.get() : null;
311 public static void removeVpnPortFixedIp(String vpnName, IpPrefix ipAddress, WriteTransaction tx) {
312 String fixedIpPrefix = ipPrefixToString(ipAddress);
313 String fixedIp = getIpAddressFromPrefix(fixedIpPrefix);
314 InstanceIdentifier<VpnPortipToPort> id = getVpnPortipToPortIdentifier(vpnName, fixedIp);
315 tx.delete(LogicalDatastoreType.CONFIGURATION, id);
318 public static void registerDirectSubnetForVpn(DataBroker dataBroker, Uuid subnetName, IpAddress gwIpAddress) {
319 final SubnetKey subnetkey = new SubnetKey(subnetName);
321 final InstanceIdentifier<Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class)
322 .child(Subnets.class).child(Subnet.class, subnetkey);
324 SubnetBuilder subnetBuilder = new SubnetBuilder();
325 subnetBuilder.setIpVersion(IpVersionV4.class);
326 subnetBuilder.setGatewayIp(gwIpAddress);
327 subnetBuilder.setKey(subnetkey);
328 MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetidentifier, subnetBuilder.build());
331 public static void unregisterDirectSubnetForVpn(DataBroker dataBroker, Uuid subnetName) {
332 final SubnetKey subnetkey = new SubnetKey(subnetName);
333 final InstanceIdentifier<Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class)
334 .child(Subnets.class).child(Subnet.class, subnetkey);
336 MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetidentifier);
339 public static void addDirectSubnetToVpn(DataBroker dataBroker,
340 final NotificationPublishService notificationPublishService, String vpnName, String subnetName,
341 IpPrefix subnetIpPrefix, String interfaceName, String intfMac, int waitForElan) {
342 InstanceIdentifier<ElanInstance> elanIdentifierId = NetvirtUtils.getElanInstanceInstanceIdentifier(subnetName);
344 @SuppressWarnings("resource") // AutoCloseable
345 DataWaitListener<ElanInstance> elanTagWaiter = new DataWaitListener<>(dataBroker, elanIdentifierId,
346 10, LogicalDatastoreType.CONFIGURATION, el -> el.getElanTag());
347 if (!elanTagWaiter.waitForData()) {
348 logger.error("Trying to add invalid elan {} to vpn {}", subnetName, vpnName);
352 Uuid subnetId = new Uuid(subnetName);
353 logger.info("Adding subnet {} {} to elan map", subnetId, subnetId);
354 createSubnetToNetworkMapping(dataBroker, subnetId, subnetId);
356 String subnetIp = getSubnetFromPrefix(ipPrefixToString(subnetIpPrefix));
357 logger.info("Adding subnet {} {} to vpn {}", subnetName, subnetIp, vpnName);
358 updateSubnetNode(dataBroker, new Uuid(vpnName), subnetId, subnetIp, intfMac);
360 logger.info("Adding port {} to subnet {}", interfaceName, subnetName);
361 updateSubnetmapNodeWithPorts(dataBroker, subnetId, new Uuid(interfaceName), null, vpnName);
363 Optional<ElanInstance> elanInstance = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
365 Long elanTag = elanInstance.get().getElanTag();
367 logger.info("Publish subnet {}", subnetName);
368 publishSubnetAddNotification(notificationPublishService, subnetId, subnetIp, vpnName, elanTag);
369 logger.info("Finished Working on subnet {}", subnetName);
372 public static void removeDirectSubnetFromVpn(DataBroker dataBroker,
373 final NotificationPublishService notificationPublishService, String vpnName, String subnetName,
374 String interfaceName) {
375 InstanceIdentifier<ElanInstance> elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class)
376 .child(ElanInstance.class, new ElanInstanceKey(subnetName)).build();
377 Optional<ElanInstance> elanInstance = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
379 if (!elanInstance.isPresent()) {
380 logger.error("Trying to add invalid elan {} to vpn {}", subnetName, vpnName);
383 Long elanTag = elanInstance.get().getElanTag() != null ? elanInstance.get().getElanTag()
384 : elanInstance.get().getSegmentationId();
385 Uuid subnetId = new Uuid(subnetName);
387 logger.info("Publish subnet remove {}", subnetName);
388 publishSubnetRemoveNotification(notificationPublishService, subnetId, vpnName, elanTag);
390 logger.info("Removing port {} from subnet {}", interfaceName, subnetName);
391 updateSubnetmapNodeWithPorts(dataBroker, subnetId, null, new Uuid(interfaceName), vpnName);
393 logger.info("Removing subnet {} from vpn {}", subnetName, vpnName);
394 removeSubnetNode(dataBroker, new Uuid(vpnName));
396 logger.info("Removing subnet {} to elan map", subnetId);
397 removeSubnetToNetworkMapping(dataBroker, subnetId);
399 logger.info("Finished Working on subnet {}", subnetName);
402 private static void createSubnetToNetworkMapping(DataBroker dataBroker, Uuid subnetId, Uuid networkId) {
403 InstanceIdentifier<NetworkMap> networkMapIdentifier = getNetworkMapIdentifier(networkId);
404 Optional<NetworkMap> optionalNetworkMap = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
405 networkMapIdentifier);
406 NetworkMapBuilder nwMapBuilder = null;
407 if (optionalNetworkMap.isPresent()) {
408 nwMapBuilder = new NetworkMapBuilder(optionalNetworkMap.get());
410 nwMapBuilder = new NetworkMapBuilder().setKey(new NetworkMapKey(networkId)).setNetworkId(networkId);
411 logger.debug("Adding a new network node in NetworkMaps DS for network {}", networkId.getValue());
413 List<Uuid> subnetIdList = nwMapBuilder.getSubnetIdList();
414 if (subnetIdList == null) {
415 subnetIdList = new ArrayList<>();
417 subnetIdList.add(subnetId);
418 nwMapBuilder.setSubnetIdList(subnetIdList);
419 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier, nwMapBuilder.build());
420 logger.debug("Created subnet-network mapping for subnet {} network {}", subnetId.getValue(),
421 networkId.getValue());
424 private static void removeSubnetToNetworkMapping(DataBroker dataBroker, Uuid networkId) {
425 InstanceIdentifier<NetworkMap> networkMapIdentifier = getNetworkMapIdentifier(networkId);
426 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier);
427 logger.debug("Deleted subnet-network mapping for network {}", networkId.getValue());
430 protected static void updateSubnetNode(DataBroker dataBroker, Uuid vpnId, Uuid subnetId, String subnetIp,
432 Subnetmap subnetmap = null;
433 SubnetmapBuilder builder = null;
434 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
435 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
437 synchronized (subnetId.getValue().intern()) {
438 Optional<Subnetmap> sn = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
439 if (sn.isPresent()) {
440 builder = new SubnetmapBuilder(sn.get());
441 logger.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
443 builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
444 logger.debug("creating new subnetmap node for subnet ID {}", subnetId.getValue());
447 builder.setSubnetIp(subnetIp);
448 builder.setNetworkId(subnetId);
449 builder.setVpnId(vpnId);
450 builder.setRouterIntfMacAddress(intfMac);
452 subnetmap = builder.build();
453 logger.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
454 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
458 protected static void removeSubnetNode(DataBroker dataBroker, Uuid subnetId) {
459 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
460 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
462 synchronized (subnetId.getValue().intern()) {
463 logger.debug("Deleting subnetMap node: {} ", subnetId.getValue());
464 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
468 private static void updateSubnetmapNodeWithPorts(DataBroker dataBroker, Uuid subnetId, Uuid portIdToAdd,
469 Uuid portIdToRemove, String vpnName) {
470 Subnetmap subnetmap = null;
471 InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
472 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
473 synchronized (subnetId.getValue().intern()) {
474 Optional<Subnetmap> sn = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
475 if (sn.isPresent()) {
476 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
477 if (null != portIdToAdd) {
478 List<Uuid> portList = builder.getPortList();
479 if (null == portList) {
480 portList = new ArrayList<>();
482 if (portIdToAdd != null) {
483 portList.add(portIdToAdd);
484 logger.debug("Updating subnetmap node {} with port {}", subnetId.getValue(),
485 portIdToAdd.getValue());
488 if (portIdToRemove != null) {
489 portList.remove(portIdToRemove);
490 logger.debug("Updating subnetmap node {} removing port {}", subnetId.getValue(),
491 portIdToRemove.getValue());
494 builder.setRouterId(new Uuid(vpnName));
495 builder.setPortList(portList);
497 subnetmap = builder.build();
498 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
500 logger.error("Trying to update non-existing subnetmap node {} ", subnetId.getValue());
505 private static InstanceIdentifier<NetworkMap> getNetworkMapIdentifier(Uuid networkId) {
506 InstanceIdentifier<NetworkMap> id = InstanceIdentifier.builder(NetworkMaps.class)
507 .child(NetworkMap.class, new NetworkMapKey(networkId)).build();
511 private static InstanceIdentifier<VpnPortipToPort> getVpnPortipToPortIdentifier(String vpnName, String fixedIp) {
512 InstanceIdentifier<VpnPortipToPort> id = InstanceIdentifier.builder(NeutronVpnPortipPortData.class)
513 .child(VpnPortipToPort.class, new VpnPortipToPortKey(fixedIp, vpnName)).build();
517 private static InstanceIdentifier<LearntVpnVipToPort> getLearntVpnVipToPortIdentifier(String vpnName,
519 InstanceIdentifier<LearntVpnVipToPort> id = InstanceIdentifier.builder(LearntVpnVipToPortData.class)
520 .child(LearntVpnVipToPort.class, new LearntVpnVipToPortKey(fixedIp, vpnName)).build();
524 public static InstanceIdentifier<VpnPortipToPort> getVpnPortipToPortIdentifier() {
525 return InstanceIdentifier.builder(NeutronVpnPortipPortData.class).child(VpnPortipToPort.class).build();
528 public static InstanceIdentifier<LearntVpnVipToPort> getLearntVpnVipToPortIdentifier() {
529 return InstanceIdentifier.builder(LearntVpnVipToPortData.class).child(LearntVpnVipToPort.class).build();
532 private static void publishSubnetAddNotification(final NotificationPublishService notificationPublishService,
533 Uuid subnetId, String subnetIp, String vpnName, Long elanTag) {
534 SubnetAddedToVpnBuilder builder = new SubnetAddedToVpnBuilder();
536 logger.info("publish notification called for network creation");
538 builder.setSubnetId(subnetId);
539 builder.setSubnetIp(subnetIp);
540 builder.setVpnName(vpnName);
541 builder.setExternalVpn(true);
542 builder.setElanTag(elanTag);
545 notificationPublishService.putNotification(builder.build());
546 } catch (InterruptedException e) {
547 logger.error("Fail to publish notification {}", builder, e);
548 throw new RuntimeException(e.getMessage());
552 private static void publishSubnetRemoveNotification(final NotificationPublishService notificationPublishService,
553 Uuid subnetId, String vpnName, Long elanTag) {
554 SubnetDeletedFromVpnBuilder builder = new SubnetDeletedFromVpnBuilder();
556 logger.info("publish notification called for network deletion");
558 builder.setSubnetId(subnetId);
559 builder.setVpnName(vpnName);
560 builder.setExternalVpn(true);
561 builder.setElanTag(elanTag);
564 notificationPublishService.putNotification(builder.build());
565 } catch (InterruptedException e) {
566 logger.error("Fail to publish notification {}", builder, e);
567 throw new RuntimeException(e.getMessage());
571 public static void sendArpRequest(OdlArputilService arpUtilService, IpAddress srcIpAddress, IpAddress dstIpAddress,
574 List<InterfaceAddress> interfaceAddresses = new ArrayList<>();
576 .add(new InterfaceAddressBuilder().setInterface(interf).setIpAddress(srcIpAddress).build());
578 SendArpRequestInput sendArpRequestInput = new SendArpRequestInputBuilder().setIpaddress(dstIpAddress)
579 .setInterfaceAddress(interfaceAddresses).build();
580 arpUtilService.sendArpRequest(sendArpRequestInput);
581 } catch (Exception e) {
582 logger.error("Failed to send ARP request to IP {} from interfaces {}",
583 dstIpAddress.getIpv4Address().getValue(), interf, e);
584 throw new RuntimeException(e.getMessage());
588 public static String getElanNameForVpnPort(String uniId, String ipUniId) {
589 return getUUidFromString(ELAN_PREFIX + uniId + ipUniId);
592 public static String getIpAddressFromPrefix(String prefix) {
593 return prefix.split(IP_MUSK_SEPARATOR)[0];
596 private static String getMaskFromPrefix(String prefix) {
597 return prefix.split(IP_MUSK_SEPARATOR)[1];
600 public static String getSubnetFromPrefix(String prefix) {
601 SubnetInfo subnet = new SubnetUtils(prefix).getInfo();
602 return subnet.getNetworkAddress() + IP_MUSK_SEPARATOR + getMaskFromPrefix(prefix);
605 public static String getSubnetFromPrefix(IpPrefix prefix) {
606 String prefixStr = ipPrefixToString(prefix);
607 return getSubnetFromPrefix(prefixStr);
610 private static String getAddressFromSubnet(String prefix) {
611 String myAddress = getIpAddressFromPrefix(prefix);
612 return myAddress + IP_ADDR_SUFFIX;
615 public static String getUUidFromString(String key) {
616 return java.util.UUID.nameUUIDFromBytes(key.getBytes()).toString();
619 public static String ipPrefixToString(IpPrefix ipAddress) {
620 if (ipAddress.getIpv4Prefix() != null) {
621 return ipAddress.getIpv4Prefix().getValue();
624 return ipAddress.getIpv6Prefix().getValue();
627 public static String ipAddressToString(IpAddress ipAddress) {
628 if (ipAddress.getIpv4Address() != null) {
629 return ipAddress.getIpv4Address().getValue();
632 return ipAddress.getIpv6Address().getValue();