2 * Copyright © 2016, 2017 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.cloudservicechain.utils;
10 import com.google.common.base.Optional;
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.stream.Collectors;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
19 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
20 import org.opendaylight.genius.mdsalutil.ActionInfo;
21 import org.opendaylight.genius.mdsalutil.FlowEntity;
22 import org.opendaylight.genius.mdsalutil.InstructionInfo;
23 import org.opendaylight.genius.mdsalutil.MDSALDataStoreUtils;
24 import org.opendaylight.genius.mdsalutil.MDSALUtil;
25 import org.opendaylight.genius.mdsalutil.MatchInfo;
26 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
27 import org.opendaylight.genius.mdsalutil.NwConstants;
28 import org.opendaylight.genius.mdsalutil.actions.ActionPopMpls;
29 import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
30 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
31 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
32 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
33 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
34 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
35 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
36 import org.opendaylight.genius.mdsalutil.matches.MatchMplsLabel;
37 import org.opendaylight.genius.utils.ServiceIndex;
38 import org.opendaylight.netvirt.cloudservicechain.CloudServiceChainConstants;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.cloud.servicechain.state.rev160711.VpnToPseudoPortList;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.cloud.servicechain.state.rev160711.vpn.to.pseudo.port.list.VpnToPseudoPortData;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.cloud.servicechain.state.rev160711.vpn.to.pseudo.port.list.VpnToPseudoPortDataKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceOpData;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.VpnInstanceToVpnId;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
62 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;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg2;
66 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
70 public final class VpnServiceChainUtils {
72 private static final Logger LOG = LoggerFactory.getLogger(VpnServiceChainUtils.class);
74 private VpnServiceChainUtils() { }
76 public static BigInteger getMetadataSCF(long scfTag) { // TODO: Move to a common place
77 return new BigInteger("FF", 16).and(BigInteger.valueOf(scfTag)).shiftLeft(32);
80 public static BigInteger getCookieL3(int vpnId) {
81 return CloudServiceChainConstants.COOKIE_L3_BASE.add(new BigInteger("0610000", 16))
82 .add(BigInteger.valueOf(vpnId));
86 public static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
87 return InstanceIdentifier.builder(VpnInstanceOpData.class)
88 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
91 public static InstanceIdentifier<BoundServices> buildBoundServicesIid(short servicePrio, String ifaceName) {
92 return InstanceIdentifier.builder(ServiceBindings.class)
93 .child(ServicesInfo.class, new ServicesInfoKey(ifaceName, ServiceModeIngress.class))
94 .child(BoundServices.class, new BoundServicesKey(servicePrio))
99 * Retrieves from MDSAL the Operational Data of the VPN specified by its
100 * Route-Distinguisher.
102 * @param rd Route-Distinguisher of the VPN
104 * @return the Operational Data of the VPN or absent if no VPN could be
105 * found for the given RD or if the VPN does not have operational
108 public static Optional<VpnInstanceOpDataEntry> getVpnInstanceOpData(DataBroker broker, String rd) {
109 InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnServiceChainUtils.getVpnInstanceOpDataIdentifier(rd);
110 return MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
113 public static InstanceIdentifier<VrfTables> buildVrfId(String rd) {
114 return InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
117 public static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
118 return InstanceIdentifier.builder(VpnInstanceOpData.class)
119 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd))
120 .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
123 public static InstanceIdentifier<VpnInstance> getVpnInstanceToVpnIdIdentifier(String vpnName) {
124 return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
125 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
128 public static InstanceIdentifier<VpnToPseudoPortData> getVpnToPseudoPortTagIid(String rd) {
129 VpnToPseudoPortDataKey key = new VpnToPseudoPortDataKey(rd);
130 return InstanceIdentifier.builder(VpnToPseudoPortList.class).child(VpnToPseudoPortData.class, key).build();
133 public static Optional<VpnToPseudoPortData> getVpnPseudoPortData(DataBroker broker, String rd) {
134 InstanceIdentifier<VpnToPseudoPortData> id = getVpnToPseudoPortTagIid(rd);
135 return MDSALDataStoreUtils.read(broker, LogicalDatastoreType.CONFIGURATION, id);
138 public static List<VpnToPseudoPortData> getAllVpnToPseudoPortData(DataBroker broker) {
139 InstanceIdentifier<VpnToPseudoPortList> path = InstanceIdentifier.builder(VpnToPseudoPortList.class).build();
140 Optional<VpnToPseudoPortList> all = MDSALDataStoreUtils.read(broker, LogicalDatastoreType.CONFIGURATION, path);
142 return all.isPresent() ? all.get().getVpnToPseudoPortData() : new ArrayList<>();
146 * Get fake VPNPseudoPort interface name.
149 * @param scfTag Service Function tag
150 * @param scsTag Service Chain tag
151 * @param lportTag Lport tag
152 * @return the fake VpnPseudoPort interface name
154 public static String buildVpnPseudoPortIfName(Long dpId, long scfTag, int scsTag, int lportTag) {
155 return new StringBuilder("VpnPseudo.").append(dpId).append(NwConstants.FLOWID_SEPARATOR)
156 .append(lportTag).append(NwConstants.FLOWID_SEPARATOR)
157 .append(scfTag).append(NwConstants.FLOWID_SEPARATOR)
158 .append(scsTag).toString();
162 * Retrieves the VpnId (datapath id) searching by VpnInstanceName.
164 * @param broker Reference to the MDSAL Databroker service
165 * @param vpnName The Vpn instance name
166 * @return the datapath identifier for the specified VPN
168 public static long getVpnId(DataBroker broker, String vpnName) {
170 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt
171 .l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id =
172 getVpnInstanceToVpnIdIdentifier(vpnName);
173 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt
174 .l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance =
175 MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
177 return vpnInstance.isPresent() ? vpnInstance.get().getVpnId() : CloudServiceChainConstants.INVALID_VPN_TAG;
181 * Retrieves the VPN's Route Distinguisher out from the VpnName.
183 * @param broker Reference to the MDSAL Databroker service
184 * @param vpnName The Vpn Instance Name. Typically the UUID.
185 * @return the RouteDistinguiser for the specified VPN
187 public static String getVpnRd(DataBroker broker, String vpnName) {
188 InstanceIdentifier<VpnInstance> id = getVpnInstanceToVpnIdIdentifier(vpnName);
189 return MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id).toJavaUtil().map(
190 VpnInstance::getVrfId).orElse(null);
194 * Returns all the VrfEntries that belong to a given VPN.
196 * @param broker Reference to the MDSAL Databroker service
197 * @param rd Route-distinguisher of the VPN
198 * @return the list of the matching VrfEntries
200 public static List<VrfEntry> getAllVrfEntries(DataBroker broker, String rd) {
201 InstanceIdentifier<VrfTables> vpnVrfTables =
202 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
203 return MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vpnVrfTables).toJavaUtil().map(
204 VrfTables::getVrfEntry).orElse(new ArrayList<>());
208 * Installs/removes a flow in LPortDispatcher table that is in charge of
209 * handling packets that falls back from SCF Pipeline to L3Vpn.
211 * @param mdsalManager MDSAL Util API accessor
212 * @param vpnId Dataplane identifier of the VPN, the Vrf Tag.
213 * @param dpId The DPN where the flow must be installed/removed
214 * @param vpnPseudoLportTag Dataplane identifier for the VpnPseudoPort
215 * @param addOrRemove States if the flow must be created or removed
217 public static void programLPortDispatcherFlowForScfToVpn(IMdsalApiManager mdsalManager, long vpnId, BigInteger dpId,
218 Integer vpnPseudoLportTag, int addOrRemove) {
219 LOG.trace("programLPortDispatcherFlowForScfToVpn: vpnId={} dpId={}, vpnPseudoLportTag={} addOrRemove={}",
220 vpnId, dpId, vpnPseudoLportTag, addOrRemove);
221 Flow flow = buildLPortDispFromScfToL3VpnFlow(vpnId, dpId, vpnPseudoLportTag, addOrRemove);
222 if (addOrRemove == NwConstants.ADD_FLOW) {
223 mdsalManager.installFlow(dpId, flow);
225 mdsalManager.removeFlow(dpId, flow);
230 * Build the flow that must be inserted when there is a ScHop whose
231 * egressPort is a VPN Pseudo Port. In that case, packets must be moved
232 * from the SCF to VPN Pipeline.
234 * Flow matches: VpnPseudo port lPortTag + SI=L3VPN
235 * Actions: Write vrfTag in Metadata + goto FIB Table
237 * @param vpnId Dataplane identifier of the VPN, the Vrf Tag.
238 * @param dpId The DPN where the flow must be installed/removed
239 * @param lportTag Dataplane identifier for the VpnPseudoPort
240 * @param addOrRemove States if it must build a Flow to be created or
243 * @return the Flow object
245 public static Flow buildLPortDispFromScfToL3VpnFlow(Long vpnId, BigInteger dpId, Integer lportTag,
247 LOG.info("buildLPortDispFlowForScf vpnId={} dpId={} lportTag={} addOrRemove={} ",
248 vpnId, dpId, lportTag, addOrRemove);
249 List<MatchInfo> matches = buildMatchOnLportTagAndSI(lportTag,
250 ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME,
251 NwConstants.L3VPN_SERVICE_INDEX));
252 List<Instruction> instructions = buildSetVrfTagAndGotoFibInstructions(vpnId.intValue());
254 String flowRef = getScfToL3VpnLportDispatcherFlowRef(lportTag);
257 if (addOrRemove == NwConstants.ADD_FLOW) {
258 result = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
259 CloudServiceChainConstants.DEFAULT_SCF_FLOW_PRIORITY, flowRef,
260 0, 0, VpnServiceChainUtils.getCookieL3(vpnId.intValue()),
261 matches, instructions);
264 result = new FlowBuilder().setTableId(NwConstants.LPORT_DISPATCHER_TABLE)
265 .setId(new FlowId(flowRef))
273 * Builds the Match for flows that must match on a given lportTag and
276 * @return the Match as a list.
278 public static List<MatchInfo> buildMatchOnLportTagAndSI(Integer lportTag, short serviceIndex) {
279 return Collections.singletonList(
280 new MatchMetadata(MetaDataUtil.getMetaDataForLPortDispatcher(lportTag, serviceIndex),
281 MetaDataUtil.getMetaDataMaskForLPortDispatcher()));
285 * Builds a The Instructions that sets the VpnTag in metadata and sends to
288 * @param vpnTag Dataplane identifier of the VPN.
289 * @return the list of Instructions
291 public static List<Instruction> buildSetVrfTagAndGotoFibInstructions(Integer vpnTag) {
292 List<Instruction> result = new ArrayList<>();
293 int instructionKey = 0;
294 result.add(MDSALUtil.buildAndGetWriteMetadaInstruction(MetaDataUtil.getVpnIdMetadata(vpnTag),
295 MetaDataUtil.METADATA_MASK_VRFID,
297 result.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_FIB_TABLE, ++instructionKey));
303 * Builds a Flow for the LFIB table that sets the LPortTag of the
304 * VpnPseudoPort and sends to LPortDispatcher table.
306 * <li>Matching: eth_type = MPLS, mpls_label = VPN MPLS label
307 * <li>Actions: setMetadata LportTag and SI=2, pop MPLS, Go to
308 * LPortDispacherTable
312 * @param label MPLS label
313 * @param nextHop Next Hop IP
314 * @param lportTag Pseudo Logical Port tag
315 * @return the FlowEntity
317 public static FlowEntity buildLFibVpnPseudoPortFlow(BigInteger dpId, Long label, String nextHop, int lportTag) {
319 List<MatchInfo> matches = new ArrayList<>();
320 matches.add(MatchEthernetType.MPLS_UNICAST);
321 matches.add(new MatchMplsLabel(label));
323 List<ActionInfo> actionsInfos = Collections.singletonList(new ActionPopMpls());
324 List<InstructionInfo> instructions = new ArrayList<>();
325 instructions.add(new InstructionWriteMetadata(
326 MetaDataUtil.getMetaDataForLPortDispatcher(lportTag,
327 ServiceIndex.getIndex(NwConstants.SCF_SERVICE_NAME,
328 NwConstants.SCF_SERVICE_INDEX)),
329 MetaDataUtil.getMetaDataMaskForLPortDispatcher()
332 instructions.add(new InstructionApplyActions(actionsInfos));
333 instructions.add(new InstructionGotoTable(NwConstants.L3_INTERFACE_TABLE));
334 String flowRef = getLFibVpnPseudoPortFlowRef(lportTag, label, nextHop);
335 return MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_LFIB_TABLE, flowRef,
336 CloudServiceChainConstants.DEFAULT_SCF_FLOW_PRIORITY, flowRef, 0, 0,
337 NwConstants.COOKIE_VM_LFIB_TABLE, matches, instructions);
342 * Modifies the LFIB table by adding/removing flows that redirects traffic
343 * from a VPN into the SCF via the VpnPseudoLport.
344 * Flows that match on the label and sets the VpnPseudoPort lportTag and
345 * sends to LPortDispatcher (via table 80)
348 public static void programLFibEntriesForSCF(IMdsalApiManager mdsalMgr, BigInteger dpId, List<VrfEntry> vrfEntries,
349 int lportTag, int addOrRemove) {
350 LOG.trace("programLFibEntriesForSCF: dpId={} lportTag={} addOrRemove={}", dpId, lportTag, addOrRemove);
351 if (vrfEntries != null) {
352 vrfEntries.forEach(vrfEntry -> vrfEntry.getRoutePaths()
353 .forEach(routePath -> {
354 Long label = routePath.getLabel();
355 String nextHop = routePath.getNexthopAddress();
356 FlowEntity flowEntity = buildLFibVpnPseudoPortFlow(dpId, label, nextHop, lportTag);
357 if (addOrRemove == NwConstants.ADD_FLOW) {
358 mdsalMgr.installFlow(flowEntity);
360 mdsalMgr.removeFlow(flowEntity);
363 "LFIBEntry for label={}, destination={}, nexthop={} {} successfully in dpn={}",
364 label, vrfEntry.getDestPrefix(), nextHop,
365 addOrRemove == NwConstants.DEL_FLOW ? "removed" : "installed", dpId);
371 * Installs/removes a flow in LPortDispatcher table that is in charge
372 * of sending the traffic to the SCF Pipeline.
375 public static void programLPortDispatcherFlowForVpnToScf(IMdsalApiManager mdsalManager, BigInteger dpId,
376 int lportTag, long scfTag, short gotoTableId,
378 LOG.trace("programLPortDispatcherFlowForVpnToScf: dpId={} lportTag={} scfTag={} gotoTableId={} addOrRemove={}",
379 dpId, lportTag, scfTag, gotoTableId, addOrRemove);
380 FlowEntity flowEntity = VpnServiceChainUtils.buildLportFlowDispForVpnToScf(dpId, lportTag, scfTag, gotoTableId);
381 if (addOrRemove == NwConstants.ADD_FLOW) {
382 mdsalManager.installFlow(flowEntity);
384 mdsalManager.removeFlow(flowEntity);
389 * Creates the flow that sends the packet from the VPN to the SCF pipeline.
390 * This usually happens when there is an ScHop whose ingressPort is a
393 * <li>Matches: lportTag = vpnPseudoLPortTag, SI = 1
394 * <li>Actions: setMetadata(scfTag), Go to: UpSubFilter table
397 public static FlowEntity buildLportFlowDispForVpnToScf(BigInteger dpId, int lportTag, long scfTag,
399 List<InstructionInfo> instructions = new ArrayList<>();
400 List<ActionInfo> actionsInfos = new ArrayList<>();
401 actionsInfos.add(new ActionRegLoad(NxmNxReg2.class, 0, 31, scfTag));
402 instructions.add(new InstructionApplyActions(actionsInfos));
403 instructions.add(new InstructionGotoTable(gotoTableId));
404 String flowRef = getL3VpnToScfLportDispatcherFlowRef(lportTag);
406 List<MatchInfo> matches =
407 buildMatchOnLportTagAndSI(lportTag, ServiceIndex.getIndex(NwConstants.SCF_SERVICE_NAME,
408 NwConstants.SCF_SERVICE_INDEX));
409 return MDSALUtil.buildFlowEntity(dpId, NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
410 CloudServiceChainConstants.DEFAULT_SCF_FLOW_PRIORITY, flowRef, 0, 0,
411 getCookieSCHop(scfTag), matches, instructions);
415 public static Optional<Long> getVpnPseudoLportTag(DataBroker broker, String rd) {
416 InstanceIdentifier<VpnToPseudoPortData> path = getVpnToPseudoPortTagIid(rd);
417 return Optional.fromJavaUtil(MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path).toJavaUtil().map(
418 VpnToPseudoPortData::getVpnLportTag));
422 * Creates a Flow that does the trick of moving the packets from one VPN to
426 public static Flow buildLPortDispFlowForVpntoVpn(Integer dstLportTag, Integer vpnTag) {
427 List<MatchInfo> matches =
428 buildMatchOnLportTagAndSI(dstLportTag, ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME,
429 NwConstants.L3VPN_SERVICE_INDEX));
430 List<Instruction> instructions = buildSetVrfTagAndGotoFibInstructions(vpnTag);
431 String flowRef = getL3VpnToL3VpnLportDispFlowRef(dstLportTag, vpnTag);
433 return MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
434 CloudServiceChainConstants.DEFAULT_LPORT_DISPATCHER_FLOW_PRIORITY, flowRef,
435 0, 0, VpnServiceChainUtils.getCookieL3(vpnTag),
436 matches, instructions);
440 private static BigInteger getCookieSCHop(long scfInstanceTag) {
441 return CloudServiceChainConstants.COOKIE_SCF_BASE.add(new BigInteger("0610000", 16))
442 .add(BigInteger.valueOf(scfInstanceTag));
446 * Id for the Flow that is inserted in LFIB that is in charge of receiving packets coming from
447 * DC-GW and setting the VpnPseudoLport tag in metadata and send to LPortDispatcher. There is
448 * one of this entries per VrfEntry.
450 private static String getLFibVpnPseudoPortFlowRef(int vpnLportTag, long label, String nextHop) {
451 return new StringBuilder(64).append(CloudServiceChainConstants.VPN_PSEUDO_PORT_FLOWID_PREFIX)
452 .append(NwConstants.FLOWID_SEPARATOR).append(vpnLportTag)
453 .append(NwConstants.FLOWID_SEPARATOR).append(label)
454 .append(NwConstants.FLOWID_SEPARATOR).append(nextHop).toString();
457 private static String getL3VpnToL3VpnLportDispFlowRef(Integer lportTag, Integer vpnTag) {
458 return new StringBuilder().append(CloudServiceChainConstants.FLOWID_PREFIX_L3).append(lportTag)
459 .append(NwConstants.FLOWID_SEPARATOR).append(vpnTag)
460 .append(NwConstants.FLOWID_SEPARATOR)
461 .append(CloudServiceChainConstants.DEFAULT_LPORT_DISPATCHER_FLOW_PRIORITY).toString();
465 * Id for the Flow that is inserted in LPortDispatcher table that is in
466 * charge of delivering packets from the L3VPN to the SCF Pipeline.
467 * The VpnPseudoLPort tag and the SCF_SERVICE_INDEX is enough to identify
468 * this kind of flows.
470 public static String getL3VpnToScfLportDispatcherFlowRef(Integer lportTag) {
471 return new StringBuffer(64).append(CloudServiceChainConstants.VPN_PSEUDO_VPN2SCF_FLOWID_PREFIX).append(lportTag)
472 .append(NwConstants.FLOWID_SEPARATOR)
473 .append(ServiceIndex.getIndex(NwConstants.SCF_SERVICE_NAME,
474 NwConstants.SCF_SERVICE_INDEX))
475 .append(NwConstants.FLOWID_SEPARATOR)
476 .append(CloudServiceChainConstants.DEFAULT_SCF_FLOW_PRIORITY).toString();
480 * Builds an identifier for the flow that is inserted in LPortDispatcher
481 * table and that is in charge of handling packets that are delivered from
482 * the SCF to the L3VPN Pipeline.
485 public static String getScfToL3VpnLportDispatcherFlowRef(Integer lportTag) {
486 return new StringBuffer().append(CloudServiceChainConstants.VPN_PSEUDO_SCF2VPN_FLOWID_PREFIX).append(lportTag)
487 .append(NwConstants.FLOWID_SEPARATOR)
488 .append(ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME,
489 NwConstants.L3VPN_SERVICE_INDEX))
490 .append(NwConstants.FLOWID_SEPARATOR)
491 .append(CloudServiceChainConstants.DEFAULT_SCF_FLOW_PRIORITY).toString();
494 public static List<String> getAllVpnIfaceNames(DataBroker dataBroker, String vpnName) {
496 String vpnRd = getVpnRd(dataBroker, vpnName);
497 InstanceIdentifier<VpnInstanceOpDataEntry> vpnOpDataIid =
498 InstanceIdentifier.builder(VpnInstanceOpData.class)
499 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vpnRd)).build();
502 VpnInstanceOpDataEntry vpnOpData =
503 SingleTransactionDataBroker.syncRead(dataBroker, LogicalDatastoreType.OPERATIONAL, vpnOpDataIid);
505 if (vpnOpData == null) {
506 return Collections.emptyList();
508 List<VpnToDpnList> dpnToVpns = vpnOpData.getVpnToDpnList();
509 if (dpnToVpns == null) {
510 return Collections.emptyList();
513 return dpnToVpns.stream()
514 .filter(dpn -> dpn.getVpnInterfaces() != null)
515 .flatMap(dpn -> dpn.getVpnInterfaces().stream())
516 .map(VpnInterfaces::getInterfaceName)
517 .collect(Collectors.toList());
518 } catch (ReadFailedException e) {
519 LOG.warn("getAllVpnInterfaces for vpn {}: Failure on read operation", vpnName, e);
520 return Collections.emptyList();