From: Suraj Ranjan Date: Sat, 11 Mar 2017 14:37:57 +0000 (+0530) Subject: Subnet-Route support for L3VPN Over VxLAN X-Git-Tag: release/carbon~159 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=67bcae065d179f5a74499ba7ea12af19db018183;p=netvirt.git Subnet-Route support for L3VPN Over VxLAN This review includes the code changes to support the subnet-route feature for EVPN RT5 Change-Id: I216da6fa446eaabff03be152865126a5cd663665 Signed-off-by: Suraj Ranjan --- diff --git a/vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/EVPNVrfEntryProcessor.java b/vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/EVPNVrfEntryProcessor.java index 4c17101790..ec39a7f173 100644 --- a/vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/EVPNVrfEntryProcessor.java +++ b/vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/EVPNVrfEntryProcessor.java @@ -28,6 +28,7 @@ import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions; import org.opendaylight.netvirt.fibmanager.api.RouteOrigin; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry; @@ -72,6 +73,30 @@ public class EVPNVrfEntryProcessor { Preconditions.checkNotNull(vpnInstance, "Vpn Instance not available " + vrfTableKey.getRouteDistinguisher()); Preconditions.checkNotNull(vpnId, "Vpn Instance with rd " + vpnInstance.getVrfId() + " has null vpnId!"); + if (RouteOrigin.value(vrfEntry.getOrigin()) == RouteOrigin.CONNECTED) { + SubnetRoute subnetRoute = vrfEntry.getAugmentation(SubnetRoute.class); + final List vpnToDpnList = vpnInstance.getVpnToDpnList(); + final long elanTag = subnetRoute.getElantag(); + logger.trace("SubnetRoute augmented vrfentry found for rd {} prefix {} with elantag {}", + rd, vrfEntry.getDestPrefix(), elanTag); + if (vpnToDpnList != null) { + DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance(); + dataStoreCoordinator.enqueueJob("FIB-" + rd + "-" + vrfEntry.getDestPrefix(), + () -> { + WriteTransaction tx = dataBroker.newWriteOnlyTransaction(); + for (final VpnToDpnList curDpn : vpnToDpnList) { + if (curDpn.getDpnState() == VpnToDpnList.DpnState.Active) { + vrfEntryListener.installSubnetRouteInFib(curDpn.getDpnId(), elanTag, rd, + vpnId, vrfEntry, tx); + } + } + List> futures = new ArrayList<>(); + futures.add(tx.submit()); + return futures; + }); + } + return; + } Prefixes localNextHopInfo = FibUtil.getPrefixToInterface(dataBroker, vpnInstance.getVpnId(), vrfEntry.getDestPrefix()); List localDpnId = new ArrayList<>(); @@ -91,6 +116,7 @@ public class EVPNVrfEntryProcessor { private List createLocalEvpnFlows(long vpnId, String rd, VrfEntry vrfEntry, Prefixes localNextHopInfo) { List returnLocalDpnId = new ArrayList<>(); + String localNextHopIP = vrfEntry.getDestPrefix(); if (localNextHopInfo == null) { //Handle extra routes and imported routes Routes extraRoute = vrfEntryListener.getVpnToExtraroute(rd, vrfEntry.getDestPrefix()); @@ -100,7 +126,7 @@ public class EVPNVrfEntryProcessor { if (nextHopIp != null) { localNextHopInfo = FibUtil.getPrefixToInterface(dataBroker, vpnId, nextHopIp + "/32"); if (localNextHopInfo != null) { - String localNextHopIP = nextHopIp + "/32"; + localNextHopIP = nextHopIp + "/32"; BigInteger dpnId = checkCreateLocalEvpnFlows(localNextHopInfo, localNextHopIP, vpnId, rd, vrfEntry); returnLocalDpnId.add(dpnId); @@ -111,7 +137,6 @@ public class EVPNVrfEntryProcessor { } else { logger.info("Creating local EVPN flows for prefix {} rd {} route-paths {} evi {}.", vrfEntry.getDestPrefix(), rd, vrfEntry.getRoutePaths(), vrfEntry.getL3vni()); - String localNextHopIP = vrfEntry.getDestPrefix(); BigInteger dpnId = checkCreateLocalEvpnFlows(localNextHopInfo, localNextHopIP, vpnId, rd, vrfEntry); returnLocalDpnId.add(dpnId); @@ -142,7 +167,6 @@ public class EVPNVrfEntryProcessor { WriteTransaction tx = dataBroker.newWriteOnlyTransaction(); vrfEntryListener.makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW, tx); - List> futures = new ArrayList<>(); futures.add(tx.submit()); return futures; @@ -158,7 +182,6 @@ public class EVPNVrfEntryProcessor { List vpnToDpnList = vpnInstance.getVpnToDpnList(); if (vpnToDpnList != null) { DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance(); - dataStoreCoordinator = DataStoreJobCoordinator.getInstance(); dataStoreCoordinator.enqueueJob("FIB" + rd.toString() + vrfEntry.getDestPrefix(), new Callable>>() { @Override diff --git a/vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/VrfEntryListener.java b/vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/VrfEntryListener.java index 1c9aaadb43..a95d907d26 100755 --- a/vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/VrfEntryListener.java +++ b/vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/VrfEntryListener.java @@ -529,7 +529,7 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase adjPath = identifier.augmentation(Adjacencies.class); Optional optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, adjPath); boolean isL3VpnOverVxLan = VpnUtil.isL3VpnOverVxLan(vpnInstanceOpData.getL3vni()); - VrfEntry.EncapType encapType = isL3VpnOverVxLan ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre; + VrfEntry.EncapType encapType = VpnUtil.getEncapType(isL3VpnOverVxLan); long l3vni = vpnInstanceOpData.getL3vni() == null ? 0L : vpnInstanceOpData.getL3vni(); VpnPopulator populator = L3vpnRegistry.getRegisteredPopulator(encapType); List adjacencies; diff --git a/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnManagerImpl.java b/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnManagerImpl.java index 1645f3abf5..b1fee81cdb 100644 --- a/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnManagerImpl.java +++ b/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnManagerImpl.java @@ -35,6 +35,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406. import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap; import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcResult; @@ -127,8 +128,11 @@ public class VpnManagerImpl implements IVpnManager { int label,RouteOrigin origin) { LOG.info("Adding extra route with destination {}, nextHop {}, label{} and origin {}", destination, nextHop, label, origin); - vpnInterfaceManager.addExtraRoute(vpnName, destination, nextHop, rd, routerID, label, 0 /*l3vni*/, origin, - /*intfName*/ null, null /*Adjacency*/, VrfEntry.EncapType.Mplsgre, null); + VpnInstanceOpDataEntry vpnOpEntry = VpnUtil.getVpnInstanceOpData(dataBroker, rd); + Boolean isVxlan = VpnUtil.isL3VpnOverVxLan(vpnOpEntry.getL3vni()); + VrfEntry.EncapType encapType = VpnUtil.getEncapType(isVxlan); + vpnInterfaceManager.addExtraRoute(vpnName, destination, nextHop, rd, routerID, label, vpnOpEntry.getL3vni(), + origin,/*intfName*/ null, null /*Adjacency*/, encapType, null); } @Override diff --git a/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnRpcServiceImpl.java b/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnRpcServiceImpl.java index 98b41c4990..389076d0ca 100644 --- a/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnRpcServiceImpl.java +++ b/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnRpcServiceImpl.java @@ -21,6 +21,7 @@ import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComp import org.opendaylight.netvirt.vpnmanager.intervpnlink.InterVpnLinkUtil; import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.AddStaticRouteOutputBuilder; @@ -148,6 +149,9 @@ public class VpnRpcServiceImpl implements VpnRpcService { } String vpnRd = VpnUtil.getVpnRd(dataBroker, input.getVpnInstanceName()); + VpnInstanceOpDataEntry vpnOpEntry = VpnUtil.getVpnInstanceOpData(dataBroker, vpnRd); + Boolean isVxlan = VpnUtil.isL3VpnOverVxLan(vpnOpEntry.getL3vni()); + VrfEntry.EncapType encapType = VpnUtil.getEncapType(isVxlan); if (vpnRd == null) { String message = "Could not find Route-Distinguisher for VpnName " + vpnInstanceName; result.set(RpcResultBuilder.failed().withError(RpcError.ErrorType.APPLICATION, @@ -171,8 +175,8 @@ public class VpnRpcServiceImpl implements VpnRpcService { } } else { vpnInterfaceMgr.addExtraRoute(vpnInstanceName, destination, nexthop, vpnRd, null /* routerId */, - label.intValue(), 0 /*l3vni*/, RouteOrigin.STATIC, null /* intfName */, null /*Adjacency*/, - VrfEntry.EncapType.Mplsgre, null); + label.intValue(), vpnOpEntry.getL3vni(), RouteOrigin.STATIC, null /* intfName */, + null /*Adjacency*/, encapType, null); } AddStaticRouteOutput labelOutput = new AddStaticRouteOutputBuilder().setLabel(label).build(); diff --git a/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnSubnetRouteHandler.java b/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnSubnetRouteHandler.java index 6ae2278aa3..9f102a4255 100644 --- a/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnSubnetRouteHandler.java +++ b/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnSubnetRouteHandler.java @@ -11,7 +11,6 @@ import com.google.common.base.Optional; import com.google.common.base.Preconditions; import java.math.BigInteger; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -22,6 +21,8 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.genius.mdsalutil.MDSALUtil; import org.opendaylight.netvirt.bgpmanager.api.IBgpManager; import org.opendaylight.netvirt.vpnmanager.VpnOpDataSyncer.VpnOpDataType; +import org.opendaylight.netvirt.vpnmanager.populator.intfc.VpnPopulator; +import org.opendaylight.netvirt.vpnmanager.populator.registry.L3vpnRegistry; import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus; @@ -38,6 +39,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.sub import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpn; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ExternalNetworks; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.Networks; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.networks.NetworksKey; @@ -921,20 +923,15 @@ public class VpnSubnetRouteHandler { return false; } if (nexthopIp != null) { - VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, - VpnUtil.getPrefixToInterfaceIdentifier(VpnUtil.getVpnId(dataBroker, vpnName), subnetIp), - VpnUtil.getPrefixToInterface(nhDpnId, subnetId.getValue(), subnetIp, subnetId, true /* isNatPrefix*/)); - vpnInterfaceManager.addSubnetRouteFibEntryToDS(rd, vpnName, subnetIp, nexthopIp, label, elanTag, nhDpnId, - networkName, null); - try { - // BGP manager will handle withdraw and advertise internally if prefix - // already exist - bgpManager.advertisePrefix(rd, null /*macAddress*/, subnetIp, Collections.singletonList(nexthopIp), - VrfEntry.EncapType.Mplsgre, label, 0 /*l3vni*/, 0 /*l2vni*/, null /*gatewayMacAddress*/); - } catch (Exception e) { - LOG.error("Fail: Subnet route not advertised for rd {} subnetIp {}", rd, subnetIp, e); - throw e; - } + VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, VpnUtil + .getPrefixToInterfaceIdentifier(VpnUtil.getVpnId(dataBroker, vpnName), subnetIp), VpnUtil + .getPrefixToInterface(nhDpnId, subnetId.getValue(), subnetIp, subnetId, true /*isNatPrefix*/)); + VpnInstanceOpDataEntry vpnOpEntry = VpnUtil.getVpnInstanceOpData(dataBroker, rd); + Boolean isVxlan = VpnUtil.isL3VpnOverVxLan(vpnOpEntry.getL3vni()); + VrfEntry.EncapType encapType = (isVxlan == true) ? VrfEntry.EncapType.Vxlan : VrfEntry.EncapType.Mplsgre; + VpnPopulator vpnPopulator = L3vpnRegistry.getRegisteredPopulator(encapType); + vpnPopulator.addSubnetRouteFibEntry(rd, vpnName, subnetIp, nexthopIp, label, elanTag, nhDpnId, + null, encapType); } else { LOG.warn("The nexthopip is empty for subnetroute subnetip {}, ignoring fib route addition", subnetIp); return false; diff --git a/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java b/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java index 26e235511e..e95339a103 100755 --- a/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java +++ b/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java @@ -95,6 +95,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagNameKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.ExtrarouteRdsMap; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.VrfEntryBase; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.extraroute.rds.map.ExtrarouteRds; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.extraroute.rds.map.ExtrarouteRdsKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.extraroute.rds.map.extraroute.rds.DestPrefixes; @@ -1678,6 +1679,10 @@ public class VpnUtil { return flowEntity; } + static VrfEntryBase.EncapType getEncapType(boolean isVxLan) { + return isVxLan ? VrfEntryBase.EncapType.Vxlan : VrfEntryBase.EncapType.Mplsgre; + } + static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.external.subnets .Subnets getExternalSubnet(DataBroker dataBroker, Uuid subnetId) { InstanceIdentifier vrfEntryId = + InstanceIdentifier.builder(FibEntries.class) + .child(VrfTables.class, new VrfTablesKey(rd)) + .child(VrfEntry.class, new VrfEntryKey(prefix)).build(); + Optional entry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId); + + if (!entry.isPresent()) { + List vrfEntryList = Collections.singletonList(vrfEntry); + + InstanceIdentifier.InstanceIdentifierBuilder idBuilder = + InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)); + InstanceIdentifier vrfTableId = idBuilder.build(); + + VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(vrfEntryList).build(); + + if (writeTxn != null) { + writeTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true); + } else { + VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew); + } + } else { // Found in MDSAL database + if (writeTxn != null) { + writeTxn.put(LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry, true); + } else { + VpnUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry); + } + LOG.debug("Updated vrfEntry for {} nexthop {} label {}", prefix, nextHop, label); + } + } + @Override public Adjacency createOperationalAdjacency(L3vpnInput input) { return new AdjacencyBuilder().build(); diff --git a/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/populator/intfc/VpnPopulator.java b/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/populator/intfc/VpnPopulator.java index 5a29dbe8d1..dccb63ccc4 100644 --- a/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/populator/intfc/VpnPopulator.java +++ b/vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/populator/intfc/VpnPopulator.java @@ -7,12 +7,19 @@ */ package org.opendaylight.netvirt.vpnmanager.populator.intfc; +import java.math.BigInteger; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.netvirt.vpnmanager.populator.input.L3vpnInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency; public interface VpnPopulator { void populateFib(L3vpnInput input, WriteTransaction writeCfgTxn, WriteTransaction writeOperTxn); + void addSubnetRouteFibEntry(String rd, String vpnName, String prefix, String nextHop, int label, + long elantag, BigInteger dpnId, WriteTransaction writeTxn, + VrfEntry.EncapType encapType); + + Adjacency createOperationalAdjacency(L3vpnInput input); }