b5c71fc8d548b8cf94f12dba7c3294addcc50368
[netvirt.git] / vpnmanager / impl / src / main / java / org / opendaylight / netvirt / vpnmanager / VpnUtil.java
1 /*
2  * Copyright © 2016, 2017 Ericsson India Global Services Pvt Ltd. 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.netvirt.vpnmanager;
10
11 import com.google.common.base.Optional;
12 import com.google.common.collect.Iterators;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import java.math.BigInteger;
16 import java.net.Inet4Address;
17 import java.net.Inet6Address;
18 import java.net.InetAddress;
19 import java.net.UnknownHostException;
20 import java.text.SimpleDateFormat;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Date;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Locale;
29 import java.util.Map;
30 import java.util.Map.Entry;
31 import java.util.Set;
32 import java.util.concurrent.ExecutionException;
33 import java.util.concurrent.Future;
34 import java.util.function.Predicate;
35 import java.util.stream.Collectors;
36 import javax.annotation.Nonnull;
37 import javax.annotation.Nullable;
38 import javax.inject.Singleton;
39
40 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
41 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
42 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
43 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
44 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
45 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
46 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
47 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
48 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
49 import org.opendaylight.genius.mdsalutil.FlowEntity;
50 import org.opendaylight.genius.mdsalutil.FlowEntityBuilder;
51 import org.opendaylight.genius.mdsalutil.InstructionInfo;
52 import org.opendaylight.genius.mdsalutil.MDSALUtil;
53 import org.opendaylight.genius.mdsalutil.MatchInfo;
54 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
55 import org.opendaylight.genius.mdsalutil.NWUtil;
56 import org.opendaylight.genius.mdsalutil.NwConstants;
57 import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
58 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
59 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
60 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
61 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetDestination;
62 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
63 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
64 import org.opendaylight.genius.utils.ServiceIndex;
65 import org.opendaylight.genius.utils.SystemPropertyReader;
66 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
67 import org.opendaylight.infrautils.utils.concurrent.ListenableFutures;
68 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
69 import org.opendaylight.netvirt.elanmanager.api.ElanHelper;
70 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
71 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
72 import org.opendaylight.netvirt.neutronvpn.api.enums.IpVersionChoice;
73 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
74 import org.opendaylight.netvirt.vpnmanager.api.InterfaceUtils;
75 import org.opendaylight.netvirt.vpnmanager.api.VpnExtraRouteHelper;
76 import org.opendaylight.netvirt.vpnmanager.api.VpnHelper;
77 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
78 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
79 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
80 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
81 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
82 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
83 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
84 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
85 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
86 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
87 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
88 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
89 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
90 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
91 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
92 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdOutput;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.IfIndexesInterfaceMap;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._if.indexes._interface.map.IfIndexInterface;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._if.indexes._interface.map.IfIndexInterfaceKey;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInput;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInputBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexOutput;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.ipv6.nd.util.rev170210.Ipv6NdUtilService;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.ipv6.nd.util.rev170210.SendNeighborSolicitationToOfGroupInput;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.ipv6.nd.util.rev170210.SendNeighborSolicitationToOfGroupInputBuilder;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.ipv6.nd.util.rev170210.SendNeighborSolicitationToOfGroupOutput;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockManagerService;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TimeUnits;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInput;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockInputBuilder;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.TryLockOutput;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInput;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockInputBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.UnlockOutput;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanTagNameMap;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.SegmentTypeVlan;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesListKey;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesKey;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterface;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.interfaces.ElanInterfaceKey;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagName;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagNameKey;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.VrfEntryBase;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.extraroute.rds.map.extraroute.rds.dest.prefixes.AllocatedRdsBuilder;
139 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.extraroute.rds.map.extraroute.rds.dest.prefixes.AllocatedRdsKey;
140 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
141 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
142 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
143 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
144 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.L3nexthop;
145 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthops;
146 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthopsKey;
147 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
148 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
149 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOp;
150 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesOpBuilder;
151 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.LearntVpnVipToPortData;
152 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.LearntVpnVipToPortEventAction;
153 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.LearntVpnVipToPortEventData;
154 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.PrefixToInterface;
155 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.SubnetOpData;
156 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnIdToVpnInstance;
157 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
158 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInterfaceOpData;
159 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnToExtraroutes;
160 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
161 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency.AdjacencyType;
162 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
163 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPort;
164 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPortBuilder;
165 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.data.LearntVpnVipToPortKey;
166 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.event.data.LearntVpnVipToPortEvent;
167 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.event.data.LearntVpnVipToPortEventBuilder;
168 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.learnt.vpn.vip.to.port.event.data.LearntVpnVipToPortEventKey;
169 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.VpnIds;
170 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.VpnIdsKey;
171 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
172 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesBuilder;
173 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey;
174 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
175 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
176 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntry;
177 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryBuilder;
178 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn._interface.op.data.VpnInterfaceOpDataEntryKey;
179 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
180 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
181 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnTargets;
182 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
183 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpntargets.VpnTarget;
184 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceBuilder;
185 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.Vpn;
186 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.VpnKey;
187 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.vpn.extra.routes.Routes;
188 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroutes.vpn.extra.routes.RoutesBuilder;
189 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExtRouters;
190 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks;
191 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalSubnets;
192 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.NaptSwitches;
193 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.Routers;
194 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersKey;
195 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.routers.ExternalIps;
196 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks;
197 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey;
198 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.SubnetsKey;
199 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitch;
200 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
201 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes.NetworkType;
202 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkMaps;
203 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
204 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
205 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
206 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey;
207 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
208 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
209 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
210 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
211 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.IpVersionBase;
212 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.constants.rev150712.IpVersionV4;
213 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.ext.rev150712.NetworkL3Extension;
214 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
215 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.NetworkKey;
216 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
217 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
218 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
219 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
220 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
221 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
222 import org.opendaylight.yangtools.yang.binding.DataObject;
223 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
224 import org.opendaylight.yangtools.yang.common.RpcResult;
225 import org.slf4j.Logger;
226 import org.slf4j.LoggerFactory;
227
228 @Singleton
229 public final class VpnUtil {
230
231     private static final Logger LOG = LoggerFactory.getLogger(VpnUtil.class);
232
233     static final int SINGLE_TRANSACTION_BROKER_NO_RETRY = 1;
234
235     private final DataBroker dataBroker;
236     private final IdManagerService idManager;
237     private final IBgpManager bgpManager;
238     private final LockManagerService lockManager;
239     private final INeutronVpnManager neutronVpnService;
240     private final IMdsalApiManager mdsalManager;
241     private final IInterfaceManager interfaceManager;
242     private final JobCoordinator jobCoordinator;
243     private final ManagedNewTransactionRunner txRunner;
244     private final OdlInterfaceRpcService ifmRpcService;
245
246     /**
247      * Class to generate timestamps with microsecond precision.
248      * For example: MicroTimestamp.INSTANCE.get() = "2012-10-21 19:13:45.267128"
249      */
250     public enum MicroTimestamp {
251         INSTANCE ;
252
253         private long              startDate ;
254         private long              startNanoseconds ;
255         private SimpleDateFormat  dateFormat ;
256
257         MicroTimestamp() {
258             this.startDate = System.currentTimeMillis() ;
259             this.startNanoseconds = System.nanoTime() ;
260             this.dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") ;
261         }
262
263         public String get() {
264             long microSeconds = (System.nanoTime() - this.startNanoseconds) / 1000 ;
265             long date = this.startDate + microSeconds / 1000 ;
266             return this.dateFormat.format(date) + String.format("%03d", microSeconds % 1000) ;
267         }
268     }
269
270     public VpnUtil(DataBroker dataBroker, IdManagerService idManager, IBgpManager bgpManager,
271                    LockManagerService lockManager, INeutronVpnManager neutronVpnService,
272                    IMdsalApiManager mdsalManager, JobCoordinator jobCoordinator,
273                    IInterfaceManager interfaceManager, OdlInterfaceRpcService ifmRpcService) {
274         this.dataBroker = dataBroker;
275         this.idManager = idManager;
276         this.bgpManager = bgpManager;
277         this.lockManager = lockManager;
278         this.neutronVpnService = neutronVpnService;
279         this.mdsalManager = mdsalManager;
280         this.interfaceManager = interfaceManager;
281         this.jobCoordinator = jobCoordinator;
282         this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
283         this.ifmRpcService = ifmRpcService;
284     }
285
286     public static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
287         return InstanceIdentifier.builder(VpnInterfaces.class)
288                 .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build();
289     }
290
291     static InstanceIdentifier<VpnInterfaceOpDataEntry> getVpnInterfaceOpDataEntryIdentifier(String vpnInterfaceName,
292                                                                                      String vpnName) {
293         return InstanceIdentifier.builder(VpnInterfaceOpData.class).child(VpnInterfaceOpDataEntry.class,
294             new VpnInterfaceOpDataEntryKey(vpnInterfaceName, vpnName)).build();
295     }
296
297     static InstanceIdentifier<VpnInstance> getVpnInstanceIdentifier(String vpnName) {
298         return InstanceIdentifier.builder(VpnInstances.class)
299                 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
300     }
301
302     VpnInterface getVpnInterface(String vpnInterfaceName) {
303         InstanceIdentifier<VpnInterface> id = getVpnInterfaceIdentifier(vpnInterfaceName);
304         Optional<VpnInterface> vpnInterface = read(LogicalDatastoreType.CONFIGURATION, id);
305         return vpnInterface.isPresent() ? vpnInterface.get() : null;
306     }
307
308     static VpnInterfaceOpDataEntry getVpnInterfaceOpDataEntry(String intfName, String vpnName, AdjacenciesOp aug,
309                                                        BigInteger dpnId, Boolean isSheduledForRemove, long lportTag,
310                                                        String gwMac) {
311         return new VpnInterfaceOpDataEntryBuilder().withKey(new VpnInterfaceOpDataEntryKey(intfName, vpnName))
312             .setDpnId(dpnId).setScheduledForRemove(isSheduledForRemove).addAugmentation(AdjacenciesOp.class, aug)
313                 .setLportTag(lportTag).setGatewayMacAddress(gwMac).build();
314     }
315
316     Optional<VpnInterfaceOpDataEntry> getVpnInterfaceOpDataEntry(String vpnInterfaceName, String vpnName) {
317         InstanceIdentifier<VpnInterfaceOpDataEntry> id = getVpnInterfaceOpDataEntryIdentifier(vpnInterfaceName,
318                                                                                               vpnName);
319         Optional<VpnInterfaceOpDataEntry> vpnInterfaceOpDataEntry = read(LogicalDatastoreType.OPERATIONAL,
320                 id);
321         return vpnInterfaceOpDataEntry;
322     }
323
324     static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
325         return InstanceIdentifier.builder(PrefixToInterface.class).child(VpnIds.class, new VpnIdsKey(vpnId))
326                 .child(Prefixes.class, new PrefixesKey(ipPrefix)).build();
327     }
328
329     static InstanceIdentifier<VpnIds> getPrefixToInterfaceIdentifier(long vpnId) {
330         return InstanceIdentifier.builder(PrefixToInterface.class).child(VpnIds.class, new VpnIdsKey(vpnId)).build();
331     }
332
333     static Prefixes getPrefixToInterface(BigInteger dpId, String vpnInterfaceName, String ipPrefix, Uuid subnetId,
334             Prefixes.PrefixCue prefixCue) {
335         return new PrefixesBuilder().setDpnId(dpId).setVpnInterfaceName(vpnInterfaceName).setIpAddress(ipPrefix)
336                 .setSubnetId(subnetId).setPrefixCue(prefixCue).build();
337     }
338
339     Optional<Prefixes> getPrefixToInterface(long vpnId, String ipPrefix) {
340         return read(LogicalDatastoreType.OPERATIONAL, getPrefixToInterfaceIdentifier(vpnId, getIpPrefix(ipPrefix)));
341     }
342
343     /**
344      * Get VRF table given a Route Distinguisher.
345      *
346      * @param rd Route-Distinguisher
347      * @return VrfTables that holds the list of VrfEntries of the specified rd
348      */
349     VrfTables getVrfTable(String rd) {
350         InstanceIdentifier<VrfTables> id = InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class,
351                 new VrfTablesKey(rd)).build();
352         Optional<VrfTables> vrfTable = read(LogicalDatastoreType.CONFIGURATION, id);
353         return vrfTable.isPresent() ? vrfTable.get() : null;
354     }
355
356     /**
357      * Retrieves the VrfEntries that belong to a given VPN filtered out by
358      * Origin, searching by its Route-Distinguisher.
359      *
360      * @param rd Route-distinguisher of the VPN
361      * @param originsToConsider Only entries whose origin is included in this list will be considered
362      * @return the list of VrfEntries
363      */
364     public List<VrfEntry> getVrfEntriesByOrigin(String rd, List<RouteOrigin> originsToConsider) {
365         List<VrfEntry> result = new ArrayList<>();
366         List<VrfEntry> allVpnVrfEntries = getAllVrfEntries(rd);
367         for (VrfEntry vrfEntry : allVpnVrfEntries) {
368             if (originsToConsider.contains(RouteOrigin.value(vrfEntry.getOrigin()))) {
369                 result.add(vrfEntry);
370             }
371         }
372         return result;
373     }
374
375     /**
376      * Retrieves all the VrfEntries that belong to a given VPN searching by its
377      * Route-Distinguisher.
378      *
379      * @param rd Route-distinguisher of the VPN
380      * @return the list of VrfEntries
381      */
382     public List<VrfEntry> getAllVrfEntries(String rd) {
383         VrfTables vrfTables = getVrfTable(rd);
384         return vrfTables != null ? vrfTables.getVrfEntry() : new ArrayList<>();
385     }
386
387     //FIXME: Implement caches for DS reads
388     public VpnInstance getVpnInstance(String vpnInstanceName) {
389         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class,
390             new VpnInstanceKey(vpnInstanceName)).build();
391         Optional<VpnInstance> vpnInstance = read(LogicalDatastoreType.CONFIGURATION, id);
392         return vpnInstance.isPresent() ? vpnInstance.get() : null;
393     }
394
395     List<VpnInstanceOpDataEntry> getAllVpnInstanceOpData() {
396         InstanceIdentifier<VpnInstanceOpData> id = InstanceIdentifier.builder(VpnInstanceOpData.class).build();
397         Optional<VpnInstanceOpData> vpnInstanceOpDataOptional = read(LogicalDatastoreType.OPERATIONAL, id);
398         return vpnInstanceOpDataOptional.isPresent() ?  vpnInstanceOpDataOptional.get().getVpnInstanceOpDataEntry()
399                 : Collections.emptyList();
400     }
401
402     List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
403             .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> getDpnVpnInterfaces(VpnInstance vpnInstance,
404                                                                                            BigInteger dpnId) {
405         String primaryRd = getPrimaryRd(vpnInstance);
406         InstanceIdentifier<VpnToDpnList> dpnToVpnId = VpnHelper.getVpnToDpnListIdentifier(primaryRd, dpnId);
407         Optional<VpnToDpnList> dpnInVpn = read(LogicalDatastoreType.OPERATIONAL, dpnToVpnId);
408         return dpnInVpn.isPresent() ? dpnInVpn.get().getVpnInterfaces() : Collections.emptyList();
409     }
410
411     static List<String> getListOfRdsFromVpnInstance(VpnInstance vpnInstance) {
412         VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
413         LOG.trace("vpnConfig {}", vpnConfig);
414         return vpnConfig.getRouteDistinguisher() != null ? vpnConfig.getRouteDistinguisher() : Collections.emptyList();
415     }
416
417     VrfEntry getVrfEntry(String rd, String ipPrefix) {
418         VrfTables vrfTable = getVrfTable(rd);
419         // TODO: why check VrfTables if we later go for the specific VrfEntry?
420         if (vrfTable != null) {
421             InstanceIdentifier<VrfEntry> vrfEntryId =
422                 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(
423                     VrfEntry.class, new VrfEntryKey(ipPrefix)).build();
424             Optional<VrfEntry> vrfEntry = read(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
425             if (vrfEntry.isPresent()) {
426                 return vrfEntry.get();
427             }
428         }
429         return null;
430     }
431
432     public List<Adjacency> getAdjacenciesForVpnInterfaceFromConfig(String intfName) {
433         final InstanceIdentifier<VpnInterface> identifier = getVpnInterfaceIdentifier(intfName);
434         InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
435         Optional<Adjacencies> adjacencies = read(LogicalDatastoreType.CONFIGURATION, path);
436         if (adjacencies.isPresent()) {
437             List<Adjacency> nextHops = adjacencies.get().getAdjacency();
438             return nextHops;
439         }
440         return null;
441     }
442
443     static Routes getVpnToExtraroute(String ipPrefix, List<String> nextHopList) {
444         return new RoutesBuilder().setPrefix(ipPrefix).setNexthopIpList(nextHopList).build();
445     }
446
447     String getVpnInterfaceName(BigInteger metadata) throws InterruptedException, ExecutionException {
448         GetInterfaceFromIfIndexInputBuilder ifIndexInputBuilder = new GetInterfaceFromIfIndexInputBuilder();
449         BigInteger lportTag = MetaDataUtil.getLportFromMetadata(metadata);
450         ifIndexInputBuilder.setIfIndex(lportTag.intValue());
451         GetInterfaceFromIfIndexInput input = ifIndexInputBuilder.build();
452         Future<RpcResult<GetInterfaceFromIfIndexOutput>> interfaceFromIfIndex =
453                 ifmRpcService.getInterfaceFromIfIndex(input);
454         GetInterfaceFromIfIndexOutput interfaceFromIfIndexOutput;
455         RpcResult<GetInterfaceFromIfIndexOutput> rpcResult = interfaceFromIfIndex.get();
456         if (rpcResult == null) {
457             return null;
458         }
459         interfaceFromIfIndexOutput = rpcResult.getResult();
460         return interfaceFromIfIndexOutput.getInterfaceName();
461     }
462
463     static AllocatedRdsBuilder getRdsBuilder(String nexthop, String rd) {
464         return new AllocatedRdsBuilder().withKey(new AllocatedRdsKey(nexthop)).setNexthop(nexthop).setRd(rd);
465     }
466
467     public static Adjacencies getVpnInterfaceAugmentation(List<Adjacency> nextHopList) {
468         return new AdjacenciesBuilder().setAdjacency(nextHopList).build();
469     }
470
471     static AdjacenciesOp getVpnInterfaceOpDataEntryAugmentation(List<Adjacency> nextHopList) {
472         return new AdjacenciesOpBuilder().setAdjacency(nextHopList).build();
473     }
474
475     static InstanceIdentifier<Interface> getInterfaceIdentifier(String interfaceName) {
476         return InstanceIdentifier.builder(Interfaces.class).child(Interface.class,
477                 new InterfaceKey(interfaceName)).build();
478     }
479
480     public static BigInteger getCookieL3(int vpnId) {
481         return VpnConstants.COOKIE_L3_BASE.add(new BigInteger("0610000", 16)).add(BigInteger.valueOf(vpnId));
482     }
483
484     public int getUniqueId(String poolName, String idKey) {
485         AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
486         try {
487             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
488             RpcResult<AllocateIdOutput> rpcResult = result.get();
489             if (rpcResult.isSuccessful()) {
490                 return rpcResult.getResult().getIdValue().intValue();
491             } else {
492                 LOG.error("getUniqueId: RPC Call to Get Unique Id from pool {} with key {} returned with Errors {}",
493                         poolName, idKey, rpcResult.getErrors());
494             }
495         } catch (InterruptedException | ExecutionException e) {
496             LOG.error("getUniqueId: Exception when getting Unique Id from pool {} for key {}", poolName, idKey, e);
497         }
498         return 0;
499     }
500
501     void releaseId(String poolName, String idKey) {
502         ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
503         try {
504             RpcResult<ReleaseIdOutput> rpcResult = idManager.releaseId(idInput).get();
505             if (!rpcResult.isSuccessful()) {
506                 LOG.error("releaseId: RPC Call to release Id for key {} from pool {} returned with Errors {}",
507                         idKey, poolName, rpcResult.getErrors());
508             }
509         } catch (InterruptedException | ExecutionException e) {
510             LOG.error("releaseId: Exception when releasing Id for key {} from pool {}", idKey, poolName, e);
511         }
512     }
513
514     public static String getNextHopLabelKey(String rd, String prefix) {
515         return rd + VpnConstants.SEPARATOR + prefix;
516     }
517
518     /**
519      * Retrieves the dataplane identifier of a specific VPN, searching by its
520      * VpnInstance name.
521      *
522      * @param vpnName Name of the VPN
523      * @return the dataplane identifier of the VPN, the VrfTag.
524      */
525     public long getVpnId(String vpnName) {
526         if (vpnName == null) {
527             return VpnConstants.INVALID_ID;
528         }
529
530         return read(LogicalDatastoreType.CONFIGURATION, VpnOperDsUtils.getVpnInstanceToVpnIdIdentifier(vpnName))
531                 .toJavaUtil().map(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911
532                         .vpn.instance.to.vpn.id.VpnInstance::getVpnId).orElse(VpnConstants.INVALID_ID);
533     }
534
535     /**
536      * Retrieves the VPN Route Distinguisher searching by its Vpn instance name.
537      *
538      * @param vpnName Name of the VPN
539      * @return the route-distinguisher of the VPN
540      */
541     public String getVpnRd(String vpnName) {
542         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
543             .VpnInstance> vpnInstance = read(LogicalDatastoreType.CONFIGURATION,
544                 VpnOperDsUtils.getVpnInstanceToVpnIdIdentifier(vpnName));
545         String rd = null;
546         if (vpnInstance.isPresent()) {
547             rd = vpnInstance.get().getVrfId();
548         }
549         return rd;
550     }
551
552     List<String> getVpnRdsFromVpnInstanceConfig(String vpnName) {
553         InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
554             .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
555         Optional<VpnInstance> vpnInstance = read(LogicalDatastoreType.CONFIGURATION, id);
556         return vpnInstance.isPresent() ? getListOfRdsFromVpnInstance(vpnInstance.get()) : new ArrayList<>();
557     }
558
559     /**
560      * Remove from MDSAL all those VrfEntries in a VPN that have an specific RouteOrigin.
561      *
562      * @param rd Route Distinguisher
563      * @param origin Origin of the Routes to be removed (see {@link RouteOrigin})
564      */
565     public void removeVrfEntriesByOrigin(String rd, RouteOrigin origin) {
566         InstanceIdentifier<VrfTables> vpnVrfTableIid =
567             InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
568         Optional<VrfTables> vrfTablesOpc = read(LogicalDatastoreType.CONFIGURATION, vpnVrfTableIid);
569         if (vrfTablesOpc.isPresent()) {
570             VrfTables vrfTables = vrfTablesOpc.get();
571             ListenableFutures.addErrorLogging(
572                     new ManagedNewTransactionRunnerImpl(dataBroker).callWithNewWriteOnlyTransactionAndSubmit(tx -> {
573                         for (VrfEntry vrfEntry : vrfTables.getVrfEntry()) {
574                             if (origin == RouteOrigin.value(vrfEntry.getOrigin())) {
575                                 tx.delete(LogicalDatastoreType.CONFIGURATION,
576                                         vpnVrfTableIid.child(VrfEntry.class, vrfEntry.key()));
577                             }
578                         }
579                     }), LOG, "Error removing VRF entries by origin");
580         }
581     }
582
583     public List<VrfEntry> findVrfEntriesByNexthop(String rd, String nexthop) {
584         InstanceIdentifier<VrfTables> vpnVrfTableIid =
585             InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
586         Optional<VrfTables> vrfTablesOpc = read(LogicalDatastoreType.CONFIGURATION, vpnVrfTableIid);
587         List<VrfEntry> matches = new ArrayList<>();
588         if (vrfTablesOpc.isPresent()) {
589             VrfTables vrfTables = vrfTablesOpc.get();
590             for (VrfEntry vrfEntry : vrfTables.getVrfEntry()) {
591                 vrfEntry.getRoutePaths().stream()
592                         .filter(routePath -> routePath.getNexthopAddress() != null && routePath.getNexthopAddress()
593                                 .equals(nexthop)).findFirst().ifPresent(routePath -> matches.add(vrfEntry));
594             }
595         }
596         return matches;
597     }
598
599     public void removeVrfEntries(String rd, List<VrfEntry> vrfEntries) {
600         InstanceIdentifier<VrfTables> vpnVrfTableIid =
601             InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
602         ListenableFutures.addErrorLogging(
603                 new ManagedNewTransactionRunnerImpl(dataBroker).callWithNewWriteOnlyTransactionAndSubmit(tx -> {
604                     for (VrfEntry vrfEntry : vrfEntries) {
605                         tx.delete(LogicalDatastoreType.CONFIGURATION,
606                                 vpnVrfTableIid.child(VrfEntry.class, vrfEntry.key()));
607                     }
608                 }), LOG, "Error removing VRF entries");
609     }
610
611     // TODO Clean up the exception handling
612     @SuppressWarnings("checkstyle:IllegalCatch")
613     public void withdrawRoutes(String rd, List<VrfEntry> vrfEntries) {
614         vrfEntries.forEach(vrfEntry -> {
615             try {
616                 bgpManager.withdrawPrefix(rd, vrfEntry.getDestPrefix());
617             } catch (Exception e) {
618                 LOG.error("withdrawRoutes: Could not withdraw route to {} with route-paths {} in VpnRd {}",
619                           vrfEntry.getDestPrefix(), vrfEntry.getRoutePaths(), rd);
620             }
621         });
622     }
623
624     static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
625         getVpnInstanceToVpnId(String vpnName, long vpnId, String rd) {
626         return new VpnInstanceBuilder().setVpnId(vpnId).setVpnInstanceName(vpnName).setVrfId(rd).build();
627
628     }
629
630     static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds
631         getVpnIdToVpnInstance(long vpnId, String vpnName, String rd, boolean isExternalVpn) {
632         return new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance
633             .VpnIdsBuilder().setVpnId(vpnId).setVpnInstanceName(vpnName).setVrfId(rd).setExternalVpn(isExternalVpn)
634                 .build();
635
636     }
637
638     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to
639         .vpn.instance.VpnIds> getVpnIdToVpnInstanceIdentifier(long vpnId) {
640         return InstanceIdentifier.builder(VpnIdToVpnInstance.class).child(org.opendaylight.yang.gen.v1.urn
641                 .opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds.class,
642                 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance
643                     .VpnIdsKey(vpnId)).build();
644     }
645
646     /**
647      * Retrieves the Vpn Name searching by its VPN Tag.
648      *
649      * @param vpnId Dataplane identifier of the VPN
650      * @return the Vpn instance name
651      */
652     String getVpnName(long vpnId) {
653
654         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn
655             .instance.VpnIds> id = getVpnIdToVpnInstanceIdentifier(vpnId);
656         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds>
657             vpnInstance
658             = read(LogicalDatastoreType.CONFIGURATION, id);
659         String vpnName = null;
660         if (vpnInstance.isPresent()) {
661             vpnName = vpnInstance.get().getVpnInstanceName();
662         }
663         return vpnName;
664     }
665
666     public static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
667         return InstanceIdentifier.builder(VpnInstanceOpData.class)
668             .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
669     }
670
671     public VpnInstanceOpDataEntry getVpnInstanceOpData(String rd) {
672         InstanceIdentifier<VpnInstanceOpDataEntry> id = getVpnInstanceOpDataIdentifier(rd);
673         return read(LogicalDatastoreType.OPERATIONAL, id).orNull();
674     }
675
676     VpnInterface getConfiguredVpnInterface(String interfaceName) {
677         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
678         Optional<VpnInterface> configuredVpnInterface = read(LogicalDatastoreType.CONFIGURATION, interfaceId);
679         if (configuredVpnInterface.isPresent()) {
680             return configuredVpnInterface.get();
681         }
682         return null;
683     }
684
685     boolean isVpnInterfaceConfigured(String interfaceName) {
686         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
687         return read(LogicalDatastoreType.CONFIGURATION, interfaceId).isPresent();
688     }
689
690     public Optional<List<String>> getVpnHandlingIpv4AssociatedWithInterface(String interfaceName) {
691         InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
692         Optional<List<String>> vpnOptional = Optional.absent();
693         Optional<VpnInterface> optConfiguredVpnInterface = read(LogicalDatastoreType.CONFIGURATION, interfaceId);
694         if (optConfiguredVpnInterface.isPresent()) {
695             VpnInterface cfgVpnInterface = optConfiguredVpnInterface.get();
696             java.util.Optional<List<VpnInstanceNames>> optVpnInstanceList =
697                  java.util.Optional.ofNullable(cfgVpnInterface.getVpnInstanceNames());
698             if (optVpnInstanceList.isPresent()) {
699                 List<String> vpnList = new ArrayList<>();
700                 for (VpnInstanceNames vpnInstance : optVpnInstanceList.get()) {
701                     vpnList.add(vpnInstance.getVpnName());
702                 }
703                 vpnOptional = Optional.of(vpnList);
704             }
705         }
706         return vpnOptional;
707     }
708
709     public static String getIpPrefix(String prefix) {
710         String[] prefixValues = prefix.split("/");
711         if (prefixValues.length == 1) {
712             prefix = NWUtil.toIpPrefix(prefix);
713         }
714         return prefix;
715     }
716
717     static final FutureCallback<Void> DEFAULT_CALLBACK =
718         new FutureCallback<Void>() {
719             @Override
720             public void onSuccess(Void result) {
721                 LOG.debug("Success in Datastore operation");
722             }
723
724             @Override
725             public void onFailure(Throwable error) {
726                 LOG.error("Error in Datastore operation", error);
727             }
728
729         };
730
731     @Deprecated
732     private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
733         try {
734             return SingleTransactionDataBroker.syncReadOptional(dataBroker, datastoreType, path);
735         } catch (ReadFailedException e) {
736             throw new RuntimeException(e);
737         }
738     }
739
740     @Deprecated
741     public <T extends DataObject> void syncWrite(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path,
742                                                  T data) {
743         try {
744             SingleTransactionDataBroker.syncWrite(dataBroker, datastoreType, path, data);
745         } catch (TransactionCommitFailedException e) {
746             LOG.error("syncWrite: Error writing to datastore (path, data) : ({}, {})", path, data, e);
747             throw new RuntimeException(e.getMessage(), e);
748         }
749     }
750
751     @Deprecated
752     public <T extends DataObject> void syncUpdate(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path,
753                                                   T data) {
754         try {
755             SingleTransactionDataBroker.syncUpdate(dataBroker, datastoreType, path, data);
756         } catch (TransactionCommitFailedException e) {
757             LOG.error("syncUpdate: Error writing to datastore (path, data) : ({}, {})", path, data, e);
758             throw new RuntimeException(e.getMessage(), e);
759         }
760     }
761
762     static long getRemoteBCGroup(long elanTag) {
763         return VpnConstants.ELAN_GID_MIN + elanTag % VpnConstants.ELAN_GID_MIN * 2;
764     }
765
766     // interface-index-tag operational container
767     IfIndexInterface getInterfaceInfoByInterfaceTag(long interfaceTag) {
768         InstanceIdentifier<IfIndexInterface> interfaceId = getInterfaceInfoEntriesOperationalDataPath(interfaceTag);
769         Optional<IfIndexInterface> existingInterfaceInfo = read(LogicalDatastoreType.OPERATIONAL, interfaceId);
770         if (existingInterfaceInfo.isPresent()) {
771             return existingInterfaceInfo.get();
772         }
773         return null;
774     }
775
776     static InstanceIdentifier<IfIndexInterface> getInterfaceInfoEntriesOperationalDataPath(long interfaceTag) {
777         return InstanceIdentifier.builder(IfIndexesInterfaceMap.class).child(IfIndexInterface.class,
778             new IfIndexInterfaceKey((int) interfaceTag)).build();
779     }
780
781     ElanTagName getElanInfoByElanTag(long elanTag) {
782         InstanceIdentifier<ElanTagName> elanId = getElanInfoEntriesOperationalDataPath(elanTag);
783         Optional<ElanTagName> existingElanInfo = read(LogicalDatastoreType.OPERATIONAL, elanId);
784         if (existingElanInfo.isPresent()) {
785             return existingElanInfo.get();
786         }
787         return null;
788     }
789
790     static InstanceIdentifier<ElanTagName> getElanInfoEntriesOperationalDataPath(long elanTag) {
791         return InstanceIdentifier.builder(ElanTagNameMap.class).child(ElanTagName.class,
792             new ElanTagNameKey(elanTag)).build();
793     }
794
795     static void removePrefixToInterfaceForVpnId(long vpnId, @Nonnull WriteTransaction operTx) {
796         // Clean up PrefixToInterface Operational DS
797         operTx.delete(LogicalDatastoreType.OPERATIONAL,
798             InstanceIdentifier.builder(PrefixToInterface.class).child(VpnIds.class, new VpnIdsKey(vpnId)).build());
799     }
800
801     static void removeVpnExtraRouteForVpn(String vpnName, @Nonnull WriteTransaction operTx) {
802         // Clean up VPNExtraRoutes Operational DS
803         operTx.delete(LogicalDatastoreType.OPERATIONAL,
804                 InstanceIdentifier.builder(VpnToExtraroutes.class).child(Vpn.class, new VpnKey(vpnName)).build());
805     }
806
807     // TODO Clean up the exception handling
808     @SuppressWarnings("checkstyle:IllegalCatch")
809     static void removeVpnOpInstance(String vpnName, @Nonnull WriteTransaction operTx) {
810         // Clean up VPNInstanceOpDataEntry
811         operTx.delete(LogicalDatastoreType.OPERATIONAL, getVpnInstanceOpDataIdentifier(vpnName));
812     }
813
814     static void removeVpnInstanceToVpnId(String vpnName, @Nonnull WriteTransaction confTx) {
815         confTx.delete(LogicalDatastoreType.CONFIGURATION, VpnOperDsUtils.getVpnInstanceToVpnIdIdentifier(vpnName));
816     }
817
818     static void removeVpnIdToVpnInstance(long vpnId, @Nonnull WriteTransaction confTx) {
819         confTx.delete(LogicalDatastoreType.CONFIGURATION, getVpnIdToVpnInstanceIdentifier(vpnId));
820     }
821
822     static void removeL3nexthopForVpnId(long vpnId, @Nonnull WriteTransaction operTx) {
823         // Clean up L3NextHop Operational DS
824         operTx.delete(LogicalDatastoreType.OPERATIONAL,
825             InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).build());
826     }
827
828     void scheduleVpnInterfaceForRemoval(String interfaceName, BigInteger dpnId, String vpnInstanceName,
829                                         Boolean isScheduledToRemove, WriteTransaction writeOperTxn) {
830         InstanceIdentifier<VpnInterfaceOpDataEntry> interfaceId =
831                 getVpnInterfaceOpDataEntryIdentifier(interfaceName, vpnInstanceName);
832         VpnInterfaceOpDataEntry interfaceToUpdate =
833             new VpnInterfaceOpDataEntryBuilder().withKey(new VpnInterfaceOpDataEntryKey(interfaceName,
834             vpnInstanceName)).setName(interfaceName).setDpnId(dpnId).setVpnInstanceName(vpnInstanceName)
835             .setScheduledForRemove(isScheduledToRemove).build();
836         if (writeOperTxn != null) {
837             writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate, true);
838         } else {
839             syncUpdate(LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate);
840         }
841     }
842
843     void createLearntVpnVipToPort(String vpnName, String fixedIp, String portName, String macAddress,
844                                   WriteTransaction writeOperTxn) {
845         synchronized ((vpnName + fixedIp).intern()) {
846             InstanceIdentifier<LearntVpnVipToPort> id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp);
847             LearntVpnVipToPortBuilder builder =
848                     new LearntVpnVipToPortBuilder().withKey(new LearntVpnVipToPortKey(fixedIp, vpnName)).setVpnName(
849                             vpnName).setPortFixedip(fixedIp).setPortName(portName)
850                             .setMacAddress(macAddress.toLowerCase(Locale.getDefault()))
851                             .setCreationTime(new SimpleDateFormat("MM/dd/yyyy h:mm:ss a").format(new Date()));
852             if (writeOperTxn != null) {
853                 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, id, builder.build(), true);
854             } else {
855                 syncWrite(LogicalDatastoreType.OPERATIONAL, id, builder.build());
856             }
857             LOG.debug("createLearntVpnVipToPort: ARP/NA learned for fixedIp: {}, vpn {}, interface {}, mac {},"
858                     + " added to LearntVpnVipToPort DS", fixedIp, vpnName, portName, macAddress);
859         }
860     }
861
862     static InstanceIdentifier<LearntVpnVipToPort> buildLearntVpnVipToPortIdentifier(String vpnName,
863             String fixedIp) {
864         return InstanceIdentifier.builder(LearntVpnVipToPortData.class).child(LearntVpnVipToPort.class,
865                 new LearntVpnVipToPortKey(fixedIp, vpnName)).build();
866     }
867
868     void removeLearntVpnVipToPort(String vpnName, String fixedIp, WriteTransaction writeOperTxn) {
869         synchronized ((vpnName + fixedIp).intern()) {
870             InstanceIdentifier<LearntVpnVipToPort> id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp);
871             if (writeOperTxn != null) {
872                 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, id);
873             } else {
874                 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
875             }
876             LOG.debug("removeLearntVpnVipToPort: Deleted LearntVpnVipToPort entry for fixedIp: {}, vpn {}",
877                 fixedIp, vpnName);
878         }
879     }
880
881     protected static void removeVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp,
882                                                      WriteTransaction writeConfigTxn) {
883         synchronized ((vpnName + fixedIp).intern()) {
884             InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
885             if (writeConfigTxn != null) {
886                 writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, id);
887             } else {
888                 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
889             }
890             LOG.debug("removeVpnPortFixedIpToPort: Deleted VpnPortipToPort entry for fixedIp: {}, vpn {}",
891                 fixedIp, vpnName);
892         }
893     }
894
895     public void createLearntVpnVipToPortEvent(String vpnName, String srcIp, String destIP, String portName,
896                                               String macAddress, LearntVpnVipToPortEventAction action,
897                                               WriteTransaction writeOperTxn) {
898         String eventId = MicroTimestamp.INSTANCE.get();
899
900         InstanceIdentifier<LearntVpnVipToPortEvent> id = buildLearntVpnVipToPortEventIdentifier(eventId);
901         LearntVpnVipToPortEventBuilder builder = new LearntVpnVipToPortEventBuilder().withKey(
902                 new LearntVpnVipToPortEventKey(eventId)).setVpnName(vpnName).setSrcFixedip(srcIp)
903                 .setDestFixedip(destIP).setPortName(portName)
904                 .setMacAddress(macAddress.toLowerCase(Locale.getDefault())).setEventAction(action);
905         if (writeOperTxn != null) {
906             writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, id);
907         } else {
908             syncWrite(LogicalDatastoreType.OPERATIONAL, id, builder.build());
909         }
910         LOG.info("createLearntVpnVipToPortEvent: ARP learn event created for fixedIp: {}, vpn {}, interface {},"
911                 + " mac {} action {} eventId {}", srcIp, vpnName, portName, macAddress, action, eventId);
912     }
913
914     private static InstanceIdentifier<LearntVpnVipToPortEvent> buildLearntVpnVipToPortEventIdentifier(String eventId) {
915         InstanceIdentifier<LearntVpnVipToPortEvent> id = InstanceIdentifier.builder(LearntVpnVipToPortEventData.class)
916                 .child(LearntVpnVipToPortEvent.class, new LearntVpnVipToPortEventKey(eventId)).build();
917         return id;
918     }
919
920     void removeLearntVpnVipToPortEvent(String eventId, WriteTransaction writeOperTxn) {
921         InstanceIdentifier<LearntVpnVipToPortEvent> id = buildLearntVpnVipToPortEventIdentifier(eventId);
922         if (writeOperTxn != null) {
923             writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, id);
924         } else {
925             MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
926         }
927         LOG.info("removeLearntVpnVipToPortEvent: Deleted Event {}", eventId);
928
929     }
930
931     void removeMipAdjAndLearntIp(String vpnName, String vpnInterface, String prefix) {
932         synchronized ((vpnName + prefix).intern()) {
933             InstanceIdentifier<LearntVpnVipToPort> id = buildLearntVpnVipToPortIdentifier(vpnName, prefix);
934             MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
935             LOG.info("removeMipAdjAndLearntIp: Delete learned ARP for fixedIp: {}, vpn {} removed from"
936                             + "VpnPortipToPort DS", prefix, vpnName);
937             String ip = VpnUtil.getIpPrefix(prefix);
938             InstanceIdentifier<VpnInterfaceOpDataEntry> vpnInterfaceOpId = VpnUtil
939                     .getVpnInterfaceOpDataEntryIdentifier(vpnInterface, vpnName);
940             InstanceIdentifier<AdjacenciesOp> path = vpnInterfaceOpId.augmentation(AdjacenciesOp.class);
941             Optional<AdjacenciesOp> adjacenciesOp = read(LogicalDatastoreType.OPERATIONAL, path);
942             if (adjacenciesOp.isPresent()) {
943                 InstanceIdentifier<Adjacency> adjacencyIdentifier = InstanceIdentifier.builder(VpnInterfaces.class)
944                         .child(VpnInterface.class, new VpnInterfaceKey(vpnInterface)).augmentation(Adjacencies.class)
945                         .child(Adjacency.class, new AdjacencyKey(ip)).build();
946                 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
947                 LOG.info("removeMipAdjAndLearntIp: Successfully Deleted Adjacency {} from interface {} vpn {}", ip,
948                         vpnInterface, vpnName);
949             }
950         }
951     }
952
953     static InstanceIdentifier<NetworkMap> buildNetworkMapIdentifier(Uuid networkId) {
954         return InstanceIdentifier.builder(NetworkMaps.class).child(NetworkMap.class, new
955                 NetworkMapKey(networkId)).build();
956     }
957
958     static InstanceIdentifier<SubnetOpDataEntry> buildSubnetOpDataEntryInstanceIdentifier(Uuid subnetId) {
959         return InstanceIdentifier.builder(SubnetOpData.class)
960                 .child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
961     }
962
963     static InstanceIdentifier<VpnPortipToPort> buildVpnPortipToPortIdentifier(String vpnName, String fixedIp) {
964         return InstanceIdentifier.builder(NeutronVpnPortipPortData.class).child(VpnPortipToPort.class,
965                 new VpnPortipToPortKey(fixedIp, vpnName)).build();
966     }
967
968     public VpnPortipToPort getNeutronPortFromVpnPortFixedIp(String vpnName, String fixedIp) {
969         InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
970         Optional<VpnPortipToPort> vpnPortipToPortData = read(LogicalDatastoreType.CONFIGURATION, id);
971         if (vpnPortipToPortData.isPresent()) {
972             return vpnPortipToPortData.get();
973         }
974         return null;
975     }
976
977     public LearntVpnVipToPort getLearntVpnVipToPort(String vpnName, String fixedIp) {
978         InstanceIdentifier<LearntVpnVipToPort> id = buildLearntVpnVipToPortIdentifier(vpnName, fixedIp);
979         Optional<LearntVpnVipToPort> learntVpnVipToPort = read(LogicalDatastoreType.OPERATIONAL, id);
980         if (learntVpnVipToPort.isPresent()) {
981             return learntVpnVipToPort.get();
982         }
983         return null;
984     }
985
986     @Nonnull
987     List<BigInteger> getDpnsOnVpn(String vpnInstanceName) {
988         List<BigInteger> result = new ArrayList<>();
989         String rd = getVpnRd(vpnInstanceName);
990         if (rd == null) {
991             LOG.debug("getDpnsOnVpn: Could not find Route-Distinguisher for VpnName={}", vpnInstanceName);
992             return result;
993         }
994         VpnInstanceOpDataEntry vpnInstanceOpData = getVpnInstanceOpData(rd);
995         if (vpnInstanceOpData == null) {
996             LOG.debug("getDpnsOnVpn: Could not find OpState for VpnName={}", vpnInstanceName);
997             return result;
998         }
999         List<VpnToDpnList> vpnToDpnList = vpnInstanceOpData.getVpnToDpnList();
1000         if (vpnToDpnList == null) {
1001             LOG.debug("getDpnsOnVpn: Could not find DPN footprint for VpnName={}", vpnInstanceName);
1002             return result;
1003         }
1004         for (VpnToDpnList vpnToDpn : vpnToDpnList) {
1005             result.add(vpnToDpn.getDpnId());
1006         }
1007         return result;
1008     }
1009
1010     String getAssociatedExternalRouter(String extIp) {
1011         InstanceIdentifier<ExtRouters> extRouterInstanceIndentifier =
1012                 InstanceIdentifier.builder(ExtRouters.class).build();
1013         Optional<ExtRouters> extRouterData = read(LogicalDatastoreType.CONFIGURATION, extRouterInstanceIndentifier);
1014         if (extRouterData.isPresent()) {
1015             for (Routers routerData : extRouterData.get().getRouters()) {
1016                 List<ExternalIps> externalIps = routerData.getExternalIps();
1017                 for (ExternalIps externalIp : externalIps) {
1018                     if (externalIp.getIpAddress().equals(extIp)) {
1019                         return routerData.getRouterName();
1020                     }
1021                 }
1022             }
1023         }
1024         return null;
1025     }
1026
1027     static InstanceIdentifier<Routers> buildRouterIdentifier(String routerId) {
1028         return InstanceIdentifier.builder(ExtRouters.class).child(Routers.class, new RoutersKey(routerId)).build();
1029     }
1030
1031     Networks getExternalNetwork(Uuid networkId) {
1032         InstanceIdentifier<Networks> netsIdentifier = InstanceIdentifier.builder(ExternalNetworks.class)
1033             .child(Networks.class, new NetworksKey(networkId)).build();
1034         Optional<Networks> optionalNets = read(LogicalDatastoreType.CONFIGURATION, netsIdentifier);
1035         return optionalNets.isPresent() ? optionalNets.get() : null;
1036     }
1037
1038     Uuid getExternalNetworkVpnId(Uuid networkId) {
1039         Networks extNetwork = getExternalNetwork(networkId);
1040         return extNetwork != null ? extNetwork.getVpnid() : null;
1041     }
1042
1043     List<Uuid> getExternalNetworkRouterIds(Uuid networkId) {
1044         Networks extNetwork = getExternalNetwork(networkId);
1045         return extNetwork != null ? extNetwork.getRouterIds() : Collections.emptyList();
1046     }
1047
1048     Routers getExternalRouter(String routerId) {
1049         InstanceIdentifier<Routers> id = InstanceIdentifier.builder(ExtRouters.class).child(Routers.class,
1050                 new RoutersKey(routerId)).build();
1051         Optional<Routers> routerData = read(LogicalDatastoreType.CONFIGURATION, id);
1052         return routerData.isPresent() ? routerData.get() : null;
1053     }
1054
1055     static InstanceIdentifier<Subnetmaps> buildSubnetMapsWildCardPath() {
1056         return InstanceIdentifier.create(Subnetmaps.class);
1057     }
1058
1059     FlowEntity buildL3vpnGatewayFlow(BigInteger dpId, String gwMacAddress, long vpnId,
1060                                                    long subnetVpnId) {
1061         List<MatchInfo> mkMatches = new ArrayList<>();
1062         Subnetmap smap = null;
1063         mkMatches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID));
1064         mkMatches.add(new MatchEthernetDestination(new MacAddress(gwMacAddress)));
1065         List<InstructionInfo> mkInstructions = new ArrayList<>();
1066         mkInstructions.add(new InstructionGotoTable(NwConstants.L3_FIB_TABLE));
1067         if (subnetVpnId != VpnConstants.INVALID_ID) {
1068             String vpnName = getVpnName(subnetVpnId);
1069             if (vpnName != null) {
1070                 smap = getSubnetmapFromItsUuid(Uuid.getDefaultInstance(vpnName));
1071                 if (smap != null && smap.getSubnetIp() != null) {
1072                     IpVersionChoice ipVersionChoice = getIpVersionFromString(smap.getSubnetIp());
1073                     if (ipVersionChoice == IpVersionChoice.IPV4) {
1074                         mkMatches.add(MatchEthernetType.IPV4);
1075                     } else {
1076                         mkMatches.add(MatchEthernetType.IPV6);
1077                     }
1078                 }
1079             }
1080             BigInteger subnetIdMetaData = MetaDataUtil.getVpnIdMetadata(subnetVpnId);
1081             mkInstructions.add(new InstructionWriteMetadata(subnetIdMetaData, MetaDataUtil.METADATA_MASK_VRFID));
1082         }
1083         String flowId = getL3VpnGatewayFlowRef(NwConstants.L3_GW_MAC_TABLE, dpId, vpnId, gwMacAddress, subnetVpnId);
1084         return MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_GW_MAC_TABLE,
1085                 flowId, 20, flowId, 0, 0, NwConstants.COOKIE_L3_GW_MAC_TABLE, mkMatches, mkInstructions);
1086     }
1087
1088     static String getL3VpnGatewayFlowRef(short l3GwMacTable, BigInteger dpId, long vpnId, String gwMacAddress,
1089                                          long subnetVpnId) {
1090         return gwMacAddress + NwConstants.FLOWID_SEPARATOR + vpnId + NwConstants.FLOWID_SEPARATOR + dpId
1091             + NwConstants.FLOWID_SEPARATOR + l3GwMacTable + NwConstants.FLOWID_SEPARATOR + subnetVpnId;
1092     }
1093
1094     void lockSubnet(String subnetId) {
1095         TryLockInput input =
1096             new TryLockInputBuilder().setLockName(subnetId).setTime(3000L).setTimeUnit(TimeUnits.Milliseconds).build();
1097         Future<RpcResult<TryLockOutput>> result = lockManager.tryLock(input);
1098         try {
1099             if (result != null && result.get().isSuccessful()) {
1100                 LOG.debug("lockSubnet: Acquired lock for {}", subnetId);
1101             } else {
1102                 LOG.error("Unable to get lock for subnet {}", subnetId);
1103                 throw new RuntimeException("Unable to get lock for subnet " + subnetId);
1104             }
1105         } catch (InterruptedException | ExecutionException e) {
1106             LOG.error("Unable to get lock for subnet {}", subnetId, e);
1107             throw new RuntimeException("Unable to get lock for subnet " + subnetId, e);
1108         }
1109     }
1110
1111     // We store the cause, which is what we really care about
1112     @SuppressWarnings("checkstyle:AvoidHidingCauseException")
1113     public void unlockSubnet(String subnetId) {
1114         UnlockInput input = new UnlockInputBuilder().setLockName(subnetId).build();
1115         Future<RpcResult<UnlockOutput>> result = lockManager.unlock(input);
1116         try {
1117             if (result != null && result.get().isSuccessful()) {
1118                 LOG.debug("unlockSubnet: Unlocked {}", subnetId);
1119             } else {
1120                 LOG.debug("unlockSubnet: Unable to unlock subnet {}", subnetId);
1121             }
1122         } catch (InterruptedException | ExecutionException e) {
1123             LOG.error("unlockSubnet: Unable to unlock subnet {}", subnetId);
1124             throw new RuntimeException(String.format("Unable to unlock subnetId %s", subnetId), e.getCause());
1125         }
1126     }
1127
1128     Optional<IpAddress> getIpv4GatewayAddressFromInterface(String srcInterface) {
1129         Optional<IpAddress> gatewayIp = Optional.absent();
1130         if (neutronVpnService != null) {
1131             //TODO(Gobinath): Need to fix this as assuming port will belong to only one Subnet would be incorrect"
1132             Port port = neutronVpnService.getNeutronPort(srcInterface);
1133             if (port != null && port.getFixedIps() != null) {
1134                 for (FixedIps portIp: port.getFixedIps()) {
1135                     if (portIp.getIpAddress().getIpv6Address() != null) {
1136                         // Skip IPv6 address
1137                         continue;
1138                     }
1139                     gatewayIp = Optional.of(
1140                             neutronVpnService.getNeutronSubnet(portIp.getSubnetId()).getGatewayIp());
1141                 }
1142             }
1143         } else {
1144             LOG.error("getGatewayIpAddressFromInterface: neutron vpn service is not configured."
1145                     + " Failed for interface {}.", srcInterface);
1146         }
1147         return gatewayIp;
1148     }
1149
1150     Optional<String> getGWMacAddressFromInterface(MacEntry macEntry, IpAddress gatewayIp) {
1151         Optional<String> gatewayMac = Optional.absent();
1152         long vpnId = getVpnId(macEntry.getVpnName());
1153         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn
1154             .instance.VpnIds>
1155             vpnIdsInstanceIdentifier = VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId);
1156         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds>
1157             vpnIdsOptional = read(LogicalDatastoreType.CONFIGURATION, vpnIdsInstanceIdentifier);
1158         if (!vpnIdsOptional.isPresent()) {
1159             LOG.error("getGWMacAddressFromInterface: VPN {} not configured", vpnId);
1160             return gatewayMac;
1161         }
1162         VpnPortipToPort vpnTargetIpToPort = getNeutronPortFromVpnPortFixedIp(macEntry.getVpnName(),
1163                 gatewayIp.getIpv4Address().getValue());
1164         if (vpnTargetIpToPort != null && vpnTargetIpToPort.isSubnetIp()) {
1165             gatewayMac = Optional.of(vpnTargetIpToPort.getMacAddress());
1166         } else {
1167             org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911
1168                     .vpn.id.to.vpn.instance.VpnIds vpnIds = vpnIdsOptional.get();
1169             if (vpnIds.isExternalVpn()) {
1170                 gatewayMac = InterfaceUtils.getMacAddressForInterface(dataBroker, macEntry.getInterfaceName());
1171             }
1172         }
1173         return gatewayMac;
1174     }
1175
1176     void setupGwMacIfExternalVpn(BigInteger dpnId, String interfaceName, long vpnId, WriteTransaction writeInvTxn,
1177                                  int addOrRemove, String gwMac) {
1178         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance
1179             .VpnIds> vpnIdsInstanceIdentifier = getVpnIdToVpnInstanceIdentifier(vpnId);
1180         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance
1181             .VpnIds> vpnIdsOptional = read(LogicalDatastoreType.CONFIGURATION, vpnIdsInstanceIdentifier);
1182         if (vpnIdsOptional.isPresent() && vpnIdsOptional.get().isExternalVpn()) {
1183             if (gwMac == null) {
1184                 LOG.error("setupGwMacIfExternalVpn: Failed to get gwMacAddress for interface {} on dpn {} vpn {}",
1185                         interfaceName, dpnId.toString(), vpnIdsOptional.get().getVpnInstanceName());
1186                 return;
1187             }
1188             FlowEntity flowEntity = buildL3vpnGatewayFlow(dpnId, gwMac, vpnId, VpnConstants.INVALID_ID);
1189             if (addOrRemove == NwConstants.ADD_FLOW) {
1190                 mdsalManager.addFlowToTx(flowEntity, writeInvTxn);
1191             } else if (addOrRemove == NwConstants.DEL_FLOW) {
1192                 mdsalManager.removeFlowToTx(flowEntity, writeInvTxn);
1193             }
1194         }
1195     }
1196
1197     public Optional<String> getVpnSubnetGatewayIp(final Uuid subnetUuid) {
1198         Optional<String> gwIpAddress = Optional.absent();
1199         final SubnetKey subnetkey = new SubnetKey(subnetUuid);
1200         final InstanceIdentifier<Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class)
1201                 .child(Subnets.class)
1202                 .child(Subnet.class, subnetkey);
1203         final Optional<Subnet> subnet = read(LogicalDatastoreType.CONFIGURATION, subnetidentifier);
1204         if (subnet.isPresent()) {
1205             Class<? extends IpVersionBase> ipVersionBase = subnet.get().getIpVersion();
1206             if (ipVersionBase.equals(IpVersionV4.class)) {
1207                 Subnetmap subnetmap = getSubnetmapFromItsUuid(subnetUuid);
1208                 if (subnetmap != null && subnetmap.getRouterInterfaceFixedIp() != null) {
1209                     LOG.trace("getVpnSubnetGatewayIp: Obtained subnetMap {} for vpn interface",
1210                             subnetmap.getId().getValue());
1211                     gwIpAddress = Optional.of(subnetmap.getRouterInterfaceFixedIp());
1212                 } else {
1213                     //For direct L3VPN to network association (no router) continue to use subnet-gateway IP
1214                     IpAddress gwIp = subnet.get().getGatewayIp();
1215                     if (gwIp != null && gwIp.getIpv4Address() != null) {
1216                         gwIpAddress = Optional.of(gwIp.getIpv4Address().getValue());
1217                     }
1218                 }
1219                 LOG.trace("getVpnSubnetGatewayIp: Obtained subnet-gw ip {} for vpn interface",
1220                         gwIpAddress.get());
1221             }
1222         }
1223         return gwIpAddress;
1224     }
1225
1226     RouterToNaptSwitch getRouterToNaptSwitch(String routerName) {
1227         InstanceIdentifier<RouterToNaptSwitch> id = InstanceIdentifier.builder(NaptSwitches.class)
1228                 .child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
1229         Optional<RouterToNaptSwitch> routerToNaptSwitchData = read(LogicalDatastoreType.CONFIGURATION, id);
1230         return routerToNaptSwitchData.isPresent() ? routerToNaptSwitchData.get() : null;
1231     }
1232
1233     static InstanceIdentifier<Subnetmap> buildSubnetmapIdentifier(Uuid subnetId) {
1234         return InstanceIdentifier.builder(Subnetmaps.class)
1235         .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
1236
1237     }
1238
1239     BigInteger getPrimarySwitchForRouter(String routerName) {
1240         RouterToNaptSwitch routerToNaptSwitch = getRouterToNaptSwitch(routerName);
1241         return routerToNaptSwitch != null ? routerToNaptSwitch.getPrimarySwitchId() : null;
1242     }
1243
1244     static boolean isL3VpnOverVxLan(Long l3Vni) {
1245         return l3Vni != null && l3Vni != 0;
1246     }
1247
1248     /**
1249      * Retrieves the primary rd of a vpn instance
1250      * Primary rd will be the first rd in the list of rds configured for a vpn instance
1251      * If rd list is empty, primary rd will be vpn instance name
1252      * Use this function only during create operation cycles. For other operations, use getVpnRd() method.
1253      *
1254      * @param vpnName Name of the VPN
1255      * @return the primary rd of the VPN
1256      */
1257     public String getPrimaryRd(String vpnName) {
1258         // Retrieves the VPN Route Distinguisher by its Vpn instance name
1259         String rd = getVpnRd(vpnName);
1260         if (rd != null) {
1261             return rd;
1262         }
1263         InstanceIdentifier<VpnInstance> id  = getVpnInstanceIdentifier(vpnName);
1264         Optional<VpnInstance> vpnInstance = read(LogicalDatastoreType.CONFIGURATION, id);
1265         if (vpnInstance.isPresent()) {
1266             return getPrimaryRd(vpnInstance.get());
1267         }
1268         return vpnName;
1269     }
1270
1271     /**
1272      * Retrieves the primary rd of a vpn instance
1273      * Primary rd will be the first rd in the list of rds configured for a vpn instance
1274      * If rd list is empty, primary rd will be vpn instance name
1275      * Use this function only during create operation cycles. For other operations, use getVpnRd() method.
1276      *
1277      * @param vpnInstance Config Vpn Instance Object
1278      * @return the primary rd of the VPN
1279      */
1280     static String getPrimaryRd(VpnInstance vpnInstance) {
1281         List<String> rds = null;
1282         if (vpnInstance != null) {
1283             rds = getListOfRdsFromVpnInstance(vpnInstance);
1284         }
1285         return rds == null || rds.isEmpty() ? vpnInstance.getVpnInstanceName() : rds.get(0);
1286     }
1287
1288     static boolean isBgpVpn(String vpnName, String primaryRd) {
1289         return !vpnName.equals(primaryRd);
1290     }
1291
1292     java.util.Optional<String> allocateRdForExtraRouteAndUpdateUsedRdsMap(long vpnId, @Nullable Long parentVpnId,
1293                                                                           String prefix, String vpnName,
1294                                                                           String nextHop, BigInteger dpnId) {
1295         //Check if rd is already allocated for this extraroute behind the same VM. If yes, reuse it.
1296         //This is particularly useful during reboot scenarios.
1297         java.util.Optional<String> allocatedRd = VpnExtraRouteHelper
1298                 .getRdAllocatedForExtraRoute(dataBroker, vpnId, prefix, nextHop);
1299         if (allocatedRd.isPresent()) {
1300             return allocatedRd;
1301         }
1302
1303         //Check if rd is already allocated for this extraroute behind the same CSS. If yes, reuse it
1304         List<String> usedRds = VpnExtraRouteHelper.getUsedRds(dataBroker, vpnId, prefix);
1305         for (String usedRd : usedRds) {
1306             Optional<Routes> vpnExtraRoutes = VpnExtraRouteHelper.getVpnExtraroutes(dataBroker,
1307                     vpnName, usedRd, prefix);
1308             if (vpnExtraRoutes.isPresent()) {
1309                 String nextHopIp = vpnExtraRoutes.get().getNexthopIpList().get(0);
1310                 // In case of VPN importing the routes, the interface is not present in the VPN
1311                 // and has to be fetched from the VPN from which it imports
1312                 Optional<Prefixes> prefixToInterface =
1313                         getPrefixToInterface(parentVpnId != null ? parentVpnId : vpnId, nextHopIp);
1314                 if (prefixToInterface.isPresent() && dpnId.equals(prefixToInterface.get().getDpnId())) {
1315                     syncUpdate(LogicalDatastoreType.CONFIGURATION,
1316                             VpnExtraRouteHelper.getUsedRdsIdentifier(vpnId, prefix, nextHop),
1317                             getRdsBuilder(nextHop, usedRd).build());
1318                     return java.util.Optional.of(usedRd);
1319                 }
1320             }
1321         }
1322         List<String> availableRds = getVpnRdsFromVpnInstanceConfig(vpnName);
1323         String rd;
1324         if (availableRds.isEmpty()) {
1325             rd = dpnId.toString();
1326             LOG.debug("Internal vpn {} Returning DpnId {} as rd", vpnName, rd);
1327         } else {
1328             LOG.trace("Removing used rds {} from available rds {} vpnid {} . prefix is {} , vpname- {}, dpnId- {}",
1329                     usedRds, availableRds, vpnId, prefix, vpnName, dpnId);
1330             availableRds.removeAll(usedRds);
1331             if (availableRds.isEmpty()) {
1332                 LOG.error("No rd available from VpnInstance to allocate for prefix {}", prefix);
1333                 return java.util.Optional.empty();
1334             }
1335             // If rd is not allocated for this prefix or if extra route is behind different OVS, select a new rd.
1336             rd = availableRds.get(0);
1337         }
1338         syncUpdate(LogicalDatastoreType.CONFIGURATION,
1339                 VpnExtraRouteHelper.getUsedRdsIdentifier(vpnId, prefix, nextHop), getRdsBuilder(nextHop, rd).build());
1340         return java.util.Optional.ofNullable(rd);
1341     }
1342
1343     static String getVpnNamePrefixKey(String vpnName, String prefix) {
1344         return vpnName + VpnConstants.SEPARATOR + prefix;
1345     }
1346
1347     static InstanceIdentifier<Adjacency> getAdjacencyIdentifier(String vpnInterfaceName, String ipAddress) {
1348         return InstanceIdentifier.builder(VpnInterfaces.class)
1349                 .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName))
1350                 .augmentation(Adjacencies.class).child(Adjacency.class, new AdjacencyKey(ipAddress)).build();
1351     }
1352
1353     public static List<String> getIpsListFromExternalIps(List<ExternalIps> externalIps) {
1354         if (externalIps == null) {
1355             return Collections.emptyList();
1356         }
1357
1358         return externalIps.stream().map(ExternalIps::getIpAddress).collect(Collectors.toList());
1359     }
1360
1361     void bindService(final String vpnInstanceName, final String interfaceName, boolean isTunnelInterface) {
1362         jobCoordinator.enqueueJob(interfaceName,
1363             () -> Collections.singletonList(
1364                     txRunner.callWithNewReadWriteTransactionAndSubmit(tx -> {
1365                         BoundServices serviceInfo = isTunnelInterface
1366                                 ? VpnUtil.getBoundServicesForTunnelInterface(vpnInstanceName, interfaceName)
1367                                 : getBoundServicesForVpnInterface(vpnInstanceName, interfaceName);
1368                         tx.put(LogicalDatastoreType.CONFIGURATION, InterfaceUtils.buildServiceId(interfaceName,
1369                                 ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME,
1370                                         NwConstants.L3VPN_SERVICE_INDEX)),
1371                                 serviceInfo, WriteTransaction.CREATE_MISSING_PARENTS);
1372                     })), SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
1373     }
1374
1375     BoundServices getBoundServicesForVpnInterface(String vpnName, String interfaceName) {
1376         List<Instruction> instructions = new ArrayList<>();
1377         int instructionKey = 0;
1378         final long vpnId = getVpnId(vpnName);
1379         List<Action> actions = Collections.singletonList(
1380                 new ActionRegLoad(0, VpnConstants.VPN_REG_ID, 0, VpnConstants.VPN_ID_LENGTH, vpnId).buildAction());
1381         instructions.add(MDSALUtil.buildApplyActionsInstruction(actions, ++instructionKey));
1382         instructions.add(
1383                 MDSALUtil.buildAndGetWriteMetadaInstruction(MetaDataUtil.getVpnIdMetadata(vpnId),
1384                         MetaDataUtil.METADATA_MASK_VRFID, ++instructionKey));
1385         instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_GW_MAC_TABLE,
1386                 ++instructionKey));
1387         BoundServices serviceInfo = InterfaceUtils.getBoundServices(
1388                 String.format("%s.%s.%s", "vpn", vpnName, interfaceName),
1389                 ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX),
1390                 VpnConstants.DEFAULT_FLOW_PRIORITY, NwConstants.COOKIE_VM_INGRESS_TABLE, instructions);
1391         return serviceInfo;
1392     }
1393
1394     static BoundServices getBoundServicesForTunnelInterface(String vpnName, String interfaceName) {
1395         int instructionKey = 0;
1396         List<Instruction> instructions = new ArrayList<>();
1397         instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(
1398                 NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE, ++instructionKey));
1399         BoundServices serviceInfo = InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",
1400                 vpnName, interfaceName),
1401                 ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME,
1402                         NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE), VpnConstants.DEFAULT_FLOW_PRIORITY,
1403                 NwConstants.COOKIE_VM_INGRESS_TABLE, instructions);
1404         return serviceInfo;
1405     }
1406
1407     void unbindService(final String vpnInterfaceName, boolean isInterfaceStateDown) {
1408         if (!isInterfaceStateDown) {
1409             jobCoordinator.enqueueJob(vpnInterfaceName,
1410                 () -> Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx ->
1411                         tx.delete(LogicalDatastoreType.CONFIGURATION,
1412                                 InterfaceUtils.buildServiceId(vpnInterfaceName,
1413                                         ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME,
1414                                                 NwConstants.L3VPN_SERVICE_INDEX))))),
1415                 SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
1416         }
1417     }
1418
1419     static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId) {
1420         return new FlowEntityBuilder().setDpnId(dpnId).setTableId(tableId).setFlowId(flowId).build();
1421     }
1422
1423     static VrfEntryBase.EncapType getEncapType(boolean isVxLan) {
1424         return isVxLan ? VrfEntryBase.EncapType.Vxlan : VrfEntryBase.EncapType.Mplsgre;
1425     }
1426
1427     org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets
1428         getExternalSubnet(Uuid subnetId) {
1429         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets
1430             .Subnets> subnetsIdentifier = InstanceIdentifier.builder(ExternalSubnets.class)
1431                 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets
1432                         .Subnets.class, new SubnetsKey(subnetId)).build();
1433         Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets.Subnets>
1434             optionalSubnets = read(LogicalDatastoreType.CONFIGURATION, subnetsIdentifier);
1435         return optionalSubnets.isPresent() ? optionalSubnets.get() : null;
1436     }
1437
1438     Uuid getSubnetFromExternalRouterByIp(Uuid routerId, String ip) {
1439         Routers externalRouter = getExternalRouter(routerId.getValue());
1440         if (externalRouter != null && externalRouter.getExternalIps() != null) {
1441             for (ExternalIps externalIp : externalRouter.getExternalIps()) {
1442                 if (externalIp.getIpAddress().equals(ip)) {
1443                     return externalIp.getSubnetId();
1444                 }
1445             }
1446         }
1447         return null;
1448     }
1449
1450     static boolean isExternalSubnetVpn(String vpnName, String subnetId) {
1451         return vpnName.equals(subnetId);
1452     }
1453
1454     static Boolean getIsExternal(Network network) {
1455         return network.augmentation(NetworkL3Extension.class) != null
1456                 && network.augmentation(NetworkL3Extension.class).isExternal();
1457     }
1458
1459     @SuppressWarnings("checkstyle:linelength")
1460     Network getNeutronNetwork(Uuid networkId) {
1461         Network network = null;
1462         LOG.debug("getNeutronNetwork for {}", networkId.getValue());
1463         InstanceIdentifier<Network> inst = InstanceIdentifier.create(Neutron.class).child(
1464                 org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks.class).child(
1465                 Network.class, new NetworkKey(networkId));
1466         Optional<Network> net = read(LogicalDatastoreType.CONFIGURATION, inst);
1467         if (net.isPresent()) {
1468             network = net.get();
1469         }
1470         return network;
1471     }
1472
1473     public static boolean isEligibleForBgp(String rd, String vpnName, BigInteger dpnId, String networkName) {
1474         if (rd != null) {
1475             if (vpnName != null && rd.equals(vpnName)) {
1476                 return false;
1477             }
1478             if (dpnId != null && rd.equals(dpnId.toString())) {
1479                 return false;
1480             }
1481             if (networkName != null && rd.equals(networkName)) {
1482                 return false;
1483             }
1484             return true;
1485         }
1486         return false;
1487     }
1488
1489     static String getFibFlowRef(BigInteger dpnId, short tableId, String vpnName, int priority) {
1490         return VpnConstants.FLOWID_PREFIX + dpnId + NwConstants.FLOWID_SEPARATOR + tableId
1491                 + NwConstants.FLOWID_SEPARATOR + vpnName + NwConstants.FLOWID_SEPARATOR + priority;
1492     }
1493
1494     void removeExternalTunnelDemuxFlows(String vpnName) {
1495         LOG.info("Removing external tunnel flows for vpn {}", vpnName);
1496         for (BigInteger dpnId: NWUtil.getOperativeDPNs(dataBroker)) {
1497             LOG.debug("Removing external tunnel flows for vpn {} from dpn {}", vpnName, dpnId);
1498             String flowRef = getFibFlowRef(dpnId, NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE,
1499                     vpnName, VpnConstants.DEFAULT_FLOW_PRIORITY);
1500             FlowEntity flowEntity = VpnUtil.buildFlowEntity(dpnId,
1501                     NwConstants.L3VNI_EXTERNAL_TUNNEL_DEMUX_TABLE, flowRef);
1502             mdsalManager.removeFlow(flowEntity);
1503         }
1504     }
1505
1506     public boolean isVpnPendingDelete(String rd) {
1507         VpnInstanceOpDataEntry vpnInstanceOpData = getVpnInstanceOpData(rd);
1508         boolean isVpnPendingDelete = false;
1509         if (vpnInstanceOpData == null
1510                 || vpnInstanceOpData.getVpnState() == VpnInstanceOpDataEntry.VpnState.PendingDelete) {
1511             isVpnPendingDelete = true;
1512         }
1513         return isVpnPendingDelete;
1514     }
1515
1516     public List<VpnInstanceOpDataEntry> getVpnsImportingMyRoute(final String vpnName) {
1517         List<VpnInstanceOpDataEntry> vpnsToImportRoute = new ArrayList<>();
1518         final String vpnRd = getVpnRd(vpnName);
1519         if (vpnRd == null) {
1520             LOG.error("getVpnsImportingMyRoute: vpn {} not present in config DS.", vpnName);
1521             return vpnsToImportRoute;
1522         }
1523         final VpnInstanceOpDataEntry vpnInstanceOpDataEntry = getVpnInstanceOpData(vpnRd);
1524         if (vpnInstanceOpDataEntry == null) {
1525             LOG.error("getVpnsImportingMyRoute: Could not retrieve vpn instance op data for {}"
1526                     + " to check for vpns importing the routes", vpnName);
1527             return vpnsToImportRoute;
1528         }
1529         Predicate<VpnInstanceOpDataEntry> excludeVpn = input -> {
1530             if (input.getVpnInstanceName() == null) {
1531                 LOG.error("getVpnsImportingMyRoute.excludeVpn: Received vpn instance with rd {} without a name.",
1532                         input.getVrfId());
1533                 return false;
1534             }
1535             return !input.getVpnInstanceName().equals(vpnName);
1536         };
1537         Predicate<VpnInstanceOpDataEntry> matchRTs = input -> {
1538             Iterable<String> commonRTs =
1539                 intersection(getRts(vpnInstanceOpDataEntry, VpnTarget.VrfRTType.ExportExtcommunity),
1540                     getRts(input, VpnTarget.VrfRTType.ImportExtcommunity));
1541             return Iterators.size(commonRTs.iterator()) > 0;
1542         };
1543         vpnsToImportRoute = getAllVpnInstanceOpData().stream().filter(excludeVpn).filter(matchRTs)
1544                 .collect(Collectors.toList());
1545         return vpnsToImportRoute;
1546     }
1547
1548     static List<String> getRts(VpnInstanceOpDataEntry vpnInstance, VpnTarget.VrfRTType rtType) {
1549         String name = vpnInstance.getVpnInstanceName();
1550         List<String> rts = new ArrayList<>();
1551         VpnTargets targets = vpnInstance.getVpnTargets();
1552         if (targets == null) {
1553             LOG.info("getRts: vpn targets not available for {}", name);
1554             return rts;
1555         }
1556         List<VpnTarget> vpnTargets = targets.getVpnTarget();
1557         if (vpnTargets == null) {
1558             LOG.info("getRts: vpnTarget values not available for {}", name);
1559             return rts;
1560         }
1561         for (VpnTarget target : vpnTargets) {
1562             //TODO: Check for RT type is Both
1563             if (target.getVrfRTType().equals(rtType) || target.getVrfRTType().equals(VpnTarget.VrfRTType.Both)) {
1564                 String rtValue = target.getVrfRTValue();
1565                 rts.add(rtValue);
1566             }
1567         }
1568         return rts;
1569     }
1570
1571     static <T> Iterable<T> intersection(final Collection<T> collection1, final Collection<T> collection2) {
1572         Set<T> intersection = new HashSet<>(collection1);
1573         intersection.retainAll(collection2);
1574         return intersection;
1575     }
1576
1577     /** Get Subnetmap from its Uuid.
1578      * @param subnetUuid the subnet's Uuid
1579      * @return the Subnetmap of Uuid or null if it is not found
1580      */
1581     Subnetmap getSubnetmapFromItsUuid(Uuid subnetUuid) {
1582         Subnetmap sn = null;
1583         InstanceIdentifier<Subnetmap> id = buildSubnetmapIdentifier(subnetUuid);
1584         Optional<Subnetmap> optionalSn = read(LogicalDatastoreType.CONFIGURATION, id);
1585         if (optionalSn.isPresent()) {
1586             sn = optionalSn.get();
1587         }
1588         return sn;
1589     }
1590
1591     boolean isAdjacencyEligibleToVpnInternet(Adjacency adjacency) {
1592         // returns true if BGPVPN Internet and adjacency is IPv6, false otherwise
1593         boolean adjacencyEligible = true;
1594         if (adjacency.getAdjacencyType() == AdjacencyType.ExtraRoute) {
1595             if (FibHelper.isIpv6Prefix(adjacency.getIpAddress())) {
1596                 return adjacencyEligible;
1597             }
1598             return false;
1599         } else if (adjacency.getSubnetId() == null) {
1600             return adjacencyEligible;
1601         }
1602         Subnetmap sn = getSubnetmapFromItsUuid(adjacency.getSubnetId());
1603         if (sn != null && sn.getInternetVpnId() != null) {
1604             adjacencyEligible = false;
1605         }
1606         return adjacencyEligible;
1607     }
1608
1609     boolean isAdjacencyEligibleToVpn(Adjacency adjacency, String vpnName) {
1610         // returns true if BGPVPN Internet and adjacency is IPv6, false otherwise
1611         boolean adjacencyEligible = true;
1612         // if BGPVPN internet, return false if subnetmap has not internetVpnId() filled in
1613         if (isBgpVpnInternet(vpnName)) {
1614             return isAdjacencyEligibleToVpnInternet(adjacency);
1615         }
1616         return adjacencyEligible;
1617     }
1618
1619     String getInternetVpnFromVpnInstanceList(List<VpnInstanceNames> vpnInstanceList) {
1620         for (VpnInstanceNames vpnInstance : vpnInstanceList) {
1621             String vpnName = vpnInstance.getVpnName();
1622             if (isBgpVpnInternet(vpnName)) {
1623                 return vpnName;
1624             }
1625         }
1626         return null;
1627     }
1628
1629     /** Get boolean true if vpn is bgpvpn internet, false otherwise.
1630      * @param vpnName name of the input VPN
1631      * @return true or false
1632      */
1633     boolean isBgpVpnInternet(String vpnName) {
1634         String primaryRd = getVpnRd(vpnName);
1635         if (primaryRd == null) {
1636             LOG.error("isBgpVpnInternet VPN {}."
1637                       + "Primary RD not found", vpnName);
1638             return false;
1639         }
1640         InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
1641               .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(primaryRd)).build();
1642
1643         Optional<VpnInstanceOpDataEntry> vpnInstanceOpDataEntryOptional = read(LogicalDatastoreType.OPERATIONAL, id);
1644         if (!vpnInstanceOpDataEntryOptional.isPresent()) {
1645             LOG.error("isBgpVpnInternet VPN {}."
1646                      + "VpnInstanceOpDataEntry not found", vpnName);
1647             return false;
1648         }
1649         LOG.debug("isBgpVpnInternet VPN {}."
1650              + "Successfully VpnInstanceOpDataEntry.getBgpvpnType {}",
1651              vpnName, vpnInstanceOpDataEntryOptional.get().getBgpvpnType());
1652         if (vpnInstanceOpDataEntryOptional.get().getBgpvpnType() == VpnInstanceOpDataEntry
1653                .BgpvpnType.BGPVPNInternet) {
1654             return true;
1655         }
1656         return false;
1657     }
1658
1659     /**Get IpVersionChoice from String IP like x.x.x.x or an representation IPv6.
1660      * @param ipAddress String of an representation IP address V4 or V6
1661      * @return the IpVersionChoice of the version or IpVersionChoice.UNDEFINED otherwise
1662      */
1663     public static IpVersionChoice getIpVersionFromString(String ipAddress) {
1664         IpVersionChoice ipchoice = IpVersionChoice.UNDEFINED;
1665         int indexIpAddress = ipAddress.indexOf('/');
1666         if (indexIpAddress >= 0) {
1667             ipAddress = ipAddress.substring(0, indexIpAddress);
1668         }
1669         try {
1670             InetAddress address = InetAddress.getByName(ipAddress);
1671             if (address instanceof Inet4Address) {
1672                 return IpVersionChoice.IPV4;
1673             } else if (address instanceof Inet6Address) {
1674                 return IpVersionChoice.IPV6;
1675             }
1676         } catch (UnknownHostException | SecurityException e) {
1677             ipchoice = IpVersionChoice.UNDEFINED;
1678         }
1679         return ipchoice;
1680     }
1681
1682     ListenableFuture<Void> unsetScheduledToRemoveForVpnInterface(String interfaceName) {
1683         VpnInterfaceBuilder builder = new VpnInterfaceBuilder().withKey(new VpnInterfaceKey(interfaceName))
1684                 .setScheduledForRemove(false);
1685         return txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> tx.merge(LogicalDatastoreType.OPERATIONAL,
1686                 VpnUtil.getVpnInterfaceIdentifier(interfaceName), builder.build(),
1687                 WriteTransaction.CREATE_MISSING_PARENTS));
1688     }
1689
1690     /**
1691      * Adds router port for all elan network of type VLAN which is a part of vpnName in the DPN with dpnId.
1692      * This will create the vlan footprint in the DPN's which are member of the VPN.
1693      *
1694      * @param vpnName the vpnName
1695      * @param dpnId  the DPN id
1696      */
1697     void addRouterPortToElanForVlanInDpn(String vpnName, BigInteger dpnId) {
1698         Map<String,String> elanInstanceRouterPortMap = getElanInstanceRouterPortMap(vpnName);
1699         for (Entry<String, String> elanInstanceRouterEntry : elanInstanceRouterPortMap.entrySet()) {
1700             addRouterPortToElanDpn(elanInstanceRouterEntry.getKey(), elanInstanceRouterEntry.getValue(), dpnId);
1701         }
1702     }
1703
1704     /**
1705      * Removes router port for all elan network of type VLAN which is a part of vpnName in the DPN with dpnId.
1706      * This will remove the  vlan footprint in all the DPN's which are member of the VPN.
1707      *
1708      * @param vpnName the vpn name
1709      * @param dpnId  the DPN id
1710      */
1711     void removeRouterPortFromElanForVlanInDpn(String vpnName, BigInteger dpnId) {
1712         Map<String,String> elanInstanceRouterPortMap = getElanInstanceRouterPortMap(vpnName);
1713         for (Entry<String, String> elanInstanceRouterEntry : elanInstanceRouterPortMap.entrySet()) {
1714             removeRouterPortFromElanDpn(elanInstanceRouterEntry.getKey(), elanInstanceRouterEntry.getValue(),
1715                     vpnName, dpnId);
1716         }
1717     }
1718
1719     /**
1720      * Adds router port for all elan network of type VLAN which is a part of vpnName in all the DPN which has a port
1721      * This will create the vlan footprint in all the DPN's which are member of the VPN.
1722      *
1723      * @param vpnName the vpn name
1724      */
1725     void addRouterPortToElanDpnListForVlaninAllDpn(String vpnName) {
1726         Map<String,String> elanInstanceRouterPortMap = getElanInstanceRouterPortMap(vpnName);
1727         Set<BigInteger> dpnList = getDpnInElan(elanInstanceRouterPortMap);
1728         for (BigInteger dpnId : dpnList) {
1729             for (Entry<String, String> elanInstanceRouterEntry : elanInstanceRouterPortMap.entrySet()) {
1730                 addRouterPortToElanDpn(elanInstanceRouterEntry.getKey(), elanInstanceRouterEntry.getValue(), dpnId);
1731             }
1732         }
1733     }
1734
1735     /**Removes router port for all elan network of type VLAN which is a part of vpnName in all the DPN which has a port
1736      * This will remove the vlan footprint in all the DPN's which are member of the VPN.
1737      *
1738      * @param routerInterfacePortId this will add the current subnet router port id to the map for removal
1739      * @param elanInstanceName the current elanstance being removed this will be added to map for removal
1740      * @param vpnName the vpn name
1741      */
1742     void removeRouterPortFromElanDpnListForVlanInAllDpn(String elanInstanceName,
1743             String routerInterfacePortId, String vpnName) {
1744         Map<String,String> elanInstanceRouterPortMap = getElanInstanceRouterPortMap(vpnName);
1745         elanInstanceRouterPortMap.put(elanInstanceName, routerInterfacePortId);
1746         Set<BigInteger> dpnList = getDpnInElan(elanInstanceRouterPortMap);
1747         for (BigInteger dpnId : dpnList) {
1748             for (Entry<String, String> elanInstanceRouterEntry : elanInstanceRouterPortMap.entrySet()) {
1749                 removeRouterPortFromElanDpn(elanInstanceRouterEntry.getKey(), elanInstanceRouterEntry.getValue(),
1750                         vpnName, dpnId);
1751             }
1752         }
1753
1754     }
1755
1756     Set<BigInteger> getDpnInElan(Map<String,String> elanInstanceRouterPortMap) {
1757         Set<BigInteger> dpnIdSet = new HashSet<>();
1758         for (String elanInstanceName : elanInstanceRouterPortMap.keySet()) {
1759             InstanceIdentifier<ElanDpnInterfacesList> elanDpnInterfaceId = getElanDpnOperationalDataPath(
1760                     elanInstanceName);
1761             Optional<ElanDpnInterfacesList> dpnInElanInterfaces = read(LogicalDatastoreType.OPERATIONAL,
1762                     elanDpnInterfaceId);
1763             if (dpnInElanInterfaces.isPresent()) {
1764                 List<DpnInterfaces> dpnInterfaces = dpnInElanInterfaces.get().getDpnInterfaces();
1765                 for (DpnInterfaces dpnInterface : dpnInterfaces) {
1766                     dpnIdSet.add(dpnInterface.getDpId());
1767                 }
1768             }
1769         }
1770         return dpnIdSet;
1771     }
1772
1773     void addRouterPortToElanDpn(String elanInstanceName, String routerInterfacePortId, BigInteger dpnId) {
1774         InstanceIdentifier<DpnInterfaces> elanDpnInterfaceId = getElanDpnInterfaceOperationalDataPath(
1775                 elanInstanceName,dpnId);
1776         synchronized (elanInstanceName.intern()) {
1777             Optional<DpnInterfaces> dpnInElanInterfaces = read(LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
1778             List<String> elanInterfaceList;
1779             DpnInterfaces dpnInterface;
1780             if (!dpnInElanInterfaces.isPresent()) {
1781                 elanInterfaceList = new ArrayList<>();
1782             } else {
1783                 dpnInterface = dpnInElanInterfaces.get();
1784                 elanInterfaceList = dpnInterface.getInterfaces();
1785             }
1786             if (!elanInterfaceList.contains(routerInterfacePortId)) {
1787                 elanInterfaceList.add(routerInterfacePortId);
1788                 dpnInterface = new DpnInterfacesBuilder().setDpId(dpnId).setInterfaces(elanInterfaceList)
1789                         .withKey(new DpnInterfacesKey(dpnId)).build();
1790                 syncWrite(LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId, dpnInterface);
1791             }
1792         }
1793
1794     }
1795
1796     void removeRouterPortFromElanDpn(String elanInstanceName, String routerInterfacePortId,
1797             String vpnName, BigInteger dpnId) {
1798         InstanceIdentifier<DpnInterfaces> elanDpnInterfaceId = getElanDpnInterfaceOperationalDataPath(
1799                 elanInstanceName,dpnId);
1800         synchronized (elanInstanceName.intern()) {
1801             Optional<DpnInterfaces> dpnInElanInterfaces = read(LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
1802             List<String> elanInterfaceList;
1803             DpnInterfaces dpnInterface;
1804             if (!dpnInElanInterfaces.isPresent()) {
1805                 LOG.info("No interface in any dpn for {}", vpnName);
1806                 return;
1807             } else {
1808                 dpnInterface = dpnInElanInterfaces.get();
1809                 elanInterfaceList = dpnInterface.getInterfaces();
1810             }
1811             if (!elanInterfaceList.contains(routerInterfacePortId)) {
1812                 LOG.info("Router port not present in DPN {} for VPN {}", dpnId, vpnName);
1813                 return;
1814             }
1815             elanInterfaceList.remove(routerInterfacePortId);
1816             dpnInterface = new DpnInterfacesBuilder().setDpId(dpnId).setInterfaces(elanInterfaceList)
1817                     .withKey(new DpnInterfacesKey(dpnId)).build();
1818             syncWrite(LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId, dpnInterface);
1819         }
1820
1821     }
1822
1823     ElanInterface getElanInterfaceByElanInterfaceName(String elanInterfaceName) {
1824         InstanceIdentifier<ElanInterface> elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName);
1825         return read(LogicalDatastoreType.CONFIGURATION, elanInterfaceId).orNull();
1826     }
1827
1828     static InstanceIdentifier<ElanInterface> getElanInterfaceConfigurationDataPathId(String interfaceName) {
1829         return InstanceIdentifier.builder(ElanInterfaces.class)
1830                 .child(ElanInterface.class, new ElanInterfaceKey(interfaceName)).build();
1831     }
1832
1833     DpnInterfaces getElanInterfaceInfoByElanDpn(String elanInstanceName, BigInteger dpId) {
1834         InstanceIdentifier<DpnInterfaces> elanDpnInterfacesId = getElanDpnInterfaceOperationalDataPath(elanInstanceName,
1835                 dpId);
1836         return read(LogicalDatastoreType.OPERATIONAL, elanDpnInterfacesId).orNull();
1837     }
1838
1839     String getExternalElanInterface(String elanInstanceName, BigInteger dpnId) {
1840         DpnInterfaces dpnInterfaces = getElanInterfaceInfoByElanDpn(elanInstanceName, dpnId);
1841         if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null) {
1842             LOG.info("Elan {} does not have interfaces in DPN {}", elanInstanceName, dpnId);
1843             return null;
1844         }
1845
1846         for (String dpnInterface : dpnInterfaces.getInterfaces()) {
1847             if (interfaceManager.isExternalInterface(dpnInterface)) {
1848                 return dpnInterface;
1849             }
1850         }
1851         return null;
1852     }
1853
1854     static boolean isVlan(ElanInstance elanInstance) {
1855         return elanInstance != null && elanInstance.getSegmentType() != null
1856                 && elanInstance.getSegmentType().isAssignableFrom(SegmentTypeVlan.class)
1857                 && elanInstance.getSegmentationId() != null && elanInstance.getSegmentationId() != 0;
1858     }
1859
1860     boolean isVlan(String interfaceName) {
1861         ElanInterface elanInterface = getElanInterfaceByElanInterfaceName(interfaceName);
1862         if (elanInterface == null) {
1863             return false;
1864         }
1865         ElanInstance  elanInstance = getElanInstanceByName(elanInterface.getElanInstanceName());
1866         return isVlan(elanInstance);
1867     }
1868
1869     ElanInstance getElanInstanceByName(String elanInstanceName) {
1870         InstanceIdentifier<ElanInstance> elanIdentifierId =
1871                 ElanHelper.getElanInstanceConfigurationDataPath(elanInstanceName);
1872         return read(LogicalDatastoreType.CONFIGURATION, elanIdentifierId).orNull();
1873     }
1874
1875     String getVpnNameFromElanIntanceName(String elanInstanceName) {
1876         Optional<Subnetmaps> subnetMapsData = read(LogicalDatastoreType.CONFIGURATION, buildSubnetMapsWildCardPath());
1877         if (subnetMapsData.isPresent()) {
1878             List<Subnetmap> subnetMapList = subnetMapsData.get().getSubnetmap();
1879             if (subnetMapList != null && !subnetMapList.isEmpty()) {
1880                 for (Subnetmap subnet : subnetMapList) {
1881                     if (subnet.getNetworkId().getValue().equals(elanInstanceName)) {
1882                         if (subnet.getVpnId() != null) {
1883                             return subnet.getVpnId().getValue();
1884                         }
1885                     }
1886                 }
1887             }
1888         }
1889         return null;
1890     }
1891
1892     Map<String, String> getElanInstanceRouterPortMap(String vpnName) {
1893         Map<String, String> elanInstanceRouterPortMap = new HashMap<>();
1894         Optional<Subnetmaps> subnetMapsData = read(LogicalDatastoreType.CONFIGURATION, buildSubnetMapsWildCardPath());
1895         if (subnetMapsData.isPresent()) {
1896             List<Subnetmap> subnetMapList = subnetMapsData.get().getSubnetmap();
1897             if (subnetMapList != null && !subnetMapList.isEmpty()) {
1898                 for (Subnetmap subnet : subnetMapList) {
1899                     if (subnet.getVpnId() != null && subnet.getVpnId().getValue().equals(vpnName)
1900                             && subnet.getNetworkType().equals(NetworkType.VLAN)) {
1901                         if (subnet.getRouterInterfacePortId() == null || subnet.getNetworkId() == null) {
1902                             LOG.warn("The RouterInterfacePortId or NetworkId is null");
1903                             continue;
1904                         }
1905                         String routerInterfacePortUuid = subnet.getRouterInterfacePortId().getValue();
1906                         if (routerInterfacePortUuid != null && !routerInterfacePortUuid.isEmpty()) {
1907                             elanInstanceRouterPortMap.put(subnet.getNetworkId().getValue(),routerInterfacePortUuid);
1908                         }
1909                     }
1910                 }
1911             }
1912         }
1913         return elanInstanceRouterPortMap;
1914     }
1915
1916     String getRouterPordIdFromElanInstance(String elanInstanceName) {
1917         Optional<Subnetmaps> subnetMapsData = read(LogicalDatastoreType.CONFIGURATION, buildSubnetMapsWildCardPath());
1918         if (subnetMapsData.isPresent()) {
1919             List<Subnetmap> subnetMapList = subnetMapsData.get().getSubnetmap();
1920             if (subnetMapList != null && !subnetMapList.isEmpty()) {
1921                 for (Subnetmap subnet : subnetMapList) {
1922                     if (subnet.getNetworkId().getValue().equals(elanInstanceName)) {
1923                         if (subnet.getRouterInterfacePortId() != null) {
1924                             return subnet.getRouterInterfacePortId().getValue();
1925                         }
1926                     }
1927                 }
1928             }
1929         }
1930         return null;
1931     }
1932
1933     boolean shouldPopulateFibForVlan(String vpnName, String elanInstanceName, BigInteger dpnId) {
1934         Map<String,String> elanInstanceRouterPortMap = getElanInstanceRouterPortMap(vpnName);
1935         boolean shouldPopulateFibForVlan = false;
1936         if (!elanInstanceRouterPortMap.isEmpty()) {
1937             shouldPopulateFibForVlan = true;
1938         }
1939         for (Entry<String, String> elanInstanceRouterEntry : elanInstanceRouterPortMap
1940                 .entrySet()) {
1941             String currentElanInstance = elanInstanceRouterEntry.getKey();
1942             if (elanInstanceName != null && elanInstanceName.equals(currentElanInstance)) {
1943                 continue;
1944             }
1945             String externalinterface = getExternalElanInterface(currentElanInstance ,dpnId);
1946             if (externalinterface == null) {
1947                 shouldPopulateFibForVlan = false;
1948                 break;
1949             }
1950         }
1951         return shouldPopulateFibForVlan;
1952     }
1953
1954     public static InstanceIdentifier<DpnInterfaces> getElanDpnInterfaceOperationalDataPath(String elanInstanceName,
1955             BigInteger dpId) {
1956         return InstanceIdentifier.builder(ElanDpnInterfaces.class)
1957                 .child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName))
1958                 .child(DpnInterfaces.class, new DpnInterfacesKey(dpId)).build();
1959     }
1960
1961     public static InstanceIdentifier<ElanDpnInterfacesList> getElanDpnOperationalDataPath(String elanInstanceName) {
1962         return InstanceIdentifier.builder(ElanDpnInterfaces.class)
1963                 .child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName))
1964                 .build();
1965     }
1966
1967     public static boolean isMatchedPrefixToInterface(Prefixes prefix, VpnInterfaceOpDataEntry vpnInterface) {
1968         if (prefix != null && vpnInterface != null) {
1969             if (prefix.getDpnId() != null && vpnInterface.getDpnId() != null) {
1970                 if (prefix.getVpnInterfaceName() != null && vpnInterface.getName() != null) {
1971                     return prefix.getDpnId().equals(vpnInterface.getDpnId())
1972                             && prefix.getVpnInterfaceName().equalsIgnoreCase(vpnInterface.getName());
1973                 }
1974             }
1975         }
1976         return false;
1977     }
1978
1979     void removePrefixToInterfaceAdj(Adjacency adj, long vpnId, VpnInterfaceOpDataEntry vpnInterfaceOpDataEntry,
1980                                     WriteTransaction writeOperTxn) {
1981         if (writeOperTxn == null) {
1982             ListenableFutures.addErrorLogging(
1983                     txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx ->
1984                         removePrefixToInterfaceAdj(adj, vpnId, vpnInterfaceOpDataEntry, tx)), LOG,
1985                     "Error removing prefix");
1986             return;
1987         }
1988
1989         Optional<Prefixes> prefix = read(LogicalDatastoreType.OPERATIONAL,
1990                 VpnUtil.getPrefixToInterfaceIdentifier(vpnId, VpnUtil.getIpPrefix(adj.getIpAddress())));
1991         List<Prefixes> prefixToInterface = new ArrayList<>();
1992         List<Prefixes> prefixToInterfaceLocal = new ArrayList<>();
1993         if (prefix.isPresent()) {
1994             prefixToInterfaceLocal.add(prefix.get());
1995         }
1996         if (prefixToInterfaceLocal.isEmpty()) {
1997             for (String nh : adj.getNextHopIpList()) {
1998                 prefix = read(LogicalDatastoreType.OPERATIONAL, VpnUtil.getPrefixToInterfaceIdentifier(vpnId,
1999                                 VpnUtil.getIpPrefix(nh)));
2000                 if (prefix.isPresent()) {
2001                     prefixToInterfaceLocal.add(prefix.get());
2002                 }
2003             }
2004         }
2005         if (!prefixToInterfaceLocal.isEmpty()) {
2006             prefixToInterface.addAll(prefixToInterfaceLocal);
2007         }
2008         for (Prefixes pref : prefixToInterface) {
2009             if (VpnUtil.isMatchedPrefixToInterface(pref, vpnInterfaceOpDataEntry)) {
2010                 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL,
2011                         VpnUtil.getPrefixToInterfaceIdentifier(vpnId, pref.getIpAddress()));
2012             }
2013         }
2014     }
2015
2016     public static void sendNeighborSolicationToOfGroup(Ipv6NdUtilService ipv6NdUtilService, Ipv6Address srcIpv6Address,
2017             MacAddress srcMac, Ipv6Address dstIpv6Address, Long ofGroupId, BigInteger dpId) {
2018         SendNeighborSolicitationToOfGroupInput input = new SendNeighborSolicitationToOfGroupInputBuilder()
2019                 .setSourceIpv6(srcIpv6Address).setSourceLlAddress(srcMac).setTargetIpAddress(dstIpv6Address)
2020                 .setOfGroupId(ofGroupId).setDpId(dpId).build();
2021         try {
2022             Future<RpcResult<SendNeighborSolicitationToOfGroupOutput>> result = ipv6NdUtilService
2023                     .sendNeighborSolicitationToOfGroup(input);
2024             RpcResult<SendNeighborSolicitationToOfGroupOutput> rpcResult = result.get();
2025             if (!rpcResult.isSuccessful()) {
2026                 LOG.error("sendNeighborSolicitationToOfGroup: RPC Call failed for input={} and Errors={}", input,
2027                         rpcResult.getErrors());
2028             }
2029         } catch (InterruptedException | ExecutionException e) {
2030             LOG.error("Failed to send NS packet to ELAN group, input={}", input, e);
2031         }
2032     }
2033 }