ECMP group creation that includes the edge labels
diff --git a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
index b8251e5..6cb5b15 100644
--- a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
+++ b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
@@ -50,12 +50,14 @@
// ****************************
/**
- * Representation of a set of neighbor switch dpids. Meant to be used as a
- * lookup-key in a hash-map to retrieve an ECMP-group that hashes packets to
- * a set of ports connecting to the neighbors in this set.
+ * Representation of a set of neighbor switch dpids along with edge node
+ * label. Meant to be used as a lookup-key in a hash-map to retrieve an
+ * ECMP-group that hashes packets to a set of ports connecting to the
+ * neighbors in this set.
*/
public class NeighborSet {
Set<Dpid> dpids;
+ int edgeLabel;
/**
* Constructor
@@ -64,6 +66,7 @@
* switches
*/
public NeighborSet(Dpid... dpids) {
+ this.edgeLabel = -1;
this.dpids = new HashSet<Dpid>();
for (Dpid d : dpids) {
this.dpids.add(d);
@@ -74,13 +77,29 @@
dpids.add(d);
}
+ public void addDpids(Set<Dpid> d) {
+ dpids.addAll(d);
+ }
+
+ public void setEdgeLabel(int edgeLabel) {
+ this.edgeLabel = edgeLabel;
+ }
+
+ public Set<Dpid> getDpids() {
+ return dpids;
+ }
+
+ public int getEdgeLabel() {
+ return edgeLabel;
+ }
+
@Override
public boolean equals(Object o) {
if (!(o instanceof NeighborSet)) {
return false;
}
NeighborSet that = (NeighborSet) o;
- return this.dpids.equals(that.dpids);
+ return (this.dpids.equals(that.dpids) && (this.edgeLabel == that.edgeLabel));
}
@Override
@@ -89,12 +108,13 @@
for (Dpid d : dpids) {
result = 31 * result + Longs.hashCode(d.value());
}
+ result = 31 * result + Longs.hashCode(edgeLabel);
return result;
}
@Override
public String toString() {
- return " Sw: {} Neighbors: " + dpids;
+ return " Neighborset Sw: " + dpids + " and Label: " + edgeLabel;
}
}
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 a3c52fe..8dae594 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
@@ -844,6 +844,7 @@
}
GroupAction groupAction = new GroupAction();
+ groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
for (String fwdSw : fwdToSws) {
groupAction.addSwitch(new Dpid(fwdSw));
@@ -936,6 +937,7 @@
}
}
GroupAction groupAction = new GroupAction();
+ groupAction.setEdgeLabel(Integer.parseInt(mplsLabel));
for (String fwdSw : fwdSws)
groupAction.addSwitch(new Dpid(fwdSw));
actions.add(groupAction);
diff --git a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
index f434ca2..9a4519d 100644
--- a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
+++ b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
@@ -24,6 +24,7 @@
import net.onrc.onos.core.configmanager.INetworkConfigService.NetworkConfigState;
import net.onrc.onos.core.configmanager.INetworkConfigService.SwitchConfigStatus;
import net.onrc.onos.core.configmanager.NetworkConfig.LinkConfig;
+import net.onrc.onos.core.configmanager.NetworkConfig.SwitchConfig;
import net.onrc.onos.core.configmanager.NetworkConfigManager;
import net.onrc.onos.core.configmanager.PktLinkConfig;
import net.onrc.onos.core.configmanager.SegmentRouterConfig;
@@ -41,8 +42,6 @@
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;
-import net.onrc.onos.core.matchaction.action.SetMplsIdAction;
import net.onrc.onos.core.matchaction.match.Ipv4Match;
import net.onrc.onos.core.matchaction.match.Match;
import net.onrc.onos.core.matchaction.match.MplsMatch;
@@ -90,8 +89,6 @@
import org.projectfloodlight.openflow.types.U32;
import org.projectfloodlight.openflow.util.HexString;
-import com.google.common.collect.Sets;
-
/**
* OFDescriptionStatistics Vendor (Manufacturer Desc.): Stanford University,
* Ericsson Research and CPqD Research. Make (Hardware Desc.) : OpenFlow 1.3
@@ -133,6 +130,8 @@
private final boolean usePipeline13;
private SegmentRouterConfig srConfig;
private ConcurrentMap<Dpid, Set<PortNumber>> neighbors;
+ private List<Integer> edgeLabels;
+ private boolean isEdgeRouter;
private ConcurrentMap<NeighborSet, EcmpInfo> ecmpGroups;
private ConcurrentMap<PortNumber, ArrayList<NeighborSet>> portNeighborSetMap;
@@ -148,6 +147,8 @@
ecmpGroups = new ConcurrentHashMap<NeighborSet, EcmpInfo>();
portNeighborSetMap =
new ConcurrentHashMap<PortNumber, ArrayList<NeighborSet>>();
+ edgeLabels = new ArrayList<Integer>();
+ isEdgeRouter = false;
this.usePipeline13 = usePipeline13;
}
@@ -517,12 +518,18 @@
SwitchConfigStatus scs = ncs.checkSwitchConfig(new Dpid(getId()));
if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
srConfig = (SegmentRouterConfig) scs.getSwitchConfig();
+ isEdgeRouter = srConfig.isEdgeRouter();
} else {
log.error("Switch not configured as Segment-Router");
}
List<LinkConfig> linkConfigList = ncs.getConfiguredAllowedLinks();
setNeighbors(linkConfigList);
+
+ if (isEdgeRouter) {
+ List<SwitchConfig> switchList = ncs.getConfiguredAllowedSwitches();
+ getAllEdgeLabels(switchList);
+ }
}
private void populateTableVlan() throws IOException {
@@ -633,6 +640,17 @@
}
}
+ private boolean isEdgeRouter(Dpid ndpid) {
+ INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
+ SwitchConfigStatus scs = ncs.checkSwitchConfig(ndpid);
+ if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
+ return ((SegmentRouterConfig) scs.getSwitchConfig()).isEdgeRouter();
+ } else {
+ // TODO: return false if router not allowed
+ return false;
+ }
+ }
+
private MacAddress getNeighborRouterMacAddress(Dpid ndpid) {
INetworkConfigService ncs = floodlightProvider.getNetworkConfigService();
SwitchConfigStatus scs = ncs.checkSwitchConfig(ndpid);
@@ -671,6 +689,46 @@
}
}
+ private void getAllEdgeLabels(List<SwitchConfig> switchList) {
+ for (SwitchConfig sc : switchList) {
+ /* TODO: Do we need to check if the SwitchConfig is of
+ * type SegmentRouter?
+ */
+ if ((sc.getDpid() == getId()) ||
+ (((SegmentRouterConfig) sc).isEdgeRouter() != true)) {
+ continue;
+ }
+ edgeLabels.add(((SegmentRouterConfig) sc).getNodeSid());
+ }
+ }
+
+ private Set<Set<Dpid>> getAllNeighborSets(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 */
+ int elements = list.size();
+ /* the number of members of a power set is 2^n
+ * including the empty set
+ */
+ int powerElements = (1 << elements);
+
+ /* run a binary counter for the number of power elements */
+ for (long i = 1; i < powerElements; i++) {
+ Set<Dpid> dpidSubSet = new HashSet<Dpid>();
+ boolean allEdgeRouters = true;
+ for (int j = 0; j < elements; j++) {
+ if ((i >> j) % 2 == 1) {
+ dpidSubSet.add(list.get(j));
+ if (!isEdgeRouter(list.get(j)))
+ allEdgeRouters = false;
+ }
+ }
+ if (!allEdgeRouters)
+ sets.add(dpidSubSet);
+ }
+ return sets;
+ }
+
/**
* createGroups creates ECMP groups for all ports on this router connected
* to other routers (in the OF network). The information for ports is
@@ -697,32 +755,38 @@
if (dpids == null || dpids.isEmpty()) {
return;
}
- // temp map of ecmp groupings
- /* Map<NeighborSet, List<BucketInfo>> temp =
- new HashMap<NeighborSet, List<BucketInfo>>();
- */
- // get all combinations of neighbors
- Set<Set<Dpid>> powerSet = Sets.powerSet(dpids);
- int groupid = 1;
+ /* Create all possible Neighbor sets from this router
+ * NOTE: Avoid any pairings of edge routers only
+ */
+ Set<Set<Dpid>> powerSet = getAllNeighborSets(dpids);
+ Set<NeighborSet> nsSet = new HashSet<NeighborSet>();
for (Set<Dpid> combo : powerSet) {
- if (combo.isEmpty()) {
- // eliminate the empty set in the power set
- continue;
+ if (isEdgeRouter && !edgeLabels.isEmpty()) {
+ for (Integer edgeLabel : edgeLabels) {
+ NeighborSet ns = new NeighborSet();
+ ns.addDpids(combo);
+ ns.setEdgeLabel(edgeLabel);
+ nsSet.add(ns);
+ }
+ } else {
+ NeighborSet ns = new NeighborSet();
+ ns.addDpids(combo);
+ nsSet.add(ns);
}
+ }
+
+ int groupid = 1;
+ for (NeighborSet ns : nsSet) {
List<BucketInfo> buckets = new ArrayList<BucketInfo>();
- NeighborSet ns = new NeighborSet();
- for (Dpid d : combo) {
- ns.addDpid(d);
+ for (Dpid d : ns.getDpids()) {
for (PortNumber sp : neighbors.get(d)) {
BucketInfo b = new BucketInfo(d,
MacAddress.of(srConfig.getRouterMac()),
- getNeighborRouterMacAddress(d), sp);
+ getNeighborRouterMacAddress(d), sp,
+ ns.getEdgeLabel());
buckets.add(b);
- }
- }
- for (Dpid d : combo) {
- for (PortNumber sp : neighbors.get(d)) {
+ /* Update Port Neighborset map */
ArrayList<NeighborSet> portNeighborSets =
portNeighborSetMap.get(sp);
if (portNeighborSets == null) {
@@ -734,12 +798,17 @@
portNeighborSets.add(ns);
}
}
-
EcmpInfo ecmpInfo = new EcmpInfo(groupid++, buckets);
setEcmpGroup(ecmpInfo);
ecmpGroups.put(ns, ecmpInfo);
- log.debug("Creating ecmp group in sw {}: {}", getStringId(), ecmpInfo);
+ log.debug("Creating ecmp group in sw {} for neighbor set {}: {}",
+ getStringId(), ns, ecmpInfo);
}
+
+ // temp map of ecmp groupings
+ /* Map<NeighborSet, List<BucketInfo>> temp =
+ new HashMap<NeighborSet, List<BucketInfo>>();
+ */
}
private class EcmpInfo {
@@ -762,18 +831,22 @@
MacAddress srcMac;
MacAddress dstMac;
PortNumber outport;
+ int mplsLabel;
- BucketInfo(Dpid nDpid, MacAddress smac, MacAddress dmac, PortNumber p) {
+ BucketInfo(Dpid nDpid, MacAddress smac, MacAddress dmac,
+ PortNumber p, int label) {
neighborDpid = nDpid;
srcMac = smac;
dstMac = dmac;
outport = p;
+ mplsLabel = label;
}
@Override
public String toString() {
return " {neighborDpid: " + neighborDpid + ", dstMac: " + dstMac +
- ", srcMac: " + srcMac + ", outport: " + outport + "}";
+ ", srcMac: " + srcMac + ", outport: " + outport +
+ "mplsLabel: " + mplsLabel + "}";
}
}
@@ -798,6 +871,18 @@
actions.add(setSA);
actions.add(setDA);
actions.add(outp);
+ if (b.mplsLabel != -1) {
+ OFAction pushLabel = factory.actions().buildPushMpls()
+ .setEthertype(EthType.MPLS_UNICAST).build();
+ OFAction setLabel = factory.actions().buildSetMplsLabel()
+ .setMplsLabel(b.mplsLabel).build();
+ OFAction copyTtl = factory.actions().copyTtlOut();
+ OFAction decrTtl = factory.actions().decMplsTtl();
+ actions.add(pushLabel);
+ actions.add(setLabel);
+ actions.add(copyTtl);
+ actions.add(decrTtl);
+ }
OFBucket ofb = factory.buildBucket()
.setWeight(1)
.setActions(actions)
@@ -841,6 +926,18 @@
actions.add(setSA);
actions.add(setDA);
actions.add(outp);
+ if (b.mplsLabel != -1) {
+ OFAction pushLabel = factory.actions().buildPushMpls()
+ .setEthertype(EthType.MPLS_UNICAST).build();
+ OFAction setLabel = factory.actions().buildSetMplsLabel()
+ .setMplsLabel(b.mplsLabel).build();
+ OFAction copyTtl = factory.actions().copyTtlOut();
+ OFAction decrTtl = factory.actions().decMplsTtl();
+ actions.add(pushLabel);
+ actions.add(setLabel);
+ actions.add(copyTtl);
+ actions.add(decrTtl);
+ }
OFBucket ofb = factory.buildBucket()
.setWeight(1)
.setActions(actions)
@@ -902,15 +999,15 @@
.ethSrc(MacAddress.of(srcMac));
ofAction = factory.actions().buildSetField()
.setField(smac).build();
- } else if (action instanceof PushMplsAction) {
- ofAction = factory.actions().pushMpls(EthType.MPLS_UNICAST);
- } else if (action instanceof SetMplsIdAction) {
- int labelid = ((SetMplsIdAction) action).getMplsId();
- OFOxmMplsLabel lid = factory.oxms()
- .mplsLabel(U32.of(labelid));
- ofAction = factory.actions().buildSetField()
- .setField(lid).build();
- } else if (action instanceof PopMplsAction) {
+ /*} else if (action instanceof PushMplsAction) {
+ ofAction = factory.actions().pushMpls(EthType.MPLS_UNICAST);
+ } else if (action instanceof SetMplsIdAction) {
+ int labelid = ((SetMplsIdAction) action).getMplsId();
+ OFOxmMplsLabel lid = factory.oxms()
+ .mplsLabel(U32.of(labelid));
+ ofAction = factory.actions().buildSetField()
+ .setField(lid).build();
+ */} else if (action instanceof PopMplsAction) {
EthType ethertype = ((PopMplsAction) action).getEthType();
ofAction = factory.actions().popMpls(ethertype);
} else if (action instanceof GroupAction) {
diff --git a/src/main/java/net/onrc/onos/core/matchaction/action/GroupAction.java b/src/main/java/net/onrc/onos/core/matchaction/action/GroupAction.java
index 5dfdfae..642e87a 100644
--- a/src/main/java/net/onrc/onos/core/matchaction/action/GroupAction.java
+++ b/src/main/java/net/onrc/onos/core/matchaction/action/GroupAction.java
@@ -14,6 +14,10 @@
fwdSws.addDpid(d);
}
+ public void setEdgeLabel(int edgeLabel) {
+ fwdSws.setEdgeLabel(edgeLabel);
+ }
+
public NeighborSet getDpids() {
return fwdSws;
}