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 | } | ... | ... |
apps/ifwd/pom.xml
0 → 100644
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 | +} |
... | @@ -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 | ... | ... |
apps/proxyarp/pom.xml
0 → 100644
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 | +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 | } | ... | ... |
158 KB
... | @@ -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 | +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 | +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 & 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 & action pair to be applied to | 8 | * Represents a generalized match & 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 & withdraw operations. Such a batch is | 29 | * Submits a batch of submit & 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; | 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.
core/net/src/main/java/org/onlab/onos/net/intent/impl/AbstractBlockAllocatorBasedIdGenerator.java
0 → 100644
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.
core/net/src/main/java/org/onlab/onos/net/intent/impl/IdBlockAllocatorBasedIntentIdGenerator.java
0 → 100644
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.
core/net/src/test/java/org/onlab/onos/net/device/impl/DistributedDeviceManagerTest.java
deleted
100644 → 0
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.
core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/impl/package-info.java
0 → 100644
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.
core/store/dist/src/main/java/org/onlab/onos/store/device/impl/GossipDeviceStoreMessageSubjects.java
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InternalDeviceEventSerializer.java
0 → 100644
This diff is collapsed. Click to expand it.
core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InternalDeviceOfflineEvent.java
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InternalDeviceRemovedEvent.java
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InternalPortEventSerializer.java
0 → 100644
This diff is collapsed. Click to expand it.
core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InternalPortStatusEvent.java
0 → 100644
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.
core/store/dist/src/main/java/org/onlab/onos/store/serializers/ClusterMessageSerializer.java
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
core/store/dist/src/main/java/org/onlab/onos/store/serializers/MessageSubjectSerializer.java
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
core/store/dist/src/test/java/org/onlab/onos/store/cluster/impl/ClusterCommunicationManagerTest.java
This diff is collapsed. Click to expand it.
core/store/dist/src/test/java/org/onlab/onos/store/common/impl/MastershipBasedTimestampTest.java
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
core/store/dist/src/test/java/org/onlab/onos/store/device/impl/GossipDeviceStoreTest.java
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
core/store/serializers/src/main/java/org/onlab/onos/store/serializers/IpAddressSerializer.java
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
core/store/serializers/src/main/java/org/onlab/onos/store/serializers/KryoSerializer.java
0 → 100644
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.
core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleIntentStore.java
0 → 100644
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.
features/old-features.xml
deleted
100644 → 0
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.
providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
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.
tools/test/bin/onos-push-update-bundle
0 → 100755
This diff is collapsed. Click to expand it.
tools/test/topos/tower.py
0 → 100644
This diff is collapsed. Click to expand it.
tools/test/topos/tt.py
0 → 100644
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment