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