Ayaka Koshibe

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

Showing 25 changed files with 1218 additions and 42 deletions
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
5 + <modelVersion>4.0.0</modelVersion>
6 +
7 + <parent>
8 + <groupId>org.onlab.onos</groupId>
9 + <artifactId>onos</artifactId>
10 + <version>1.0.0-SNAPSHOT</version>
11 + <relativePath>../pom.xml</relativePath>
12 + </parent>
13 +
14 + <artifactId>onos-apps</artifactId>
15 + <packaging>pom</packaging>
16 +
17 + <description>ONOS sample applications</description>
18 +
19 + <modules>
20 + <module>tvue</module>
21 + </modules>
22 +
23 + <properties>
24 + <web.context>default</web.context>
25 + </properties>
26 +
27 + <dependencies>
28 + <dependency>
29 + <groupId>org.onlab.onos</groupId>
30 + <artifactId>onos-api</artifactId>
31 + </dependency>
32 +
33 + <dependency>
34 + <groupId>org.onlab.onos</groupId>
35 + <artifactId>onlab-osgi</artifactId>
36 + <version>${project.version}</version>
37 + </dependency>
38 +
39 + <dependency>
40 + <groupId>org.onlab.onos</groupId>
41 + <artifactId>onlab-rest</artifactId>
42 + <version>${project.version}</version>
43 + </dependency>
44 +
45 + <dependency>
46 + <groupId>com.sun.jersey</groupId>
47 + <artifactId>jersey-servlet</artifactId>
48 + </dependency>
49 + <dependency>
50 + <groupId>com.sun.jersey.jersey-test-framework</groupId>
51 + <artifactId>jersey-test-framework-core</artifactId>
52 + <version>1.18.1</version>
53 + <scope>test</scope>
54 + </dependency>
55 + <dependency>
56 + <groupId>com.sun.jersey.jersey-test-framework</groupId>
57 + <artifactId>jersey-test-framework-grizzly2</artifactId>
58 + <version>1.18.1</version>
59 + <scope>test</scope>
60 + </dependency>
61 +
62 + <dependency>
63 + <groupId>com.fasterxml.jackson.core</groupId>
64 + <artifactId>jackson-databind</artifactId>
65 + </dependency>
66 +
67 + <dependency>
68 + <groupId>com.fasterxml.jackson.core</groupId>
69 + <artifactId>jackson-annotations</artifactId>
70 + </dependency>
71 +
72 + <dependency>
73 + <groupId>org.osgi</groupId>
74 + <artifactId>org.osgi.core</artifactId>
75 + </dependency>
76 + <dependency>
77 + <groupId>org.apache.felix</groupId>
78 + <artifactId>org.apache.felix.scr.annotations</artifactId>
79 + </dependency>
80 + </dependencies>
81 +
82 + <build>
83 + <plugins>
84 + <plugin>
85 + <groupId>org.apache.felix</groupId>
86 + <artifactId>maven-bundle-plugin</artifactId>
87 + <extensions>true</extensions>
88 + <configuration>
89 + <instructions>
90 + <_wab>src/main/webapp/</_wab>
91 + <Bundle-SymbolicName>
92 + ${project.groupId}.${project.artifactId}
93 + </Bundle-SymbolicName>
94 + <Import-Package>
95 + org.osgi.framework,
96 + javax.ws.rs,javax.ws.rs.core,
97 + com.sun.jersey.api.core,
98 + com.sun.jersey.spi.container.servlet,
99 + com.sun.jersey.server.impl.container.servlet,
100 + com.fasterxml.jackson.databind,
101 + com.fasterxml.jackson.databind.node,
102 + org.onlab.rest.*,
103 + org.onlab.onos.*
104 + </Import-Package>
105 + <Web-ContextPath>${web.context}</Web-ContextPath>
106 + </instructions>
107 + </configuration>
108 + </plugin>
109 + </plugins>
110 + </build>
111 +
112 +</project>
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
5 + <modelVersion>4.0.0</modelVersion>
6 +
7 + <parent>
8 + <groupId>org.onlab.onos</groupId>
9 + <artifactId>onos-apps</artifactId>
10 + <version>1.0.0-SNAPSHOT</version>
11 + <relativePath>../pom.xml</relativePath>
12 + </parent>
13 +
14 + <artifactId>onos-app-tvue</artifactId>
15 + <packaging>bundle</packaging>
16 +
17 + <description>ONOS simple topology viewer</description>
18 +
19 + <properties>
20 + <web.context>/onos/tvue</web.context>
21 + </properties>
22 +
23 +</project>
1 +package org.onlab.onos.tvue;
2 +
3 +import com.fasterxml.jackson.databind.ObjectMapper;
4 +import com.fasterxml.jackson.databind.node.ArrayNode;
5 +import com.fasterxml.jackson.databind.node.ObjectNode;
6 +import org.onlab.onos.net.ConnectPoint;
7 +import org.onlab.onos.net.ElementId;
8 +import org.onlab.onos.net.Link;
9 +import org.onlab.onos.net.device.DeviceService;
10 +import org.onlab.onos.net.host.HostService;
11 +import org.onlab.onos.net.link.LinkService;
12 +import org.onlab.onos.net.topology.Topology;
13 +import org.onlab.onos.net.topology.TopologyGraph;
14 +import org.onlab.onos.net.topology.TopologyService;
15 +import org.onlab.onos.net.topology.TopologyVertex;
16 +import org.onlab.rest.BaseResource;
17 +
18 +import javax.ws.rs.GET;
19 +import javax.ws.rs.Path;
20 +import javax.ws.rs.Produces;
21 +import javax.ws.rs.core.Response;
22 +import java.util.HashMap;
23 +import java.util.HashSet;
24 +import java.util.Map;
25 +import java.util.Set;
26 +
27 +/**
28 + * Topology viewer resource.
29 + */
30 +@Path("topology")
31 +public class TopologyResource extends BaseResource {
32 +
33 + @Path("/graph")
34 + @GET
35 + @Produces("application/json")
36 + public Response graph() {
37 + ObjectMapper mapper = new ObjectMapper();
38 +
39 + // Fetch the services we'll be using.
40 + DeviceService deviceService = get(DeviceService.class);
41 + HostService hostService = get(HostService.class);
42 + TopologyService topologyService = get(TopologyService.class);
43 +
44 + // Fetch the current topology and its graph that we'll use to render.
45 + Topology topo = topologyService.currentTopology();
46 + TopologyGraph graph = topologyService.getGraph(topo);
47 +
48 + // Build all interior vertexes, i.e. no end-station hosts yet
49 + ArrayNode vertexesNode = mapper.createArrayNode();
50 + for (TopologyVertex vertex : graph.getVertexes()) {
51 + vertexesNode.add(json(mapper, vertex.deviceId(), 2,
52 + deviceService.isAvailable(vertex.deviceId())));
53 + }
54 +
55 + // Now scan all links and count number of them between the same devices
56 + // using a normalized link key.
57 + Map<String, AggLink> linkRecords = aggregateLinks();
58 +
59 + // Now build all interior edges using the aggregated links.
60 + ArrayNode edgesNode = mapper.createArrayNode();
61 + for (AggLink lr : linkRecords.values()) {
62 + edgesNode.add(json(mapper, lr.links.size(), lr.link.src(), lr.link.dst()));
63 + }
64 +
65 + // Merge the exterior and interior vertexes and inject host links as
66 + // the exterior edges.
67 +// Iterator<Host> hosts = hostService.getHosts();
68 +// while (hosts.hasNext()) {
69 +// Host host = hosts.next();
70 +// vertexesNode.add(json(mapper, host.id().ip().toString(), 3, true));
71 +// edgesNode.add(json(mapper, 1, host.ip().toString(),
72 +// host.location().elementId().uri()));
73 +// }
74 +
75 + // Now put the vertexes and edges into a root node and ship them off
76 + ObjectNode rootNode = mapper.createObjectNode();
77 + rootNode.put("vertexes", vertexesNode);
78 + rootNode.put("edges", edgesNode);
79 + return Response.ok(rootNode.toString()).build();
80 + }
81 +
82 + // Scan all links and counts number of them between the same devices
83 + // using a normalized link key.
84 + private Map<String, AggLink> aggregateLinks() {
85 + Map<String, AggLink> aggLinks = new HashMap<>();
86 + LinkService linkService = get(LinkService.class);
87 + for (Link link : linkService.getLinks()) {
88 + String key = key(link);
89 + AggLink lr = aggLinks.get(key);
90 + if (lr == null) {
91 + lr = new AggLink(key);
92 + aggLinks.put(key, lr);
93 + }
94 + lr.addLink(link);
95 + }
96 + return aggLinks;
97 + }
98 +
99 + // Produces JSON for a graph vertex.
100 + private ObjectNode json(ObjectMapper mapper, ElementId id, int group,
101 + boolean isOnline) {
102 + return mapper.createObjectNode()
103 + .put("name", id.uri().getSchemeSpecificPart())
104 + .put("group", group)
105 + .put("online", isOnline);
106 + }
107 +
108 + // Produces JSON for a graph edge.
109 + private ObjectNode json(ObjectMapper mapper, int count,
110 + ConnectPoint src, ConnectPoint dst) {
111 + return json(mapper, count, id(src), id(dst));
112 + }
113 +
114 + // Produces JSON for a graph edge.
115 + private ObjectNode json(ObjectMapper mapper, int count, String src, String dst) {
116 + return mapper.createObjectNode()
117 + .put("source", src).put("target", dst).put("value", count);
118 + }
119 +
120 + // Aggregate link of all links between the same devices regardless of
121 + // their direction.
122 + private class AggLink {
123 + Link link; // representative links
124 +
125 + final String key;
126 + final Set<Link> links = new HashSet<>();
127 +
128 + AggLink(String key) {
129 + this.key = key;
130 + }
131 +
132 + void addLink(Link link) {
133 + links.add(link);
134 + if (this.link == null) {
135 + this.link = link;
136 + }
137 + }
138 + }
139 +
140 + // Returns a canonical key for the specified link.
141 + static String key(Link link) {
142 + String s = id(link.src());
143 + String d = id(link.dst());
144 + return s.compareTo(d) > 0 ? d + s : s + d;
145 + }
146 +
147 + // Returns a formatted string for the element associated with the given
148 + // connection point.
149 + private static String id(ConnectPoint cp) {
150 + return cp.elementId().uri().getSchemeSpecificPart();
151 + }
152 +
153 +}
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
3 + xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
4 + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
5 + id="ONOS" version="2.5">
6 + <display-name>ONOS GUI</display-name>
7 +
8 + <welcome-file-list>
9 + <welcome-file>index.html</welcome-file>
10 + </welcome-file-list>
11 +
12 + <servlet>
13 + <servlet-name>JAX-RS Service</servlet-name>
14 + <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
15 + <init-param>
16 + <param-name>com.sun.jersey.config.property.packages</param-name>
17 + <param-value>org.onlab.onos.tvue</param-value>
18 + </init-param>
19 + <load-on-startup>1</load-on-startup>
20 + </servlet>
21 +
22 + <servlet-mapping>
23 + <servlet-name>JAX-RS Service</servlet-name>
24 + <url-pattern>/rs/*</url-pattern>
25 + </servlet-mapping>
26 +
27 +</web-app>
...\ No newline at end of file ...\ No newline at end of file
1 +<!DOCTYPE html>
2 +<html>
3 +<head>
4 + <title>Topology Viewer</title>
5 + <script src="libs/d3.v3.min.js"></script>
6 + <script src="libs/jquery-1.11.1.min.js"></script>
7 + <style>
8 + .link {
9 + }
10 +
11 + .node {
12 + stroke-width: 3px;
13 + }
14 +
15 + .textClass {
16 + stroke: #323232;
17 + font-family: "Lucida Grande", "Droid Sans", Arial, Helvetica, sans-serif;
18 + font-weight: normal;
19 + stroke-width: .5;
20 + font-size: 14px;
21 + }
22 + </style>
23 +</head>
24 +<body>
25 + <script>
26 + // Adapted from sample code @ ericcoopey’s block #6c602d7cb14b25c179a4
27 + // by Thomas Vachuska
28 +
29 + var graph,
30 + topo = {vertexes:{}, edges:{}},
31 + paths = [],
32 + currentPath = 0;
33 +
34 + // Set up the canvas
35 + var w = 2048,
36 + h = 2048;
37 +
38 + // Allocate colors predictably
39 + var color = d3.scale.category10(),
40 + deviceColor = color(2),
41 + sourceColor = color(0),
42 + targetColor = color(1),
43 + dummy1Color = color(9),
44 + dummy2Color = color(8),
45 + dummy3Color = color(7),
46 + dummy4Color = color(6),
47 + offlineColor = color(5),
48 + dummy5Color = color(4),
49 + hostColor = color(3);
50 +
51 + var selectedNode,
52 + sourceNode,
53 + targetNode,
54 + pathRequested;
55 +
56 +
57 + function fillColor(d) {
58 + return ((targetNode && targetNode.id == d.id) ? targetColor :
59 + ((sourceNode && sourceNode.id == d.id) ? sourceColor :
60 + d.online ? color(d.group) : offlineColor));
61 + }
62 +
63 + function strokeColor(d) {
64 + return selectedNode && d.id == selectedNode.id ? "#f00" : "#aaa";
65 + }
66 +
67 + function linkColor(d) {
68 + if (!paths || paths.length == 0) {
69 + return "#666";
70 + }
71 +
72 + var path = paths[currentPath];
73 + if (path) {
74 + for (var i = 0, n = path.length; i < n; i++) {
75 + var link = path[i];
76 + if ((link.src == d.source.id || link.dst == d.source.id) &&
77 + (link.dst == d.target.id || link.src == d.target.id)) {
78 + return "#f00";
79 + }
80 + }
81 + }
82 + return "#666";
83 + }
84 +
85 + function linkKey(link) {
86 + return link.source.id + "-" + link.target.id;
87 +
88 + };
89 +
90 + function toggleNode(node) {
91 + pathRequested = false;
92 + return selectedNode && selectedNode != node ? selectedNode : null;
93 +
94 + };
95 +
96 + function refreshPaths() {
97 + d3.selectAll("line").attr("stroke", linkColor);
98 + }
99 +
100 + function fetchPaths() {
101 + if (!pathRequested && sourceNode && targetNode) {
102 + pathRequested = true;
103 + d3.json("rs/topology/paths/" + sourceNode.id + "/" + targetNode.id, function(error, data) {
104 + currentPath = 0;
105 + paths = data.paths;
106 + refreshPaths();
107 + });
108 + }
109 + }
110 +
111 + function resetSelections() {
112 + selectedNode = null;
113 + sourceNode = null;
114 + targetNode = null;
115 + paths = [];
116 + currentPath = 0;
117 + refreshPaths();
118 + d3.selectAll(".nodeStrokeClass").attr("stroke", strokeColor);
119 + }
120 +
121 + function nextPath() {
122 + currentPath = paths && currentPath < paths.length - 1 ? currentPath + 1 : 0
123 + console.log("Showing path: " + currentPath);
124 + refreshPaths();
125 + }
126 +
127 + function dblclick(d) {
128 + d3.select(this).classed("fixed", d.fixed = false);
129 + }
130 +
131 + function dragstart(d) {
132 + d3.select(this).classed("fixed", d.fixed = true);
133 + }
134 +
135 +
136 + function topoGraph() {
137 + // Add and remove elements on the graph object
138 + this.addNode = function (vertex, stamp) {
139 + var node = topo.vertexes[vertex.name];
140 + if (node) {
141 + var oldState = node.online;
142 + node.online = vertex.online;
143 + node.stamp = stamp;
144 + if (oldState != node.online) {
145 + update();
146 + return true;
147 + }
148 + return false;
149 + }
150 + node = {"id": vertex.name, "group": vertex.group,
151 + "online": vertex.online, "stamp": stamp};
152 + nodes.push(node);
153 + topo.vertexes[vertex.name] = node;
154 + update();
155 + return true;
156 + };
157 +
158 + this.addLink = function (edge, stamp) {
159 + var key = edge.source + "-" + edge.target;
160 + var link = topo.edges[key];
161 + if (link) {
162 + var oldValue = link.value;
163 + link.value = edge.value;
164 + link.stamp = stamp;
165 + if (oldValue != link.value) {
166 + update();
167 + return true;
168 + }
169 + return false;
170 + }
171 + link = {"source": findNode(edge.source), "target": findNode(edge.target),
172 + "value": edge.value, "stamp": stamp};
173 + links.push(link);
174 + topo.edges[key] = link;
175 + update();
176 + return true;
177 + };
178 +
179 + this.prune = function (stamp) {
180 + var linksChanged = pruneArray(links, stamp, topo.edges, linkKey);
181 + var nodesChanged = pruneArray(nodes, stamp, topo.vertexes,
182 + function(node) { return node.id; });
183 + if (linksChanged || nodesChanged) {
184 + update();
185 + return true;
186 + }
187 + return false;
188 + };
189 +
190 + var pruneArray = function(array, stamp, map, key) {
191 + var changed = false;
192 + for (var i = 0; i < array.length; i++) {
193 + if (array[i].stamp < stamp) {
194 + changed = true;
195 + map[key(array[i])] = null;
196 + array.splice(i, 1);
197 + i--;
198 + }
199 + }
200 + return changed;
201 + };
202 +
203 + var findNode = function (id) {
204 + for (var i in nodes) {
205 + if (nodes[i]["id"] === id) return nodes[i];
206 + }
207 + };
208 +
209 + var force = d3.layout.force();
210 +
211 + var drag = force.drag()
212 + .on("dragstart", dragstart);
213 +
214 + var nodes = force.nodes(),
215 + links = force.links();
216 +
217 + var vis = d3.select("body")
218 + .append("svg:svg")
219 + .attr("width", w)
220 + .attr("height", h)
221 + .attr("id", "svg")
222 + .attr("pointer-events", "all")
223 + .attr("viewBox", "0 0 " + w + " " + h)
224 + .attr("perserveAspectRatio", "xMinYMid")
225 + .append('svg:g');
226 +
227 + d3.select("body")
228 + .on("keydown", function(d) {
229 + console.log(d3.event.keyCode);
230 + if (d3.event.keyCode == 27) {
231 + resetSelections();
232 + } else if (d3.event.keyCode == 83) {
233 + sourceNode = toggleNode(sourceNode);
234 + } else if (d3.event.keyCode == 68) {
235 + targetNode = toggleNode(targetNode);
236 + } else if (d3.event.keyCode == 65) {
237 + var aux = sourceNode;
238 + sourceNode = targetNode;
239 + targetNode = aux;
240 + } else if (d3.event.keyCode == 70) {
241 + nextPath();
242 + }
243 +
244 + d3.selectAll(".nodeStrokeClass").attr("fill", fillColor);
245 + fetchPaths();
246 + });
247 +
248 +
249 + var update = function () {
250 + var link = vis.selectAll("line")
251 + .data(links, linkKey);
252 +
253 + link.enter().append("line")
254 + .attr("id", linkKey)
255 + .attr("class", "link")
256 + .attr("stroke-width", function (d) { return d.value; })
257 + .attr("stroke", linkColor);
258 + link.append("title").text(function (d) { return d.id; });
259 + link.exit().remove();
260 +
261 + var node = vis.selectAll("g.node")
262 + .data(nodes, function (d) { return d.id; })
263 + .on("click", function(d) {
264 + selectedNode = d;
265 + d3.selectAll(".nodeStrokeClass").attr("stroke", strokeColor);
266 + });
267 +
268 + var nodeEnter = node.enter().append("g")
269 + .attr("class", "node")
270 + .on("dblclick", dblclick)
271 + .call(force.drag);
272 +
273 + nodeEnter.append("svg:circle")
274 + .attr("r", function(d) { return 28 / 2; })
275 + .attr("id", function (d) { return "n-" + d.id.replace(/[.:]/g, ""); })
276 + .attr("class", "nodeStrokeClass")
277 + .attr("fill", fillColor)
278 + .attr("stroke", strokeColor);
279 +
280 + nodeEnter.append("image")
281 + .attr("xlink:href", function(d) { return d.group == 2 ? "images/switch.png" : "images/server.png"; })
282 + .attr("x", -12)
283 + .attr("y", -12)
284 + .attr("width", 24)
285 + .attr("height", 24);
286 +
287 + nodeEnter.append("svg:text")
288 + .attr("class", "textClass")
289 + .attr("x", 20)
290 + .attr("y", ".31em")
291 + .text(function (d) { return d.id; });
292 +
293 + node.exit().remove();
294 +
295 + d3.selectAll("nodeStrokeClass").attr("stroke", strokeColor);
296 +
297 + force.on("tick", function () {
298 + node.attr("transform", function (d) {
299 + return "translate(" + d.x + "," + d.y + ")";
300 + });
301 +
302 + link.attr("x1", function (d) { return d.source.x; })
303 + .attr("y1", function (d) { return d.source.y; })
304 + .attr("x2", function (d) { return d.target.x; })
305 + .attr("y2", function (d) { return d.target.y; });
306 + });
307 +
308 + // Restart the force layout.
309 + force
310 + .gravity(0.3)
311 + .charge(-15000)
312 + .friction(0.1)
313 + .linkDistance(function(d) { return d.value * 30; })
314 + .linkStrength(function(d) { return d.value * 0.6; })
315 + .size([w, h])
316 + .start();
317 + };
318 +
319 + // Make it all go
320 + update();
321 + }
322 +
323 + function drawGraph() {
324 + graph = new topoGraph("#svgdiv");
325 + bringNodesToFront();
326 + }
327 +
328 + function bringNodesToFront() {
329 + $(".nodeStrokeClass").each(function( index ) {
330 + var gnode = this.parentNode;
331 + gnode.parentNode.appendChild(gnode);
332 + });
333 + }
334 +
335 + function addNodes() {
336 + d3.select("svg")
337 + .remove();
338 + drawGraph();
339 + }
340 +
341 + function fetchData() {
342 + var stamp = new Date().getTime();
343 + d3.json("rs/topology/graph", function(error, data) {
344 + var changed = false;
345 + data.vertexes.forEach(function(vertex) { changed = graph.addNode(vertex, stamp) || changed; });
346 + data.edges.forEach(function(edge) { changed = graph.addLink(edge, stamp) || changed; });
347 +
348 + changed = graph.prune(stamp) || changed;
349 + if (changed) {
350 + bringNodesToFront();
351 + // Update node and links styles
352 + d3.selectAll(".nodeStrokeClass").attr("fill", fillColor);
353 + d3.selectAll(".line").attr("stroke-width", function (d) { return d.value; })
354 + }
355 +
356 + setTimeout(fetchData, 1000);
357 + });
358 + };
359 +
360 + drawGraph();
361 + setTimeout(fetchData, 500);
362 +
363 + </script>
364 +</body>
365 +</html>
...\ No newline at end of file ...\ No newline at end of file
1 +package org.onlab.onos.net.flow;
2 +
3 +/**
4 + * Factory class to create various traffic selection criteria.
5 + */
6 +public final class Criteria {
7 +
8 + // Ban construction
9 + private Criteria() {
10 + }
11 +
12 + /**
13 + * Creates a match on ETH_SRC field using the specified value. This value
14 + * may be a wildcard mask.
15 + *
16 + * @param macValue MAC address value or wildcard mask
17 + * @return match criterion
18 + */
19 + public static Criterion matchEthSrc(MACValue macValue) {
20 + return null;
21 + }
22 +
23 + // Dummy to illustrate the concept for now; delete ASAP
24 + private static class MACValue { }
25 +}
1 +package org.onlab.onos.net.flow;
2 +
3 +/**
4 + * Representation of a single header field selection.
5 + */
6 +public interface Criterion {
7 +
8 + /**
9 + * Types of fields to which the selection criterion may apply.
10 + */
11 + // From page 42 of OpenFlow 1.3.x spec
12 + public enum Type {
13 + /** Switch input port. */
14 + IN_PORT,
15 + /** Switch physical input port. */
16 + IN_PHY_PORT,
17 + /** Metadata passed between tables. */
18 + METADATA,
19 + /** Ethernet destination address. */
20 + ETH_DST,
21 + /** Ethernet source address. */
22 + ETH_SRC,
23 + /** Ethernet frame type. */
24 + ETH_TYPE,
25 + /** VLAN id. */
26 + VLAN_VID,
27 + /** VLAN priority. */
28 + VLAN_PCP,
29 + /** IP DSCP (6 bits in ToS field). */
30 + IP_DSCP,
31 + /** IP ECN (2 bits in ToS field). */
32 + IP_ECN,
33 + /** IP protocol. */
34 + IP_PROTO,
35 + /** IPv4 source address. */
36 + IPV4_SRC,
37 + /** IPv4 destination address. */
38 + IPV4_DST,
39 + /** TCP source port. */
40 + TCP_SRC,
41 + /** TCP destination port. */
42 + TCP_DST,
43 + /** UDP source port. */
44 + UDP_SRC,
45 + /** UDP destination port. */
46 + UDP_DST,
47 + /** SCTP source port. */
48 + SCTP_SRC,
49 + /** SCTP destination port. */
50 + SCTP_DST,
51 + /** ICMP type. */
52 + ICMPV4_TYPE,
53 + /** ICMP code. */
54 + ICMPV4_CODE,
55 + /** ARP opcode. */
56 + ARP_OP,
57 + /** ARP source IPv4 address. */
58 + ARP_SPA,
59 + /** ARP target IPv4 address. */
60 + ARP_TPA,
61 + /** ARP source hardware address. */
62 + ARP_SHA,
63 + /** ARP target hardware address. */
64 + ARP_THA,
65 + /** IPv6 source address. */
66 + IPV6_SRC,
67 + /** IPv6 destination address. */
68 + IPV6_DST,
69 + /** IPv6 Flow Label. */
70 + IPV6_FLABEL,
71 + /** ICMPv6 type. */
72 + ICMPV6_TYPE,
73 + /** ICMPv6 code. */
74 + ICMPV6_CODE,
75 + /** Target address for ND. */
76 + IPV6_ND_TARGET,
77 + /** Source link-layer for ND. */
78 + IPV6_ND_SLL,
79 + /** Target link-layer for ND. */
80 + IPV6_ND_TLL,
81 + /** MPLS label. */
82 + MPLS_LABEL,
83 + /** MPLS TC. */
84 + MPLS_TC,
85 + /** MPLS BoS bit. */
86 + MPLS_BOS,
87 + /** PBB I-SID. */
88 + PBB_ISID,
89 + /** Logical Port Metadata. */
90 + TUNNEL_ID,
91 + /** IPv6 Extension Header pseudo-field. */
92 + IPV6_EXTHDR
93 + }
94 +
95 + // TODO: Create factory class 'Criteria' that will have various factory
96 + // to create specific criterions.
97 +
98 +}
1 +package org.onlab.onos.net.flow;
2 +
3 +/**
4 + * Represents a flow rule and its associated accumulated metrics.
5 + */
6 +public interface FlowEntry extends FlowRule {
7 +
8 + /**
9 + * Returns the number of milliseconds this flow rule has been applied.
10 + *
11 + * @return number of millis
12 + */
13 + long lifeMillis();
14 +
15 + /**
16 + * Returns the number of milliseconds this flow rule has been idle.
17 + *
18 + * @return number of millis
19 + */
20 + long idleMillis();
21 +
22 + /**
23 + * Returns the number of packets this flow rule has matched.
24 + *
25 + * @return number of packets
26 + */
27 + long packets();
28 +
29 + /**
30 + * Returns the number of bytes this flow rule has matched.
31 + *
32 + * @return number of bytes
33 + */
34 + long bytes();
35 +
36 +}
1 +package org.onlab.onos.net.flow;
2 +
3 +import org.onlab.onos.net.DeviceId;
4 +
5 +import java.util.List;
6 +
7 +/**
8 + * Represents a generalized match &amp; action pair to be applied to
9 + * an infrastucture device.
10 + */
11 +public interface FlowRule {
12 +
13 + /**
14 + * Returns the flow rule priority given in natural order; higher numbers
15 + * mean higher priorities.
16 + *
17 + * @return flow rule priority
18 + */
19 + int priority();
20 +
21 + /**
22 + * Returns the identity of the device where this rule applies.
23 + *
24 + * @return device identifier
25 + */
26 + DeviceId deviceId();
27 +
28 + /**
29 + * Returns the traffic selector that identifies what traffic this
30 + * rule should apply to.
31 + *
32 + * @return traffic selector
33 + */
34 + TrafficSelector selector();
35 +
36 + /**
37 + * Returns the traffic treatment that applies to selected traffic.
38 + *
39 + * @return traffic treatment
40 + */
41 + List<Treatment> treatments();
42 +
43 +}
1 +package org.onlab.onos.net.flow;
2 +
3 +import org.onlab.onos.event.AbstractEvent;
4 +
5 +/**
6 + * Describes flow rule event.
7 + */
8 +public class FlowRuleEvent extends AbstractEvent<FlowRuleEvent.Type, FlowRule> {
9 +
10 + /**
11 + * Type of flow rule events.
12 + */
13 + public enum Type {
14 + /**
15 + * Signifies that a new flow rule has been detected.
16 + */
17 + RULE_ADDED,
18 +
19 + /**
20 + * Signifies that a flow rule has been removed.
21 + */
22 + RULE_REMOVED,
23 + }
24 +
25 + /**
26 + * Creates an event of a given type and for the specified flow rule and the
27 + * current time.
28 + *
29 + * @param type flow rule event type
30 + * @param flowRule event flow rule subject
31 + */
32 + public FlowRuleEvent(Type type, FlowRule flowRule) {
33 + super(type, flowRule);
34 + }
35 +
36 + /**
37 + * Creates an event of a given type and for the specified flow rule and time.
38 + *
39 + * @param type flow rule event type
40 + * @param flowRule event flow rule subject
41 + * @param time occurrence time
42 + */
43 + public FlowRuleEvent(Type type, FlowRule flowRule, long time) {
44 + super(type, flowRule, time);
45 + }
46 +
47 +}
1 package org.onlab.onos.net.flow; 1 package org.onlab.onos.net.flow;
2 2
3 -import org.onlab.onos.net.Description; 3 +import org.onlab.onos.event.EventListener;
4 4
5 /** 5 /**
6 - * Information about a flow rule. 6 + * Entity capable of receiving flow rule related events.
7 */ 7 */
8 -public interface FlowDescription extends Description { 8 +public interface FlowRuleListener extends EventListener<FlowRuleEvent> {
9 -
10 - // Match and action, possibly reason for flow rule, unless reason is too OF-specific.
11 -
12 } 9 }
......
1 package org.onlab.onos.net.flow; 1 package org.onlab.onos.net.flow;
2 2
3 +import org.onlab.onos.net.DeviceId;
3 import org.onlab.onos.net.provider.Provider; 4 import org.onlab.onos.net.provider.Provider;
4 5
5 /** 6 /**
...@@ -7,6 +8,23 @@ import org.onlab.onos.net.provider.Provider; ...@@ -7,6 +8,23 @@ import org.onlab.onos.net.provider.Provider;
7 */ 8 */
8 public interface FlowRuleProvider extends Provider { 9 public interface FlowRuleProvider extends Provider {
9 10
10 - // TODO: pushFlowRule 11 + /**
12 + * Instructs the provider to apply the specified flow rules to their
13 + * respective devices.
14 + * @param flowRules one or more flow rules
15 + * throws SomeKindOfException that indicates which ones were applied and
16 + * which ones failed
17 + */
18 + void applyFlowRule(FlowRule... flowRules);
19 +
20 +
21 + /**
22 + * Returns the collection of flow entries currently applied on the given
23 + * device.
24 + *
25 + * @param deviceId device identifier
26 + * @return collection of flow entries
27 + */
28 + Iterable<FlowEntry> getFlowMetrics(DeviceId deviceId);
11 29
12 } 30 }
......
...@@ -3,33 +3,23 @@ package org.onlab.onos.net.flow; ...@@ -3,33 +3,23 @@ package org.onlab.onos.net.flow;
3 import org.onlab.onos.net.provider.ProviderService; 3 import org.onlab.onos.net.provider.ProviderService;
4 4
5 /** 5 /**
6 - * Service through which flowrule providers can inject flowrule information into 6 + * Service through which flow rule providers can inject information into
7 * the core. 7 * the core.
8 */ 8 */
9 public interface FlowRuleProviderService extends ProviderService<FlowRuleProvider> { 9 public interface FlowRuleProviderService extends ProviderService<FlowRuleProvider> {
10 10
11 /** 11 /**
12 - * Signals that a flow that was previously installed has been removed. 12 + * Signals that a flow rule that was previously installed has been removed.
13 * 13 *
14 - * @param flowDescription information about the removed flow 14 + * @param flowRule information about the removed flow
15 */ 15 */
16 - void flowRemoved(FlowDescription flowDescription); 16 + void flowRemoved(FlowRule flowRule);
17 17
18 /** 18 /**
19 - * Signals that a flowrule is missing for some network traffic. 19 + * Signals that a flow rule is missing for some network traffic.
20 * 20 *
21 - * @param flowDescription information about traffic in need of flow rule(s) 21 + * @param flowRule information about traffic in need of flow rule(s)
22 */ 22 */
23 - void flowMissing(FlowDescription flowDescription); 23 + void flowMissing(FlowRule flowRule);
24 -
25 - /**
26 - * Signals that a flowrule has been added.
27 - *
28 - * TODO think about if this really makes sense, e.g. if stats collection or
29 - * something can leverage it.
30 - *
31 - * @param flowDescription the rule that was added
32 - */
33 - void flowAdded(FlowDescription flowDescription);
34 24
35 } 25 }
......
1 +package org.onlab.onos.net.flow;
2 +
3 +import org.onlab.onos.net.DeviceId;
4 +
5 +/**
6 + * Service for injecting flow rules into the environment and for obtaining
7 + * information about flow rules already in the environment.
8 + */
9 +public interface FlowRuleService {
10 +
11 + /**
12 + * Returns the collection of flow entries applied on the specified device.
13 + *
14 + * @param deviceId device identifier
15 + * @return collection of flow rules
16 + */
17 + Iterable<FlowEntry> getFlowEntries(DeviceId deviceId);
18 +
19 + /**
20 + * Applies the specified flow rules onto their respective devices.
21 + *
22 + * @param flowRules one or more flow rules
23 + * throws SomeKindOfException that indicates which ones were applied and
24 + * which ones failed
25 + */
26 + void applyFlowRules(FlowRule... flowRules);
27 +
28 + /**
29 + * Adds the specified flow rule listener.
30 + *
31 + * @param listener flow rule listener
32 + */
33 + void addListener(FlowRuleListener listener);
34 +
35 + /**
36 + * Removes the specified flow rule listener.
37 + *
38 + * @param listener flow rule listener
39 + */
40 + void removeListener(FlowRuleListener listener);
41 +
42 +}
1 +package org.onlab.onos.net.flow;
2 +
3 +/**
4 + * Abstraction of a single traffic treatment step.
5 + */
6 +public interface Instruction {
7 +
8 + /**
9 + * Represents the type of traffic treatment.
10 + */
11 + public enum Type {
12 + /**
13 + * Signifies that the traffic should be dropped.
14 + */
15 + DROP,
16 +
17 + /**
18 + * Signifies that the traffic should be output to a port.
19 + */
20 + OUTPUT,
21 +
22 + /**
23 + * Signifies that.... (do we need this?)
24 + */
25 + GROUP,
26 +
27 + /**
28 + * Signifies that the traffic should be modified in some way.
29 + */
30 + MODIFICATION
31 + }
32 +
33 + // TODO: Create factory class 'Instructions' that will have various factory
34 + // to create specific instructions.
35 +
36 +}
1 +package org.onlab.onos.net.flow;
2 +
3 +import org.onlab.onos.net.PortNumber;
4 +
5 +/**
6 + * Factory class for creating various traffic treatment instructions.
7 + */
8 +public final class Instructions {
9 +
10 + // Ban construction
11 + private Instructions() {
12 + }
13 +
14 + /**
15 + * Creates an output instruction using the specified port number. This can
16 + * include logical ports such as CONTROLLER, FLOOD, etc.
17 + *
18 + * @param number port number
19 + * @return output instruction
20 + */
21 + public static Instruction createOutput(PortNumber number) {
22 + return null;
23 + }
24 +
25 + // TODO: add create methods
26 +
27 +}
1 +package org.onlab.onos.net.flow;
2 +
3 +import java.util.List;
4 +
5 +/**
6 + * Abstraction of a slice of network traffic.
7 + */
8 +public interface TrafficSelector {
9 +
10 + /**
11 + * Returns selection criteria as an ordered list.
12 + *
13 + * @return list of criteria
14 + */
15 + List<Criterion> criteria();
16 +
17 + /**
18 + * Builder of traffic selector entities.
19 + */
20 + public interface Builder {
21 +
22 + /**
23 + * Adds a traffic selection criterion. If a same type criterion has
24 + * already been added, it will be replaced by this one.
25 + *
26 + * @param criterion new criterion
27 + */
28 + void add(Criterion criterion);
29 +
30 + /**
31 + * Builds an immutable traffic selector.
32 + *
33 + * @return traffic selector
34 + */
35 + TrafficSelector build();
36 + }
37 +
38 +}
1 +package org.onlab.onos.net.flow;
2 +
3 +import java.util.List;
4 +
5 +/**
6 + * Abstraction of network traffic treatment.
7 + */
8 +public interface TrafficTreatment {
9 +
10 + /**
11 + * Returns list of instructions on how to treat traffic.
12 + *
13 + * @return list of treatment instructions
14 + */
15 + List<Instruction> instructions();
16 +
17 + /**
18 + * Builder of traffic treatment entities.
19 + */
20 + public interface Builder {
21 +
22 + /**
23 + * Adds a traffic treatment instruction. If a same type instruction has
24 + * already been added, it will be replaced by this one.
25 + *
26 + * @param instruction new instruction
27 + */
28 + void add(Instruction instruction);
29 +
30 + /**
31 + * Builds an immutable traffic treatment descriptor.
32 + *
33 + * @return traffic treatment
34 + */
35 + TrafficTreatment build();
36 + }
37 +
38 +}
1 -package org.onlab.onos.net.packet; 1 +package org.onlab.onos.net.flow;
2 2
3 import org.onlab.onos.net.PortNumber; 3 import org.onlab.onos.net.PortNumber;
4 4
......
1 package org.onlab.onos.net.packet; 1 package org.onlab.onos.net.packet;
2 2
3 import com.google.common.base.MoreObjects; 3 import com.google.common.base.MoreObjects;
4 -import com.google.common.collect.ImmutableList;
5 import org.onlab.onos.net.DeviceId; 4 import org.onlab.onos.net.DeviceId;
5 +import org.onlab.onos.net.flow.TrafficTreatment;
6 6
7 import java.nio.ByteBuffer; 7 import java.nio.ByteBuffer;
8 -import java.util.List;
9 8
10 /** 9 /**
11 * Default implementation of an immutable outbound packet. 10 * Default implementation of an immutable outbound packet.
12 */ 11 */
13 public class DefaultOutboundPacket implements OutboundPacket { 12 public class DefaultOutboundPacket implements OutboundPacket {
14 private final DeviceId sendThrough; 13 private final DeviceId sendThrough;
15 - private final List<Treatment> treatments; 14 + private final TrafficTreatment treatment;
16 private final ByteBuffer data; 15 private final ByteBuffer data;
17 16
18 /** 17 /**
19 * Creates an immutable outbound packet. 18 * Creates an immutable outbound packet.
20 * 19 *
21 * @param sendThrough identifier through which to send the packet 20 * @param sendThrough identifier through which to send the packet
22 - * @param treatments list of packet treatments 21 + * @param treatment list of packet treatments
23 * @param data raw packet data 22 * @param data raw packet data
24 */ 23 */
25 public DefaultOutboundPacket(DeviceId sendThrough, 24 public DefaultOutboundPacket(DeviceId sendThrough,
26 - List<Treatment> treatments, ByteBuffer data) { 25 + TrafficTreatment treatment, ByteBuffer data) {
27 this.sendThrough = sendThrough; 26 this.sendThrough = sendThrough;
28 - this.treatments = ImmutableList.copyOf(treatments); 27 + this.treatment = treatment;
29 this.data = data; 28 this.data = data;
30 } 29 }
31 30
...@@ -35,8 +34,8 @@ public class DefaultOutboundPacket implements OutboundPacket { ...@@ -35,8 +34,8 @@ public class DefaultOutboundPacket implements OutboundPacket {
35 } 34 }
36 35
37 @Override 36 @Override
38 - public List<Treatment> treatments() { 37 + public TrafficTreatment treatment() {
39 - return treatments; 38 + return treatment;
40 } 39 }
41 40
42 @Override 41 @Override
...@@ -49,7 +48,7 @@ public class DefaultOutboundPacket implements OutboundPacket { ...@@ -49,7 +48,7 @@ public class DefaultOutboundPacket implements OutboundPacket {
49 public String toString() { 48 public String toString() {
50 return MoreObjects.toStringHelper(this) 49 return MoreObjects.toStringHelper(this)
51 .add("sendThrough", sendThrough) 50 .add("sendThrough", sendThrough)
52 - .add("treatments", treatments) 51 + .add("treatment", treatment)
53 .toString(); 52 .toString();
54 } 53 }
55 } 54 }
......
1 +package org.onlab.onos.net.packet;
2 +
3 +
4 +public abstract class DefaultPacketContext implements PacketContext {
5 +
6 + private final long time;
7 + private final InboundPacket inPkt;
8 + private final OutboundPacket outPkt;
9 + private boolean block = false;
10 +
11 + protected DefaultPacketContext(long time, InboundPacket inPkt,
12 + OutboundPacket outPkt, boolean block) {
13 + super();
14 + this.time = time;
15 + this.inPkt = inPkt;
16 + this.outPkt = outPkt;
17 + this.block = block;
18 + }
19 +
20 + @Override
21 + public long time() {
22 + return time;
23 + }
24 +
25 + @Override
26 + public InboundPacket inPacket() {
27 + return inPkt;
28 + }
29 +
30 + @Override
31 + public OutboundPacket outPacket() {
32 + return outPkt;
33 + }
34 +
35 + @Override
36 + public abstract void send();
37 +
38 + @Override
39 + public void block() {
40 + this.block = true;
41 + }
42 +
43 + @Override
44 + public boolean isHandled() {
45 + return this.block;
46 + }
47 +
48 +}
1 package org.onlab.onos.net.packet; 1 package org.onlab.onos.net.packet;
2 2
3 import org.onlab.onos.net.DeviceId; 3 import org.onlab.onos.net.DeviceId;
4 +import org.onlab.onos.net.flow.TrafficTreatment;
4 5
5 import java.nio.ByteBuffer; 6 import java.nio.ByteBuffer;
6 -import java.util.List;
7 7
8 /** 8 /**
9 * Represents an outbound data packet that is to be emitted to network via 9 * Represents an outbound data packet that is to be emitted to network via
...@@ -20,14 +20,14 @@ public interface OutboundPacket { ...@@ -20,14 +20,14 @@ public interface OutboundPacket {
20 DeviceId sendThrough(); 20 DeviceId sendThrough();
21 21
22 /** 22 /**
23 - * Returns list of treatments for the outbound packet. 23 + * Returns how the outbound packet should be treated.
24 * 24 *
25 * @return output treatment 25 * @return output treatment
26 */ 26 */
27 - List<Treatment> treatments(); 27 + TrafficTreatment treatment();
28 28
29 /** 29 /**
30 - * Returns the raw data to be sent. 30 + * Returns immutable view of the raw data to be sent.
31 * 31 *
32 * @return data to emit 32 * @return data to emit
33 */ 33 */
......
1 package org.onlab.onos.net.packet; 1 package org.onlab.onos.net.packet;
2 2
3 +import org.onlab.onos.net.flow.TrafficTreatment;
4 +
3 /** 5 /**
4 * Represents context for processing an inbound packet, and (optionally) 6 * Represents context for processing an inbound packet, and (optionally)
5 * emitting a corresponding outbound packet. 7 * emitting a corresponding outbound packet.
...@@ -28,11 +30,11 @@ public interface PacketContext { ...@@ -28,11 +30,11 @@ public interface PacketContext {
28 OutboundPacket outPacket(); 30 OutboundPacket outPacket();
29 31
30 /** 32 /**
31 - * Appends a new treatment to be applied to the outbound packet. 33 + * Returns a builder for constructing traffic treatment.
32 * 34 *
33 - * @param treatment output treatment 35 + * @return traffic treatment builder
34 */ 36 */
35 - void appendTreatment(Treatment treatment); 37 + TrafficTreatment.Builder treatmentBuilder();
36 38
37 /** 39 /**
38 * Triggers the outbound packet to be sent. 40 * Triggers the outbound packet to be sent.
......
...@@ -62,7 +62,6 @@ ...@@ -62,7 +62,6 @@
62 <feature>onos-core</feature> 62 <feature>onos-core</feature>
63 <bundle>mvn:io.netty/netty/3.9.2.Final</bundle> 63 <bundle>mvn:io.netty/netty/3.9.2.Final</bundle>
64 64
65 - <!--bundle>mvn:org.projectfloodlight/openflowj/0.3.8-SNAPSHOT</bundle-->
66 <bundle>mvn:org.onlab.onos/onos-of-api/1.0.0-SNAPSHOT</bundle> 65 <bundle>mvn:org.onlab.onos/onos-of-api/1.0.0-SNAPSHOT</bundle>
67 <bundle>mvn:org.onlab.onos/onos-of-ctl/1.0.0-SNAPSHOT</bundle> 66 <bundle>mvn:org.onlab.onos/onos-of-ctl/1.0.0-SNAPSHOT</bundle>
68 67
...@@ -71,4 +70,10 @@ ...@@ -71,4 +70,10 @@
71 <bundle>mvn:org.onlab.onos/onos-of-provider-host/1.0.0-SNAPSHOT</bundle> 70 <bundle>mvn:org.onlab.onos/onos-of-provider-host/1.0.0-SNAPSHOT</bundle>
72 </feature> 71 </feature>
73 72
73 + <feature name="onos-app-tvue" version="1.0.0"
74 + description="ONOS sample topology viewer application">
75 + <feature>onos-core</feature>
76 + <bundle>mvn:org.onlab.onos/onos-app-tvue/1.0.0-SNAPSHOT</bundle>
77 + </feature>
78 +
74 </features> 79 </features>
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
19 <module>cli</module> 19 <module>cli</module>
20 <module>providers</module> 20 <module>providers</module>
21 <module>of</module> 21 <module>of</module>
22 + <module>apps</module>
22 <module>features</module> 23 <module>features</module>
23 </modules> 24 </modules>
24 25
...@@ -355,6 +356,12 @@ ...@@ -355,6 +356,12 @@
355 org.onlab.onos.gui:org.onlab.onos.rest:org.onlab.onos.cli:org.onlab.onos.gui.*:org.onlab.onos.rest.*:org.onlab.onos.cli.* 356 org.onlab.onos.gui:org.onlab.onos.rest:org.onlab.onos.cli:org.onlab.onos.gui.*:org.onlab.onos.rest.*:org.onlab.onos.cli.*
356 </packages> 357 </packages>
357 </group> 358 </group>
359 + <group>
360 + <title>Sample Applications</title>
361 + <packages>
362 + org.onlab.onos.tvue
363 + </packages>
364 + </group>
358 </groups> 365 </groups>
359 </configuration> 366 </configuration>
360 </plugin> 367 </plugin>
......