Ayaka Koshibe

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

Showing 25 changed files with 1218 additions and 42 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</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>
<?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>
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();
}
}
<?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>
\ No newline at end of file
<!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>
\ No newline at end of file
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 { }
}
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.
}
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();
}
package org.onlab.onos.net.flow;
import org.onlab.onos.net.DeviceId;
import java.util.List;
/**
* Represents a generalized match &amp; 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();
}
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);
}
}
package org.onlab.onos.net.flow;
import org.onlab.onos.net.Description;
import org.onlab.onos.event.EventListener;
/**
* Information about a flow rule.
* Entity capable of receiving flow rule related events.
*/
public interface FlowDescription extends Description {
// Match and action, possibly reason for flow rule, unless reason is too OF-specific.
public interface FlowRuleListener extends EventListener<FlowRuleEvent> {
}
......
package org.onlab.onos.net.flow;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.provider.Provider;
/**
......@@ -7,6 +8,23 @@ import org.onlab.onos.net.provider.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;
/**
* Service through which flowrule providers can inject flowrule information into
* Service through which flow rule providers can inject information into
* the core.
*/
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);
/**
* 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);
void flowMissing(FlowRule flowRule);
}
......
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);
}
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.
}
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
}
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();
}
}
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();
}
}
package org.onlab.onos.net.packet;
package org.onlab.onos.net.flow;
import org.onlab.onos.net.PortNumber;
......
package org.onlab.onos.net.packet;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.flow.TrafficTreatment;
import java.nio.ByteBuffer;
import java.util.List;
/**
* Default implementation of an immutable outbound packet.
*/
public class DefaultOutboundPacket implements OutboundPacket {
private final DeviceId sendThrough;
private final List<Treatment> treatments;
private final TrafficTreatment treatment;
private final ByteBuffer data;
/**
* Creates an immutable outbound 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
*/
public DefaultOutboundPacket(DeviceId sendThrough,
List<Treatment> treatments, ByteBuffer data) {
TrafficTreatment treatment, ByteBuffer data) {
this.sendThrough = sendThrough;
this.treatments = ImmutableList.copyOf(treatments);
this.treatment = treatment;
this.data = data;
}
......@@ -35,8 +34,8 @@ public class DefaultOutboundPacket implements OutboundPacket {
}
@Override
public List<Treatment> treatments() {
return treatments;
public TrafficTreatment treatment() {
return treatment;
}
@Override
......@@ -49,7 +48,7 @@ public class DefaultOutboundPacket implements OutboundPacket {
public String toString() {
return MoreObjects.toStringHelper(this)
.add("sendThrough", sendThrough)
.add("treatments", treatments)
.add("treatment", treatment)
.toString();
}
}
......
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;
}
}
package org.onlab.onos.net.packet;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.flow.TrafficTreatment;
import java.nio.ByteBuffer;
import java.util.List;
/**
* Represents an outbound data packet that is to be emitted to network via
......@@ -20,14 +20,14 @@ public interface OutboundPacket {
DeviceId sendThrough();
/**
* Returns list of treatments for the outbound packet.
* Returns how the outbound packet should be treated.
*
* @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
*/
......
package org.onlab.onos.net.packet;
import org.onlab.onos.net.flow.TrafficTreatment;
/**
* Represents context for processing an inbound packet, and (optionally)
* emitting a corresponding outbound packet.
......@@ -28,11 +30,11 @@ public interface PacketContext {
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.
......
......@@ -62,7 +62,6 @@
<feature>onos-core</feature>
<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-ctl/1.0.0-SNAPSHOT</bundle>
......@@ -71,4 +70,10 @@
<bundle>mvn:org.onlab.onos/onos-of-provider-host/1.0.0-SNAPSHOT</bundle>
</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>
......
......@@ -19,6 +19,7 @@
<module>cli</module>
<module>providers</module>
<module>of</module>
<module>apps</module>
<module>features</module>
</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.*
</packages>
</group>
<group>
<title>Sample Applications</title>
<packages>
org.onlab.onos.tvue
</packages>
</group>
</groups>
</configuration>
</plugin>
......