Driver hooks for making Dell specific changes to push Router MPLS/IP MACs depending on the outgoing packet type
diff --git a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
index 8360374..e3cd0d8 100644
--- a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
+++ b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
@@ -7,7 +7,6 @@
import java.util.Map;
import java.util.Set;
-import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
import net.onrc.onos.core.util.Dpid;
import net.onrc.onos.core.util.PortNumber;
@@ -62,8 +61,14 @@
* neighbors in this set.
*/
public class NeighborSet {
+ public enum groupPktType {
+ IP_OUTGOING,
+ MPLS_OUTGOING
+ };
+
Set<Dpid> dpids;
int edgeLabel;
+ groupPktType outPktType;
/**
* Constructor
@@ -73,6 +78,7 @@
*/
public NeighborSet(Dpid... dpids) {
this.edgeLabel = -1;
+ this.outPktType = groupPktType.IP_OUTGOING;
this.dpids = new HashSet<Dpid>();
for (Dpid d : dpids) {
this.dpids.add(d);
@@ -89,6 +95,8 @@
public void setEdgeLabel(int edgeLabel) {
this.edgeLabel = edgeLabel;
+ if (edgeLabel > 0)
+ this.outPktType = groupPktType.MPLS_OUTGOING;
}
public Set<Dpid> getDpids() {
@@ -99,13 +107,22 @@
return edgeLabel;
}
+ public groupPktType getOutPktType() {
+ return outPktType;
+ }
+
+ public void setOutPktType(groupPktType outPktType) {
+ this.outPktType = outPktType;
+ }
+
@Override
public boolean equals(Object o) {
if (!(o instanceof NeighborSet)) {
return false;
}
NeighborSet that = (NeighborSet) o;
- return (this.dpids.equals(that.dpids) && (this.edgeLabel == that.edgeLabel));
+ return (this.dpids.equals(that.dpids) &&
+ (this.edgeLabel == that.edgeLabel) && (this.outPktType == that.outPktType));
}
@Override
@@ -115,6 +132,7 @@
result = 31 * result + Longs.hashCode(d.value());
}
result = 31 * result + Longs.hashCode(edgeLabel);
+ result = 31 * result + outPktType.hashCode();
return result;
}
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
index 8f7bc48..10324ff 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
@@ -50,8 +50,6 @@
import net.onrc.onos.core.matchaction.action.DecMplsTtlAction;
import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
import net.onrc.onos.core.matchaction.action.GroupAction;
-import net.onrc.onos.core.matchaction.action.ModifyDstMacAction;
-import net.onrc.onos.core.matchaction.action.ModifySrcMacAction;
import net.onrc.onos.core.matchaction.action.OutputAction;
import net.onrc.onos.core.matchaction.action.PopMplsAction;
import net.onrc.onos.core.matchaction.action.PushMplsAction;
@@ -767,8 +765,8 @@
// Output action
if (srcMac != null && dstMac != null) {
- ModifyDstMacAction setDstAction = new ModifyDstMacAction(MACAddress.valueOf(dstMac));
- ModifySrcMacAction setSrcAction = new ModifySrcMacAction(MACAddress.valueOf(srcMac));
+ SetDAAction setDstAction = new SetDAAction(MacAddress.of(dstMac));
+ SetSAAction setSrcAction = new SetSAAction(MacAddress.of(srcMac));
OutputAction outportAction = new OutputAction(PortNumber.uint32(num));
actions.add(setDstAction);
diff --git a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplDellOSR.java b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplDellOSR.java
index 7327c14..d5a0ddb 100644
--- a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplDellOSR.java
+++ b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplDellOSR.java
@@ -1,11 +1,23 @@
package net.onrc.onos.core.drivermanager;
import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import net.floodlightcontroller.core.IOF13Switch.NeighborSet.groupPktType;
+import net.onrc.onos.core.matchaction.MatchAction;
+import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
+import net.onrc.onos.core.matchaction.action.Action;
+import net.onrc.onos.core.matchaction.action.GroupAction;
+import net.onrc.onos.core.matchaction.action.OutputAction;
+import net.onrc.onos.core.matchaction.action.PopMplsAction;
+import net.onrc.onos.core.matchaction.action.SetDAAction;
+import net.onrc.onos.core.matchaction.action.SetMplsBosAction;
import net.onrc.onos.core.matchaction.match.Ipv4Match;
import net.onrc.onos.core.matchaction.match.Match;
import net.onrc.onos.core.util.Dpid;
import net.onrc.onos.core.util.IPv4Net;
+import net.onrc.onos.core.util.PortNumber;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFactory;
@@ -31,6 +43,10 @@
private static final int DELL_TABLE_MPLS = 25;
private static final int DELL_TABLE_ACL = 40;
+ private static final int MPLS_SWAP_FLOW = 0x00;
+ private static final int MPLS_POP_NO_BOS_FLOW = 0x10;
+ private static final int MPLS_POP_BOS_FLOW = 0x11;
+
public OFSwitchImplDellOSR(OFDescStatsReply desc, boolean usePipeline13) {
super(desc, usePipeline13);
setVlanTableId(DELL_TABLE_VLAN);
@@ -73,6 +89,14 @@
populateTableMissEntry(aclTableId, true, false, false, -1);
}
+ protected MacAddress getNeighborRouterMacAddress(Dpid ndpid,
+ groupPktType outPktType) {
+ if (outPktType == groupPktType.MPLS_OUTGOING)
+ return getRouterMPLSMac(ndpid);
+ else
+ return super.getNeighborRouterMacAddress(ndpid,
+ groupPktType.IP_OUTGOING);
+ }
/* Dell Open Segment Router specific Implementation .
* Gets the specified Router's MAC address to be used for MPLS flows
* For Dell OSR, the MPLS MAC is IP MAC + 1
@@ -82,4 +106,71 @@
return MacAddress.of(super.getRouterIPMac(dpid).getLong() + 1);
}
+ protected void createGroupsAtTransitRouter(Set<Dpid> dpids) {
+ /* Create all possible Neighbor sets from this router
+ * NOTE: Avoid any pairings of edge routers only
+ */
+ Set<Set<Dpid>> sets = getPowerSetOfNeighbors(dpids);
+ sets = filterEdgeRouterOnlyPairings(sets);
+ log.debug("createGroupsAtTransitRouter: The size of neighbor powerset "
+ + "for sw {} is {}", getStringId(), sets.size());
+ Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
+ for (Set<Dpid> combo : sets) {
+ if (combo.isEmpty())
+ continue;
+ for (groupPktType gType : groupPktType.values()) {
+ NeighborSet ns = new NeighborSet();
+ ns.addDpids(combo);
+ ns.setOutPktType(gType);
+ log.debug("createGroupsAtTransitRouter: sw {} combo {} ns {}",
+ getStringId(), combo, ns);
+ nsSet.add(ns);
+ }
+ }
+ log.debug("createGroupsAtTransitRouter: The neighborset with label "
+ + "for sw {} is {}", getStringId(), nsSet);
+
+ for (NeighborSet ns : nsSet) {
+ updatePortNeighborSetMap(ns);
+ int gid = createGroupForANeighborSet(ns);
+ if (gid == -1) {
+ log.warn("Create Group failed with -1");
+ }
+ }
+ }
+
+ protected void analyzeAndUpdateMplsActions(
+ MatchActionOperationEntry mao) {
+ MatchAction ma = mao.getTarget();
+ int flowType = 0x00;
+ PortNumber outPort = null;
+ for (Action action : ma.getActions()) {
+ if (action instanceof PopMplsAction)
+ flowType |= 0x10;
+ else if (action instanceof SetMplsBosAction)
+ flowType |= 0x01;
+ else if (action instanceof OutputAction)
+ outPort = ((OutputAction) action).getPortNumber();
+ }
+
+ groupPktType outPktType = groupPktType.IP_OUTGOING;
+ if ((flowType == MPLS_SWAP_FLOW) ||
+ (flowType == MPLS_POP_NO_BOS_FLOW))
+ outPktType = groupPktType.MPLS_OUTGOING;
+
+ for (Action action : ma.getActions()) {
+ if ((action instanceof GroupAction)
+ && (((GroupAction) action).getGroupId() == -1)) {
+ ((GroupAction) action).getDpids().setOutPktType(outPktType);
+ }
+ else if (action instanceof SetDAAction) {
+ if ((outPort != null) &&
+ (portToNeighbors.get(outPort) != null)) {
+ Dpid neighborDpid = portToNeighbors.get(outPort);
+ ((SetDAAction) action).setAddress(
+ getNeighborRouterMacAddress(neighborDpid, outPktType));
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplSpringOpenTTP.java b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplSpringOpenTTP.java
index 2f92d49..382513e 100644
--- a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplSpringOpenTTP.java
+++ b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplSpringOpenTTP.java
@@ -17,6 +17,7 @@
import net.floodlightcontroller.core.IFloodlightProviderService.Role;
import net.floodlightcontroller.core.IOF13Switch;
+import net.floodlightcontroller.core.IOF13Switch.NeighborSet.groupPktType;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.SwitchDriverSubHandshakeAlreadyStarted;
import net.floodlightcontroller.core.SwitchDriverSubHandshakeCompleted;
@@ -112,7 +113,7 @@
public class OFSwitchImplSpringOpenTTP extends OFSwitchImplBase implements IOF13Switch {
private AtomicBoolean driverHandshakeComplete;
private AtomicBoolean haltStateMachine;
- private OFFactory factory;
+ protected OFFactory factory;
private static final int OFPCML_NO_BUFFER = 0xffff;
// Configuration of asynch messages to controller. We need different
// asynch messages depending on role-equal or role-master.
@@ -143,8 +144,8 @@
private DriverState driverState;
private final boolean usePipeline13;
private SegmentRouterConfig srConfig;
- private ConcurrentMap<Dpid, Set<PortNumber>> neighbors;
- private ConcurrentMap<PortNumber, Dpid> portToNeighbors;
+ protected ConcurrentMap<Dpid, Set<PortNumber>> neighbors;
+ protected ConcurrentMap<PortNumber, Dpid> portToNeighbors;
private List<Integer> segmentIds;
private boolean isEdgeRouter;
private ConcurrentMap<NeighborSet, EcmpInfo> ecmpGroups;
@@ -347,7 +348,7 @@
}
BucketInfo b = new BucketInfo(neighborDpid,
MacAddress.of(srConfig.getRouterMac()),
- getNeighborRouterMacAddress(neighborDpid),
+ getNeighborRouterMacAddress(neighborDpid, ns.getOutPktType()),
port,
ns.getEdgeLabel(), true, -1);
buckets.add(b);
@@ -800,9 +801,15 @@
}
}
+ /* Base implementation returns the configured router MAC only */
+ protected MacAddress getNeighborRouterMacAddress(Dpid ndpid,
+ groupPktType outPktType) {
+ return getNeighborRouterMacAddress(ndpid);
+ }
+
/* Default implementation of this interface.
* Gets the specified Router's MAC address to be used for IP flows
- * To be overridden depending on the underlying switch type
+ * To be overridden depending on the underlying switch type
*/
public MacAddress getRouterIPMac(Dpid dpid) {
return getNeighborRouterMacAddress(dpid);
@@ -810,7 +817,7 @@
/* Default implementation of this interface.
* Gets the specified Router's MAC address to be used for MPLS flows
- * To be overridden depending on the underlying switch type
+ * To be overridden depending on the underlying switch type
*/
public MacAddress getRouterMPLSMac(Dpid dpid) {
return getNeighborRouterMacAddress(dpid);
@@ -873,7 +880,7 @@
}
}
- private Set<Set<Dpid>> getAllNeighborSets(Set<Dpid> neighbors) {
+ protected Set<Set<Dpid>> getPowerSetOfNeighbors(Set<Dpid> neighbors) {
List<Dpid> list = new ArrayList<Dpid>(neighbors);
Set<Set<Dpid>> sets = new HashSet<Set<Dpid>>();
/* get the number of elements in the neighbors */
@@ -893,27 +900,43 @@
dpidSubSet.add(list.get(j));
}
}
- /* NOTE: Avoid any pairings of edge routers only
- * at a backbone router */
- boolean avoidEdgeRouterPairing = true;
- if ((!isEdgeRouter) && (dpidSubSet.size() > 1)) {
+ sets.add(dpidSubSet);
+ }
+ return sets;
+ }
+
+ protected Set<Set<Dpid>> filterEdgeRouterOnlyPairings(Set<Set<Dpid>> sets) {
+ Set<Set<Dpid>> fiteredSets = new HashSet<Set<Dpid>>();
+ for (Set<Dpid> dpidSubSet : sets) {
+ if (dpidSubSet.size() > 1) {
+ boolean avoidEdgeRouterPairing = true;
for (Dpid dpid : dpidSubSet) {
if (!isEdgeRouter(dpid)) {
avoidEdgeRouterPairing = false;
break;
}
}
+ if (!avoidEdgeRouterPairing)
+ fiteredSets.add(dpidSubSet);
}
else
- avoidEdgeRouterPairing = false;
+ fiteredSets.add(dpidSubSet);
- if (!avoidEdgeRouterPairing)
- sets.add(dpidSubSet);
+ }
+ return fiteredSets;
+ }
+
+ private Set<Set<Dpid>> getAllNeighborSets(Set<Dpid> neighbors) {
+ Set<Set<Dpid>> sets = getPowerSetOfNeighbors(neighbors);
+ if (!isEdgeRouter) {
+ /* NOTE: Avoid any pairings of edge routers only
+ * at a backbone router */
+ sets = filterEdgeRouterOnlyPairings(sets);
}
return sets;
}
- private int createGroupForANeighborSet(NeighborSet ns) {
+ protected int createGroupForANeighborSet(NeighborSet ns) {
int groupId = -1;
List<BucketInfo> buckets = new ArrayList<BucketInfo>();
for (Dpid d : ns.getDpids()) {
@@ -921,8 +944,8 @@
if (portEnabled((int) sp.value())) {
BucketInfo b = new BucketInfo(d,
MacAddress.of(srConfig.getRouterMac()),
- getNeighborRouterMacAddress(d), sp,
- ns.getEdgeLabel(), true, -1);
+ getNeighborRouterMacAddress(d, ns.getOutPktType()),
+ sp, ns.getEdgeLabel(), true, -1);
buckets.add(b);
}
}
@@ -964,6 +987,107 @@
}
}
+ protected List<Integer> getSegmentIdsTobePairedWithNeighborSet(
+ Set<Dpid> dpids) {
+
+ List<Integer> nsSegmentIds = new ArrayList<Integer>();
+
+ /* Add one entry for "no label" (-1) to the list if
+ * dpid list has not more than one node/neighbor as
+ * there will never be a case a packet going to more than one
+ * neighbor without a label at an edge router
+ */
+ if (dpids.size() == 1) {
+ nsSegmentIds.add(-1);
+ }
+ if (!segmentIds.isEmpty()) {
+ /* Filter out SegmentIds matching with the
+ * nodes in the combo
+ */
+ for (Integer sId : segmentIds) {
+ boolean filterOut = false;
+ /* Check if the edge label being set is of
+ * any node in the Neighbor set
+ */
+ for (Dpid dpid : dpids) {
+ if (isSegmentIdSameAsNodeSegmentId(dpid, sId)) {
+ filterOut = true;
+ break;
+ }
+ }
+ if (!filterOut)
+ nsSegmentIds.add(sId);
+ }
+ }
+
+ return nsSegmentIds;
+ }
+
+ protected void createGroupsAtEdgeRouter(Set<Dpid> dpids) {
+ /* Create all possible Neighbor sets from this router
+ */
+ Set<Set<Dpid>> powerSet = getPowerSetOfNeighbors(dpids);
+ log.debug("createGroupsAtEdgeRouter: The size of neighbor powerset "
+ + "for sw {} is {}", getStringId(), powerSet.size());
+ Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
+ for (Set<Dpid> combo : powerSet) {
+ if (combo.isEmpty())
+ continue;
+ List<Integer> groupSegmentIds =
+ getSegmentIdsTobePairedWithNeighborSet(combo);
+ if (!groupSegmentIds.isEmpty()) {
+ for (Integer sId : groupSegmentIds) {
+ NeighborSet ns = new NeighborSet();
+ ns.addDpids(combo);
+ ns.setEdgeLabel(sId);
+ log.debug("createGroupsAtEdgeRouter: sw {} combo {} sId {} ns {}",
+ getStringId(), combo, sId, ns);
+ nsSet.add(ns);
+ }
+ }
+ }
+ log.debug("createGroupsAtEdgeRouter: The neighborset with label for sw {} is {}",
+ getStringId(), nsSet);
+
+ for (NeighborSet ns : nsSet) {
+ updatePortNeighborSetMap(ns);
+ int gid = createGroupForANeighborSet(ns);
+ if (gid == -1) {
+ log.warn("Create Group failed with -1");
+ }
+ }
+ }
+
+ protected void createGroupsAtTransitRouter(Set<Dpid> dpids) {
+ /* Create all possible Neighbor sets from this router
+ * NOTE: Avoid any pairings of edge routers only
+ */
+ Set<Set<Dpid>> sets = getPowerSetOfNeighbors(dpids);
+ sets = filterEdgeRouterOnlyPairings(sets);
+ log.debug("createGroupsAtTransitRouter: The size of neighbor powerset "
+ + "for sw {} is {}", getStringId(), sets.size());
+ Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
+ for (Set<Dpid> combo : sets) {
+ if (combo.isEmpty())
+ continue;
+ NeighborSet ns = new NeighborSet();
+ ns.addDpids(combo);
+ log.debug("createGroupsAtTransitRouter: sw {} combo {} ns {}",
+ getStringId(), combo, ns);
+ nsSet.add(ns);
+ }
+ log.debug("createGroupsAtTransitRouter: The neighborset with label "
+ + "for sw {} is {}", getStringId(), nsSet);
+
+ for (NeighborSet ns : nsSet) {
+ updatePortNeighborSetMap(ns);
+ int gid = createGroupForANeighborSet(ns);
+ if (gid == -1) {
+ log.warn("Create Group failed with -1");
+ }
+ }
+ }
+
/**
* createGroups creates ECMP groups for all ports on this router connected
* to other routers (in the OF network). The information for ports is
@@ -991,63 +1115,12 @@
if (dpids == null || dpids.isEmpty()) {
return;
}
- /* Create all possible Neighbor sets from this router
- * NOTE: Avoid any pairings of edge routers only
- */
- Set<Set<Dpid>> powerSet = getAllNeighborSets(dpids);
- log.debug("createGroups: The size of neighbor powerset for sw {} is {}",
- getStringId(), powerSet.size());
- Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
- for (Set<Dpid> combo : powerSet) {
- if (combo.isEmpty())
- continue;
- if (isEdgeRouter && !segmentIds.isEmpty()) {
- /* Filter out SegmentIds matching with the
- * nodes in the combo
- * Add one entry for "no label" (-1) to the list
- */
- List<Integer> groupSegmentIds = new ArrayList<Integer>();
- groupSegmentIds.add(-1);
- for (Integer sId : segmentIds) {
- boolean filterOut = false;
- /* Check if the edge label being set is of
- * any node in the Neighbor set
- */
- for (Dpid dpid : combo) {
- if (isSegmentIdSameAsNodeSegmentId(dpid, sId)) {
- filterOut = true;
- break;
- }
- }
- if (!filterOut)
- groupSegmentIds.add(sId);
- }
- for (Integer sId : groupSegmentIds) {
- NeighborSet ns = new NeighborSet();
- ns.addDpids(combo);
- ns.setEdgeLabel(sId);
- log.debug("createGroups: sw {} combo {} sId {} ns {}",
- getStringId(), combo, sId, ns);
- nsSet.add(ns);
- }
- } else {
- NeighborSet ns = new NeighborSet();
- ns.addDpids(combo);
- log.debug("createGroups: sw {} combo {} ns {}",
- getStringId(), combo, ns);
- nsSet.add(ns);
- }
- }
- log.debug("createGroups: The neighborset with label for sw {} is {}",
- getStringId(), nsSet);
- for (NeighborSet ns : nsSet) {
- updatePortNeighborSetMap(ns);
- int gid = createGroupForANeighborSet(ns);
- if (gid == -1) {
- log.warn("Create Group failed with -1");
- }
+ if (isEdgeRouter) {
+ createGroupsAtEdgeRouter(dpids);
}
+ else
+ createGroupsAtTransitRouter(dpids);
}
private class EcmpInfo {
@@ -1528,7 +1601,16 @@
return ipFlow;
}
+ protected void analyzeAndUpdateMplsActions(
+ MatchActionOperationEntry mao) {
+ /* For base switch implementation, use the MPLS actions
+ * as specified by the application
+ */
+ return;
+ }
+
private OFMessage getMplsEntry(MatchActionOperationEntry mao) {
+ analyzeAndUpdateMplsActions(mao);
MatchAction ma = mao.getTarget();
Operator op = mao.getOperator();
MplsMatch mplsm = (MplsMatch) ma.getMatch();
diff --git a/src/main/java/net/onrc/onos/core/matchaction/action/SetDAAction.java b/src/main/java/net/onrc/onos/core/matchaction/action/SetDAAction.java
index 6a28e7b..8209ec0 100644
--- a/src/main/java/net/onrc/onos/core/matchaction/action/SetDAAction.java
+++ b/src/main/java/net/onrc/onos/core/matchaction/action/SetDAAction.java
@@ -12,4 +12,8 @@
public MacAddress getAddress() {
return this.macAddress;
}
+
+ public void setAddress(MacAddress macAddress) {
+ this.macAddress = macAddress;
+ }
}