Tunnel loadbalancing policy: phase1 support
diff --git a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
index 04e2a8d..3eaf58d 100644
--- a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
+++ b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
@@ -1,7 +1,9 @@
package net.floodlightcontroller.core;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -214,6 +216,89 @@
* @return group identifier
*/
public List<Integer> createGroup(List<Integer> labelStack, List<PortNumber> ports);
+
+ public class GroupChainParams {
+ private String id;
+ private List<PortNumber> ports;
+ private List<Integer> labelStack;
+
+ public GroupChainParams(String id, List<Integer> labelStack,
+ List<PortNumber> ports) {
+ this.setId(id);
+ this.setPorts(ports);
+ this.setLabelStack(labelStack);
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public List<PortNumber> getPorts() {
+ return ports;
+ }
+
+ public void setPorts(List<PortNumber> ports) {
+ this.ports = ports;
+ }
+
+ public List<Integer> getLabelStack() {
+ return labelStack;
+ }
+
+ public void setLabelStack(List<Integer> labelStack) {
+ this.labelStack = labelStack;
+ }
+ }
+
+ public class GroupChain {
+ private String id;
+ private HashMap<PortNumber, List<Integer>> groupChain;
+ private int innermostGroupId;
+
+ public GroupChain(String id) {
+ this.setId(id);
+ groupChain = new HashMap<PortNumber,List<Integer>>();
+ }
+
+ public void addGroupChain(PortNumber port, List<Integer> chain) {
+ this.groupChain.put(port, chain);
+ }
+
+ public void addGroupToChain(PortNumber port, int groupId) {
+ List<Integer> chain = groupChain.get(port);
+ if (chain == null) {
+ chain = new ArrayList<Integer>();
+ groupChain.put(port, chain);
+ }
+ chain.add(groupId);
+ }
+
+ public HashMap<PortNumber, List<Integer>> getGroupChain() {
+ return groupChain;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public int getInnermostGroupId() {
+ return innermostGroupId;
+ }
+
+ public void setInnermostGroupId(int innermostGroupId) {
+ this.innermostGroupId = innermostGroupId;
+ }
+ }
+
+ public List<GroupChain> createGroupChain(List<GroupChainParams> groupChainParams);
/**
* Remove the specified group
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/OFFlowStatsEntryModSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/OFFlowStatsEntryModSerializer.java
index 42108d2..12187eb 100644
--- a/src/main/java/net/floodlightcontroller/core/web/serializers/OFFlowStatsEntryModSerializer.java
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/OFFlowStatsEntryModSerializer.java
@@ -88,7 +88,7 @@
+(matchGeneric.isMasked() ?
OFFlowStatsEntryModSerializer.covertToMask(
IPv4.toIPv4Address(
- matchGeneric.getMask().toString())):"0"));
+ matchGeneric.getMask().toString())):"32"));
}
else if (matchGeneric.getMatchField().id == MatchFields.ETH_DST){
jGen.writeStringField("dataLayerDestination", matchGeneric.getValue().toString());
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/ISegmentRoutingService.java b/src/main/java/net/onrc/onos/apps/segmentrouting/ISegmentRoutingService.java
index 9924ad7..9c49eba 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/ISegmentRoutingService.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/ISegmentRoutingService.java
@@ -7,6 +7,8 @@
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.util.MACAddress;
import net.onrc.onos.apps.segmentrouting.SegmentRoutingManager.removeTunnelMessages;
+import net.onrc.onos.apps.segmentrouting.web.SegmentRouterTunnelRESTParams;
+import net.onrc.onos.apps.segmentrouting.web.SegmentRouterTunnelsetRESTParams;
import net.onrc.onos.core.topology.Link;
import net.onrc.onos.core.util.IPv4Net;
@@ -27,6 +29,17 @@
public boolean createTunnel(String tunnelId, List<Integer> labelIds);
/**
+ * Create a tunnelset for policy routing.
+ *
+ * @param tunnelId ID for the tunnel
+ * @param labelIds Node label IDs for the tunnel
+ *
+ * @return "true/false" depending tunnel creation status
+ */
+ public boolean createTunnelset(String tunnelsetId,
+ SegmentRouterTunnelsetRESTParams tunnelsetParams);
+
+ /**
* Remove a Segment Routing tunnel given a tunnel Id.
*
* @param tunnelId ID for the tunnel
@@ -51,7 +64,7 @@
*/
public boolean createPolicy(String pid, MACAddress srcMac, MACAddress dstMac,
Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
- Short srcPort, Short dstPort, int priority, String tid);
+ Short srcPort, Short dstPort, int priority, String tid, boolean isTunnelsetId);
/**
@@ -93,6 +106,7 @@
*/
public Collection<SegmentRoutingTunnel> getTunnelTable();
+ public Collection<SegmentRoutingTunnelset> getTunnelsetTable();
/**
* Get the first group ID for the tunnel for specific source router
* If Segment Stitching was required to create the tunnel, there are
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/PolicyNotification.java b/src/main/java/net/onrc/onos/apps/segmentrouting/PolicyNotification.java
index 6fbcc07..4bcf1bc 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/PolicyNotification.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/PolicyNotification.java
@@ -12,6 +12,7 @@
private int priority;
private PacketMatch match;
private String tunnelId; // XXX need to define PolicyTunnelNotification
+ private boolean isSetId;
/**
*
*/
@@ -34,6 +35,7 @@
// XXX need to be processed in PolicyTunnelNotification
if (PolicyType.valueOf(policyType) == PolicyType.TUNNEL_FLOW) {
this.tunnelId = ((SegmentRoutingPolicyTunnel)srPolicy).getTunnelId();
+ this.isSetId = ((SegmentRoutingPolicyTunnel)srPolicy).isTunnelsetId();
}
}
@@ -61,10 +63,20 @@
public void setTunnelId(String tid) {
this.tunnelId = tid;
+ this.isSetId = false;
+ }
+
+ public void setTunnelId(String tid, boolean isSetId) {
+ this.tunnelId = tid;
+ this.isSetId = isSetId;
}
public String getTunnelId() {
return tunnelId;
}
+
+ public boolean isTunnelsetId() {
+ return this.isSetId;
+ }
}
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 8851420..9a5aaea 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
@@ -34,6 +34,8 @@
import net.onrc.onos.api.packet.IPacketListener;
import net.onrc.onos.api.packet.IPacketService;
import net.onrc.onos.apps.segmentrouting.SegmentRoutingPolicy.PolicyType;
+import net.onrc.onos.apps.segmentrouting.web.SegmentRouterTunnelRESTParams;
+import net.onrc.onos.apps.segmentrouting.web.SegmentRouterTunnelsetRESTParams;
import net.onrc.onos.apps.segmentrouting.web.SegmentRoutingWebRoutable;
import net.onrc.onos.core.datagrid.IDatagridService;
import net.onrc.onos.core.datagrid.IEventChannel;
@@ -129,6 +131,7 @@
private ConcurrentLinkedQueue<TopologyEvents> topologyEventQueue;
private HashMap<String, SegmentRoutingPolicy> policyTable;
private HashMap<String, SegmentRoutingTunnel> tunnelTable;
+ private HashMap<String, SegmentRoutingTunnelset> tunnelsetTable;
private HashMap<Integer, HashMap<Integer, List<Integer>>> adjacencySidTable;
private HashMap<String, HashMap<Integer, Integer>> adjcencyGroupIdTable;
private PolicyEventHandler policyEventHandler;
@@ -225,6 +228,7 @@
restApi = context.getServiceImpl(IRestApiService.class);
policyTable = new HashMap<String, SegmentRoutingPolicy>();
tunnelTable = new HashMap<String, SegmentRoutingTunnel>();
+ tunnelsetTable = new HashMap<String, SegmentRoutingTunnelset>();
adjacencySidTable = new HashMap<Integer,HashMap<Integer, List<Integer>>>();
adjcencyGroupIdTable = new HashMap<String, HashMap<Integer, Integer>>();
switchDpidListWithMastership = new ArrayList<String>();
@@ -1288,6 +1292,19 @@
}
/**
+ * Return the Tunnel table
+ *
+ * @return collection of TunnelInfo
+ */
+ public Collection<SegmentRoutingTunnelset> getTunnelsetTable() {
+ return this.tunnelsetTable.values();
+ }
+
+ public SegmentRoutingTunnelset getTunnelsetInfo(String tsid) {
+ return tunnelsetTable.get(tsid);
+ }
+
+ /**
* Return the Policy Table
*/
public Collection<SegmentRoutingPolicy> getPoclicyTable() {
@@ -1348,6 +1365,24 @@
return false;
}
}
+
+ public boolean createTunnelset(String tunnelsetId,
+ SegmentRouterTunnelsetRESTParams tunnelsetParams) {
+ SegmentRoutingTunnelset srTunnelset =
+ new SegmentRoutingTunnelset(this, tunnelsetParams);
+ if (srTunnelset.createTunnelSet()) {
+ tunnelsetTable.put(tunnelsetId, srTunnelset);
+ HashMap<String,SegmentRoutingTunnel> tunnelsetTunnels =
+ srTunnelset.getTunnels();
+ for (String tunnelId:tunnelsetTunnels.keySet())
+ tunnelTable.put(tunnelId, tunnelsetTunnels.get(tunnelId));
+ return true;
+ }
+ else {
+ log.warn("Failed to create a tunnel");
+ return false;
+ }
+ }
/**
* Create a policy with tunnel type
@@ -1355,14 +1390,32 @@
@Override
public boolean createPolicy(String pid, MACAddress srcMac, MACAddress dstMac,
Short etherType, IPv4Net srcIp, IPv4Net dstIp, Byte ipProto,
- Short srcPort, Short dstPort, int priority, String tid) {
+ Short srcPort, Short dstPort, int priority, String tid, boolean isTunnelsetId) {
// Sanity check
- SegmentRoutingTunnel tunnelInfo = tunnelTable.get(tid);
- if (tunnelInfo == null) {
- log.warn("Tunnel {} is not defined", tid);
- return false;
- }
+ if (isTunnelsetId) {
+ SegmentRoutingTunnelset tunnelsetInfo = tunnelsetTable.get(tid);
+ if (tunnelsetInfo == null) {
+ log.warn("Tunnelset {} is not defined", tid);
+ return false;
+ }
+ }
+ else {
+ SegmentRoutingTunnel tunnelInfo = tunnelTable.get(tid);
+ if (tunnelInfo == null) {
+ log.warn("Tunnel {} is not defined", tid);
+ return false;
+ }
+ else {
+ /* Check if the tunnel is part of a tunnelset,
+ * if so decline the request */
+ if (tunnelInfo.getTunnelsetId() != null) {
+ log.warn("Tunnel {} is part of a tunnelset, "
+ + "a policy can not point to such tunnels", tid);
+ return false;
+ }
+ }
+ }
PacketMatch policyMatch = buildPacketMatch(srcMac, dstMac, etherType,
srcIp, dstIp, ipProto, srcPort, dstPort);
@@ -1370,6 +1423,7 @@
SegmentRoutingPolicy srPolicy =
new SegmentRoutingPolicyTunnel(this,pid, PolicyType.TUNNEL_FLOW,
policyMatch, priority, tid);
+ ((SegmentRoutingPolicyTunnel)srPolicy).setIsTunnelsetId(isTunnelsetId);
if (srPolicy.createPolicy()) {
policyTable.put(pid, srPolicy);
PolicyNotification policyNotification =
@@ -2121,7 +2175,7 @@
log.debug("Set the policy 1");
this.createPolicy("1", null, null, Ethernet.TYPE_IPV4, srcIp,
dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 10000,
- "1");
+ "1", false);
testMode = TEST_MODE.POLICY_ADD2;
testTask.reschedule(5, TimeUnit.SECONDS);
}
@@ -2140,7 +2194,7 @@
log.debug("Set the policy 2");
this.createPolicy("2", null, null, Ethernet.TYPE_IPV4, srcIp,
dstIp, IPv4.PROTOCOL_ICMP, (short)-1, (short)-1, 20000,
- "2");
+ "2", false);
//testMode = POLICY_REMOVE2;
//testTask.reschedule(5, TimeUnit.SECONDS);
}
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingPolicyTunnel.java b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingPolicyTunnel.java
index ab3f653..e7e2026 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingPolicyTunnel.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingPolicyTunnel.java
@@ -1,9 +1,26 @@
package net.onrc.onos.apps.segmentrouting;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import net.floodlightcontroller.core.IOF13Switch.GroupChain;
+import net.onrc.onos.core.matchaction.MatchAction;
+import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
+import net.onrc.onos.core.matchaction.MatchActionOperations.Operator;
+import net.onrc.onos.core.matchaction.action.Action;
+import net.onrc.onos.core.matchaction.action.DecNwTtlAction;
+import net.onrc.onos.core.matchaction.action.GroupAction;
+import net.onrc.onos.core.matchaction.action.OutputAction;
+import net.onrc.onos.core.matchaction.action.SetDAAction;
+import net.onrc.onos.core.matchaction.action.SetSAAction;
import net.onrc.onos.core.matchaction.match.PacketMatch;
+import net.onrc.onos.core.topology.Switch;
+import net.onrc.onos.core.util.Dpid;
+import net.onrc.onos.core.util.PortNumber;
+import net.onrc.onos.core.util.SwitchPort;
+import org.projectfloodlight.openflow.types.MacAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -13,27 +30,37 @@
.getLogger(SegmentRoutingPolicyTunnel.class);
private String tunnelId;
+ private boolean isSetId;
public SegmentRoutingPolicyTunnel(SegmentRoutingManager srm, String pid,
PolicyType type, PacketMatch match, int priority, String tid) {
super(srm, pid, type, match, priority);
this.tunnelId = tid;
+ this.setIsTunnelsetId(false);
}
public SegmentRoutingPolicyTunnel(SegmentRoutingManager srm, PolicyNotification policyNotication) {
super(policyNotication);
this.srManager = srm;
this.tunnelId = policyNotication.getTunnelId();
+ this.isSetId = policyNotication.isTunnelsetId();
}
@Override
public boolean createPolicy() {
- SegmentRoutingTunnel tunnelInfo = srManager.getTunnelInfo(tunnelId);
-
- List<TunnelRouteInfo> routes = tunnelInfo.getRoutes();
-
- populateAclRule(routes);
+ if (isSetId) {
+ SegmentRoutingTunnelset tunnelset =
+ srManager.getTunnelsetInfo(tunnelId);
+ populateAclRuleToTunnelset(tunnelset);
+ }
+ else {
+ SegmentRoutingTunnel tunnelInfo = srManager.getTunnelInfo(tunnelId);
+
+ List<TunnelRouteInfo> routes = tunnelInfo.getRoutes();
+
+ populateAclRule(routes);
+ }
return true;
}
@@ -61,4 +88,32 @@
return this.tunnelId;
}
+ public boolean isTunnelsetId() {
+ return isSetId;
+ }
+
+ public void setIsTunnelsetId(boolean isSetId) {
+ this.isSetId = isSetId;
+ }
+
+ protected void populateAclRuleToTunnelset(SegmentRoutingTunnelset tunnelset) {
+ HashMap<String,List<GroupChain>> tunnelsetGroupChain =
+ tunnelset.getTunnelsetGroupChain();
+ for (String targetSwDpid: tunnelsetGroupChain.keySet()) {
+ List<Action> actions = new ArrayList<>();
+ GroupAction groupAction = new GroupAction();
+ groupAction.setGroupId(tunnelsetGroupChain.
+ get(targetSwDpid).get(0).getInnermostGroupId());
+ actions.add(groupAction);
+
+ MatchAction matchAction = new MatchAction(
+ srManager.getMatchActionId(),
+ new SwitchPort((new Dpid(targetSwDpid)).value(), (long)0), match, priority,
+ actions);
+ MatchActionOperationEntry maEntry =
+ new MatchActionOperationEntry(Operator.ADD, matchAction);
+
+ srManager.executeMatchActionOpEntry(maEntry);
+ }
+ }
}
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingTunnel.java b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingTunnel.java
index a5a0f2b..47351b7 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingTunnel.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingTunnel.java
@@ -1,9 +1,11 @@
package net.onrc.onos.apps.segmentrouting;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import net.floodlightcontroller.core.IOF13Switch;
+import net.floodlightcontroller.core.IOF13Switch.GroupChainParams;
import net.floodlightcontroller.core.IOF13Switch.NeighborSet;
import net.onrc.onos.core.drivermanager.OFSwitchImplDellOSR;
import net.onrc.onos.core.topology.Link;
@@ -23,6 +25,7 @@
private List<Integer> labelIds;
private List<TunnelRouteInfo> routes;
private SegmentRoutingManager srManager;
+ private String tunnelsetId;
private final int MAX_NUM_LABELS = 3;
@@ -38,6 +41,16 @@
this.srManager = srm;
this.tunnelId = tid;
this.labelIds = labelIds;
+ this.setTunnelsetId(null);
+ this.routes = new ArrayList<TunnelRouteInfo>();
+ }
+
+ public SegmentRoutingTunnel(SegmentRoutingManager srm, String tid,
+ List<Integer> labelIds, String tunnelsetId) {
+ this.srManager = srm;
+ this.tunnelId = tid;
+ this.labelIds = labelIds;
+ this.setTunnelsetId(tunnelsetId);
this.routes = new ArrayList<TunnelRouteInfo>();
}
@@ -114,7 +127,24 @@
public List<TunnelRouteInfo> getRoutes(){
return this.routes;
}
-
+
+ public HashMap<String, GroupChainParams> getGroupChainParams() {
+ HashMap<String, GroupChainParams> groupChainParamList =
+ new HashMap<String, GroupChainParams>();
+ for (TunnelRouteInfo route: routes) {
+ List<Integer> Ids = new ArrayList<Integer>();
+ for (String IdStr: route.route)
+ Ids.add(Integer.parseInt(IdStr));
+ NeighborSet ns = new NeighborSet();
+ for (Dpid dpid: route.getFwdSwDpid())
+ ns.addDpid(dpid);
+ List<PortNumber> ports = getPortsFromNeighborSet(route.srcSwDpid, ns);
+ GroupChainParams groupChainParams = new GroupChainParams(tunnelId, Ids, ports);
+ groupChainParamList.put(route.srcSwDpid, groupChainParams);
+ }
+
+ return groupChainParamList;
+ }
/**
* Create a tunnel
* It requests the driver to create a group chaining for the tunnel.
@@ -169,6 +199,38 @@
return true;
}
+ public boolean computeTunnelLabelStack() {
+
+ if (labelIds.isEmpty() || labelIds.size() < 2) {
+ log.debug("Wrong tunnel information");
+ return false;
+ }
+
+ List<String> Ids = new ArrayList<String>();
+ for (Integer label : labelIds) {
+ Ids.add(label.toString());
+ }
+
+ List<TunnelRouteInfo> stitchingRule = getStitchingRule(Ids);
+ if (stitchingRule == null) {
+ log.debug("Failed to get a tunnel rule.");
+ return false;
+ }
+
+ // Rearrange the tunnels if the last subtunnel does not have any label
+ // NOTE: this is only for DELL switches because all ACL rule needs PUSH
+ // Label Action.
+ checkAndSplitLabels(stitchingRule);
+
+ for (TunnelRouteInfo route: stitchingRule) {
+ route.setGroupIdList(null);
+ }
+
+ this.routes = stitchingRule;
+
+ return true;
+ }
+
/**
* Check if last sub tunnel rule label stack is empty.
* If so, move a label of previous tunnel to the last sub-tunnel.
@@ -621,5 +683,13 @@
}
+ public String getTunnelsetId() {
+ return tunnelsetId;
+ }
+
+ public void setTunnelsetId(String tunnelsetId) {
+ this.tunnelsetId = tunnelsetId;
+ }
+
}
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingTunnelset.java b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingTunnelset.java
new file mode 100644
index 0000000..8848714
--- /dev/null
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingTunnelset.java
@@ -0,0 +1,107 @@
+package net.onrc.onos.apps.segmentrouting;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import net.floodlightcontroller.core.IOF13Switch;
+import net.floodlightcontroller.core.IOF13Switch.GroupChain;
+import net.floodlightcontroller.core.IOF13Switch.GroupChainParams;
+import net.floodlightcontroller.core.IOF13Switch.NeighborSet;
+import net.onrc.onos.core.drivermanager.OFSwitchImplDellOSR;
+import net.onrc.onos.core.topology.Link;
+import net.onrc.onos.core.topology.Switch;
+import net.onrc.onos.core.util.Dpid;
+import net.onrc.onos.core.util.PortNumber;
+import net.onrc.onos.apps.segmentrouting.web.SegmentRouterTunnelRESTParams;
+import net.onrc.onos.apps.segmentrouting.web.SegmentRouterTunnelsetRESTParams;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SegmentRoutingTunnelset {
+
+ private static final Logger log = LoggerFactory
+ .getLogger(SegmentRoutingTunnel.class);
+ private SegmentRoutingManager srManager;
+ private String tunnelsetId;
+ private HashMap<String, SegmentRoutingTunnel> tunnelMap;
+ private HashMap<String, HashMap<String,GroupChain>> tunnelIdGroupChainMap;
+ private HashMap<String, List<GroupChain>> tunnelsetGroupChain;
+
+ public SegmentRoutingTunnelset(SegmentRoutingManager srm,
+ SegmentRouterTunnelsetRESTParams tunnelsetParams) {
+ this.srManager = srm;
+ this.tunnelsetId = tunnelsetParams.getTunnelset_id();
+ tunnelsetGroupChain = new HashMap<String, List<GroupChain>>();
+ tunnelMap = new HashMap<String,SegmentRoutingTunnel>();
+ tunnelIdGroupChainMap = new HashMap<String, HashMap<String,GroupChain>>();
+ for (SegmentRouterTunnelRESTParams tunnelParams:tunnelsetParams.getTunnelParams()) {
+ SegmentRoutingTunnel tunnel = new
+ SegmentRoutingTunnel(srm, tunnelParams.getTunnel_id(),
+ tunnelParams.getLabel_path(), tunnelsetId);
+ tunnel.computeTunnelLabelStack();
+ tunnelMap.put(tunnelParams.getTunnel_id(), tunnel);
+ }
+ }
+
+ public boolean createTunnelSet() {
+ HashMap<String, List<GroupChainParams>> tunnelsetGroupChainParamsMap =
+ new HashMap<String, List<GroupChainParams>>();
+ for (SegmentRoutingTunnel tunnel:tunnelMap.values()) {
+ HashMap<String, GroupChainParams> tunnelGroupChainParams =
+ tunnel.getGroupChainParams();
+ for (String targetSwDpid: tunnelGroupChainParams.keySet()) {
+ List<GroupChainParams> groupChainParams =
+ tunnelsetGroupChainParamsMap.get(targetSwDpid);
+ if (groupChainParams == null) {
+ groupChainParams = new ArrayList<GroupChainParams>();
+ tunnelsetGroupChainParamsMap.put(targetSwDpid, groupChainParams);
+ }
+ groupChainParams.add(tunnelGroupChainParams.get(targetSwDpid));
+ }
+ }
+
+ for (String targetSwDpid: tunnelsetGroupChainParamsMap.keySet()) {
+ IOF13Switch targetSw = srManager.getIOF13Switch(targetSwDpid);
+
+ if (targetSw == null) {
+ log.debug("Switch {} is gone.", targetSwDpid);
+ continue;
+ }
+
+ List<GroupChain> groupChainList = targetSw.createGroupChain(
+ tunnelsetGroupChainParamsMap.get(targetSwDpid));
+ for (GroupChain groupChain:groupChainList) {
+ HashMap<String,GroupChain> dpidGroupMap =
+ tunnelIdGroupChainMap.get(groupChain.getId());
+ if (dpidGroupMap == null)
+ {
+ dpidGroupMap = new HashMap<String, IOF13Switch.GroupChain>();
+ tunnelIdGroupChainMap.put(groupChain.getId(), dpidGroupMap);
+ }
+
+ dpidGroupMap.put(targetSwDpid, groupChain);
+ }
+ tunnelsetGroupChain.put(targetSwDpid, groupChainList);
+ }
+
+ return true;
+ }
+
+ public String getTunnelsetId() {
+ return this.tunnelsetId;
+ }
+
+ public HashMap<String,SegmentRoutingTunnel> getTunnels() {
+ return this.tunnelMap;
+ }
+
+ public HashMap<String, GroupChain> getTunnelGroupChain(String tunnelId) {
+ return tunnelIdGroupChainMap.get(tunnelId);
+ }
+
+ public HashMap<String, List<GroupChain>> getTunnelsetGroupChain() {
+ return tunnelsetGroupChain;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterPolicyRESTParams.java b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterPolicyRESTParams.java
index 8fc9256..03629ac 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterPolicyRESTParams.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterPolicyRESTParams.java
@@ -6,6 +6,7 @@
private String policy_type;
private int priority;
private String tunnel_id;
+ private String tunnelset_id;
private String proto_type;
private String src_ip;
private String src_tp_port_op;
@@ -19,6 +20,7 @@
this.policy_type = null;
this.priority = 0;
this.tunnel_id = null;
+ this.setTunnelset_id(null);
this.proto_type = null;
this.src_ip = null;
this.src_tp_port_op = null;
@@ -115,4 +117,12 @@
public short getDst_tp_port() {
return this.dst_tp_port;
}
+
+ public String getTunnelset_id() {
+ return tunnelset_id;
+ }
+
+ public void setTunnelset_id(String tunnelset_id) {
+ this.tunnelset_id = tunnelset_id;
+ }
}
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterPolicyResource.java b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterPolicyResource.java
index a955440..2aab718 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterPolicyResource.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterPolicyResource.java
@@ -47,14 +47,21 @@
log.error("Exception occurred parsing inbound JSON", ex);
return "fail";
}
+
+ String tunnelId = createParams.getTunnel_id();
+ boolean isTunnelsetId = false;
+ if (createParams.getTunnelset_id() != null) {
+ tunnelId = createParams.getTunnelset_id();
+ isTunnelsetId = true;
+ }
log.debug("createPolicy of type {} with params id {} src_ip {} dst_ip {}"
- + "proto {} src_port {} dst_port {} priority {} tunnel_id {}",
+ + "proto {} src_port {} dst_port {} priority {} tunnel_id {} isSet {}",
createParams.getPolicy_type(),
createParams.getPolicy_id(), createParams.getSrc_ip(),
createParams.getDst_ip(), createParams.getProto_type(),
createParams.getSrc_tp_port(), createParams.getDst_tp_port(),
- createParams.getPriority(), createParams.getTunnel_id());
+ createParams.getPriority(), tunnelId, isTunnelsetId);
IPv4Net src_ip = (createParams.getSrc_ip() != null) ?
new IPv4Net(createParams.getSrc_ip()) : null;
@@ -68,7 +75,7 @@
createParams.getSrc_tp_port(),
createParams.getDst_tp_port(),
createParams.getPriority(),
- createParams.getTunnel_id());
+ tunnelId, isTunnelsetId);
return (result == true) ? "success" : "fail";
}
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelInfo.java b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelInfo.java
index 3808ef8..9cd2cc0 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelInfo.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelInfo.java
@@ -7,23 +7,29 @@
*/
public class SegmentRouterTunnelInfo {
private String tunnelId;
+ private String tunnelsetId;
private List<List<String>> labelStack;
private List<String> dpidGroup;
private List<Integer> tunnelPath;
private String policies;
public SegmentRouterTunnelInfo (String tId,List<List<String>> tunnelRoutes,
- List<String> dpidsWithGroup,List<Integer> path, String policiesId){
+ List<String> dpidsWithGroup,List<Integer> path,
+ String policiesId, String tunnelsetId){
this.tunnelId = tId;
this.labelStack = tunnelRoutes;
this.dpidGroup = dpidsWithGroup;
this.tunnelPath = path;
this.policies = policiesId;
+ this.tunnelsetId = tunnelsetId;
}
public String getTunnelId (){
return this.tunnelId;
}
+ public String getTunnelsetId (){
+ return this.tunnelsetId;
+ }
public List<List<String>> getLabelStack (){
return this.labelStack;
}
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelResource.java b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelResource.java
index efaed12..c611d0f 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelResource.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelResource.java
@@ -12,6 +12,7 @@
import net.onrc.onos.apps.segmentrouting.SegmentRoutingPolicy.PolicyType;
import net.onrc.onos.apps.segmentrouting.SegmentRoutingPolicyTunnel;
import net.onrc.onos.apps.segmentrouting.SegmentRoutingTunnel;
+import net.onrc.onos.apps.segmentrouting.SegmentRoutingTunnelset;
import net.onrc.onos.apps.segmentrouting.TunnelRouteInfo;
import org.codehaus.jackson.map.ObjectMapper;
@@ -88,6 +89,7 @@
SegmentRoutingTunnel tunnelInfo = ttI.next();
List<Integer> tunnelPath = tunnelInfo.getLabelids();
String tunnelId = tunnelInfo.getTunnelId();
+ String tunnelsetId = tunnelInfo.getTunnelsetId();
Collection<SegmentRoutingPolicy> policies = segmentRoutingService.getPoclicyTable();
Iterator<SegmentRoutingPolicy> piI = policies.iterator();
String policiesId = "";
@@ -107,15 +109,31 @@
while(trI.hasNext()){
TunnelRouteInfo label = trI.next();
labelStack.add(label.getRoute());
- Integer gId = segmentRoutingService.getTunnelGroupId(tunnelId,
- label.getSrcSwDpid());
+ Integer gId = -1;
+ if (tunnelsetId != null) {
+ Iterator<SegmentRoutingTunnelset> tstI =
+ segmentRoutingService.getTunnelsetTable().iterator();
+ while(tstI.hasNext()){
+ SegmentRoutingTunnelset parentTunnelset = tstI.next();
+ if (parentTunnelset.getTunnelsetId() == tunnelsetId) {
+ gId = parentTunnelset.getTunnelGroupChain(
+ tunnelId).get(label.getSrcSwDpid()).
+ getInnermostGroupId();
+ break;
+ }
+ }
+ }
+ else {
+ gId = segmentRoutingService.getTunnelGroupId(tunnelId,
+ label.getSrcSwDpid());
+ }
dpidGroup.add(label.getSrcSwDpid()+"("
+ segmentRoutingService.getMplsLabel(label.getSrcSwDpid())+ ")"
+ "/"+ gId
);
}
SegmentRouterTunnelInfo info = new SegmentRouterTunnelInfo(tunnelId,
- labelStack, dpidGroup, tunnelPath, policiesId );
+ labelStack, dpidGroup, tunnelPath, policiesId, tunnelsetId );
infoList.add(info);
}
log.debug("getTunnel with params");
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelsetInfo.java b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelsetInfo.java
new file mode 100644
index 0000000..0e42d0f
--- /dev/null
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelsetInfo.java
@@ -0,0 +1,38 @@
+package net.onrc.onos.apps.segmentrouting.web;
+
+import java.util.List;
+/**
+ * This class contains tunnelset info of ONOS Segement Routing App
+ * Used for rest API
+ */
+public class SegmentRouterTunnelsetInfo {
+ private String tunnelsetId;
+ private List<SegmentRouterTunnelInfo> constituentTunnels;
+ private String policies;
+
+ public SegmentRouterTunnelsetInfo(String tunnelsetId) {
+ this.tunnelsetId = tunnelsetId;
+ this.constituentTunnels = null;
+ }
+
+ public String getTunnelsetId() {
+ return tunnelsetId;
+ }
+ public void setTunnelsetId(String tunnelsetId) {
+ this.tunnelsetId = tunnelsetId;
+ }
+ public List<SegmentRouterTunnelInfo> getConstituentTunnels() {
+ return constituentTunnels;
+ }
+ public void setConstituentTunnels(List<SegmentRouterTunnelInfo> constituentTunnels) {
+ this.constituentTunnels = constituentTunnels;
+ }
+
+ public String getPolicies() {
+ return policies;
+ }
+
+ public void setPolicies(String policies) {
+ this.policies = policies;
+ }
+}
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelsetRESTParams.java b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelsetRESTParams.java
new file mode 100644
index 0000000..6faf4e7
--- /dev/null
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelsetRESTParams.java
@@ -0,0 +1,36 @@
+package net.onrc.onos.apps.segmentrouting.web;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.codehaus.jackson.map.annotate.JsonDeserialize;
+
+public class SegmentRouterTunnelsetRESTParams {
+ private String tunnelset_id;
+ @JsonProperty("tunnel_params")
+ //@JsonDeserialize(contentUsing = SegmentRouterTunnelRESTParams.class)
+ private List<SegmentRouterTunnelRESTParams> tunnel_params =
+ new ArrayList<SegmentRouterTunnelRESTParams>();
+
+ public SegmentRouterTunnelsetRESTParams() {
+ //this.tunnelset_id = null;
+ //this.tunnel_params = null;
+ }
+
+ public void setTunnelset_id(String tunnelset_id) {
+ this.tunnelset_id = tunnelset_id;
+ }
+
+ public String getTunnelset_id() {
+ return this.tunnelset_id;
+ }
+
+ public void setTunnelParams(List<SegmentRouterTunnelRESTParams> tunnel_params) {
+ this.tunnel_params = tunnel_params;
+ }
+
+ public List<SegmentRouterTunnelRESTParams> getTunnelParams() {
+ return this.tunnel_params;
+ }
+}
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelsetResource.java b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelsetResource.java
new file mode 100644
index 0000000..46e6126
--- /dev/null
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRouterTunnelsetResource.java
@@ -0,0 +1,141 @@
+package net.onrc.onos.apps.segmentrouting.web;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import net.floodlightcontroller.core.IOF13Switch.GroupChain;
+import net.onrc.onos.apps.segmentrouting.ISegmentRoutingService;
+import net.onrc.onos.apps.segmentrouting.SegmentRoutingPolicy;
+import net.onrc.onos.apps.segmentrouting.SegmentRoutingPolicyTunnel;
+import net.onrc.onos.apps.segmentrouting.SegmentRoutingTunnel;
+import net.onrc.onos.apps.segmentrouting.SegmentRoutingTunnelset;
+import net.onrc.onos.apps.segmentrouting.TunnelRouteInfo;
+import net.onrc.onos.apps.segmentrouting.SegmentRoutingManager.removeTunnelMessages;
+import net.onrc.onos.apps.segmentrouting.SegmentRoutingPolicy.PolicyType;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.restlet.resource.Delete;
+import org.restlet.resource.Get;
+import org.restlet.resource.Post;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SegmentRouterTunnelsetResource extends ServerResource {
+ protected final static Logger log =
+ LoggerFactory.getLogger(SegmentRouterTunnelsetResource.class);
+
+ @Post("json")
+ public String createTunnelset(String tunnelsetParams) {
+ log.debug("createTunnelset with tunnelsetParams {}", tunnelsetParams);
+ ISegmentRoutingService segmentRoutingService =
+ (ISegmentRoutingService) getContext().getAttributes().
+ get(ISegmentRoutingService.class.getCanonicalName());
+ ObjectMapper mapper = new ObjectMapper();
+ SegmentRouterTunnelsetRESTParams createParams = null;
+ try {
+ if (tunnelsetParams != null) {
+ createParams = mapper.readValue(tunnelsetParams,
+ SegmentRouterTunnelsetRESTParams.class);
+ }
+ else
+ return "fail";
+ } catch (IOException ex) {
+ log.error("Exception occurred parsing inbound JSON", ex);
+ return "fail";
+ }
+ log.debug("createTunnelset with tunnelsetId {} tunnel params{}",
+ createParams.getTunnelset_id(), createParams.getTunnelParams().get(0));
+ boolean result = true;
+ result = segmentRoutingService.createTunnelset(createParams.getTunnelset_id(),
+ createParams);
+ return (result == true) ? "success" : "fail";
+ }
+/*
+ @Delete("json")
+ public String deleteTunnel(String tunnelParams) {
+ ISegmentRoutingService segmentRoutingService =
+ (ISegmentRoutingService) getContext().getAttributes().
+ get(ISegmentRoutingService.class.getCanonicalName());
+ ObjectMapper mapper = new ObjectMapper();
+ SegmentRouterTunnelRESTParams createParams = null;
+ try {
+ if (tunnelParams != null) {
+ createParams = mapper.readValue(tunnelParams,
+ SegmentRouterTunnelRESTParams.class);
+ }
+ } catch (IOException ex) {
+ log.error("Exception occurred parsing inbound JSON", ex);
+ return "fail";
+ }
+ log.debug("deleteTunnel with Id {}", createParams.getTunnel_id());
+ removeTunnelMessages result = segmentRoutingService.removeTunnel(
+ createParams.getTunnel_id());
+ return result.name()+" "+result.toString();
+ }*/
+
+ @Get("json")
+ public Object getTunnelset() {
+ ISegmentRoutingService segmentRoutingService =
+ (ISegmentRoutingService) getContext().getAttributes().
+ get(ISegmentRoutingService.class.getCanonicalName());
+ Iterator<SegmentRoutingTunnelset> ttI =
+ segmentRoutingService.getTunnelsetTable().iterator();
+ List<SegmentRouterTunnelsetInfo> tunnelsetInfoList =
+ new ArrayList<SegmentRouterTunnelsetInfo>();
+ while(ttI.hasNext()){
+ SegmentRoutingTunnelset tunnelset = ttI.next();
+ String tunnelsetId = tunnelset.getTunnelsetId();
+ SegmentRouterTunnelsetInfo tunnelsetInfo = new SegmentRouterTunnelsetInfo(
+ tunnelsetId);
+ Collection<SegmentRoutingPolicy> policies = segmentRoutingService.getPoclicyTable();
+ Iterator<SegmentRoutingPolicy> piI = policies.iterator();
+ String policiesId = "";
+ while(piI.hasNext()){
+ SegmentRoutingPolicy policy = piI.next();
+ if(policy.getType() == PolicyType.TUNNEL_FLOW &&
+ (((SegmentRoutingPolicyTunnel)policy).isTunnelsetId() &&
+ ((SegmentRoutingPolicyTunnel)policy).getTunnelId().equals(tunnelsetId))){
+ policiesId += (policy.getPolicyId()+",");
+ }
+ }
+ if (policiesId.endsWith(",")){
+ policiesId = (String) policiesId.subSequence(0, policiesId.length()-1);
+ }
+ HashMap<String, SegmentRoutingTunnel> constituentTunnels =
+ tunnelset.getTunnels();
+ List<SegmentRouterTunnelInfo> tunnelInfoList =
+ new ArrayList<SegmentRouterTunnelInfo>();
+ for (SegmentRoutingTunnel tunnel:constituentTunnels.values()) {
+ String tunnelId = tunnel.getTunnelId();
+ List<Integer> tunnelPath = tunnel.getLabelids();
+ String parentTunnelsetId = tunnel.getTunnelsetId();
+ Iterator<TunnelRouteInfo>trI = tunnel.getRoutes().iterator();
+ List<List<String>> labelStack = new ArrayList<List<String>>();
+ List<String> dpidGroup = new ArrayList<String>();
+ while(trI.hasNext()){
+ TunnelRouteInfo label = trI.next();
+ labelStack.add(label.getRoute());
+ Integer gId = tunnelset.getTunnelGroupChain(tunnelId).
+ get(label.getSrcSwDpid()).getInnermostGroupId();
+ dpidGroup.add(label.getSrcSwDpid()+"("
+ + segmentRoutingService.getMplsLabel(label.getSrcSwDpid())+ ")"
+ + "/"+ gId
+ );
+ }
+ SegmentRouterTunnelInfo info = new SegmentRouterTunnelInfo(tunnelId,
+ labelStack, dpidGroup, tunnelPath, null, parentTunnelsetId );
+ tunnelInfoList.add(info);
+ }
+ tunnelsetInfo.setPolicies(policiesId);
+ tunnelsetInfo.setConstituentTunnels(tunnelInfoList);
+ tunnelsetInfoList.add(tunnelsetInfo);
+ }
+ log.debug("getTunnelset with params");
+ return tunnelsetInfoList;
+ }
+}
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRoutingWebRoutable.java b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRoutingWebRoutable.java
index 6c9db02..c08225c 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRoutingWebRoutable.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/web/SegmentRoutingWebRoutable.java
@@ -18,6 +18,7 @@
//TODO: rewrite Router/SwitchesResource for router specific info.
router.attach("/routers", SegmentRouterResource.class);
router.attach("/router/{routerId}/{statsType}", SegmentRouterResource.class);
+ router.attach("/tunnelset", SegmentRouterTunnelsetResource.class);
router.attach("/tunnel", SegmentRouterTunnelResource.class);
router.attach("/policy", SegmentRouterPolicyResource.class);
return router;
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 1fe9c1b..d45a13b 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,8 @@
import net.floodlightcontroller.core.IFloodlightProviderService.Role;
import net.floodlightcontroller.core.IOF13Switch;
+import net.floodlightcontroller.core.IOF13Switch.GroupChain;
+import net.floodlightcontroller.core.IOF13Switch.GroupChainParams;
import net.floodlightcontroller.core.IOF13Switch.NeighborSet.groupPktType;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.SwitchDriverSubHandshakeAlreadyStarted;
@@ -2183,6 +2185,90 @@
getStringId(), innermostGroupId);
return groupIdList;
}
+
+ public List<GroupChain> createGroupChain(List<GroupChainParams> groupChainParams) {
+ List<GroupChain> groupChains = new ArrayList<GroupChain>();
+
+ List<BucketInfo> buckets = new ArrayList<BucketInfo>();
+ for (GroupChainParams i: groupChainParams) {
+ List<PortNumber> ports = i.getPorts();
+ if (ports == null) {
+ log.warn("createGroupChain in sw {} with wrong "
+ + "input parameters", getStringId());
+ return null;
+ }
+
+ List<PortNumber> activePorts = new ArrayList<PortNumber>();
+ for (PortNumber port : ports) {
+ if (portEnabled((int) port.value()))
+ activePorts.add(port);
+ }
+ if (activePorts.isEmpty()) {
+ log.warn("createGroupChain in sw {} with no "
+ + "active ports for groupChainParams id {}",
+ getStringId(), i.getId());
+ continue;
+ }
+
+ int labelStackSize = (i.getLabelStack() != null) ?
+ i.getLabelStack().size() : 0;
+ GroupChain groupChain = new GroupChain(i.getId());
+ groupChains.add(groupChain);
+
+ if (labelStackSize > 0) {
+ for (PortNumber sp : activePorts) {
+ int previousGroupId = -1;
+ for (int idx=0; idx < i.getLabelStack().size(); idx++) {
+ if (idx == (labelStackSize - 1)) {
+ int label = i.getLabelStack().get(idx).intValue();
+ Dpid neighborDpid = portToNeighbors.get(sp);
+ BucketInfo b = new BucketInfo(neighborDpid,
+ MacAddress.of(srConfig.getRouterMac()),
+ getNeighborRouterMacAddress(neighborDpid),
+ sp, label, true, previousGroupId);
+ buckets.add(b);
+ }
+ else {
+ int currGroupId = getNextFreeGroupId();
+ EcmpInfo indirectGroup = createIndirectGroup(currGroupId,
+ null, null, sp, previousGroupId,
+ i.getLabelStack().get(idx).intValue(), false);
+ previousGroupId = currGroupId;
+ userDefinedGroups.put(currGroupId, indirectGroup);
+ groupChain.addGroupToChain(sp, currGroupId);
+ }
+ }
+ }
+ }
+ else
+ {
+ for (PortNumber sp : activePorts) {
+ Dpid neighborDpid = portToNeighbors.get(sp);
+ BucketInfo b = new BucketInfo(neighborDpid,
+ MacAddress.of(srConfig.getRouterMac()),
+ getNeighborRouterMacAddress(neighborDpid),
+ sp, -1, false, -1);
+ buckets.add(b);
+ }
+ }
+ }
+
+ if (!buckets.isEmpty()) {
+ int innermostGroupId = getNextFreeGroupId();
+ EcmpInfo ecmpInfo = new EcmpInfo(innermostGroupId,
+ OFGroupType.SELECT, buckets);
+ setEcmpGroup(ecmpInfo);
+ userDefinedGroups.put(innermostGroupId, ecmpInfo);
+ for (GroupChain groupChain:groupChains) {
+ groupChain.setInnermostGroupId(innermostGroupId);
+ }
+ log.debug(
+ "createInnermostLabelGroup: Creating select group {} in sw {} "
+ + "with: {}", innermostGroupId, getStringId(), ecmpInfo);
+ }
+
+ return groupChains;
+ }
/**
* Remove the specified group