Ayaka Koshibe

Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next

Showing 162 changed files with 3767 additions and 185 deletions
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-apps</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-calendar</artifactId>
<packaging>bundle</packaging>
<description>ONOS simple calendaring REST interface for intents</description>
<properties>
<web.context>/onos/calendar</web.context>
</properties>
<dependencies>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onlab-rest</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-servlet</artifactId>
</dependency>
<dependency>
<groupId>com.sun.jersey.jersey-test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>1.18.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey.jersey-test-framework</groupId>
<artifactId>jersey-test-framework-grizzly2</artifactId>
<version>1.18.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<_wab>src/main/webapp/</_wab>
<Bundle-SymbolicName>
${project.groupId}.${project.artifactId}
</Bundle-SymbolicName>
<Import-Package>
org.osgi.framework,
javax.ws.rs,javax.ws.rs.core,
com.sun.jersey.api.core,
com.sun.jersey.spi.container.servlet,
com.sun.jersey.server.impl.container.servlet,
org.onlab.packet.*,
org.onlab.rest.*,
org.onlab.onos.*
</Import-Package>
<Web-ContextPath>${web.context}</Web-ContextPath>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
package org.onlab.onos.calendar;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.rest.BaseResource;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
import java.net.URI;
import static org.onlab.onos.net.PortNumber.portNumber;
/**
* Web resource for triggering calendared intents.
*/
@Path("intent")
public class BandwidthCalendarResource extends BaseResource {
@POST
@Path("{src}/{dst}/{srcPort}/{dstPort}/{bandwidth}")
public Response createIntent(@PathParam("src") String src,
@PathParam("dst") String dst,
@PathParam("srcPort") String srcPort,
@PathParam("dstPort") String dstPort,
@PathParam("bandwidth") String bandwidth) {
// TODO: implement calls to intent framework
IntentService service = get(IntentService.class);
ConnectPoint srcPoint = new ConnectPoint(deviceId(src), portNumber(srcPort));
ConnectPoint dstPoint = new ConnectPoint(deviceId(dst), portNumber(dstPort));
return Response.ok("Yo! We got src=" + srcPoint + "; dst=" + dstPoint +
"; bw=" + bandwidth + "; intent service " + service).build();
}
private DeviceId deviceId(String dpid) {
return DeviceId.deviceId(URI.create("of:" + dpid));
}
}
/**
* Application providing integration between OSCARS and ONOS intent
* framework via REST API.
*/
package org.onlab.onos.calendar;
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="ONOS" version="2.5">
<display-name>ONOS GUI</display-name>
<servlet>
<servlet-name>JAX-RS Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>org.onlab.onos.calendar</param-value>
</init-param>
<load-on-startup>10</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Service</servlet-name>
<url-pattern>/rs/*</url-pattern>
</servlet-mapping>
</web-app>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-apps</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-app-optical</artifactId>
<packaging>bundle</packaging>
<description>ONOS application for packet/optical deployments</description>
<dependencies>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-cli</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
package org.onlab.onos.optical.cfg;
import java.util.Map;
import org.codehaus.jackson.JsonNode;
import org.onlab.util.HexString;
/**
* Public class corresponding to JSON described data model.
*/
public class OpticalLinkDescription {
protected String type;
protected Boolean allowed;
protected long dpid1;
protected long dpid2;
protected String nodeDpid1;
protected String nodeDpid2;
protected Map<String, JsonNode> params;
protected Map<String, String> publishAttributes;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Boolean isAllowed() {
return allowed;
}
public void setAllowed(Boolean allowed) {
this.allowed = allowed;
}
public String getNodeDpid1() {
return nodeDpid1;
}
public void setNodeDpid1(String nodeDpid1) {
this.nodeDpid1 = nodeDpid1;
this.dpid1 = HexString.toLong(nodeDpid1);
}
public String getNodeDpid2() {
return nodeDpid2;
}
public void setNodeDpid2(String nodeDpid2) {
this.nodeDpid2 = nodeDpid2;
this.dpid2 = HexString.toLong(nodeDpid2);
}
public long getDpid1() {
return dpid1;
}
public void setDpid1(long dpid1) {
this.dpid1 = dpid1;
this.nodeDpid1 = HexString.toHexString(dpid1);
}
public long getDpid2() {
return dpid2;
}
public void setDpid2(long dpid2) {
this.dpid2 = dpid2;
this.nodeDpid2 = HexString.toHexString(dpid2);
}
public Map<String, JsonNode> getParams() {
return params;
}
public void setParams(Map<String, JsonNode> params) {
this.params = params;
}
public Map<String, String> getPublishAttributes() {
return publishAttributes;
}
public void setPublishAttributes(Map<String, String> publishAttributes) {
this.publishAttributes = publishAttributes;
}
}
package org.onlab.onos.optical.cfg;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Public class corresponding to JSON described data model.
*/
public class OpticalNetworkConfig {
protected static final Logger log = LoggerFactory.getLogger(OpticalNetworkConfig.class);
private List<OpticalSwitchDescription> opticalSwitches;
private List<OpticalLinkDescription> opticalLinks;
public OpticalNetworkConfig() {
opticalSwitches = new ArrayList<OpticalSwitchDescription>();
opticalLinks = new ArrayList<OpticalLinkDescription>();
}
public List<OpticalSwitchDescription> getOpticalSwitches() {
return opticalSwitches;
}
public void setOpticalSwitches(List<OpticalSwitchDescription> switches) {
this.opticalSwitches = switches;
}
public List<OpticalLinkDescription> getOpticalLinks() {
return opticalLinks;
}
public void setOpticalLinks(List<OpticalLinkDescription> links) {
this.opticalLinks = links;
}
}
package org.onlab.onos.optical.cfg;
import java.util.Map;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.annotate.JsonProperty;
import org.onlab.util.HexString;
/**
* Public class corresponding to JSON described data model.
*/
public class OpticalSwitchDescription {
protected String name;
protected long dpid;
protected String nodeDpid;
protected String type;
protected double latitude;
protected double longitude;
protected boolean allowed;
protected Map<String, JsonNode> params;
protected Map<String, String> publishAttributes;
public String getName() {
return name;
}
@JsonProperty("name")
public void setName(String name) {
this.name = name;
}
public long getDpid() {
return dpid;
}
@JsonProperty("dpid")
public void setDpid(long dpid) {
this.dpid = dpid;
this.nodeDpid = HexString.toHexString(dpid);
}
public String getNodeDpid() {
return nodeDpid;
}
public String getHexDpid() {
return nodeDpid;
}
public void setNodeDpid(String nodeDpid) {
this.nodeDpid = nodeDpid;
this.dpid = HexString.toLong(nodeDpid);
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public boolean isAllowed() {
return allowed;
}
public void setAllowed(boolean allowed) {
this.allowed = allowed;
}
public Map<String, JsonNode> getParams() {
return params;
}
public void setParams(Map<String, JsonNode> params) {
this.params = params;
}
public Map<String, String> getPublishAttributes() {
return publishAttributes;
}
public void setPublishAttributes(Map<String, String> publishAttributes) {
this.publishAttributes = publishAttributes;
}
}
package org.onlab.onos.optical.cfg;
/**
* Packet-optical link Java data object.
*/
class PktOptLink {
private String srcNodeName;
private String snkNodeName;
private String srcNodeId;
private String snkNodeId;
private int srcPort;
private int snkPort;
private double bandwidth;
private double cost;
private long adminWeight;
public PktOptLink(String srcName, String snkName) {
this.srcNodeName = srcName;
this.snkNodeName = snkName;
}
public PktOptLink() {
// TODO Auto-generated constructor stub
}
public void setSrcNodeName(String name) {
this.srcNodeName = name;
}
public String getSrcNodeName() {
return this.srcNodeName;
}
public void setSnkNodeName(String name) {
this.snkNodeName = name;
}
public String getSnkNodeName() {
return this.snkNodeName;
}
public void setSrcNodeId(String nodeId) {
this.srcNodeId = nodeId;
}
public String getSrcNodeId() {
return this.srcNodeId;
}
public void setSnkNodeId(String nodeId) {
this.snkNodeId = nodeId;
}
public String getSnkNodeId() {
return this.snkNodeId;
}
public void setSrcPort(int port) {
this.srcPort = port;
}
public int getSrcPort() {
return this.srcPort;
}
public void setSnkPort(int port) {
this.snkPort = port;
}
public int getSnkPort() {
return this.snkPort;
}
public void setBandwdith(double x) {
this.bandwidth = x;
}
public double getBandwidth() {
return this.bandwidth;
}
public void setCost(double x) {
this.cost = x;
}
public double getCost() {
return this.cost;
}
public void setAdminWeight(long x) {
this.adminWeight = x;
}
public long getAdminWeight() {
return this.adminWeight;
}
@Override
public String toString() {
return new StringBuilder(" srcNodeName: ").append(this.srcNodeName)
.append(" snkNodeName: ").append(this.snkNodeName)
.append(" srcNodeId: ").append(this.srcNodeId)
.append(" snkNodeId: ").append(this.snkNodeId)
.append(" srcPort: ").append(this.srcPort)
.append(" snkPort: ").append(this.snkPort)
.append(" bandwidth: ").append(this.bandwidth)
.append(" cost: ").append(this.cost)
.append(" adminWeight: ").append(this.adminWeight).toString();
}
}
package org.onlab.onos.optical.cfg;
/**
* ROADM java data object converted from a JSON file.
*/
class Roadm {
private String name;
private String nodeID;
private double longtitude;
private double latitude;
private int regenNum;
//TODO use the following attributes when needed for configurations
private int tPort10G;
private int tPort40G;
private int tPort100G;
private int wPort;
public Roadm() {
}
public Roadm(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setNodeId(String nameId) {
this.nodeID = nameId;
}
public String getNodeId() {
return this.nodeID;
}
public void setLongtitude(double x) {
this.longtitude = x;
}
public double getLongtitude() {
return this.longtitude;
}
public void setLatitude(double y) {
this.latitude = y;
}
public double getLatitude() {
return this.latitude;
}
public void setRegenNum(int num) {
this.regenNum = num;
}
public int getRegenNum() {
return this.regenNum;
}
public void setTport10GNum(int num) {
this.tPort10G = num;
}
public int getTport10GNum() {
return this.tPort10G;
}
public void setTport40GNum(int num) {
this.tPort40G = num;
}
public int getTport40GNum() {
return this.tPort40G;
}
public void setTport100GNum(int num) {
this.tPort100G = num;
}
public int getTport100GNum() {
return this.tPort100G;
}
public void setWportNum(int num) {
this.wPort = num;
}
public int getWportNum() {
return this.wPort;
}
@Override
public String toString() {
return new StringBuilder(" ROADM Name: ").append(this.name)
.append(" nodeID: ").append(this.nodeID)
.append(" longtitude: ").append(this.longtitude)
.append(" latitude: ").append(this.latitude)
.append(" regenNum: ").append(this.regenNum)
.append(" 10GTportNum: ").append(this.tPort10G)
.append(" 40GTportNum: ").append(this.tPort40G)
.append(" 100GTportNum: ").append(this.tPort100G)
.append(" WportNum: ").append(this.wPort).toString();
}
}
package org.onlab.onos.optical.cfg;
/**
* WDM Link Java data object converted from a JSON file.
*/
class WdmLink {
private String srcNodeName;
private String snkNodeName;
private String srcNodeId;
private String snkNodeId;
private int srcPort;
private int snkPort;
private double distance;
private double cost;
private int wavelengthNumber;
private long adminWeight;
public WdmLink(String name1, String name2) {
this.srcNodeName = name1;
this.snkNodeName = name2;
}
public WdmLink() {
// TODO Auto-generated constructor stub
}
public void setSrcNodeName(String name) {
this.srcNodeName = name;
}
public String getSrcNodeName() {
return this.srcNodeName;
}
public void setSnkNodeName(String name) {
this.snkNodeName = name;
}
public String getSnkNodeName() {
return this.snkNodeName;
}
public void setSrcNodeId(String nodeId) {
this.srcNodeId = nodeId;
}
public String getSrcNodeId() {
return this.srcNodeId;
}
public void setSnkNodeId(String nodeId) {
this.snkNodeId = nodeId;
}
public String getSnkNodeId() {
return this.snkNodeId;
}
public void setSrcPort(int port) {
this.srcPort = port;
}
public int getSrcPort() {
return this.srcPort;
}
public void setSnkPort(int port) {
this.snkPort = port;
}
public int getSnkPort() {
return this.snkPort;
}
public void setDistance(double x) {
this.distance = x;
}
public double getDistance() {
return this.distance;
}
public void setCost(double x) {
this.cost = x;
}
public double getCost() {
return this.cost;
}
public void setWavelengthNumber(int x) {
this.wavelengthNumber = x;
}
public int getWavelengthNumber() {
return this.wavelengthNumber;
}
public void setAdminWeight(long x) {
this.adminWeight = x;
}
public long getAdminWeight() {
return this.adminWeight;
}
@Override
public String toString() {
return new StringBuilder(" srcNodeName: ").append(this.srcNodeName)
.append(" snkNodeName: ").append(this.snkNodeName)
.append(" srcNodeId: ").append(this.srcNodeId)
.append(" snkNodeId: ").append(this.snkNodeId)
.append(" srcPort: ").append(this.srcPort)
.append(" snkPort: ").append(this.snkPort)
.append(" distance: ").append(this.distance)
.append(" cost: ").append(this.cost)
.append(" wavelengthNumber: ").append(this.wavelengthNumber)
.append(" adminWeight: ").append(this.adminWeight).toString();
}
}
{
"opticalSwitches": [
{
"allowed": true,
"latitude": 37.6,
"longitude": 122.3,
"name": "SFO-W10",
"nodeDpid": "00:00:ff:ff:ff:ff:ff:01",
"params": {
"numRegen": 0
},
"type": "Roadm"
},
{
"allowed": true,
"latitude": 37.3,
"longitude": 121.9,
"name": "SJC-W10",
"nodeDpid": "00:00:ff:ff:ff:ff:ff:02",
"params": {
"numRegen": 0
},
"type": "Roadm"
},
{
"allowed": true,
"latitude": 33.9,
"longitude": 118.4
"name": "LAX-W10",
"nodeDpid": "00:00:ff:ff:ff:ff:ff:03",
"params": {
"numRegen": 0
},
"type": "Roadm"
},
{
"allowed": true,
"latitude": 32.8,
"longitude": 117.1,
"name": "SDG-W10",
"nodeDpid": "00:00:ff:ff:ff:ff:ff:04",
"params": {
"numRegen": 3
},
"type": "Roadm"
},
{
"allowed": true,
"latitude": 44.8,
"longitude": 93.1,
"name": "MSP-M10",
"nodeDpid": "00:00:ff:ff:ff:ff:ff:05",
"params": {
"numRegen": 3
},
"type": "Roadm"
},
{
"allowed": true,
"latitude": 32.8,
"longitude": 97.1,
"name": "DFW-M10",
"nodeDpid": "00:00:ff:ff:ff:ff:ff:06",
"params": {
"numRegen": 3
},
"type": "Roadm"
},
{
"allowed": true,
"latitude": 41.8,
"longitude": 120.1,
"name": "CHG-N10",
"nodeDpid": "00:00:ff:ff:ff:ff:ff:07",
"params": {
"numRegen": 3
},
"type": "Roadm"
},
{
"allowed": true,
"latitude": 38.8,
"longitude": 77.1,
"name": "IAD-M10",
"nodeDpid": "00:00:ff:ff:ff:ff:ff:08",
"params": {
"numRegen": 3
},
"type": "Roadm"
},
{
"allowed": true,
"latitude": 40.8,
"longitude": 73.1,
"name": "JFK-E10",
"nodeDpid": "00:00:ff:ff:ff:ff:ff:09",
"params": {
"numRegen": 0
},
"type": "Roadm"
},
{
"allowed": true,
"latitude": 33.8,
"longitude": 84.1,
"name": "ATL-S10",
"nodeDpid": "00:00:ff:ff:ff:ff:ff:0A",
"params": {
"numRegen": 0
},
"type": "Roadm"
}
],
"opticalLinks": [
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:01",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:02",
"params": {
"distKms": 1000,
"nodeName1": "SFO-W10",
"nodeName2": "SJC-W10",
"numWaves": 80,
"port1": 10,
"port2": 10
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:02",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:03",
"params": {
"distKms": 1000,
"nodeName1": "SJC-W10",
"nodeName2": "LAX-W10",
"numWaves": 80,
"port1": 20,
"port2": 10
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:03",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:04",
"params": {
"distKms": 1000,
"nodeName1": "LAX-W10",
"nodeName2": "SDG-W10",
"numWaves": 80,
"port1": 30,
"port2": 10
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:02",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:05",
"params": {
"distKms": 4000,
"nodeName1": "SJC-W10",
"nodeName2": "MSP-M10",
"numWaves": 80,
"port1": 20,
"port2": 10
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:03",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:06",
"params": {
"distKms": 5000,
"nodeName1": "LAX-W10",
"nodeName2": "DFW-M10",
"numWaves": 80,
"port1": 20,
"port2": 10
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:05",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:06",
"params": {
"distKms": 3000,
"nodeName1": "MSP-M10",
"nodeName2": "DFW-M10",
"numWaves": 80,
"port1": 30,
"port2": 20
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:05",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:07",
"params": {
"distKms": 3000,
"nodeName1": "MSP-M10",
"nodeName2": "CHG-N10",
"numWaves": 80,
"port1": 20,
"port2": 21
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:06",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:08",
"params": {
"distKms": 4000,
"nodeName1": "DFW-M10",
"nodeName2": "IAD-M10",
"numWaves": 80,
"port1": 30,
"port2": 10
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:07",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:08",
"params": {
"distKms": 4000,
"nodeName1": "CHG-M10",
"nodeName2": "IAD-M10",
"numWaves": 80,
"port1": 30,
"port2": 20
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:07",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:09",
"params": {
"distKms": 5000,
"nodeName1": "CHG-M10",
"nodeName2": "JFK-E10",
"numWaves": 80,
"port1": 20,
"port2": 10
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:08",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:0A",
"params": {
"distKms": 3000,
"nodeName1": "IAD-M10",
"nodeName2": "ATL-S10",
"numWaves": 80,
"port1": 30,
"port2": 10
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:09",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:0A",
"params": {
"distKms": 4000,
"nodeName1": "JFK-E10",
"nodeName2": "ATL-S10",
"numWaves": 80,
"port1": 20,
"port2": 20
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:00:01",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:01",
"params": {
"nodeName1": "SFO-R10",
"nodeName2": "SFO-W10",
"port1": 10,
"port2": 1
},
"type": "pktOptLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:00:03",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:03",
"params": {
"nodeName1": "LAX-R10",
"nodeName2": "LAX-W10",
"port1": 10,
"port2": 1
},
"type": "pktOptLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:00:04",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:04",
"params": {
"nodeName1": "SDG-R10",
"nodeName2": "SDG-W10",
"port1": 10,
"port2": 1
},
"type": "pktOptLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:00:07",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:07",
"params": {
"nodeName1": "CHG-R10",
"nodeName2": "CHG-W10",
"port1": 10,
"port2": 1
},
"type": "pktOptLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:00:09",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:09",
"params": {
"nodeName1": "JFK-R10",
"nodeName2": "JFK-W10",
"port1": 10,
"port2": 1
},
"type": "pktOptLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:00:0A",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:0A",
"params": {
"nodeName1": "ATL-R10",
"nodeName2": "ATL-W10",
"port1": 10,
"port2": 1
},
"type": "pktOptLink"
},
]
}
{
"opticalSwitches": [
{
"allowed": true,
"latitude": 37.6,
"longitude": 122.3,
"name": "ROADM1",
"nodeDpid": "00:00:ff:ff:ff:ff:ff:01",
"params": {
"numRegen": 0
},
"type": "Roadm"
},
{
"allowed": true,
"latitude": 37.3,
"longitude": 121.9,
"name": "ROADM2",
"nodeDpid": "00:00:ff:ff:ff:ff:ff:02",
"params": {
"numRegen": 0
},
"type": "Roadm"
},
{
"allowed": true,
"latitude": 33.9,
"longitude": 118.4,
"name": "ROADM3",
"nodeDpid": "00:00:ff:ff:ff:ff:ff:03",
"params": {
"numRegen": 2
},
"type": "Roadm"
}
],
"opticalLinks": [
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:01",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:03",
"params": {
"distKms": 1000,
"nodeName1": "ROADM1",
"nodeName2": "ROADM3",
"numWaves": 80,
"port1": 10,
"port2": 30
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:ff:03",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:02",
"params": {
"distKms": 2000,
"nodeName1": "ROADM3",
"nodeName2": "ROADM2",
"numWaves": 80,
"port1": 31,
"port2": 20
},
"type": "wdmLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:00:01",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:01",
"params": {
"nodeName1": "ROUTER1",
"nodeName2": "ROADM1",
"bandWidth": 100000,
"port1": 10,
"port2": 11
},
"type": "pktOptLink"
},
{
"allowed": true,
"nodeDpid1": "00:00:ff:ff:ff:ff:00:02",
"nodeDpid2": "00:00:ff:ff:ff:ff:ff:02",
"params": {
"nodeName1": "ROUTER2",
"nodeName2": "ROADM2",
"bandWidth": 100000,
"port1": 10,
"port2": 21
},
"type": "pktOptLink"
}
]
}
......@@ -25,6 +25,8 @@
<module>proxyarp</module>
<module>config</module>
<module>sdnip</module>
<module>calendar</module>
<module>optical</module>
</modules>
<properties>
......
......@@ -42,6 +42,30 @@
<artifactId>onlab-thirdparty</artifactId>
</dependency>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onlab-misc</artifactId>
</dependency>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-cli</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
......
......@@ -25,10 +25,10 @@ import org.slf4j.LoggerFactory;
/**
* Manages the connectivity requirements between peers.
*/
public class PeerConnectivity {
public class PeerConnectivityManager {
private static final Logger log = LoggerFactory.getLogger(
PeerConnectivity.class);
PeerConnectivityManager.class);
// TODO these shouldn't be defined here
private static final short BGP_PORT = 179;
......@@ -41,7 +41,7 @@ public class PeerConnectivity {
// TODO this sucks.
private int intentId = 0;
public PeerConnectivity(SdnIpConfigService configInfoService,
public PeerConnectivityManager(SdnIpConfigService configInfoService,
InterfaceService interfaceService, IntentService intentService) {
this.configInfoService = configInfoService;
this.interfaceService = interfaceService;
......
......@@ -62,10 +62,8 @@ public class Router implements RouteListener {
private static final Logger log = LoggerFactory.getLogger(Router.class);
// Store all route updates in a InvertedRadixTree.
// The key in this Tree is the binary sting of prefix of route.
// The Ip4Address is the next hop address of route, and is also the value
// of each entry.
// Store all route updates in a radix tree.
// The key in this tree is the binary string of prefix of the route.
private InvertedRadixTree<RouteEntry> bgpRoutes;
// Stores all incoming route updates in a queue.
......@@ -102,7 +100,7 @@ public class Router implements RouteListener {
* Class constructor.
*
* @param intentService the intent service
* @param proxyArp the proxy ARP service
* @param hostService the host service
* @param configInfoService the configuration service
* @param interfaceService the interface service
*/
......@@ -135,6 +133,10 @@ public class Router implements RouteListener {
*/
public void start() {
// TODO hack to enable SDN-IP now for testing
isElectedLeader = true;
isActivatedLeader = true;
bgpUpdatesExecutor.execute(new Runnable() {
@Override
public void run() {
......@@ -441,8 +443,8 @@ public class Router implements RouteListener {
/**
* Processes adding a route entry.
* <p/>
* Put new route entry into InvertedRadixTree. If there was an existing
* nexthop for this prefix, but the next hop was different, then execute
* Put new route entry into the radix tree. If there was an existing
* next hop for this prefix, but the next hop was different, then execute
* deleting old route entry. If the next hop is the SDN domain, we do not
* handle it at the moment. Otherwise, execute adding a route.
*
......@@ -623,8 +625,8 @@ public class Router implements RouteListener {
/**
* Executes deleting a route entry.
* <p/>
* Removes prefix from InvertedRadixTree, if success, then try to delete
* the relative intent.
* Removes prefix from radix tree, and if successful, then try to delete
* the related intent.
*
* @param routeEntry the route entry to delete
*/
......@@ -690,9 +692,9 @@ public class Router implements RouteListener {
public void arpResponse(IpAddress ipAddress, MacAddress macAddress) {
log.debug("Received ARP response: {} => {}", ipAddress, macAddress);
// We synchronize on this to prevent changes to the InvertedRadixTree
// while we're pushing intent. If the InvertedRadixTree changes, the
// InvertedRadixTree and intent could get out of sync.
// We synchronize on this to prevent changes to the radix tree
// while we're pushing intents. If the tree changes, the
// tree and intents could get out of sync.
synchronized (this) {
Set<RouteEntry> routesToPush =
......@@ -709,14 +711,14 @@ public class Router implements RouteListener {
log.debug("Pushing prefix {} next hop {}",
routeEntry.prefix(), routeEntry.nextHop());
// We only push prefix flows if the prefix is still in the
// InvertedRadixTree and the next hop is the same as our
// radix tree and the next hop is the same as our
// update.
// The prefix could have been removed while we were waiting
// for the ARP, or the next hop could have changed.
addRouteIntentToNextHop(prefix, ipAddress, macAddress);
} else {
log.debug("Received ARP response, but {}/{} is no longer in"
+ " InvertedRadixTree", routeEntry.prefix(),
+ " the radix tree", routeEntry.prefix(),
routeEntry.nextHop());
}
}
......
......@@ -2,14 +2,18 @@ package org.onlab.onos.sdnip;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Collection;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.intent.IntentService;
import org.onlab.onos.sdnip.RouteUpdate.Type;
import org.onlab.onos.sdnip.bgp.BgpRouteEntry;
import org.onlab.onos.sdnip.bgp.BgpSessionManager;
import org.onlab.onos.sdnip.config.SdnIpConfigReader;
import org.onlab.packet.IpAddress;
......@@ -17,10 +21,11 @@ import org.onlab.packet.IpPrefix;
import org.slf4j.Logger;
/**
* Placeholder SDN-IP component.
* Component for the SDN-IP peering application.
*/
@Component(immediate = true)
public class SdnIp {
@Service
public class SdnIp implements SdnIpService {
private final Logger log = getLogger(getClass());
......@@ -31,7 +36,7 @@ public class SdnIp {
protected HostService hostService;
private SdnIpConfigReader config;
private PeerConnectivity peerConnectivity;
private PeerConnectivityManager peerConnectivity;
private Router router;
private BgpSessionManager bgpSessionManager;
......@@ -44,7 +49,7 @@ public class SdnIp {
InterfaceService interfaceService = new HostServiceBasedInterfaceService(hostService);
peerConnectivity = new PeerConnectivity(config, interfaceService, intentService);
peerConnectivity = new PeerConnectivityManager(config, interfaceService, intentService);
peerConnectivity.start();
router = new Router(intentService, hostService, config, interfaceService);
......@@ -64,4 +69,18 @@ public class SdnIp {
protected void deactivate() {
log.info("Stopped");
}
@Override
public Collection<BgpRouteEntry> getBgpRoutes() {
return bgpSessionManager.getBgpRoutes();
}
@Override
public Collection<RouteEntry> getRoutes() {
return router.getRoutes();
}
static String dpidToUri(String dpid) {
return "of:" + dpid.replace(":", "");
}
}
......
package org.onlab.onos.sdnip;
import java.util.Collection;
import org.onlab.onos.sdnip.bgp.BgpRouteEntry;
/**
* Service interface exported by SDN-IP.
*/
public interface SdnIpService {
/**
* Gets the BGP routes.
*
* @return the BGP routes
*/
public Collection<BgpRouteEntry> getBgpRoutes();
/**
* Gets all the routes known to SDN-IP.
*
* @return the SDN-IP routes
*/
public Collection<RouteEntry> getRoutes();
}
package org.onlab.onos.sdnip.cli;
import org.apache.karaf.shell.commands.Command;
import org.onlab.onos.cli.AbstractShellCommand;
import org.onlab.onos.sdnip.SdnIpService;
import org.onlab.onos.sdnip.bgp.BgpConstants;
import org.onlab.onos.sdnip.bgp.BgpRouteEntry;
/**
* Command to show the routes learned through BGP.
*/
@Command(scope = "onos", name = "bgp-routes",
description = "Lists all routes received from BGP")
public class BgpRoutesListCommand extends AbstractShellCommand {
private static final String FORMAT =
"prefix=%s, nexthop=%s, origin=%s, localpref=%s, med=%s, aspath=%s, bgpid=%s";
@Override
protected void execute() {
SdnIpService service = get(SdnIpService.class);
for (BgpRouteEntry route : service.getBgpRoutes()) {
printRoute(route);
}
}
private void printRoute(BgpRouteEntry route) {
if (route != null) {
print(FORMAT, route.prefix(), route.nextHop(),
originToString(route.getOrigin()), route.getLocalPref(),
route.getMultiExitDisc(), route.getAsPath(),
route.getBgpSession().getRemoteBgpId());
}
}
private static String originToString(int origin) {
String originString = "UNKNOWN";
switch (origin) {
case BgpConstants.Update.Origin.IGP:
originString = "IGP";
break;
case BgpConstants.Update.Origin.EGP:
originString = "EGP";
break;
case BgpConstants.Update.Origin.INCOMPLETE:
originString = "INCOMPLETE";
break;
default:
break;
}
return originString;
}
}
package org.onlab.onos.sdnip.cli;
import org.apache.karaf.shell.commands.Command;
import org.onlab.onos.cli.AbstractShellCommand;
import org.onlab.onos.sdnip.RouteEntry;
import org.onlab.onos.sdnip.SdnIpService;
/**
* Command to show the list of routes in SDN-IP's routing table.
*/
@Command(scope = "onos", name = "routes",
description = "Lists all routes known to SDN-IP")
public class RoutesListCommand extends AbstractShellCommand {
private static final String FORMAT =
"prefix=%s, nexthop=%s";
@Override
protected void execute() {
SdnIpService service = get(SdnIpService.class);
for (RouteEntry route : service.getRoutes()) {
printRoute(route);
}
}
private void printRoute(RouteEntry route) {
if (route != null) {
print(FORMAT, route.prefix(), route.nextHop());
}
}
}
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command>
<action class="org.onlab.onos.sdnip.cli.BgpRoutesListCommand"/>
</command>
<command>
<action class="org.onlab.onos.sdnip.cli.RoutesListCommand"/>
</command>
</command-bundle>
</blueprint>
package org.onlab.onos.sdnip.bgp;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import org.junit.Test;
/**
* Unit tests for the BgpRouteEntry.AsPath class.
*/
public class AsPathTest {
/**
* Generates an AS Path.
*
* @return a generated AS Path
*/
private BgpRouteEntry.AsPath generateAsPath() {
ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
segmentAsNumbers1.add((long) 1);
segmentAsNumbers1.add((long) 2);
segmentAsNumbers1.add((long) 3);
BgpRouteEntry.PathSegment pathSegment1 =
new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
pathSegments.add(pathSegment1);
//
byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
segmentAsNumbers2.add((long) 4);
segmentAsNumbers2.add((long) 5);
segmentAsNumbers2.add((long) 6);
BgpRouteEntry.PathSegment pathSegment2 =
new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
pathSegments.add(pathSegment2);
//
BgpRouteEntry.AsPath asPath = new BgpRouteEntry.AsPath(pathSegments);
return asPath;
}
/**
* Tests valid class constructor.
*/
@Test
public void testConstructor() {
BgpRouteEntry.AsPath asPath = generateAsPath();
String expectedString =
"AsPath{pathSegments=" +
"[PathSegment{type=2, segmentAsNumbers=[1, 2, 3]}, " +
"PathSegment{type=1, segmentAsNumbers=[4, 5, 6]}]}";
assertThat(asPath.toString(), is(expectedString));
}
/**
* Tests invalid class constructor for null Path Segments.
*/
@Test(expected = NullPointerException.class)
public void testInvalidConstructorNullPathSegments() {
ArrayList<BgpRouteEntry.PathSegment> pathSegments = null;
new BgpRouteEntry.AsPath(pathSegments);
}
/**
* Tests getting the fields of an AS Path.
*/
@Test
public void testGetFields() {
// Create the fields to compare against
ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
segmentAsNumbers1.add((long) 1);
segmentAsNumbers1.add((long) 2);
segmentAsNumbers1.add((long) 3);
BgpRouteEntry.PathSegment pathSegment1 =
new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
pathSegments.add(pathSegment1);
//
byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
segmentAsNumbers2.add((long) 4);
segmentAsNumbers2.add((long) 5);
segmentAsNumbers2.add((long) 6);
BgpRouteEntry.PathSegment pathSegment2 =
new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
pathSegments.add(pathSegment2);
// Generate the entry to test
BgpRouteEntry.AsPath asPath = generateAsPath();
assertThat(asPath.getPathSegments(), is(pathSegments));
}
/**
* Tests getting the AS Path Length.
*/
@Test
public void testGetAsPathLength() {
BgpRouteEntry.AsPath asPath = generateAsPath();
assertThat(asPath.getAsPathLength(), is(4));
// Create an empty AS Path
ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
asPath = new BgpRouteEntry.AsPath(pathSegments);
assertThat(asPath.getAsPathLength(), is(0));
}
/**
* Tests equality of {@link BgpRouteEntry.AsPath}.
*/
@Test
public void testEquality() {
BgpRouteEntry.AsPath asPath1 = generateAsPath();
BgpRouteEntry.AsPath asPath2 = generateAsPath();
assertThat(asPath1, is(asPath2));
}
/**
* Tests non-equality of {@link BgpRouteEntry.AsPath}.
*/
@Test
public void testNonEquality() {
BgpRouteEntry.AsPath asPath1 = generateAsPath();
// Setup AS Path 2
ArrayList<BgpRouteEntry.PathSegment> pathSegments = new ArrayList<>();
byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
ArrayList<Long> segmentAsNumbers1 = new ArrayList<>();
segmentAsNumbers1.add((long) 1);
segmentAsNumbers1.add((long) 2);
segmentAsNumbers1.add((long) 3);
BgpRouteEntry.PathSegment pathSegment1 =
new BgpRouteEntry.PathSegment(pathSegmentType1, segmentAsNumbers1);
pathSegments.add(pathSegment1);
//
byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
ArrayList<Long> segmentAsNumbers2 = new ArrayList<>();
segmentAsNumbers2.add((long) 4);
segmentAsNumbers2.add((long) 55); // Different
segmentAsNumbers2.add((long) 6);
BgpRouteEntry.PathSegment pathSegment2 =
new BgpRouteEntry.PathSegment(pathSegmentType2, segmentAsNumbers2);
pathSegments.add(pathSegment2);
//
BgpRouteEntry.AsPath asPath2 = new BgpRouteEntry.AsPath(pathSegments);
assertThat(asPath1, is(not(asPath2)));
}
/**
* Tests object string representation.
*/
@Test
public void testToString() {
BgpRouteEntry.AsPath asPath = generateAsPath();
String expectedString =
"AsPath{pathSegments=" +
"[PathSegment{type=2, segmentAsNumbers=[1, 2, 3]}, " +
"PathSegment{type=1, segmentAsNumbers=[4, 5, 6]}]}";
assertThat(asPath.toString(), is(expectedString));
}
}
package org.onlab.onos.sdnip.bgp;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import org.junit.Test;
/**
* Unit tests for the BgpRouteEntry.PathSegment class.
*/
public class PathSegmentTest {
/**
* Generates a Path Segment.
*
* @return a generated PathSegment
*/
private BgpRouteEntry.PathSegment generatePathSegment() {
byte pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
ArrayList<Long> segmentAsNumbers = new ArrayList<>();
segmentAsNumbers.add((long) 1);
segmentAsNumbers.add((long) 2);
segmentAsNumbers.add((long) 3);
BgpRouteEntry.PathSegment pathSegment =
new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
return pathSegment;
}
/**
* Tests valid class constructor.
*/
@Test
public void testConstructor() {
BgpRouteEntry.PathSegment pathSegment = generatePathSegment();
String expectedString =
"PathSegment{type=2, segmentAsNumbers=[1, 2, 3]}";
assertThat(pathSegment.toString(), is(expectedString));
}
/**
* Tests invalid class constructor for null Segment AS Numbers.
*/
@Test(expected = NullPointerException.class)
public void testInvalidConstructorNullSegmentAsNumbers() {
byte pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
ArrayList<Long> segmentAsNumbers = null;
new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
}
/**
* Tests getting the fields of a Path Segment.
*/
@Test
public void testGetFields() {
// Create the fields to compare against
byte pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
ArrayList<Long> segmentAsNumbers = new ArrayList<>();
segmentAsNumbers.add((long) 1);
segmentAsNumbers.add((long) 2);
segmentAsNumbers.add((long) 3);
// Generate the entry to test
BgpRouteEntry.PathSegment pathSegment = generatePathSegment();
assertThat(pathSegment.getType(), is(pathSegmentType));
assertThat(pathSegment.getSegmentAsNumbers(), is(segmentAsNumbers));
}
/**
* Tests equality of {@link BgpRouteEntry.PathSegment}.
*/
@Test
public void testEquality() {
BgpRouteEntry.PathSegment pathSegment1 = generatePathSegment();
BgpRouteEntry.PathSegment pathSegment2 = generatePathSegment();
assertThat(pathSegment1, is(pathSegment2));
}
/**
* Tests non-equality of {@link BgpRouteEntry.PathSegment}.
*/
@Test
public void testNonEquality() {
BgpRouteEntry.PathSegment pathSegment1 = generatePathSegment();
// Setup Path Segment 2
byte pathSegmentType = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
ArrayList<Long> segmentAsNumbers = new ArrayList<>();
segmentAsNumbers.add((long) 1);
segmentAsNumbers.add((long) 22); // Different
segmentAsNumbers.add((long) 3);
//
BgpRouteEntry.PathSegment pathSegment2 =
new BgpRouteEntry.PathSegment(pathSegmentType, segmentAsNumbers);
assertThat(pathSegment1, is(not(pathSegment2)));
}
/**
* Tests object string representation.
*/
@Test
public void testToString() {
BgpRouteEntry.PathSegment pathSegment = generatePathSegment();
String expectedString =
"PathSegment{type=2, segmentAsNumbers=[1, 2, 3]}";
assertThat(pathSegment.toString(), is(expectedString));
}
}
package org.onlab.onos.sdnip.bgp;
import java.util.Collection;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
/**
* Class for handling the remote BGP Peer session.
*/
class TestBgpPeerChannelHandler extends SimpleChannelHandler {
static final long PEER_AS = 65001;
static final int PEER_HOLDTIME = 120; // 120 seconds
final IpAddress bgpId; // The BGP ID
final long localPref; // Local preference for routes
final long multiExitDisc = 20; // MED value
ChannelHandlerContext savedCtx;
/**
* Constructor for given BGP ID.
*
* @param bgpId the BGP ID to use
* @param localPref the local preference for the routes to use
*/
TestBgpPeerChannelHandler(IpAddress bgpId,
long localPref) {
this.bgpId = bgpId;
this.localPref = localPref;
}
/**
* Closes the channel.
*/
void closeChannel() {
savedCtx.getChannel().close();
}
@Override
public void channelConnected(ChannelHandlerContext ctx,
ChannelStateEvent channelEvent) {
this.savedCtx = ctx;
// Prepare and transmit BGP OPEN message
ChannelBuffer message = prepareBgpOpen();
ctx.getChannel().write(message);
// Prepare and transmit BGP KEEPALIVE message
message = prepareBgpKeepalive();
ctx.getChannel().write(message);
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx,
ChannelStateEvent channelEvent) {
// Nothing to do
}
/**
* Prepares BGP OPEN message.
*
* @return the message to transmit (BGP header included)
*/
ChannelBuffer prepareBgpOpen() {
ChannelBuffer message =
ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
message.writeByte(BgpConstants.BGP_VERSION);
message.writeShort((int) PEER_AS);
message.writeShort(PEER_HOLDTIME);
message.writeInt(bgpId.toInt());
message.writeByte(0); // No Optional Parameters
return prepareBgpMessage(BgpConstants.BGP_TYPE_OPEN, message);
}
/**
* Prepares BGP UPDATE message.
*
* @param nextHopRouter the next-hop router address for the routes to add
* @param addedRoutes the routes to add
* @param withdrawnRoutes the routes to withdraw
* @return the message to transmit (BGP header included)
*/
ChannelBuffer prepareBgpUpdate(IpAddress nextHopRouter,
Collection<IpPrefix> addedRoutes,
Collection<IpPrefix> withdrawnRoutes) {
int attrFlags;
ChannelBuffer message =
ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
ChannelBuffer pathAttributes =
ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
// Encode the Withdrawn Routes
ChannelBuffer encodedPrefixes = encodePackedPrefixes(withdrawnRoutes);
message.writeShort(encodedPrefixes.readableBytes());
message.writeBytes(encodedPrefixes);
// Encode the Path Attributes
// ORIGIN: IGP
attrFlags = 0x40; // Transitive flag
pathAttributes.writeByte(attrFlags);
pathAttributes.writeByte(BgpConstants.Update.Origin.TYPE);
pathAttributes.writeByte(1); // Data length
pathAttributes.writeByte(BgpConstants.Update.Origin.IGP);
// AS_PATH: Two Path Segments of 3 ASes each
attrFlags = 0x40; // Transitive flag
pathAttributes.writeByte(attrFlags);
pathAttributes.writeByte(BgpConstants.Update.AsPath.TYPE);
pathAttributes.writeByte(16); // Data length
byte pathSegmentType1 = (byte) BgpConstants.Update.AsPath.AS_SEQUENCE;
pathAttributes.writeByte(pathSegmentType1);
pathAttributes.writeByte(3); // Three ASes
pathAttributes.writeShort(65010); // AS=65010
pathAttributes.writeShort(65020); // AS=65020
pathAttributes.writeShort(65030); // AS=65030
byte pathSegmentType2 = (byte) BgpConstants.Update.AsPath.AS_SET;
pathAttributes.writeByte(pathSegmentType2);
pathAttributes.writeByte(3); // Three ASes
pathAttributes.writeShort(65041); // AS=65041
pathAttributes.writeShort(65042); // AS=65042
pathAttributes.writeShort(65043); // AS=65043
// NEXT_HOP: nextHopRouter
attrFlags = 0x40; // Transitive flag
pathAttributes.writeByte(attrFlags);
pathAttributes.writeByte(BgpConstants.Update.NextHop.TYPE);
pathAttributes.writeByte(4); // Data length
pathAttributes.writeInt(nextHopRouter.toInt()); // Next-hop router
// LOCAL_PREF: localPref
attrFlags = 0x40; // Transitive flag
pathAttributes.writeByte(attrFlags);
pathAttributes.writeByte(BgpConstants.Update.LocalPref.TYPE);
pathAttributes.writeByte(4); // Data length
pathAttributes.writeInt((int) localPref); // Preference value
// MULTI_EXIT_DISC: multiExitDisc
attrFlags = 0x80; // Optional
// Non-Transitive flag
pathAttributes.writeByte(attrFlags);
pathAttributes.writeByte(BgpConstants.Update.MultiExitDisc.TYPE);
pathAttributes.writeByte(4); // Data length
pathAttributes.writeInt((int) multiExitDisc); // Preference value
// The NLRI prefixes
encodedPrefixes = encodePackedPrefixes(addedRoutes);
// Write the Path Attributes, beginning with its length
message.writeShort(pathAttributes.readableBytes());
message.writeBytes(pathAttributes);
message.writeBytes(encodedPrefixes);
return prepareBgpMessage(BgpConstants.BGP_TYPE_UPDATE, message);
}
/**
* Encodes a collection of IPv4 network prefixes in a packed format.
* <p>
* The IPv4 prefixes are encoded in the form:
* <Length, Prefix> where Length is the length in bits of the IPv4 prefix,
* and Prefix is the IPv4 prefix (padded with trailing bits to the end
* of an octet).
*
* @param prefixes the prefixes to encode
* @return the buffer with the encoded prefixes
*/
private ChannelBuffer encodePackedPrefixes(Collection<IpPrefix> prefixes) {
ChannelBuffer message =
ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
// Write each of the prefixes
for (IpPrefix prefix : prefixes) {
int prefixBitlen = prefix.prefixLength();
int prefixBytelen = (prefixBitlen + 7) / 8; // Round-up
message.writeByte(prefixBitlen);
IpAddress address = prefix.toIpAddress();
long value = address.toInt() & 0xffffffffL;
for (int i = 0; i < IpAddress.INET_LEN; i++) {
if (prefixBytelen-- == 0) {
break;
}
long nextByte =
(value >> ((IpAddress.INET_LEN - i - 1) * 8)) & 0xff;
message.writeByte((int) nextByte);
}
}
return message;
}
/**
* Prepares BGP KEEPALIVE message.
*
* @return the message to transmit (BGP header included)
*/
ChannelBuffer prepareBgpKeepalive() {
ChannelBuffer message =
ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
return prepareBgpMessage(BgpConstants.BGP_TYPE_KEEPALIVE, message);
}
/**
* Prepares BGP NOTIFICATION message.
*
* @param errorCode the BGP NOTIFICATION Error Code
* @param errorSubcode the BGP NOTIFICATION Error Subcode if applicable,
* otherwise BgpConstants.Notifications.ERROR_SUBCODE_UNSPECIFIC
* @param payload the BGP NOTIFICATION Data if applicable, otherwise null
* @return the message to transmit (BGP header included)
*/
ChannelBuffer prepareBgpNotification(int errorCode, int errorSubcode,
ChannelBuffer data) {
ChannelBuffer message =
ChannelBuffers.buffer(BgpConstants.BGP_MESSAGE_MAX_LENGTH);
// Prepare the NOTIFICATION message payload
message.writeByte(errorCode);
message.writeByte(errorSubcode);
if (data != null) {
message.writeBytes(data);
}
return prepareBgpMessage(BgpConstants.BGP_TYPE_NOTIFICATION, message);
}
/**
* Prepares BGP message.
*
* @param type the BGP message type
* @param payload the message payload to transmit (BGP header excluded)
* @return the message to transmit (BGP header included)
*/
private ChannelBuffer prepareBgpMessage(int type, ChannelBuffer payload) {
ChannelBuffer message =
ChannelBuffers.buffer(BgpConstants.BGP_HEADER_LENGTH +
payload.readableBytes());
// Write the marker
for (int i = 0; i < BgpConstants.BGP_HEADER_MARKER_LENGTH; i++) {
message.writeByte(0xff);
}
// Write the rest of the BGP header
message.writeShort(BgpConstants.BGP_HEADER_LENGTH +
payload.readableBytes());
message.writeByte(type);
// Write the payload
message.writeBytes(payload);
return message;
}
}
package org.onlab.onos.sdnip.bgp;
import java.util.concurrent.CountDownLatch;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
import org.onlab.packet.IpAddress;
/**
* Class for handling the decoding of the BGP messages at the remote
* BGP peer session.
*/
class TestBgpPeerFrameDecoder extends FrameDecoder {
int remoteBgpVersion; // 1 octet
long remoteAs; // 2 octets
long remoteHoldtime; // 2 octets
IpAddress remoteBgpIdentifier; // 4 octets -> IPv4 address
final CountDownLatch receivedOpenMessageLatch = new CountDownLatch(1);
final CountDownLatch receivedKeepaliveMessageLatch = new CountDownLatch(1);
@Override
protected Object decode(ChannelHandlerContext ctx,
Channel channel,
ChannelBuffer buf) throws Exception {
// Test for minimum length of the BGP message
if (buf.readableBytes() < BgpConstants.BGP_HEADER_LENGTH) {
// No enough data received
return null;
}
//
// Mark the current buffer position in case we haven't received
// the whole message.
//
buf.markReaderIndex();
//
// Read and check the BGP message Marker field: it must be all ones
//
byte[] marker = new byte[BgpConstants.BGP_HEADER_MARKER_LENGTH];
buf.readBytes(marker);
for (int i = 0; i < marker.length; i++) {
if (marker[i] != (byte) 0xff) {
// ERROR: Connection Not Synchronized. Close the channel.
ctx.getChannel().close();
return null;
}
}
//
// Read and check the BGP message Length field
//
int length = buf.readUnsignedShort();
if ((length < BgpConstants.BGP_HEADER_LENGTH) ||
(length > BgpConstants.BGP_MESSAGE_MAX_LENGTH)) {
// ERROR: Bad Message Length. Close the channel.
ctx.getChannel().close();
return null;
}
//
// Test whether the rest of the message is received:
// So far we have read the Marker (16 octets) and the
// Length (2 octets) fields.
//
int remainingMessageLen =
length - BgpConstants.BGP_HEADER_MARKER_LENGTH - 2;
if (buf.readableBytes() < remainingMessageLen) {
// No enough data received
buf.resetReaderIndex();
return null;
}
//
// Read the BGP message Type field, and process based on that type
//
int type = buf.readUnsignedByte();
remainingMessageLen--; // Adjust after reading the type
ChannelBuffer message = buf.readBytes(remainingMessageLen);
//
// Process the remaining of the message based on the message type
//
switch (type) {
case BgpConstants.BGP_TYPE_OPEN:
processBgpOpen(ctx, message);
break;
case BgpConstants.BGP_TYPE_UPDATE:
// NOTE: Not used as part of the test, because ONOS does not
// originate UPDATE messages.
break;
case BgpConstants.BGP_TYPE_NOTIFICATION:
// NOTE: Not used as part of the testing (yet)
break;
case BgpConstants.BGP_TYPE_KEEPALIVE:
processBgpKeepalive(ctx, message);
break;
default:
// ERROR: Bad Message Type. Close the channel.
ctx.getChannel().close();
return null;
}
return null;
}
/**
* Processes BGP OPEN message.
*
* @param ctx the Channel Handler Context.
* @param message the message to process.
*/
private void processBgpOpen(ChannelHandlerContext ctx,
ChannelBuffer message) {
int minLength =
BgpConstants.BGP_OPEN_MIN_LENGTH - BgpConstants.BGP_HEADER_LENGTH;
if (message.readableBytes() < minLength) {
// ERROR: Bad Message Length. Close the channel.
ctx.getChannel().close();
return;
}
//
// Parse the OPEN message
//
remoteBgpVersion = message.readUnsignedByte();
remoteAs = message.readUnsignedShort();
remoteHoldtime = message.readUnsignedShort();
remoteBgpIdentifier = IpAddress.valueOf((int) message.readUnsignedInt());
// Optional Parameters
int optParamLen = message.readUnsignedByte();
if (message.readableBytes() < optParamLen) {
// ERROR: Bad Message Length. Close the channel.
ctx.getChannel().close();
return;
}
message.readBytes(optParamLen); // NOTE: data ignored
// BGP OPEN message successfully received
receivedOpenMessageLatch.countDown();
}
/**
* Processes BGP KEEPALIVE message.
*
* @param ctx the Channel Handler Context.
* @param message the message to process.
*/
private void processBgpKeepalive(ChannelHandlerContext ctx,
ChannelBuffer message) {
if (message.readableBytes() + BgpConstants.BGP_HEADER_LENGTH !=
BgpConstants.BGP_KEEPALIVE_EXPECTED_LENGTH) {
// ERROR: Bad Message Length. Close the channel.
ctx.getChannel().close();
return;
}
// BGP KEEPALIVE message successfully received
receivedKeepaliveMessageLatch.countDown();
}
}
......@@ -94,7 +94,7 @@ public class FlowsListCommand extends AbstractShellCommand {
result.put("device", device.id().toString())
.put("flowCount", flows.size())
.put("flows", array);
.set("flows", array);
return result;
}
......
......@@ -90,11 +90,15 @@ public class IntentPushTestCommand extends AbstractShellCommand
service.submit(intent);
}
try {
latch.await(5, TimeUnit.SECONDS);
printResults(count);
if (latch.await(10, TimeUnit.SECONDS)) {
printResults(count);
} else {
print("I FAIL MISERABLY -> %d", latch.getCount());
}
} catch (InterruptedException e) {
print(e.toString());
}
service.removeListener(this);
}
......@@ -140,6 +144,8 @@ public class IntentPushTestCommand extends AbstractShellCommand
} else {
log.warn("install event latch is null");
}
} else {
log.info("I FAIL -> {}", event);
}
}
}
......
package org.onlab.onos.net;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.packet.ChassisId;
import java.util.Objects;
......@@ -16,6 +17,7 @@ public class DefaultDevice extends AbstractElement implements Device {
private final String serialNumber;
private final String hwVersion;
private final String swVersion;
private final ChassisId chassisId;
// For serialization
private DefaultDevice() {
......@@ -24,6 +26,7 @@ public class DefaultDevice extends AbstractElement implements Device {
this.hwVersion = null;
this.swVersion = null;
this.serialNumber = null;
this.chassisId = null;
}
/**
......@@ -40,13 +43,15 @@ public class DefaultDevice extends AbstractElement implements Device {
*/
public DefaultDevice(ProviderId providerId, DeviceId id, Type type,
String manufacturer, String hwVersion, String swVersion,
String serialNumber, Annotations... annotations) {
String serialNumber, ChassisId chassisId,
Annotations... annotations) {
super(providerId, id, annotations);
this.type = type;
this.manufacturer = manufacturer;
this.hwVersion = hwVersion;
this.swVersion = swVersion;
this.serialNumber = serialNumber;
this.chassisId = chassisId;
}
@Override
......@@ -80,6 +85,11 @@ public class DefaultDevice extends AbstractElement implements Device {
}
@Override
public ChassisId chassisId() {
return chassisId;
}
@Override
public int hashCode() {
return Objects.hash(id, type, manufacturer, hwVersion, swVersion, serialNumber);
}
......
package org.onlab.onos.net;
import org.onlab.packet.ChassisId;
/**
* Representation of a network infrastructure device.
*/
......@@ -54,6 +56,13 @@ public interface Device extends Element {
*/
String serialNumber();
/**
* Returns the device chassis id.
*
* @return chassis id
*/
ChassisId chassisId();
// Device realizedBy(); ?
// ports are not provided directly, but rather via DeviceService.getPorts(Device device);
......
......@@ -2,6 +2,7 @@ package org.onlab.onos.net.device;
import org.onlab.onos.net.AbstractDescription;
import org.onlab.onos.net.SparseAnnotations;
import org.onlab.packet.ChassisId;
import java.net.URI;
......@@ -20,6 +21,7 @@ public class DefaultDeviceDescription extends AbstractDescription
private final String hwVersion;
private final String swVersion;
private final String serialNumber;
private final ChassisId chassisId;
/**
* Creates a device description using the supplied information.
......@@ -34,7 +36,7 @@ public class DefaultDeviceDescription extends AbstractDescription
*/
public DefaultDeviceDescription(URI uri, Type type, String manufacturer,
String hwVersion, String swVersion,
String serialNumber,
String serialNumber, ChassisId chassis,
SparseAnnotations... annotations) {
super(annotations);
this.uri = checkNotNull(uri, "Device URI cannot be null");
......@@ -43,6 +45,7 @@ public class DefaultDeviceDescription extends AbstractDescription
this.hwVersion = hwVersion;
this.swVersion = swVersion;
this.serialNumber = serialNumber;
this.chassisId = chassis;
}
/**
......@@ -54,7 +57,7 @@ public class DefaultDeviceDescription extends AbstractDescription
SparseAnnotations... annotations) {
this(base.deviceURI(), base.type(), base.manufacturer(),
base.hwVersion(), base.swVersion(), base.serialNumber(),
annotations);
base.chassisId(), annotations);
}
@Override
......@@ -88,6 +91,11 @@ public class DefaultDeviceDescription extends AbstractDescription
}
@Override
public ChassisId chassisId() {
return chassisId;
}
@Override
public String toString() {
return toStringHelper(this)
.add("uri", uri).add("type", type).add("mfr", manufacturer)
......@@ -104,5 +112,6 @@ public class DefaultDeviceDescription extends AbstractDescription
this.hwVersion = null;
this.swVersion = null;
this.serialNumber = null;
this.chassisId = null;
}
}
......
......@@ -2,6 +2,7 @@ package org.onlab.onos.net.device;
import org.onlab.onos.net.Description;
import org.onlab.onos.net.Device;
import org.onlab.packet.ChassisId;
import java.net.URI;
......@@ -54,4 +55,11 @@ public interface DeviceDescription extends Description {
*/
String serialNumber();
/**
* Returns a device chassis id.
*
* @return chassis id
*/
ChassisId chassisId();
}
......
......@@ -8,7 +8,7 @@ import org.slf4j.Logger;
public class DefaultFlowEntry extends DefaultFlowRule implements FlowEntry {
private final Logger log = getLogger(getClass());
private static final Logger log = getLogger(DefaultFlowEntry.class);
private long life;
private long packets;
......
......@@ -11,7 +11,7 @@ import org.slf4j.Logger;
public class DefaultFlowRule implements FlowRule {
private final Logger log = getLogger(getClass());
private static final Logger log = getLogger(DefaultFlowRule.class);
private final DeviceId deviceId;
private final int priority;
......
......@@ -12,7 +12,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* Abstraction of end-station to end-station bidirectional connectivity.
*/
public class HostToHostIntent extends ConnectivityIntent {
public final class HostToHostIntent extends ConnectivityIntent {
private final HostId one;
private final HostId two;
......
......@@ -14,7 +14,7 @@ import com.google.common.base.MoreObjects;
* Abstraction of a connectivity intent that is implemented by a set of path
* segments.
*/
public class LinkCollectionIntent extends ConnectivityIntent implements InstallableIntent {
public final class LinkCollectionIntent extends ConnectivityIntent implements InstallableIntent {
private final Set<Link> links;
......@@ -46,6 +46,12 @@ public class LinkCollectionIntent extends ConnectivityIntent implements Installa
return links;
}
/**
* Returns the set of links that represent the network connections needed
* by this intent.
*
* @return Set of links for the network hops needed by this intent
*/
public Set<Link> links() {
return links;
}
......
......@@ -15,7 +15,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* Abstraction of multiple source to single destination connectivity intent.
*/
public class MultiPointToSinglePointIntent extends ConnectivityIntent {
public final class MultiPointToSinglePointIntent extends ConnectivityIntent {
private final Set<ConnectPoint> ingressPoints;
private final ConnectPoint egressPoint;
......
......@@ -62,6 +62,9 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro
((AbstractProviderService) service).invalidate();
services.remove(provider.id());
providers.remove(provider.id());
if (!provider.id().isAncillary()) {
providersByScheme.remove(provider.id().scheme());
}
}
}
......
......@@ -7,6 +7,8 @@ import org.onlab.onos.net.Provided;
*/
public interface Topology extends Provided {
// FIXME: Following is not true right now. It is actually System.nanoTime(),
// which has no relation to epoch time, wall clock, etc.
/**
* Returns the time, specified in milliseconds since start of epoch,
* when the topology became active and made available.
......
......@@ -37,6 +37,15 @@ public interface ClusterCommunicationService {
boolean multicast(ClusterMessage message, Set<NodeId> nodeIds) throws IOException;
/**
* Sends a message synchronously.
* @param message message to send
* @param toNodeId recipient node identifier
* @return ClusterMessageResponse which is reply future.
* @throws IOException
*/
ClusterMessageResponse sendAndReceive(ClusterMessage message, NodeId toNodeId) throws IOException;
/**
* Adds a new subscriber for the specified message subject.
*
* @param subject message subject
......
package org.onlab.onos.store.cluster.messaging;
import java.io.IOException;
import org.onlab.onos.cluster.NodeId;
// TODO: Should payload type be ByteBuffer?
......@@ -49,4 +51,14 @@ public class ClusterMessage {
public byte[] payload() {
return payload;
}
/**
* Sends a response to the sender.
*
* @param data payload response.
* @throws IOException
*/
public void respond(byte[] data) throws IOException {
throw new IllegalStateException("One can only repond to message recived from others.");
}
}
......
package org.onlab.onos.store.cluster.messaging;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.onlab.onos.cluster.NodeId;
public interface ClusterMessageResponse {
public NodeId sender();
public byte[] get(long timeout, TimeUnit timeunit) throws TimeoutException;
public byte[] get(long timeout) throws InterruptedException;
}
......@@ -3,6 +3,7 @@ package org.onlab.onos.net;
import com.google.common.testing.EqualsTester;
import org.junit.Test;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.packet.ChassisId;
import static org.junit.Assert.assertEquals;
import static org.onlab.onos.net.Device.Type.SWITCH;
......@@ -21,14 +22,15 @@ public class DefaultDeviceTest {
static final String SW = "3.9.1";
static final String SN1 = "43311-12345";
static final String SN2 = "42346-43512";
static final ChassisId CID = new ChassisId();
@Test
public void testEquality() {
Device d1 = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1);
Device d2 = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1);
Device d3 = new DefaultDevice(PID, DID2, SWITCH, MFR, HW, SW, SN2);
Device d4 = new DefaultDevice(PID, DID2, SWITCH, MFR, HW, SW, SN2);
Device d5 = new DefaultDevice(PID, DID2, SWITCH, MFR, HW, SW, SN1);
Device d1 = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1, CID);
Device d2 = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1, CID);
Device d3 = new DefaultDevice(PID, DID2, SWITCH, MFR, HW, SW, SN2, CID);
Device d4 = new DefaultDevice(PID, DID2, SWITCH, MFR, HW, SW, SN2, CID);
Device d5 = new DefaultDevice(PID, DID2, SWITCH, MFR, HW, SW, SN1, CID);
new EqualsTester().addEqualityGroup(d1, d2)
.addEqualityGroup(d3, d4)
......@@ -38,13 +40,13 @@ public class DefaultDeviceTest {
@Test
public void basics() {
Device device = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1);
Device device = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1, CID);
validate(device);
}
@Test
public void annotations() {
Device device = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1,
Device device = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1, CID,
DefaultAnnotations.builder().set("foo", "bar").build());
validate(device);
assertEquals("incorrect provider", "bar", device.annotations().value("foo"));
......
......@@ -3,6 +3,7 @@ package org.onlab.onos.net;
import com.google.common.testing.EqualsTester;
import org.junit.Test;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.packet.ChassisId;
import static org.junit.Assert.assertEquals;
import static org.onlab.onos.net.Device.Type.SWITCH;
......@@ -22,7 +23,8 @@ public class DefaultPortTest {
@Test
public void testEquality() {
Device device = new DefaultDevice(PID, DID1, SWITCH, "m", "h", "s", "n");
Device device = new DefaultDevice(PID, DID1, SWITCH, "m", "h", "s", "n",
new ChassisId());
Port p1 = new DefaultPort(device, portNumber(1), true);
Port p2 = new DefaultPort(device, portNumber(1), true);
Port p3 = new DefaultPort(device, portNumber(2), true);
......@@ -37,7 +39,8 @@ public class DefaultPortTest {
@Test
public void basics() {
Device device = new DefaultDevice(PID, DID1, SWITCH, "m", "h", "s", "n");
Device device = new DefaultDevice(PID, DID1, SWITCH, "m", "h", "s", "n",
new ChassisId());
Port port = new DefaultPort(device, portNumber(1), true);
assertEquals("incorrect element", device, port.element());
assertEquals("incorrect number", portNumber(1), port.number());
......
package org.onlab.onos.net;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.packet.ChassisId;
import org.onlab.packet.IpPrefix;
import java.util.ArrayList;
......@@ -37,7 +38,7 @@ public final class NetTestTools {
// Crates a new device with the specified id
public static Device device(String id) {
return new DefaultDevice(PID, did(id), Device.Type.SWITCH,
"mfg", "1.0", "1.1", "1234");
"mfg", "1.0", "1.1", "1234", new ChassisId());
}
// Crates a new host with the specified id
......@@ -47,10 +48,16 @@ public final class NetTestTools {
new HashSet<IpPrefix>());
}
// Short-hand for creating a connection point.
public static ConnectPoint connectPoint(String id, int port) {
return new ConnectPoint(did(id), portNumber(port));
}
// Short-hand for creating a link.
public static Link link(String src, int sp, String dst, int dp) {
return new DefaultLink(PID, new ConnectPoint(did(src), portNumber(sp)),
new ConnectPoint(did(dst), portNumber(dp)),
return new DefaultLink(PID,
connectPoint(src, sp),
connectPoint(dst, dp),
Link.Type.DIRECT);
}
......
package org.onlab.onos.net.device;
import org.junit.Test;
import org.onlab.packet.ChassisId;
import java.net.URI;
......@@ -18,12 +19,13 @@ public class DefaultDeviceDescriptionTest {
private static final String HW = "1.1.x";
private static final String SW = "3.9.1";
private static final String SN = "43311-12345";
private static final ChassisId CID = new ChassisId();
@Test
public void basics() {
DeviceDescription device =
new DefaultDeviceDescription(DURI, SWITCH, MFR, HW, SW, SN);
new DefaultDeviceDescription(DURI, SWITCH, MFR, HW, SW, SN, CID);
assertEquals("incorrect uri", DURI, device.deviceURI());
assertEquals("incorrect type", SWITCH, device.type());
assertEquals("incorrect manufacturer", MFR, device.manufacturer());
......@@ -31,6 +33,7 @@ public class DefaultDeviceDescriptionTest {
assertEquals("incorrect sw", SW, device.swVersion());
assertEquals("incorrect serial", SN, device.serialNumber());
assertTrue("incorrect toString", device.toString().contains("uri=of:foo"));
assertTrue("Incorrect chassis", device.chassisId().value() == 0);
}
}
......
......@@ -11,6 +11,7 @@ import org.onlab.onos.net.Device;
import org.onlab.onos.net.Port;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.packet.ChassisId;
/**
* Tests of the device event.
......@@ -19,7 +20,7 @@ public class DeviceEventTest extends AbstractEventTest {
private Device createDevice() {
return new DefaultDevice(new ProviderId("of", "foo"), deviceId("of:foo"),
Device.Type.SWITCH, "box", "hw", "sw", "sn");
Device.Type.SWITCH, "box", "hw", "sw", "sn", new ChassisId());
}
@Override
......
......@@ -18,9 +18,9 @@ public class DefaultGraphDescriptionTest {
private static final DeviceId D3 = deviceId("3");
static final Device DEV1 = new DefaultDevice(PID, D1, SWITCH, "", "", "", "");
static final Device DEV2 = new DefaultDevice(PID, D2, SWITCH, "", "", "", "");
static final Device DEV3 = new DefaultDevice(PID, D3, SWITCH, "", "", "", "");
static final Device DEV1 = new DefaultDevice(PID, D1, SWITCH, "", "", "", "", null);
static final Device DEV2 = new DefaultDevice(PID, D2, SWITCH, "", "", "", "", null);
static final Device DEV3 = new DefaultDevice(PID, D3, SWITCH, "", "", "", "", null);
@Test
public void basics() {
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-core</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-json</artifactId>
<packaging>bundle</packaging>
<description>ONOS JSON encode/decode facilities</description>
<dependencies>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-api</artifactId>
</dependency>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-api</artifactId>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-core-trivial</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package org.onlab.onos.json.impl;
/**
* Created by tom on 10/16/14.
*/
public class DeleteMe {
}
/**
* Implementation of JSON codec factory and of the builtin codecs.
*/
package org.onlab.onos.json.impl;
\ No newline at end of file
......@@ -36,26 +36,9 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<!-- TODO Consider removing store dependency.
Currently required for DistributedDeviceManagerTest. -->
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-core-hz-net</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.onlab.onos</groupId>
<!-- FIXME: should be somewhere else -->
<artifactId>onos-core-hz-common</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
......
......@@ -388,7 +388,7 @@ public class DeviceManager
new DefaultDeviceDescription(
did.uri(), device.type(), device.manufacturer(),
device.hwVersion(), device.swVersion(),
device.serialNumber()));
device.serialNumber(), device.chassisId()));
}
//TODO re-collect device information to fix potential staleness
applyRole(did, MastershipRole.MASTER);
......
......@@ -401,7 +401,7 @@ public class FlowRuleManager
CompletedBatchOperation completed;
for (Future<CompletedBatchOperation> future : futures) {
completed = future.get();
success = validateBatchOperation(failed, completed, future);
success = validateBatchOperation(failed, completed);
}
return finalizeBatchOperation(success, failed);
......@@ -426,14 +426,13 @@ public class FlowRuleManager
long now = System.nanoTime();
long thisTimeout = end - now;
completed = future.get(thisTimeout, TimeUnit.NANOSECONDS);
success = validateBatchOperation(failed, completed, future);
success = validateBatchOperation(failed, completed);
}
return finalizeBatchOperation(success, failed);
}
private boolean validateBatchOperation(List<FlowEntry> failed,
CompletedBatchOperation completed,
Future<CompletedBatchOperation> future) {
CompletedBatchOperation completed) {
if (isCancelled()) {
throw new CancellationException();
......
......@@ -41,7 +41,7 @@ public class HostToHostIntentCompiler
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
private IdGenerator<IntentId> intentIdGenerator;
protected IdGenerator<IntentId> intentIdGenerator;
@Activate
public void activate() {
......
......@@ -37,7 +37,7 @@ public class MultiPointToSinglePointIntentCompiler
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PathService pathService;
private IdGenerator<IntentId> intentIdGenerator;
protected IdGenerator<IntentId> intentIdGenerator;
@Activate
public void activate() {
......
......@@ -96,7 +96,7 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> {
FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
builder.build(), treatment,
123, appId, 600);
123, appId, 15);
rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
prev = link.dst();
}
......
......@@ -43,7 +43,7 @@ public class PointToPointIntentCompiler
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
private IdGenerator<IntentId> intentIdGenerator;
protected IdGenerator<IntentId> intentIdGenerator;
@Activate
public void activate() {
......
......@@ -244,6 +244,7 @@ public class LinkManager
return;
}
log.info("Links for connection point {} vanished", connectPoint);
// FIXME: This will remove links registered by other providers
removeLinks(getLinks(connectPoint));
}
......
......@@ -167,6 +167,7 @@ public class ProxyArpManager implements ProxyArpService {
return;
}
// TODO find the correct IP address
Ethernet arpReply = buildArpReply(dst.ipAddresses().iterator().next(),
dst.mac(), eth);
// TODO: check send status with host service.
......
......@@ -23,6 +23,7 @@ import org.onlab.onos.net.topology.TopologyProviderRegistry;
import org.onlab.onos.net.topology.TopologyProviderService;
import org.slf4j.Logger;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.concurrent.ExecutorService;
......@@ -88,7 +89,7 @@ public class DefaultTopologyProvider extends AbstractProvider
linkService.addListener(linkListener);
isStarted = true;
triggerTopologyBuild(null);
triggerTopologyBuild(Collections.<Event>emptyList());
log.info("Started");
}
......
......@@ -37,6 +37,7 @@ import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.trivial.impl.SimpleDeviceStore;
import org.onlab.packet.ChassisId;
import org.onlab.packet.IpPrefix;
import java.util.ArrayList;
......@@ -62,6 +63,7 @@ public class DeviceManagerTest {
private static final String SW1 = "3.8.1";
private static final String SW2 = "3.9.5";
private static final String SN = "43311-12345";
private static final ChassisId CID = new ChassisId();
private static final PortNumber P1 = PortNumber.portNumber(1);
private static final PortNumber P2 = PortNumber.portNumber(2);
......@@ -111,7 +113,7 @@ public class DeviceManagerTest {
private void connectDevice(DeviceId deviceId, String swVersion) {
DeviceDescription description =
new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
HW, swVersion, SN);
HW, swVersion, SN, CID);
providerService.deviceConnected(deviceId, description);
assertNotNull("device should be found", service.getDevice(DID1));
}
......
......@@ -8,7 +8,9 @@ import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_UPDATED;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
......@@ -54,6 +56,7 @@ import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
......@@ -68,7 +71,7 @@ public class FlowRuleManagerTest {
private static final DeviceId DID = DeviceId.deviceId("of:001");
private static final int TIMEOUT = 10;
private static final Device DEV = new DefaultDevice(
PID, DID, Type.SWITCH, "", "", "", "");
PID, DID, Type.SWITCH, "", "", "", "", null);
private FlowRuleManager mgr;
......@@ -166,16 +169,17 @@ public class FlowRuleManagerTest {
}
// TODO: If preserving iteration order is a requirement, redo FlowRuleStore.
//backing store is sensitive to the order of additions/removals
private boolean validateState(FlowEntryState... state) {
private boolean validateState(Map<FlowRule, FlowEntryState> expected) {
Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected);
Iterable<FlowEntry> rules = service.getFlowEntries(DID);
int i = 0;
for (FlowEntry f : rules) {
if (f.state() != state[i]) {
return false;
}
i++;
assertTrue("Unexpected FlowRule " + f, expectedToCheck.containsKey(f));
assertEquals("FlowEntry" + f, expectedToCheck.get(f), f.state());
expectedToCheck.remove(f);
}
assertEquals(Collections.emptySet(), expectedToCheck.entrySet());
return true;
}
......@@ -191,8 +195,10 @@ public class FlowRuleManagerTest {
mgr.applyFlowRules(r1, r2, r3);
assertEquals("3 rules should exist", 3, flowCount());
assertTrue("Entries should be pending add.",
validateState(FlowEntryState.PENDING_ADD, FlowEntryState.PENDING_ADD,
FlowEntryState.PENDING_ADD));
validateState(ImmutableMap.of(
r1, FlowEntryState.PENDING_ADD,
r2, FlowEntryState.PENDING_ADD,
r3, FlowEntryState.PENDING_ADD)));
}
@Test
......@@ -213,8 +219,10 @@ public class FlowRuleManagerTest {
validateEvents();
assertEquals("3 rule should exist", 3, flowCount());
assertTrue("Entries should be pending remove.",
validateState(FlowEntryState.PENDING_REMOVE, FlowEntryState.PENDING_REMOVE,
FlowEntryState.ADDED));
validateState(ImmutableMap.of(
f1, FlowEntryState.PENDING_REMOVE,
f2, FlowEntryState.PENDING_REMOVE,
f3, FlowEntryState.ADDED)));
mgr.removeFlowRules(f1);
assertEquals("3 rule should still exist", 3, flowCount());
......@@ -263,8 +271,10 @@ public class FlowRuleManagerTest {
providerService.pushFlowMetrics(DID, Lists.newArrayList(fe1, fe2));
assertTrue("Entries should be added.",
validateState(FlowEntryState.ADDED, FlowEntryState.ADDED,
FlowEntryState.PENDING_ADD));
validateState(ImmutableMap.of(
f1, FlowEntryState.ADDED,
f2, FlowEntryState.ADDED,
f3, FlowEntryState.PENDING_ADD)));
validateEvents(RULE_ADDED, RULE_ADDED);
}
......@@ -336,7 +346,9 @@ public class FlowRuleManagerTest {
//only check that we are in pending remove. Events and actual remove state will
// be set by flowRemoved call.
validateState(FlowEntryState.PENDING_REMOVE, FlowEntryState.PENDING_REMOVE);
validateState(ImmutableMap.of(
f1, FlowEntryState.PENDING_REMOVE,
f2, FlowEntryState.PENDING_REMOVE));
}
@Test
......@@ -360,7 +372,9 @@ public class FlowRuleManagerTest {
Lists.newArrayList(fbe1, fbe2));
Future<CompletedBatchOperation> future = mgr.applyBatch(fbo);
assertTrue("Entries in wrong state",
validateState(FlowEntryState.PENDING_REMOVE, FlowEntryState.PENDING_ADD));
validateState(ImmutableMap.of(
f1, FlowEntryState.PENDING_REMOVE,
f2, FlowEntryState.PENDING_ADD)));
CompletedBatchOperation completed = null;
try {
completed = future.get();
......@@ -381,9 +395,18 @@ public class FlowRuleManagerTest {
mgr.applyFlowRules(f1);
assertTrue("Entries in wrong state",
validateState(ImmutableMap.of(
f1, FlowEntryState.PENDING_ADD)));
FlowEntry fe1 = new DefaultFlowEntry(f1);
providerService.pushFlowMetrics(DID, Collections.<FlowEntry>singletonList(fe1));
assertTrue("Entries in wrong state",
validateState(ImmutableMap.of(
f1, FlowEntryState.ADDED)));
FlowRuleBatchEntry fbe1 = new FlowRuleBatchEntry(
FlowRuleBatchEntry.FlowRuleOperation.REMOVE, f1);
......@@ -403,9 +426,9 @@ public class FlowRuleManagerTest {
* state.
*/
assertTrue("Entries in wrong state",
validateState(FlowEntryState.PENDING_REMOVE,
FlowEntryState.PENDING_ADD));
validateState(ImmutableMap.of(
f2, FlowEntryState.PENDING_REMOVE,
f1, FlowEntryState.PENDING_ADD)));
}
......
package org.onlab.onos.net.intent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.onlab.onos.net.ElementId;
import org.onlab.onos.net.Path;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.flow.criteria.Criterion;
import org.onlab.onos.net.flow.instructions.Instruction;
import org.onlab.onos.net.topology.LinkWeight;
import org.onlab.onos.net.topology.PathService;
import static org.onlab.onos.net.NetTestTools.createPath;
/**
* Common mocks used by the intent framework tests.
*/
public class IntentTestsMocks {
/**
* Mock traffic selector class used for satisfying API requirements.
*/
public static class MockSelector implements TrafficSelector {
@Override
public Set<Criterion> criteria() {
return new HashSet<>();
}
}
/**
* Mock traffic treatment class used for satisfying API requirements.
*/
public static class MockTreatment implements TrafficTreatment {
@Override
public List<Instruction> instructions() {
return new ArrayList<>();
}
}
/**
* Mock path service for creating paths within the test.
*/
public static class MockPathService implements PathService {
final String[] pathHops;
final String[] reversePathHops;
/**
* Constructor that provides a set of hops to mock.
*
* @param pathHops path hops to mock
*/
public MockPathService(String[] pathHops) {
this.pathHops = pathHops;
String[] reversed = pathHops.clone();
Collections.reverse(Arrays.asList(reversed));
reversePathHops = reversed;
}
@Override
public Set<Path> getPaths(ElementId src, ElementId dst) {
Set<Path> result = new HashSet<>();
String[] allHops = new String[pathHops.length];
if (src.toString().endsWith(pathHops[0])) {
System.arraycopy(pathHops, 0, allHops, 0, pathHops.length);
} else {
System.arraycopy(reversePathHops, 0, allHops, 0, pathHops.length);
}
result.add(createPath(allHops));
return result;
}
@Override
public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
return getPaths(src, dst);
}
}
}
package org.onlab.onos.net.intent;
import java.util.Collection;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.onlab.onos.net.Link;
/**
* Matcher to determine if a Collection of Links contains a path between a source
* and a destination.
*/
public class LinksHaveEntryWithSourceDestinationPairMatcher extends
TypeSafeMatcher<Collection<Link>> {
private final String source;
private final String destination;
/**
* Creates a matcher for a given path represented by a source and
* a destination.
*
* @param source string identifier for the source of the path
* @param destination string identifier for the destination of the path
*/
LinksHaveEntryWithSourceDestinationPairMatcher(String source,
String destination) {
this.source = source;
this.destination = destination;
}
@Override
public boolean matchesSafely(Collection<Link> links) {
for (Link link : links) {
if (link.src().elementId().toString().endsWith(source) &&
link.dst().elementId().toString().endsWith(destination)) {
return true;
}
}
return false;
}
@Override
public void describeTo(Description description) {
description.appendText("link lookup for source \"");
description.appendText(source);
description.appendText(" and destination ");
description.appendText(destination);
description.appendText("\"");
}
@Override
public void describeMismatchSafely(Collection<Link> links,
Description mismatchDescription) {
mismatchDescription.appendText("was ").
appendText(links.toString());
}
/**
* Creates a link has path matcher.
*
* @param source string identifier for the source of the path
* @param destination string identifier for the destination of the path
* @return matcher to match the path
*/
public static LinksHaveEntryWithSourceDestinationPairMatcher linksHasPath(
String source,
String destination) {
return new LinksHaveEntryWithSourceDestinationPairMatcher(source,
destination);
}
}
package org.onlab.onos.net.intent;
import org.junit.Test;
import org.onlab.onos.net.HostId;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.onlab.onos.net.NetTestTools.hid;
/**
* Unit tests for the HostToHostIntent class.
*/
public class TestHostToHostIntent {
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
private HostToHostIntent makeHostToHost(long id, HostId one, HostId two) {
return new HostToHostIntent(new IntentId(id),
one,
two,
selector,
treatment);
}
/**
* Tests the equals() method where two HostToHostIntents have references
* to the same hosts. These should compare equal.
*/
@Test
public void testSameEquals() {
HostId one = hid("00:00:00:00:00:01/-1");
HostId two = hid("00:00:00:00:00:02/-1");
HostToHostIntent i1 = makeHostToHost(12, one, two);
HostToHostIntent i2 = makeHostToHost(12, one, two);
assertThat(i1, is(equalTo(i2)));
}
/**
* Tests the equals() method where two HostToHostIntents have references
* to different Hosts. These should compare not equal.
*/
@Test
public void testLinksDifferentEquals() {
HostId one = hid("00:00:00:00:00:01/-1");
HostId two = hid("00:00:00:00:00:02/-1");
HostToHostIntent i1 = makeHostToHost(12, one, two);
HostToHostIntent i2 = makeHostToHost(12, two, one);
assertThat(i1, is(not(equalTo(i2))));
}
/**
* Tests the equals() method where two HostToHostIntents have different
* ids. These should compare not equal.
*/
@Test
public void testBaseDifferentEquals() {
HostId one = hid("00:00:00:00:00:01/-1");
HostId two = hid("00:00:00:00:00:02/-1");
HostToHostIntent i1 = makeHostToHost(12, one, two);
HostToHostIntent i2 = makeHostToHost(11, one, two);
assertThat(i1, is(not(equalTo(i2))));
}
/**
* Tests that the hashCode() values for two equivalent HostToHostIntent
* objects are the same.
*/
@Test
public void testHashCodeEquals() {
HostId one = hid("00:00:00:00:00:01/-1");
HostId two = hid("00:00:00:00:00:02/-1");
HostToHostIntent i1 = makeHostToHost(12, one, two);
HostToHostIntent i2 = makeHostToHost(12, one, two);
assertThat(i1.hashCode(), is(equalTo(i2.hashCode())));
}
/**
* Tests that the hashCode() values for two distinct LinkCollectionIntent
* objects are different.
*/
@Test
public void testHashCodeDifferent() {
HostId one = hid("00:00:00:00:00:01/-1");
HostId two = hid("00:00:00:00:00:02/-1");
HostToHostIntent i1 = makeHostToHost(12, one, two);
HostToHostIntent i2 = makeHostToHost(112, one, two);
assertThat(i1.hashCode(), is(not(equalTo(i2.hashCode()))));
}
/**
* Checks that the HostToHostIntent class is immutable.
*/
@Test
public void checkImmutability() {
ImmutableClassChecker.assertThatClassIsImmutable(HostToHostIntent.class);
}
}
package org.onlab.onos.net.intent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.flow.criteria.Criterion;
import org.onlab.onos.net.flow.instructions.Instruction;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.onlab.onos.net.NetTestTools.link;
/**
* Unit tests for the LinkCollectionIntent class.
*/
public class TestLinkCollectionIntent {
private static class MockSelector implements TrafficSelector {
@Override
public Set<Criterion> criteria() {
return new HashSet<Criterion>();
}
private Link link1 = link("dev1", 1, "dev2", 2);
private Link link2 = link("dev1", 1, "dev3", 2);
private Link link3 = link("dev2", 1, "dev3", 2);
private Set<Link> links1;
private Set<Link> links2;
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
private LinkCollectionIntent makeLinkCollection(long id, Set<Link> links) {
return new LinkCollectionIntent(new IntentId(id),
selector, treatment, links);
}
@Before
public void setup() {
links1 = new HashSet<>();
links2 = new HashSet<>();
}
private static class MockTreatment implements TrafficTreatment {
@Override
public List<Instruction> instructions() {
return new ArrayList<>();
}
/**
* Tests the equals() method where two LinkCollectionIntents have references
* to the same Links in different orders. These should compare equal.
*/
@Test
public void testSameEquals() {
links1.add(link1);
links1.add(link2);
links1.add(link3);
links2.add(link3);
links2.add(link2);
links2.add(link1);
LinkCollectionIntent i1 = makeLinkCollection(12, links1);
LinkCollectionIntent i2 = makeLinkCollection(12, links2);
assertThat(i1, is(equalTo(i2)));
}
/**
* Tests the equals() method where two LinkCollectionIntents have references
* to different Links. These should compare not equal.
*/
@Test
public void testComparison() {
TrafficSelector selector = new MockSelector();
TrafficTreatment treatment = new MockTreatment();
Set<Link> links = new HashSet<>();
LinkCollectionIntent i1 = new LinkCollectionIntent(new IntentId(12),
selector, treatment, links);
LinkCollectionIntent i2 = new LinkCollectionIntent(new IntentId(12),
selector, treatment, links);
public void testLinksDifferentEquals() {
links1.add(link1);
links1.add(link2);
links2.add(link3);
links2.add(link1);
assertThat(i1.equals(i2), is(true));
LinkCollectionIntent i1 = makeLinkCollection(12, links1);
LinkCollectionIntent i2 = makeLinkCollection(12, links2);
assertThat(i1, is(not(equalTo(i2))));
}
/**
* Tests the equals() method where two LinkCollectionIntents have different
* ids. These should compare not equal.
*/
@Test
public void testBaseDifferentEquals() {
links1.add(link1);
links1.add(link2);
links2.add(link2);
links2.add(link1);
LinkCollectionIntent i1 = makeLinkCollection(1, links1);
LinkCollectionIntent i2 = makeLinkCollection(2, links2);
assertThat(i1, is(not(equalTo(i2))));
}
/**
* Tests that the hashCode() values for two equivalent LinkCollectionIntent
* objects are the same.
*/
@Test
public void testHashCodeEquals() {
links1.add(link1);
links1.add(link2);
links1.add(link3);
links2.add(link3);
links2.add(link2);
links2.add(link1);
LinkCollectionIntent i1 = makeLinkCollection(1, links1);
LinkCollectionIntent i2 = makeLinkCollection(1, links2);
assertThat(i1.hashCode(), is(equalTo(i2.hashCode())));
}
/**
* Tests that the hashCode() values for two distinct LinkCollectionIntent
* objects are different.
*/
@Test
public void testHashCodeDifferent() {
links1.add(link1);
links1.add(link2);
links2.add(link1);
links2.add(link3);
LinkCollectionIntent i1 = makeLinkCollection(1, links1);
LinkCollectionIntent i2 = makeLinkCollection(1, links2);
assertThat(i1.hashCode(), is(not(equalTo(i2.hashCode()))));
}
/**
* Checks that the HostToHostIntent class is immutable.
*/
@Test
public void checkImmutability() {
ImmutableClassChecker.assertThatClassIsImmutable(LinkCollectionIntent.class);
}
}
......
package org.onlab.onos.net.intent;
import java.util.HashSet;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.onlab.onos.net.NetTestTools.connectPoint;
/**
* Unit tests for the MultiPointToSinglePointIntent class.
*/
public class TestMultiPointToSinglePointIntent {
private ConnectPoint point1 = connectPoint("dev1", 1);
private ConnectPoint point2 = connectPoint("dev2", 1);
private ConnectPoint point3 = connectPoint("dev3", 1);
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
Set<ConnectPoint> ingress1;
Set<ConnectPoint> ingress2;
/**
* Creates a MultiPointToSinglePointIntent object.
*
* @param id identifier to use for the new intent
* @param ingress set of ingress points
* @param egress egress point
* @return MultiPointToSinglePoint intent
*/
private MultiPointToSinglePointIntent makeIntent(long id,
Set<ConnectPoint> ingress,
ConnectPoint egress) {
return new MultiPointToSinglePointIntent(new IntentId(id),
selector,
treatment,
ingress,
egress);
}
/**
* Initializes the ingress sets.
*/
@Before
public void setup() {
ingress1 = new HashSet<>();
ingress2 = new HashSet<>();
}
/**
* Tests the equals() method where two MultiPointToSinglePoint have references
* to the same Links in different orders. These should compare equal.
*/
@Test
public void testSameEquals() {
Set<ConnectPoint> ingress1 = new HashSet<>();
ingress1.add(point2);
ingress1.add(point3);
Set<ConnectPoint> ingress2 = new HashSet<>();
ingress2.add(point3);
ingress2.add(point2);
Intent i1 = makeIntent(12, ingress1, point1);
Intent i2 = makeIntent(12, ingress2, point1);
assertThat(i1, is(equalTo(i2)));
}
/**
* Tests the equals() method where two MultiPointToSinglePoint have references
* to different Links. These should compare not equal.
*/
@Test
public void testLinksDifferentEquals() {
ingress1.add(point3);
ingress2.add(point3);
ingress2.add(point2);
Intent i1 = makeIntent(12, ingress1, point1);
Intent i2 = makeIntent(12, ingress2, point1);
assertThat(i1, is(not(equalTo(i2))));
}
/**
* Tests the equals() method where two MultiPointToSinglePoint have different
* ids. These should compare not equal.
*/
@Test
public void testBaseDifferentEquals() {
ingress1.add(point3);
ingress2.add(point3);
Intent i1 = makeIntent(12, ingress1, point1);
Intent i2 = makeIntent(11, ingress2, point1);
assertThat(i1, is(not(equalTo(i2))));
}
/**
* Tests that the hashCode() values for two equivalent MultiPointToSinglePoint
* objects are the same.
*/
@Test
public void testHashCodeEquals() {
ingress1.add(point2);
ingress1.add(point3);
ingress2.add(point3);
ingress2.add(point2);
Intent i1 = makeIntent(12, ingress1, point1);
Intent i2 = makeIntent(12, ingress2, point1);
assertThat(i1.hashCode(), is(equalTo(i2.hashCode())));
}
/**
* Tests that the hashCode() values for two distinct MultiPointToSinglePoint
* objects are different.
*/
@Test
public void testHashCodeDifferent() {
ingress1.add(point2);
ingress2.add(point3);
ingress2.add(point2);
Intent i1 = makeIntent(12, ingress1, point1);
Intent i2 = makeIntent(12, ingress2, point1);
assertThat(i1.hashCode(), is(not(equalTo(i2.hashCode()))));
}
/**
* Checks that the MultiPointToSinglePointIntent class is immutable.
*/
@Test
public void checkImmutability() {
ImmutableClassChecker.
assertThatClassIsImmutable(MultiPointToSinglePointIntent.class);
}
}
package org.onlab.onos.net.intent;
import org.junit.Test;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.onlab.onos.net.NetTestTools.connectPoint;
/**
* Unit tests for the HostToHostIntent class.
*/
public class TestPointToPointIntent {
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
private ConnectPoint point1 = connectPoint("dev1", 1);
private ConnectPoint point2 = connectPoint("dev2", 1);
private PointToPointIntent makePointToPoint(long id,
ConnectPoint ingress,
ConnectPoint egress) {
return new PointToPointIntent(new IntentId(id),
selector,
treatment,
ingress,
egress);
}
/**
* Tests the equals() method where two PointToPointIntents have references
* to the same ingress and egress points. These should compare equal.
*/
@Test
public void testSameEquals() {
PointToPointIntent i1 = makePointToPoint(12, point1, point2);
PointToPointIntent i2 = makePointToPoint(12, point1, point2);
assertThat(i1, is(equalTo(i2)));
}
/**
* Tests the equals() method where two HostToHostIntents have references
* to different Hosts. These should compare not equal.
*/
@Test
public void testLinksDifferentEquals() {
PointToPointIntent i1 = makePointToPoint(12, point1, point2);
PointToPointIntent i2 = makePointToPoint(12, point2, point1);
assertThat(i1, is(not(equalTo(i2))));
}
/**
* Tests the equals() method where two HostToHostIntents have different
* ids. These should compare not equal.
*/
@Test
public void testBaseDifferentEquals() {
PointToPointIntent i1 = makePointToPoint(12, point1, point2);
PointToPointIntent i2 = makePointToPoint(11, point1, point2);
assertThat(i1, is(not(equalTo(i2))));
}
/**
* Tests that the hashCode() values for two equivalent HostToHostIntent
* objects are the same.
*/
@Test
public void testHashCodeEquals() {
PointToPointIntent i1 = makePointToPoint(12, point1, point2);
PointToPointIntent i2 = makePointToPoint(12, point1, point2);
assertThat(i1.hashCode(), is(equalTo(i2.hashCode())));
}
/**
* Tests that the hashCode() values for two distinct LinkCollectionIntent
* objects are different.
*/
@Test
public void testHashCodeDifferent() {
PointToPointIntent i1 = makePointToPoint(12, point1, point2);
PointToPointIntent i2 = makePointToPoint(22, point1, point2);
assertThat(i1.hashCode(), is(not(equalTo(i2.hashCode()))));
}
}
package org.onlab.onos.net.intent.impl;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.onlab.onos.net.Host;
import org.onlab.onos.net.HostId;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.host.HostService;
import org.onlab.onos.net.intent.HostToHostIntent;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentTestsMocks;
import org.onlab.onos.net.intent.PathIntent;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.onlab.onos.net.NetTestTools.hid;
import static org.onlab.onos.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath;
/**
* Unit tests for the HostToHost intent compiler.
*/
public class TestHostToHostIntentCompiler {
private static final String HOST_ONE_MAC = "00:00:00:00:00:01";
private static final String HOST_TWO_MAC = "00:00:00:00:00:02";
private static final String HOST_ONE_VLAN = "-1";
private static final String HOST_TWO_VLAN = "-1";
private static final String HOST_ONE = HOST_ONE_MAC + "/" + HOST_ONE_VLAN;
private static final String HOST_TWO = HOST_TWO_MAC + "/" + HOST_TWO_VLAN;
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
private HostId hostOneId = HostId.hostId(HOST_ONE);
private HostId hostTwoId = HostId.hostId(HOST_TWO);
private HostService mockHostService;
@Before
public void setup() {
Host hostOne = createMock(Host.class);
expect(hostOne.mac()).andReturn(new MacAddress(HOST_ONE_MAC.getBytes())).anyTimes();
expect(hostOne.vlan()).andReturn(VlanId.vlanId()).anyTimes();
replay(hostOne);
Host hostTwo = createMock(Host.class);
expect(hostTwo.mac()).andReturn(new MacAddress(HOST_TWO_MAC.getBytes())).anyTimes();
expect(hostTwo.vlan()).andReturn(VlanId.vlanId()).anyTimes();
replay(hostTwo);
mockHostService = createMock(HostService.class);
expect(mockHostService.getHost(eq(hostOneId))).andReturn(hostOne).anyTimes();
expect(mockHostService.getHost(eq(hostTwoId))).andReturn(hostTwo).anyTimes();
replay(mockHostService);
}
/**
* Creates a HostToHost intent based on two host Ids.
*
* @param oneIdString string for host one id
* @param twoIdString string for host two id
* @return HostToHostIntent for the two hosts
*/
private HostToHostIntent makeIntent(String oneIdString, String twoIdString) {
return new HostToHostIntent(new IntentId(12),
hid(oneIdString),
hid(twoIdString),
selector,
treatment);
}
/**
* Creates a compiler for HostToHost intents.
*
* @param hops string array describing the path hops to use when compiling
* @return HostToHost intent compiler
*/
private HostToHostIntentCompiler makeCompiler(String[] hops) {
HostToHostIntentCompiler compiler =
new HostToHostIntentCompiler();
compiler.pathService = new IntentTestsMocks.MockPathService(hops);
compiler.hostService = mockHostService;
IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
compiler.intentIdGenerator =
new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
return compiler;
}
/**
* Tests a pair of hosts with 8 hops between them.
*/
@Test
public void testSingleLongPathCompilation() {
HostToHostIntent intent = makeIntent(HOST_ONE,
HOST_TWO);
assertThat(intent, is(notNullValue()));
String[] hops = {HOST_ONE, "h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8", HOST_TWO};
HostToHostIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
List<Intent> result = compiler.compile(intent);
assertThat(result, is(Matchers.notNullValue()));
assertThat(result, hasSize(2));
Intent forwardResultIntent = result.get(0);
assertThat(forwardResultIntent instanceof PathIntent, is(true));
Intent reverseResultIntent = result.get(1);
assertThat(reverseResultIntent instanceof PathIntent, is(true));
if (forwardResultIntent instanceof PathIntent) {
PathIntent forwardPathIntent = (PathIntent) forwardResultIntent;
assertThat(forwardPathIntent.path().links(), hasSize(9));
assertThat(forwardPathIntent.path().links(), linksHasPath(HOST_ONE, "h1"));
assertThat(forwardPathIntent.path().links(), linksHasPath("h1", "h2"));
assertThat(forwardPathIntent.path().links(), linksHasPath("h2", "h3"));
assertThat(forwardPathIntent.path().links(), linksHasPath("h3", "h4"));
assertThat(forwardPathIntent.path().links(), linksHasPath("h4", "h5"));
assertThat(forwardPathIntent.path().links(), linksHasPath("h5", "h6"));
assertThat(forwardPathIntent.path().links(), linksHasPath("h6", "h7"));
assertThat(forwardPathIntent.path().links(), linksHasPath("h7", "h8"));
assertThat(forwardPathIntent.path().links(), linksHasPath("h8", HOST_TWO));
}
if (reverseResultIntent instanceof PathIntent) {
PathIntent reversePathIntent = (PathIntent) reverseResultIntent;
assertThat(reversePathIntent.path().links(), hasSize(9));
assertThat(reversePathIntent.path().links(), linksHasPath("h1", HOST_ONE));
assertThat(reversePathIntent.path().links(), linksHasPath("h2", "h1"));
assertThat(reversePathIntent.path().links(), linksHasPath("h3", "h2"));
assertThat(reversePathIntent.path().links(), linksHasPath("h4", "h3"));
assertThat(reversePathIntent.path().links(), linksHasPath("h5", "h4"));
assertThat(reversePathIntent.path().links(), linksHasPath("h6", "h5"));
assertThat(reversePathIntent.path().links(), linksHasPath("h7", "h6"));
assertThat(reversePathIntent.path().links(), linksHasPath("h8", "h7"));
assertThat(reversePathIntent.path().links(), linksHasPath(HOST_TWO, "h8"));
}
}
}
package org.onlab.onos.net.intent.impl;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.ElementId;
import org.onlab.onos.net.Path;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentTestsMocks;
import org.onlab.onos.net.intent.LinkCollectionIntent;
import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
import org.onlab.onos.net.topology.LinkWeight;
import org.onlab.onos.net.topology.PathService;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.onlab.onos.net.NetTestTools.connectPoint;
import static org.onlab.onos.net.NetTestTools.createPath;
import static org.onlab.onos.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath;
/**
* Unit tests for the MultiPointToSinglePoint intent compiler.
*/
public class TestMultiPointToSinglePointIntentCompiler {
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
/**
* Mock path service for creating paths within the test.
*/
private static class MockPathService implements PathService {
final String[] pathHops;
/**
* Constructor that provides a set of hops to mock.
*
* @param pathHops path hops to mock
*/
MockPathService(String[] pathHops) {
this.pathHops = pathHops;
}
@Override
public Set<Path> getPaths(ElementId src, ElementId dst) {
Set<Path> result = new HashSet<>();
String[] allHops = new String[pathHops.length + 1];
allHops[0] = src.toString();
System.arraycopy(pathHops, 0, allHops, 1, pathHops.length);
result.add(createPath(allHops));
return result;
}
@Override
public Set<Path> getPaths(ElementId src, ElementId dst, LinkWeight weight) {
return null;
}
}
/**
* Creates a MultiPointToSinglePoint intent for a group of ingress points
* and an egress point.
*
* @param ingressIds array of ingress device ids
* @param egressId device id of the egress point
* @return MultiPointToSinglePoint intent
*/
private MultiPointToSinglePointIntent makeIntent(String[] ingressIds, String egressId) {
Set<ConnectPoint> ingressPoints = new HashSet<>();
ConnectPoint egressPoint = connectPoint(egressId, 1);
for (String ingressId : ingressIds) {
ingressPoints.add(connectPoint(ingressId, 1));
}
return new MultiPointToSinglePointIntent(
new IntentId(12),
selector,
treatment,
ingressPoints,
egressPoint);
}
/**
* Creates a compiler for MultiPointToSinglePoint intents.
*
* @param hops hops to use while computing paths for this intent
* @return MultiPointToSinglePoint intent
*/
private MultiPointToSinglePointIntentCompiler makeCompiler(String[] hops) {
MultiPointToSinglePointIntentCompiler compiler =
new MultiPointToSinglePointIntentCompiler();
compiler.pathService = new MockPathService(hops);
IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
compiler.intentIdGenerator =
new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
return compiler;
}
/**
* Tests a single ingress point with 8 hops to its egress point.
*/
@Test
public void testSingleLongPathCompilation() {
String[] ingress = {"ingress"};
String egress = "egress";
MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
assertThat(intent, is(notNullValue()));
String[] hops = {"h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8",
egress};
MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
List<Intent> result = compiler.compile(intent);
assertThat(result, is(Matchers.notNullValue()));
assertThat(result, hasSize(1));
Intent resultIntent = result.get(0);
assertThat(resultIntent instanceof LinkCollectionIntent, is(true));
if (resultIntent instanceof LinkCollectionIntent) {
LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
assertThat(linkIntent.links(), hasSize(9));
assertThat(linkIntent.links(), linksHasPath("ingress", "h1"));
assertThat(linkIntent.links(), linksHasPath("h1", "h2"));
assertThat(linkIntent.links(), linksHasPath("h2", "h3"));
assertThat(linkIntent.links(), linksHasPath("h4", "h5"));
assertThat(linkIntent.links(), linksHasPath("h5", "h6"));
assertThat(linkIntent.links(), linksHasPath("h7", "h8"));
assertThat(linkIntent.links(), linksHasPath("h8", "egress"));
}
}
/**
* Tests a simple topology where two ingress points share some path segments
* and some path segments are not shared.
*/
@Test
public void testTwoIngressCompilation() {
String[] ingress = {"ingress1", "ingress2"};
String egress = "egress";
MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
assertThat(intent, is(notNullValue()));
final String[] hops = {"inner1", "inner2", egress};
MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
List<Intent> result = compiler.compile(intent);
assertThat(result, is(notNullValue()));
assertThat(result, hasSize(1));
Intent resultIntent = result.get(0);
assertThat(resultIntent instanceof LinkCollectionIntent, is(true));
if (resultIntent instanceof LinkCollectionIntent) {
LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
assertThat(linkIntent.links(), hasSize(4));
assertThat(linkIntent.links(), linksHasPath("ingress1", "inner1"));
assertThat(linkIntent.links(), linksHasPath("ingress2", "inner1"));
assertThat(linkIntent.links(), linksHasPath("inner1", "inner2"));
assertThat(linkIntent.links(), linksHasPath("inner2", "egress"));
}
}
/**
* Tests a large number of ingress points that share a common path to the
* egress point.
*/
@Test
public void testMultiIngressCompilation() {
String[] ingress = {"i1", "i2", "i3", "i4", "i5",
"i6", "i7", "i8", "i9", "i10"};
String egress = "e";
MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
assertThat(intent, is(notNullValue()));
final String[] hops = {"n1", egress};
MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
List<Intent> result = compiler.compile(intent);
assertThat(result, is(notNullValue()));
assertThat(result, hasSize(1));
Intent resultIntent = result.get(0);
assertThat(resultIntent instanceof LinkCollectionIntent, is(true));
if (resultIntent instanceof LinkCollectionIntent) {
LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
assertThat(linkIntent.links(), hasSize(ingress.length + 1));
for (String ingressToCheck : ingress) {
assertThat(linkIntent.links(),
linksHasPath(ingressToCheck,
"n1"));
}
assertThat(linkIntent.links(), linksHasPath("n1", egress));
}
}
}
package org.onlab.onos.net.intent.impl;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.onlab.onos.net.flow.TrafficSelector;
import org.onlab.onos.net.flow.TrafficTreatment;
import org.onlab.onos.net.intent.Intent;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.intent.IntentTestsMocks;
import org.onlab.onos.net.intent.PathIntent;
import org.onlab.onos.net.intent.PointToPointIntent;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.onlab.onos.net.NetTestTools.connectPoint;
import static org.onlab.onos.net.intent.LinksHaveEntryWithSourceDestinationPairMatcher.linksHasPath;
/**
* Unit tests for the HostToHost intent compiler.
*/
public class TestPointToPointIntentCompiler {
private TrafficSelector selector = new IntentTestsMocks.MockSelector();
private TrafficTreatment treatment = new IntentTestsMocks.MockTreatment();
/**
* Creates a PointToPoint intent based on ingress and egress device Ids.
*
* @param ingressIdString string for id of ingress device
* @param egressIdString string for id of egress device
* @return PointToPointIntent for the two devices
*/
private PointToPointIntent makeIntent(String ingressIdString,
String egressIdString) {
return new PointToPointIntent(new IntentId(12),
selector,
treatment,
connectPoint(ingressIdString, 1),
connectPoint(egressIdString, 1));
}
/**
* Creates a compiler for HostToHost intents.
*
* @param hops string array describing the path hops to use when compiling
* @return HostToHost intent compiler
*/
private PointToPointIntentCompiler makeCompiler(String[] hops) {
PointToPointIntentCompiler compiler =
new PointToPointIntentCompiler();
compiler.pathService = new IntentTestsMocks.MockPathService(hops);
IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
compiler.intentIdGenerator =
new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
return compiler;
}
/**
* Tests a pair of devices in an 8 hop path, forward direction.
*/
@Test
public void testForwardPathCompilation() {
PointToPointIntent intent = makeIntent("d1", "d8");
assertThat(intent, is(notNullValue()));
String[] hops = {"d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8"};
PointToPointIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
List<Intent> result = compiler.compile(intent);
assertThat(result, is(Matchers.notNullValue()));
assertThat(result, hasSize(1));
Intent forwardResultIntent = result.get(0);
assertThat(forwardResultIntent instanceof PathIntent, is(true));
if (forwardResultIntent instanceof PathIntent) {
PathIntent forwardPathIntent = (PathIntent) forwardResultIntent;
// 7 links for the hops, plus one default lnk on ingress and egress
assertThat(forwardPathIntent.path().links(), hasSize(hops.length + 1));
assertThat(forwardPathIntent.path().links(), linksHasPath("d1", "d2"));
assertThat(forwardPathIntent.path().links(), linksHasPath("d2", "d3"));
assertThat(forwardPathIntent.path().links(), linksHasPath("d3", "d4"));
assertThat(forwardPathIntent.path().links(), linksHasPath("d4", "d5"));
assertThat(forwardPathIntent.path().links(), linksHasPath("d5", "d6"));
assertThat(forwardPathIntent.path().links(), linksHasPath("d6", "d7"));
assertThat(forwardPathIntent.path().links(), linksHasPath("d7", "d8"));
}
}
/**
* Tests a pair of devices in an 8 hop path, forward direction.
*/
@Test
public void testReversePathCompilation() {
PointToPointIntent intent = makeIntent("d8", "d1");
assertThat(intent, is(notNullValue()));
String[] hops = {"d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8"};
PointToPointIntentCompiler compiler = makeCompiler(hops);
assertThat(compiler, is(notNullValue()));
List<Intent> result = compiler.compile(intent);
assertThat(result, is(Matchers.notNullValue()));
assertThat(result, hasSize(1));
Intent reverseResultIntent = result.get(0);
assertThat(reverseResultIntent instanceof PathIntent, is(true));
if (reverseResultIntent instanceof PathIntent) {
PathIntent reversePathIntent = (PathIntent) reverseResultIntent;
assertThat(reversePathIntent.path().links(), hasSize(hops.length + 1));
assertThat(reversePathIntent.path().links(), linksHasPath("d2", "d1"));
assertThat(reversePathIntent.path().links(), linksHasPath("d3", "d2"));
assertThat(reversePathIntent.path().links(), linksHasPath("d4", "d3"));
assertThat(reversePathIntent.path().links(), linksHasPath("d5", "d4"));
assertThat(reversePathIntent.path().links(), linksHasPath("d6", "d5"));
assertThat(reversePathIntent.path().links(), linksHasPath("d7", "d6"));
assertThat(reversePathIntent.path().links(), linksHasPath("d8", "d7"));
}
}
}
......@@ -20,6 +20,7 @@
<module>api</module>
<module>net</module>
<module>store</module>
<module>json</module>
</modules>
<dependencies>
......
......@@ -19,21 +19,10 @@
<dependencies>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-api</artifactId>
</dependency>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-core-serializers</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onlab-nio</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onlab-netty</artifactId>
......@@ -50,10 +39,6 @@
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-testlib</artifactId>
<scope>test</scope>
......@@ -67,15 +52,12 @@
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-api</artifactId>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
......
......@@ -4,6 +4,9 @@ import static com.google.common.base.Preconditions.checkArgument;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
......@@ -17,6 +20,7 @@ import org.onlab.onos.store.cluster.impl.ClusterMembershipEvent;
import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
import org.onlab.onos.store.cluster.messaging.ClusterMessage;
import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler;
import org.onlab.onos.store.cluster.messaging.ClusterMessageResponse;
import org.onlab.onos.store.cluster.messaging.MessageSubject;
import org.onlab.onos.store.serializers.ClusterMessageSerializer;
import org.onlab.onos.store.serializers.KryoPoolUtil;
......@@ -28,6 +32,7 @@ import org.onlab.netty.Message;
import org.onlab.netty.MessageHandler;
import org.onlab.netty.MessagingService;
import org.onlab.netty.NettyMessagingService;
import org.onlab.netty.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -114,7 +119,23 @@ public class ClusterCommunicationManager
message.subject().value(), SERIALIZER.encode(message));
return true;
} catch (IOException e) {
log.error("Failed to send cluster message to nodeId: " + toNodeId, e);
log.trace("Failed to send cluster message to nodeId: " + toNodeId, e);
throw e;
}
}
@Override
public ClusterMessageResponse sendAndReceive(ClusterMessage message, NodeId toNodeId) throws IOException {
ControllerNode node = clusterService.getNode(toNodeId);
checkArgument(node != null, "Unknown nodeId: %s", toNodeId);
Endpoint nodeEp = new Endpoint(node.ip().toString(), node.tcpPort());
try {
Response responseFuture =
messagingService.sendAndReceive(nodeEp, message.subject().value(), SERIALIZER.encode(message));
return new InternalClusterMessageResponse(toNodeId, responseFuture);
} catch (IOException e) {
log.error("Failed interaction with remote nodeId: " + toNodeId, e);
throw e;
}
}
......@@ -137,11 +158,52 @@ public class ClusterCommunicationManager
public void handle(Message message) {
try {
ClusterMessage clusterMessage = SERIALIZER.decode(message.payload());
handler.handle(clusterMessage);
handler.handle(new InternalClusterMessage(clusterMessage, message));
} catch (Exception e) {
log.error("Exception caught during ClusterMessageHandler", e);
throw e;
}
}
}
public static final class InternalClusterMessage extends ClusterMessage {
private final Message rawMessage;
public InternalClusterMessage(ClusterMessage clusterMessage, Message rawMessage) {
super(clusterMessage.sender(), clusterMessage.subject(), clusterMessage.payload());
this.rawMessage = rawMessage;
}
@Override
public void respond(byte[] response) throws IOException {
rawMessage.respond(response);
}
}
private static final class InternalClusterMessageResponse implements ClusterMessageResponse {
private final NodeId sender;
private final Response responseFuture;
public InternalClusterMessageResponse(NodeId sender, Response responseFuture) {
this.sender = sender;
this.responseFuture = responseFuture;
}
@Override
public NodeId sender() {
return sender;
}
@Override
public byte[] get(long timeout, TimeUnit timeunit)
throws TimeoutException {
return responseFuture.get(timeout, timeunit);
}
@Override
public byte[] get(long timeout) throws InterruptedException {
return responseFuture.get();
}
}
}
......
/**
* Common abstractions and facilities for implementing distributed store
* using gossip protocol.
*/
package org.onlab.onos.store.common.impl;
......@@ -15,7 +15,7 @@ import org.onlab.onos.net.device.DefaultPortDescription;
import org.onlab.onos.net.device.DeviceDescription;
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.store.Timestamp;
import org.onlab.onos.store.common.impl.Timestamped;
import org.onlab.onos.store.impl.Timestamped;
/*
* Collection of Description of a Device and Ports, given from a Provider.
......
......@@ -38,9 +38,10 @@ import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
import org.onlab.onos.store.cluster.messaging.ClusterMessage;
import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler;
import org.onlab.onos.store.cluster.messaging.MessageSubject;
import org.onlab.onos.store.common.impl.Timestamped;
import org.onlab.onos.store.impl.Timestamped;
import org.onlab.onos.store.serializers.KryoSerializer;
import org.onlab.onos.store.serializers.DistributedStoreSerializers;
import org.onlab.packet.ChassisId;
import org.onlab.util.KryoPool;
import org.onlab.util.NewConcurrentHashMap;
import org.slf4j.Logger;
......@@ -746,6 +747,7 @@ public class GossipDeviceStore
String hwVersion = base.hwVersion();
String swVersion = base.swVersion();
String serialNumber = base.serialNumber();
ChassisId chassisId = base.chassisId();
DefaultAnnotations annotations = DefaultAnnotations.builder().build();
annotations = merge(annotations, base.annotations());
......@@ -763,7 +765,8 @@ public class GossipDeviceStore
}
return new DefaultDevice(primary, deviceId , type, manufacturer,
hwVersion, swVersion, serialNumber, annotations);
hwVersion, swVersion, serialNumber,
chassisId, annotations);
}
/**
......@@ -1137,7 +1140,7 @@ public class GossipDeviceStore
try {
unicastMessage(peer, DEVICE_ADVERTISE, ad);
} catch (IOException e) {
log.error("Failed to send anti-entropy advertisement", e);
log.debug("Failed to send anti-entropy advertisement to {}", peer);
return;
}
} catch (Exception e) {
......
package org.onlab.onos.store.device.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import org.apache.commons.lang3.concurrent.ConcurrentException;
import org.apache.commons.lang3.concurrent.ConcurrentInitializer;
import org.onlab.onos.net.device.DeviceDescription;
import org.onlab.onos.store.common.impl.Timestamped;
// FIXME: consider removing this class
public final class InitDeviceDescs
implements ConcurrentInitializer<DeviceDescriptions> {
private final Timestamped<DeviceDescription> deviceDesc;
public InitDeviceDescs(Timestamped<DeviceDescription> deviceDesc) {
this.deviceDesc = checkNotNull(deviceDesc);
}
@Override
public DeviceDescriptions get() throws ConcurrentException {
return new DeviceDescriptions(deviceDesc);
}
}
......@@ -3,7 +3,7 @@ package org.onlab.onos.store.device.impl;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.DeviceDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.common.impl.Timestamped;
import org.onlab.onos.store.impl.Timestamped;
import com.google.common.base.MoreObjects;
......
......@@ -3,7 +3,7 @@ package org.onlab.onos.store.device.impl;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.DeviceDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.common.impl.Timestamped;
import org.onlab.onos.store.impl.Timestamped;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
......
......@@ -5,7 +5,7 @@ import java.util.List;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.common.impl.Timestamped;
import org.onlab.onos.store.impl.Timestamped;
import com.google.common.base.MoreObjects;
......
......@@ -5,7 +5,7 @@ import java.util.List;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.common.impl.Timestamped;
import org.onlab.onos.store.impl.Timestamped;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
......
......@@ -3,7 +3,7 @@ package org.onlab.onos.store.device.impl;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.common.impl.Timestamped;
import org.onlab.onos.store.impl.Timestamped;
import com.google.common.base.MoreObjects;
......
......@@ -3,7 +3,7 @@ package org.onlab.onos.store.device.impl;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.common.impl.Timestamped;
import org.onlab.onos.store.impl.Timestamped;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
......
/**
* Implementation of device store using distributed distributed p2p synchronization protocol.
* Implementation of distributed device store using p2p synchronization protocol.
*/
package org.onlab.onos.store.device.impl;
......
package org.onlab.onos.store.flow;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collection;
import java.util.Collections;
import org.onlab.onos.cluster.NodeId;
import com.google.common.base.Optional;
/**
* Class to represent placement information about Master/Backup copy.
*/
public final class ReplicaInfo {
private final Optional<NodeId> master;
private final Collection<NodeId> backups;
/**
* Creates a ReplicaInfo instance.
*
* @param master NodeId of the node where the master copy should be
* @param backups collection of NodeId, where backup copies should be placed
*/
public ReplicaInfo(NodeId master, Collection<NodeId> backups) {
this.master = Optional.fromNullable(master);
this.backups = checkNotNull(backups);
}
/**
* Returns the NodeId, if there is a Node where the master copy should be.
*
* @return NodeId, where the master copy should be placed
*/
public Optional<NodeId> master() {
return master;
}
/**
* Returns the collection of NodeId, where backup copies should be placed.
*
* @return collection of NodeId, where backup copies should be placed
*/
public Collection<NodeId> backups() {
return backups;
}
// for Serializer
private ReplicaInfo() {
this.master = Optional.absent();
this.backups = Collections.emptyList();
}
}
package org.onlab.onos.store.flow;
import static com.google.common.base.Preconditions.checkNotNull;
import org.onlab.onos.event.AbstractEvent;
import org.onlab.onos.net.DeviceId;
/**
* Describes a device replicainfo event.
*/
public class ReplicaInfoEvent extends AbstractEvent<ReplicaInfoEvent.Type, DeviceId> {
private final ReplicaInfo replicaInfo;
/**
* Types of Replica info event.
*/
public enum Type {
/**
* Event to notify that master placement should be changed.
*/
MASTER_CHANGED,
//
// BACKUPS_CHANGED?
}
/**
* Creates an event of a given type and for the specified device,
* and replica info.
*
* @param type replicainfo event type
* @param device event device subject
* @param replicaInfo replicainfo
*/
public ReplicaInfoEvent(Type type, DeviceId device, ReplicaInfo replicaInfo) {
super(type, device);
this.replicaInfo = checkNotNull(replicaInfo);
}
/**
* Returns the current replica information for the subject.
*
* @return replica information for the subject
*/
public ReplicaInfo replicaInfo() {
return replicaInfo;
};
}
package org.onlab.onos.store.flow;
import org.onlab.onos.event.EventListener;
/**
* Entity capable of receiving Replica placement information-related events.
*/
public interface ReplicaInfoEventListener extends EventListener<ReplicaInfoEvent> {
}
package org.onlab.onos.store.flow;
import org.onlab.onos.net.DeviceId;
/**
* Service to return where the replica should be placed.
*/
public interface ReplicaInfoService {
// returns where it should be.
/**
* Returns the placement information for given Device.
*
* @param deviceId identifier of the device
* @return placement information
*/
ReplicaInfo getReplicaInfoFor(DeviceId deviceId);
/**
* Adds the specified replica placement info change listener.
*
* @param listener the replica placement info change listener
*/
void addListener(ReplicaInfoEventListener listener);
/**
* Removes the specified replica placement info change listener.
*
* @param listener the replica placement info change listener
*/
void removeListener(ReplicaInfoEventListener listener);
}
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.