[CORD-576] Implements VPWS transport in OFDPA pipelines
Changes:
- Introduces the emulation of the MPLS-ECMP groups for CPQD;
- Adds a couple of check to avoid the creation of MPLS-ECMP for OFDPA;
- Implements the VPWS transport for OFDPA3;
- Implements the VPWS tranposrt for CPQD-OFDPA2;
Change-Id: I8181fceffa35f73f549e3df07fa353642c9d6872
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2GroupHandler.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2GroupHandler.java
index 60fefcf..2a4de98 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2GroupHandler.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/Ofdpa2GroupHandler.java
@@ -77,6 +77,11 @@
import java.util.stream.Collectors;
import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.driver.pipeline.Ofdpa2GroupHandler.OfdpaMplsGroupSubType.OFDPA_GROUP_TYPE_SHIFT;
+import static org.onosproject.driver.pipeline.Ofdpa2GroupHandler.OfdpaMplsGroupSubType.OFDPA_MPLS_SUBTYPE_SHIFT;
+import static org.onosproject.driver.pipeline.Ofdpa2Pipeline.isNotMplsBos;
+import static org.onosproject.net.flow.criteria.Criterion.Type.VLAN_VID;
+import static org.onosproject.net.flowobjective.NextObjective.Type.HASHED;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -185,6 +190,30 @@
groupService.addListener(new InnerGroupListener());
}
+ /**
+ * The purpose of this function is to verify if the hashed next
+ * objective is supported by the current pipeline.
+ *
+ * @param nextObjective the hashed objective to verify
+ * @return true if the hashed objective is supported. Otherwise false.
+ */
+ public boolean verifyHashedNextObjective(NextObjective nextObjective) {
+ // if it is not hashed, there is something wrong;
+ if (nextObjective.type() != HASHED) {
+ return false;
+ }
+ // The case non supported is the MPLS-ECMP. For now, we try
+ // to create a MPLS-ECMP for the transport of a VPWS. The
+ // necessary info are contained in the meta selector. In particular
+ // we are looking for the case of BoS==False;
+ TrafficSelector metaSelector = nextObjective.meta();
+ if (metaSelector != null && isNotMplsBos(metaSelector)) {
+ return false;
+ }
+
+ return true;
+ }
+
//////////////////////////////////////
// Group Creation
//////////////////////////////////////
@@ -206,6 +235,12 @@
processBroadcastNextObjective(nextObjective);
break;
case HASHED:
+ if (!verifyHashedNextObjective(nextObjective)) {
+ log.error("Next Objectives of type hashed not supported. Next Objective Id:{}",
+ nextObjective.id());
+ Ofdpa2Pipeline.fail(nextObjective, ObjectiveError.BADPARAMS);
+ return;
+ }
processHashedNextObjective(nextObjective);
break;
case FAILOVER:
@@ -248,9 +283,14 @@
return;
}
+ boolean isMpls = false;
+ if (nextObj.meta() != null) {
+ isMpls = isNotMplsBos(nextObj.meta());
+ }
+
// break up simple next objective to GroupChain objects
GroupInfo groupInfo = createL2L3Chain(treatment, nextObj.id(),
- nextObj.appId(), false,
+ nextObj.appId(), isMpls,
nextObj.meta());
if (groupInfo == null) {
log.error("Could not process nextObj={} in dev:{}", nextObj.id(), deviceId);
@@ -404,7 +444,7 @@
if (vlanid == null && meta != null) {
// use metadata if available
- Criterion vidCriterion = meta.getCriterion(Criterion.Type.VLAN_VID);
+ Criterion vidCriterion = meta.getCriterion(VLAN_VID);
if (vidCriterion != null) {
vlanid = ((VlanIdCriterion) vidCriterion).vlanId();
}
@@ -746,7 +786,7 @@
*
* @param nextObj the nextObjective of type HASHED
*/
- private void processHashedNextObjective(NextObjective nextObj) {
+ protected void processHashedNextObjective(NextObjective nextObj) {
// storage for all group keys in the chain of groups created
List<Deque<GroupKey>> allGroupKeys = new ArrayList<>();
List<GroupInfo> unsentGroups = new ArrayList<>();
@@ -812,7 +852,7 @@
* @param allGroupKeys a list to store groupKey for each bucket-group-chain
* @param unsentGroups a list to store GroupInfo for each bucket-group-chain
*/
- private void createHashBucketChains(NextObjective nextObj,
+ protected void createHashBucketChains(NextObjective nextObj,
List<Deque<GroupKey>> allGroupKeys,
List<GroupInfo> unsentGroups) {
// break up hashed next objective to multiple groups
@@ -839,9 +879,23 @@
Deque<GroupKey> gkeyChain = new ArrayDeque<>();
// XXX we only deal with 0 and 1 label push right now
if (labelsPushed == 0) {
- GroupInfo nolabelGroupInfo = createL2L3Chain(bucket, nextObj.id(),
- nextObj.appId(), false,
- nextObj.meta());
+ GroupInfo nolabelGroupInfo;
+ TrafficSelector metaSelector = nextObj.meta();
+ if (metaSelector != null) {
+ if (isNotMplsBos(metaSelector)) {
+ nolabelGroupInfo = createL2L3Chain(bucket, nextObj.id(),
+ nextObj.appId(), true,
+ nextObj.meta());
+ } else {
+ nolabelGroupInfo = createL2L3Chain(bucket, nextObj.id(),
+ nextObj.appId(), false,
+ nextObj.meta());
+ }
+ } else {
+ nolabelGroupInfo = createL2L3Chain(bucket, nextObj.id(),
+ nextObj.appId(), false,
+ nextObj.meta());
+ }
if (nolabelGroupInfo == null) {
log.error("Could not process nextObj={} in dev:{}",
nextObj.id(), deviceId);
@@ -1326,7 +1380,7 @@
// Helper Methods and Classes
//////////////////////////////////////
- private void updatePendingNextObjective(GroupKey key, OfdpaNextGroup value) {
+ protected void updatePendingNextObjective(GroupKey key, OfdpaNextGroup value) {
List<OfdpaNextGroup> nextList = new CopyOnWriteArrayList<OfdpaNextGroup>();
nextList.add(value);
List<OfdpaNextGroup> ret = pendingAddNextObjectives.asMap()
@@ -1489,8 +1543,7 @@
* @param portNumber Port number
* @return L2 interface group key
*/
- protected int l2InterfaceGroupKey(
- DeviceId deviceId, VlanId vlanId, long portNumber) {
+ protected int l2InterfaceGroupKey(DeviceId deviceId, VlanId vlanId, long portNumber) {
int portLowerBits = (int) portNumber & PORT_LOWER_BITS_MASK;
long portHigherBits = portNumber & PORT_HIGHER_BITS_MASK;
int hash = Objects.hash(deviceId, vlanId, portHigherBits);
@@ -1544,6 +1597,24 @@
this.innerMostGroupDesc = innerMostGroupDesc;
this.nextGroupDesc = nextGroupDesc;
}
+
+ /**
+ * Getter for innerMostGroupDesc.
+ *
+ * @return the inner most group description
+ */
+ public GroupDescription getInnerMostGroupDesc() {
+ return innerMostGroupDesc;
+ }
+
+ /**
+ * Getter for the next group description.
+ *
+ * @return the next group description
+ */
+ public GroupDescription getNextGroupDesc() {
+ return nextGroupDesc;
+ }
}
/**
@@ -1628,4 +1699,70 @@
" device: " + deviceId);
}
}
+
+ /**
+ * Helper enum to handle the different MPLS group
+ * types.
+ */
+ protected enum OfdpaMplsGroupSubType {
+
+ MPLS_INTF((short) 0),
+
+ L2_VPN((short) 1),
+
+ L3_VPN((short) 2),
+
+ MPLS_TUNNEL_LABEL_1((short) 3),
+
+ MPLS_TUNNEL_LABEL_2((short) 4),
+
+ MPLS_SWAP_LABEL((short) 5),
+
+ MPLS_ECMP((short) 8);
+
+ private short value;
+
+ public static final int OFDPA_GROUP_TYPE_SHIFT = 28;
+ public static final int OFDPA_MPLS_SUBTYPE_SHIFT = 24;
+
+ OfdpaMplsGroupSubType(short value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the value as an short.
+ *
+ * @return the value as an short
+ */
+ public short getValue() {
+ return this.value;
+ }
+
+ }
+
+ /**
+ * Creates MPLS Label group id given a sub type and
+ * the index.
+ *
+ * @param subType the MPLS Label group sub type
+ * @param index the index of the group
+ * @return the OFDPA group id
+ */
+ public Integer makeMplsLabelGroupId(OfdpaMplsGroupSubType subType, int index) {
+ index = index & 0x00FFFFFF;
+ return index | (9 << OFDPA_GROUP_TYPE_SHIFT) | (subType.value << OFDPA_MPLS_SUBTYPE_SHIFT);
+ }
+
+ /**
+ * Creates MPLS Forwarding group id given a sub type and
+ * the index.
+ *
+ * @param subType the MPLS forwarding group sub type
+ * @param index the index of the group
+ * @return the OFDPA group id
+ */
+ public Integer makeMplsForwardingGroupId(OfdpaMplsGroupSubType subType, int index) {
+ index = index & 0x00FFFFFF;
+ return index | (10 << OFDPA_GROUP_TYPE_SHIFT) | (subType.value << OFDPA_MPLS_SUBTYPE_SHIFT);
+ }
}