Support for MPLS Swap Group creation.
Modified the processSimpleNextObjective method to be able to create the
Group chain MPLS Swap - MPLS Interface - L2 Interface , when the MPLS Label
is set to the Treatment.
Change-Id: I72d502ba2f0da811d14d28c170d2e119c3dc8221
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java
index 38cc72b..f9c9f22 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java
@@ -87,6 +87,7 @@
import static org.onosproject.net.flow.criteria.Criterion.Type.TUNNEL_ID;
import static org.onosproject.net.flow.criteria.Criterion.Type.VLAN_VID;
import static org.onosproject.net.group.GroupDescription.Type.ALL;
+import static org.onosproject.net.group.GroupDescription.Type.INDIRECT;
import static org.onosproject.net.group.GroupDescription.Type.SELECT;
import static org.slf4j.LoggerFactory.getLogger;
@@ -247,23 +248,34 @@
* a chain of groups. The simple Next Objective passed
* in by the application has to be broken up into a group chain
* comprising of an L3 Unicast Group that points to an L2 Interface
- * Group which in-turn points to an output port. In some cases, the simple
+ * Group which in-turn points to an output port or an MPLS Interface Group
+ * that points to an L2 Interface Group. In some cases, the simple
* next Objective can just be an L2 interface without the need for chaining.
+ * Further, if the label is set to the Next objective then the Group chain
+ * MPLS Swap - MPLS Interface - L2 Interface is created
*
* @param nextObj the nextObjective of type SIMPLE
*/
private void processSimpleNextObjective(NextObjective nextObj) {
TrafficTreatment treatment = nextObj.next().iterator().next();
- // determine if plain L2 or L3->L2
+ // determine if plain L2 or L3->L2 or MPLS Swap -> MPLS Interface -> L2
boolean plainL2 = true;
+ boolean mplsSwap = false;
+ MplsLabel mplsLabel = null;
for (Instruction ins : treatment.allInstructions()) {
if (ins.type() == Instruction.Type.L2MODIFICATION) {
L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
if (l2ins.subtype() == L2ModificationInstruction.L2SubType.ETH_DST ||
l2ins.subtype() == L2ModificationInstruction.L2SubType.ETH_SRC) {
plainL2 = false;
- break;
}
+ // mpls label in simple next objectives is used only to indicate
+ // a MPLS Swap group before the MPLS Interface Group
+ if (l2ins.subtype() == L2ModificationInstruction.L2SubType.MPLS_LABEL) {
+ mplsSwap = true;
+ mplsLabel = ((L2ModificationInstruction.ModMplsLabelInstruction) l2ins).label();
+ }
+
}
}
@@ -288,13 +300,59 @@
}
- if (!isPw) {
+ if (mplsSwap) {
+ log.debug("Creating a MPLS Swap - MPLS Interface - L2 Interface group chain.");
+
+ // break up simple next objective to GroupChain objects
+ GroupInfo groupInfo = createL2L3Chain(treatment, nextObj.id(),
+ nextObj.appId(), true,
+ nextObj.meta());
+ if (groupInfo == null) {
+ log.error("Could not process nextObj={} in dev:{}", nextObj.id(), deviceId);
+ fail(nextObj, ObjectiveError.BADPARAMS);
+ return;
+ }
+
+ Deque<GroupKey> gkeyChain = new ArrayDeque<>();
+ gkeyChain.addFirst(groupInfo.innerMostGroupDesc().appCookie());
+ gkeyChain.addFirst(groupInfo.nextGroupDesc().appCookie());
+
+ // creating the mpls swap group and adding it to the chain
+ GroupChainElem groupChainElem;
+ GroupKey groupKey;
+ GroupDescription groupDescription;
+ int nextGid = groupInfo.nextGroupDesc().givenGroupId();
+ int index = getNextAvailableIndex();
+
+ groupDescription = createMplsSwap(
+ nextGid,
+ OfdpaMplsGroupSubType.MPLS_SWAP_LABEL,
+ index,
+ mplsLabel,
+ nextObj.appId()
+ );
+
+ groupKey = new DefaultGroupKey(Ofdpa2Pipeline.appKryo.serialize(index));
+ groupChainElem = new GroupChainElem(groupDescription, 1, false, deviceId);
+ updatePendingGroups(groupInfo.nextGroupDesc().appCookie(), groupChainElem);
+ gkeyChain.addFirst(groupKey);
+
+ // create a new List from singletonList that is mutable
+ OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(Collections.singletonList(gkeyChain), nextObj);
+ updatePendingNextObjective(groupInfo.nextGroupDesc().appCookie(), ofdpaGrp);
+
+ // now we are ready to send the l2 groupDescription (inner), as all the stores
+ // that will get async replies have been updated. By waiting to update
+ // the stores, we prevent nasty race conditions.
+ groupService.addGroup(groupInfo.innerMostGroupDesc());
+ } else if (!isPw) {
// break up simple next objective to GroupChain objects
GroupInfo groupInfo = createL2L3Chain(treatment, nextObj.id(),
nextObj.appId(), isMpls,
nextObj.meta());
if (groupInfo == null) {
log.error("Could not process nextObj={} in dev:{}", nextObj.id(), deviceId);
+ fail(nextObj, ObjectiveError.BADPARAMS);
return;
}
// create object for local and distributed storage
@@ -352,6 +410,45 @@
}
/**
+ * Creates an Mpls group of type swap.
+ *
+ * @param nextGroupId the next group in the chain
+ * @param subtype the mpls swap label group subtype
+ * @param index the index of the group
+ * @param mplsLabel the mpls label to swap
+ * @param applicationId the application id
+ * @return the group description
+ */
+ protected GroupDescription createMplsSwap(int nextGroupId,
+ OfdpaMplsGroupSubType subtype,
+ int index,
+ MplsLabel mplsLabel,
+ ApplicationId applicationId) {
+
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+
+ treatment.setMpls(mplsLabel);
+
+ // We point the group to the next group.
+ treatment.group(new GroupId(nextGroupId));
+ GroupBucket groupBucket = DefaultGroupBucket
+ .createIndirectGroupBucket(treatment.build());
+ // Finally we build the group description.
+ int groupId = makeMplsLabelGroupId(subtype, index);
+ GroupKey groupKey = new DefaultGroupKey(
+ Ofdpa2Pipeline.appKryo.serialize(index)
+ );
+ return new DefaultGroupDescription(
+ deviceId,
+ INDIRECT,
+ new GroupBuckets(Collections.singletonList(groupBucket)),
+ groupKey,
+ groupId,
+ applicationId
+ );
+ }
+
+ /**
* Creates one of two possible group-chains from the treatment
* passed in. Depending on the MPLS boolean, this method either creates
* an L3Unicast Group --> L2Interface Group, if mpls is false;