Adding support for adjacency label configuration, auto-generation
and publication
Change-Id: I9e5195c99299c7457230d71dad7002d15bf62bf9
diff --git a/conf/onos.properties b/conf/onos.properties
index 60283c8..a3e1d19 100644
--- a/conf/onos.properties
+++ b/conf/onos.properties
@@ -23,5 +23,4 @@
# Uncomment and list all the ZooKeeper instances after localhost on multi-instance deployment.
#net.onrc.onos.core.registry.ZookeeperRegistry.connectionString = localhost:2181,otherhost:2181
# Specify a network configuration file to be used by the NetworkConfigManager
-net.onrc.onos.core.configmanager.NetworkConfigManager.networkConfigFile = conf/sr-ecmp10.conf
-
+net.onrc.onos.core.configmanager.NetworkConfigManager.networkConfigFile = conf/sr-ecmp.conf
diff --git a/conf/sr-3node.conf b/conf/sr-3node.conf
index 19eeff5..8d0a25b 100644
--- a/conf/sr-3node.conf
+++ b/conf/sr-3node.conf
@@ -11,10 +11,6 @@
"routerMac": "00:00:01:01:01:80",
"nodeSid": 101,
"isEdgeRouter" : true,
- "adjacencySids": [
- { "portNo": 6, "adjSid": 10234 },
- { "portNo": 7, "adjSid": 29019 }
- ],
"subnets": [
{ "portNo": 1, "subnetIp": "10.0.1.128/24" },
{ "portNo": 2, "subnetIp": "10.0.1.128/24" },
@@ -30,12 +26,7 @@
"params": { "routerIp": "192.168.0.2/32",
"routerMac": "00:00:02:02:02:80",
"nodeSid": 102,
- "isEdgeRouter" : false,
- "adjacencySids": [
- { "portNo": 1, "adjSid": 12453 },
- { "portNo": 2, "adjSid": 23333 },
- { "portNo": 3, "adjSid": 22233 }
- ]
+ "isEdgeRouter" : false
}
},
@@ -45,9 +36,6 @@
"routerMac": "00:00:07:07:07:80",
"nodeSid": 103,
"isEdgeRouter" : true,
- "adjacencySids": [
- { "portNo": 2, "adjSid": 92033 }
- ],
"subnets": [
{ "portNo": 1, "subnetIp": "7.7.7.128/24" }
]
diff --git a/conf/sr-ecmp.conf b/conf/sr-ecmp.conf
index a6c2d79..7c2c812 100644
--- a/conf/sr-ecmp.conf
+++ b/conf/sr-ecmp.conf
@@ -1,5 +1,5 @@
{
- "comment": " Multilayer topology description and configuration",
+ "comment": " Fist topology 1 - [2,3] - [5,4] - 6",
"restrictSwitches": true,
"restrictLinks": true,
@@ -11,10 +11,6 @@
"routerMac": "00:00:01:01:01:80",
"nodeSid": 101,
"isEdgeRouter" : true,
- "adjacencySids": [
- { "portNo": 6, "adjSid": 10234 },
- { "portNo": 7, "adjSid": 29019 }
- ],
"subnets": [
{ "portNo": 1, "subnetIp": "10.0.1.128/24" }
]
@@ -28,9 +24,7 @@
"nodeSid": 102,
"isEdgeRouter" : false,
"adjacencySids": [
- { "portNo": 1, "adjSid": 12453 },
- { "portNo": 2, "adjSid": 23333 },
- { "portNo": 3, "adjSid": 22233 }
+ { "adjSid": 12453 , "ports": [ 2 ,3 ] }
]
}
},
@@ -40,10 +34,7 @@
"params": { "routerIp": "192.168.0.3/32",
"routerMac": "00:00:03:03:03:80",
"nodeSid": 103,
- "isEdgeRouter" : false,
- "adjacencySids": [
- { "portNo": 2, "adjSid": 92033 }
- ]
+ "isEdgeRouter" : false
}
},
@@ -52,10 +43,7 @@
"params": { "routerIp": "192.168.0.4/32",
"routerMac": "00:00:04:04:04:80",
"nodeSid": 104,
- "isEdgeRouter" : false,
- "adjacencySids": [
- { "portNo": 2, "adjSid": 92033 }
- ]
+ "isEdgeRouter" : false
}
},
@@ -64,10 +52,7 @@
"params": { "routerIp": "192.168.0.5/32",
"routerMac": "00:00:05:05:05:80",
"nodeSid": 105,
- "isEdgeRouter" : false,
- "adjacencySids": [
- { "portNo": 2, "adjSid": 92033 }
- ]
+ "isEdgeRouter" : false
}
},
@@ -77,9 +62,6 @@
"routerMac": "00:00:07:07:07:80",
"nodeSid": 106,
"isEdgeRouter" : true,
- "adjacencySids": [
- { "portNo": 2, "adjSid": 92033 }
- ],
"subnets": [
{ "portNo": 1, "subnetIp": "7.7.7.128/24" }
]
diff --git a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
index 94b8930..4203c13 100644
--- a/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
+++ b/src/main/java/net/floodlightcontroller/core/IOF13Switch.java
@@ -4,6 +4,7 @@
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
@@ -167,4 +168,6 @@
* @return first Group ID for the tunnel or -1 if not found
*/
public int getTunnelGroupId(String tunnelID);
+
+ public Map<String, String> getPublishAttributes();
}
diff --git a/src/main/java/net/onrc/onos/core/configmanager/SegmentRouterConfig.java b/src/main/java/net/onrc/onos/core/configmanager/SegmentRouterConfig.java
index 89df3c6..2020dea 100644
--- a/src/main/java/net/onrc/onos/core/configmanager/SegmentRouterConfig.java
+++ b/src/main/java/net/onrc/onos/core/configmanager/SegmentRouterConfig.java
@@ -33,6 +33,7 @@
public static final String ADJACENCY_SIDS = "adjacencySids";
public static final String SUBNETS = "subnets";
public static final String ISEDGE = "isEdgeRouter";
+ private static final int SRGB_MAX = 1000;
public SegmentRouterConfig(SwitchConfig swc) {
this.setName(swc.getName());
@@ -86,20 +87,20 @@
}
public static class AdjacencySid {
- private int portNo;
private int adjSid;
+ private List<Integer> ports;
- public AdjacencySid(int portNo, int adjSid) {
- this.portNo = portNo;
+ public AdjacencySid(int adjSid, List<Integer> ports) {
+ this.ports = ports;
this.adjSid = adjSid;
}
- public int getPortNo() {
- return portNo;
+ public List<Integer> getPorts() {
+ return ports;
}
- public void setPortNo(int portNo) {
- this.portNo = portNo;
+ public void setPorts(List<Integer> ports) {
+ this.ports = ports;
}
public int getAdjSid() {
@@ -190,6 +191,7 @@
int portNo = -1;
int adjSid = -1;
String subnetIp = null;
+ List<Integer> ports = null;
while (f.hasNext()) {
Entry<String, JsonNode> fe = f.next();
if (fe.getKey().equals("portNo")) {
@@ -198,12 +200,20 @@
adjSid = fe.getValue().asInt();
} else if (fe.getKey().equals("subnetIp")) {
subnetIp = fe.getValue().asText();
+ } else if (fe.getKey().equals("ports")) {
+ if (fe.getValue().isArray()) {
+ Iterator<JsonNode> i = fe.getValue().getElements();
+ ports = new ArrayList<Integer>();
+ while (i.hasNext()) {
+ ports.add(i.next().asInt());
+ }
+ }
} else {
throw new UnknownSegmentRouterConfig(fe.getKey(), dpid);
}
}
if (innerParam.equals("adjacencySids")) {
- AdjacencySid ads = new AdjacencySid(portNo, adjSid);
+ AdjacencySid ads = new AdjacencySid(adjSid, ports);
adjacencySids.add(ads);
} else {
Subnet sip = new Subnet(portNo, subnetIp);
@@ -222,6 +232,20 @@
if (!isEdgeRouter && !subnets.isEmpty()) {
throw new SubnetSpecifiedInBackboneRouter(dpid);
}
+ if (nodeSid > SRGB_MAX) {
+ throw new NodeLabelNotInSRGB(nodeSid, dpid);
+ }
+ for (AdjacencySid as : adjacencySids) {
+ int label = as.getAdjSid();
+ List<Integer> plist = as.getPorts();
+ if (label <= SRGB_MAX) {
+ throw new AdjacencyLabelInSRGB(label, dpid);
+ }
+ if (plist.size() <= 1) {
+ throw new AdjacencyLabelNotEnoughPorts(label, dpid);
+ }
+ }
+
// TODO more validations
}
@@ -284,7 +308,7 @@
}
public static class SubnetSpecifiedInBackboneRouter extends RuntimeException {
- private static final long serialVersionUID = -5855458472668581268L;
+ private static final long serialVersionUID = 1L;
public SubnetSpecifiedInBackboneRouter(long dpid) {
super();
@@ -293,6 +317,37 @@
}
}
+ public static class NodeLabelNotInSRGB extends RuntimeException {
+ private static final long serialVersionUID = -8482670903748519526L;
+ public NodeLabelNotInSRGB(int label, long dpid) {
+ super();
+ log.error("Node sif {} specified in not in global label-base "
+ + "in dpid: {}", label,
+ HexString.toHexString(dpid));
+ }
+ }
+ public static class AdjacencyLabelInSRGB extends RuntimeException {
+ private static final long serialVersionUID = -8482670903748519526L;
+
+ public AdjacencyLabelInSRGB(int label, long dpid) {
+ super();
+ log.error("Adjaceny label {} specified from global label-base "
+ + "in dpid: {}", label,
+ HexString.toHexString(dpid));
+ }
+ }
+
+ public static class AdjacencyLabelNotEnoughPorts extends RuntimeException {
+ private static final long serialVersionUID = -8482670903748519526L;
+
+ public AdjacencyLabelNotEnoughPorts(int label, long dpid) {
+ super();
+ log.error("Adjaceny label {} must be specified for at least 2 ports. "
+ + "Adjacency labels for single ports are auto-generated "
+ + "in dpid: {}", label,
+ HexString.toHexString(dpid));
+ }
+ }
}
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 2353fb7..fec88c5 100644
--- a/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
+++ b/src/main/java/net/onrc/onos/core/drivermanager/OFSwitchImplCPqD13.java
@@ -4,9 +4,11 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -30,6 +32,7 @@
import net.onrc.onos.core.configmanager.NetworkConfigManager;
import net.onrc.onos.core.configmanager.PktLinkConfig;
import net.onrc.onos.core.configmanager.SegmentRouterConfig;
+import net.onrc.onos.core.configmanager.SegmentRouterConfig.AdjacencySid;
import net.onrc.onos.core.matchaction.MatchAction;
import net.onrc.onos.core.matchaction.MatchActionOperationEntry;
import net.onrc.onos.core.matchaction.MatchActionOperations;
@@ -55,6 +58,7 @@
import net.onrc.onos.core.util.IPv4Net;
import net.onrc.onos.core.util.PortNumber;
+import org.codehaus.jackson.map.ObjectMapper;
import org.projectfloodlight.openflow.protocol.OFAsyncGetReply;
import org.projectfloodlight.openflow.protocol.OFBarrierRequest;
import org.projectfloodlight.openflow.protocol.OFBucket;
@@ -141,11 +145,11 @@
private ConcurrentMap<PortNumber, Dpid> portToNeighbors;
private List<Integer> segmentIds;
private boolean isEdgeRouter;
- private int sid;
private ConcurrentMap<NeighborSet, EcmpInfo> ecmpGroups;
private ConcurrentMap<String, List<Integer>> tunnelGroupIdTable;
private ConcurrentMap<PortNumber, ArrayList<NeighborSet>> portNeighborSetMap;
private AtomicInteger groupid;
+ private Map<String, String> publishAttributes;
public OFSwitchImplCPqD13(OFDescStatsReply desc, boolean usePipeline13) {
super();
@@ -489,6 +493,7 @@
private void processGroupDesc(OFGroupDescStatsReply gdsr) {
log.info("Sw: {} Group Desc {}", getStringId(), gdsr);
+ // TODO -- actually do verification
try {
nextDriverState();
} catch (IOException e) {
@@ -608,7 +613,6 @@
if (scs.getConfigState() == NetworkConfigState.ACCEPT_ADD) {
srConfig = (SegmentRouterConfig) scs.getSwitchConfig();
isEdgeRouter = srConfig.isEdgeRouter();
- sid = srConfig.getNodeSid();
} else {
log.error("Switch not configured as Segment-Router");
}
@@ -1248,7 +1252,30 @@
}
private void assignAdjacencyLabels() {
- // TODO
+ List<AdjacencySid> autogenAdjSids = new ArrayList<AdjacencySid>();
+ publishAttributes = new HashMap<String, String>();
+ for (OFPortDesc p : getPorts()) {
+ int pnum = p.getPortNo().getPortNumber();
+
+ if (U32.ofRaw(pnum).compareTo(U32.ofRaw(OFPort.MAX.getPortNumber())) >= 1) {
+ continue;
+ }
+ // create unique adj-sid assuming that operator only
+ // enters adjSids for multiple-ports and only in the range
+ // 1-10k XXX make sure that happens
+ int adjSid = srConfig.getNodeSid() * 1000 + pnum;
+ AdjacencySid as = new AdjacencySid(adjSid,
+ Collections.singletonList(pnum));
+ autogenAdjSids.add(as);
+ }
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ publishAttributes.put("autogenAdjSids",
+ mapper.writeValueAsString(autogenAdjSids));
+ } catch (IOException e1) {
+ log.error("Error while writing adjacency labels: {}", e1.getCause());
+ }
+
try {
nextDriverState();
} catch (IOException e) {
@@ -1691,6 +1718,10 @@
return groups.get(0);
}
+ @Override
+ public Map<String, String> getPublishAttributes() {
+ return publishAttributes;
+ }
// *****************************
// Unused
@@ -1956,4 +1987,6 @@
}
}
+
+
}
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java b/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java
index 2fe43ba..66e1b88 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java
@@ -16,6 +16,7 @@
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IFloodlightProviderService.Role;
+import net.floodlightcontroller.core.IOF13Switch;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.IOFSwitch.PortChangeType;
import net.floodlightcontroller.core.IOFSwitchListener;
@@ -390,6 +391,12 @@
for (Entry<String, String> e : attr.entrySet()) {
switchData.createStringAttribute(e.getKey(), e.getValue());
}
+ if (sw instanceof IOF13Switch) {
+ Map<String, String> pa = ((IOF13Switch) sw).getPublishAttributes();
+ for (Entry<String, String> e : pa.entrySet()) {
+ switchData.createStringAttribute(e.getKey(), e.getValue());
+ }
+ }
switchData.createStringAttribute(TopologyElement.ELEMENT_CONFIG_STATE,
ConfigState.CONFIGURED.toString());
} else {