Ayaka Koshibe

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

Conflicts:
	core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
	core/store/hz/cluster/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java

Change-Id: Ia1274657b27e01366a4a87196a13068d7104ee80
Showing 265 changed files with 2539 additions and 631 deletions
...@@ -24,10 +24,20 @@ ...@@ -24,10 +24,20 @@
24 </dependency> 24 </dependency>
25 <dependency> 25 <dependency>
26 <groupId>org.onlab.onos</groupId> 26 <groupId>org.onlab.onos</groupId>
27 + <artifactId>onlab-osgi</artifactId>
28 + <version>${project.version}</version>
29 + </dependency>
30 + <dependency>
31 + <groupId>org.onlab.onos</groupId>
27 <artifactId>onlab-nio</artifactId> 32 <artifactId>onlab-nio</artifactId>
28 <version>${project.version}</version> 33 <version>${project.version}</version>
29 </dependency> 34 </dependency>
30 <dependency> 35 <dependency>
36 + <groupId>org.onlab.onos</groupId>
37 + <artifactId>onlab-netty</artifactId>
38 + <version>${project.version}</version>
39 + </dependency>
40 + <dependency>
31 <groupId>org.apache.karaf.shell</groupId> 41 <groupId>org.apache.karaf.shell</groupId>
32 <artifactId>org.apache.karaf.shell.console</artifactId> 42 <artifactId>org.apache.karaf.shell.console</artifactId>
33 </dependency> 43 </dependency>
......
...@@ -11,6 +11,9 @@ import org.onlab.onos.cluster.ClusterService; ...@@ -11,6 +11,9 @@ import org.onlab.onos.cluster.ClusterService;
11 import org.onlab.onos.net.device.DeviceEvent; 11 import org.onlab.onos.net.device.DeviceEvent;
12 import org.onlab.onos.net.device.DeviceListener; 12 import org.onlab.onos.net.device.DeviceListener;
13 import org.onlab.onos.net.device.DeviceService; 13 import org.onlab.onos.net.device.DeviceService;
14 +import org.onlab.onos.net.intent.IntentEvent;
15 +import org.onlab.onos.net.intent.IntentListener;
16 +import org.onlab.onos.net.intent.IntentService;
14 import org.slf4j.Logger; 17 import org.slf4j.Logger;
15 18
16 import static org.slf4j.LoggerFactory.getLogger; 19 import static org.slf4j.LoggerFactory.getLogger;
...@@ -29,13 +32,18 @@ public class FooComponent { ...@@ -29,13 +32,18 @@ public class FooComponent {
29 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 32 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
30 protected DeviceService deviceService; 33 protected DeviceService deviceService;
31 34
35 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
36 + protected IntentService intentService;
37 +
32 private final ClusterEventListener clusterListener = new InnerClusterListener(); 38 private final ClusterEventListener clusterListener = new InnerClusterListener();
33 private final DeviceListener deviceListener = new InnerDeviceListener(); 39 private final DeviceListener deviceListener = new InnerDeviceListener();
40 + private final IntentListener intentListener = new InnerIntentListener();
34 41
35 @Activate 42 @Activate
36 public void activate() { 43 public void activate() {
37 clusterService.addListener(clusterListener); 44 clusterService.addListener(clusterListener);
38 deviceService.addListener(deviceListener); 45 deviceService.addListener(deviceListener);
46 + intentService.addListener(intentListener);
39 log.info("Started"); 47 log.info("Started");
40 } 48 }
41 49
...@@ -43,6 +51,7 @@ public class FooComponent { ...@@ -43,6 +51,7 @@ public class FooComponent {
43 public void deactivate() { 51 public void deactivate() {
44 clusterService.removeListener(clusterListener); 52 clusterService.removeListener(clusterListener);
45 deviceService.removeListener(deviceListener); 53 deviceService.removeListener(deviceListener);
54 + intentService.removeListener(intentListener);
46 log.info("Stopped"); 55 log.info("Stopped");
47 } 56 }
48 57
...@@ -59,6 +68,23 @@ public class FooComponent { ...@@ -59,6 +68,23 @@ public class FooComponent {
59 log.info("YEEEEHAAAAW! {}", event); 68 log.info("YEEEEHAAAAW! {}", event);
60 } 69 }
61 } 70 }
71 +
72 + private class InnerIntentListener implements IntentListener {
73 + @Override
74 + public void event(IntentEvent event) {
75 + String message;
76 + if (event.type() == IntentEvent.Type.SUBMITTED) {
77 + message = "WOW! It looks like someone has some intentions: {}";
78 + } else if (event.type() == IntentEvent.Type.INSTALLED) {
79 + message = "AWESOME! So far things are going great: {}";
80 + } else if (event.type() == IntentEvent.Type.WITHDRAWN) {
81 + message = "HMMM! Ambitions are fading apparently: {}";
82 + } else {
83 + message = "CRAP!!! Things are not turning out as intended: {}";
84 + }
85 + log.info(message, event.subject());
86 + }
87 + }
62 } 88 }
63 89
64 90
......
1 +package org.onlab.onos.foo;
2 +
3 +import java.io.IOException;
4 +
5 +import org.onlab.netty.Message;
6 +import org.onlab.netty.MessageHandler;
7 +import org.slf4j.Logger;
8 +import org.slf4j.LoggerFactory;
9 +
10 +
11 +/**
12 + * Message handler that echos the message back to the sender.
13 + */
14 +public class NettyEchoHandler implements MessageHandler {
15 +
16 + private final Logger log = LoggerFactory.getLogger(getClass());
17 +
18 + @Override
19 + public void handle(Message message) throws IOException {
20 + //log.info("Received message. Echoing it back to the sender.");
21 + message.respond(message.payload());
22 + }
23 +}
1 +package org.onlab.onos.foo;
2 +
3 +import org.onlab.netty.Message;
4 +import org.onlab.netty.MessageHandler;
5 +import org.slf4j.Logger;
6 +import org.slf4j.LoggerFactory;
7 +
8 +/**
9 + * A MessageHandler that simply logs the information.
10 + */
11 +public class NettyLoggingHandler implements MessageHandler {
12 +
13 + private final Logger log = LoggerFactory.getLogger(getClass());
14 +
15 + @Override
16 + public void handle(Message message) {
17 + //log.info("Received message. Payload has {} bytes", message.payload().length);
18 + }
19 +}
1 +package org.onlab.onos.foo;
2 +
3 +import java.io.IOException;
4 +import java.util.concurrent.ExecutionException;
5 +import java.util.concurrent.TimeoutException;
6 +
7 +import org.onlab.metrics.MetricsComponent;
8 +import org.onlab.metrics.MetricsFeature;
9 +import org.onlab.metrics.MetricsManager;
10 +import org.onlab.netty.Endpoint;
11 +import org.onlab.netty.NettyMessagingService;
12 +import org.onlab.netty.Response;
13 +import org.slf4j.Logger;
14 +import org.slf4j.LoggerFactory;
15 +
16 +import com.codahale.metrics.Timer;
17 +
18 +// FIXME: Should be move out to test or app
19 +public final class SimpleNettyClient {
20 +
21 +private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class);
22 +
23 + private SimpleNettyClient() {
24 + }
25 +
26 + public static void main(String[] args)
27 + throws IOException, InterruptedException, ExecutionException,
28 + TimeoutException {
29 + try {
30 + startStandalone(args);
31 + } catch (Exception e) {
32 + e.printStackTrace();
33 + }
34 +
35 + System.exit(0);
36 + }
37 + public static void startStandalone(String... args) throws Exception {
38 + String host = args.length > 0 ? args[0] : "localhost";
39 + int port = args.length > 1 ? Integer.parseInt(args[1]) : 8081;
40 + int warmup = args.length > 2 ? Integer.parseInt(args[2]) : 1000;
41 + int iterations = args.length > 3 ? Integer.parseInt(args[3]) : 50 * 100000;
42 + NettyMessagingService messaging = new TestNettyMessagingService(9081);
43 + MetricsManager metrics = new MetricsManager();
44 + messaging.activate();
45 + metrics.activate();
46 + MetricsFeature feature = new MetricsFeature("latency");
47 + MetricsComponent component = metrics.registerComponent("NettyMessaging");
48 + log.info("warmup....");
49 +
50 + for (int i = 0; i < warmup; i++) {
51 + messaging.sendAsync(new Endpoint(host, port), "simple", "Hello World".getBytes());
52 + Response response = messaging
53 + .sendAndReceive(new Endpoint(host, port), "echo",
54 + "Hello World".getBytes());
55 + }
56 +
57 + log.info("measuring async sender");
58 + Timer sendAsyncTimer = metrics.createTimer(component, feature, "AsyncSender");
59 +
60 + for (int i = 0; i < iterations; i++) {
61 + Timer.Context context = sendAsyncTimer.time();
62 + messaging.sendAsync(new Endpoint(host, port), "simple", "Hello World".getBytes());
63 + context.stop();
64 + }
65 +
66 + Timer sendAndReceiveTimer = metrics.createTimer(component, feature, "SendAndReceive");
67 + for (int i = 0; i < iterations; i++) {
68 + Timer.Context context = sendAndReceiveTimer.time();
69 + Response response = messaging
70 + .sendAndReceive(new Endpoint(host, port), "echo",
71 + "Hello World".getBytes());
72 + // System.out.println("Got back:" + new String(response.get(2, TimeUnit.SECONDS)));
73 + context.stop();
74 + }
75 + }
76 +
77 + public static class TestNettyMessagingService extends NettyMessagingService {
78 + public TestNettyMessagingService(int port) throws Exception {
79 + super(port);
80 + }
81 + }
82 +}
1 +package org.onlab.onos.foo;
2 +
3 +import static org.onlab.onos.foo.SimpleNettyClient.startStandalone;
4 +
5 +import org.apache.karaf.shell.commands.Argument;
6 +import org.apache.karaf.shell.commands.Command;
7 +import org.onlab.onos.cli.AbstractShellCommand;
8 +
9 +/**
10 + * Test Netty client performance.
11 + */
12 +@Command(scope = "onos", name = "simple-netty-client",
13 + description = "Starts the simple Netty client")
14 +public class SimpleNettyClientCommand extends AbstractShellCommand {
15 +
16 + //FIXME: replace these arguments with proper ones needed for the test.
17 + @Argument(index = 0, name = "hostname", description = "Server Hostname",
18 + required = false, multiValued = false)
19 + String host = "localhost";
20 +
21 + @Argument(index = 3, name = "port", description = "Port",
22 + required = false, multiValued = false)
23 + String port = "8081";
24 +
25 + @Argument(index = 1, name = "warmupCount", description = "Warm-up count",
26 + required = false, multiValued = false)
27 + String warmup = "1000";
28 +
29 + @Argument(index = 2, name = "messageCount", description = "Message count",
30 + required = false, multiValued = false)
31 + String messageCount = "100000";
32 +
33 + @Override
34 + protected void execute() {
35 + try {
36 + startStandalone(new String[]{host, port, warmup, messageCount});
37 + } catch (Exception e) {
38 + error("Unable to start client %s", e);
39 + }
40 + }
41 +
42 +}
1 +package org.onlab.onos.foo;
2 +
3 +import org.onlab.netty.NettyMessagingService;
4 +import org.slf4j.Logger;
5 +import org.slf4j.LoggerFactory;
6 +
7 +/**
8 + * Test to measure Messaging performance.
9 + */
10 + public final class SimpleNettyServer {
11 + private static Logger log = LoggerFactory.getLogger(SimpleNettyServer.class);
12 +
13 + private SimpleNettyServer() {}
14 +
15 + public static void main(String... args) throws Exception {
16 + startStandalone(args);
17 + System.exit(0);
18 + }
19 +
20 + public static void startStandalone(String[] args) throws Exception {
21 + NettyMessagingService server = new NettyMessagingService(8081);
22 + server.activate();
23 + server.registerHandler("simple", new NettyLoggingHandler());
24 + server.registerHandler("echo", new NettyEchoHandler());
25 + }
26 + }
27 +
1 +package org.onlab.onos.foo;
2 +
3 +import static org.onlab.onos.foo.SimpleNettyServer.startStandalone;
4 +
5 +import org.apache.karaf.shell.commands.Argument;
6 +import org.apache.karaf.shell.commands.Command;
7 +import org.onlab.onos.cli.AbstractShellCommand;
8 +
9 +/**
10 + * Starts the Simple Netty server.
11 + */
12 +@Command(scope = "onos", name = "simple-netty-server",
13 + description = "Starts the simple netty server")
14 +public class SimpleNettyServerCommand extends AbstractShellCommand {
15 +
16 + //FIXME: Replace these with parameters for
17 + @Argument(index = 0, name = "serverIp", description = "Server IP address",
18 + required = false, multiValued = false)
19 + String serverIp = "127.0.0.1";
20 +
21 + @Argument(index = 1, name = "workers", description = "IO workers",
22 + required = false, multiValued = false)
23 + String workers = "6";
24 +
25 + @Argument(index = 2, name = "messageLength", description = "Message length (bytes)",
26 + required = false, multiValued = false)
27 + String messageLength = "128";
28 +
29 + @Override
30 + protected void execute() {
31 + try {
32 + startStandalone(new String[]{serverIp, workers, messageLength});
33 + } catch (Exception e) {
34 + error("Unable to start server %s", e);
35 + }
36 + }
37 +
38 +}
...@@ -7,6 +7,12 @@ ...@@ -7,6 +7,12 @@
7 <command> 7 <command>
8 <action class="org.onlab.onos.foo.TestIOServerCommand"/> 8 <action class="org.onlab.onos.foo.TestIOServerCommand"/>
9 </command> 9 </command>
10 + <command>
11 + <action class="org.onlab.onos.foo.SimpleNettyServerCommand"/>
12 + </command>
13 + <command>
14 + <action class="org.onlab.onos.foo.SimpleNettyClientCommand"/>
15 + </command>
10 </command-bundle> 16 </command-bundle>
11 17
12 </blueprint> 18 </blueprint>
......
...@@ -26,9 +26,7 @@ import org.onlab.onos.net.packet.InboundPacket; ...@@ -26,9 +26,7 @@ import org.onlab.onos.net.packet.InboundPacket;
26 import org.onlab.onos.net.packet.PacketContext; 26 import org.onlab.onos.net.packet.PacketContext;
27 import org.onlab.onos.net.packet.PacketProcessor; 27 import org.onlab.onos.net.packet.PacketProcessor;
28 import org.onlab.onos.net.packet.PacketService; 28 import org.onlab.onos.net.packet.PacketService;
29 -import org.onlab.onos.net.proxyarp.ProxyArpService;
30 import org.onlab.onos.net.topology.TopologyService; 29 import org.onlab.onos.net.topology.TopologyService;
31 -import org.onlab.packet.ARP;
32 import org.onlab.packet.Ethernet; 30 import org.onlab.packet.Ethernet;
33 import org.slf4j.Logger; 31 import org.slf4j.Logger;
34 32
...@@ -39,6 +37,7 @@ import org.slf4j.Logger; ...@@ -39,6 +37,7 @@ import org.slf4j.Logger;
39 public class ReactiveForwarding { 37 public class ReactiveForwarding {
40 38
41 private static final int TIMEOUT = 10; 39 private static final int TIMEOUT = 10;
40 + private static final int PRIORITY = 10;
42 41
43 private final Logger log = getLogger(getClass()); 42 private final Logger log = getLogger(getClass());
44 43
...@@ -54,9 +53,6 @@ public class ReactiveForwarding { ...@@ -54,9 +53,6 @@ public class ReactiveForwarding {
54 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 53 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
55 protected FlowRuleService flowRuleService; 54 protected FlowRuleService flowRuleService;
56 55
57 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 - protected ProxyArpService proxyArpService;
59 -
60 private ReactivePacketProcessor processor = new ReactivePacketProcessor(); 56 private ReactivePacketProcessor processor = new ReactivePacketProcessor();
61 57
62 private ApplicationId appId; 58 private ApplicationId appId;
...@@ -64,7 +60,7 @@ public class ReactiveForwarding { ...@@ -64,7 +60,7 @@ public class ReactiveForwarding {
64 @Activate 60 @Activate
65 public void activate() { 61 public void activate() {
66 appId = ApplicationId.getAppId(); 62 appId = ApplicationId.getAppId();
67 - packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 1); 63 + packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
68 log.info("Started with Application ID {}", appId.id()); 64 log.info("Started with Application ID {}", appId.id());
69 } 65 }
70 66
...@@ -92,16 +88,6 @@ public class ReactiveForwarding { ...@@ -92,16 +88,6 @@ public class ReactiveForwarding {
92 88
93 InboundPacket pkt = context.inPacket(); 89 InboundPacket pkt = context.inPacket();
94 Ethernet ethPkt = pkt.parsed(); 90 Ethernet ethPkt = pkt.parsed();
95 - if (ethPkt.getEtherType() == Ethernet.TYPE_ARP) {
96 - ARP arp = (ARP) ethPkt.getPayload();
97 - if (arp.getOpCode() == ARP.OP_REPLY) {
98 - proxyArpService.forward(ethPkt);
99 - } else if (arp.getOpCode() == ARP.OP_REQUEST) {
100 - proxyArpService.reply(ethPkt);
101 - }
102 - context.block();
103 - return;
104 - }
105 91
106 HostId id = HostId.hostId(ethPkt.getDestinationMAC()); 92 HostId id = HostId.hostId(ethPkt.getDestinationMAC());
107 93
...@@ -180,24 +166,24 @@ public class ReactiveForwarding { ...@@ -180,24 +166,24 @@ public class ReactiveForwarding {
180 // We don't yet support bufferids in the flowservice so packet out first. 166 // We don't yet support bufferids in the flowservice so packet out first.
181 packetOut(context, portNumber); 167 packetOut(context, portNumber);
182 168
183 - if (context.inPacket().parsed().getEtherType() == Ethernet.TYPE_IPV4) {
184 169
185 - // Install the flow rule to handle this type of message from now on.
186 - Ethernet inPkt = context.inPacket().parsed();
187 - TrafficSelector.Builder builder = new DefaultTrafficSelector.Builder();
188 - builder.matchEthType(inPkt.getEtherType())
189 - .matchEthSrc(inPkt.getSourceMAC())
190 - .matchEthDst(inPkt.getDestinationMAC())
191 - .matchInport(context.inPacket().receivedFrom().port());
192 170
193 - TrafficTreatment.Builder treat = new DefaultTrafficTreatment.Builder(); 171 + // Install the flow rule to handle this type of message from now on.
194 - treat.setOutput(portNumber); 172 + Ethernet inPkt = context.inPacket().parsed();
173 + TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
174 + builder.matchEthType(inPkt.getEtherType())
175 + .matchEthSrc(inPkt.getSourceMAC())
176 + .matchEthDst(inPkt.getDestinationMAC())
177 + .matchInport(context.inPacket().receivedFrom().port());
195 178
196 - FlowRule f = new DefaultFlowRule(context.inPacket().receivedFrom().deviceId(), 179 + TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder();
197 - builder.build(), treat.build(), 0, appId, TIMEOUT); 180 + treat.setOutput(portNumber);
181 +
182 + FlowRule f = new DefaultFlowRule(context.inPacket().receivedFrom().deviceId(),
183 + builder.build(), treat.build(), PRIORITY, appId, TIMEOUT);
184 +
185 + flowRuleService.applyFlowRules(f);
198 186
199 - flowRuleService.applyFlowRules(f);
200 - }
201 } 187 }
202 188
203 } 189 }
......
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-ifwd</artifactId>
15 + <packaging>bundle</packaging>
16 +
17 + <description>ONOS simple reactive forwarding app that uses intent service</description>
18 +
19 +</project>
1 +package org.onlab.onos.ifwd;
2 +
3 +import static org.slf4j.LoggerFactory.getLogger;
4 +
5 +import org.apache.felix.scr.annotations.Activate;
6 +import org.apache.felix.scr.annotations.Component;
7 +import org.apache.felix.scr.annotations.Deactivate;
8 +import org.apache.felix.scr.annotations.Reference;
9 +import org.apache.felix.scr.annotations.ReferenceCardinality;
10 +import org.onlab.onos.net.Host;
11 +import org.onlab.onos.net.HostId;
12 +import org.onlab.onos.net.PortNumber;
13 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
14 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
15 +import org.onlab.onos.net.flow.TrafficSelector;
16 +import org.onlab.onos.net.flow.TrafficTreatment;
17 +import org.onlab.onos.net.host.HostService;
18 +import org.onlab.onos.net.intent.HostToHostIntent;
19 +import org.onlab.onos.net.intent.IntentId;
20 +import org.onlab.onos.net.intent.IntentService;
21 +import org.onlab.onos.net.packet.DefaultOutboundPacket;
22 +import org.onlab.onos.net.packet.InboundPacket;
23 +import org.onlab.onos.net.packet.OutboundPacket;
24 +import org.onlab.onos.net.packet.PacketContext;
25 +import org.onlab.onos.net.packet.PacketProcessor;
26 +import org.onlab.onos.net.packet.PacketService;
27 +import org.onlab.onos.net.topology.TopologyService;
28 +import org.onlab.packet.Ethernet;
29 +import org.slf4j.Logger;
30 +
31 +/**
32 + * WORK-IN-PROGRESS: Sample reactive forwarding application using intent framework.
33 + */
34 +@Component(immediate = true)
35 +public class IntentReactiveForwarding {
36 +
37 + private final Logger log = getLogger(getClass());
38 +
39 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
40 + protected TopologyService topologyService;
41 +
42 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
43 + protected PacketService packetService;
44 +
45 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
46 + protected IntentService intentService;
47 +
48 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
49 + protected HostService hostService;
50 +
51 + private ReactivePacketProcessor processor = new ReactivePacketProcessor();
52 +
53 + private static long intentId = 0x123000;
54 +
55 + @Activate
56 + public void activate() {
57 + packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
58 + log.info("Started");
59 + }
60 +
61 + @Deactivate
62 + public void deactivate() {
63 + packetService.removeProcessor(processor);
64 + processor = null;
65 + log.info("Stopped");
66 + }
67 +
68 + /**
69 + * Packet processor responsible for forwarding packets along their paths.
70 + */
71 + private class ReactivePacketProcessor implements PacketProcessor {
72 +
73 + @Override
74 + public void process(PacketContext context) {
75 + // Stop processing if the packet has been handled, since we
76 + // can't do any more to it.
77 + if (context.isHandled()) {
78 + return;
79 + }
80 +
81 + InboundPacket pkt = context.inPacket();
82 + Ethernet ethPkt = pkt.parsed();
83 +
84 + HostId srcId = HostId.hostId(ethPkt.getSourceMAC());
85 + HostId dstId = HostId.hostId(ethPkt.getDestinationMAC());
86 +
87 + // Do we know who this is for? If not, flood and bail.
88 + Host dst = hostService.getHost(dstId);
89 + if (dst == null) {
90 + flood(context);
91 + return;
92 + }
93 +
94 + // Otherwise forward and be done with it.
95 + setUpConnectivity(context, srcId, dstId);
96 + forwardPacketToDst(context, dst);
97 + }
98 + }
99 +
100 + // Floods the specified packet if permissible.
101 + private void flood(PacketContext context) {
102 + if (topologyService.isBroadcastPoint(topologyService.currentTopology(),
103 + context.inPacket().receivedFrom())) {
104 + packetOut(context, PortNumber.FLOOD);
105 + } else {
106 + context.block();
107 + }
108 + }
109 +
110 + // Sends a packet out the specified port.
111 + private void packetOut(PacketContext context, PortNumber portNumber) {
112 + context.treatmentBuilder().setOutput(portNumber);
113 + context.send();
114 + }
115 +
116 + private void forwardPacketToDst(PacketContext context, Host dst) {
117 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(dst.location().port()).build();
118 + OutboundPacket packet = new DefaultOutboundPacket(dst.location().deviceId(),
119 + treatment, context.inPacket().unparsed());
120 + packetService.emit(packet);
121 + log.info("sending packet: {}", packet);
122 + }
123 +
124 + // Install a rule forwarding the packet to the specified port.
125 + private void setUpConnectivity(PacketContext context, HostId srcId, HostId dstId) {
126 + TrafficSelector selector = DefaultTrafficSelector.builder().build();
127 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
128 +
129 + HostToHostIntent intent =
130 + new HostToHostIntent(new IntentId(intentId++), srcId, dstId,
131 + selector, treatment);
132 +
133 + intentService.submit(intent);
134 + }
135 +
136 +}
1 +/**
2 + * Trivial application that provides simple form of reactive forwarding
3 + * using the intent service.
4 + */
5 +package org.onlab.onos.ifwd;
...@@ -19,8 +19,10 @@ ...@@ -19,8 +19,10 @@
19 <modules> 19 <modules>
20 <module>tvue</module> 20 <module>tvue</module>
21 <module>fwd</module> 21 <module>fwd</module>
22 + <module>ifwd</module>
22 <module>foo</module> 23 <module>foo</module>
23 <module>mobility</module> 24 <module>mobility</module>
25 + <module>proxyarp</module>
24 <module>config</module> 26 <module>config</module>
25 </modules> 27 </modules>
26 28
......
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-proxyarp</artifactId>
15 + <packaging>bundle</packaging>
16 +
17 + <description>ONOS simple proxy arp module</description>
18 +
19 +</project>
1 +package org.onlab.onos.proxyarp;
2 +
3 +import static org.slf4j.LoggerFactory.getLogger;
4 +
5 +import org.apache.felix.scr.annotations.Activate;
6 +import org.apache.felix.scr.annotations.Component;
7 +import org.apache.felix.scr.annotations.Deactivate;
8 +import org.apache.felix.scr.annotations.Reference;
9 +import org.apache.felix.scr.annotations.ReferenceCardinality;
10 +import org.onlab.onos.ApplicationId;
11 +import org.onlab.onos.net.packet.PacketContext;
12 +import org.onlab.onos.net.packet.PacketProcessor;
13 +import org.onlab.onos.net.packet.PacketService;
14 +import org.onlab.onos.net.proxyarp.ProxyArpService;
15 +import org.slf4j.Logger;
16 +
17 +/**
18 + * Sample reactive proxy arp application.
19 + */
20 +@Component(immediate = true)
21 +public class ProxyArp {
22 +
23 +
24 + private final Logger log = getLogger(getClass());
25 +
26 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
27 + protected PacketService packetService;
28 +
29 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
30 + protected ProxyArpService proxyArpService;
31 +
32 + private ProxyArpProcessor processor = new ProxyArpProcessor();
33 +
34 + private ApplicationId appId;
35 +
36 + @Activate
37 + public void activate() {
38 + appId = ApplicationId.getAppId();
39 + packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 1);
40 + log.info("Started with Application ID {}", appId.id());
41 + }
42 +
43 + @Deactivate
44 + public void deactivate() {
45 + packetService.removeProcessor(processor);
46 + processor = null;
47 + log.info("Stopped");
48 + }
49 +
50 +
51 + /**
52 + * Packet processor responsible for forwarding packets along their paths.
53 + */
54 + private class ProxyArpProcessor implements PacketProcessor {
55 +
56 + @Override
57 + public void process(PacketContext context) {
58 + // Stop processing if the packet has been handled, since we
59 + // can't do any more to it.
60 + if (context.isHandled()) {
61 + return;
62 + }
63 +
64 + //handle the arp packet.
65 + proxyArpService.handleArp(context);
66 + }
67 + }
68 +}
69 +
70 +
1 +/**
2 + * Proxy Arp application that handles arp resolution for you.
3 + */
4 +package org.onlab.onos.proxyarp;
1 +package org.onlab.onos.cli;
2 +
3 +import org.apache.karaf.shell.commands.Command;
4 +import org.onlab.onos.CoreService;
5 +import org.onlab.onos.cluster.ClusterService;
6 +import org.onlab.onos.net.device.DeviceService;
7 +import org.onlab.onos.net.flow.FlowRuleService;
8 +import org.onlab.onos.net.host.HostService;
9 +import org.onlab.onos.net.intent.IntentService;
10 +import org.onlab.onos.net.link.LinkService;
11 +import org.onlab.onos.net.topology.Topology;
12 +import org.onlab.onos.net.topology.TopologyService;
13 +
14 +/**
15 + * Provides summary of ONOS model.
16 + */
17 +@Command(scope = "onos", name = "summary",
18 + description = "Provides summary of ONOS model")
19 +public class SummaryCommand extends AbstractShellCommand {
20 +
21 + @Override
22 + protected void execute() {
23 + TopologyService topologyService = get(TopologyService.class);
24 + Topology topology = topologyService.currentTopology();
25 + print("version=%s, nodes=%d, devices=%d, links=%d, hosts=%d, clusters=%s, paths=%d, flows=%d, intents=%d",
26 + get(CoreService.class).version().toString(),
27 + get(ClusterService.class).getNodes().size(),
28 + get(DeviceService.class).getDeviceCount(),
29 + get(LinkService.class).getLinkCount(),
30 + get(HostService.class).getHostCount(),
31 + topologyService.getClusters(topology).size(),
32 + topology.pathCount(),
33 + get(FlowRuleService.class).getFlowRuleCount(),
34 + get(IntentService.class).getIntentCount());
35 + }
36 +
37 +}
1 +package org.onlab.onos.cli.net;
2 +
3 +import org.apache.karaf.shell.commands.Argument;
4 +import org.apache.karaf.shell.commands.Command;
5 +import org.onlab.onos.cli.AbstractShellCommand;
6 +import org.onlab.onos.net.HostId;
7 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
8 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
9 +import org.onlab.onos.net.flow.TrafficSelector;
10 +import org.onlab.onos.net.flow.TrafficTreatment;
11 +import org.onlab.onos.net.intent.HostToHostIntent;
12 +import org.onlab.onos.net.intent.IntentId;
13 +import org.onlab.onos.net.intent.IntentService;
14 +
15 +/**
16 + * Installs host-to-host connectivity intent.
17 + */
18 +@Command(scope = "onos", name = "add-host-intent",
19 + description = "Installs host-to-host connectivity intent")
20 +public class AddHostToHostIntentCommand extends AbstractShellCommand {
21 +
22 + @Argument(index = 0, name = "one", description = "One host ID",
23 + required = true, multiValued = false)
24 + String one = null;
25 +
26 + @Argument(index = 1, name = "two", description = "Another host ID",
27 + required = true, multiValued = false)
28 + String two = null;
29 +
30 + private static long id = 0x7870001;
31 +
32 + @Override
33 + protected void execute() {
34 + IntentService service = get(IntentService.class);
35 +
36 + HostId oneId = HostId.hostId(one);
37 + HostId twoId = HostId.hostId(two);
38 +
39 + TrafficSelector selector = DefaultTrafficSelector.builder().build();
40 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
41 +
42 + HostToHostIntent intent =
43 + new HostToHostIntent(new IntentId(id++), oneId, twoId,
44 + selector, treatment);
45 + service.submit(intent);
46 + }
47 +
48 +}
1 +package org.onlab.onos.cli.net;
2 +
3 +import org.apache.karaf.shell.commands.Argument;
4 +import org.apache.karaf.shell.commands.Command;
5 +import org.onlab.onos.cli.AbstractShellCommand;
6 +import org.onlab.onos.net.ConnectPoint;
7 +import org.onlab.onos.net.DeviceId;
8 +import org.onlab.onos.net.PortNumber;
9 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
10 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
11 +import org.onlab.onos.net.flow.TrafficSelector;
12 +import org.onlab.onos.net.flow.TrafficTreatment;
13 +import org.onlab.onos.net.intent.Intent;
14 +import org.onlab.onos.net.intent.IntentId;
15 +import org.onlab.onos.net.intent.IntentService;
16 +import org.onlab.onos.net.intent.PointToPointIntent;
17 +import org.onlab.packet.Ethernet;
18 +
19 +/**
20 + * Installs point-to-point connectivity intents.
21 + */
22 +@Command(scope = "onos", name = "add-point-intent",
23 + description = "Installs point-to-point connectivity intent")
24 +public class AddPointToPointIntentCommand extends AbstractShellCommand {
25 +
26 + @Argument(index = 0, name = "ingressDevice",
27 + description = "Ingress Device/Port Description",
28 + required = true, multiValued = false)
29 + String ingressDeviceString = null;
30 +
31 + @Argument(index = 1, name = "egressDevice",
32 + description = "Egress Device/Port Description",
33 + required = true, multiValued = false)
34 + String egressDeviceString = null;
35 +
36 + private static long id = 0x7470001;
37 +
38 + @Override
39 + protected void execute() {
40 + IntentService service = get(IntentService.class);
41 +
42 + DeviceId ingressDeviceId = DeviceId.deviceId(getDeviceId(ingressDeviceString));
43 + PortNumber ingressPortNumber =
44 + PortNumber.portNumber(getPortNumber(ingressDeviceString));
45 + ConnectPoint ingress = new ConnectPoint(ingressDeviceId, ingressPortNumber);
46 +
47 + DeviceId egressDeviceId = DeviceId.deviceId(getDeviceId(egressDeviceString));
48 + PortNumber egressPortNumber =
49 + PortNumber.portNumber(getPortNumber(egressDeviceString));
50 + ConnectPoint egress = new ConnectPoint(egressDeviceId, egressPortNumber);
51 +
52 + TrafficSelector selector = DefaultTrafficSelector.builder()
53 + .matchEthType(Ethernet.TYPE_IPV4)
54 + .build();
55 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
56 +
57 + Intent intent =
58 + new PointToPointIntent(new IntentId(id++),
59 + selector,
60 + treatment,
61 + ingress,
62 + egress);
63 + service.submit(intent);
64 + }
65 +
66 + /**
67 + * Extracts the port number portion of the ConnectPoint.
68 + *
69 + * @param deviceString string representing the device/port
70 + * @return port number as a string, empty string if the port is not found
71 + */
72 + private String getPortNumber(String deviceString) {
73 + int slash = deviceString.indexOf('/');
74 + if (slash <= 0) {
75 + return "";
76 + }
77 + return deviceString.substring(slash + 1, deviceString.length());
78 + }
79 +
80 + /**
81 + * Extracts the device ID portion of the ConnectPoint.
82 + *
83 + * @param deviceString string representing the device/port
84 + * @return device ID string
85 + */
86 + private String getDeviceId(String deviceString) {
87 + int slash = deviceString.indexOf('/');
88 + if (slash <= 0) {
89 + return "";
90 + }
91 + return deviceString.substring(0, slash);
92 + }
93 +}
1 +package org.onlab.onos.cli.net;
2 +
3 +import java.util.List;
4 +import java.util.SortedSet;
5 +
6 +import org.apache.karaf.shell.console.Completer;
7 +import org.apache.karaf.shell.console.completer.StringsCompleter;
8 +import org.onlab.onos.cli.AbstractShellCommand;
9 +import org.onlab.onos.net.Device;
10 +import org.onlab.onos.net.Port;
11 +import org.onlab.onos.net.device.DeviceService;
12 +
13 +/**
14 + * ConnectPoint completer.
15 + */
16 +public class ConnectPointCompleter implements Completer {
17 + @Override
18 + public int complete(String buffer, int cursor, List<String> candidates) {
19 + // Delegate string completer
20 + StringsCompleter delegate = new StringsCompleter();
21 +
22 + // Fetch our service and feed it's offerings to the string completer
23 + DeviceService service = AbstractShellCommand.get(DeviceService.class);
24 +
25 + // Generate the device ID/port number identifiers
26 + for (Device device : service.getDevices()) {
27 + SortedSet<String> strings = delegate.getStrings();
28 +
29 + for (Port port : service.getPorts(device.id())) {
30 + strings.add(device.id().toString() + "/" + port.number());
31 + }
32 + }
33 +
34 + // Now let the completer do the work for figuring out what to offer.
35 + return delegate.complete(buffer, cursor, candidates);
36 + }
37 +
38 +}
...@@ -35,7 +35,7 @@ public class DevicesListCommand extends AbstractShellCommand { ...@@ -35,7 +35,7 @@ public class DevicesListCommand extends AbstractShellCommand {
35 * @param service device service 35 * @param service device service
36 * @return sorted device list 36 * @return sorted device list
37 */ 37 */
38 - protected List<Device> getSortedDevices(DeviceService service) { 38 + protected static List<Device> getSortedDevices(DeviceService service) {
39 List<Device> devices = newArrayList(service.getDevices()); 39 List<Device> devices = newArrayList(service.getDevices());
40 Collections.sort(devices, Comparators.ELEMENT_COMPARATOR); 40 Collections.sort(devices, Comparators.ELEMENT_COMPARATOR);
41 return devices; 41 return devices;
......
...@@ -5,7 +5,7 @@ import java.util.SortedSet; ...@@ -5,7 +5,7 @@ import java.util.SortedSet;
5 5
6 import org.apache.karaf.shell.console.Completer; 6 import org.apache.karaf.shell.console.Completer;
7 import org.apache.karaf.shell.console.completer.StringsCompleter; 7 import org.apache.karaf.shell.console.completer.StringsCompleter;
8 -import org.onlab.onos.net.flow.FlowRule.FlowRuleState; 8 +import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
9 9
10 /** 10 /**
11 * Device ID completer. 11 * Device ID completer.
...@@ -16,7 +16,7 @@ public class FlowRuleStatusCompleter implements Completer { ...@@ -16,7 +16,7 @@ public class FlowRuleStatusCompleter implements Completer {
16 // Delegate string completer 16 // Delegate string completer
17 StringsCompleter delegate = new StringsCompleter(); 17 StringsCompleter delegate = new StringsCompleter();
18 18
19 - FlowRuleState[] states = FlowRuleState.values(); 19 + FlowEntryState[] states = FlowEntryState.values();
20 SortedSet<String> strings = delegate.getStrings(); 20 SortedSet<String> strings = delegate.getStrings();
21 for (int i = 0; i < states.length; i++) { 21 for (int i = 0; i < states.length; i++) {
22 strings.add(states[i].toString().toLowerCase()); 22 strings.add(states[i].toString().toLowerCase());
......
1 package org.onlab.onos.cli.net; 1 package org.onlab.onos.cli.net;
2 2
3 import static com.google.common.collect.Lists.newArrayList; 3 import static com.google.common.collect.Lists.newArrayList;
4 +import static org.onlab.onos.cli.net.DevicesListCommand.getSortedDevices;
4 5
5 import java.util.Collections; 6 import java.util.Collections;
6 import java.util.List; 7 import java.util.List;
...@@ -13,8 +14,8 @@ import org.onlab.onos.cli.Comparators; ...@@ -13,8 +14,8 @@ import org.onlab.onos.cli.Comparators;
13 import org.onlab.onos.net.Device; 14 import org.onlab.onos.net.Device;
14 import org.onlab.onos.net.DeviceId; 15 import org.onlab.onos.net.DeviceId;
15 import org.onlab.onos.net.device.DeviceService; 16 import org.onlab.onos.net.device.DeviceService;
16 -import org.onlab.onos.net.flow.FlowRule; 17 +import org.onlab.onos.net.flow.FlowEntry;
17 -import org.onlab.onos.net.flow.FlowRule.FlowRuleState; 18 +import org.onlab.onos.net.flow.FlowEntry.FlowEntryState;
18 import org.onlab.onos.net.flow.FlowRuleService; 19 import org.onlab.onos.net.flow.FlowRuleService;
19 20
20 import com.google.common.collect.Maps; 21 import com.google.common.collect.Maps;
...@@ -45,8 +46,8 @@ public class FlowsListCommand extends AbstractShellCommand { ...@@ -45,8 +46,8 @@ public class FlowsListCommand extends AbstractShellCommand {
45 protected void execute() { 46 protected void execute() {
46 DeviceService deviceService = get(DeviceService.class); 47 DeviceService deviceService = get(DeviceService.class);
47 FlowRuleService service = get(FlowRuleService.class); 48 FlowRuleService service = get(FlowRuleService.class);
48 - Map<Device, List<FlowRule>> flows = getSortedFlows(deviceService, service); 49 + Map<Device, List<FlowEntry>> flows = getSortedFlows(deviceService, service);
49 - for (Device d : flows.keySet()) { 50 + for (Device d : getSortedDevices(deviceService)) {
50 printFlows(d, flows.get(d)); 51 printFlows(d, flows.get(d));
51 } 52 }
52 } 53 }
...@@ -57,21 +58,22 @@ public class FlowsListCommand extends AbstractShellCommand { ...@@ -57,21 +58,22 @@ public class FlowsListCommand extends AbstractShellCommand {
57 * @param service device service 58 * @param service device service
58 * @return sorted device list 59 * @return sorted device list
59 */ 60 */
60 - protected Map<Device, List<FlowRule>> getSortedFlows(DeviceService deviceService, FlowRuleService service) { 61 + protected Map<Device, List<FlowEntry>> getSortedFlows(DeviceService deviceService,
61 - Map<Device, List<FlowRule>> flows = Maps.newHashMap(); 62 + FlowRuleService service) {
62 - List<FlowRule> rules; 63 + Map<Device, List<FlowEntry>> flows = Maps.newHashMap();
63 - FlowRuleState s = null; 64 + List<FlowEntry> rules;
65 + FlowEntryState s = null;
64 if (state != null && !state.equals("any")) { 66 if (state != null && !state.equals("any")) {
65 - s = FlowRuleState.valueOf(state.toUpperCase()); 67 + s = FlowEntryState.valueOf(state.toUpperCase());
66 } 68 }
67 - Iterable<Device> devices = uri == null ? deviceService.getDevices() : 69 + Iterable<Device> devices = uri == null ? deviceService.getDevices() :
68 Collections.singletonList(deviceService.getDevice(DeviceId.deviceId(uri))); 70 Collections.singletonList(deviceService.getDevice(DeviceId.deviceId(uri)));
69 for (Device d : devices) { 71 for (Device d : devices) {
70 if (s == null) { 72 if (s == null) {
71 rules = newArrayList(service.getFlowEntries(d.id())); 73 rules = newArrayList(service.getFlowEntries(d.id()));
72 } else { 74 } else {
73 rules = newArrayList(); 75 rules = newArrayList();
74 - for (FlowRule f : service.getFlowEntries(d.id())) { 76 + for (FlowEntry f : service.getFlowEntries(d.id())) {
75 if (f.state().equals(s)) { 77 if (f.state().equals(s)) {
76 rules.add(f); 78 rules.add(f);
77 } 79 }
...@@ -88,19 +90,17 @@ public class FlowsListCommand extends AbstractShellCommand { ...@@ -88,19 +90,17 @@ public class FlowsListCommand extends AbstractShellCommand {
88 * @param d the device 90 * @param d the device
89 * @param flows the set of flows for that device. 91 * @param flows the set of flows for that device.
90 */ 92 */
91 - protected void printFlows(Device d, List<FlowRule> flows) { 93 + protected void printFlows(Device d, List<FlowEntry> flows) {
92 - print("Device: " + d.id()); 94 + boolean empty = flows == null || flows.isEmpty();
93 - if (flows == null | flows.isEmpty()) { 95 + print("deviceId=%s, flowRuleCount=%d", d.id(), empty ? 0 : flows.size());
94 - print(" %s", "No flows."); 96 + if (!empty) {
95 - return; 97 + for (FlowEntry f : flows) {
96 - } 98 + print(FMT, Long.toHexString(f.id().value()), f.state(), f.bytes(),
97 - for (FlowRule f : flows) { 99 + f.packets(), f.life(), f.priority());
98 - print(FMT, Long.toHexString(f.id().value()), f.state(), f.bytes(), 100 + print(SFMT, f.selector().criteria());
99 - f.packets(), f.lifeMillis(), f.priority()); 101 + print(TFMT, f.treatment().instructions());
100 - print(SFMT, f.selector().criteria()); 102 + }
101 - print(TFMT, f.treatment().instructions());
102 } 103 }
103 -
104 } 104 }
105 105
106 } 106 }
......
1 +package org.onlab.onos.cli.net;
2 +
3 +import org.apache.karaf.shell.console.Completer;
4 +import org.apache.karaf.shell.console.completer.StringsCompleter;
5 +import org.onlab.onos.cli.AbstractShellCommand;
6 +import org.onlab.onos.net.intent.Intent;
7 +import org.onlab.onos.net.intent.IntentService;
8 +
9 +import java.util.Iterator;
10 +import java.util.List;
11 +import java.util.SortedSet;
12 +
13 +/**
14 + * Intent ID completer.
15 + */
16 +public class IntentIdCompleter implements Completer {
17 + @Override
18 + public int complete(String buffer, int cursor, List<String> candidates) {
19 + // Delegate string completer
20 + StringsCompleter delegate = new StringsCompleter();
21 +
22 + // Fetch our service and feed it's offerings to the string completer
23 + IntentService service = AbstractShellCommand.get(IntentService.class);
24 + Iterator<Intent> it = service.getIntents().iterator();
25 + SortedSet<String> strings = delegate.getStrings();
26 + while (it.hasNext()) {
27 + strings.add(it.next().id().toString());
28 + }
29 +
30 + // Now let the completer do the work for figuring out what to offer.
31 + return delegate.complete(buffer, cursor, candidates);
32 + }
33 +
34 +}
1 +package org.onlab.onos.cli.net;
2 +
3 +import org.apache.karaf.shell.commands.Argument;
4 +import org.apache.karaf.shell.commands.Command;
5 +import org.onlab.onos.cli.AbstractShellCommand;
6 +import org.onlab.onos.net.intent.Intent;
7 +import org.onlab.onos.net.intent.IntentId;
8 +import org.onlab.onos.net.intent.IntentService;
9 +
10 +/**
11 + * Removes host-to-host connectivity intent.
12 + */
13 +@Command(scope = "onos", name = "remove-intent",
14 + description = "Removes the specified intent")
15 +public class IntentRemoveCommand extends AbstractShellCommand {
16 +
17 + @Argument(index = 0, name = "id", description = "Intent ID",
18 + required = true, multiValued = false)
19 + String id = null;
20 +
21 + @Override
22 + protected void execute() {
23 + IntentService service = get(IntentService.class);
24 +
25 + int radix = id.startsWith("0x") ? 16 : 10;
26 + if (radix == 16) {
27 + id = id.replaceFirst("0x", "");
28 + }
29 + IntentId intentId = new IntentId(Long.parseLong(id, radix));
30 +
31 +
32 + Intent intent = service.getIntent(intentId);
33 + if (intent != null) {
34 + service.withdraw(intent);
35 + }
36 + }
37 +}
1 +package org.onlab.onos.cli.net;
2 +
3 +import org.apache.karaf.shell.commands.Command;
4 +import org.onlab.onos.cli.AbstractShellCommand;
5 +import org.onlab.onos.net.intent.Intent;
6 +import org.onlab.onos.net.intent.IntentService;
7 +import org.onlab.onos.net.intent.IntentState;
8 +
9 +/**
10 + * Lists the inventory of intents and their states.
11 + */
12 +@Command(scope = "onos", name = "intents",
13 + description = "Lists the inventory of intents and their states")
14 +public class IntentsListCommand extends AbstractShellCommand {
15 +
16 + @Override
17 + protected void execute() {
18 + IntentService service = get(IntentService.class);
19 + for (Intent intent : service.getIntents()) {
20 + IntentState state = service.getIntentState(intent.id());
21 + print("%s %s %s", intent.id(), state, intent);
22 + }
23 + }
24 +
25 +}
1 package org.onlab.onos.cli.net; 1 package org.onlab.onos.cli.net;
2 2
3 +import org.apache.karaf.shell.commands.Argument;
3 import org.apache.karaf.shell.commands.Command; 4 import org.apache.karaf.shell.commands.Command;
4 import org.onlab.onos.net.Device; 5 import org.onlab.onos.net.Device;
5 import org.onlab.onos.net.Host; 6 import org.onlab.onos.net.Host;
...@@ -7,28 +8,51 @@ import org.onlab.onos.net.device.DeviceAdminService; ...@@ -7,28 +8,51 @@ import org.onlab.onos.net.device.DeviceAdminService;
7 import org.onlab.onos.net.device.DeviceService; 8 import org.onlab.onos.net.device.DeviceService;
8 import org.onlab.onos.net.host.HostAdminService; 9 import org.onlab.onos.net.host.HostAdminService;
9 import org.onlab.onos.net.host.HostService; 10 import org.onlab.onos.net.host.HostService;
11 +import org.onlab.onos.net.intent.Intent;
12 +import org.onlab.onos.net.intent.IntentService;
13 +import org.onlab.onos.net.intent.IntentState;
10 14
11 /** 15 /**
12 - * Wipes-out the entire network information base, i.e. devices, links, hosts. 16 + * Wipes-out the entire network information base, i.e. devices, links, hosts, intents.
13 */ 17 */
14 @Command(scope = "onos", name = "wipe-out", 18 @Command(scope = "onos", name = "wipe-out",
15 description = "Wipes-out the entire network information base, i.e. devices, links, hosts") 19 description = "Wipes-out the entire network information base, i.e. devices, links, hosts")
16 public class WipeOutCommand extends ClustersListCommand { 20 public class WipeOutCommand extends ClustersListCommand {
17 21
22 + private static final String DISCLAIMER = "Delete everything please.";
23 +
24 + @Argument(index = 0, name = "disclaimer", description = "Device ID",
25 + required = false, multiValued = false)
26 + String disclaimer = null;
27 +
18 @Override 28 @Override
19 protected void execute() { 29 protected void execute() {
30 + if (disclaimer == null || !disclaimer.equals(DISCLAIMER)) {
31 + print("I'm afraid I can't do that!\nPlease acknowledge with phrase: '%s'",
32 + DISCLAIMER);
33 + return;
34 + }
35 +
36 + print("Wiping devices");
20 DeviceAdminService deviceAdminService = get(DeviceAdminService.class); 37 DeviceAdminService deviceAdminService = get(DeviceAdminService.class);
21 DeviceService deviceService = get(DeviceService.class); 38 DeviceService deviceService = get(DeviceService.class);
22 for (Device device : deviceService.getDevices()) { 39 for (Device device : deviceService.getDevices()) {
23 deviceAdminService.removeDevice(device.id()); 40 deviceAdminService.removeDevice(device.id());
24 } 41 }
25 42
43 + print("Wiping hosts");
26 HostAdminService hostAdminService = get(HostAdminService.class); 44 HostAdminService hostAdminService = get(HostAdminService.class);
27 HostService hostService = get(HostService.class); 45 HostService hostService = get(HostService.class);
28 for (Host host : hostService.getHosts()) { 46 for (Host host : hostService.getHosts()) {
29 hostAdminService.removeHost(host.id()); 47 hostAdminService.removeHost(host.id());
30 } 48 }
31 - }
32 -
33 49
50 + print("Wiping intents");
51 + IntentService intentService = get(IntentService.class);
52 + for (Intent intent : intentService.getIntents()) {
53 + if (intentService.getIntentState(intent.id()) == IntentState.INSTALLED) {
54 + intentService.withdraw(intent);
55 + }
56 + }
57 + }
34 } 58 }
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
2 2
3 <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0"> 3 <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
4 <command> 4 <command>
5 + <action class="org.onlab.onos.cli.SummaryCommand"/>
6 + </command>
7 + <command>
5 <action class="org.onlab.onos.cli.NodesListCommand"/> 8 <action class="org.onlab.onos.cli.NodesListCommand"/>
6 </command> 9 </command>
7 <command> 10 <command>
...@@ -56,6 +59,30 @@ ...@@ -56,6 +59,30 @@
56 <ref component-id="deviceIdCompleter"/> 59 <ref component-id="deviceIdCompleter"/>
57 </completers> 60 </completers>
58 </command> 61 </command>
62 +
63 + <command>
64 + <action class="org.onlab.onos.cli.net.IntentsListCommand"/>
65 + </command>
66 + <command>
67 + <action class="org.onlab.onos.cli.net.IntentRemoveCommand"/>
68 + <completers>
69 + <ref component-id="intentIdCompleter"/>
70 + </completers>
71 + </command>
72 + <command>
73 + <action class="org.onlab.onos.cli.net.AddHostToHostIntentCommand"/>
74 + <completers>
75 + <ref component-id="hostIdCompleter"/>
76 + </completers>
77 + </command>
78 + <command>
79 + <action class="org.onlab.onos.cli.net.AddPointToPointIntentCommand"/>
80 + <completers>
81 + <ref component-id="connectPointCompleter"/>
82 + <ref component-id="connectPointCompleter"/>
83 + </completers>
84 + </command>
85 +
59 <command> 86 <command>
60 <action class="org.onlab.onos.cli.net.ClustersListCommand"/> 87 <action class="org.onlab.onos.cli.net.ClustersListCommand"/>
61 </command> 88 </command>
...@@ -94,6 +121,8 @@ ...@@ -94,6 +121,8 @@
94 <bean id="clusterIdCompleter" class="org.onlab.onos.cli.net.ClusterIdCompleter"/> 121 <bean id="clusterIdCompleter" class="org.onlab.onos.cli.net.ClusterIdCompleter"/>
95 <bean id="roleCompleter" class="org.onlab.onos.cli.net.RoleCompleter"/> 122 <bean id="roleCompleter" class="org.onlab.onos.cli.net.RoleCompleter"/>
96 <bean id="hostIdCompleter" class="org.onlab.onos.cli.net.HostIdCompleter"/> 123 <bean id="hostIdCompleter" class="org.onlab.onos.cli.net.HostIdCompleter"/>
124 + <bean id="intentIdCompleter" class="org.onlab.onos.cli.net.IntentIdCompleter"/>
97 <bean id="flowRuleStatusCompleter" class="org.onlab.onos.cli.net.FlowRuleStatusCompleter"/> 125 <bean id="flowRuleStatusCompleter" class="org.onlab.onos.cli.net.FlowRuleStatusCompleter"/>
126 + <bean id="connectPointCompleter" class="org.onlab.onos.cli.net.ConnectPointCompleter"/>
98 127
99 </blueprint> 128 </blueprint>
......
...@@ -8,7 +8,7 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -8,7 +8,7 @@ import java.util.concurrent.atomic.AtomicInteger;
8 */ 8 */
9 public final class ApplicationId { 9 public final class ApplicationId {
10 10
11 - private static AtomicInteger idDispenser; 11 + private static final AtomicInteger ID_DISPENCER = new AtomicInteger(1);
12 private final Integer id; 12 private final Integer id;
13 13
14 // Ban public construction 14 // Ban public construction
...@@ -50,10 +50,7 @@ public final class ApplicationId { ...@@ -50,10 +50,7 @@ public final class ApplicationId {
50 * @return app id 50 * @return app id
51 */ 51 */
52 public static ApplicationId getAppId() { 52 public static ApplicationId getAppId() {
53 - if (ApplicationId.idDispenser == null) { 53 + return new ApplicationId(ApplicationId.ID_DISPENCER.getAndIncrement());
54 - ApplicationId.idDispenser = new AtomicInteger(1);
55 - }
56 - return new ApplicationId(ApplicationId.idDispenser.getAndIncrement());
57 } 54 }
58 55
59 } 56 }
......
1 +package org.onlab.onos;
2 +
3 +/**
4 + * Service for interacting with the core system of the controller.
5 + */
6 +public interface CoreService {
7 +
8 + /**
9 + * Returns the product version.
10 + *
11 + * @return product version
12 + */
13 + Version version();
14 +
15 +}
1 +package org.onlab.onos;
2 +
3 +import java.util.Objects;
4 +
5 +import static java.lang.Integer.parseInt;
6 +
7 +/**
8 + * Representation of the product version.
9 + */
10 +public final class Version {
11 +
12 + public static final String FORMAT = "%d.%d.%d.%s";
13 +
14 + private final int major;
15 + private final int minor;
16 + private final int patch;
17 + private final String build;
18 +
19 + private final String format;
20 +
21 + // Creates a new version descriptor
22 + private Version(int major, int minor, int patch, String build) {
23 + this.major = major;
24 + this.minor = minor;
25 + this.patch = patch;
26 + this.build = build;
27 + this.format = String.format(FORMAT, major, minor, patch, build);
28 + }
29 +
30 +
31 + /**
32 + * Creates a new version from the specified constituent numbers.
33 + *
34 + * @param major major version number
35 + * @param minor minod version number
36 + * @param patch version patch number
37 + * @param build build string
38 + * @return version descriptor
39 + */
40 + public static Version version(int major, int minor, int patch, String build) {
41 + return new Version(major, minor, patch, build);
42 + }
43 +
44 + /**
45 + * Creates a new version by parsing the specified string.
46 + *
47 + * @param string version string
48 + * @return version descriptor
49 + */
50 + public static Version version(String string) {
51 + String[] fields = string.split("[.-]");
52 + return new Version(parseInt(fields[0]), parseInt(fields[1]),
53 + parseInt(fields[2]), fields[3]);
54 + }
55 +
56 + /**
57 + * Returns the major version number.
58 + *
59 + * @return major version number
60 + */
61 + public int major() {
62 + return major;
63 + }
64 +
65 + /**
66 + * Returns the minor version number.
67 + *
68 + * @return minor version number
69 + */
70 + public int minor() {
71 + return minor;
72 + }
73 +
74 + /**
75 + * Returns the version patch number.
76 + *
77 + * @return patch number
78 + */
79 + public int patch() {
80 + return patch;
81 + }
82 +
83 + /**
84 + * Returns the version build string.
85 + *
86 + * @return build string
87 + */
88 + public String build() {
89 + return build;
90 + }
91 +
92 + @Override
93 + public String toString() {
94 + return format;
95 + }
96 +
97 + @Override
98 + public int hashCode() {
99 + return Objects.hash(format);
100 + }
101 +
102 + @Override
103 + public boolean equals(Object obj) {
104 + if (this == obj) {
105 + return true;
106 + }
107 + if (obj instanceof Version) {
108 + final Version other = (Version) obj;
109 + return Objects.equals(this.format, other.format);
110 + }
111 + return false;
112 + }
113 +}
...@@ -17,6 +17,7 @@ public interface MastershipService { ...@@ -17,6 +17,7 @@ public interface MastershipService {
17 * Returns the role of the local node for the specified device, without 17 * Returns the role of the local node for the specified device, without
18 * triggering master selection. 18 * triggering master selection.
19 * 19 *
20 + * @param deviceId the the identifier of the device
20 * @return role of the current node 21 * @return role of the current node
21 */ 22 */
22 MastershipRole getLocalRole(DeviceId deviceId); 23 MastershipRole getLocalRole(DeviceId deviceId);
......
1 +package org.onlab.onos.net;
2 +
3 +public final class AnnotationsUtil {
4 +
5 + public static boolean isEqual(Annotations lhs, Annotations rhs) {
6 + if (lhs == rhs) {
7 + return true;
8 + }
9 + if (lhs == null || rhs == null) {
10 + return false;
11 + }
12 +
13 + if (!lhs.keys().equals(rhs.keys())) {
14 + return false;
15 + }
16 +
17 + for (String key : lhs.keys()) {
18 + if (!lhs.value(key).equals(rhs.value(key))) {
19 + return false;
20 + }
21 + }
22 + return true;
23 + }
24 +
25 + // not to be instantiated
26 + private AnnotationsUtil() {}
27 +}
...@@ -47,7 +47,23 @@ public class ConnectPoint { ...@@ -47,7 +47,23 @@ public class ConnectPoint {
47 return (DeviceId) elementId; 47 return (DeviceId) elementId;
48 } 48 }
49 throw new IllegalStateException("Connection point not associated " + 49 throw new IllegalStateException("Connection point not associated " +
50 - "with an infrastructure device"); 50 + "with an infrastructure device");
51 + }
52 +
53 + /**
54 + * Returns the identifier of the infrastructure device if the connection
55 + * point belongs to a network element which is indeed an end-station host.
56 + *
57 + * @return network element identifier as a host identifier
58 + * @throws java.lang.IllegalStateException if connection point is not
59 + * associated with a host
60 + */
61 + public HostId hostId() {
62 + if (elementId instanceof HostId) {
63 + return (HostId) elementId;
64 + }
65 + throw new IllegalStateException("Connection point not associated " +
66 + "with an end-station host");
51 } 67 }
52 68
53 /** 69 /**
......
...@@ -73,31 +73,63 @@ public final class DefaultAnnotations implements SparseAnnotations { ...@@ -73,31 +73,63 @@ public final class DefaultAnnotations implements SparseAnnotations {
73 } 73 }
74 74
75 /** 75 /**
76 - * Convert Annotations to DefaultAnnotations if needed and merges. 76 + * Creates the union of two given SparseAnnotations.
77 + * Unlike the {@link #merge(DefaultAnnotations, SparseAnnotations)} method,
78 + * result will be {@link SparseAnnotations} instead of {@link Annotations}.
77 * 79 *
78 - * @see #merge(DefaultAnnotations, SparseAnnotations) 80 + * A key tagged for removal will remain in the output SparseAnnotations,
81 + * if the counterpart of the input does not contain the same key.
79 * 82 *
80 * @param annotations base annotations 83 * @param annotations base annotations
81 * @param sparseAnnotations additional sparse annotations 84 * @param sparseAnnotations additional sparse annotations
82 * @return combined annotations or the original base annotations if there 85 * @return combined annotations or the original base annotations if there
83 * are not additional annotations 86 * are not additional annotations
84 */ 87 */
85 - public static DefaultAnnotations merge(Annotations annotations, 88 + public static SparseAnnotations union(SparseAnnotations annotations,
86 - SparseAnnotations sparseAnnotations) { 89 + SparseAnnotations sparseAnnotations) {
90 +
91 + if (sparseAnnotations == null || sparseAnnotations.keys().isEmpty()) {
92 + return annotations;
93 + }
94 +
95 + final HashMap<String, String> newMap;
87 if (annotations instanceof DefaultAnnotations) { 96 if (annotations instanceof DefaultAnnotations) {
88 - return merge((DefaultAnnotations) annotations, sparseAnnotations); 97 + newMap = copy(((DefaultAnnotations) annotations).map);
98 + } else {
99 + newMap = new HashMap<>(annotations.keys().size() +
100 + sparseAnnotations.keys().size());
101 + putAllSparseAnnotations(newMap, annotations);
89 } 102 }
90 103
91 - DefaultAnnotations.Builder builder = DefaultAnnotations.builder(); 104 + putAllSparseAnnotations(newMap, sparseAnnotations);
92 - for (String key : annotations.keys()) { 105 + return new DefaultAnnotations(newMap);
93 - builder.set(key, annotations.value(key)); 106 + }
107 +
108 + // adds the key-values contained in sparseAnnotations to
109 + // newMap, if sparseAnnotations had a key tagged for removal,
110 + // and corresponding key exist in newMap, entry will be removed.
111 + // if corresponding key does not exist, removal tag will be added to
112 + // the newMap.
113 + private static void putAllSparseAnnotations(
114 + final HashMap<String, String> newMap,
115 + SparseAnnotations sparseAnnotations) {
116 +
117 + for (String key : sparseAnnotations.keys()) {
118 + if (sparseAnnotations.isRemoved(key)) {
119 + if (newMap.containsKey(key)) {
120 + newMap.remove(key);
121 + } else {
122 + newMap.put(key, Builder.REMOVED);
123 + }
124 + } else {
125 + String value = sparseAnnotations.value(key);
126 + newMap.put(key, value);
127 + }
94 } 128 }
95 - return merge(builder.build(), sparseAnnotations);
96 } 129 }
97 130
98 @Override 131 @Override
99 public Set<String> keys() { 132 public Set<String> keys() {
100 - // TODO: unmodifiable to be removed after switching to ImmutableMap;
101 return Collections.unmodifiableSet(map.keySet()); 133 return Collections.unmodifiableSet(map.keySet());
102 } 134 }
103 135
...@@ -115,7 +147,7 @@ public final class DefaultAnnotations implements SparseAnnotations { ...@@ -115,7 +147,7 @@ public final class DefaultAnnotations implements SparseAnnotations {
115 @SuppressWarnings("unchecked") 147 @SuppressWarnings("unchecked")
116 private static HashMap<String, String> copy(Map<String, String> original) { 148 private static HashMap<String, String> copy(Map<String, String> original) {
117 if (original instanceof HashMap) { 149 if (original instanceof HashMap) {
118 - return (HashMap) ((HashMap) original).clone(); 150 + return (HashMap<String, String>) ((HashMap<?, ?>) original).clone();
119 } 151 }
120 throw new IllegalArgumentException("Expecting HashMap instance"); 152 throw new IllegalArgumentException("Expecting HashMap instance");
121 } 153 }
......
...@@ -3,6 +3,7 @@ package org.onlab.onos.net; ...@@ -3,6 +3,7 @@ package org.onlab.onos.net;
3 import org.onlab.onos.net.provider.ProviderId; 3 import org.onlab.onos.net.provider.ProviderId;
4 4
5 import static com.google.common.base.Preconditions.checkArgument; 5 import static com.google.common.base.Preconditions.checkArgument;
6 +import static com.google.common.base.Preconditions.checkNotNull;
6 7
7 /** 8 /**
8 * Default edge link model implementation. 9 * Default edge link model implementation.
...@@ -18,9 +19,9 @@ public class DefaultEdgeLink extends DefaultLink implements EdgeLink { ...@@ -18,9 +19,9 @@ public class DefaultEdgeLink extends DefaultLink implements EdgeLink {
18 * @param providerId provider identity 19 * @param providerId provider identity
19 * @param hostPoint host-side connection point 20 * @param hostPoint host-side connection point
20 * @param hostLocation location where host attaches to the network 21 * @param hostLocation location where host attaches to the network
21 - * @param isIngress true to indicated host-to-network direction; false 22 + * @param isIngress true to indicate host-to-network direction; false
22 * for network-to-host direction 23 * for network-to-host direction
23 - * @param annotations optional key/value annotations 24 + * @param annotations optional key/value annotations
24 */ 25 */
25 public DefaultEdgeLink(ProviderId providerId, ConnectPoint hostPoint, 26 public DefaultEdgeLink(ProviderId providerId, ConnectPoint hostPoint,
26 HostLocation hostLocation, boolean isIngress, 27 HostLocation hostLocation, boolean isIngress,
...@@ -42,4 +43,24 @@ public class DefaultEdgeLink extends DefaultLink implements EdgeLink { ...@@ -42,4 +43,24 @@ public class DefaultEdgeLink extends DefaultLink implements EdgeLink {
42 public HostLocation hostLocation() { 43 public HostLocation hostLocation() {
43 return hostLocation; 44 return hostLocation;
44 } 45 }
46 +
47 + /**
48 + * Creates a phantom edge link, to an unspecified end-station. This link
49 + * does not represent any actually discovered link stored in the system.
50 + *
51 + * @param edgePort network edge port
52 + * @param isIngress true to indicate host-to-network direction; false
53 + * for network-to-host direction
54 + * @return new phantom edge link
55 + */
56 + public static DefaultEdgeLink createEdgeLink(ConnectPoint edgePort,
57 + boolean isIngress) {
58 + checkNotNull(edgePort, "Edge port cannot be null");
59 + HostLocation location = (edgePort instanceof HostLocation) ?
60 + (HostLocation) edgePort : new HostLocation(edgePort, 0);
61 + return new DefaultEdgeLink(ProviderId.NONE,
62 + new ConnectPoint(HostId.NONE, PortNumber.P0),
63 + location, isIngress);
64 + }
65 +
45 } 66 }
......
...@@ -10,6 +10,14 @@ import java.net.URI; ...@@ -10,6 +10,14 @@ import java.net.URI;
10 */ 10 */
11 public final class HostId extends ElementId { 11 public final class HostId extends ElementId {
12 12
13 + private static final String NIC = "nic";
14 +
15 + /**
16 + * Represents either no host, or an unspecified host; used for creating
17 + * open ingress/egress edge links.
18 + */
19 + public static final HostId NONE = hostId(NIC + ":none-0");
20 +
13 // Public construction is prohibited 21 // Public construction is prohibited
14 private HostId(URI uri) { 22 private HostId(URI uri) {
15 super(uri); 23 super(uri);
...@@ -43,8 +51,7 @@ public final class HostId extends ElementId { ...@@ -43,8 +51,7 @@ public final class HostId extends ElementId {
43 * @return host identifier 51 * @return host identifier
44 */ 52 */
45 public static HostId hostId(MacAddress mac, VlanId vlanId) { 53 public static HostId hostId(MacAddress mac, VlanId vlanId) {
46 - // FIXME: use more efficient means of encoding 54 + return hostId(NIC + ":" + mac + "-" + vlanId);
47 - return hostId("nic" + ":" + mac + "-" + vlanId);
48 } 55 }
49 56
50 /** 57 /**
......
...@@ -22,6 +22,17 @@ public class HostLocation extends ConnectPoint { ...@@ -22,6 +22,17 @@ public class HostLocation extends ConnectPoint {
22 } 22 }
23 23
24 /** 24 /**
25 + * Creates a new host location derived from the supplied connection point.
26 + *
27 + * @param connectPoint connection point
28 + * @param time time when detected, in millis since start of epoch
29 + */
30 + public HostLocation(ConnectPoint connectPoint, long time) {
31 + super(connectPoint.deviceId(), connectPoint.port());
32 + this.time = time;
33 + }
34 +
35 + /**
25 * Returns the time when the location was established, given in 36 * Returns the time when the location was established, given in
26 * milliseconds since start of epoch. 37 * milliseconds since start of epoch.
27 * 38 *
......
...@@ -6,6 +6,7 @@ import com.google.common.base.MoreObjects; ...@@ -6,6 +6,7 @@ import com.google.common.base.MoreObjects;
6 6
7 // TODO Consider renaming. 7 // TODO Consider renaming.
8 // it's an identifier for a Link, but it's not ElementId, so not using LinkId. 8 // it's an identifier for a Link, but it's not ElementId, so not using LinkId.
9 +
9 /** 10 /**
10 * Immutable representation of a link identity. 11 * Immutable representation of a link identity.
11 */ 12 */
...@@ -43,6 +44,15 @@ public class LinkKey { ...@@ -43,6 +44,15 @@ public class LinkKey {
43 this.dst = dst; 44 this.dst = dst;
44 } 45 }
45 46
47 + /**
48 + * Creates a link identifier for the specified link.
49 + *
50 + * @param link link descriptor
51 + */
52 + public LinkKey(Link link) {
53 + this(link.src(), link.dst());
54 + }
55 +
46 @Override 56 @Override
47 public int hashCode() { 57 public int hashCode() {
48 return Objects.hash(src(), dst); 58 return Objects.hash(src(), dst);
......
...@@ -9,6 +9,8 @@ import com.google.common.primitives.UnsignedLongs; ...@@ -9,6 +9,8 @@ import com.google.common.primitives.UnsignedLongs;
9 */ 9 */
10 public final class PortNumber { 10 public final class PortNumber {
11 11
12 + public static final PortNumber P0 = portNumber(0);
13 +
12 // TODO: revisit the max and the logical port value assignments 14 // TODO: revisit the max and the logical port value assignments
13 15
14 private static final long MAX_NUMBER = (2L * Integer.MAX_VALUE) + 1; 16 private static final long MAX_NUMBER = (2L * Integer.MAX_VALUE) + 1;
......
...@@ -96,4 +96,13 @@ public class DefaultDeviceDescription extends AbstractDescription ...@@ -96,4 +96,13 @@ public class DefaultDeviceDescription extends AbstractDescription
96 .toString(); 96 .toString();
97 } 97 }
98 98
99 + // default constructor for serialization
100 + private DefaultDeviceDescription() {
101 + this.uri = null;
102 + this.type = null;
103 + this.manufacturer = null;
104 + this.hwVersion = null;
105 + this.swVersion = null;
106 + this.serialNumber = null;
107 + }
99 } 108 }
......
...@@ -48,4 +48,9 @@ public class DefaultPortDescription extends AbstractDescription ...@@ -48,4 +48,9 @@ public class DefaultPortDescription extends AbstractDescription
48 return isEnabled; 48 return isEnabled;
49 } 49 }
50 50
51 + // default constructor for serialization
52 + private DefaultPortDescription() {
53 + this.number = null;
54 + this.isEnabled = false;
55 + }
51 } 56 }
......
1 +package org.onlab.onos.net.flow;
2 +
3 +public class CompletedBatchOperation {
4 +
5 +
6 +}
1 +package org.onlab.onos.net.flow;
2 +
3 +import static com.google.common.base.MoreObjects.toStringHelper;
4 +import static org.slf4j.LoggerFactory.getLogger;
5 +
6 +import org.onlab.onos.net.DeviceId;
7 +import org.slf4j.Logger;
8 +
9 +public class DefaultFlowEntry extends DefaultFlowRule implements FlowEntry {
10 +
11 + private final Logger log = getLogger(getClass());
12 +
13 + private long life;
14 + private long packets;
15 + private long bytes;
16 + private FlowEntryState state;
17 +
18 + private long lastSeen = -1;
19 +
20 +
21 + public DefaultFlowEntry(DeviceId deviceId, TrafficSelector selector,
22 + TrafficTreatment treatment, int priority, FlowEntryState state,
23 + long life, long packets, long bytes, long flowId,
24 + int timeout) {
25 + super(deviceId, selector, treatment, priority, flowId, timeout);
26 + this.state = state;
27 + this.life = life;
28 + this.packets = packets;
29 + this.bytes = bytes;
30 + this.lastSeen = System.currentTimeMillis();
31 + }
32 +
33 + public DefaultFlowEntry(FlowRule rule, FlowEntryState state,
34 + long life, long packets, long bytes) {
35 + super(rule);
36 + this.state = state;
37 + this.life = life;
38 + this.packets = packets;
39 + this.bytes = bytes;
40 + this.lastSeen = System.currentTimeMillis();
41 + }
42 +
43 + public DefaultFlowEntry(FlowRule rule) {
44 + super(rule);
45 + this.state = FlowEntryState.PENDING_ADD;
46 + this.life = 0;
47 + this.packets = 0;
48 + this.bytes = 0;
49 + this.lastSeen = System.currentTimeMillis();
50 + }
51 +
52 + @Override
53 + public long life() {
54 + return life;
55 + }
56 +
57 + @Override
58 + public long packets() {
59 + return packets;
60 + }
61 +
62 + @Override
63 + public long bytes() {
64 + return bytes;
65 + }
66 +
67 + @Override
68 + public FlowEntryState state() {
69 + return this.state;
70 + }
71 +
72 + @Override
73 + public long lastSeen() {
74 + return lastSeen;
75 + }
76 +
77 + @Override
78 + public void setLastSeen() {
79 + this.lastSeen = System.currentTimeMillis();
80 + }
81 +
82 + @Override
83 + public void setState(FlowEntryState newState) {
84 + this.state = newState;
85 + }
86 +
87 + @Override
88 + public void setLife(long life) {
89 + this.life = life;
90 + }
91 +
92 + @Override
93 + public void setPackets(long packets) {
94 + this.packets = packets;
95 + }
96 +
97 + @Override
98 + public void setBytes(long bytes) {
99 + this.bytes = bytes;
100 + }
101 +
102 + @Override
103 + public String toString() {
104 + return toStringHelper(this)
105 + .add("rule", super.toString())
106 + .add("state", state)
107 + .toString();
108 + }
109 +
110 +
111 +}
...@@ -18,10 +18,6 @@ public class DefaultFlowRule implements FlowRule { ...@@ -18,10 +18,6 @@ public class DefaultFlowRule implements FlowRule {
18 private final TrafficSelector selector; 18 private final TrafficSelector selector;
19 private final TrafficTreatment treatment; 19 private final TrafficTreatment treatment;
20 private final long created; 20 private final long created;
21 - private final long life;
22 - private final long packets;
23 - private final long bytes;
24 - private final FlowRuleState state;
25 21
26 private final FlowId id; 22 private final FlowId id;
27 23
...@@ -29,73 +25,50 @@ public class DefaultFlowRule implements FlowRule { ...@@ -29,73 +25,50 @@ public class DefaultFlowRule implements FlowRule {
29 25
30 private final int timeout; 26 private final int timeout;
31 27
28 +
32 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector, 29 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
33 - TrafficTreatment treatment, int priority, FlowRuleState state, 30 + TrafficTreatment treatment, int priority, long flowId,
34 - long life, long packets, long bytes, long flowId, boolean expired,
35 int timeout) { 31 int timeout) {
36 this.deviceId = deviceId; 32 this.deviceId = deviceId;
37 this.priority = priority; 33 this.priority = priority;
38 this.selector = selector; 34 this.selector = selector;
39 this.treatment = treatment; 35 this.treatment = treatment;
40 - this.state = state; 36 + this.timeout = timeout;
37 + this.created = System.currentTimeMillis();
38 +
41 this.appId = ApplicationId.valueOf((int) (flowId >> 32)); 39 this.appId = ApplicationId.valueOf((int) (flowId >> 32));
42 this.id = FlowId.valueOf(flowId); 40 this.id = FlowId.valueOf(flowId);
43 - this.life = life;
44 - this.packets = packets;
45 - this.bytes = bytes;
46 - this.created = System.currentTimeMillis();
47 - this.timeout = timeout;
48 } 41 }
49 42
50 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector, 43 public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector,
51 TrafficTreatment treatement, int priority, ApplicationId appId, 44 TrafficTreatment treatement, int priority, ApplicationId appId,
52 int timeout) { 45 int timeout) {
53 - this(deviceId, selector, treatement, priority,
54 - FlowRuleState.CREATED, appId, timeout);
55 - }
56 46
57 - public DefaultFlowRule(FlowRule rule, FlowRuleState state) { 47 + if (priority < FlowRule.MIN_PRIORITY) {
58 - this(rule.deviceId(), rule.selector(), rule.treatment(), 48 + throw new IllegalArgumentException("Priority cannot be less than " + MIN_PRIORITY);
59 - rule.priority(), state, rule.id(), rule.appId(), 49 + }
60 - rule.timeout());
61 - }
62 50
63 - private DefaultFlowRule(DeviceId deviceId,
64 - TrafficSelector selector, TrafficTreatment treatment,
65 - int priority, FlowRuleState state, ApplicationId appId,
66 - int timeout) {
67 this.deviceId = deviceId; 51 this.deviceId = deviceId;
68 this.priority = priority; 52 this.priority = priority;
69 this.selector = selector; 53 this.selector = selector;
70 - this.treatment = treatment; 54 + this.treatment = treatement;
71 - this.state = state;
72 - this.life = 0;
73 - this.packets = 0;
74 - this.bytes = 0;
75 this.appId = appId; 55 this.appId = appId;
76 -
77 this.timeout = timeout; 56 this.timeout = timeout;
57 + this.created = System.currentTimeMillis();
78 58
79 this.id = FlowId.valueOf((((long) appId().id()) << 32) | (this.hash() & 0xffffffffL)); 59 this.id = FlowId.valueOf((((long) appId().id()) << 32) | (this.hash() & 0xffffffffL));
80 - this.created = System.currentTimeMillis();
81 } 60 }
82 61
83 - private DefaultFlowRule(DeviceId deviceId, 62 + public DefaultFlowRule(FlowRule rule) {
84 - TrafficSelector selector, TrafficTreatment treatment, 63 + this.deviceId = rule.deviceId();
85 - int priority, FlowRuleState state, FlowId flowId, ApplicationId appId, 64 + this.priority = rule.priority();
86 - int timeout) { 65 + this.selector = rule.selector();
87 - this.deviceId = deviceId; 66 + this.treatment = rule.treatment();
88 - this.priority = priority; 67 + this.appId = rule.appId();
89 - this.selector = selector; 68 + this.id = rule.id();
90 - this.treatment = treatment; 69 + this.timeout = rule.timeout();
91 - this.state = state;
92 - this.life = 0;
93 - this.packets = 0;
94 - this.bytes = 0;
95 - this.appId = appId;
96 - this.id = flowId;
97 - this.timeout = timeout;
98 this.created = System.currentTimeMillis(); 70 this.created = System.currentTimeMillis();
71 +
99 } 72 }
100 73
101 74
...@@ -129,26 +102,6 @@ public class DefaultFlowRule implements FlowRule { ...@@ -129,26 +102,6 @@ public class DefaultFlowRule implements FlowRule {
129 return treatment; 102 return treatment;
130 } 103 }
131 104
132 - @Override
133 - public long lifeMillis() {
134 - return life;
135 - }
136 -
137 - @Override
138 - public long packets() {
139 - return packets;
140 - }
141 -
142 - @Override
143 - public long bytes() {
144 - return bytes;
145 - }
146 -
147 - @Override
148 - public FlowRuleState state() {
149 - return this.state;
150 - }
151 -
152 105
153 @Override 106 @Override
154 /* 107 /*
...@@ -162,7 +115,7 @@ public class DefaultFlowRule implements FlowRule { ...@@ -162,7 +115,7 @@ public class DefaultFlowRule implements FlowRule {
162 } 115 }
163 116
164 public int hash() { 117 public int hash() {
165 - return Objects.hash(deviceId, selector, id); 118 + return Objects.hash(deviceId, selector, treatment);
166 } 119 }
167 120
168 @Override 121 @Override
...@@ -179,7 +132,7 @@ public class DefaultFlowRule implements FlowRule { ...@@ -179,7 +132,7 @@ public class DefaultFlowRule implements FlowRule {
179 if (obj instanceof DefaultFlowRule) { 132 if (obj instanceof DefaultFlowRule) {
180 DefaultFlowRule that = (DefaultFlowRule) obj; 133 DefaultFlowRule that = (DefaultFlowRule) obj;
181 return Objects.equals(deviceId, that.deviceId) && 134 return Objects.equals(deviceId, that.deviceId) &&
182 - //Objects.equals(id, that.id) && 135 + Objects.equals(id, that.id) &&
183 Objects.equals(priority, that.priority) && 136 Objects.equals(priority, that.priority) &&
184 Objects.equals(selector, that.selector); 137 Objects.equals(selector, that.selector);
185 138
...@@ -190,19 +143,18 @@ public class DefaultFlowRule implements FlowRule { ...@@ -190,19 +143,18 @@ public class DefaultFlowRule implements FlowRule {
190 @Override 143 @Override
191 public String toString() { 144 public String toString() {
192 return toStringHelper(this) 145 return toStringHelper(this)
193 - .add("id", id) 146 + .add("id", Long.toHexString(id.value()))
194 .add("deviceId", deviceId) 147 .add("deviceId", deviceId)
195 .add("priority", priority) 148 .add("priority", priority)
196 .add("selector", selector.criteria()) 149 .add("selector", selector.criteria())
197 .add("treatment", treatment == null ? "N/A" : treatment.instructions()) 150 .add("treatment", treatment == null ? "N/A" : treatment.instructions())
198 .add("created", created) 151 .add("created", created)
199 - .add("state", state)
200 .toString(); 152 .toString();
201 } 153 }
202 154
203 @Override 155 @Override
204 public int timeout() { 156 public int timeout() {
205 - return timeout > MAX_TIMEOUT ? MAX_TIMEOUT : this.timeout; 157 + return timeout;
206 } 158 }
207 159
208 } 160 }
......
1 package org.onlab.onos.net.flow; 1 package org.onlab.onos.net.flow;
2 2
3 -import static org.slf4j.LoggerFactory.getLogger; 3 +import com.google.common.collect.ImmutableSet;
4 -
5 -import java.util.Collections;
6 -import java.util.HashSet;
7 -import java.util.Objects;
8 -import java.util.Set;
9 -
10 import org.onlab.onos.net.PortNumber; 4 import org.onlab.onos.net.PortNumber;
11 import org.onlab.onos.net.flow.criteria.Criteria; 5 import org.onlab.onos.net.flow.criteria.Criteria;
12 import org.onlab.onos.net.flow.criteria.Criterion; 6 import org.onlab.onos.net.flow.criteria.Criterion;
13 import org.onlab.packet.IpPrefix; 7 import org.onlab.packet.IpPrefix;
14 import org.onlab.packet.MacAddress; 8 import org.onlab.packet.MacAddress;
15 import org.onlab.packet.VlanId; 9 import org.onlab.packet.VlanId;
16 -import org.slf4j.Logger;
17 10
11 +import java.util.Collections;
12 +import java.util.HashMap;
13 +import java.util.Map;
14 +import java.util.Objects;
15 +import java.util.Set;
16 +
17 +/**
18 + * Default traffic selector implementation.
19 + */
18 public final class DefaultTrafficSelector implements TrafficSelector { 20 public final class DefaultTrafficSelector implements TrafficSelector {
19 21
20 - private final Set<Criterion> selector; 22 + private final Set<Criterion> criteria;
21 23
22 - private DefaultTrafficSelector(Set<Criterion> selector) { 24 + /**
23 - this.selector = Collections.unmodifiableSet(selector); 25 + * Creates a new traffic selector with the specified criteria.
26 + *
27 + * @param criteria criteria
28 + */
29 + private DefaultTrafficSelector(Set<Criterion> criteria) {
30 + this.criteria = Collections.unmodifiableSet(criteria);
24 } 31 }
25 32
26 @Override 33 @Override
27 public Set<Criterion> criteria() { 34 public Set<Criterion> criteria() {
28 - return selector; 35 + return criteria;
29 } 36 }
30 37
31 @Override 38 @Override
32 public int hashCode() { 39 public int hashCode() {
33 - return Objects.hash(selector); 40 + return Objects.hash(criteria);
34 } 41 }
35 42
36 @Override 43 @Override
...@@ -40,23 +47,50 @@ public final class DefaultTrafficSelector implements TrafficSelector { ...@@ -40,23 +47,50 @@ public final class DefaultTrafficSelector implements TrafficSelector {
40 } 47 }
41 if (obj instanceof DefaultTrafficSelector) { 48 if (obj instanceof DefaultTrafficSelector) {
42 DefaultTrafficSelector that = (DefaultTrafficSelector) obj; 49 DefaultTrafficSelector that = (DefaultTrafficSelector) obj;
43 - return Objects.equals(selector, that.selector); 50 + return Objects.equals(criteria, that.criteria);
44 51
45 } 52 }
46 return false; 53 return false;
47 } 54 }
48 55
56 + /**
57 + * Returns a new traffic selector builder.
58 + *
59 + * @return traffic selector builder
60 + */
61 + public static TrafficSelector.Builder builder() {
62 + return new Builder();
63 + }
49 64
65 + /**
66 + * Returns a new traffic selector builder primed to produce entities
67 + * patterned after the supplied selector.
68 + *
69 + * @return traffic selector builder
70 + */
71 + public static TrafficSelector.Builder builder(TrafficSelector selector) {
72 + return new Builder(selector);
73 + }
50 74
51 - public static class Builder implements TrafficSelector.Builder { 75 + /**
76 + * Builder of traffic selector entities.
77 + */
78 + public static final class Builder implements TrafficSelector.Builder {
52 79
53 - private final Logger log = getLogger(getClass()); 80 + private final Map<Criterion.Type, Criterion> selector = new HashMap<>();
54 81
55 - private final Set<Criterion> selector = new HashSet<>(); 82 + private Builder() {
83 + }
84 +
85 + private Builder(TrafficSelector selector) {
86 + for (Criterion c : selector.criteria()) {
87 + add(c);
88 + }
89 + }
56 90
57 @Override 91 @Override
58 public Builder add(Criterion criterion) { 92 public Builder add(Criterion criterion) {
59 - selector.add(criterion); 93 + selector.put(criterion.type(), criterion);
60 return this; 94 return this;
61 } 95 }
62 96
...@@ -107,7 +141,7 @@ public final class DefaultTrafficSelector implements TrafficSelector { ...@@ -107,7 +141,7 @@ public final class DefaultTrafficSelector implements TrafficSelector {
107 141
108 @Override 142 @Override
109 public TrafficSelector build() { 143 public TrafficSelector build() {
110 - return new DefaultTrafficSelector(selector); 144 + return new DefaultTrafficSelector(ImmutableSet.copyOf(selector.values()));
111 } 145 }
112 146
113 } 147 }
......
...@@ -5,6 +5,7 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -5,6 +5,7 @@ import static org.slf4j.LoggerFactory.getLogger;
5 import java.util.Collections; 5 import java.util.Collections;
6 import java.util.LinkedList; 6 import java.util.LinkedList;
7 import java.util.List; 7 import java.util.List;
8 +import java.util.Objects;
8 9
9 import org.onlab.onos.net.PortNumber; 10 import org.onlab.onos.net.PortNumber;
10 import org.onlab.onos.net.flow.instructions.Instruction; 11 import org.onlab.onos.net.flow.instructions.Instruction;
...@@ -14,10 +15,18 @@ import org.onlab.packet.MacAddress; ...@@ -14,10 +15,18 @@ import org.onlab.packet.MacAddress;
14 import org.onlab.packet.VlanId; 15 import org.onlab.packet.VlanId;
15 import org.slf4j.Logger; 16 import org.slf4j.Logger;
16 17
18 +/**
19 + * Default traffic treatment implementation.
20 + */
17 public final class DefaultTrafficTreatment implements TrafficTreatment { 21 public final class DefaultTrafficTreatment implements TrafficTreatment {
18 22
19 private final List<Instruction> instructions; 23 private final List<Instruction> instructions;
20 24
25 + /**
26 + * Creates a new traffic treatment from the specified list of instructions.
27 + *
28 + * @param instructions treatment instructions
29 + */
21 private DefaultTrafficTreatment(List<Instruction> instructions) { 30 private DefaultTrafficTreatment(List<Instruction> instructions) {
22 this.instructions = Collections.unmodifiableList(instructions); 31 this.instructions = Collections.unmodifiableList(instructions);
23 } 32 }
...@@ -28,12 +37,38 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -28,12 +37,38 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
28 } 37 }
29 38
30 /** 39 /**
31 - * Builds a list of treatments following the following order. 40 + * Returns a new traffic treatment builder.
32 - * Modifications -> Group -> Output (including drop)
33 * 41 *
42 + * @return traffic treatment builder
34 */ 43 */
44 + public static TrafficTreatment.Builder builder() {
45 + return new Builder();
46 + }
47 +
48 + //FIXME: Order of instructions may affect hashcode
49 + @Override
50 + public int hashCode() {
51 + return Objects.hash(instructions);
52 + }
53 +
54 + @Override
55 + public boolean equals(Object obj) {
56 + if (this == obj) {
57 + return true;
58 + }
59 + if (obj instanceof DefaultTrafficTreatment) {
60 + DefaultTrafficTreatment that = (DefaultTrafficTreatment) obj;
61 + return Objects.equals(instructions, that.instructions);
35 62
36 - public static class Builder implements TrafficTreatment.Builder { 63 + }
64 + return false;
65 + }
66 +
67 + /**
68 + * Builds a list of treatments following the following order.
69 + * Modifications -> Group -> Output (including drop)
70 + */
71 + public static final class Builder implements TrafficTreatment.Builder {
37 72
38 private final Logger log = getLogger(getClass()); 73 private final Logger log = getLogger(getClass());
39 74
...@@ -47,27 +82,32 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { ...@@ -47,27 +82,32 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
47 // TODO: should be a list of instructions based on modification objects 82 // TODO: should be a list of instructions based on modification objects
48 List<Instruction> modifications = new LinkedList<>(); 83 List<Instruction> modifications = new LinkedList<>();
49 84
85 + // Creates a new builder
86 + private Builder() {
87 + }
88 +
89 + @Override
50 public Builder add(Instruction instruction) { 90 public Builder add(Instruction instruction) {
51 if (drop) { 91 if (drop) {
52 return this; 92 return this;
53 } 93 }
54 switch (instruction.type()) { 94 switch (instruction.type()) {
55 - case DROP: 95 + case DROP:
56 - drop = true; 96 + drop = true;
57 - break; 97 + break;
58 - case OUTPUT: 98 + case OUTPUT:
59 - outputs.add(instruction); 99 + outputs.add(instruction);
60 - break; 100 + break;
61 - case L2MODIFICATION: 101 + case L2MODIFICATION:
62 - case L3MODIFICATION: 102 + case L3MODIFICATION:
63 - // TODO: enforce modification order if any 103 + // TODO: enforce modification order if any
64 - modifications.add(instruction); 104 + modifications.add(instruction);
65 - break; 105 + break;
66 - case GROUP: 106 + case GROUP:
67 - groups.add(instruction); 107 + groups.add(instruction);
68 - break; 108 + break;
69 - default: 109 + default:
70 - log.warn("Unknown instruction type {}", instruction.type()); 110 + log.warn("Unknown instruction type {}", instruction.type());
71 } 111 }
72 return this; 112 return this;
73 } 113 }
......
1 +package org.onlab.onos.net.flow;
2 +
3 +
4 +/**
5 + * Represents a generalized match &amp; action pair to be applied to
6 + * an infrastucture device.
7 + */
8 +public interface FlowEntry extends FlowRule {
9 +
10 +
11 + public enum FlowEntryState {
12 +
13 + /**
14 + * Indicates that this rule has been submitted for addition.
15 + * Not necessarily in the flow table.
16 + */
17 + PENDING_ADD,
18 +
19 + /**
20 + * Rule has been added which means it is in the flow table.
21 + */
22 + ADDED,
23 +
24 + /**
25 + * Flow has been marked for removal, might still be in flow table.
26 + */
27 + PENDING_REMOVE,
28 +
29 + /**
30 + * Flow has been removed from flow table and can be purged.
31 + */
32 + REMOVED
33 + }
34 +
35 + /**
36 + * Returns the flow entry state.
37 + *
38 + * @return flow entry state
39 + */
40 + FlowEntryState state();
41 +
42 + /**
43 + * Returns the number of milliseconds this flow rule has been applied.
44 + *
45 + * @return number of millis
46 + */
47 + long life();
48 +
49 + /**
50 + * Returns the number of packets this flow rule has matched.
51 + *
52 + * @return number of packets
53 + */
54 + long packets();
55 +
56 + /**
57 + * Returns the number of bytes this flow rule has matched.
58 + *
59 + * @return number of bytes
60 + */
61 + long bytes();
62 +
63 + /**
64 + * When this flow entry was last deemed active.
65 + * @return epoch time of last activity
66 + */
67 + long lastSeen();
68 +
69 + /**
70 + * Sets the last active epoch time.
71 + */
72 + void setLastSeen();
73 +
74 + /**
75 + * Sets the new state for this entry.
76 + * @param newState new flow entry state.
77 + */
78 + void setState(FlowEntryState newState);
79 +
80 + /**
81 + * Sets how long this entry has been entered in the system.
82 + * @param life epoch time
83 + */
84 + void setLife(long life);
85 +
86 + /**
87 + * Number of packets seen by this entry.
88 + * @param packets a long value
89 + */
90 + void setPackets(long packets);
91 +
92 + /**
93 + * Number of bytes seen by this rule.
94 + * @param bytes a long value
95 + */
96 + void setBytes(long bytes);
97 +
98 +}
...@@ -26,6 +26,9 @@ public final class FlowId { ...@@ -26,6 +26,9 @@ public final class FlowId {
26 if (this == obj) { 26 if (this == obj) {
27 return true; 27 return true;
28 } 28 }
29 + if (obj == null) {
30 + return false;
31 + }
29 if (obj.getClass() == this.getClass()) { 32 if (obj.getClass() == this.getClass()) {
30 FlowId that = (FlowId) obj; 33 FlowId that = (FlowId) obj;
31 return Objects.equal(this.flowid, that.flowid); 34 return Objects.equal(this.flowid, that.flowid);
......
...@@ -2,49 +2,16 @@ package org.onlab.onos.net.flow; ...@@ -2,49 +2,16 @@ package org.onlab.onos.net.flow;
2 2
3 import org.onlab.onos.ApplicationId; 3 import org.onlab.onos.ApplicationId;
4 import org.onlab.onos.net.DeviceId; 4 import org.onlab.onos.net.DeviceId;
5 +import org.onlab.onos.net.intent.BatchOperationTarget;
5 6
6 /** 7 /**
7 * Represents a generalized match &amp; action pair to be applied to 8 * Represents a generalized match &amp; action pair to be applied to
8 * an infrastucture device. 9 * an infrastucture device.
9 */ 10 */
10 -public interface FlowRule { 11 +public interface FlowRule extends BatchOperationTarget {
11 12
12 static final int MAX_TIMEOUT = 60; 13 static final int MAX_TIMEOUT = 60;
13 - 14 + static final int MIN_PRIORITY = 0;
14 - public enum FlowRuleState {
15 - /**
16 - * Indicates that this rule has been created.
17 - */
18 - CREATED,
19 -
20 - /**
21 - * Indicates that this rule has been submitted for addition.
22 - * Not necessarily in the flow table.
23 - */
24 - PENDING_ADD,
25 -
26 - /**
27 - * Rule has been added which means it is in the flow table.
28 - */
29 - ADDED,
30 -
31 - /**
32 - * Flow has been marked for removal, might still be in flow table.
33 - */
34 - PENDING_REMOVE,
35 -
36 - /**
37 - * Flow has been removed from flow table and can be purged.
38 - */
39 - REMOVED
40 - }
41 -
42 - /**
43 - * Returns the flow rule state.
44 - *
45 - * @return flow rule state
46 - */
47 - FlowRuleState state();
48 15
49 //TODO: build cookie value 16 //TODO: build cookie value
50 /** 17 /**
...@@ -92,27 +59,6 @@ public interface FlowRule { ...@@ -92,27 +59,6 @@ public interface FlowRule {
92 TrafficTreatment treatment(); 59 TrafficTreatment treatment();
93 60
94 /** 61 /**
95 - * Returns the number of milliseconds this flow rule has been applied.
96 - *
97 - * @return number of millis
98 - */
99 - long lifeMillis();
100 -
101 - /**
102 - * Returns the number of packets this flow rule has matched.
103 - *
104 - * @return number of packets
105 - */
106 - long packets();
107 -
108 - /**
109 - * Returns the number of bytes this flow rule has matched.
110 - *
111 - * @return number of bytes
112 - */
113 - long bytes();
114 -
115 - /**
116 * Returns the timeout for this flow requested by an application. 62 * Returns the timeout for this flow requested by an application.
117 * @return integer value of the timeout 63 * @return integer value of the timeout
118 */ 64 */
......
1 +package org.onlab.onos.net.flow;
2 +
3 +import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
4 +import org.onlab.onos.net.intent.BatchOperationEntry;
5 +
6 +
7 +public class FlowRuleBatchEntry
8 + extends BatchOperationEntry<FlowRuleOperation, FlowRule> {
9 +
10 + public FlowRuleBatchEntry(FlowRuleOperation operator, FlowRule target) {
11 + super(operator, target);
12 + }
13 +
14 + public enum FlowRuleOperation {
15 + ADD,
16 + REMOVE,
17 + MODIFY
18 + }
19 +
20 +}
1 +package org.onlab.onos.net.flow;
2 +
3 +import java.util.Collection;
4 +
5 +import org.onlab.onos.net.intent.BatchOperation;
6 +
7 +public class FlowRuleBatchOperation
8 + extends BatchOperation<FlowRuleBatchEntry> {
9 +
10 + public FlowRuleBatchOperation(Collection<FlowRuleBatchEntry> operations) {
11 + super(operations);
12 + }
13 +}
1 package org.onlab.onos.net.flow; 1 package org.onlab.onos.net.flow;
2 2
3 +import java.util.concurrent.Future;
4 +
3 import org.onlab.onos.ApplicationId; 5 import org.onlab.onos.ApplicationId;
6 +import org.onlab.onos.net.intent.BatchOperation;
4 import org.onlab.onos.net.provider.Provider; 7 import org.onlab.onos.net.provider.Provider;
5 8
6 /** 9 /**
...@@ -34,4 +37,6 @@ public interface FlowRuleProvider extends Provider { ...@@ -34,4 +37,6 @@ public interface FlowRuleProvider extends Provider {
34 */ 37 */
35 void removeRulesById(ApplicationId id, FlowRule... flowRules); 38 void removeRulesById(ApplicationId id, FlowRule... flowRules);
36 39
40 + Future<Void> executeBatch(BatchOperation<FlowRuleBatchEntry> batch);
41 +
37 } 42 }
......
...@@ -14,7 +14,7 @@ public interface FlowRuleProviderService extends ProviderService<FlowRuleProvide ...@@ -14,7 +14,7 @@ public interface FlowRuleProviderService extends ProviderService<FlowRuleProvide
14 * 14 *
15 * @param flowRule information about the removed flow 15 * @param flowRule information about the removed flow
16 */ 16 */
17 - void flowRemoved(FlowRule flowRule); 17 + void flowRemoved(FlowEntry flowEntry);
18 18
19 /** 19 /**
20 * Pushes the collection of flow entries currently applied on the given 20 * Pushes the collection of flow entries currently applied on the given
...@@ -22,7 +22,7 @@ public interface FlowRuleProviderService extends ProviderService<FlowRuleProvide ...@@ -22,7 +22,7 @@ public interface FlowRuleProviderService extends ProviderService<FlowRuleProvide
22 * 22 *
23 * @param flowRules collection of flow rules 23 * @param flowRules collection of flow rules
24 */ 24 */
25 - void pushFlowMetrics(DeviceId deviceId, Iterable<FlowRule> flowRules); 25 + void pushFlowMetrics(DeviceId deviceId, Iterable<FlowEntry> flowEntries);
26 26
27 27
28 28
......
1 package org.onlab.onos.net.flow; 1 package org.onlab.onos.net.flow;
2 2
3 +import java.util.concurrent.Future;
4 +
3 import org.onlab.onos.ApplicationId; 5 import org.onlab.onos.ApplicationId;
4 import org.onlab.onos.net.DeviceId; 6 import org.onlab.onos.net.DeviceId;
5 7
...@@ -13,6 +15,13 @@ import org.onlab.onos.net.DeviceId; ...@@ -13,6 +15,13 @@ import org.onlab.onos.net.DeviceId;
13 public interface FlowRuleService { 15 public interface FlowRuleService {
14 16
15 /** 17 /**
18 + * Returns the number of flow rules in the system.
19 + *
20 + * @return flow rule count
21 + */
22 + int getFlowRuleCount();
23 +
24 + /**
16 * Returns the collection of flow entries applied on the specified device. 25 * Returns the collection of flow entries applied on the specified device.
17 * This will include flow rules which may not yet have been applied to 26 * This will include flow rules which may not yet have been applied to
18 * the device. 27 * the device.
...@@ -20,7 +29,7 @@ public interface FlowRuleService { ...@@ -20,7 +29,7 @@ public interface FlowRuleService {
20 * @param deviceId device identifier 29 * @param deviceId device identifier
21 * @return collection of flow rules 30 * @return collection of flow rules
22 */ 31 */
23 - Iterable<FlowRule> getFlowEntries(DeviceId deviceId); 32 + Iterable<FlowEntry> getFlowEntries(DeviceId deviceId);
24 33
25 // TODO: add createFlowRule factory method and execute operations method 34 // TODO: add createFlowRule factory method and execute operations method
26 35
...@@ -60,6 +69,13 @@ public interface FlowRuleService { ...@@ -60,6 +69,13 @@ public interface FlowRuleService {
60 Iterable<FlowRule> getFlowRulesById(ApplicationId id); 69 Iterable<FlowRule> getFlowRulesById(ApplicationId id);
61 70
62 /** 71 /**
72 + * Applies a batch operation of FlowRules.
73 + *
74 + * @return future indicating the state of the batch operation
75 + */
76 + Future<CompletedBatchOperation> applyBatch(FlowRuleBatchOperation batch);
77 +
78 + /**
63 * Adds the specified flow rule listener. 79 * Adds the specified flow rule listener.
64 * 80 *
65 * @param listener flow rule listener 81 * @param listener flow rule listener
...@@ -72,7 +88,4 @@ public interface FlowRuleService { ...@@ -72,7 +88,4 @@ public interface FlowRuleService {
72 * @param listener flow rule listener 88 * @param listener flow rule listener
73 */ 89 */
74 void removeListener(FlowRuleListener listener); 90 void removeListener(FlowRuleListener listener);
75 -
76 -
77 -
78 } 91 }
......
...@@ -10,11 +10,19 @@ import org.onlab.onos.store.Store; ...@@ -10,11 +10,19 @@ import org.onlab.onos.store.Store;
10 public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegate> { 10 public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegate> {
11 11
12 /** 12 /**
13 + * Returns the number of flow rule in the store.
14 + *
15 + * @return number of flow rules
16 + */
17 + int getFlowRuleCount();
18 +
19 + /**
13 * Returns the stored flow. 20 * Returns the stored flow.
21 + *
14 * @param rule the rule to look for 22 * @param rule the rule to look for
15 * @return a flow rule 23 * @return a flow rule
16 */ 24 */
17 - FlowRule getFlowRule(FlowRule rule); 25 + FlowEntry getFlowEntry(FlowRule rule);
18 26
19 /** 27 /**
20 * Returns the flow entries associated with a device. 28 * Returns the flow entries associated with a device.
...@@ -22,7 +30,7 @@ public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegat ...@@ -22,7 +30,7 @@ public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegat
22 * @param deviceId the device ID 30 * @param deviceId the device ID
23 * @return the flow entries 31 * @return the flow entries
24 */ 32 */
25 - Iterable<FlowRule> getFlowEntries(DeviceId deviceId); 33 + Iterable<FlowEntry> getFlowEntries(DeviceId deviceId);
26 34
27 /** 35 /**
28 * Returns the flow entries associated with an application. 36 * Returns the flow entries associated with an application.
...@@ -30,7 +38,7 @@ public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegat ...@@ -30,7 +38,7 @@ public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegat
30 * @param appId the application id 38 * @param appId the application id
31 * @return the flow entries 39 * @return the flow entries
32 */ 40 */
33 - Iterable<FlowRule> getFlowEntriesByAppId(ApplicationId appId); 41 + Iterable<FlowRule> getFlowRulesByAppId(ApplicationId appId);
34 42
35 /** 43 /**
36 * Stores a new flow rule without generating events. 44 * Stores a new flow rule without generating events.
...@@ -40,7 +48,8 @@ public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegat ...@@ -40,7 +48,8 @@ public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegat
40 void storeFlowRule(FlowRule rule); 48 void storeFlowRule(FlowRule rule);
41 49
42 /** 50 /**
43 - * Deletes a flow rule without generating events. 51 + * Marks a flow rule for deletion. Actual deletion will occur
52 + * when the provider indicates that the flow has been removed.
44 * 53 *
45 * @param rule the flow rule to delete 54 * @param rule the flow rule to delete
46 */ 55 */
...@@ -52,12 +61,11 @@ public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegat ...@@ -52,12 +61,11 @@ public interface FlowRuleStore extends Store<FlowRuleEvent, FlowRuleStoreDelegat
52 * @param rule the flow rule to add or update 61 * @param rule the flow rule to add or update
53 * @return flow_added event, or null if just an update 62 * @return flow_added event, or null if just an update
54 */ 63 */
55 - FlowRuleEvent addOrUpdateFlowRule(FlowRule rule); 64 + FlowRuleEvent addOrUpdateFlowRule(FlowEntry rule);
56 65
57 /** 66 /**
58 - * @param rule the flow rule to remove 67 + * @param rule the flow entry to remove
59 * @return flow_removed event, or null if nothing removed 68 * @return flow_removed event, or null if nothing removed
60 */ 69 */
61 - FlowRuleEvent removeFlowRule(FlowRule rule); 70 + FlowRuleEvent removeFlowRule(FlowEntry rule);
62 -
63 } 71 }
......
...@@ -3,6 +3,8 @@ package org.onlab.onos.net.flow.instructions; ...@@ -3,6 +3,8 @@ package org.onlab.onos.net.flow.instructions;
3 import static com.google.common.base.MoreObjects.toStringHelper; 3 import static com.google.common.base.MoreObjects.toStringHelper;
4 import static com.google.common.base.Preconditions.checkNotNull; 4 import static com.google.common.base.Preconditions.checkNotNull;
5 5
6 +import java.util.Objects;
7 +
6 import org.onlab.onos.net.PortNumber; 8 import org.onlab.onos.net.PortNumber;
7 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.L2SubType; 9 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.L2SubType;
8 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction; 10 import org.onlab.onos.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
...@@ -117,6 +119,24 @@ public final class Instructions { ...@@ -117,6 +119,24 @@ public final class Instructions {
117 return toStringHelper(type()).toString(); 119 return toStringHelper(type()).toString();
118 120
119 } 121 }
122 +
123 + @Override
124 + public int hashCode() {
125 + return Objects.hash(type());
126 + }
127 +
128 + @Override
129 + public boolean equals(Object obj) {
130 + if (this == obj) {
131 + return true;
132 + }
133 + if (obj instanceof DropInstruction) {
134 + DropInstruction that = (DropInstruction) obj;
135 + return Objects.equals(type(), that.type());
136 +
137 + }
138 + return false;
139 + }
120 } 140 }
121 141
122 142
...@@ -140,6 +160,26 @@ public final class Instructions { ...@@ -140,6 +160,26 @@ public final class Instructions {
140 return toStringHelper(type().toString()) 160 return toStringHelper(type().toString())
141 .add("port", port).toString(); 161 .add("port", port).toString();
142 } 162 }
163 +
164 + @Override
165 + public int hashCode() {
166 + return Objects.hash(port, type());
167 + }
168 +
169 + @Override
170 + public boolean equals(Object obj) {
171 + if (this == obj) {
172 + return true;
173 + }
174 + if (obj instanceof OutputInstruction) {
175 + OutputInstruction that = (OutputInstruction) obj;
176 + Objects.equals(port, that.port);
177 +
178 + }
179 + return false;
180 + }
143 } 181 }
144 182
145 } 183 }
184 +
185 +
......
...@@ -2,6 +2,8 @@ package org.onlab.onos.net.flow.instructions; ...@@ -2,6 +2,8 @@ package org.onlab.onos.net.flow.instructions;
2 2
3 import static com.google.common.base.MoreObjects.toStringHelper; 3 import static com.google.common.base.MoreObjects.toStringHelper;
4 4
5 +import java.util.Objects;
6 +
5 import org.onlab.packet.MacAddress; 7 import org.onlab.packet.MacAddress;
6 import org.onlab.packet.VlanId; 8 import org.onlab.packet.VlanId;
7 9
...@@ -74,6 +76,25 @@ public abstract class L2ModificationInstruction implements Instruction { ...@@ -74,6 +76,25 @@ public abstract class L2ModificationInstruction implements Instruction {
74 .add("mac", mac).toString(); 76 .add("mac", mac).toString();
75 } 77 }
76 78
79 + @Override
80 + public int hashCode() {
81 + return Objects.hash(mac, subtype);
82 + }
83 +
84 + @Override
85 + public boolean equals(Object obj) {
86 + if (this == obj) {
87 + return true;
88 + }
89 + if (obj instanceof ModEtherInstruction) {
90 + ModEtherInstruction that = (ModEtherInstruction) obj;
91 + return Objects.equals(mac, that.mac) &&
92 + Objects.equals(subtype, that.subtype);
93 +
94 + }
95 + return false;
96 + }
97 +
77 98
78 } 99 }
79 100
...@@ -103,6 +124,25 @@ public abstract class L2ModificationInstruction implements Instruction { ...@@ -103,6 +124,25 @@ public abstract class L2ModificationInstruction implements Instruction {
103 .add("id", vlanId).toString(); 124 .add("id", vlanId).toString();
104 } 125 }
105 126
127 + @Override
128 + public int hashCode() {
129 + return Objects.hash(vlanId, subtype());
130 + }
131 +
132 + @Override
133 + public boolean equals(Object obj) {
134 + if (this == obj) {
135 + return true;
136 + }
137 + if (obj instanceof ModVlanIdInstruction) {
138 + ModVlanIdInstruction that = (ModVlanIdInstruction) obj;
139 + return Objects.equals(vlanId, that.vlanId);
140 +
141 + }
142 + return false;
143 + }
144 +
145 +
106 } 146 }
107 147
108 /** 148 /**
...@@ -131,6 +171,24 @@ public abstract class L2ModificationInstruction implements Instruction { ...@@ -131,6 +171,24 @@ public abstract class L2ModificationInstruction implements Instruction {
131 .add("pcp", Long.toHexString(vlanPcp)).toString(); 171 .add("pcp", Long.toHexString(vlanPcp)).toString();
132 } 172 }
133 173
174 + @Override
175 + public int hashCode() {
176 + return Objects.hash(vlanPcp, subtype());
177 + }
178 +
179 + @Override
180 + public boolean equals(Object obj) {
181 + if (this == obj) {
182 + return true;
183 + }
184 + if (obj instanceof ModVlanPcpInstruction) {
185 + ModVlanPcpInstruction that = (ModVlanPcpInstruction) obj;
186 + return Objects.equals(vlanPcp, that.vlanPcp);
187 +
188 + }
189 + return false;
190 + }
191 +
134 } 192 }
135 193
136 194
......
...@@ -2,6 +2,8 @@ package org.onlab.onos.net.flow.instructions; ...@@ -2,6 +2,8 @@ package org.onlab.onos.net.flow.instructions;
2 2
3 import static com.google.common.base.MoreObjects.toStringHelper; 3 import static com.google.common.base.MoreObjects.toStringHelper;
4 4
5 +import java.util.Objects;
6 +
5 import org.onlab.packet.IpPrefix; 7 import org.onlab.packet.IpPrefix;
6 8
7 /** 9 /**
...@@ -66,5 +68,23 @@ public abstract class L3ModificationInstruction implements Instruction { ...@@ -66,5 +68,23 @@ public abstract class L3ModificationInstruction implements Instruction {
66 .add("ip", ip).toString(); 68 .add("ip", ip).toString();
67 } 69 }
68 70
71 + @Override
72 + public int hashCode() {
73 + return Objects.hash(ip, subtype());
74 + }
75 +
76 + @Override
77 + public boolean equals(Object obj) {
78 + if (this == obj) {
79 + return true;
80 + }
81 + if (obj instanceof ModIPInstruction) {
82 + ModIPInstruction that = (ModIPInstruction) obj;
83 + return Objects.equals(ip, that.ip);
84 +
85 + }
86 + return false;
87 + }
88 +
69 } 89 }
70 } 90 }
......
...@@ -24,7 +24,7 @@ public abstract class AbstractIntent implements Intent { ...@@ -24,7 +24,7 @@ public abstract class AbstractIntent implements Intent {
24 } 24 }
25 25
26 @Override 26 @Override
27 - public IntentId getId() { 27 + public IntentId id() {
28 return id; 28 return id;
29 } 29 }
30 30
......
...@@ -3,6 +3,7 @@ package org.onlab.onos.net.intent; ...@@ -3,6 +3,7 @@ package org.onlab.onos.net.intent;
3 3
4 import static com.google.common.base.Preconditions.checkNotNull; 4 import static com.google.common.base.Preconditions.checkNotNull;
5 5
6 +import java.util.Collection;
6 import java.util.Collections; 7 import java.util.Collections;
7 import java.util.LinkedList; 8 import java.util.LinkedList;
8 import java.util.List; 9 import java.util.List;
...@@ -11,11 +12,11 @@ import java.util.List; ...@@ -11,11 +12,11 @@ import java.util.List;
11 * A list of BatchOperationEntry. 12 * A list of BatchOperationEntry.
12 * 13 *
13 * @param <T> the enum of operators <br> 14 * @param <T> the enum of operators <br>
14 - * This enum must be defined in each sub-classes. 15 + * This enum must be defined in each sub-classes.
15 - *
16 */ 16 */
17 public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> { 17 public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> {
18 - private List<T> ops; 18 +
19 + private final List<T> ops;
19 20
20 /** 21 /**
21 * Creates new {@link BatchOperation} object. 22 * Creates new {@link BatchOperation} object.
...@@ -30,7 +31,7 @@ public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> { ...@@ -30,7 +31,7 @@ public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> {
30 * 31 *
31 * @param batchOperations the list of batch operation entries. 32 * @param batchOperations the list of batch operation entries.
32 */ 33 */
33 - public BatchOperation(List<T> batchOperations) { 34 + public BatchOperation(Collection<T> batchOperations) {
34 ops = new LinkedList<>(checkNotNull(batchOperations)); 35 ops = new LinkedList<>(checkNotNull(batchOperations));
35 } 36 }
36 37
...@@ -61,6 +62,10 @@ public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> { ...@@ -61,6 +62,10 @@ public abstract class BatchOperation<T extends BatchOperationEntry<?, ?>> {
61 62
62 /** 63 /**
63 * Adds an operation. 64 * Adds an operation.
65 + * FIXME: Brian promises that the Intent Framework
66 + * will not modify the batch operation after it has submitted it.
67 + * Ali would prefer immutablity, but trusts brian for better or
68 + * for worse.
64 * 69 *
65 * @param entry the operation to be added 70 * @param entry the operation to be added
66 * @return this object if succeeded, null otherwise 71 * @return this object if succeeded, null otherwise
......
...@@ -15,14 +15,7 @@ public class BatchOperationEntry<T extends Enum<?>, U extends BatchOperationTarg ...@@ -15,14 +15,7 @@ public class BatchOperationEntry<T extends Enum<?>, U extends BatchOperationTarg
15 private final T operator; 15 private final T operator;
16 private final U target; 16 private final U target;
17 17
18 - /** 18 +
19 - * Default constructor for serializer.
20 - */
21 - @Deprecated
22 - protected BatchOperationEntry() {
23 - this.operator = null;
24 - this.target = null;
25 - }
26 19
27 /** 20 /**
28 * Constructs new instance for the entry of the BatchOperation. 21 * Constructs new instance for the entry of the BatchOperation.
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 -import static com.google.common.base.Preconditions.checkNotNull; 3 +import com.google.common.base.Objects;
4 -
5 import org.onlab.onos.net.flow.TrafficSelector; 4 import org.onlab.onos.net.flow.TrafficSelector;
6 import org.onlab.onos.net.flow.TrafficTreatment; 5 import org.onlab.onos.net.flow.TrafficTreatment;
7 6
8 -import com.google.common.base.Objects; 7 +import static com.google.common.base.Preconditions.checkNotNull;
9 8
10 /** 9 /**
11 * Abstraction of connectivity intent for traffic matching some criteria. 10 * Abstraction of connectivity intent for traffic matching some criteria.
...@@ -26,17 +25,18 @@ public abstract class ConnectivityIntent extends AbstractIntent { ...@@ -26,17 +25,18 @@ public abstract class ConnectivityIntent extends AbstractIntent {
26 25
27 /** 26 /**
28 * Creates a connectivity intent that matches on the specified intent 27 * Creates a connectivity intent that matches on the specified intent
29 - * and applies the specified action. 28 + * and applies the specified treatement.
30 * 29 *
31 - * @param id intent identifier 30 + * @param intentId intent identifier
32 - * @param match traffic match 31 + * @param selector traffic selector
33 - * @param action action 32 + * @param treatement treatement
34 - * @throws NullPointerException if the match or action is null 33 + * @throws NullPointerException if the selector or treatement is null
35 */ 34 */
36 - protected ConnectivityIntent(IntentId id, TrafficSelector match, TrafficTreatment action) { 35 + protected ConnectivityIntent(IntentId intentId, TrafficSelector selector,
37 - super(id); 36 + TrafficTreatment treatement) {
38 - this.selector = checkNotNull(match); 37 + super(intentId);
39 - this.treatment = checkNotNull(action); 38 + this.selector = checkNotNull(selector);
39 + this.treatment = checkNotNull(treatement);
40 } 40 }
41 41
42 /** 42 /**
...@@ -53,7 +53,7 @@ public abstract class ConnectivityIntent extends AbstractIntent { ...@@ -53,7 +53,7 @@ public abstract class ConnectivityIntent extends AbstractIntent {
53 * 53 *
54 * @return traffic match 54 * @return traffic match
55 */ 55 */
56 - public TrafficSelector getTrafficSelector() { 56 + public TrafficSelector selector() {
57 return selector; 57 return selector;
58 } 58 }
59 59
...@@ -62,7 +62,7 @@ public abstract class ConnectivityIntent extends AbstractIntent { ...@@ -62,7 +62,7 @@ public abstract class ConnectivityIntent extends AbstractIntent {
62 * 62 *
63 * @return applied action 63 * @return applied action
64 */ 64 */
65 - public TrafficTreatment getTrafficTreatment() { 65 + public TrafficTreatment treatment() {
66 return treatment; 66 return treatment;
67 } 67 }
68 68
......
1 +package org.onlab.onos.net.intent;
2 +
3 +import com.google.common.base.MoreObjects;
4 +import org.onlab.onos.net.HostId;
5 +import org.onlab.onos.net.flow.TrafficSelector;
6 +import org.onlab.onos.net.flow.TrafficTreatment;
7 +
8 +import java.util.Objects;
9 +
10 +import static com.google.common.base.Preconditions.checkNotNull;
11 +
12 +/**
13 + * Abstraction of end-station to end-station bidirectional connectivity.
14 + */
15 +public class HostToHostIntent extends ConnectivityIntent {
16 +
17 + private final HostId one;
18 + private final HostId two;
19 +
20 + /**
21 + * Creates a new point-to-point intent with the supplied ingress/egress
22 + * ports.
23 + *
24 + * @param intentId intent identifier
25 + * @param one first host
26 + * @param two second host
27 + * @param selector action
28 + * @param treatment ingress port
29 + * @throws NullPointerException if {@code ingressPort} or {@code egressPort}
30 + * is null.
31 + */
32 + public HostToHostIntent(IntentId intentId, HostId one, HostId two,
33 + TrafficSelector selector,
34 + TrafficTreatment treatment) {
35 + super(intentId, selector, treatment);
36 + this.one = checkNotNull(one);
37 + this.two = checkNotNull(two);
38 + }
39 +
40 + /**
41 + * Returns identifier of the first host.
42 + *
43 + * @return first host identifier
44 + */
45 + public HostId one() {
46 + return one;
47 + }
48 +
49 + /**
50 + * Returns identifier of the second host.
51 + *
52 + * @return second host identifier
53 + */
54 + public HostId two() {
55 + return two;
56 + }
57 +
58 + @Override
59 + public boolean equals(Object o) {
60 + if (this == o) {
61 + return true;
62 + }
63 + if (o == null || getClass() != o.getClass()) {
64 + return false;
65 + }
66 + if (!super.equals(o)) {
67 + return false;
68 + }
69 +
70 + HostToHostIntent that = (HostToHostIntent) o;
71 + return Objects.equals(this.one, that.one)
72 + && Objects.equals(this.two, that.two);
73 + }
74 +
75 + @Override
76 + public int hashCode() {
77 + return Objects.hash(super.hashCode(), one, two);
78 + }
79 +
80 + @Override
81 + public String toString() {
82 + return MoreObjects.toStringHelper(getClass())
83 + .add("id", id())
84 + .add("selector", selector())
85 + .add("treatment", treatment())
86 + .add("one", one)
87 + .add("two", two)
88 + .toString();
89 + }
90 +
91 +}
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 +import org.onlab.onos.net.Link;
4 +
5 +import java.util.Collection;
6 +
3 /** 7 /**
4 * Abstraction of an intent that can be installed into 8 * Abstraction of an intent that can be installed into
5 * the underlying system without additional compilation. 9 * the underlying system without additional compilation.
6 */ 10 */
7 public interface InstallableIntent extends Intent { 11 public interface InstallableIntent extends Intent {
12 +
13 + /**
14 + * Returns the collection of links that are required for this installable
15 + * intent to exist.
16 + *
17 + * @return collection of links
18 + */
19 + // FIXME: replace this with 'NetworkResource'
20 + Collection<Link> requiredLinks();
21 +
8 } 22 }
......
...@@ -2,7 +2,7 @@ package org.onlab.onos.net.intent; ...@@ -2,7 +2,7 @@ package org.onlab.onos.net.intent;
2 2
3 /** 3 /**
4 * Abstraction of an application level intent. 4 * Abstraction of an application level intent.
5 - * 5 + * <p/>
6 * Make sure that an Intent should be immutable when a new type is defined. 6 * Make sure that an Intent should be immutable when a new type is defined.
7 */ 7 */
8 public interface Intent extends BatchOperationTarget { 8 public interface Intent extends BatchOperationTarget {
...@@ -11,5 +11,5 @@ public interface Intent extends BatchOperationTarget { ...@@ -11,5 +11,5 @@ public interface Intent extends BatchOperationTarget {
11 * 11 *
12 * @return intent identifier 12 * @return intent identifier
13 */ 13 */
14 - IntentId getId(); 14 + IntentId id();
15 } 15 }
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 -import static com.google.common.base.Preconditions.checkNotNull; 3 +import org.onlab.onos.event.AbstractEvent;
4 -
5 -import java.util.Objects;
6 -
7 -import com.google.common.base.MoreObjects;
8 4
9 /** 5 /**
10 * A class to represent an intent related event. 6 * A class to represent an intent related event.
11 */ 7 */
12 -public class IntentEvent { 8 +public class IntentEvent extends AbstractEvent<IntentEvent.Type, Intent> {
13 9
14 - // TODO: determine a suitable parent class; if one does not exist, consider introducing one 10 + public enum Type {
11 + /**
12 + * Signifies that a new intent has been submitted to the system.
13 + */
14 + SUBMITTED,
15 15
16 - private final long time; 16 + /**
17 - private final Intent intent; 17 + * Signifies that an intent has been successfully installed.
18 - private final IntentState state; 18 + */
19 - private final IntentState previous; 19 + INSTALLED,
20 -
21 - /**
22 - * Creates an event describing a state change of an intent.
23 - *
24 - * @param intent subject intent
25 - * @param state new intent state
26 - * @param previous previous intent state
27 - * @param time time the event created in milliseconds since start of epoch
28 - * @throws NullPointerException if the intent or state is null
29 - */
30 - public IntentEvent(Intent intent, IntentState state, IntentState previous, long time) {
31 - this.intent = checkNotNull(intent);
32 - this.state = checkNotNull(state);
33 - this.previous = previous;
34 - this.time = time;
35 - }
36 20
37 - /** 21 + /**
38 - * Constructor for serializer. 22 + * Signifies that an intent has failed compilation or installation.
39 - */ 23 + */
40 - protected IntentEvent() { 24 + FAILED,
41 - this.intent = null;
42 - this.state = null;
43 - this.previous = null;
44 - this.time = 0;
45 - }
46 25
47 - /** 26 + /**
48 - * Returns the state of the intent which caused the event. 27 + * Signifies that an intent has been withdrawn from the system.
49 - * 28 + */
50 - * @return the state of the intent 29 + WITHDRAWN
51 - */
52 - public IntentState getState() {
53 - return state;
54 } 30 }
55 31
56 /** 32 /**
57 - * Returns the previous state of the intent which caused the event. 33 + * Creates an event of a given type and for the specified intent and the
34 + * current time.
58 * 35 *
59 - * @return the previous state of the intent 36 + * @param type event type
60 - */ 37 + * @param intent subject intent
61 - public IntentState getPreviousState() { 38 + * @param time time the event created in milliseconds since start of epoch
62 - return previous;
63 - }
64 -
65 - /**
66 - * Returns the intent associated with the event.
67 - *
68 - * @return the intent
69 */ 39 */
70 - public Intent getIntent() { 40 + public IntentEvent(Type type, Intent intent, long time) {
71 - return intent; 41 + super(type, intent, time);
72 } 42 }
73 43
74 /** 44 /**
75 - * Returns the time at which the event was created. 45 + * Creates an event of a given type and for the specified intent and the
46 + * current time.
76 * 47 *
77 - * @return the time in milliseconds since start of epoch 48 + * @param type event type
49 + * @param intent subject intent
78 */ 50 */
79 - public long getTime() { 51 + public IntentEvent(Type type, Intent intent) {
80 - return time; 52 + super(type, intent);
81 } 53 }
82 54
83 - @Override
84 - public boolean equals(Object o) {
85 - if (this == o) {
86 - return true;
87 - }
88 - if (o == null || getClass() != o.getClass()) {
89 - return false;
90 - }
91 -
92 - IntentEvent that = (IntentEvent) o;
93 - return Objects.equals(this.intent, that.intent)
94 - && Objects.equals(this.state, that.state)
95 - && Objects.equals(this.previous, that.previous)
96 - && Objects.equals(this.time, that.time);
97 - }
98 -
99 - @Override
100 - public int hashCode() {
101 - return Objects.hash(intent, state, previous, time);
102 - }
103 -
104 - @Override
105 - public String toString() {
106 - return MoreObjects.toStringHelper(getClass())
107 - .add("intent", intent)
108 - .add("state", state)
109 - .add("previous", previous)
110 - .add("time", time)
111 - .toString();
112 - }
113 } 55 }
......
...@@ -26,7 +26,7 @@ public class IntentException extends RuntimeException { ...@@ -26,7 +26,7 @@ public class IntentException extends RuntimeException {
26 * Constructs an exception with the specified message and the underlying cause. 26 * Constructs an exception with the specified message and the underlying cause.
27 * 27 *
28 * @param message the message describing the specific nature of the error 28 * @param message the message describing the specific nature of the error
29 - * @param cause the underlying cause of this error 29 + * @param cause the underlying cause of this error
30 */ 30 */
31 public IntentException(String message, Throwable cause) { 31 public IntentException(String message, Throwable cause) {
32 super(message, cause); 32 super(message, cause);
......
...@@ -10,9 +10,9 @@ public interface IntentExtensionService { ...@@ -10,9 +10,9 @@ public interface IntentExtensionService {
10 /** 10 /**
11 * Registers the specified compiler for the given intent class. 11 * Registers the specified compiler for the given intent class.
12 * 12 *
13 - * @param cls intent class 13 + * @param cls intent class
14 * @param compiler intent compiler 14 * @param compiler intent compiler
15 - * @param <T> the type of intent 15 + * @param <T> the type of intent
16 */ 16 */
17 <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler); 17 <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler);
18 18
...@@ -34,9 +34,9 @@ public interface IntentExtensionService { ...@@ -34,9 +34,9 @@ public interface IntentExtensionService {
34 /** 34 /**
35 * Registers the specified installer for the given installable intent class. 35 * Registers the specified installer for the given installable intent class.
36 * 36 *
37 - * @param cls installable intent class 37 + * @param cls installable intent class
38 * @param installer intent installer 38 * @param installer intent installer
39 - * @param <T> the type of installable intent 39 + * @param <T> the type of installable intent
40 */ 40 */
41 <T extends InstallableIntent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer); 41 <T extends InstallableIntent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer);
42 42
......
...@@ -2,7 +2,7 @@ package org.onlab.onos.net.intent; ...@@ -2,7 +2,7 @@ package org.onlab.onos.net.intent;
2 2
3 /** 3 /**
4 * Intent identifier suitable as an external key. 4 * Intent identifier suitable as an external key.
5 - * 5 + * <p/>
6 * This class is immutable. 6 * This class is immutable.
7 */ 7 */
8 public final class IntentId implements BatchOperationTarget { 8 public final class IntentId implements BatchOperationTarget {
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 +import org.onlab.onos.event.EventListener;
4 +
3 /** 5 /**
4 * Listener for {@link IntentEvent intent events}. 6 * Listener for {@link IntentEvent intent events}.
5 */ 7 */
6 -public interface IntentEventListener { 8 +public interface IntentListener extends EventListener<IntentEvent> {
7 - /**
8 - * Processes the specified intent event.
9 - *
10 - * @param event the event to process
11 - */
12 - void event(IntentEvent event);
13 } 9 }
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 -import java.util.Set;
4 3
5 /** 4 /**
6 * Service for application submitting or withdrawing their intents. 5 * Service for application submitting or withdrawing their intents.
...@@ -8,9 +7,9 @@ import java.util.Set; ...@@ -8,9 +7,9 @@ import java.util.Set;
8 public interface IntentService { 7 public interface IntentService {
9 /** 8 /**
10 * Submits an intent into the system. 9 * Submits an intent into the system.
11 - * 10 + * <p/>
12 - * This is an asynchronous request meaning that any compiling 11 + * This is an asynchronous request meaning that any compiling or
13 - * or installation activities may be done at later time. 12 + * installation activities may be done at later time.
14 * 13 *
15 * @param intent intent to be submitted 14 * @param intent intent to be submitted
16 */ 15 */
...@@ -18,9 +17,9 @@ public interface IntentService { ...@@ -18,9 +17,9 @@ public interface IntentService {
18 17
19 /** 18 /**
20 * Withdraws an intent from the system. 19 * Withdraws an intent from the system.
21 - * 20 + * <p/>
22 - * This is an asynchronous request meaning that the environment 21 + * This is an asynchronous request meaning that the environment may be
23 - * may be affected at later time. 22 + * affected at later time.
24 * 23 *
25 * @param intent intent to be withdrawn 24 * @param intent intent to be withdrawn
26 */ 25 */
...@@ -29,20 +28,27 @@ public interface IntentService { ...@@ -29,20 +28,27 @@ public interface IntentService {
29 /** 28 /**
30 * Submits a batch of submit &amp; withdraw operations. Such a batch is 29 * Submits a batch of submit &amp; withdraw operations. Such a batch is
31 * assumed to be processed together. 30 * assumed to be processed together.
32 - * 31 + * <p/>
33 - * This is an asynchronous request meaning that the environment 32 + * This is an asynchronous request meaning that the environment may be
34 - * may be affected at later time. 33 + * affected at later time.
35 * 34 *
36 * @param operations batch of intent operations 35 * @param operations batch of intent operations
37 */ 36 */
38 void execute(IntentOperations operations); 37 void execute(IntentOperations operations);
39 38
40 /** 39 /**
41 - * Returns immutable set of intents currently in the system. 40 + * Returns an iterable of intents currently in the system.
42 * 41 *
43 * @return set of intents 42 * @return set of intents
44 */ 43 */
45 - Set<Intent> getIntents(); 44 + Iterable<Intent> getIntents();
45 +
46 + /**
47 + * Returns the number of intents currently in the system.
48 + *
49 + * @return number of intents
50 + */
51 + long getIntentCount();
46 52
47 /** 53 /**
48 * Retrieves the intent specified by its identifier. 54 * Retrieves the intent specified by its identifier.
...@@ -56,7 +62,8 @@ public interface IntentService { ...@@ -56,7 +62,8 @@ public interface IntentService {
56 * Retrieves the state of an intent by its identifier. 62 * Retrieves the state of an intent by its identifier.
57 * 63 *
58 * @param id intent identifier 64 * @param id intent identifier
59 - * @return the intent state or null if one with the given identifier is not found 65 + * @return the intent state or null if one with the given identifier is not
66 + * found
60 */ 67 */
61 IntentState getIntentState(IntentId id); 68 IntentState getIntentState(IntentId id);
62 69
...@@ -65,12 +72,12 @@ public interface IntentService { ...@@ -65,12 +72,12 @@ public interface IntentService {
65 * 72 *
66 * @param listener listener to be added 73 * @param listener listener to be added
67 */ 74 */
68 - void addListener(IntentEventListener listener); 75 + void addListener(IntentListener listener);
69 76
70 /** 77 /**
71 * Removes the specified listener for intent events. 78 * Removes the specified listener for intent events.
72 * 79 *
73 * @param listener listener to be removed 80 * @param listener listener to be removed
74 */ 81 */
75 - void removeListener(IntentEventListener listener); 82 + void removeListener(IntentListener listener);
76 } 83 }
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 /** 3 /**
4 - * This class represents the states of an intent. 4 + * Representation of the phases an intent may attain during its lifecycle.
5 - *
6 - * <p>
7 - * Note: The state is expressed as enum, but there is possibility
8 - * in the future that we define specific class instead of enum to improve
9 - * the extensibility of state definition.
10 - * </p>
11 */ 5 */
12 public enum IntentState { 6 public enum IntentState {
13 - // FIXME: requires discussion on State vs. EventType and a solid state-transition diagram 7 +
14 - // TODO: consider the impact of conflict detection
15 - // TODO: consider the impact that external events affect an installed intent
16 /** 8 /**
17 - * The beginning state. 9 + * Signifies that the intent has been submitted and will start compiling
18 - * 10 + * shortly. However, this compilation may not necessarily occur on the
11 + * local controller instance.
12 + * <p/>
19 * All intent in the runtime take this state first. 13 * All intent in the runtime take this state first.
20 */ 14 */
21 SUBMITTED, 15 SUBMITTED,
22 16
23 /** 17 /**
24 - * The intent compilation has been completed. 18 + * Signifies that the intent is being compiled into installable intents.
25 - * 19 + * This is a transitional state after which the intent will enter either
26 - * An intent translation graph (tree) is completely created. 20 + * {@link #FAILED} state or {@link #INSTALLING} state.
27 - * Leaves of the graph are installable intent type. 21 + */
22 + COMPILING,
23 +
24 + /**
25 + * Signifies that the resulting installable intents are being installed
26 + * into the network environment. This is a transitional state after which
27 + * the intent will enter either {@link #INSTALLED} state or
28 + * {@link #RECOMPILING} state.
28 */ 29 */
29 - COMPILED, 30 + INSTALLING,
30 31
31 /** 32 /**
32 - * The intent has been successfully installed. 33 + * The intent has been successfully installed. This is a state where the
34 + * intent may remain parked until it is withdrawn by the application or
35 + * until the network environment changes in some way to make the original
36 + * set of installable intents untenable.
33 */ 37 */
34 INSTALLED, 38 INSTALLED,
35 39
36 /** 40 /**
37 - * The intent is being withdrawn. 41 + * Signifies that the intent is being recompiled into installable intents
38 - * 42 + * as an attempt to adapt to an anomaly in the network environment.
39 - * When {@link IntentService#withdraw(Intent)} is called, 43 + * This is a transitional state after which the intent will enter either
40 - * the intent takes this state first. 44 + * {@link #FAILED} state or {@link #INSTALLING} state.
45 + * <p/>
46 + * Exit to the {@link #FAILED} state may be caused by failure to compile
47 + * or by compiling into the same set of installable intents which have
48 + * previously failed to be installed.
49 + */
50 + RECOMPILING,
51 +
52 + /**
53 + * Indicates that the intent is being withdrawn. This is a transitional
54 + * state, triggered by invocation of the
55 + * {@link IntentService#withdraw(Intent)} but one with only one outcome,
56 + * which is the the intent being placed in the {@link #WITHDRAWN} state.
41 */ 57 */
42 WITHDRAWING, 58 WITHDRAWING,
43 59
44 /** 60 /**
45 - * The intent has been successfully withdrawn. 61 + * Indicates that the intent has been successfully withdrawn.
46 */ 62 */
47 WITHDRAWN, 63 WITHDRAWN,
48 64
49 /** 65 /**
50 - * The intent has failed to be compiled, installed, or withdrawn. 66 + * Signifies that the intent has failed compiling, installing or
51 - * 67 + * recompiling states.
52 - * When the intent failed to be withdrawn, it is still, at least partially installed.
53 */ 68 */
54 - FAILED, 69 + FAILED
55 } 70 }
......
1 +package org.onlab.onos.net.intent;
2 +
3 +import org.onlab.onos.store.Store;
4 +
5 +import java.util.List;
6 +
7 +/**
8 + * Manages inventory of end-station intents; not intended for direct use.
9 + */
10 +public interface IntentStore extends Store<IntentEvent, IntentStoreDelegate> {
11 +
12 + /**
13 + * Submits a new intent into the store. If the returned event is not
14 + * null, the manager is expected to dispatch the event and then to kick
15 + * off intent compilation process. Otherwise, another node has been elected
16 + * to perform the compilation process and the node will learn about
17 + * the submittal and results of the intent compilation via the delegate
18 + * mechanism.
19 + *
20 + * @param intent intent to be submitted
21 + * @return event indicating the intent was submitted or null if no
22 + * change resulted, e.g. duplicate intent
23 + */
24 + IntentEvent createIntent(Intent intent);
25 +
26 + /**
27 + * Removes the specified intent from the inventory.
28 + *
29 + * @param intentId intent identification
30 + * @return removed state transition event or null if intent was not found
31 + */
32 + IntentEvent removeIntent(IntentId intentId);
33 +
34 + /**
35 + * Returns the number of intents in the store.
36 + */
37 + long getIntentCount();
38 +
39 + /**
40 + * Returns a collection of all intents in the store.
41 + *
42 + * @return iterable collection of all intents
43 + */
44 + Iterable<Intent> getIntents();
45 +
46 + /**
47 + * Returns the intent with the specified identifer.
48 + *
49 + * @param intentId intent identification
50 + * @return intent or null if not found
51 + */
52 + Intent getIntent(IntentId intentId);
53 +
54 + /**
55 + * Returns the state of the specified intent.
56 + *
57 + * @param intentId intent identification
58 + * @return current intent state
59 + */
60 + IntentState getIntentState(IntentId intentId);
61 +
62 + /**
63 + * Sets the state of the specified intent to the new state.
64 + *
65 + * @param intent intent whose state is to be changed
66 + * @param newState new state
67 + * @return state transition event
68 + */
69 + IntentEvent setState(Intent intent, IntentState newState);
70 +
71 + /**
72 + * Adds the installable intents which resulted from compilation of the
73 + * specified original intent.
74 + *
75 + * @param intentId original intent identifier
76 + * @param installableIntents compiled installable intents
77 + */
78 + void addInstallableIntents(IntentId intentId,
79 + List<InstallableIntent> installableIntents);
80 +
81 + /**
82 + * Returns the list of the installable events associated with the specified
83 + * original intent.
84 + *
85 + * @param intentId original intent identifier
86 + * @return compiled installable intents
87 + */
88 + List<InstallableIntent> getInstallableIntents(IntentId intentId);
89 +
90 + // TODO: this should be triggered from with the store as a result of removeIntent call
91 +
92 + /**
93 + * Removes any installable intents which resulted from compilation of the
94 + * specified original intent.
95 + *
96 + * @param intentId original intent identifier
97 + * @return compiled state transition event
98 + */
99 + void removeInstalledIntents(IntentId intentId);
100 +
101 +}
1 +package org.onlab.onos.net.intent;
2 +
3 +import org.onlab.onos.store.StoreDelegate;
4 +
5 +/**
6 + * Intent store delegate abstraction.
7 + */
8 +public interface IntentStoreDelegate extends StoreDelegate<IntentEvent> {
9 +}
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 -import static com.google.common.base.Preconditions.checkArgument; 3 +import com.google.common.base.MoreObjects;
4 -import static com.google.common.base.Preconditions.checkNotNull; 4 +import com.google.common.collect.Sets;
5 -
6 -import java.util.Objects;
7 -import java.util.Set;
8 -
9 import org.onlab.onos.net.ConnectPoint; 5 import org.onlab.onos.net.ConnectPoint;
10 import org.onlab.onos.net.flow.TrafficSelector; 6 import org.onlab.onos.net.flow.TrafficSelector;
11 import org.onlab.onos.net.flow.TrafficTreatment; 7 import org.onlab.onos.net.flow.TrafficTreatment;
12 8
13 -import com.google.common.base.MoreObjects; 9 +import java.util.Objects;
14 -import com.google.common.collect.Sets; 10 +import java.util.Set;
11 +
12 +import static com.google.common.base.Preconditions.checkArgument;
13 +import static com.google.common.base.Preconditions.checkNotNull;
15 14
16 /** 15 /**
17 * Abstraction of multiple source to single destination connectivity intent. 16 * Abstraction of multiple source to single destination connectivity intent.
18 */ 17 */
19 public class MultiPointToSinglePointIntent extends ConnectivityIntent { 18 public class MultiPointToSinglePointIntent extends ConnectivityIntent {
20 19
21 - private final Set<ConnectPoint> ingressPorts; 20 + private final Set<ConnectPoint> ingressPoints;
22 - private final ConnectPoint egressPort; 21 + private final ConnectPoint egressPoint;
23 22
24 /** 23 /**
25 * Creates a new multi-to-single point connectivity intent for the specified 24 * Creates a new multi-to-single point connectivity intent for the specified
...@@ -28,23 +27,25 @@ public class MultiPointToSinglePointIntent extends ConnectivityIntent { ...@@ -28,23 +27,25 @@ public class MultiPointToSinglePointIntent extends ConnectivityIntent {
28 * @param id intent identifier 27 * @param id intent identifier
29 * @param match traffic match 28 * @param match traffic match
30 * @param action action 29 * @param action action
31 - * @param ingressPorts set of ports from which ingress traffic originates 30 + * @param ingressPoints set of ports from which ingress traffic originates
32 - * @param egressPort port to which traffic will egress 31 + * @param egressPoint port to which traffic will egress
33 - * @throws NullPointerException if {@code ingressPorts} or 32 + * @throws NullPointerException if {@code ingressPoints} or
34 - * {@code egressPort} is null. 33 + * {@code egressPoint} is null.
35 - * @throws IllegalArgumentException if the size of {@code ingressPorts} is 34 + * @throws IllegalArgumentException if the size of {@code ingressPoints} is
36 - * not more than 1 35 + * not more than 1
37 */ 36 */
38 - public MultiPointToSinglePointIntent(IntentId id, TrafficSelector match, TrafficTreatment action, 37 + public MultiPointToSinglePointIntent(IntentId id, TrafficSelector match,
39 - Set<ConnectPoint> ingressPorts, ConnectPoint egressPort) { 38 + TrafficTreatment action,
39 + Set<ConnectPoint> ingressPoints,
40 + ConnectPoint egressPoint) {
40 super(id, match, action); 41 super(id, match, action);
41 42
42 - checkNotNull(ingressPorts); 43 + checkNotNull(ingressPoints);
43 - checkArgument(!ingressPorts.isEmpty(), 44 + checkArgument(!ingressPoints.isEmpty(),
44 - "there should be at least one ingress port"); 45 + "there should be at least one ingress port");
45 46
46 - this.ingressPorts = Sets.newHashSet(ingressPorts); 47 + this.ingressPoints = Sets.newHashSet(ingressPoints);
47 - this.egressPort = checkNotNull(egressPort); 48 + this.egressPoint = checkNotNull(egressPoint);
48 } 49 }
49 50
50 /** 51 /**
...@@ -52,8 +53,8 @@ public class MultiPointToSinglePointIntent extends ConnectivityIntent { ...@@ -52,8 +53,8 @@ public class MultiPointToSinglePointIntent extends ConnectivityIntent {
52 */ 53 */
53 protected MultiPointToSinglePointIntent() { 54 protected MultiPointToSinglePointIntent() {
54 super(); 55 super();
55 - this.ingressPorts = null; 56 + this.ingressPoints = null;
56 - this.egressPort = null; 57 + this.egressPoint = null;
57 } 58 }
58 59
59 /** 60 /**
...@@ -62,8 +63,8 @@ public class MultiPointToSinglePointIntent extends ConnectivityIntent { ...@@ -62,8 +63,8 @@ public class MultiPointToSinglePointIntent extends ConnectivityIntent {
62 * 63 *
63 * @return set of ingress ports 64 * @return set of ingress ports
64 */ 65 */
65 - public Set<ConnectPoint> getIngressPorts() { 66 + public Set<ConnectPoint> ingressPoints() {
66 - return ingressPorts; 67 + return ingressPoints;
67 } 68 }
68 69
69 /** 70 /**
...@@ -71,8 +72,8 @@ public class MultiPointToSinglePointIntent extends ConnectivityIntent { ...@@ -71,8 +72,8 @@ public class MultiPointToSinglePointIntent extends ConnectivityIntent {
71 * 72 *
72 * @return egress port 73 * @return egress port
73 */ 74 */
74 - public ConnectPoint getEgressPort() { 75 + public ConnectPoint egressPoint() {
75 - return egressPort; 76 + return egressPoint;
76 } 77 }
77 78
78 @Override 79 @Override
...@@ -88,23 +89,23 @@ public class MultiPointToSinglePointIntent extends ConnectivityIntent { ...@@ -88,23 +89,23 @@ public class MultiPointToSinglePointIntent extends ConnectivityIntent {
88 } 89 }
89 90
90 MultiPointToSinglePointIntent that = (MultiPointToSinglePointIntent) o; 91 MultiPointToSinglePointIntent that = (MultiPointToSinglePointIntent) o;
91 - return Objects.equals(this.ingressPorts, that.ingressPorts) 92 + return Objects.equals(this.ingressPoints, that.ingressPoints)
92 - && Objects.equals(this.egressPort, that.egressPort); 93 + && Objects.equals(this.egressPoint, that.egressPoint);
93 } 94 }
94 95
95 @Override 96 @Override
96 public int hashCode() { 97 public int hashCode() {
97 - return Objects.hash(super.hashCode(), ingressPorts, egressPort); 98 + return Objects.hash(super.hashCode(), ingressPoints, egressPoint);
98 } 99 }
99 100
100 @Override 101 @Override
101 public String toString() { 102 public String toString() {
102 return MoreObjects.toStringHelper(getClass()) 103 return MoreObjects.toStringHelper(getClass())
103 - .add("id", getId()) 104 + .add("id", id())
104 - .add("match", getTrafficSelector()) 105 + .add("match", selector())
105 - .add("action", getTrafficTreatment()) 106 + .add("action", treatment())
106 - .add("ingressPorts", getIngressPorts()) 107 + .add("ingressPoints", ingressPoints())
107 - .add("egressPort", getEgressPort()) 108 + .add("egressPoint", egressPoint())
108 .toString(); 109 .toString();
109 } 110 }
110 } 111 }
......
...@@ -3,30 +3,30 @@ package org.onlab.onos.net.intent; ...@@ -3,30 +3,30 @@ package org.onlab.onos.net.intent;
3 import org.onlab.onos.net.ConnectPoint; 3 import org.onlab.onos.net.ConnectPoint;
4 4
5 // TODO: consider if this intent should be sub-class of ConnectivityIntent 5 // TODO: consider if this intent should be sub-class of ConnectivityIntent
6 +
6 /** 7 /**
7 * An optical layer Intent for a connectivity from a transponder port to another 8 * An optical layer Intent for a connectivity from a transponder port to another
8 * transponder port. 9 * transponder port.
9 - * <p> 10 + * <p/>
10 * This class doesn't accepts lambda specifier. This class computes path between 11 * This class doesn't accepts lambda specifier. This class computes path between
11 * ports and assign lambda automatically. The lambda can be specified using 12 * ports and assign lambda automatically. The lambda can be specified using
12 * OpticalPathFlow class. 13 * OpticalPathFlow class.
13 */ 14 */
14 public class OpticalConnectivityIntent extends AbstractIntent { 15 public class OpticalConnectivityIntent extends AbstractIntent {
15 - protected ConnectPoint srcConnectPoint; 16 + protected ConnectPoint src;
16 - protected ConnectPoint dstConnectPoint; 17 + protected ConnectPoint dst;
17 18
18 /** 19 /**
19 * Constructor. 20 * Constructor.
20 * 21 *
21 - * @param id ID for this new Intent object. 22 + * @param id ID for this new Intent object.
22 - * @param srcConnectPoint The source transponder port. 23 + * @param src The source transponder port.
23 - * @param dstConnectPoint The destination transponder port. 24 + * @param dst The destination transponder port.
24 */ 25 */
25 - public OpticalConnectivityIntent(IntentId id, 26 + public OpticalConnectivityIntent(IntentId id, ConnectPoint src, ConnectPoint dst) {
26 - ConnectPoint srcConnectPoint, ConnectPoint dstConnectPoint) {
27 super(id); 27 super(id);
28 - this.srcConnectPoint = srcConnectPoint; 28 + this.src = src;
29 - this.dstConnectPoint = dstConnectPoint; 29 + this.dst = dst;
30 } 30 }
31 31
32 /** 32 /**
...@@ -34,8 +34,8 @@ public class OpticalConnectivityIntent extends AbstractIntent { ...@@ -34,8 +34,8 @@ public class OpticalConnectivityIntent extends AbstractIntent {
34 */ 34 */
35 protected OpticalConnectivityIntent() { 35 protected OpticalConnectivityIntent() {
36 super(); 36 super();
37 - this.srcConnectPoint = null; 37 + this.src = null;
38 - this.dstConnectPoint = null; 38 + this.dst = null;
39 } 39 }
40 40
41 /** 41 /**
...@@ -44,7 +44,7 @@ public class OpticalConnectivityIntent extends AbstractIntent { ...@@ -44,7 +44,7 @@ public class OpticalConnectivityIntent extends AbstractIntent {
44 * @return The source transponder port. 44 * @return The source transponder port.
45 */ 45 */
46 public ConnectPoint getSrcConnectPoint() { 46 public ConnectPoint getSrcConnectPoint() {
47 - return srcConnectPoint; 47 + return src;
48 } 48 }
49 49
50 /** 50 /**
...@@ -52,7 +52,7 @@ public class OpticalConnectivityIntent extends AbstractIntent { ...@@ -52,7 +52,7 @@ public class OpticalConnectivityIntent extends AbstractIntent {
52 * 52 *
53 * @return The source transponder port. 53 * @return The source transponder port.
54 */ 54 */
55 - public ConnectPoint getDstConnectPoint() { 55 + public ConnectPoint getDst() {
56 - return dstConnectPoint; 56 + return dst;
57 } 57 }
58 } 58 }
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 -import java.util.Objects; 3 +import com.google.common.base.MoreObjects;
4 -
5 import org.onlab.onos.net.ConnectPoint; 4 import org.onlab.onos.net.ConnectPoint;
5 +import org.onlab.onos.net.Link;
6 import org.onlab.onos.net.Path; 6 import org.onlab.onos.net.Path;
7 import org.onlab.onos.net.flow.TrafficSelector; 7 import org.onlab.onos.net.flow.TrafficSelector;
8 import org.onlab.onos.net.flow.TrafficTreatment; 8 import org.onlab.onos.net.flow.TrafficTreatment;
9 9
10 -import com.google.common.base.MoreObjects; 10 +import java.util.Collection;
11 +import java.util.Objects;
11 12
12 /** 13 /**
13 * Abstraction of explicitly path specified connectivity intent. 14 * Abstraction of explicitly path specified connectivity intent.
14 */ 15 */
15 -public class PathIntent extends PointToPointIntent { 16 +public class PathIntent extends PointToPointIntent implements InstallableIntent {
16 17
17 private final Path path; 18 private final Path path;
18 19
...@@ -45,7 +46,7 @@ public class PathIntent extends PointToPointIntent { ...@@ -45,7 +46,7 @@ public class PathIntent extends PointToPointIntent {
45 * 46 *
46 * @return traversed links 47 * @return traversed links
47 */ 48 */
48 - public Path getPath() { 49 + public Path path() {
49 return path; 50 return path;
50 } 51 }
51 52
...@@ -78,12 +79,18 @@ public class PathIntent extends PointToPointIntent { ...@@ -78,12 +79,18 @@ public class PathIntent extends PointToPointIntent {
78 @Override 79 @Override
79 public String toString() { 80 public String toString() {
80 return MoreObjects.toStringHelper(getClass()) 81 return MoreObjects.toStringHelper(getClass())
81 - .add("id", getId()) 82 + .add("id", id())
82 - .add("match", getTrafficSelector()) 83 + .add("match", selector())
83 - .add("action", getTrafficTreatment()) 84 + .add("action", treatment())
84 - .add("ingressPort", getIngressPort()) 85 + .add("ingressPort", ingressPoint())
85 - .add("egressPort", getEgressPort()) 86 + .add("egressPort", egressPoint())
86 .add("path", path) 87 .add("path", path)
87 .toString(); 88 .toString();
88 } 89 }
90 +
91 + @Override
92 + public Collection<Link> requiredLinks() {
93 + return path.links();
94 + }
95 +
89 } 96 }
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 -import static com.google.common.base.Preconditions.checkNotNull; 3 +import com.google.common.base.MoreObjects;
4 -
5 -import java.util.Objects;
6 -
7 import org.onlab.onos.net.ConnectPoint; 4 import org.onlab.onos.net.ConnectPoint;
8 import org.onlab.onos.net.flow.TrafficSelector; 5 import org.onlab.onos.net.flow.TrafficSelector;
9 import org.onlab.onos.net.flow.TrafficTreatment; 6 import org.onlab.onos.net.flow.TrafficTreatment;
10 7
11 -import com.google.common.base.MoreObjects; 8 +import java.util.Objects;
9 +
10 +import static com.google.common.base.Preconditions.checkNotNull;
12 11
13 /** 12 /**
14 * Abstraction of point-to-point connectivity. 13 * Abstraction of point-to-point connectivity.
15 */ 14 */
16 public class PointToPointIntent extends ConnectivityIntent { 15 public class PointToPointIntent extends ConnectivityIntent {
17 16
18 - private final ConnectPoint ingressPort; 17 + private final ConnectPoint ingressPoint;
19 - private final ConnectPoint egressPort; 18 + private final ConnectPoint egressPoint;
20 19
21 /** 20 /**
22 * Creates a new point-to-point intent with the supplied ingress/egress 21 * Creates a new point-to-point intent with the supplied ingress/egress
23 * ports. 22 * ports.
24 * 23 *
25 - * @param id intent identifier 24 + * @param id intent identifier
26 - * @param match traffic match 25 + * @param selector traffic selector
27 - * @param action action 26 + * @param treatment treatment
28 - * @param ingressPort ingress port 27 + * @param ingressPoint ingress port
29 - * @param egressPort egress port 28 + * @param egressPoint egress port
30 - * @throws NullPointerException if {@code ingressPort} or {@code egressPort} is null. 29 + * @throws NullPointerException if {@code ingressPoint} or {@code egressPoints} is null.
31 */ 30 */
32 - public PointToPointIntent(IntentId id, TrafficSelector match, TrafficTreatment action, 31 + public PointToPointIntent(IntentId id, TrafficSelector selector,
33 - ConnectPoint ingressPort, ConnectPoint egressPort) { 32 + TrafficTreatment treatment,
34 - super(id, match, action); 33 + ConnectPoint ingressPoint,
35 - this.ingressPort = checkNotNull(ingressPort); 34 + ConnectPoint egressPoint) {
36 - this.egressPort = checkNotNull(egressPort); 35 + super(id, selector, treatment);
36 + this.ingressPoint = checkNotNull(ingressPoint);
37 + this.egressPoint = checkNotNull(egressPoint);
37 } 38 }
38 39
39 /** 40 /**
...@@ -41,8 +42,8 @@ public class PointToPointIntent extends ConnectivityIntent { ...@@ -41,8 +42,8 @@ public class PointToPointIntent extends ConnectivityIntent {
41 */ 42 */
42 protected PointToPointIntent() { 43 protected PointToPointIntent() {
43 super(); 44 super();
44 - this.ingressPort = null; 45 + this.ingressPoint = null;
45 - this.egressPort = null; 46 + this.egressPoint = null;
46 } 47 }
47 48
48 /** 49 /**
...@@ -51,8 +52,8 @@ public class PointToPointIntent extends ConnectivityIntent { ...@@ -51,8 +52,8 @@ public class PointToPointIntent extends ConnectivityIntent {
51 * 52 *
52 * @return ingress port 53 * @return ingress port
53 */ 54 */
54 - public ConnectPoint getIngressPort() { 55 + public ConnectPoint ingressPoint() {
55 - return ingressPort; 56 + return ingressPoint;
56 } 57 }
57 58
58 /** 59 /**
...@@ -60,8 +61,8 @@ public class PointToPointIntent extends ConnectivityIntent { ...@@ -60,8 +61,8 @@ public class PointToPointIntent extends ConnectivityIntent {
60 * 61 *
61 * @return egress port 62 * @return egress port
62 */ 63 */
63 - public ConnectPoint getEgressPort() { 64 + public ConnectPoint egressPoint() {
64 - return egressPort; 65 + return egressPoint;
65 } 66 }
66 67
67 @Override 68 @Override
...@@ -77,23 +78,23 @@ public class PointToPointIntent extends ConnectivityIntent { ...@@ -77,23 +78,23 @@ public class PointToPointIntent extends ConnectivityIntent {
77 } 78 }
78 79
79 PointToPointIntent that = (PointToPointIntent) o; 80 PointToPointIntent that = (PointToPointIntent) o;
80 - return Objects.equals(this.ingressPort, that.ingressPort) 81 + return Objects.equals(this.ingressPoint, that.ingressPoint)
81 - && Objects.equals(this.egressPort, that.egressPort); 82 + && Objects.equals(this.egressPoint, that.egressPoint);
82 } 83 }
83 84
84 @Override 85 @Override
85 public int hashCode() { 86 public int hashCode() {
86 - return Objects.hash(super.hashCode(), ingressPort, egressPort); 87 + return Objects.hash(super.hashCode(), ingressPoint, egressPoint);
87 } 88 }
88 89
89 @Override 90 @Override
90 public String toString() { 91 public String toString() {
91 return MoreObjects.toStringHelper(getClass()) 92 return MoreObjects.toStringHelper(getClass())
92 - .add("id", getId()) 93 + .add("id", id())
93 - .add("match", getTrafficSelector()) 94 + .add("match", selector())
94 - .add("action", getTrafficTreatment()) 95 + .add("action", treatment())
95 - .add("ingressPort", ingressPort) 96 + .add("ingressPoint", ingressPoint)
96 - .add("egressPort", egressPort) 97 + .add("egressPoints", egressPoint)
97 .toString(); 98 .toString();
98 } 99 }
99 100
......
1 package org.onlab.onos.net.intent; 1 package org.onlab.onos.net.intent;
2 2
3 -import static com.google.common.base.Preconditions.checkArgument; 3 +import com.google.common.base.MoreObjects;
4 -import static com.google.common.base.Preconditions.checkNotNull; 4 +import com.google.common.collect.Sets;
5 -
6 -import java.util.Objects;
7 -import java.util.Set;
8 -
9 import org.onlab.onos.net.ConnectPoint; 5 import org.onlab.onos.net.ConnectPoint;
10 import org.onlab.onos.net.flow.TrafficSelector; 6 import org.onlab.onos.net.flow.TrafficSelector;
11 import org.onlab.onos.net.flow.TrafficTreatment; 7 import org.onlab.onos.net.flow.TrafficTreatment;
12 8
13 -import com.google.common.base.MoreObjects; 9 +import java.util.Objects;
14 -import com.google.common.collect.Sets; 10 +import java.util.Set;
11 +
12 +import static com.google.common.base.Preconditions.checkArgument;
13 +import static com.google.common.base.Preconditions.checkNotNull;
15 14
16 /** 15 /**
17 * Abstraction of single source, multiple destination connectivity intent. 16 * Abstraction of single source, multiple destination connectivity intent.
18 */ 17 */
19 public class SinglePointToMultiPointIntent extends ConnectivityIntent { 18 public class SinglePointToMultiPointIntent extends ConnectivityIntent {
20 19
21 - private final ConnectPoint ingressPort; 20 + private final ConnectPoint ingressPoint;
22 - private final Set<ConnectPoint> egressPorts; 21 + private final Set<ConnectPoint> egressPoints;
23 22
24 /** 23 /**
25 * Creates a new single-to-multi point connectivity intent. 24 * Creates a new single-to-multi point connectivity intent.
26 * 25 *
27 - * @param id intent identifier 26 + * @param id intent identifier
28 - * @param match traffic match 27 + * @param selector traffic selector
29 - * @param action action 28 + * @param treatment treatment
30 - * @param ingressPort port on which traffic will ingress 29 + * @param ingressPoint port on which traffic will ingress
31 - * @param egressPorts set of ports on which traffic will egress 30 + * @param egressPoints set of ports on which traffic will egress
32 - * @throws NullPointerException if {@code ingressPort} or 31 + * @throws NullPointerException if {@code ingressPoint} or
33 - * {@code egressPorts} is null 32 + * {@code egressPoints} is null
34 - * @throws IllegalArgumentException if the size of {@code egressPorts} is 33 + * @throws IllegalArgumentException if the size of {@code egressPoints} is
35 - * not more than 1 34 + * not more than 1
36 */ 35 */
37 - public SinglePointToMultiPointIntent(IntentId id, TrafficSelector match, TrafficTreatment action, 36 + public SinglePointToMultiPointIntent(IntentId id, TrafficSelector selector,
38 - ConnectPoint ingressPort, 37 + TrafficTreatment treatment,
39 - Set<ConnectPoint> egressPorts) { 38 + ConnectPoint ingressPoint,
40 - super(id, match, action); 39 + Set<ConnectPoint> egressPoints) {
41 - 40 + super(id, selector, treatment);
42 - checkNotNull(egressPorts); 41 +
43 - checkArgument(!egressPorts.isEmpty(), 42 + checkNotNull(egressPoints);
44 - "there should be at least one egress port"); 43 + checkArgument(!egressPoints.isEmpty(),
45 - 44 + "there should be at least one egress port");
46 - this.ingressPort = checkNotNull(ingressPort); 45 +
47 - this.egressPorts = Sets.newHashSet(egressPorts); 46 + this.ingressPoint = checkNotNull(ingressPoint);
47 + this.egressPoints = Sets.newHashSet(egressPoints);
48 } 48 }
49 49
50 /** 50 /**
...@@ -52,8 +52,8 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent { ...@@ -52,8 +52,8 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent {
52 */ 52 */
53 protected SinglePointToMultiPointIntent() { 53 protected SinglePointToMultiPointIntent() {
54 super(); 54 super();
55 - this.ingressPort = null; 55 + this.ingressPoint = null;
56 - this.egressPorts = null; 56 + this.egressPoints = null;
57 } 57 }
58 58
59 /** 59 /**
...@@ -61,8 +61,8 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent { ...@@ -61,8 +61,8 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent {
61 * 61 *
62 * @return ingress port 62 * @return ingress port
63 */ 63 */
64 - public ConnectPoint getIngressPort() { 64 + public ConnectPoint ingressPoint() {
65 - return ingressPort; 65 + return ingressPoint;
66 } 66 }
67 67
68 /** 68 /**
...@@ -70,8 +70,8 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent { ...@@ -70,8 +70,8 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent {
70 * 70 *
71 * @return set of egress ports 71 * @return set of egress ports
72 */ 72 */
73 - public Set<ConnectPoint> getEgressPorts() { 73 + public Set<ConnectPoint> egressPoints() {
74 - return egressPorts; 74 + return egressPoints;
75 } 75 }
76 76
77 @Override 77 @Override
...@@ -87,23 +87,23 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent { ...@@ -87,23 +87,23 @@ public class SinglePointToMultiPointIntent extends ConnectivityIntent {
87 } 87 }
88 88
89 SinglePointToMultiPointIntent that = (SinglePointToMultiPointIntent) o; 89 SinglePointToMultiPointIntent that = (SinglePointToMultiPointIntent) o;
90 - return Objects.equals(this.ingressPort, that.ingressPort) 90 + return Objects.equals(this.ingressPoint, that.ingressPoint)
91 - && Objects.equals(this.egressPorts, that.egressPorts); 91 + && Objects.equals(this.egressPoints, that.egressPoints);
92 } 92 }
93 93
94 @Override 94 @Override
95 public int hashCode() { 95 public int hashCode() {
96 - return Objects.hash(super.hashCode(), ingressPort, egressPorts); 96 + return Objects.hash(super.hashCode(), ingressPoint, egressPoints);
97 } 97 }
98 98
99 @Override 99 @Override
100 public String toString() { 100 public String toString() {
101 return MoreObjects.toStringHelper(getClass()) 101 return MoreObjects.toStringHelper(getClass())
102 - .add("id", getId()) 102 + .add("id", id())
103 - .add("match", getTrafficSelector()) 103 + .add("match", selector())
104 - .add("action", getTrafficTreatment()) 104 + .add("action", treatment())
105 - .add("ingressPort", ingressPort) 105 + .add("ingressPoint", ingressPoint)
106 - .add("egressPort", egressPorts) 106 + .add("egressPort", egressPoints)
107 .toString(); 107 .toString();
108 } 108 }
109 109
......
1 /** 1 /**
2 - * Intent Package. TODO 2 + * Set of abstractions for conveying high-level intents for treatment of
3 + * selected network traffic by allowing applications to express the
4 + * <em>what</em> rather than the <em>how</em>. This makes such instructions
5 + * largely independent of topology and device specifics, thus allowing them to
6 + * survive topology mutations.
7 + * <p/>
8 + * The controller core provides a suite of built-in intents and their compilers
9 + * and installers. However, the intent framework is extensible in that it allows
10 + * additional intents and their compilers or installers to be added
11 + * dynamically at run-time. This allows others to enhance the initial arsenal of
12 + * connectivity and policy-based intents available in base controller software.
13 + * <p/>
14 + * The following diagram depicts the state transition diagram for each top-level intent:<br>
15 + * <img src="doc-files/intent-states.png" alt="ONOS intent states">
16 + * <p/>
17 + * The controller core accepts the intent specifications and translates them, via a
18 + * process referred to as intent compilation, to installable intents, which are
19 + * essentially actionable operations on the network environment.
20 + * These actions are carried out by intent installation process, which results
21 + * in some changes to the environment, e.g. tunnel links being provisioned,
22 + * flow rules being installed on the data-plane, optical lambdas being reserved.
23 + * <p/>
24 + * After an intent is submitted by an application, it will be sent immediately
25 + * (but asynchronously) into a compiling phase, then to installing phase and if
26 + * all goes according to plan into installed state. Once an application decides
27 + * it no longer wishes the intent to hold, it can withdraw it. This describes
28 + * the nominal flow. However, it may happen that some issue is encountered.
29 + * For example, an application may ask for an objective that is not currently
30 + * achievable, e.g. connectivity across to unconnected network segments.
31 + * If this is the case, the compiling phase may fail to produce a set of
32 + * installable intents and instead result in a failed compile. If this occurs,
33 + * only a change in the environment can trigger a transition back to the
34 + * compiling state.
35 + * <p/>
36 + * Similarly, an issue may be encountered during the installation phase in
37 + * which case the framework will attempt to recompile the intent to see if an
38 + * alternate approach is available. If so, the intent will be sent back to
39 + * installing phase. Otherwise, it will be parked in the failed state. Another
40 + * scenario that’s very likely to be encountered is where the intent is
41 + * successfully compiled and installed, but due to some topology event, such
42 + * as a downed or downgraded link, loss of throughput may occur or connectivity
43 + * may be lost altogether, thus impacting the viability of a previously
44 + * satisfied intent. If this occurs, the framework will attempt to recompile
45 + * the intent, and if an alternate approach is available, its installation
46 + * will be attempted. Otherwise, the original top-level intent will be parked
47 + * in the failed state.
48 + * <p/>
49 + * Please note that all *ing states, depicted in orange, are transitional and
50 + * are expected to last only a brief amount of time. The rest of the states
51 + * are parking states where the intent may spent some time; except for the
52 + * submitted state of course. There, the intent may pause, but only briefly,
53 + * while the system determines where to perform the compilation or while it
54 + * performs global recomputation/optimization across all prior intents.
3 */ 55 */
4 -
5 package org.onlab.onos.net.intent; 56 package org.onlab.onos.net.intent;
...\ No newline at end of file ...\ No newline at end of file
......
1 package org.onlab.onos.net.link; 1 package org.onlab.onos.net.link;
2 2
3 import org.onlab.onos.net.ConnectPoint; 3 import org.onlab.onos.net.ConnectPoint;
4 +import org.onlab.onos.net.Description;
4 import org.onlab.onos.net.Link; 5 import org.onlab.onos.net.Link;
5 6
6 /** 7 /**
7 * Describes an infrastructure link. 8 * Describes an infrastructure link.
8 */ 9 */
9 -public interface LinkDescription { 10 +public interface LinkDescription extends Description {
10 11
11 /** 12 /**
12 * Returns the link source. 13 * Returns the link source.
......
...@@ -24,7 +24,7 @@ public abstract class DefaultPacketContext implements PacketContext { ...@@ -24,7 +24,7 @@ public abstract class DefaultPacketContext implements PacketContext {
24 this.inPkt = inPkt; 24 this.inPkt = inPkt;
25 this.outPkt = outPkt; 25 this.outPkt = outPkt;
26 this.block = new AtomicBoolean(block); 26 this.block = new AtomicBoolean(block);
27 - this.builder = new DefaultTrafficTreatment.Builder(); 27 + this.builder = DefaultTrafficTreatment.builder();
28 } 28 }
29 29
30 @Override 30 @Override
......
...@@ -3,6 +3,7 @@ package org.onlab.onos.net.provider; ...@@ -3,6 +3,7 @@ package org.onlab.onos.net.provider;
3 import java.util.Objects; 3 import java.util.Objects;
4 4
5 import static com.google.common.base.MoreObjects.toStringHelper; 5 import static com.google.common.base.MoreObjects.toStringHelper;
6 +import static com.google.common.base.Preconditions.checkNotNull;
6 7
7 /** 8 /**
8 * External identity of a {@link org.onlab.onos.net.provider.Provider} family. 9 * External identity of a {@link org.onlab.onos.net.provider.Provider} family.
...@@ -19,10 +20,22 @@ import static com.google.common.base.MoreObjects.toStringHelper; ...@@ -19,10 +20,22 @@ import static com.google.common.base.MoreObjects.toStringHelper;
19 */ 20 */
20 public class ProviderId { 21 public class ProviderId {
21 22
23 + /**
24 + * Represents no provider ID.
25 + */
26 + public static final ProviderId NONE = new ProviderId();
27 +
22 private final String scheme; 28 private final String scheme;
23 private final String id; 29 private final String id;
24 private final boolean ancillary; 30 private final boolean ancillary;
25 31
32 + // For serialization
33 + private ProviderId() {
34 + scheme = null;
35 + id = null;
36 + ancillary = false;
37 + }
38 +
26 /** 39 /**
27 * Creates a new primary provider identifier from the specified string. 40 * Creates a new primary provider identifier from the specified string.
28 * The providers are expected to follow the reverse DNS convention, e.g. 41 * The providers are expected to follow the reverse DNS convention, e.g.
...@@ -45,8 +58,8 @@ public class ProviderId { ...@@ -45,8 +58,8 @@ public class ProviderId {
45 * @param ancillary ancillary provider indicator 58 * @param ancillary ancillary provider indicator
46 */ 59 */
47 public ProviderId(String scheme, String id, boolean ancillary) { 60 public ProviderId(String scheme, String id, boolean ancillary) {
48 - this.scheme = scheme; 61 + this.scheme = checkNotNull(scheme, "Scheme cannot be null");
49 - this.id = id; 62 + this.id = checkNotNull(id, "ID cannot be null");
50 this.ancillary = ancillary; 63 this.ancillary = ancillary;
51 } 64 }
52 65
......
1 package org.onlab.onos.net.proxyarp; 1 package org.onlab.onos.net.proxyarp;
2 2
3 +import org.onlab.onos.net.packet.PacketContext;
3 import org.onlab.packet.Ethernet; 4 import org.onlab.packet.Ethernet;
4 import org.onlab.packet.IpPrefix; 5 import org.onlab.packet.IpPrefix;
5 6
...@@ -33,4 +34,12 @@ public interface ProxyArpService { ...@@ -33,4 +34,12 @@ public interface ProxyArpService {
33 */ 34 */
34 void forward(Ethernet eth); 35 void forward(Ethernet eth);
35 36
37 + /**
38 + * Handles a arp packet.
39 + * Replies to arp requests and forwards request to the right place.
40 + * @param context the packet context to handle
41 + * @return true if handled, false otherwise.
42 + */
43 + boolean handleArp(PacketContext context);
44 +
36 } 45 }
......
1 package org.onlab.onos.net.topology; 1 package org.onlab.onos.net.topology;
2 2
3 import org.onlab.onos.event.AbstractEvent; 3 import org.onlab.onos.event.AbstractEvent;
4 +import org.onlab.onos.event.Event;
5 +
6 +import java.util.List;
4 7
5 /** 8 /**
6 * Describes network topology event. 9 * Describes network topology event.
7 */ 10 */
8 public class TopologyEvent extends AbstractEvent<TopologyEvent.Type, Topology> { 11 public class TopologyEvent extends AbstractEvent<TopologyEvent.Type, Topology> {
9 12
13 + private final List<Event> reasons;
14 +
10 /** 15 /**
11 * Type of topology events. 16 * Type of topology events.
12 */ 17 */
...@@ -23,9 +28,11 @@ public class TopologyEvent extends AbstractEvent<TopologyEvent.Type, Topology> { ...@@ -23,9 +28,11 @@ public class TopologyEvent extends AbstractEvent<TopologyEvent.Type, Topology> {
23 * 28 *
24 * @param type topology event type 29 * @param type topology event type
25 * @param topology event topology subject 30 * @param topology event topology subject
31 + * @param reasons list of events that triggered topology change
26 */ 32 */
27 - public TopologyEvent(Type type, Topology topology) { 33 + public TopologyEvent(Type type, Topology topology, List<Event> reasons) {
28 super(type, topology); 34 super(type, topology);
35 + this.reasons = reasons;
29 } 36 }
30 37
31 /** 38 /**
...@@ -33,10 +40,24 @@ public class TopologyEvent extends AbstractEvent<TopologyEvent.Type, Topology> { ...@@ -33,10 +40,24 @@ public class TopologyEvent extends AbstractEvent<TopologyEvent.Type, Topology> {
33 * 40 *
34 * @param type link event type 41 * @param type link event type
35 * @param topology event topology subject 42 * @param topology event topology subject
43 + * @param reasons list of events that triggered topology change
36 * @param time occurrence time 44 * @param time occurrence time
37 */ 45 */
38 - public TopologyEvent(Type type, Topology topology, long time) { 46 + public TopologyEvent(Type type, Topology topology, List<Event> reasons,
47 + long time) {
39 super(type, topology, time); 48 super(type, topology, time);
49 + this.reasons = reasons;
50 + }
51 +
52 +
53 + /**
54 + * Returns the list of events that triggered the topology change.
55 + *
56 + * @return list of events responsible for change in topology; null if
57 + * initial topology computation
58 + */
59 + public List<Event> reasons() {
60 + return reasons;
40 } 61 }
41 62
42 } 63 }
......
1 +package org.onlab.onos.store;
2 +
3 +import org.onlab.onos.cluster.MastershipTerm;
4 +import org.onlab.onos.net.DeviceId;
5 +
6 +//TODO: Consider renaming to DeviceClockProviderService?
7 +/**
8 +* Interface for feeding term information to a logical clock service
9 +* that vends per device timestamps.
10 +*/
11 +public interface ClockProviderService {
12 +
13 + /**
14 + * Updates the mastership term for the specified deviceId.
15 + *
16 + * @param deviceId device identifier.
17 + * @param term mastership term.
18 + */
19 + public void setMastershipTerm(DeviceId deviceId, MastershipTerm term);
20 +}
1 package org.onlab.onos.store; 1 package org.onlab.onos.store;
2 2
3 -import org.onlab.onos.cluster.MastershipTerm;
4 import org.onlab.onos.net.DeviceId; 3 import org.onlab.onos.net.DeviceId;
5 4
6 // TODO: Consider renaming to DeviceClockService? 5 // TODO: Consider renaming to DeviceClockService?
...@@ -15,12 +14,4 @@ public interface ClockService { ...@@ -15,12 +14,4 @@ public interface ClockService {
15 * @return timestamp. 14 * @return timestamp.
16 */ 15 */
17 public Timestamp getTimestamp(DeviceId deviceId); 16 public Timestamp getTimestamp(DeviceId deviceId);
18 -
19 - // TODO: Should this be here or separate as Admin service, etc.?
20 - /**
21 - * Updates the mastership term for the specified deviceId.
22 - * @param deviceId device identifier.
23 - * @param term mastership term.
24 - */
25 - public void setMastershipTerm(DeviceId deviceId, MastershipTerm term);
26 } 17 }
......
...@@ -2,7 +2,15 @@ package org.onlab.onos.store; ...@@ -2,7 +2,15 @@ package org.onlab.onos.store;
2 2
3 /** 3 /**
4 * Opaque version structure. 4 * Opaque version structure.
5 + * <p>
6 + * Classes implementing this interface must also implement
7 + * {@link #hashCode()} and {@link #equals(Object)}.
5 */ 8 */
6 public interface Timestamp extends Comparable<Timestamp> { 9 public interface Timestamp extends Comparable<Timestamp> {
7 10
11 + @Override
12 + public abstract int hashCode();
13 +
14 + @Override
15 + public abstract boolean equals(Object obj);
8 } 16 }
......
1 +package org.onlab.onos;
2 +
3 +import com.google.common.testing.EqualsTester;
4 +import org.junit.Test;
5 +
6 +import static org.junit.Assert.*;
7 +import static org.onlab.onos.Version.version;
8 +
9 +/**
10 + * Tests of the version descriptor.
11 + */
12 +public class VersionTest {
13 +
14 + @Test
15 + public void fromParts() {
16 + Version v = version(1, 2, 3, "4321");
17 + assertEquals("wrong major", 1, v.major());
18 + assertEquals("wrong minor", 2, v.minor());
19 + assertEquals("wrong patch", 3, v.patch());
20 + assertEquals("wrong build", "4321", v.build());
21 + }
22 +
23 + @Test
24 + public void fromString() {
25 + Version v = version("1.2.3.4321");
26 + assertEquals("wrong major", 1, v.major());
27 + assertEquals("wrong minor", 2, v.minor());
28 + assertEquals("wrong patch", 3, v.patch());
29 + assertEquals("wrong build", "4321", v.build());
30 + }
31 +
32 + @Test
33 + public void snapshot() {
34 + Version v = version("1.2.3-SNAPSHOT");
35 + assertEquals("wrong major", 1, v.major());
36 + assertEquals("wrong minor", 2, v.minor());
37 + assertEquals("wrong patch", 3, v.patch());
38 + assertEquals("wrong build", "SNAPSHOT", v.build());
39 + }
40 +
41 + @Test
42 + public void testEquals() {
43 + new EqualsTester()
44 + .addEqualityGroup(version("1.2.3.4321"), version(1, 2, 3, "4321"))
45 + .addEqualityGroup(version("1.9.3.4321"), version(1, 9, 3, "4321"))
46 + .addEqualityGroup(version("1.2.8.4321"), version(1, 2, 8, "4321"))
47 + .addEqualityGroup(version("1.2.3.x"), version(1, 2, 3, "x"))
48 + .testEquals();
49 + }
50 +}
...\ No newline at end of file ...\ No newline at end of file
...@@ -33,4 +33,4 @@ public class ConnectPointTest { ...@@ -33,4 +33,4 @@ public class ConnectPointTest {
33 .addEqualityGroup(new ConnectPoint(DID2, P1), new ConnectPoint(DID2, P1)) 33 .addEqualityGroup(new ConnectPoint(DID2, P1), new ConnectPoint(DID2, P1))
34 .testEquals(); 34 .testEquals();
35 } 35 }
36 -}
...\ No newline at end of file ...\ No newline at end of file
36 +}
......
...@@ -36,6 +36,23 @@ public class DefaultAnnotationsTest { ...@@ -36,6 +36,23 @@ public class DefaultAnnotationsTest {
36 } 36 }
37 37
38 @Test 38 @Test
39 + public void union() {
40 + annotations = builder().set("foo", "1").set("bar", "2").remove("buz").build();
41 + assertEquals("incorrect keys", of("foo", "bar", "buz"), annotations.keys());
42 +
43 + SparseAnnotations updates = builder().remove("foo").set("bar", "3").set("goo", "4").remove("fuzz").build();
44 +
45 + SparseAnnotations result = DefaultAnnotations.union(annotations, updates);
46 +
47 + assertTrue("remove instruction in original remains", result.isRemoved("buz"));
48 + assertTrue("remove instruction in update remains", result.isRemoved("fuzz"));
49 + assertEquals("incorrect keys", of("buz", "goo", "bar", "fuzz"), result.keys());
50 + assertNull("incorrect value", result.value("foo"));
51 + assertEquals("incorrect value", "3", result.value("bar"));
52 + assertEquals("incorrect value", "4", result.value("goo"));
53 + }
54 +
55 + @Test
39 public void merge() { 56 public void merge() {
40 annotations = builder().set("foo", "1").set("bar", "2").build(); 57 annotations = builder().set("foo", "1").set("bar", "2").build();
41 assertEquals("incorrect keys", of("foo", "bar"), annotations.keys()); 58 assertEquals("incorrect keys", of("foo", "bar"), annotations.keys());
...@@ -65,4 +82,4 @@ public class DefaultAnnotationsTest { ...@@ -65,4 +82,4 @@ public class DefaultAnnotationsTest {
65 DefaultAnnotations.merge(null, null); 82 DefaultAnnotations.merge(null, null);
66 } 83 }
67 84
68 -}
...\ No newline at end of file ...\ No newline at end of file
85 +}
......
...@@ -58,7 +58,5 @@ public class DefaultDeviceTest { ...@@ -58,7 +58,5 @@ public class DefaultDeviceTest {
58 assertEquals("incorrect hw", HW, device.hwVersion()); 58 assertEquals("incorrect hw", HW, device.hwVersion());
59 assertEquals("incorrect sw", SW, device.swVersion()); 59 assertEquals("incorrect sw", SW, device.swVersion());
60 assertEquals("incorrect serial", SN1, device.serialNumber()); 60 assertEquals("incorrect serial", SN1, device.serialNumber());
61 - assertEquals("incorrect serial", SN1, device.serialNumber());
62 } 61 }
63 -
64 -}
...\ No newline at end of file ...\ No newline at end of file
62 +}
......
...@@ -5,6 +5,7 @@ import org.junit.Test; ...@@ -5,6 +5,7 @@ import org.junit.Test;
5 import org.onlab.onos.net.provider.ProviderId; 5 import org.onlab.onos.net.provider.ProviderId;
6 6
7 import static org.junit.Assert.assertEquals; 7 import static org.junit.Assert.assertEquals;
8 +import static org.onlab.onos.net.DefaultEdgeLink.createEdgeLink;
8 import static org.onlab.onos.net.DefaultLinkTest.cp; 9 import static org.onlab.onos.net.DefaultLinkTest.cp;
9 import static org.onlab.onos.net.DeviceId.deviceId; 10 import static org.onlab.onos.net.DeviceId.deviceId;
10 import static org.onlab.onos.net.HostId.hostId; 11 import static org.onlab.onos.net.HostId.hostId;
...@@ -55,4 +56,24 @@ public class DefaultEdgeLinkTest { ...@@ -55,4 +56,24 @@ public class DefaultEdgeLinkTest {
55 assertEquals("incorrect time", 123L, link.hostLocation().time()); 56 assertEquals("incorrect time", 123L, link.hostLocation().time());
56 } 57 }
57 58
59 + @Test
60 + public void phantomIngress() {
61 + HostLocation hostLocation = new HostLocation(DID1, P1, 123L);
62 + EdgeLink link = createEdgeLink(hostLocation, true);
63 + assertEquals("incorrect dst", hostLocation, link.dst());
64 + assertEquals("incorrect type", Link.Type.EDGE, link.type());
65 + assertEquals("incorrect connect point", hostLocation, link.hostLocation());
66 + assertEquals("incorrect time", 123L, link.hostLocation().time());
67 + }
68 +
69 + @Test
70 + public void phantomEgress() {
71 + ConnectPoint hostLocation = new ConnectPoint(DID1, P1);
72 + EdgeLink link = createEdgeLink(hostLocation, false);
73 + assertEquals("incorrect src", hostLocation, link.src());
74 + assertEquals("incorrect type", Link.Type.EDGE, link.type());
75 + assertEquals("incorrect connect point", hostLocation, link.hostLocation());
76 + assertEquals("incorrect time", 0L, link.hostLocation().time());
77 + }
78 +
58 } 79 }
......
...@@ -39,7 +39,7 @@ public class DeviceEventTest extends AbstractEventTest { ...@@ -39,7 +39,7 @@ public class DeviceEventTest extends AbstractEventTest {
39 Device device = createDevice(); 39 Device device = createDevice();
40 Port port = new DefaultPort(device, PortNumber.portNumber(123), true); 40 Port port = new DefaultPort(device, PortNumber.portNumber(123), true);
41 long before = System.currentTimeMillis(); 41 long before = System.currentTimeMillis();
42 - DeviceEvent event = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, device); 42 + DeviceEvent event = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, device, port);
43 long after = System.currentTimeMillis(); 43 long after = System.currentTimeMillis();
44 validateEvent(event, DeviceEvent.Type.DEVICE_ADDED, device, before, after); 44 validateEvent(event, DeviceEvent.Type.DEVICE_ADDED, device, before, after);
45 } 45 }
......
...@@ -16,8 +16,8 @@ import org.onlab.onos.net.flow.TrafficTreatment; ...@@ -16,8 +16,8 @@ import org.onlab.onos.net.flow.TrafficTreatment;
16 public abstract class ConnectivityIntentTest extends IntentTest { 16 public abstract class ConnectivityIntentTest extends IntentTest {
17 17
18 public static final IntentId IID = new IntentId(123); 18 public static final IntentId IID = new IntentId(123);
19 - public static final TrafficSelector MATCH = (new DefaultTrafficSelector.Builder()).build(); 19 + public static final TrafficSelector MATCH = DefaultTrafficSelector.builder().build();
20 - public static final TrafficTreatment NOP = (new DefaultTrafficTreatment.Builder()).build(); 20 + public static final TrafficTreatment NOP = DefaultTrafficTreatment.builder().build();
21 21
22 public static final ConnectPoint P1 = new ConnectPoint(DeviceId.deviceId("111"), PortNumber.portNumber(0x1)); 22 public static final ConnectPoint P1 = new ConnectPoint(DeviceId.deviceId("111"), PortNumber.portNumber(0x1));
23 public static final ConnectPoint P2 = new ConnectPoint(DeviceId.deviceId("222"), PortNumber.portNumber(0x2)); 23 public static final ConnectPoint P2 = new ConnectPoint(DeviceId.deviceId("222"), PortNumber.portNumber(0x2));
......
...@@ -11,19 +11,19 @@ import java.util.concurrent.ExecutorService; ...@@ -11,19 +11,19 @@ import java.util.concurrent.ExecutorService;
11 import java.util.concurrent.Executors; 11 import java.util.concurrent.Executors;
12 12
13 /** 13 /**
14 - * Fake implementation of the intent service to assist in developing tests 14 + * Fake implementation of the intent service to assist in developing tests of
15 - * of the interface contract. 15 + * the interface contract.
16 */ 16 */
17 public class FakeIntentManager implements TestableIntentService { 17 public class FakeIntentManager implements TestableIntentService {
18 18
19 private final Map<IntentId, Intent> intents = new HashMap<>(); 19 private final Map<IntentId, Intent> intents = new HashMap<>();
20 private final Map<IntentId, IntentState> intentStates = new HashMap<>(); 20 private final Map<IntentId, IntentState> intentStates = new HashMap<>();
21 private final Map<IntentId, List<InstallableIntent>> installables = new HashMap<>(); 21 private final Map<IntentId, List<InstallableIntent>> installables = new HashMap<>();
22 - private final Set<IntentEventListener> listeners = new HashSet<>(); 22 + private final Set<IntentListener> listeners = new HashSet<>();
23 23
24 private final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers = new HashMap<>(); 24 private final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers = new HashMap<>();
25 - private final Map<Class<? extends InstallableIntent>, 25 + private final Map<Class<? extends InstallableIntent>, IntentInstaller<? extends InstallableIntent>> installers
26 - IntentInstaller<? extends InstallableIntent>> installers = new HashMap<>(); 26 + = new HashMap<>();
27 27
28 private final ExecutorService executor = Executors.newSingleThreadExecutor(); 28 private final ExecutorService executor = Executors.newSingleThreadExecutor();
29 private final List<IntentException> exceptions = new ArrayList<>(); 29 private final List<IntentException> exceptions = new ArrayList<>();
...@@ -40,8 +40,7 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -40,8 +40,7 @@ public class FakeIntentManager implements TestableIntentService {
40 @Override 40 @Override
41 public void run() { 41 public void run() {
42 try { 42 try {
43 - List<InstallableIntent> installable = compileIntent(intent); 43 + executeCompilingPhase(intent);
44 - installIntents(intent, installable);
45 } catch (IntentException e) { 44 } catch (IntentException e) {
46 exceptions.add(e); 45 exceptions.add(e);
47 } 46 }
...@@ -55,8 +54,8 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -55,8 +54,8 @@ public class FakeIntentManager implements TestableIntentService {
55 @Override 54 @Override
56 public void run() { 55 public void run() {
57 try { 56 try {
58 - List<InstallableIntent> installable = getInstallable(intent.getId()); 57 + List<InstallableIntent> installable = getInstallable(intent.id());
59 - uninstallIntents(intent, installable); 58 + executeWithdrawingPhase(intent, installable);
60 } catch (IntentException e) { 59 } catch (IntentException e) {
61 exceptions.add(e); 60 exceptions.add(e);
62 } 61 }
...@@ -76,61 +75,68 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -76,61 +75,68 @@ public class FakeIntentManager implements TestableIntentService {
76 75
77 private <T extends InstallableIntent> IntentInstaller<T> getInstaller(T intent) { 76 private <T extends InstallableIntent> IntentInstaller<T> getInstaller(T intent) {
78 @SuppressWarnings("unchecked") 77 @SuppressWarnings("unchecked")
79 - IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent.getClass()); 78 + IntentInstaller<T> installer = (IntentInstaller<T>) installers.get(intent
79 + .getClass());
80 if (installer == null) { 80 if (installer == null) {
81 throw new IntentException("no installer for class " + intent.getClass()); 81 throw new IntentException("no installer for class " + intent.getClass());
82 } 82 }
83 return installer; 83 return installer;
84 } 84 }
85 85
86 - private <T extends Intent> List<InstallableIntent> compileIntent(T intent) { 86 + private <T extends Intent> void executeCompilingPhase(T intent) {
87 + setState(intent, IntentState.COMPILING);
87 try { 88 try {
88 // For the fake, we compile using a single level pass 89 // For the fake, we compile using a single level pass
89 List<InstallableIntent> installable = new ArrayList<>(); 90 List<InstallableIntent> installable = new ArrayList<>();
90 for (Intent compiled : getCompiler(intent).compile(intent)) { 91 for (Intent compiled : getCompiler(intent).compile(intent)) {
91 installable.add((InstallableIntent) compiled); 92 installable.add((InstallableIntent) compiled);
92 } 93 }
93 - setState(intent, IntentState.COMPILED); 94 + executeInstallingPhase(intent, installable);
94 - return installable; 95 +
95 } catch (IntentException e) { 96 } catch (IntentException e) {
96 setState(intent, IntentState.FAILED); 97 setState(intent, IntentState.FAILED);
97 - throw e; 98 + dispatch(new IntentEvent(IntentEvent.Type.FAILED, intent));
98 } 99 }
99 } 100 }
100 101
101 - private void installIntents(Intent intent, List<InstallableIntent> installable) { 102 + private void executeInstallingPhase(Intent intent,
103 + List<InstallableIntent> installable) {
104 + setState(intent, IntentState.INSTALLING);
102 try { 105 try {
103 for (InstallableIntent ii : installable) { 106 for (InstallableIntent ii : installable) {
104 registerSubclassInstallerIfNeeded(ii); 107 registerSubclassInstallerIfNeeded(ii);
105 getInstaller(ii).install(ii); 108 getInstaller(ii).install(ii);
106 } 109 }
107 setState(intent, IntentState.INSTALLED); 110 setState(intent, IntentState.INSTALLED);
108 - putInstallable(intent.getId(), installable); 111 + putInstallable(intent.id(), installable);
112 + dispatch(new IntentEvent(IntentEvent.Type.INSTALLED, intent));
113 +
109 } catch (IntentException e) { 114 } catch (IntentException e) {
110 setState(intent, IntentState.FAILED); 115 setState(intent, IntentState.FAILED);
111 - throw e; 116 + dispatch(new IntentEvent(IntentEvent.Type.FAILED, intent));
112 } 117 }
113 } 118 }
114 119
115 - private void uninstallIntents(Intent intent, List<InstallableIntent> installable) { 120 + private void executeWithdrawingPhase(Intent intent,
121 + List<InstallableIntent> installable) {
122 + setState(intent, IntentState.WITHDRAWING);
116 try { 123 try {
117 for (InstallableIntent ii : installable) { 124 for (InstallableIntent ii : installable) {
118 getInstaller(ii).uninstall(ii); 125 getInstaller(ii).uninstall(ii);
119 } 126 }
127 + removeInstallable(intent.id());
120 setState(intent, IntentState.WITHDRAWN); 128 setState(intent, IntentState.WITHDRAWN);
121 - removeInstallable(intent.getId()); 129 + dispatch(new IntentEvent(IntentEvent.Type.WITHDRAWN, intent));
122 } catch (IntentException e) { 130 } catch (IntentException e) {
131 + // FIXME: Rework this to always go from WITHDRAWING to WITHDRAWN!
123 setState(intent, IntentState.FAILED); 132 setState(intent, IntentState.FAILED);
124 - throw e; 133 + dispatch(new IntentEvent(IntentEvent.Type.FAILED, intent));
125 } 134 }
126 } 135 }
127 136
128 -
129 // Sets the internal state for the given intent and dispatches an event 137 // Sets the internal state for the given intent and dispatches an event
130 private void setState(Intent intent, IntentState state) { 138 private void setState(Intent intent, IntentState state) {
131 - IntentState previous = intentStates.get(intent.getId()); 139 + intentStates.put(intent.id(), state);
132 - intentStates.put(intent.getId(), state);
133 - dispatch(new IntentEvent(intent, state, previous, System.currentTimeMillis()));
134 } 140 }
135 141
136 private void putInstallable(IntentId id, List<InstallableIntent> installable) { 142 private void putInstallable(IntentId id, List<InstallableIntent> installable) {
...@@ -152,15 +158,15 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -152,15 +158,15 @@ public class FakeIntentManager implements TestableIntentService {
152 158
153 @Override 159 @Override
154 public void submit(Intent intent) { 160 public void submit(Intent intent) {
155 - intents.put(intent.getId(), intent); 161 + intents.put(intent.id(), intent);
156 setState(intent, IntentState.SUBMITTED); 162 setState(intent, IntentState.SUBMITTED);
163 + dispatch(new IntentEvent(IntentEvent.Type.SUBMITTED, intent));
157 executeSubmit(intent); 164 executeSubmit(intent);
158 } 165 }
159 166
160 @Override 167 @Override
161 public void withdraw(Intent intent) { 168 public void withdraw(Intent intent) {
162 - intents.remove(intent.getId()); 169 + intents.remove(intent.id());
163 - setState(intent, IntentState.WITHDRAWING);
164 executeWithdraw(intent); 170 executeWithdraw(intent);
165 } 171 }
166 172
...@@ -175,6 +181,11 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -175,6 +181,11 @@ public class FakeIntentManager implements TestableIntentService {
175 } 181 }
176 182
177 @Override 183 @Override
184 + public long getIntentCount() {
185 + return intents.size();
186 + }
187 +
188 + @Override
178 public Intent getIntent(IntentId id) { 189 public Intent getIntent(IntentId id) {
179 return intents.get(id); 190 return intents.get(id);
180 } 191 }
...@@ -185,23 +196,24 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -185,23 +196,24 @@ public class FakeIntentManager implements TestableIntentService {
185 } 196 }
186 197
187 @Override 198 @Override
188 - public void addListener(IntentEventListener listener) { 199 + public void addListener(IntentListener listener) {
189 listeners.add(listener); 200 listeners.add(listener);
190 } 201 }
191 202
192 @Override 203 @Override
193 - public void removeListener(IntentEventListener listener) { 204 + public void removeListener(IntentListener listener) {
194 listeners.remove(listener); 205 listeners.remove(listener);
195 } 206 }
196 207
197 private void dispatch(IntentEvent event) { 208 private void dispatch(IntentEvent event) {
198 - for (IntentEventListener listener : listeners) { 209 + for (IntentListener listener : listeners) {
199 listener.event(event); 210 listener.event(event);
200 } 211 }
201 } 212 }
202 213
203 @Override 214 @Override
204 - public <T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler) { 215 + public <T extends Intent> void registerCompiler(Class<T> cls,
216 + IntentCompiler<T> compiler) {
205 compilers.put(cls, compiler); 217 compilers.put(cls, compiler);
206 } 218 }
207 219
...@@ -216,7 +228,8 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -216,7 +228,8 @@ public class FakeIntentManager implements TestableIntentService {
216 } 228 }
217 229
218 @Override 230 @Override
219 - public <T extends InstallableIntent> void registerInstaller(Class<T> cls, IntentInstaller<T> installer) { 231 + public <T extends InstallableIntent> void registerInstaller(Class<T> cls,
232 + IntentInstaller<T> installer) {
220 installers.put(cls, installer); 233 installers.put(cls, installer);
221 } 234 }
222 235
...@@ -227,7 +240,7 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -227,7 +240,7 @@ public class FakeIntentManager implements TestableIntentService {
227 240
228 @Override 241 @Override
229 public Map<Class<? extends InstallableIntent>, 242 public Map<Class<? extends InstallableIntent>,
230 - IntentInstaller<? extends InstallableIntent>> getInstallers() { 243 + IntentInstaller<? extends InstallableIntent>> getInstallers() {
231 return Collections.unmodifiableMap(installers); 244 return Collections.unmodifiableMap(installers);
232 } 245 }
233 246
...@@ -252,7 +265,8 @@ public class FakeIntentManager implements TestableIntentService { ...@@ -252,7 +265,8 @@ public class FakeIntentManager implements TestableIntentService {
252 if (!installers.containsKey(intent.getClass())) { 265 if (!installers.containsKey(intent.getClass())) {
253 Class<?> cls = intent.getClass(); 266 Class<?> cls = intent.getClass();
254 while (cls != Object.class) { 267 while (cls != Object.class) {
255 - // As long as we're within the InstallableIntent class descendants 268 + // As long as we're within the InstallableIntent class
269 + // descendants
256 if (InstallableIntent.class.isAssignableFrom(cls)) { 270 if (InstallableIntent.class.isAssignableFrom(cls)) {
257 IntentInstaller<?> installer = installers.get(cls); 271 IntentInstaller<?> installer = installers.get(cls);
258 if (installer != null) { 272 if (installer != null) {
......
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.