a180cb32b3bdea172f1b43d4f0063fb148150c58
[unimgr.git] / netvirt / src / main / java / org / opendaylight / unimgr / mef / netvirt / NetvirtVpnUtils.java
1 /*
2  * Copyright (c) 2016 Hewlett Packard Enterprise, Co. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.unimgr.mef.netvirt;
10
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;
16
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.VpnInstanceOpData;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkMaps;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetAddedToVpnBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.SubnetDeletedFromVpnBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.IpVersionV4;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
76 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
77 import org.slf4j.Logger;
78 import org.slf4j.LoggerFactory;
79
80 import com.google.common.base.Optional;
81
82 public class NetvirtVpnUtils {
83     private static final Logger logger = LoggerFactory.getLogger(NetvirtVpnUtils.class);
84     private final static String ELAN_PREFIX = "elan.";
85     private final static String IP_ADDR_SUFFIX = "/32";
86     private final static String IP_MUSK_SEPARATOR = "/";
87
88     public static void createVpnInstance(DataBroker dataBroker, String instanceName) {
89         WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
90         createVpnInstance(instanceName, tx);
91         MdsalUtils.commitTransaction(tx);
92     }
93
94     public static void createVpnInstance(String instanceName, WriteTransaction tx) {
95         VpnInstanceBuilder builder = new VpnInstanceBuilder();
96         builder.setVpnInstanceName(instanceName);
97         Ipv4FamilyBuilder ipv4FamilyBuilder = new Ipv4FamilyBuilder();
98         VpnTargetsBuilder vpnTargetsB = new VpnTargetsBuilder();
99         vpnTargetsB.setVpnTarget(new ArrayList<VpnTarget>());
100         ipv4FamilyBuilder.setVpnTargets(vpnTargetsB.build());
101
102         // WA till netvirt will allow creation of VPN without RD
103         UUID vpnId = UUID.fromString(instanceName);
104         String rd = String.valueOf(Math.abs(vpnId.getLeastSignificantBits()));
105         ipv4FamilyBuilder.setRouteDistinguisher(rd);
106         builder.setIpv4Family(ipv4FamilyBuilder.build());
107
108         tx.put(LogicalDatastoreType.CONFIGURATION, getVpnInstanceInstanceIdentifier(instanceName), builder.build());
109     }
110
111     public static void removeVpnInstance(String instanceName, WriteTransaction tx) {
112         tx.delete(LogicalDatastoreType.CONFIGURATION, getVpnInstanceInstanceIdentifier(instanceName));
113     }
114
115     private static InstanceIdentifier<VpnInstance> getVpnInstanceInstanceIdentifier(String instanceName) {
116         return InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class, new VpnInstanceKey(instanceName))
117                 .build();
118     }
119
120     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> getVpnInstanceToVpnIdIdentifier(
121             String vpnName) {
122         return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
123                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
124                         new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(
125                                 vpnName))
126                 .build();
127     }
128
129     public static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
130         return InstanceIdentifier.builder(VpnInstanceOpData.class)
131                 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
132     }
133
134     public static void createUpdateVpnInterface(DataBroker dataBroker, String vpnName, String interfaceName,
135             String ifAddr, String macAddress, boolean primary, String gwIpAddress, String directSubnetId) {
136         WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
137         createUpdateVpnInterface(vpnName, interfaceName, ifAddr, macAddress, primary, gwIpAddress, directSubnetId, tx);
138         MdsalUtils.commitTransaction(tx);
139     }
140
141     public static void createUpdateVpnInterface(String vpnName, String interfaceName, IpPrefix ifPrefix,
142             String macAddress, boolean primary, IpPrefix gwIpAddress, String directSubnetId, WriteTransaction tx) {
143         synchronized (interfaceName.intern()) {
144             String ipAddress = null;
145             String nextHopIp = null;
146             if (primary) {
147                 ipAddress = getAddressFromSubnet(ipPrefixToString(ifPrefix));
148             } else {
149                 ipAddress = ipPrefixToString(ifPrefix);
150                 nextHopIp = getIpAddressFromPrefix(ipPrefixToString(gwIpAddress));
151             }
152             createUpdateVpnInterface(vpnName, interfaceName, ipAddress, macAddress, primary, nextHopIp, directSubnetId,
153                     tx);
154         }
155     }
156
157     public static void createUpdateVpnInterface(String vpnName, String interfaceName, String ipAddress,
158             String macAddress, boolean primary, String nextHopIp, String subnetId, WriteTransaction tx) {
159         synchronized (interfaceName.intern()) {
160             Adjacencies adjancencies = buildInterfaceAdjacency(ipAddress, macAddress, primary, nextHopIp, subnetId);
161             VpnInterfaceBuilder einterfaceBuilder = createVpnInterface(vpnName, interfaceName, adjancencies);
162
163             tx.merge(LogicalDatastoreType.CONFIGURATION, getVpnInterfaceInstanceIdentifier(interfaceName),
164                     einterfaceBuilder.build());
165         }
166     }
167
168     private static VpnInterfaceBuilder createVpnInterface(String instanceName, String interfaceName,
169             Adjacencies adjacencies) {
170         VpnInterfaceBuilder einterfaceBuilder = new VpnInterfaceBuilder();
171         einterfaceBuilder.setVpnInstanceName(instanceName);
172         einterfaceBuilder.setName(interfaceName);
173         einterfaceBuilder.addAugmentation(Adjacencies.class, adjacencies);
174         return einterfaceBuilder;
175     }
176
177     private static Adjacencies buildInterfaceAdjacency(String ipAddress, String macAddress, boolean primary,
178             String nextHopIp, String subnetId) {
179         AdjacenciesBuilder builder = new AdjacenciesBuilder();
180         List<Adjacency> list = new ArrayList<>();
181
182         AdjacencyBuilder aBuilder = new AdjacencyBuilder();
183         aBuilder.setIpAddress(ipAddress);
184         if (macAddress != null) {
185             aBuilder.setMacAddress(macAddress);
186         }
187         aBuilder.setPrimaryAdjacency(primary);
188         if (subnetId != null) {
189             aBuilder.setSubnetId(new Uuid(subnetId));
190         }
191         if (nextHopIp != null) {
192             aBuilder.setNextHopIpList(Arrays.asList(nextHopIp));
193         }
194         list.add(aBuilder.build());
195
196         builder.setAdjacency(list);
197         return builder.build();
198     }
199
200     public static void removeVpnInterface(String interfaceName, WriteTransaction tx) {
201         synchronized (interfaceName.intern()) {
202             tx.delete(LogicalDatastoreType.CONFIGURATION, getVpnInterfaceInstanceIdentifier(interfaceName));
203         }
204     }
205
206     public static void removeVpnInterfaceAdjacencies(DataBroker dataBroker, String vpnName, String interfaceName) {
207         InstanceIdentifier<VpnInterface> identifier = getVpnInterfaceInstanceIdentifier(interfaceName);
208         InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
209         Optional<Adjacencies> adjacencies = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
210         List<Adjacency> adjacenciesList = adjacencies.isPresent() && adjacencies.get().getAdjacency() != null
211                 ? adjacencies.get().getAdjacency() : Collections.emptyList();
212         adjacenciesList.forEach(a -> {
213             String ipStr = getIpAddressFromPrefix(a.getIpAddress());
214             InstanceIdentifier<VpnPortipToPort> id = getVpnPortipToPortIdentifier(vpnName, ipStr);
215             MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
216         });
217
218         AdjacenciesBuilder builder = new AdjacenciesBuilder();
219         List<Adjacency> list = new ArrayList<>();
220         builder.setAdjacency(list);
221         VpnInterfaceBuilder einterfaceBuilder = createVpnInterface(vpnName, interfaceName, builder.build());
222
223         MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION,
224                 getVpnInterfaceInstanceIdentifier(interfaceName), einterfaceBuilder.build());
225
226     }
227
228     public static void removeVpnInterfaceAdjacency(DataBroker dataBroker, String interfaceName, IpPrefix ifPrefix) {
229         WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
230         String ipAddress = ipPrefixToString(ifPrefix);
231         removeVpnInterfaceAdjacency(interfaceName, ipAddress, tx);
232         MdsalUtils.commitTransaction(tx);
233     }
234
235     public static void removeVpnInterfaceAdjacency(DataBroker dataBroker, String interfaceName, IpAddress ifAddress) {
236         WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
237         String ifAddressStr = getAddressFromSubnet(ipAddressToString(ifAddress));
238         removeVpnInterfaceAdjacency(interfaceName, ifAddressStr, tx);
239         MdsalUtils.commitTransaction(tx);
240     }
241
242     private static void removeVpnInterfaceAdjacency(String interfaceName, String ipAddress, WriteTransaction tx) {
243         synchronized (interfaceName.intern()) {
244
245             InstanceIdentifier<Adjacency> adjacencyIdentifier = InstanceIdentifier.builder(VpnInterfaces.class)
246                     .child(VpnInterface.class, new VpnInterfaceKey(interfaceName)).augmentation(Adjacencies.class)
247                     .child(Adjacency.class, new AdjacencyKey(ipAddress)).build();
248
249             tx.delete(LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
250         }
251     }
252
253     private static InstanceIdentifier<VpnInterface> getVpnInterfaceInstanceIdentifier(String interfaceName) {
254         return InstanceIdentifier.builder(VpnInterfaces.class)
255                 .child(VpnInterface.class, new VpnInterfaceKey(interfaceName)).build();
256     }
257
258     public static void createVpnPortFixedIp(DataBroker dataBroker, String vpnName, String portName, IpPrefix ipAddress,
259             MacAddress macAddress) {
260         String fixedIpPrefix = ipPrefixToString(ipAddress);
261         String fixedIp = getIpAddressFromPrefix(fixedIpPrefix);
262
263         WriteTransaction tx = MdsalUtils.createTransaction(dataBroker);
264         createVpnPortFixedIp(vpnName, portName, fixedIp, macAddress, tx);
265         MdsalUtils.commitTransaction(tx);
266     }
267
268     private static void createVpnPortFixedIp(String vpnName, String portName, String fixedIp, MacAddress macAddress,
269             WriteTransaction tx) {
270         synchronized ((vpnName + fixedIp).intern()) {
271             InstanceIdentifier<VpnPortipToPort> id = getVpnPortipToPortIdentifier(vpnName, fixedIp);
272             VpnPortipToPortBuilder builder = new VpnPortipToPortBuilder()
273                     .setKey(new VpnPortipToPortKey(fixedIp, vpnName)).setVpnName(vpnName).setPortFixedip(fixedIp)
274                     .setPortName(portName).setMacAddress(macAddress.getValue()).setSubnetIp(true);
275             tx.put(LogicalDatastoreType.OPERATIONAL, id, builder.build());
276             logger.debug(
277                     "Interface to fixedIp added: {}, vpn {}, interface {}, mac {} added to " + "VpnPortipToPort DS",
278                     fixedIp, vpnName, portName, macAddress);
279         }
280     }
281
282     public static VpnPortipToPort getVpnPortFixedIp(DataBroker dataBroker, String vpnName, String fixedIp) {
283         InstanceIdentifier<VpnPortipToPort> id = getVpnPortipToPortIdentifier(vpnName, fixedIp);
284         Optional<VpnPortipToPort> opt = MdsalUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
285         return opt != null && opt.isPresent() ? opt.get() : null;
286     }
287
288     public static void removeVpnPortFixedIp(String vpnName, IpPrefix ipAddress, WriteTransaction tx) {
289         String fixedIpPrefix = ipPrefixToString(ipAddress);
290         String fixedIp = getIpAddressFromPrefix(fixedIpPrefix);
291         InstanceIdentifier<VpnPortipToPort> id = getVpnPortipToPortIdentifier(vpnName, fixedIp);
292         tx.delete(LogicalDatastoreType.OPERATIONAL, id);
293     }
294
295     public static void registerDirectSubnetForVpn(DataBroker dataBroker, Uuid subnetName, IpAddress gwIpAddress) {
296         final SubnetKey subnetkey = new SubnetKey(subnetName);
297
298         final InstanceIdentifier<Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class)
299                 .child(Subnets.class).child(Subnet.class, subnetkey);
300
301         SubnetBuilder subnetBuilder = new SubnetBuilder();
302         subnetBuilder.setIpVersion(IpVersionV4.class);
303         subnetBuilder.setGatewayIp(gwIpAddress);
304         subnetBuilder.setKey(subnetkey);
305         MdsalUtils.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetidentifier, subnetBuilder.build());
306     }
307
308     public static void unregisterDirectSubnetForVpn(DataBroker dataBroker, Uuid subnetName) {
309         final SubnetKey subnetkey = new SubnetKey(subnetName);
310         final InstanceIdentifier<Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class)
311                 .child(Subnets.class).child(Subnet.class, subnetkey);
312
313         MdsalUtils.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetidentifier);
314     }
315
316     public static void addDirectSubnetToVpn(DataBroker dataBroker,
317             final NotificationPublishService notificationPublishService, String vpnName, String subnetName,
318             IpPrefix subnetIpPrefix, String interfaceName, String intfMac, int waitForElan) {
319         InstanceIdentifier<ElanInstance> elanIdentifierId = NetvirtUtils.getElanInstanceInstanceIdentifier(subnetName);
320
321         @SuppressWarnings("resource") // AutoCloseable
322         DataWaitListener<ElanInstance> elanTagWaiter = new DataWaitListener<>(dataBroker, elanIdentifierId,
323                 10, LogicalDatastoreType.CONFIGURATION, el -> el.getElanTag());
324         if (!elanTagWaiter.waitForData()) {
325             logger.error("Trying to add invalid elan {} to vpn {}", subnetName, vpnName);
326             return;
327         }
328
329         Uuid subnetId = new Uuid(subnetName);
330         logger.info("Adding subnet {} {} to elan map", subnetId, subnetId);
331         createSubnetToNetworkMapping(dataBroker, subnetId, subnetId);
332
333         String subnetIp = getSubnetFromPrefix(ipPrefixToString(subnetIpPrefix));
334         logger.info("Adding subnet {} {} to vpn {}", subnetName, subnetIp, vpnName);
335         updateSubnetNode(dataBroker, new Uuid(vpnName), subnetId, subnetIp, intfMac);
336
337         logger.info("Adding port {} to subnet {}", interfaceName, subnetName);
338         updateSubnetmapNodeWithPorts(dataBroker, subnetId, new Uuid(interfaceName), null, vpnName);
339
340         Optional<ElanInstance> elanInstance = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
341                 elanIdentifierId);
342         Long elanTag = elanInstance.get().getElanTag();
343
344         logger.info("Publish subnet {}", subnetName);
345         publishSubnetAddNotification(notificationPublishService, subnetId, subnetIp, vpnName, elanTag);
346         logger.info("Finished Working on subnet {}", subnetName);
347     }
348
349     public static void removeDirectSubnetFromVpn(DataBroker dataBroker,
350             final NotificationPublishService notificationPublishService, String vpnName, String subnetName,
351             String interfaceName) {
352         InstanceIdentifier<ElanInstance> elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class)
353                 .child(ElanInstance.class, new ElanInstanceKey(subnetName)).build();
354         Optional<ElanInstance> elanInstance = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
355                 elanIdentifierId);
356         if (!elanInstance.isPresent()) {
357             logger.error("Trying to add invalid elan {} to vpn {}", subnetName, vpnName);
358             return;
359         }
360         Long elanTag = elanInstance.get().getElanTag() != null ? elanInstance.get().getElanTag()
361                 : elanInstance.get().getSegmentationId();
362         Uuid subnetId = new Uuid(subnetName);
363
364         logger.info("Publish subnet remove {}", subnetName);
365         publishSubnetRemoveNotification(notificationPublishService, subnetId, vpnName, elanTag);
366
367         logger.info("Removing port {} from subnet {}", interfaceName, subnetName);
368         updateSubnetmapNodeWithPorts(dataBroker, subnetId, null, new Uuid(interfaceName), vpnName);
369
370         logger.info("Removing subnet {} from vpn {}", subnetName, vpnName);
371         removeSubnetNode(dataBroker, new Uuid(vpnName));
372
373         logger.info("Removing subnet {} to elan map", subnetId);
374         removeSubnetToNetworkMapping(dataBroker, subnetId);
375
376         logger.info("Finished Working on subnet {}", subnetName);
377     }
378
379     private static void createSubnetToNetworkMapping(DataBroker dataBroker, Uuid subnetId, Uuid networkId) {
380         InstanceIdentifier<NetworkMap> networkMapIdentifier = getNetworkMapIdentifier(networkId);
381         Optional<NetworkMap> optionalNetworkMap = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION,
382                 networkMapIdentifier);
383         NetworkMapBuilder nwMapBuilder = null;
384         if (optionalNetworkMap.isPresent()) {
385             nwMapBuilder = new NetworkMapBuilder(optionalNetworkMap.get());
386         } else {
387             nwMapBuilder = new NetworkMapBuilder().setKey(new NetworkMapKey(networkId)).setNetworkId(networkId);
388             logger.debug("Adding a new network node in NetworkMaps DS for network {}", networkId.getValue());
389         }
390         List<Uuid> subnetIdList = nwMapBuilder.getSubnetIdList();
391         if (subnetIdList == null) {
392             subnetIdList = new ArrayList<>();
393         }
394         subnetIdList.add(subnetId);
395         nwMapBuilder.setSubnetIdList(subnetIdList);
396         MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier, nwMapBuilder.build());
397         logger.debug("Created subnet-network mapping for subnet {} network {}", subnetId.getValue(),
398                 networkId.getValue());
399     }
400
401     private static void removeSubnetToNetworkMapping(DataBroker dataBroker, Uuid networkId) {
402         InstanceIdentifier<NetworkMap> networkMapIdentifier = getNetworkMapIdentifier(networkId);
403         MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier);
404         logger.debug("Deleted subnet-network mapping for  network {}", networkId.getValue());
405     }
406
407     protected static void updateSubnetNode(DataBroker dataBroker, Uuid vpnId, Uuid subnetId, String subnetIp,
408             String intfMac) {
409         Subnetmap subnetmap = null;
410         SubnetmapBuilder builder = null;
411         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
412                 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
413
414         synchronized (subnetId.getValue().intern()) {
415             Optional<Subnetmap> sn = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
416             if (sn.isPresent()) {
417                 builder = new SubnetmapBuilder(sn.get());
418                 logger.debug("updating existing subnetmap node for subnet ID {}", subnetId.getValue());
419             } else {
420                 builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
421                 logger.debug("creating new subnetmap node for subnet ID {}", subnetId.getValue());
422             }
423
424             builder.setSubnetIp(subnetIp);
425             builder.setNetworkId(subnetId);
426             builder.setVpnId(vpnId);
427             builder.setRouterIntfMacAddress(intfMac);
428
429             subnetmap = builder.build();
430             logger.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
431             MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
432         }
433     }
434
435     protected static void removeSubnetNode(DataBroker dataBroker, Uuid subnetId) {
436         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
437                 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
438
439         synchronized (subnetId.getValue().intern()) {
440             logger.debug("Deleting subnetMap node: {} ", subnetId.getValue());
441             MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
442         }
443     }
444
445     private static void updateSubnetmapNodeWithPorts(DataBroker dataBroker, Uuid subnetId, Uuid portIdToAdd,
446             Uuid portIdToRemove, String vpnName) {
447         Subnetmap subnetmap = null;
448         InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class)
449                 .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
450         synchronized (subnetId.getValue().intern()) {
451             Optional<Subnetmap> sn = MdsalUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
452             if (sn.isPresent()) {
453                 SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
454                 if (null != portIdToAdd) {
455                     List<Uuid> portList = builder.getPortList();
456                     if (null == portList) {
457                         portList = new ArrayList<>();
458                     }
459                     if (portIdToAdd != null) {
460                         portList.add(portIdToAdd);
461                         logger.debug("Updating subnetmap node {} with port {}", subnetId.getValue(),
462                                 portIdToAdd.getValue());
463
464                     }
465                     if (portIdToRemove != null) {
466                         portList.remove(portIdToRemove);
467                         logger.debug("Updating subnetmap node {} removing port {}", subnetId.getValue(),
468                                 portIdToRemove.getValue());
469
470                     }
471                     builder.setRouterId(new Uuid(vpnName));
472                     builder.setPortList(portList);
473                 }
474                 subnetmap = builder.build();
475                 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
476             } else {
477                 logger.error("Trying to update non-existing subnetmap node {} ", subnetId.getValue());
478             }
479         }
480     }
481
482     private static InstanceIdentifier<NetworkMap> getNetworkMapIdentifier(Uuid networkId) {
483         InstanceIdentifier<NetworkMap> id = InstanceIdentifier.builder(NetworkMaps.class)
484                 .child(NetworkMap.class, new NetworkMapKey(networkId)).build();
485         return id;
486     }
487
488     private static InstanceIdentifier<VpnPortipToPort> getVpnPortipToPortIdentifier(String vpnName, String fixedIp) {
489         InstanceIdentifier<VpnPortipToPort> id = InstanceIdentifier.builder(NeutronVpnPortipPortData.class)
490                 .child(VpnPortipToPort.class, new VpnPortipToPortKey(fixedIp, vpnName)).build();
491         return id;
492     }
493
494     public static InstanceIdentifier<VpnPortipToPort> getVpnPortipToPortIdentifier() {
495         return InstanceIdentifier.builder(NeutronVpnPortipPortData.class).child(VpnPortipToPort.class).build();
496     }
497
498     private static void publishSubnetAddNotification(final NotificationPublishService notificationPublishService,
499             Uuid subnetId, String subnetIp, String vpnName, Long elanTag) {
500         SubnetAddedToVpnBuilder builder = new SubnetAddedToVpnBuilder();
501
502         logger.info("publish notification called for network creation");
503
504         builder.setSubnetId(subnetId);
505         builder.setSubnetIp(subnetIp);
506         builder.setVpnName(vpnName);
507         builder.setExternalVpn(true);
508         builder.setElanTag(elanTag);
509
510         try {
511             notificationPublishService.putNotification(builder.build());
512         } catch (InterruptedException e) {
513             logger.error("Fail to publish notification {}", builder, e);
514             throw new RuntimeException(e.getMessage());
515         }
516     }
517
518     private static void publishSubnetRemoveNotification(final NotificationPublishService notificationPublishService,
519             Uuid subnetId, String vpnName, Long elanTag) {
520         SubnetDeletedFromVpnBuilder builder = new SubnetDeletedFromVpnBuilder();
521
522         logger.info("publish notification called for network deletion");
523
524         builder.setSubnetId(subnetId);
525         builder.setVpnName(vpnName);
526         builder.setExternalVpn(true);
527         builder.setElanTag(elanTag);
528
529         try {
530             notificationPublishService.putNotification(builder.build());
531         } catch (InterruptedException e) {
532             logger.error("Fail to publish notification {}", builder, e);
533             throw new RuntimeException(e.getMessage());
534         }
535     }
536
537     public static void sendArpRequest(OdlArputilService arpUtilService, IpAddress srcIpAddress, IpAddress dstIpAddress,
538             String interf) {
539         try {
540             List<InterfaceAddress> interfaceAddresses = new ArrayList<>();
541             interfaceAddresses
542                     .add(new InterfaceAddressBuilder().setInterface(interf).setIpAddress(srcIpAddress).build());
543
544             SendArpRequestInput sendArpRequestInput = new SendArpRequestInputBuilder().setIpaddress(dstIpAddress)
545                     .setInterfaceAddress(interfaceAddresses).build();
546             arpUtilService.sendArpRequest(sendArpRequestInput);
547         } catch (Exception e) {
548             logger.error("Failed to send ARP request to IP {} from interfaces {}",
549                     dstIpAddress.getIpv4Address().getValue(), interf, e);
550             throw new RuntimeException(e.getMessage());
551         }
552     }
553
554     public static String getElanNameForVpnPort(String uniId, String ipUniId) {
555         return getUUidFromString(ELAN_PREFIX + uniId + ipUniId);
556     }
557
558     public static String getIpAddressFromPrefix(String prefix) {
559         return prefix.split(IP_MUSK_SEPARATOR)[0];
560     }
561
562     private static String getMaskFromPrefix(String prefix) {
563         return prefix.split(IP_MUSK_SEPARATOR)[1];
564     }
565
566     public static String getSubnetFromPrefix(String prefix) {
567         SubnetInfo subnet = new SubnetUtils(prefix).getInfo();
568         return subnet.getNetworkAddress() + IP_MUSK_SEPARATOR + getMaskFromPrefix(prefix);
569     }
570
571     public static String getSubnetFromPrefix(IpPrefix prefix) {
572         String prefixStr = ipPrefixToString(prefix);
573         return getSubnetFromPrefix(prefixStr);
574     }
575
576     private static String getAddressFromSubnet(String prefix) {
577         String myAddress = getIpAddressFromPrefix(prefix);
578         return myAddress + IP_ADDR_SUFFIX;
579     }
580
581     public static String getUUidFromString(String key) {
582         return java.util.UUID.nameUUIDFromBytes(key.getBytes()).toString();
583     }
584
585     public static String ipPrefixToString(IpPrefix ipAddress) {
586         if (ipAddress.getIpv4Prefix() != null) {
587             return ipAddress.getIpv4Prefix().getValue();
588         }
589
590         return ipAddress.getIpv6Prefix().getValue();
591     }
592
593     public static String ipAddressToString(IpAddress ipAddress) {
594         if (ipAddress.getIpv4Address() != null) {
595             return ipAddress.getIpv4Address().getValue();
596         }
597
598         return ipAddress.getIpv6Address().getValue();
599     }
600 }