2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netvirt.fibmanager;
10 import static org.opendaylight.netvirt.fibmanager.FibConstants.COOKIE_TUNNEL;
11 import static org.opendaylight.netvirt.fibmanager.FibConstants.DEFAULT_FIB_FLOW_PRIORITY;
12 import static org.opendaylight.netvirt.fibmanager.FibConstants.FLOWID_PREFIX;
14 import com.google.common.base.Optional;
15 import com.google.common.util.concurrent.Futures;
16 import java.math.BigInteger;
17 import java.net.InetAddress;
18 import java.net.UnknownHostException;
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.concurrent.Future;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.genius.mdsalutil.ActionInfo;
26 import org.opendaylight.genius.mdsalutil.InstructionInfo;
27 import org.opendaylight.genius.mdsalutil.InstructionType;
28 import org.opendaylight.genius.mdsalutil.MDSALUtil;
29 import org.opendaylight.genius.mdsalutil.MatchFieldType;
30 import org.opendaylight.genius.mdsalutil.MatchInfo;
31 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
32 import org.opendaylight.genius.mdsalutil.NwConstants;
33 import org.opendaylight.genius.mdsalutil.actions.ActionPopMpls;
34 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
35 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CleanupDpnForVpnInput;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.CreateFibEntryInput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.PopulateFibOnDpnInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.RemoveFibEntryInput;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddressesBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddressesKey;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey;
56 import org.opendaylight.yangtools.yang.binding.DataObject;
57 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
58 import org.opendaylight.yangtools.yang.common.RpcResult;
59 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
63 public class FibRpcServiceImpl implements FibRpcService {
64 private static final Logger LOG = LoggerFactory.getLogger(FibRpcServiceImpl.class);
65 private final DataBroker dataBroker;
66 private final IMdsalApiManager mdsalManager;
67 private final IFibManager fibManager;
69 public FibRpcServiceImpl(final DataBroker dataBroker, final IMdsalApiManager mdsalManager,
70 final IFibManager fibManager) {
71 this.dataBroker = dataBroker;
72 this.mdsalManager = mdsalManager;
73 this.fibManager = fibManager;
77 * to install FIB routes on specified dpn with given instructions
81 public Future<RpcResult<Void>> createFibEntry(CreateFibEntryInput input) {
83 BigInteger dpnId = input.getSourceDpid();
84 String vpnName = input.getVpnName();
85 long vpnId = getVpnId(dataBroker, vpnName);
86 String vpnRd = getVpnRd(dataBroker, vpnName);
87 String ipAddress = input.getIpAddress();
88 LOG.info("Create custom FIB entry - {} on dpn {} for VPN {} ", ipAddress, dpnId, vpnName);
89 List<Instruction> instructions = input.getInstruction();
90 LOG.info("ADD: Adding Custom Fib Entry rd {} prefix {} label {}", vpnRd, ipAddress, input.getServiceId());
91 makeLocalFibEntry(vpnId, dpnId, ipAddress, instructions);
92 updateVpnToDpnAssociation(vpnId, dpnId, ipAddress, vpnName);
93 LOG.info("ADD: Added Custom Fib Entry rd {} prefix {} label {}", vpnRd, ipAddress, input.getServiceId());
94 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
98 * to remove FIB/LFIB/TST routes from specified dpn
102 public Future<RpcResult<Void>> removeFibEntry(RemoveFibEntryInput input) {
103 BigInteger dpnId = input.getSourceDpid();
104 String vpnName = input.getVpnName();
105 long vpnId = getVpnId(dataBroker, vpnName);
106 String vpnRd = getVpnRd(dataBroker, vpnName);
107 long serviceId = input.getServiceId();
108 String ipAddress = input.getIpAddress();
110 LOG.info("Delete custom FIB entry - {} on dpn {} for VPN {} ", ipAddress, dpnId, vpnName);
111 LOG.info("REMOVE: Removing Custom Fib Entry rd {} prefix {} label {}", vpnRd, ipAddress, input.getServiceId());
112 removeLocalFibEntry(dpnId, vpnId, ipAddress);
113 //removeLFibTableEntry(dpnId, serviceId);
114 //removeTunnelTableEntry(dpnId, serviceId);
115 removeFromVpnDpnAssociation(vpnId, dpnId, ipAddress, vpnName);
116 LOG.info("REMOVE: Removed Custom Fib Entry rd {} prefix {} label {}", vpnRd, ipAddress, input.getServiceId());
118 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
123 public Future<RpcResult<Void>> populateFibOnDpn(PopulateFibOnDpnInput input) {
124 fibManager.populateFibOnNewDpn(input.getDpid(), input.getVpnId(), input.getRd(), null);
125 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
129 public Future<RpcResult<Void>> cleanupDpnForVpn(CleanupDpnForVpnInput input) {
130 fibManager.cleanUpDpnForVpn(input.getDpid(), input.getVpnId(), input.getRd(), null);
131 return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
134 private void removeLocalFibEntry(BigInteger dpnId, long vpnId, String ipPrefix) {
135 String values[] = ipPrefix.split("/");
136 String ipAddress = values[0];
137 int prefixLength = (values.length == 1) ? 0 : Integer.parseInt(values[1]);
138 LOG.debug("Removing route from DPN. ip {} masklen {}", ipAddress, prefixLength);
139 InetAddress destPrefix = null;
141 destPrefix = InetAddress.getByName(ipAddress);
142 } catch (UnknownHostException e) {
143 LOG.error("UnknowHostException in removeRoute. Failed to remove Route for ipPrefix {}", ipAddress, e);
146 List<MatchInfo> matches = new ArrayList<MatchInfo>();
148 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
149 MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
151 matches.add(new MatchInfo(MatchFieldType.eth_type,
152 new long[] { 0x0800L }));
154 if(prefixLength != 0) {
155 matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] {
156 destPrefix.getHostAddress(), Integer.toString(prefixLength) }));
159 String flowRef = getFlowRef(dpnId, NwConstants.L3_FIB_TABLE, vpnId, ipAddress);
162 int priority = DEFAULT_FIB_FLOW_PRIORITY + prefixLength;
163 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_FIB_TABLE, flowRef,
164 priority, flowRef, 0, 0,
165 NwConstants.COOKIE_VM_FIB_TABLE, matches, null);
167 mdsalManager.removeFlow(dpnId, flowEntity);
169 LOG.debug("FIB entry for route {} on dpn {} removed successfully", ipAddress, dpnId);
172 private void removeLFibTableEntry(BigInteger dpnId, long serviceId) {
173 List<MatchInfo> matches = new ArrayList<MatchInfo>();
174 matches.add(new MatchInfo(MatchFieldType.eth_type,
175 new long[] { 0x8847L }));
176 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
178 String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
180 LOG.debug("removing LFib entry with flow ref {}", flowRef);
182 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
183 DEFAULT_FIB_FLOW_PRIORITY, flowRef, 0, 0,
184 NwConstants.COOKIE_VM_LFIB_TABLE, matches, null);
186 mdsalManager.removeFlow(dpnId, flowEntity);
188 LOG.debug("LFIB Entry for dpID : {} label : {} removed successfully {}",dpnId, serviceId);
191 private void removeTunnelTableEntry(BigInteger dpnId, long serviceId) {
192 LOG.info("remove terminatingServiceActions called with DpnId = {} and label = {}", dpnId , serviceId);
193 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
195 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
196 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
197 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
198 5, String.format("%s:%d","TST Flow Entry ",serviceId), 0, 0,
199 COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, null);
200 mdsalManager.removeFlow(dpnId, flowEntity);
201 LOG.debug("Terminating service Entry for dpID {} : label : {} removed successfully {}",dpnId, serviceId);
204 private void makeTunnelTableEntry(BigInteger dpnId, long serviceId, List<Instruction> customInstructions) {
205 List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
207 LOG.info("create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", dpnId , serviceId);
209 mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
211 Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
212 getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""), 5, String.format("%s:%d","TST Flow Entry ",serviceId),
213 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)),mkMatches, customInstructions);
215 mdsalManager.installFlow(dpnId, terminatingServiceTableFlowEntity);
218 private long getIpAddress(byte[] rawIpAddress) {
219 return (((rawIpAddress[0] & 0xFF) << (3 * 8)) + ((rawIpAddress[1] & 0xFF) << (2 * 8))
220 + ((rawIpAddress[2] & 0xFF) << (1 * 8)) + (rawIpAddress[3] & 0xFF)) & 0xffffffffL;
223 private void makeLocalFibEntry(long vpnId, BigInteger dpnId, String ipPrefix, List<Instruction> customInstructions) {
224 String values[] = ipPrefix.split("/");
225 String ipAddress = values[0];
226 int prefixLength = (values.length == 1) ? 0 : Integer.parseInt(values[1]);
227 LOG.debug("Adding route to DPN. ip {} masklen {}", ipAddress, prefixLength);
228 InetAddress destPrefix = null;
230 destPrefix = InetAddress.getByName(ipAddress);
231 } catch (UnknownHostException e) {
232 LOG.error("UnknowHostException in addRoute. Failed to add Route for ipPrefix {}", ipAddress, e);
235 List<MatchInfo> matches = new ArrayList<MatchInfo>();
237 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
238 MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
240 matches.add(new MatchInfo(MatchFieldType.eth_type,
241 new long[] { 0x0800L }));
243 if(prefixLength != 0) {
244 matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] {
245 destPrefix.getHostAddress(), Integer.toString(prefixLength) }));
248 String flowRef = getFlowRef(dpnId, NwConstants.L3_FIB_TABLE, vpnId, ipAddress);
251 int priority = DEFAULT_FIB_FLOW_PRIORITY + prefixLength;
252 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_FIB_TABLE, flowRef,
253 priority, flowRef, 0, 0,
254 NwConstants.COOKIE_VM_FIB_TABLE, matches, customInstructions);
256 mdsalManager.installFlow(dpnId, flowEntity);
258 LOG.debug("FIB entry for route {} on dpn {} installed successfully", ipAddress, dpnId);
261 private void makeLFibTableEntry(BigInteger dpId, long serviceId, List<Instruction> customInstructions) {
262 List<MatchInfo> matches = new ArrayList<MatchInfo>();
263 matches.add(new MatchInfo(MatchFieldType.eth_type,
264 new long[] { 0x8847L }));
265 matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
267 List<Instruction> instructions = new ArrayList<Instruction>();
268 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
269 actionsInfos.add(new ActionPopMpls());
270 Instruction writeInstruction = new InstructionInfo(InstructionType.apply_actions, actionsInfos).buildInstruction(0);
271 instructions.add(writeInstruction);
272 instructions.addAll(customInstructions);
274 // Install the flow entry in L3_LFIB_TABLE
275 String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, serviceId, "");
277 Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
278 DEFAULT_FIB_FLOW_PRIORITY, flowRef, 0, 0,
279 NwConstants.COOKIE_VM_LFIB_TABLE, matches, instructions);
281 mdsalManager.installFlow(dpId, flowEntity);
283 LOG.debug("LFIB Entry for dpID {} : label : {} modified successfully {}",dpId, serviceId );
286 private String getFlowRef(BigInteger dpnId, short tableId, long id, String ipAddress) {
287 return new StringBuilder(64).append(FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
288 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
289 .append(id).append(NwConstants.FLOWID_SEPARATOR).append(ipAddress).toString();
292 private synchronized void updateVpnToDpnAssociation(long vpnId, BigInteger dpnId, String ipAddr, String vpnName) {
293 LOG.debug("Updating VPN to DPN list for dpn : {} for VPN: {} with ip: {}",
294 dpnId, vpnName, ipAddr);
295 String routeDistinguisher = getVpnRd(dataBroker, vpnName);
296 String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
297 synchronized (vpnName.intern()) {
298 InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(rd, dpnId);
299 Optional<VpnToDpnList> dpnInVpn = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
300 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses
301 ipAddress = new IpAddressesBuilder().setIpAddress(ipAddr).build();
303 if (dpnInVpn.isPresent()) {
304 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id.child(
305 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance
306 .op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses.class,
307 new IpAddressesKey(ipAddr)), ipAddress);
309 MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL,
310 getVpnInstanceOpDataIdentifier(rd),
311 getVpnInstanceOpData(rd, vpnId, vpnName));
312 VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
313 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
314 .vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses> ipAddresses = new ArrayList<>();
315 ipAddresses.add(ipAddress);
316 MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id,
317 vpnToDpnList.setIpAddresses(ipAddresses).build());
318 LOG.debug("populate FIB on new dpn {} for VPN {}", dpnId, vpnName);
319 fibManager.populateFibOnNewDpn(dpnId, vpnId, rd, null);
324 private synchronized void removeFromVpnDpnAssociation(long vpnId, BigInteger dpnId, String ipAddr, String vpnName) {
325 LOG.debug("Removing association of VPN to DPN list for dpn : {} for VPN: {} with ip: {}",
326 dpnId, vpnName, ipAddr);
327 String routeDistinguisher = getVpnRd(dataBroker, vpnName);
328 String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
329 synchronized (vpnName.intern()) {
330 InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(rd, dpnId);
331 Optional<VpnToDpnList> dpnInVpn = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
332 if (dpnInVpn.isPresent()) {
333 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
334 .vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
335 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses
336 ipAddress = new IpAddressesBuilder().setIpAddress(ipAddr).build();
338 if (ipAddresses != null && ipAddresses.remove(ipAddress)) {
339 if (ipAddresses.isEmpty()) {
340 List<VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
341 if (vpnInterfaces == null || vpnInterfaces.isEmpty()) {
343 LOG.debug("Cleaning up dpn {} from VPN {}", dpnId, vpnName);
344 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
345 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd, null);
348 delete(dataBroker, LogicalDatastoreType.OPERATIONAL, id.child(
349 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
350 .vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses.class,
351 new IpAddressesKey(ipAddr)));
358 //TODO: Below Util methods to be removed once VpnUtil methods are exposed in api bundle
359 public static String getVpnRd(DataBroker broker, String vpnName) {
360 InstanceIdentifier<VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
361 return MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id).transform(VpnInstance::getVrfId).orNull();
364 static InstanceIdentifier<VpnInstance>
365 getVpnInstanceToVpnIdIdentifier(String vpnName) {
366 return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
367 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
371 static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
372 return InstanceIdentifier.builder(VpnInstanceOpData.class)
373 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd))
374 .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
377 static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
378 return InstanceIdentifier.builder(VpnInstanceOpData.class)
379 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
382 static VpnInstanceOpDataEntry getVpnInstanceOpData(String rd, long vpnId, String vpnName) {
383 return new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnName).build();
386 static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
387 InstanceIdentifier<T> path) {
388 WriteTransaction tx = broker.newWriteOnlyTransaction();
389 tx.delete(datastoreType, path);
393 static long getVpnId(DataBroker broker, String vpnName) {
394 InstanceIdentifier<VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
395 return MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id).transform(VpnInstance::getVpnId).or(-1L);