package net.onrc.onos.core.configmanager; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import net.onrc.onos.core.configmanager.NetworkConfig.SwitchConfig; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.JsonProcessingException; import org.codehaus.jackson.map.ObjectMapper; import org.projectfloodlight.openflow.util.HexString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SegmentRouterConfig extends SwitchConfig { protected static final Logger log = LoggerFactory .getLogger(SegmentRouterConfig.class); private String routerIp; private String routerMac; private int nodeSid; private boolean isEdgeRouter; private List<AdjacencySid> adjacencySids; private List<Subnet> subnets; public static final String ROUTER_IP = "routerIp"; public static final String ROUTER_MAC = "routerMac"; public static final String NODE_SID = "nodeSid"; 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()); this.setDpid(swc.getDpid()); this.setType(swc.getType()); this.setLatitude(swc.getLatitude()); this.setLongitude(swc.getLongitude()); this.setParams(swc.getParams()); this.setAllowed(swc.isAllowed()); publishAttributes = new ConcurrentHashMap<String, String>(); adjacencySids = new ArrayList<AdjacencySid>(); subnets = new ArrayList<Subnet>(); parseParams(); validateParams(); setPublishAttributes(); } // ******************** // Segment Router Configuration // ******************** public String getRouterIp() { return routerIp; } public void setRouterIp(String routerIp) { this.routerIp = routerIp; } public String getRouterMac() { return routerMac; } public void setRouterMac(String routerMac) { this.routerMac = routerMac; } public int getNodeSid() { return nodeSid; } public void setNodeSid(int nodeSid) { this.nodeSid = nodeSid; } public boolean isEdgeRouter() { return isEdgeRouter; } public void setIsEdgeRouter(boolean isEdge) { this.isEdgeRouter = isEdge; } public static class AdjacencySid { private int adjSid; private List<Integer> ports; public AdjacencySid(int adjSid, List<Integer> ports) { this.ports = ports; this.adjSid = adjSid; } public List<Integer> getPorts() { return ports; } public void setPorts(List<Integer> ports) { this.ports = ports; } public int getAdjSid() { return adjSid; } public void setAdjSid(int adjSid) { this.adjSid = adjSid; } } public List<AdjacencySid> getAdjacencySids() { return adjacencySids; } public void setAdjacencySids(List<AdjacencySid> adjacencySids) { this.adjacencySids = adjacencySids; } public static class Subnet { private int portNo; private String subnetIp; public Subnet(int portNo, String subnetIp) { this.portNo = portNo; this.subnetIp = subnetIp; } public int getPortNo() { return portNo; } public void setPortNo(int portNo) { this.portNo = portNo; } public String getSubnetIp() { return subnetIp; } public void setSubnetIp(String subnetIp) { this.subnetIp = subnetIp; } } public List<Subnet> getSubnets() { return subnets; } public void setSubnets(List<Subnet> subnets) { this.subnets = subnets; } // ******************** // Helper methods // ******************** private void parseParams() { if (params == null) { throw new NetworkConfigException.ParamsNotSpecified(name); } Set<Entry<String, JsonNode>> m = params.entrySet(); for (Entry<String, JsonNode> e : m) { String key = e.getKey(); JsonNode j = e.getValue(); if (key.equals("routerIp")) { setRouterIp(j.asText()); } else if (key.equals("routerMac")) { setRouterMac(j.asText()); } else if (key.equals("nodeSid")) { setNodeSid(j.asInt()); } else if (key.equals("isEdgeRouter")) { setIsEdgeRouter(j.asBoolean()); } else if (key.equals("adjacencySids") || key.equals("subnets")) { getInnerParams(j, key); } else { throw new UnknownSegmentRouterConfig(key, dpid); } } } private void getInnerParams(JsonNode j, String innerParam) { Iterator<JsonNode> innerList = j.getElements(); while (innerList.hasNext()) { Iterator<Entry<String, JsonNode>> f = innerList.next().getFields(); 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")) { portNo = fe.getValue().asInt(); } else if (fe.getKey().equals("adjSid")) { 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(adjSid, ports); adjacencySids.add(ads); } else { Subnet sip = new Subnet(portNo, subnetIp); subnets.add(sip); } } } private void validateParams() { if (routerIp == null) { throw new IpNotSpecified(dpid); } if (isEdgeRouter && subnets.isEmpty()) { throw new SubnetNotSpecifiedInEdgeRouter(dpid); } 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 } /** * Setting publishAttributes implies that this is the configuration that * will be added to Topology.Switch object before it is published on the * channel to other controller instances. */ private void setPublishAttributes() { publishAttributes.put(ROUTER_IP, routerIp); publishAttributes.put(ROUTER_MAC, routerMac); publishAttributes.put(NODE_SID, String.valueOf(nodeSid)); publishAttributes.put(ISEDGE, String.valueOf(isEdgeRouter)); ObjectMapper mapper = new ObjectMapper(); try { publishAttributes.put(ADJACENCY_SIDS, mapper.writeValueAsString(adjacencySids)); publishAttributes.put(SUBNETS, mapper.writeValueAsString(subnets)); } catch (JsonProcessingException e) { log.error("Error while writing SR config: {}", e.getCause()); } catch (IOException e) { log.error("Error while writing SR config: {}", e.getCause()); } } // ******************** // Exceptions // ******************** public static class IpNotSpecified extends RuntimeException { private static final long serialVersionUID = -3001502553646331686L; public IpNotSpecified(long dpid) { super(); log.error("Router IP address not specified for SR config dpid:{}", HexString.toHexString(dpid)); } } public static class UnknownSegmentRouterConfig extends RuntimeException { private static final long serialVersionUID = -5750132094884129179L; public UnknownSegmentRouterConfig(String key, long dpid) { super(); log.error("Unknown Segment Router config {} in dpid: {}", key, HexString.toHexString(dpid)); } } public static class SubnetNotSpecifiedInEdgeRouter extends RuntimeException { private static final long serialVersionUID = -5855458472668581268L; public SubnetNotSpecifiedInEdgeRouter(long dpid) { super(); log.error("Subnet was not specified for edge router in dpid: {}", HexString.toHexString(dpid)); } } public static class SubnetSpecifiedInBackboneRouter extends RuntimeException { private static final long serialVersionUID = 1L; public SubnetSpecifiedInBackboneRouter(long dpid) { super(); log.error("Subnet was specified in backbone router in dpid: {}", HexString.toHexString(dpid)); } } 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)); } } }