mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-12-16 06:41:29 +01:00
Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
This commit is contained in:
commit
7c479476b0
112
apps/pom.xml
Normal file
112
apps/pom.xml
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
<?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</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>onos-apps</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
<description>ONOS sample applications</description>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>tvue</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<web.context>default</web.context>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.onlab.onos</groupId>
|
||||||
|
<artifactId>onos-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.onlab.onos</groupId>
|
||||||
|
<artifactId>onlab-osgi</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<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>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-annotations</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.osgi</groupId>
|
||||||
|
<artifactId>org.osgi.core</artifactId>
|
||||||
|
</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-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,
|
||||||
|
com.fasterxml.jackson.databind,
|
||||||
|
com.fasterxml.jackson.databind.node,
|
||||||
|
org.onlab.rest.*,
|
||||||
|
org.onlab.onos.*
|
||||||
|
</Import-Package>
|
||||||
|
<Web-ContextPath>${web.context}</Web-ContextPath>
|
||||||
|
</instructions>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
23
apps/tvue/pom.xml
Normal file
23
apps/tvue/pom.xml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?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-tvue</artifactId>
|
||||||
|
<packaging>bundle</packaging>
|
||||||
|
|
||||||
|
<description>ONOS simple topology viewer</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<web.context>/onos/tvue</web.context>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
||||||
@ -0,0 +1,153 @@
|
|||||||
|
package org.onlab.onos.tvue;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import org.onlab.onos.net.ConnectPoint;
|
||||||
|
import org.onlab.onos.net.ElementId;
|
||||||
|
import org.onlab.onos.net.Link;
|
||||||
|
import org.onlab.onos.net.device.DeviceService;
|
||||||
|
import org.onlab.onos.net.host.HostService;
|
||||||
|
import org.onlab.onos.net.link.LinkService;
|
||||||
|
import org.onlab.onos.net.topology.Topology;
|
||||||
|
import org.onlab.onos.net.topology.TopologyGraph;
|
||||||
|
import org.onlab.onos.net.topology.TopologyService;
|
||||||
|
import org.onlab.onos.net.topology.TopologyVertex;
|
||||||
|
import org.onlab.rest.BaseResource;
|
||||||
|
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.Produces;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Topology viewer resource.
|
||||||
|
*/
|
||||||
|
@Path("topology")
|
||||||
|
public class TopologyResource extends BaseResource {
|
||||||
|
|
||||||
|
@Path("/graph")
|
||||||
|
@GET
|
||||||
|
@Produces("application/json")
|
||||||
|
public Response graph() {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
|
||||||
|
// Fetch the services we'll be using.
|
||||||
|
DeviceService deviceService = get(DeviceService.class);
|
||||||
|
HostService hostService = get(HostService.class);
|
||||||
|
TopologyService topologyService = get(TopologyService.class);
|
||||||
|
|
||||||
|
// Fetch the current topology and its graph that we'll use to render.
|
||||||
|
Topology topo = topologyService.currentTopology();
|
||||||
|
TopologyGraph graph = topologyService.getGraph(topo);
|
||||||
|
|
||||||
|
// Build all interior vertexes, i.e. no end-station hosts yet
|
||||||
|
ArrayNode vertexesNode = mapper.createArrayNode();
|
||||||
|
for (TopologyVertex vertex : graph.getVertexes()) {
|
||||||
|
vertexesNode.add(json(mapper, vertex.deviceId(), 2,
|
||||||
|
deviceService.isAvailable(vertex.deviceId())));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now scan all links and count number of them between the same devices
|
||||||
|
// using a normalized link key.
|
||||||
|
Map<String, AggLink> linkRecords = aggregateLinks();
|
||||||
|
|
||||||
|
// Now build all interior edges using the aggregated links.
|
||||||
|
ArrayNode edgesNode = mapper.createArrayNode();
|
||||||
|
for (AggLink lr : linkRecords.values()) {
|
||||||
|
edgesNode.add(json(mapper, lr.links.size(), lr.link.src(), lr.link.dst()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge the exterior and interior vertexes and inject host links as
|
||||||
|
// the exterior edges.
|
||||||
|
// Iterator<Host> hosts = hostService.getHosts();
|
||||||
|
// while (hosts.hasNext()) {
|
||||||
|
// Host host = hosts.next();
|
||||||
|
// vertexesNode.add(json(mapper, host.id().ip().toString(), 3, true));
|
||||||
|
// edgesNode.add(json(mapper, 1, host.ip().toString(),
|
||||||
|
// host.location().elementId().uri()));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Now put the vertexes and edges into a root node and ship them off
|
||||||
|
ObjectNode rootNode = mapper.createObjectNode();
|
||||||
|
rootNode.put("vertexes", vertexesNode);
|
||||||
|
rootNode.put("edges", edgesNode);
|
||||||
|
return Response.ok(rootNode.toString()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan all links and counts number of them between the same devices
|
||||||
|
// using a normalized link key.
|
||||||
|
private Map<String, AggLink> aggregateLinks() {
|
||||||
|
Map<String, AggLink> aggLinks = new HashMap<>();
|
||||||
|
LinkService linkService = get(LinkService.class);
|
||||||
|
for (Link link : linkService.getLinks()) {
|
||||||
|
String key = key(link);
|
||||||
|
AggLink lr = aggLinks.get(key);
|
||||||
|
if (lr == null) {
|
||||||
|
lr = new AggLink(key);
|
||||||
|
aggLinks.put(key, lr);
|
||||||
|
}
|
||||||
|
lr.addLink(link);
|
||||||
|
}
|
||||||
|
return aggLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Produces JSON for a graph vertex.
|
||||||
|
private ObjectNode json(ObjectMapper mapper, ElementId id, int group,
|
||||||
|
boolean isOnline) {
|
||||||
|
return mapper.createObjectNode()
|
||||||
|
.put("name", id.uri().getSchemeSpecificPart())
|
||||||
|
.put("group", group)
|
||||||
|
.put("online", isOnline);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Produces JSON for a graph edge.
|
||||||
|
private ObjectNode json(ObjectMapper mapper, int count,
|
||||||
|
ConnectPoint src, ConnectPoint dst) {
|
||||||
|
return json(mapper, count, id(src), id(dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Produces JSON for a graph edge.
|
||||||
|
private ObjectNode json(ObjectMapper mapper, int count, String src, String dst) {
|
||||||
|
return mapper.createObjectNode()
|
||||||
|
.put("source", src).put("target", dst).put("value", count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregate link of all links between the same devices regardless of
|
||||||
|
// their direction.
|
||||||
|
private class AggLink {
|
||||||
|
Link link; // representative links
|
||||||
|
|
||||||
|
final String key;
|
||||||
|
final Set<Link> links = new HashSet<>();
|
||||||
|
|
||||||
|
AggLink(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addLink(Link link) {
|
||||||
|
links.add(link);
|
||||||
|
if (this.link == null) {
|
||||||
|
this.link = link;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a canonical key for the specified link.
|
||||||
|
static String key(Link link) {
|
||||||
|
String s = id(link.src());
|
||||||
|
String d = id(link.dst());
|
||||||
|
return s.compareTo(d) > 0 ? d + s : s + d;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a formatted string for the element associated with the given
|
||||||
|
// connection point.
|
||||||
|
private static String id(ConnectPoint cp) {
|
||||||
|
return cp.elementId().uri().getSchemeSpecificPart();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
27
apps/tvue/src/main/webapp/WEB-INF/web.xml
Normal file
27
apps/tvue/src/main/webapp/WEB-INF/web.xml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?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>
|
||||||
|
|
||||||
|
<welcome-file-list>
|
||||||
|
<welcome-file>index.html</welcome-file>
|
||||||
|
</welcome-file-list>
|
||||||
|
|
||||||
|
<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.tvue</param-value>
|
||||||
|
</init-param>
|
||||||
|
<load-on-startup>1</load-on-startup>
|
||||||
|
</servlet>
|
||||||
|
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>JAX-RS Service</servlet-name>
|
||||||
|
<url-pattern>/rs/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
</web-app>
|
||||||
365
apps/tvue/src/main/webapp/index.html
Normal file
365
apps/tvue/src/main/webapp/index.html
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Topology Viewer</title>
|
||||||
|
<script src="libs/d3.v3.min.js"></script>
|
||||||
|
<script src="libs/jquery-1.11.1.min.js"></script>
|
||||||
|
<style>
|
||||||
|
.link {
|
||||||
|
}
|
||||||
|
|
||||||
|
.node {
|
||||||
|
stroke-width: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.textClass {
|
||||||
|
stroke: #323232;
|
||||||
|
font-family: "Lucida Grande", "Droid Sans", Arial, Helvetica, sans-serif;
|
||||||
|
font-weight: normal;
|
||||||
|
stroke-width: .5;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
// Adapted from sample code @ ericcoopey’s block #6c602d7cb14b25c179a4
|
||||||
|
// by Thomas Vachuska
|
||||||
|
|
||||||
|
var graph,
|
||||||
|
topo = {vertexes:{}, edges:{}},
|
||||||
|
paths = [],
|
||||||
|
currentPath = 0;
|
||||||
|
|
||||||
|
// Set up the canvas
|
||||||
|
var w = 2048,
|
||||||
|
h = 2048;
|
||||||
|
|
||||||
|
// Allocate colors predictably
|
||||||
|
var color = d3.scale.category10(),
|
||||||
|
deviceColor = color(2),
|
||||||
|
sourceColor = color(0),
|
||||||
|
targetColor = color(1),
|
||||||
|
dummy1Color = color(9),
|
||||||
|
dummy2Color = color(8),
|
||||||
|
dummy3Color = color(7),
|
||||||
|
dummy4Color = color(6),
|
||||||
|
offlineColor = color(5),
|
||||||
|
dummy5Color = color(4),
|
||||||
|
hostColor = color(3);
|
||||||
|
|
||||||
|
var selectedNode,
|
||||||
|
sourceNode,
|
||||||
|
targetNode,
|
||||||
|
pathRequested;
|
||||||
|
|
||||||
|
|
||||||
|
function fillColor(d) {
|
||||||
|
return ((targetNode && targetNode.id == d.id) ? targetColor :
|
||||||
|
((sourceNode && sourceNode.id == d.id) ? sourceColor :
|
||||||
|
d.online ? color(d.group) : offlineColor));
|
||||||
|
}
|
||||||
|
|
||||||
|
function strokeColor(d) {
|
||||||
|
return selectedNode && d.id == selectedNode.id ? "#f00" : "#aaa";
|
||||||
|
}
|
||||||
|
|
||||||
|
function linkColor(d) {
|
||||||
|
if (!paths || paths.length == 0) {
|
||||||
|
return "#666";
|
||||||
|
}
|
||||||
|
|
||||||
|
var path = paths[currentPath];
|
||||||
|
if (path) {
|
||||||
|
for (var i = 0, n = path.length; i < n; i++) {
|
||||||
|
var link = path[i];
|
||||||
|
if ((link.src == d.source.id || link.dst == d.source.id) &&
|
||||||
|
(link.dst == d.target.id || link.src == d.target.id)) {
|
||||||
|
return "#f00";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "#666";
|
||||||
|
}
|
||||||
|
|
||||||
|
function linkKey(link) {
|
||||||
|
return link.source.id + "-" + link.target.id;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
function toggleNode(node) {
|
||||||
|
pathRequested = false;
|
||||||
|
return selectedNode && selectedNode != node ? selectedNode : null;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
function refreshPaths() {
|
||||||
|
d3.selectAll("line").attr("stroke", linkColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchPaths() {
|
||||||
|
if (!pathRequested && sourceNode && targetNode) {
|
||||||
|
pathRequested = true;
|
||||||
|
d3.json("rs/topology/paths/" + sourceNode.id + "/" + targetNode.id, function(error, data) {
|
||||||
|
currentPath = 0;
|
||||||
|
paths = data.paths;
|
||||||
|
refreshPaths();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetSelections() {
|
||||||
|
selectedNode = null;
|
||||||
|
sourceNode = null;
|
||||||
|
targetNode = null;
|
||||||
|
paths = [];
|
||||||
|
currentPath = 0;
|
||||||
|
refreshPaths();
|
||||||
|
d3.selectAll(".nodeStrokeClass").attr("stroke", strokeColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextPath() {
|
||||||
|
currentPath = paths && currentPath < paths.length - 1 ? currentPath + 1 : 0
|
||||||
|
console.log("Showing path: " + currentPath);
|
||||||
|
refreshPaths();
|
||||||
|
}
|
||||||
|
|
||||||
|
function dblclick(d) {
|
||||||
|
d3.select(this).classed("fixed", d.fixed = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function dragstart(d) {
|
||||||
|
d3.select(this).classed("fixed", d.fixed = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function topoGraph() {
|
||||||
|
// Add and remove elements on the graph object
|
||||||
|
this.addNode = function (vertex, stamp) {
|
||||||
|
var node = topo.vertexes[vertex.name];
|
||||||
|
if (node) {
|
||||||
|
var oldState = node.online;
|
||||||
|
node.online = vertex.online;
|
||||||
|
node.stamp = stamp;
|
||||||
|
if (oldState != node.online) {
|
||||||
|
update();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
node = {"id": vertex.name, "group": vertex.group,
|
||||||
|
"online": vertex.online, "stamp": stamp};
|
||||||
|
nodes.push(node);
|
||||||
|
topo.vertexes[vertex.name] = node;
|
||||||
|
update();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.addLink = function (edge, stamp) {
|
||||||
|
var key = edge.source + "-" + edge.target;
|
||||||
|
var link = topo.edges[key];
|
||||||
|
if (link) {
|
||||||
|
var oldValue = link.value;
|
||||||
|
link.value = edge.value;
|
||||||
|
link.stamp = stamp;
|
||||||
|
if (oldValue != link.value) {
|
||||||
|
update();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
link = {"source": findNode(edge.source), "target": findNode(edge.target),
|
||||||
|
"value": edge.value, "stamp": stamp};
|
||||||
|
links.push(link);
|
||||||
|
topo.edges[key] = link;
|
||||||
|
update();
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.prune = function (stamp) {
|
||||||
|
var linksChanged = pruneArray(links, stamp, topo.edges, linkKey);
|
||||||
|
var nodesChanged = pruneArray(nodes, stamp, topo.vertexes,
|
||||||
|
function(node) { return node.id; });
|
||||||
|
if (linksChanged || nodesChanged) {
|
||||||
|
update();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
var pruneArray = function(array, stamp, map, key) {
|
||||||
|
var changed = false;
|
||||||
|
for (var i = 0; i < array.length; i++) {
|
||||||
|
if (array[i].stamp < stamp) {
|
||||||
|
changed = true;
|
||||||
|
map[key(array[i])] = null;
|
||||||
|
array.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return changed;
|
||||||
|
};
|
||||||
|
|
||||||
|
var findNode = function (id) {
|
||||||
|
for (var i in nodes) {
|
||||||
|
if (nodes[i]["id"] === id) return nodes[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var force = d3.layout.force();
|
||||||
|
|
||||||
|
var drag = force.drag()
|
||||||
|
.on("dragstart", dragstart);
|
||||||
|
|
||||||
|
var nodes = force.nodes(),
|
||||||
|
links = force.links();
|
||||||
|
|
||||||
|
var vis = d3.select("body")
|
||||||
|
.append("svg:svg")
|
||||||
|
.attr("width", w)
|
||||||
|
.attr("height", h)
|
||||||
|
.attr("id", "svg")
|
||||||
|
.attr("pointer-events", "all")
|
||||||
|
.attr("viewBox", "0 0 " + w + " " + h)
|
||||||
|
.attr("perserveAspectRatio", "xMinYMid")
|
||||||
|
.append('svg:g');
|
||||||
|
|
||||||
|
d3.select("body")
|
||||||
|
.on("keydown", function(d) {
|
||||||
|
console.log(d3.event.keyCode);
|
||||||
|
if (d3.event.keyCode == 27) {
|
||||||
|
resetSelections();
|
||||||
|
} else if (d3.event.keyCode == 83) {
|
||||||
|
sourceNode = toggleNode(sourceNode);
|
||||||
|
} else if (d3.event.keyCode == 68) {
|
||||||
|
targetNode = toggleNode(targetNode);
|
||||||
|
} else if (d3.event.keyCode == 65) {
|
||||||
|
var aux = sourceNode;
|
||||||
|
sourceNode = targetNode;
|
||||||
|
targetNode = aux;
|
||||||
|
} else if (d3.event.keyCode == 70) {
|
||||||
|
nextPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
d3.selectAll(".nodeStrokeClass").attr("fill", fillColor);
|
||||||
|
fetchPaths();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var update = function () {
|
||||||
|
var link = vis.selectAll("line")
|
||||||
|
.data(links, linkKey);
|
||||||
|
|
||||||
|
link.enter().append("line")
|
||||||
|
.attr("id", linkKey)
|
||||||
|
.attr("class", "link")
|
||||||
|
.attr("stroke-width", function (d) { return d.value; })
|
||||||
|
.attr("stroke", linkColor);
|
||||||
|
link.append("title").text(function (d) { return d.id; });
|
||||||
|
link.exit().remove();
|
||||||
|
|
||||||
|
var node = vis.selectAll("g.node")
|
||||||
|
.data(nodes, function (d) { return d.id; })
|
||||||
|
.on("click", function(d) {
|
||||||
|
selectedNode = d;
|
||||||
|
d3.selectAll(".nodeStrokeClass").attr("stroke", strokeColor);
|
||||||
|
});
|
||||||
|
|
||||||
|
var nodeEnter = node.enter().append("g")
|
||||||
|
.attr("class", "node")
|
||||||
|
.on("dblclick", dblclick)
|
||||||
|
.call(force.drag);
|
||||||
|
|
||||||
|
nodeEnter.append("svg:circle")
|
||||||
|
.attr("r", function(d) { return 28 / 2; })
|
||||||
|
.attr("id", function (d) { return "n-" + d.id.replace(/[.:]/g, ""); })
|
||||||
|
.attr("class", "nodeStrokeClass")
|
||||||
|
.attr("fill", fillColor)
|
||||||
|
.attr("stroke", strokeColor);
|
||||||
|
|
||||||
|
nodeEnter.append("image")
|
||||||
|
.attr("xlink:href", function(d) { return d.group == 2 ? "images/switch.png" : "images/server.png"; })
|
||||||
|
.attr("x", -12)
|
||||||
|
.attr("y", -12)
|
||||||
|
.attr("width", 24)
|
||||||
|
.attr("height", 24);
|
||||||
|
|
||||||
|
nodeEnter.append("svg:text")
|
||||||
|
.attr("class", "textClass")
|
||||||
|
.attr("x", 20)
|
||||||
|
.attr("y", ".31em")
|
||||||
|
.text(function (d) { return d.id; });
|
||||||
|
|
||||||
|
node.exit().remove();
|
||||||
|
|
||||||
|
d3.selectAll("nodeStrokeClass").attr("stroke", strokeColor);
|
||||||
|
|
||||||
|
force.on("tick", function () {
|
||||||
|
node.attr("transform", function (d) {
|
||||||
|
return "translate(" + d.x + "," + d.y + ")";
|
||||||
|
});
|
||||||
|
|
||||||
|
link.attr("x1", function (d) { return d.source.x; })
|
||||||
|
.attr("y1", function (d) { return d.source.y; })
|
||||||
|
.attr("x2", function (d) { return d.target.x; })
|
||||||
|
.attr("y2", function (d) { return d.target.y; });
|
||||||
|
});
|
||||||
|
|
||||||
|
// Restart the force layout.
|
||||||
|
force
|
||||||
|
.gravity(0.3)
|
||||||
|
.charge(-15000)
|
||||||
|
.friction(0.1)
|
||||||
|
.linkDistance(function(d) { return d.value * 30; })
|
||||||
|
.linkStrength(function(d) { return d.value * 0.6; })
|
||||||
|
.size([w, h])
|
||||||
|
.start();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make it all go
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawGraph() {
|
||||||
|
graph = new topoGraph("#svgdiv");
|
||||||
|
bringNodesToFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
function bringNodesToFront() {
|
||||||
|
$(".nodeStrokeClass").each(function( index ) {
|
||||||
|
var gnode = this.parentNode;
|
||||||
|
gnode.parentNode.appendChild(gnode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addNodes() {
|
||||||
|
d3.select("svg")
|
||||||
|
.remove();
|
||||||
|
drawGraph();
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchData() {
|
||||||
|
var stamp = new Date().getTime();
|
||||||
|
d3.json("rs/topology/graph", function(error, data) {
|
||||||
|
var changed = false;
|
||||||
|
data.vertexes.forEach(function(vertex) { changed = graph.addNode(vertex, stamp) || changed; });
|
||||||
|
data.edges.forEach(function(edge) { changed = graph.addLink(edge, stamp) || changed; });
|
||||||
|
|
||||||
|
changed = graph.prune(stamp) || changed;
|
||||||
|
if (changed) {
|
||||||
|
bringNodesToFront();
|
||||||
|
// Update node and links styles
|
||||||
|
d3.selectAll(".nodeStrokeClass").attr("fill", fillColor);
|
||||||
|
d3.selectAll(".line").attr("stroke-width", function (d) { return d.value; })
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(fetchData, 1000);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
drawGraph();
|
||||||
|
setTimeout(fetchData, 500);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
25
core/api/src/main/java/org/onlab/onos/net/flow/Criteria.java
Normal file
25
core/api/src/main/java/org/onlab/onos/net/flow/Criteria.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package org.onlab.onos.net.flow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory class to create various traffic selection criteria.
|
||||||
|
*/
|
||||||
|
public final class Criteria {
|
||||||
|
|
||||||
|
// Ban construction
|
||||||
|
private Criteria() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a match on ETH_SRC field using the specified value. This value
|
||||||
|
* may be a wildcard mask.
|
||||||
|
*
|
||||||
|
* @param macValue MAC address value or wildcard mask
|
||||||
|
* @return match criterion
|
||||||
|
*/
|
||||||
|
public static Criterion matchEthSrc(MACValue macValue) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dummy to illustrate the concept for now; delete ASAP
|
||||||
|
private static class MACValue { }
|
||||||
|
}
|
||||||
@ -0,0 +1,98 @@
|
|||||||
|
package org.onlab.onos.net.flow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of a single header field selection.
|
||||||
|
*/
|
||||||
|
public interface Criterion {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types of fields to which the selection criterion may apply.
|
||||||
|
*/
|
||||||
|
// From page 42 of OpenFlow 1.3.x spec
|
||||||
|
public enum Type {
|
||||||
|
/** Switch input port. */
|
||||||
|
IN_PORT,
|
||||||
|
/** Switch physical input port. */
|
||||||
|
IN_PHY_PORT,
|
||||||
|
/** Metadata passed between tables. */
|
||||||
|
METADATA,
|
||||||
|
/** Ethernet destination address. */
|
||||||
|
ETH_DST,
|
||||||
|
/** Ethernet source address. */
|
||||||
|
ETH_SRC,
|
||||||
|
/** Ethernet frame type. */
|
||||||
|
ETH_TYPE,
|
||||||
|
/** VLAN id. */
|
||||||
|
VLAN_VID,
|
||||||
|
/** VLAN priority. */
|
||||||
|
VLAN_PCP,
|
||||||
|
/** IP DSCP (6 bits in ToS field). */
|
||||||
|
IP_DSCP,
|
||||||
|
/** IP ECN (2 bits in ToS field). */
|
||||||
|
IP_ECN,
|
||||||
|
/** IP protocol. */
|
||||||
|
IP_PROTO,
|
||||||
|
/** IPv4 source address. */
|
||||||
|
IPV4_SRC,
|
||||||
|
/** IPv4 destination address. */
|
||||||
|
IPV4_DST,
|
||||||
|
/** TCP source port. */
|
||||||
|
TCP_SRC,
|
||||||
|
/** TCP destination port. */
|
||||||
|
TCP_DST,
|
||||||
|
/** UDP source port. */
|
||||||
|
UDP_SRC,
|
||||||
|
/** UDP destination port. */
|
||||||
|
UDP_DST,
|
||||||
|
/** SCTP source port. */
|
||||||
|
SCTP_SRC,
|
||||||
|
/** SCTP destination port. */
|
||||||
|
SCTP_DST,
|
||||||
|
/** ICMP type. */
|
||||||
|
ICMPV4_TYPE,
|
||||||
|
/** ICMP code. */
|
||||||
|
ICMPV4_CODE,
|
||||||
|
/** ARP opcode. */
|
||||||
|
ARP_OP,
|
||||||
|
/** ARP source IPv4 address. */
|
||||||
|
ARP_SPA,
|
||||||
|
/** ARP target IPv4 address. */
|
||||||
|
ARP_TPA,
|
||||||
|
/** ARP source hardware address. */
|
||||||
|
ARP_SHA,
|
||||||
|
/** ARP target hardware address. */
|
||||||
|
ARP_THA,
|
||||||
|
/** IPv6 source address. */
|
||||||
|
IPV6_SRC,
|
||||||
|
/** IPv6 destination address. */
|
||||||
|
IPV6_DST,
|
||||||
|
/** IPv6 Flow Label. */
|
||||||
|
IPV6_FLABEL,
|
||||||
|
/** ICMPv6 type. */
|
||||||
|
ICMPV6_TYPE,
|
||||||
|
/** ICMPv6 code. */
|
||||||
|
ICMPV6_CODE,
|
||||||
|
/** Target address for ND. */
|
||||||
|
IPV6_ND_TARGET,
|
||||||
|
/** Source link-layer for ND. */
|
||||||
|
IPV6_ND_SLL,
|
||||||
|
/** Target link-layer for ND. */
|
||||||
|
IPV6_ND_TLL,
|
||||||
|
/** MPLS label. */
|
||||||
|
MPLS_LABEL,
|
||||||
|
/** MPLS TC. */
|
||||||
|
MPLS_TC,
|
||||||
|
/** MPLS BoS bit. */
|
||||||
|
MPLS_BOS,
|
||||||
|
/** PBB I-SID. */
|
||||||
|
PBB_ISID,
|
||||||
|
/** Logical Port Metadata. */
|
||||||
|
TUNNEL_ID,
|
||||||
|
/** IPv6 Extension Header pseudo-field. */
|
||||||
|
IPV6_EXTHDR
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Create factory class 'Criteria' that will have various factory
|
||||||
|
// to create specific criterions.
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,12 +0,0 @@
|
|||||||
package org.onlab.onos.net.flow;
|
|
||||||
|
|
||||||
import org.onlab.onos.net.Description;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information about a flow rule.
|
|
||||||
*/
|
|
||||||
public interface FlowDescription extends Description {
|
|
||||||
|
|
||||||
// Match and action, possibly reason for flow rule, unless reason is too OF-specific.
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package org.onlab.onos.net.flow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a flow rule and its associated accumulated metrics.
|
||||||
|
*/
|
||||||
|
public interface FlowEntry extends FlowRule {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of milliseconds this flow rule has been applied.
|
||||||
|
*
|
||||||
|
* @return number of millis
|
||||||
|
*/
|
||||||
|
long lifeMillis();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of milliseconds this flow rule has been idle.
|
||||||
|
*
|
||||||
|
* @return number of millis
|
||||||
|
*/
|
||||||
|
long idleMillis();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of packets this flow rule has matched.
|
||||||
|
*
|
||||||
|
* @return number of packets
|
||||||
|
*/
|
||||||
|
long packets();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of bytes this flow rule has matched.
|
||||||
|
*
|
||||||
|
* @return number of bytes
|
||||||
|
*/
|
||||||
|
long bytes();
|
||||||
|
|
||||||
|
}
|
||||||
43
core/api/src/main/java/org/onlab/onos/net/flow/FlowRule.java
Normal file
43
core/api/src/main/java/org/onlab/onos/net/flow/FlowRule.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package org.onlab.onos.net.flow;
|
||||||
|
|
||||||
|
import org.onlab.onos.net.DeviceId;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a generalized match & action pair to be applied to
|
||||||
|
* an infrastucture device.
|
||||||
|
*/
|
||||||
|
public interface FlowRule {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the flow rule priority given in natural order; higher numbers
|
||||||
|
* mean higher priorities.
|
||||||
|
*
|
||||||
|
* @return flow rule priority
|
||||||
|
*/
|
||||||
|
int priority();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the identity of the device where this rule applies.
|
||||||
|
*
|
||||||
|
* @return device identifier
|
||||||
|
*/
|
||||||
|
DeviceId deviceId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the traffic selector that identifies what traffic this
|
||||||
|
* rule should apply to.
|
||||||
|
*
|
||||||
|
* @return traffic selector
|
||||||
|
*/
|
||||||
|
TrafficSelector selector();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the traffic treatment that applies to selected traffic.
|
||||||
|
*
|
||||||
|
* @return traffic treatment
|
||||||
|
*/
|
||||||
|
List<Treatment> treatments();
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
package org.onlab.onos.net.flow;
|
||||||
|
|
||||||
|
import org.onlab.onos.event.AbstractEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes flow rule event.
|
||||||
|
*/
|
||||||
|
public class FlowRuleEvent extends AbstractEvent<FlowRuleEvent.Type, FlowRule> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of flow rule events.
|
||||||
|
*/
|
||||||
|
public enum Type {
|
||||||
|
/**
|
||||||
|
* Signifies that a new flow rule has been detected.
|
||||||
|
*/
|
||||||
|
RULE_ADDED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signifies that a flow rule has been removed.
|
||||||
|
*/
|
||||||
|
RULE_REMOVED,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an event of a given type and for the specified flow rule and the
|
||||||
|
* current time.
|
||||||
|
*
|
||||||
|
* @param type flow rule event type
|
||||||
|
* @param flowRule event flow rule subject
|
||||||
|
*/
|
||||||
|
public FlowRuleEvent(Type type, FlowRule flowRule) {
|
||||||
|
super(type, flowRule);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an event of a given type and for the specified flow rule and time.
|
||||||
|
*
|
||||||
|
* @param type flow rule event type
|
||||||
|
* @param flowRule event flow rule subject
|
||||||
|
* @param time occurrence time
|
||||||
|
*/
|
||||||
|
public FlowRuleEvent(Type type, FlowRule flowRule, long time) {
|
||||||
|
super(type, flowRule, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package org.onlab.onos.net.flow;
|
||||||
|
|
||||||
|
import org.onlab.onos.event.EventListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entity capable of receiving flow rule related events.
|
||||||
|
*/
|
||||||
|
public interface FlowRuleListener extends EventListener<FlowRuleEvent> {
|
||||||
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
package org.onlab.onos.net.flow;
|
package org.onlab.onos.net.flow;
|
||||||
|
|
||||||
|
import org.onlab.onos.net.DeviceId;
|
||||||
import org.onlab.onos.net.provider.Provider;
|
import org.onlab.onos.net.provider.Provider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -7,6 +8,23 @@ import org.onlab.onos.net.provider.Provider;
|
|||||||
*/
|
*/
|
||||||
public interface FlowRuleProvider extends Provider {
|
public interface FlowRuleProvider extends Provider {
|
||||||
|
|
||||||
// TODO: pushFlowRule
|
/**
|
||||||
|
* Instructs the provider to apply the specified flow rules to their
|
||||||
|
* respective devices.
|
||||||
|
* @param flowRules one or more flow rules
|
||||||
|
* throws SomeKindOfException that indicates which ones were applied and
|
||||||
|
* which ones failed
|
||||||
|
*/
|
||||||
|
void applyFlowRule(FlowRule... flowRules);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the collection of flow entries currently applied on the given
|
||||||
|
* device.
|
||||||
|
*
|
||||||
|
* @param deviceId device identifier
|
||||||
|
* @return collection of flow entries
|
||||||
|
*/
|
||||||
|
Iterable<FlowEntry> getFlowMetrics(DeviceId deviceId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,33 +3,23 @@ package org.onlab.onos.net.flow;
|
|||||||
import org.onlab.onos.net.provider.ProviderService;
|
import org.onlab.onos.net.provider.ProviderService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service through which flowrule providers can inject flowrule information into
|
* Service through which flow rule providers can inject information into
|
||||||
* the core.
|
* the core.
|
||||||
*/
|
*/
|
||||||
public interface FlowRuleProviderService extends ProviderService<FlowRuleProvider> {
|
public interface FlowRuleProviderService extends ProviderService<FlowRuleProvider> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals that a flow that was previously installed has been removed.
|
* Signals that a flow rule that was previously installed has been removed.
|
||||||
*
|
*
|
||||||
* @param flowDescription information about the removed flow
|
* @param flowRule information about the removed flow
|
||||||
*/
|
*/
|
||||||
void flowRemoved(FlowDescription flowDescription);
|
void flowRemoved(FlowRule flowRule);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signals that a flowrule is missing for some network traffic.
|
* Signals that a flow rule is missing for some network traffic.
|
||||||
*
|
*
|
||||||
* @param flowDescription information about traffic in need of flow rule(s)
|
* @param flowRule information about traffic in need of flow rule(s)
|
||||||
*/
|
*/
|
||||||
void flowMissing(FlowDescription flowDescription);
|
void flowMissing(FlowRule flowRule);
|
||||||
|
|
||||||
/**
|
|
||||||
* Signals that a flowrule has been added.
|
|
||||||
*
|
|
||||||
* TODO think about if this really makes sense, e.g. if stats collection or
|
|
||||||
* something can leverage it.
|
|
||||||
*
|
|
||||||
* @param flowDescription the rule that was added
|
|
||||||
*/
|
|
||||||
void flowAdded(FlowDescription flowDescription);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,42 @@
|
|||||||
|
package org.onlab.onos.net.flow;
|
||||||
|
|
||||||
|
import org.onlab.onos.net.DeviceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for injecting flow rules into the environment and for obtaining
|
||||||
|
* information about flow rules already in the environment.
|
||||||
|
*/
|
||||||
|
public interface FlowRuleService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the collection of flow entries applied on the specified device.
|
||||||
|
*
|
||||||
|
* @param deviceId device identifier
|
||||||
|
* @return collection of flow rules
|
||||||
|
*/
|
||||||
|
Iterable<FlowEntry> getFlowEntries(DeviceId deviceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the specified flow rules onto their respective devices.
|
||||||
|
*
|
||||||
|
* @param flowRules one or more flow rules
|
||||||
|
* throws SomeKindOfException that indicates which ones were applied and
|
||||||
|
* which ones failed
|
||||||
|
*/
|
||||||
|
void applyFlowRules(FlowRule... flowRules);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the specified flow rule listener.
|
||||||
|
*
|
||||||
|
* @param listener flow rule listener
|
||||||
|
*/
|
||||||
|
void addListener(FlowRuleListener listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the specified flow rule listener.
|
||||||
|
*
|
||||||
|
* @param listener flow rule listener
|
||||||
|
*/
|
||||||
|
void removeListener(FlowRuleListener listener);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package org.onlab.onos.net.flow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstraction of a single traffic treatment step.
|
||||||
|
*/
|
||||||
|
public interface Instruction {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the type of traffic treatment.
|
||||||
|
*/
|
||||||
|
public enum Type {
|
||||||
|
/**
|
||||||
|
* Signifies that the traffic should be dropped.
|
||||||
|
*/
|
||||||
|
DROP,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signifies that the traffic should be output to a port.
|
||||||
|
*/
|
||||||
|
OUTPUT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signifies that.... (do we need this?)
|
||||||
|
*/
|
||||||
|
GROUP,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signifies that the traffic should be modified in some way.
|
||||||
|
*/
|
||||||
|
MODIFICATION
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Create factory class 'Instructions' that will have various factory
|
||||||
|
// to create specific instructions.
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package org.onlab.onos.net.flow;
|
||||||
|
|
||||||
|
import org.onlab.onos.net.PortNumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory class for creating various traffic treatment instructions.
|
||||||
|
*/
|
||||||
|
public final class Instructions {
|
||||||
|
|
||||||
|
// Ban construction
|
||||||
|
private Instructions() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an output instruction using the specified port number. This can
|
||||||
|
* include logical ports such as CONTROLLER, FLOOD, etc.
|
||||||
|
*
|
||||||
|
* @param number port number
|
||||||
|
* @return output instruction
|
||||||
|
*/
|
||||||
|
public static Instruction createOutput(PortNumber number) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add create methods
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
package org.onlab.onos.net.flow;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstraction of a slice of network traffic.
|
||||||
|
*/
|
||||||
|
public interface TrafficSelector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns selection criteria as an ordered list.
|
||||||
|
*
|
||||||
|
* @return list of criteria
|
||||||
|
*/
|
||||||
|
List<Criterion> criteria();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder of traffic selector entities.
|
||||||
|
*/
|
||||||
|
public interface Builder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a traffic selection criterion. If a same type criterion has
|
||||||
|
* already been added, it will be replaced by this one.
|
||||||
|
*
|
||||||
|
* @param criterion new criterion
|
||||||
|
*/
|
||||||
|
void add(Criterion criterion);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds an immutable traffic selector.
|
||||||
|
*
|
||||||
|
* @return traffic selector
|
||||||
|
*/
|
||||||
|
TrafficSelector build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
package org.onlab.onos.net.flow;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstraction of network traffic treatment.
|
||||||
|
*/
|
||||||
|
public interface TrafficTreatment {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns list of instructions on how to treat traffic.
|
||||||
|
*
|
||||||
|
* @return list of treatment instructions
|
||||||
|
*/
|
||||||
|
List<Instruction> instructions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder of traffic treatment entities.
|
||||||
|
*/
|
||||||
|
public interface Builder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a traffic treatment instruction. If a same type instruction has
|
||||||
|
* already been added, it will be replaced by this one.
|
||||||
|
*
|
||||||
|
* @param instruction new instruction
|
||||||
|
*/
|
||||||
|
void add(Instruction instruction);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds an immutable traffic treatment descriptor.
|
||||||
|
*
|
||||||
|
* @return traffic treatment
|
||||||
|
*/
|
||||||
|
TrafficTreatment build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package org.onlab.onos.net.packet;
|
package org.onlab.onos.net.flow;
|
||||||
|
|
||||||
import org.onlab.onos.net.PortNumber;
|
import org.onlab.onos.net.PortNumber;
|
||||||
|
|
||||||
@ -1,31 +1,30 @@
|
|||||||
package org.onlab.onos.net.packet;
|
package org.onlab.onos.net.packet;
|
||||||
|
|
||||||
import com.google.common.base.MoreObjects;
|
import com.google.common.base.MoreObjects;
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import org.onlab.onos.net.DeviceId;
|
import org.onlab.onos.net.DeviceId;
|
||||||
|
import org.onlab.onos.net.flow.TrafficTreatment;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default implementation of an immutable outbound packet.
|
* Default implementation of an immutable outbound packet.
|
||||||
*/
|
*/
|
||||||
public class DefaultOutboundPacket implements OutboundPacket {
|
public class DefaultOutboundPacket implements OutboundPacket {
|
||||||
private final DeviceId sendThrough;
|
private final DeviceId sendThrough;
|
||||||
private final List<Treatment> treatments;
|
private final TrafficTreatment treatment;
|
||||||
private final ByteBuffer data;
|
private final ByteBuffer data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an immutable outbound packet.
|
* Creates an immutable outbound packet.
|
||||||
*
|
*
|
||||||
* @param sendThrough identifier through which to send the packet
|
* @param sendThrough identifier through which to send the packet
|
||||||
* @param treatments list of packet treatments
|
* @param treatment list of packet treatments
|
||||||
* @param data raw packet data
|
* @param data raw packet data
|
||||||
*/
|
*/
|
||||||
public DefaultOutboundPacket(DeviceId sendThrough,
|
public DefaultOutboundPacket(DeviceId sendThrough,
|
||||||
List<Treatment> treatments, ByteBuffer data) {
|
TrafficTreatment treatment, ByteBuffer data) {
|
||||||
this.sendThrough = sendThrough;
|
this.sendThrough = sendThrough;
|
||||||
this.treatments = ImmutableList.copyOf(treatments);
|
this.treatment = treatment;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,8 +34,8 @@ public class DefaultOutboundPacket implements OutboundPacket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Treatment> treatments() {
|
public TrafficTreatment treatment() {
|
||||||
return treatments;
|
return treatment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -49,7 +48,7 @@ public class DefaultOutboundPacket implements OutboundPacket {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return MoreObjects.toStringHelper(this)
|
return MoreObjects.toStringHelper(this)
|
||||||
.add("sendThrough", sendThrough)
|
.add("sendThrough", sendThrough)
|
||||||
.add("treatments", treatments)
|
.add("treatment", treatment)
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,48 @@
|
|||||||
|
package org.onlab.onos.net.packet;
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class DefaultPacketContext implements PacketContext {
|
||||||
|
|
||||||
|
private final long time;
|
||||||
|
private final InboundPacket inPkt;
|
||||||
|
private final OutboundPacket outPkt;
|
||||||
|
private boolean block = false;
|
||||||
|
|
||||||
|
protected DefaultPacketContext(long time, InboundPacket inPkt,
|
||||||
|
OutboundPacket outPkt, boolean block) {
|
||||||
|
super();
|
||||||
|
this.time = time;
|
||||||
|
this.inPkt = inPkt;
|
||||||
|
this.outPkt = outPkt;
|
||||||
|
this.block = block;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long time() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InboundPacket inPacket() {
|
||||||
|
return inPkt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OutboundPacket outPacket() {
|
||||||
|
return outPkt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract void send();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void block() {
|
||||||
|
this.block = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isHandled() {
|
||||||
|
return this.block;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,9 +1,9 @@
|
|||||||
package org.onlab.onos.net.packet;
|
package org.onlab.onos.net.packet;
|
||||||
|
|
||||||
import org.onlab.onos.net.DeviceId;
|
import org.onlab.onos.net.DeviceId;
|
||||||
|
import org.onlab.onos.net.flow.TrafficTreatment;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an outbound data packet that is to be emitted to network via
|
* Represents an outbound data packet that is to be emitted to network via
|
||||||
@ -20,14 +20,14 @@ public interface OutboundPacket {
|
|||||||
DeviceId sendThrough();
|
DeviceId sendThrough();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns list of treatments for the outbound packet.
|
* Returns how the outbound packet should be treated.
|
||||||
*
|
*
|
||||||
* @return output treatment
|
* @return output treatment
|
||||||
*/
|
*/
|
||||||
List<Treatment> treatments();
|
TrafficTreatment treatment();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the raw data to be sent.
|
* Returns immutable view of the raw data to be sent.
|
||||||
*
|
*
|
||||||
* @return data to emit
|
* @return data to emit
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package org.onlab.onos.net.packet;
|
package org.onlab.onos.net.packet;
|
||||||
|
|
||||||
|
import org.onlab.onos.net.flow.TrafficTreatment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents context for processing an inbound packet, and (optionally)
|
* Represents context for processing an inbound packet, and (optionally)
|
||||||
* emitting a corresponding outbound packet.
|
* emitting a corresponding outbound packet.
|
||||||
@ -28,11 +30,11 @@ public interface PacketContext {
|
|||||||
OutboundPacket outPacket();
|
OutboundPacket outPacket();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends a new treatment to be applied to the outbound packet.
|
* Returns a builder for constructing traffic treatment.
|
||||||
*
|
*
|
||||||
* @param treatment output treatment
|
* @return traffic treatment builder
|
||||||
*/
|
*/
|
||||||
void appendTreatment(Treatment treatment);
|
TrafficTreatment.Builder treatmentBuilder();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers the outbound packet to be sent.
|
* Triggers the outbound packet to be sent.
|
||||||
|
|||||||
@ -62,7 +62,6 @@
|
|||||||
<feature>onos-core</feature>
|
<feature>onos-core</feature>
|
||||||
<bundle>mvn:io.netty/netty/3.9.2.Final</bundle>
|
<bundle>mvn:io.netty/netty/3.9.2.Final</bundle>
|
||||||
|
|
||||||
<!--bundle>mvn:org.projectfloodlight/openflowj/0.3.8-SNAPSHOT</bundle-->
|
|
||||||
<bundle>mvn:org.onlab.onos/onos-of-api/1.0.0-SNAPSHOT</bundle>
|
<bundle>mvn:org.onlab.onos/onos-of-api/1.0.0-SNAPSHOT</bundle>
|
||||||
<bundle>mvn:org.onlab.onos/onos-of-ctl/1.0.0-SNAPSHOT</bundle>
|
<bundle>mvn:org.onlab.onos/onos-of-ctl/1.0.0-SNAPSHOT</bundle>
|
||||||
|
|
||||||
@ -71,4 +70,10 @@
|
|||||||
<bundle>mvn:org.onlab.onos/onos-of-provider-host/1.0.0-SNAPSHOT</bundle>
|
<bundle>mvn:org.onlab.onos/onos-of-provider-host/1.0.0-SNAPSHOT</bundle>
|
||||||
</feature>
|
</feature>
|
||||||
|
|
||||||
|
<feature name="onos-app-tvue" version="1.0.0"
|
||||||
|
description="ONOS sample topology viewer application">
|
||||||
|
<feature>onos-core</feature>
|
||||||
|
<bundle>mvn:org.onlab.onos/onos-app-tvue/1.0.0-SNAPSHOT</bundle>
|
||||||
|
</feature>
|
||||||
|
|
||||||
</features>
|
</features>
|
||||||
|
|||||||
7
pom.xml
7
pom.xml
@ -19,6 +19,7 @@
|
|||||||
<module>cli</module>
|
<module>cli</module>
|
||||||
<module>providers</module>
|
<module>providers</module>
|
||||||
<module>of</module>
|
<module>of</module>
|
||||||
|
<module>apps</module>
|
||||||
<module>features</module>
|
<module>features</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
@ -355,6 +356,12 @@
|
|||||||
org.onlab.onos.gui:org.onlab.onos.rest:org.onlab.onos.cli:org.onlab.onos.gui.*:org.onlab.onos.rest.*:org.onlab.onos.cli.*
|
org.onlab.onos.gui:org.onlab.onos.rest:org.onlab.onos.cli:org.onlab.onos.gui.*:org.onlab.onos.rest.*:org.onlab.onos.cli.*
|
||||||
</packages>
|
</packages>
|
||||||
</group>
|
</group>
|
||||||
|
<group>
|
||||||
|
<title>Sample Applications</title>
|
||||||
|
<packages>
|
||||||
|
org.onlab.onos.tvue
|
||||||
|
</packages>
|
||||||
|
</group>
|
||||||
</groups>
|
</groups>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user