Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
Showing
117 changed files
with
1746 additions
and
429 deletions
... | @@ -16,14 +16,24 @@ | ... | @@ -16,14 +16,24 @@ |
16 | package org.onlab.onos.calendar; | 16 | package org.onlab.onos.calendar; |
17 | 17 | ||
18 | import java.net.URI; | 18 | import java.net.URI; |
19 | +import java.util.concurrent.CountDownLatch; | ||
20 | +import java.util.concurrent.TimeUnit; | ||
21 | + | ||
19 | import org.onlab.onos.net.ConnectPoint; | 22 | import org.onlab.onos.net.ConnectPoint; |
20 | import org.onlab.onos.net.DeviceId; | 23 | import org.onlab.onos.net.DeviceId; |
24 | +import org.onlab.onos.net.intent.Intent; | ||
25 | +import org.onlab.onos.net.intent.IntentEvent; | ||
26 | +import org.onlab.onos.net.intent.IntentId; | ||
27 | +import org.onlab.onos.net.intent.IntentListener; | ||
21 | import org.onlab.onos.net.intent.IntentService; | 28 | import org.onlab.onos.net.intent.IntentService; |
29 | +import org.onlab.onos.net.intent.IntentState; | ||
22 | import org.onlab.rest.BaseResource; | 30 | import org.onlab.rest.BaseResource; |
31 | + | ||
23 | import javax.ws.rs.POST; | 32 | import javax.ws.rs.POST; |
24 | import javax.ws.rs.DELETE; | 33 | import javax.ws.rs.DELETE; |
25 | import javax.ws.rs.PathParam; | 34 | import javax.ws.rs.PathParam; |
26 | import javax.ws.rs.core.Response; | 35 | import javax.ws.rs.core.Response; |
36 | + | ||
27 | import org.onlab.onos.core.ApplicationId; | 37 | import org.onlab.onos.core.ApplicationId; |
28 | import org.onlab.onos.core.CoreService; | 38 | import org.onlab.onos.core.CoreService; |
29 | import org.onlab.onos.net.flow.DefaultTrafficSelector; | 39 | import org.onlab.onos.net.flow.DefaultTrafficSelector; |
... | @@ -31,10 +41,15 @@ import org.onlab.onos.net.flow.TrafficSelector; | ... | @@ -31,10 +41,15 @@ import org.onlab.onos.net.flow.TrafficSelector; |
31 | import org.onlab.onos.net.flow.TrafficTreatment; | 41 | import org.onlab.onos.net.flow.TrafficTreatment; |
32 | import org.onlab.onos.net.intent.PointToPointIntent; | 42 | import org.onlab.onos.net.intent.PointToPointIntent; |
33 | import org.onlab.packet.Ethernet; | 43 | import org.onlab.packet.Ethernet; |
44 | + | ||
34 | import static org.onlab.onos.net.PortNumber.portNumber; | 45 | import static org.onlab.onos.net.PortNumber.portNumber; |
35 | import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder; | 46 | import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder; |
36 | 47 | ||
48 | +import static org.onlab.onos.net.intent.IntentState.FAILED; | ||
49 | +import static org.onlab.onos.net.intent.IntentState.INSTALLED; | ||
50 | +import static org.onlab.onos.net.intent.IntentState.WITHDRAWN; | ||
37 | import static org.slf4j.LoggerFactory.getLogger; | 51 | import static org.slf4j.LoggerFactory.getLogger; |
52 | + | ||
38 | import org.slf4j.Logger; | 53 | import org.slf4j.Logger; |
39 | 54 | ||
40 | /** | 55 | /** |
... | @@ -44,6 +59,7 @@ import org.slf4j.Logger; | ... | @@ -44,6 +59,7 @@ import org.slf4j.Logger; |
44 | public class BandwidthCalendarResource extends BaseResource { | 59 | public class BandwidthCalendarResource extends BaseResource { |
45 | 60 | ||
46 | private static final Logger log = getLogger(BandwidthCalendarResource.class); | 61 | private static final Logger log = getLogger(BandwidthCalendarResource.class); |
62 | + private static final long TIMEOUT = 5; // seconds | ||
47 | 63 | ||
48 | @javax.ws.rs.Path("/{src}/{dst}/{srcPort}/{dstPort}/{bandwidth}") | 64 | @javax.ws.rs.Path("/{src}/{dst}/{srcPort}/{dstPort}/{bandwidth}") |
49 | @POST | 65 | @POST |
... | @@ -68,24 +84,38 @@ public class BandwidthCalendarResource extends BaseResource { | ... | @@ -68,24 +84,38 @@ public class BandwidthCalendarResource extends BaseResource { |
68 | PointToPointIntent intentP2P = | 84 | PointToPointIntent intentP2P = |
69 | new PointToPointIntent(appId(), selector, treatment, | 85 | new PointToPointIntent(appId(), selector, treatment, |
70 | srcPoint, dstPoint); | 86 | srcPoint, dstPoint); |
71 | - service.submit(intentP2P); | ||
72 | - log.info("Submitted Calendar App intent: src = " + src + "dest = " + dst | ||
73 | - + "srcPort = " + srcPort + "destPort" + dstPort + "intentID = " + intentP2P.id().toString()); | ||
74 | - String reply = intentP2P.id().toString() + "\n"; | ||
75 | 87 | ||
88 | + CountDownLatch latch = new CountDownLatch(1); | ||
89 | + InternalIntentListener listener = new InternalIntentListener(intentP2P, service, latch); | ||
90 | + service.addListener(listener); | ||
91 | + service.submit(intentP2P); | ||
92 | + try { | ||
93 | + if (latch.await(TIMEOUT, TimeUnit.SECONDS)) { | ||
94 | + log.info("Submitted Calendar App intent: src = {}; dst = {}; " + | ||
95 | + "srcPort = {}; dstPort = {}; intentID = {}", | ||
96 | + src, dst, srcPort, dstPort, intentP2P.id()); | ||
97 | + String reply = intentP2P.id() + " " + listener.getState() + "\n"; | ||
76 | return Response.ok(reply).build(); | 98 | return Response.ok(reply).build(); |
77 | } | 99 | } |
100 | + } catch (InterruptedException e) { | ||
101 | + log.warn("Interrupted while waiting for intent {} status", intentP2P.id()); | ||
102 | + } | ||
103 | + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); | ||
104 | + } | ||
78 | 105 | ||
79 | @javax.ws.rs.Path("/cancellation/{intentId}") | 106 | @javax.ws.rs.Path("/cancellation/{intentId}") |
80 | @DELETE | 107 | @DELETE |
81 | public Response withdrawIntent(@PathParam("intentId") String intentId) { | 108 | public Response withdrawIntent(@PathParam("intentId") String intentId) { |
82 | - | 109 | + log.info("Receiving Teardown request for {}", intentId); |
83 | - log.info("Receiving Teardown request..."); | 110 | + IntentService service = get(IntentService.class); |
84 | - log.info("Withdraw intentId = {} ", intentId); | 111 | + Intent intent = service.getIntent(IntentId.valueOf(Long.parseLong(intentId))); |
85 | - | 112 | + if (intent != null) { |
113 | + service.withdraw(intent); | ||
86 | String reply = "ok\n"; | 114 | String reply = "ok\n"; |
87 | return Response.ok(reply).build(); | 115 | return Response.ok(reply).build(); |
88 | } | 116 | } |
117 | + return Response.status(Response.Status.NOT_FOUND).build(); | ||
118 | + } | ||
89 | 119 | ||
90 | @javax.ws.rs.Path("/modification/{intentId}/{bandwidth}") | 120 | @javax.ws.rs.Path("/modification/{intentId}/{bandwidth}") |
91 | @POST | 121 | @POST |
... | @@ -115,4 +145,34 @@ public class BandwidthCalendarResource extends BaseResource { | ... | @@ -115,4 +145,34 @@ public class BandwidthCalendarResource extends BaseResource { |
115 | protected ApplicationId appId() { | 145 | protected ApplicationId appId() { |
116 | return get(CoreService.class).registerApplication("org.onlab.onos.calendar"); | 146 | return get(CoreService.class).registerApplication("org.onlab.onos.calendar"); |
117 | } | 147 | } |
148 | + | ||
149 | + // Auxiliary listener to wait until the given intent reaches the installed or failed states. | ||
150 | + private final class InternalIntentListener implements IntentListener { | ||
151 | + private final Intent intent; | ||
152 | + private final IntentService service; | ||
153 | + private final CountDownLatch latch; | ||
154 | + private IntentState state; | ||
155 | + | ||
156 | + private InternalIntentListener(Intent intent, IntentService service, | ||
157 | + CountDownLatch latch) { | ||
158 | + this.intent = intent; | ||
159 | + this.service = service; | ||
160 | + this.latch = latch; | ||
161 | + } | ||
162 | + | ||
163 | + @Override | ||
164 | + public void event(IntentEvent event) { | ||
165 | + if (event.subject().equals(intent)) { | ||
166 | + state = service.getIntentState(intent.id()); | ||
167 | + if (state == INSTALLED || state == FAILED || state == WITHDRAWN) { | ||
168 | + latch.countDown(); | ||
169 | + } | ||
170 | + service.removeListener(this); | ||
171 | + } | ||
172 | + } | ||
173 | + | ||
174 | + public IntentState getState() { | ||
175 | + return state; | ||
176 | + } | ||
177 | + } | ||
118 | } | 178 | } | ... | ... |
... | @@ -50,7 +50,10 @@ public class NetworkConfigReader { | ... | @@ -50,7 +50,10 @@ public class NetworkConfigReader { |
50 | 50 | ||
51 | private final Logger log = getLogger(getClass()); | 51 | private final Logger log = getLogger(getClass()); |
52 | 52 | ||
53 | - private static final String DEFAULT_CONFIG_FILE = "config/addresses.json"; | 53 | + // Current working dir seems to be /opt/onos/apache-karaf-3.0.2 |
54 | + // TODO: Set the path to /opt/onos/config | ||
55 | + private static final String CONFIG_DIR = "../config"; | ||
56 | + private static final String DEFAULT_CONFIG_FILE = "addresses.json"; | ||
54 | private String configFileName = DEFAULT_CONFIG_FILE; | 57 | private String configFileName = DEFAULT_CONFIG_FILE; |
55 | 58 | ||
56 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 59 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
... | @@ -60,19 +63,53 @@ public class NetworkConfigReader { | ... | @@ -60,19 +63,53 @@ public class NetworkConfigReader { |
60 | protected void activate() { | 63 | protected void activate() { |
61 | log.info("Started network config reader"); | 64 | log.info("Started network config reader"); |
62 | 65 | ||
63 | - log.info("Config file set to {}", configFileName); | ||
64 | - | ||
65 | AddressConfiguration config = readNetworkConfig(); | 66 | AddressConfiguration config = readNetworkConfig(); |
66 | - | ||
67 | if (config != null) { | 67 | if (config != null) { |
68 | - for (AddressEntry entry : config.getAddresses()) { | 68 | + applyNetworkConfig(config); |
69 | + } | ||
70 | + } | ||
71 | + | ||
72 | + @Deactivate | ||
73 | + protected void deactivate() { | ||
74 | + log.info("Stopped"); | ||
75 | + } | ||
76 | + | ||
77 | + /** | ||
78 | + * Reads the network configuration. | ||
79 | + * | ||
80 | + * @return the network configuration on success, otherwise null | ||
81 | + */ | ||
82 | + private AddressConfiguration readNetworkConfig() { | ||
83 | + File configFile = new File(CONFIG_DIR, configFileName); | ||
84 | + ObjectMapper mapper = new ObjectMapper(); | ||
85 | + | ||
86 | + try { | ||
87 | + log.info("Loading config: {}", configFile.getAbsolutePath()); | ||
88 | + AddressConfiguration config = | ||
89 | + mapper.readValue(configFile, AddressConfiguration.class); | ||
90 | + | ||
91 | + return config; | ||
92 | + } catch (FileNotFoundException e) { | ||
93 | + log.warn("Configuration file not found: {}", configFileName); | ||
94 | + } catch (IOException e) { | ||
95 | + log.error("Error loading configuration", e); | ||
96 | + } | ||
97 | + | ||
98 | + return null; | ||
99 | + } | ||
69 | 100 | ||
101 | + /** | ||
102 | + * Applies the network configuration. | ||
103 | + * | ||
104 | + * @param config the network configuration to apply | ||
105 | + */ | ||
106 | + private void applyNetworkConfig(AddressConfiguration config) { | ||
107 | + for (AddressEntry entry : config.getAddresses()) { | ||
70 | ConnectPoint cp = new ConnectPoint( | 108 | ConnectPoint cp = new ConnectPoint( |
71 | DeviceId.deviceId(dpidToUri(entry.getDpid())), | 109 | DeviceId.deviceId(dpidToUri(entry.getDpid())), |
72 | PortNumber.portNumber(entry.getPortNumber())); | 110 | PortNumber.portNumber(entry.getPortNumber())); |
73 | 111 | ||
74 | Set<InterfaceIpAddress> interfaceIpAddresses = new HashSet<>(); | 112 | Set<InterfaceIpAddress> interfaceIpAddresses = new HashSet<>(); |
75 | - | ||
76 | for (String strIp : entry.getIpAddresses()) { | 113 | for (String strIp : entry.getIpAddresses()) { |
77 | // Get the IP address and the subnet mask length | 114 | // Get the IP address and the subnet mask length |
78 | try { | 115 | try { |
... | @@ -103,35 +140,9 @@ public class NetworkConfigReader { | ... | @@ -103,35 +140,9 @@ public class NetworkConfigReader { |
103 | 140 | ||
104 | PortAddresses addresses = new PortAddresses(cp, | 141 | PortAddresses addresses = new PortAddresses(cp, |
105 | interfaceIpAddresses, macAddress); | 142 | interfaceIpAddresses, macAddress); |
106 | - | ||
107 | hostAdminService.bindAddressesToPort(addresses); | 143 | hostAdminService.bindAddressesToPort(addresses); |
108 | } | 144 | } |
109 | } | 145 | } |
110 | - } | ||
111 | - | ||
112 | - @Deactivate | ||
113 | - protected void deactivate() { | ||
114 | - log.info("Stopped"); | ||
115 | - } | ||
116 | - | ||
117 | - private AddressConfiguration readNetworkConfig() { | ||
118 | - File configFile = new File(configFileName); | ||
119 | - | ||
120 | - ObjectMapper mapper = new ObjectMapper(); | ||
121 | - | ||
122 | - try { | ||
123 | - AddressConfiguration config = | ||
124 | - mapper.readValue(configFile, AddressConfiguration.class); | ||
125 | - | ||
126 | - return config; | ||
127 | - } catch (FileNotFoundException e) { | ||
128 | - log.warn("Configuration file not found: {}", configFileName); | ||
129 | - } catch (IOException e) { | ||
130 | - log.error("Unable to read config from file:", e); | ||
131 | - } | ||
132 | - | ||
133 | - return null; | ||
134 | - } | ||
135 | 146 | ||
136 | private static String dpidToUri(String dpid) { | 147 | private static String dpidToUri(String dpid) { |
137 | return "of:" + dpid.replace(":", ""); | 148 | return "of:" + dpid.replace(":", ""); | ... | ... |
1 | -{ | ||
2 | - "interfaces" : [ | ||
3 | - { | ||
4 | - "dpid" : "00:00:00:00:00:00:01", | ||
5 | - "port" : "1", | ||
6 | - "ips" : ["192.168.10.101/24"], | ||
7 | - "mac" : "00:00:00:11:22:33" | ||
8 | - }, | ||
9 | - { | ||
10 | - "dpid" : "00:00:00:00:00:00:02", | ||
11 | - "port" : "1", | ||
12 | - "ips" : ["192.168.20.101/24", "192.168.30.101/24"] | ||
13 | - }, | ||
14 | - { | ||
15 | - "dpid" : "00:00:00:00:00:00:03", | ||
16 | - "port" : "1", | ||
17 | - "ips" : ["10.1.0.1/16"], | ||
18 | - "mac" : "00:00:00:00:00:01" | ||
19 | - } | ||
20 | - ] | ||
21 | -} |
apps/demo/pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!-- | ||
3 | + ~ Copyright 2014 Open Networking Laboratory | ||
4 | + ~ | ||
5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + ~ you may not use this file except in compliance with the License. | ||
7 | + ~ You may obtain a copy of the License at | ||
8 | + ~ | ||
9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + ~ | ||
11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + ~ See the License for the specific language governing permissions and | ||
15 | + ~ limitations under the License. | ||
16 | + --> | ||
17 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
18 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
19 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
20 | + <modelVersion>4.0.0</modelVersion> | ||
21 | + | ||
22 | + <parent> | ||
23 | + <groupId>org.onlab.onos</groupId> | ||
24 | + <artifactId>onos-apps</artifactId> | ||
25 | + <version>1.0.0-SNAPSHOT</version> | ||
26 | + <relativePath>../pom.xml</relativePath> | ||
27 | + </parent> | ||
28 | + | ||
29 | + <artifactId>onos-app-demo</artifactId> | ||
30 | + <packaging>bundle</packaging> | ||
31 | + | ||
32 | + <description>ONOS demo app bundle</description> | ||
33 | + | ||
34 | + <properties> | ||
35 | + <web.context>/onos/demo</web.context> | ||
36 | + </properties> | ||
37 | + | ||
38 | + <dependencies> | ||
39 | + <dependency> | ||
40 | + <groupId>org.osgi</groupId> | ||
41 | + <artifactId>org.osgi.compendium</artifactId> | ||
42 | + </dependency> | ||
43 | + <dependency> | ||
44 | + <groupId>org.onlab.onos</groupId> | ||
45 | + <artifactId>onlab-rest</artifactId> | ||
46 | + <version>${project.version}</version> | ||
47 | + </dependency> | ||
48 | + | ||
49 | + <dependency> | ||
50 | + <groupId>org.onlab.onos</groupId> | ||
51 | + <artifactId>onos-rest</artifactId> | ||
52 | + <version>${project.version}</version> | ||
53 | + </dependency> | ||
54 | + | ||
55 | + <dependency> | ||
56 | + <groupId>com.sun.jersey</groupId> | ||
57 | + <artifactId>jersey-servlet</artifactId> | ||
58 | + </dependency> | ||
59 | + <dependency> | ||
60 | + <groupId>com.sun.jersey.jersey-test-framework</groupId> | ||
61 | + <artifactId>jersey-test-framework-core</artifactId> | ||
62 | + <version>1.18.1</version> | ||
63 | + <scope>test</scope> | ||
64 | + </dependency> | ||
65 | + <dependency> | ||
66 | + <groupId>com.sun.jersey.jersey-test-framework</groupId> | ||
67 | + <artifactId>jersey-test-framework-grizzly2</artifactId> | ||
68 | + <version>1.18.1</version> | ||
69 | + <scope>test</scope> | ||
70 | + </dependency> | ||
71 | + | ||
72 | + <dependency> | ||
73 | + <groupId>com.fasterxml.jackson.core</groupId> | ||
74 | + <artifactId>jackson-databind</artifactId> | ||
75 | + </dependency> | ||
76 | + | ||
77 | + <dependency> | ||
78 | + <groupId>com.fasterxml.jackson.core</groupId> | ||
79 | + <artifactId>jackson-annotations</artifactId> | ||
80 | + </dependency> | ||
81 | + | ||
82 | + <dependency> | ||
83 | + <groupId>org.osgi</groupId> | ||
84 | + <artifactId>org.osgi.core</artifactId> | ||
85 | + </dependency> | ||
86 | + </dependencies> | ||
87 | + | ||
88 | + <build> | ||
89 | + <plugins> | ||
90 | + <plugin> | ||
91 | + <groupId>org.apache.felix</groupId> | ||
92 | + <artifactId>maven-bundle-plugin</artifactId> | ||
93 | + <extensions>true</extensions> | ||
94 | + <configuration> | ||
95 | + <instructions> | ||
96 | + <_wab>src/main/webapp/</_wab> | ||
97 | + <Bundle-SymbolicName> | ||
98 | + ${project.groupId}.${project.artifactId} | ||
99 | + </Bundle-SymbolicName> | ||
100 | + <Import-Package> | ||
101 | + org.slf4j, | ||
102 | + org.osgi.framework, | ||
103 | + javax.ws.rs,javax.ws.rs.core, | ||
104 | + com.sun.jersey.api.core, | ||
105 | + com.sun.jersey.spi.container.servlet, | ||
106 | + com.sun.jersey.server.impl.container.servlet, | ||
107 | + com.fasterxml.jackson.databind, | ||
108 | + com.fasterxml.jackson.databind.node, | ||
109 | + com.google.common.*, | ||
110 | + org.onlab.packet.*, | ||
111 | + org.onlab.rest.*, | ||
112 | + org.onlab.onos.* | ||
113 | + </Import-Package> | ||
114 | + <Web-ContextPath>${web.context}</Web-ContextPath> | ||
115 | + </instructions> | ||
116 | + </configuration> | ||
117 | + </plugin> | ||
118 | + </plugins> | ||
119 | + </build> | ||
120 | + | ||
121 | +</project> |
1 | +package org.onlab.onos.demo; | ||
2 | + | ||
3 | +/** | ||
4 | + * Simple demo api interface. | ||
5 | + */ | ||
6 | +public interface DemoAPI { | ||
7 | + | ||
8 | + enum InstallType { MESH, RANDOM }; | ||
9 | + | ||
10 | + /** | ||
11 | + * Installs intents based on the installation type. | ||
12 | + * @param type the installation type. | ||
13 | + */ | ||
14 | + void setup(InstallType type); | ||
15 | + | ||
16 | + /** | ||
17 | + * Uninstalls all existing intents. | ||
18 | + */ | ||
19 | + void tearDown(); | ||
20 | + | ||
21 | +} |
1 | +/* | ||
2 | + * Copyright 2014 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onlab.onos.demo; | ||
17 | + | ||
18 | +import com.google.common.collect.Lists; | ||
19 | +import com.google.common.util.concurrent.ThreadFactoryBuilder; | ||
20 | +import org.apache.felix.scr.annotations.Activate; | ||
21 | +import org.apache.felix.scr.annotations.Component; | ||
22 | +import org.apache.felix.scr.annotations.Deactivate; | ||
23 | +import org.apache.felix.scr.annotations.Reference; | ||
24 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
25 | +import org.apache.felix.scr.annotations.Service; | ||
26 | +import org.onlab.onos.core.ApplicationId; | ||
27 | +import org.onlab.onos.core.CoreService; | ||
28 | +import org.onlab.onos.net.Host; | ||
29 | +import org.onlab.onos.net.flow.DefaultTrafficSelector; | ||
30 | +import org.onlab.onos.net.flow.DefaultTrafficTreatment; | ||
31 | +import org.onlab.onos.net.flow.TrafficSelector; | ||
32 | +import org.onlab.onos.net.flow.TrafficTreatment; | ||
33 | +import org.onlab.onos.net.host.HostService; | ||
34 | +import org.onlab.onos.net.intent.HostToHostIntent; | ||
35 | +import org.onlab.onos.net.intent.Intent; | ||
36 | +import org.onlab.onos.net.intent.IntentService; | ||
37 | +import org.slf4j.Logger; | ||
38 | + | ||
39 | + | ||
40 | +import java.util.HashSet; | ||
41 | +import java.util.List; | ||
42 | +import java.util.Set; | ||
43 | +import java.util.concurrent.ExecutorService; | ||
44 | +import java.util.concurrent.Executors; | ||
45 | + | ||
46 | +import static org.slf4j.LoggerFactory.getLogger; | ||
47 | + | ||
48 | +/** | ||
49 | + * Application to set up demos. | ||
50 | + */ | ||
51 | +@Component(immediate = true) | ||
52 | +@Service | ||
53 | +public class DemoInstaller implements DemoAPI { | ||
54 | + | ||
55 | + private final Logger log = getLogger(getClass()); | ||
56 | + | ||
57 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
58 | + protected CoreService coreService; | ||
59 | + | ||
60 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
61 | + protected IntentService intentService; | ||
62 | + | ||
63 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
64 | + protected HostService hostService; | ||
65 | + | ||
66 | + private ExecutorService worker; | ||
67 | + | ||
68 | + private ApplicationId appId; | ||
69 | + | ||
70 | + private final Set<Intent> existingIntents = new HashSet<>(); | ||
71 | + | ||
72 | + | ||
73 | + | ||
74 | + @Activate | ||
75 | + public void activate() { | ||
76 | + appId = coreService.registerApplication("org.onlab.onos.demo.installer"); | ||
77 | + worker = Executors.newFixedThreadPool(1, | ||
78 | + new ThreadFactoryBuilder() | ||
79 | + .setNameFormat("demo-app-worker") | ||
80 | + .build()); | ||
81 | + log.info("Started with Application ID {}", appId.id()); | ||
82 | + } | ||
83 | + | ||
84 | + @Deactivate | ||
85 | + public void deactivate() { | ||
86 | + worker.shutdownNow(); | ||
87 | + log.info("Stopped"); | ||
88 | + } | ||
89 | + | ||
90 | + @Override | ||
91 | + public void setup(InstallType type) { | ||
92 | + switch (type) { | ||
93 | + case MESH: | ||
94 | + log.debug("Installing mesh intents"); | ||
95 | + worker.execute(new MeshInstaller()); | ||
96 | + break; | ||
97 | + case RANDOM: | ||
98 | + throw new IllegalArgumentException("Not yet implemented."); | ||
99 | + default: | ||
100 | + throw new IllegalArgumentException("What is it you want exactly?"); | ||
101 | + } | ||
102 | + } | ||
103 | + | ||
104 | + @Override | ||
105 | + public void tearDown() { | ||
106 | + worker.submit(new UnInstaller()); | ||
107 | + } | ||
108 | + | ||
109 | + | ||
110 | + private class MeshInstaller implements Runnable { | ||
111 | + | ||
112 | + @Override | ||
113 | + public void run() { | ||
114 | + TrafficSelector selector = DefaultTrafficSelector.builder().build(); | ||
115 | + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build(); | ||
116 | + | ||
117 | + List<Host> hosts = Lists.newArrayList(hostService.getHosts()); | ||
118 | + while (!hosts.isEmpty()) { | ||
119 | + Host src = hosts.remove(0); | ||
120 | + for (Host dst : hosts) { | ||
121 | + HostToHostIntent intent = new HostToHostIntent(appId, src.id(), dst.id(), | ||
122 | + selector, treatment, | ||
123 | + null); | ||
124 | + existingIntents.add(intent); | ||
125 | + intentService.submit(intent); | ||
126 | + } | ||
127 | + } | ||
128 | + } | ||
129 | + } | ||
130 | + | ||
131 | + | ||
132 | + private class UnInstaller implements Runnable { | ||
133 | + @Override | ||
134 | + public void run() { | ||
135 | + for (Intent i : existingIntents) { | ||
136 | + intentService.withdraw(i); | ||
137 | + } | ||
138 | + } | ||
139 | + } | ||
140 | +} | ||
141 | + | ||
142 | + |
1 | +package org.onlab.onos.demo; | ||
2 | + | ||
3 | +import com.fasterxml.jackson.databind.JsonNode; | ||
4 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
5 | +import org.onlab.rest.BaseResource; | ||
6 | + | ||
7 | +import javax.ws.rs.Consumes; | ||
8 | +import javax.ws.rs.GET; | ||
9 | +import javax.ws.rs.POST; | ||
10 | +import javax.ws.rs.Path; | ||
11 | +import javax.ws.rs.Produces; | ||
12 | +import javax.ws.rs.core.MediaType; | ||
13 | +import javax.ws.rs.core.Response; | ||
14 | +import java.io.IOException; | ||
15 | +import java.io.InputStream; | ||
16 | + | ||
17 | +/** | ||
18 | + * Rest API for demos. | ||
19 | + */ | ||
20 | +@Path("intents") | ||
21 | +public class DemoResource extends BaseResource { | ||
22 | + | ||
23 | + | ||
24 | + @POST | ||
25 | + @Path("setup") | ||
26 | + @Consumes(MediaType.APPLICATION_JSON) | ||
27 | + @Produces(MediaType.APPLICATION_JSON) | ||
28 | + public Response setup(InputStream input) throws IOException { | ||
29 | + ObjectMapper mapper = new ObjectMapper(); | ||
30 | + JsonNode cfg = mapper.readTree(input); | ||
31 | + if (!cfg.has("type")) { | ||
32 | + return Response.status(Response.Status.BAD_REQUEST) | ||
33 | + .entity("Expected type field containing either mesh or random.").build(); | ||
34 | + } | ||
35 | + | ||
36 | + DemoAPI.InstallType type = DemoAPI.InstallType.valueOf( | ||
37 | + cfg.get("type").asText().toUpperCase()); | ||
38 | + DemoAPI demo = get(DemoAPI.class); | ||
39 | + demo.setup(type); | ||
40 | + | ||
41 | + return Response.ok(mapper.createObjectNode().toString()).build(); | ||
42 | + } | ||
43 | + | ||
44 | + @GET | ||
45 | + @Path("teardown") | ||
46 | + @Produces(MediaType.APPLICATION_JSON) | ||
47 | + public Response tearDown() throws IOException { | ||
48 | + ObjectMapper mapper = new ObjectMapper(); | ||
49 | + DemoAPI demo = get(DemoAPI.class); | ||
50 | + demo.tearDown(); | ||
51 | + return Response.ok(mapper.createObjectNode().toString()).build(); | ||
52 | + } | ||
53 | + | ||
54 | +} |
1 | +/* | ||
2 | + * Copyright 2014 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +/** | ||
18 | + * Demo applications live here. | ||
19 | + */ | ||
20 | +package org.onlab.onos.demo; |
apps/demo/src/main/webapp/WEB-INF/web.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!-- | ||
3 | + ~ Copyright 2014 Open Networking Laboratory | ||
4 | + ~ | ||
5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + ~ you may not use this file except in compliance with the License. | ||
7 | + ~ You may obtain a copy of the License at | ||
8 | + ~ | ||
9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + ~ | ||
11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + ~ See the License for the specific language governing permissions and | ||
15 | + ~ limitations under the License. | ||
16 | + --> | ||
17 | +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" | ||
18 | + xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" | ||
19 | + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" | ||
20 | + id="ONOS" version="2.5"> | ||
21 | + <display-name>ONOS DEMO APP API v1.0</display-name> | ||
22 | + | ||
23 | + <servlet> | ||
24 | + <servlet-name>JAX-RS Service</servlet-name> | ||
25 | + <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> | ||
26 | + <init-param> | ||
27 | + <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name> | ||
28 | + <param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value> | ||
29 | + </init-param> | ||
30 | + <init-param> | ||
31 | + <param-name>com.sun.jersey.config.property.classnames</param-name> | ||
32 | + <param-value> | ||
33 | + org.onlab.onos.demo.DemoResource | ||
34 | + </param-value> | ||
35 | + </init-param> | ||
36 | + <load-on-startup>1</load-on-startup> | ||
37 | + </servlet> | ||
38 | + | ||
39 | + <servlet-mapping> | ||
40 | + <servlet-name>JAX-RS Service</servlet-name> | ||
41 | + <url-pattern>/*</url-pattern> | ||
42 | + </servlet-mapping> | ||
43 | + | ||
44 | +</web-app> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
... | @@ -44,6 +44,7 @@ | ... | @@ -44,6 +44,7 @@ |
44 | <module>optical</module> | 44 | <module>optical</module> |
45 | <module>metrics</module> | 45 | <module>metrics</module> |
46 | <module>oecfg</module> | 46 | <module>oecfg</module> |
47 | + <module>demo</module> | ||
47 | </modules> | 48 | </modules> |
48 | 49 | ||
49 | <properties> | 50 | <properties> | ... | ... |
... | @@ -37,24 +37,31 @@ import com.fasterxml.jackson.databind.ObjectMapper; | ... | @@ -37,24 +37,31 @@ import com.fasterxml.jackson.databind.ObjectMapper; |
37 | */ | 37 | */ |
38 | public class SdnIpConfigReader implements SdnIpConfigService { | 38 | public class SdnIpConfigReader implements SdnIpConfigService { |
39 | 39 | ||
40 | - private static final Logger log = LoggerFactory.getLogger(SdnIpConfigReader.class); | 40 | + private final Logger log = LoggerFactory.getLogger(getClass()); |
41 | 41 | ||
42 | - private static final String DEFAULT_CONFIG_FILE = "config/sdnip.json"; | 42 | + // Current working dir seems to be /opt/onos/apache-karaf-3.0.2 |
43 | + // TODO: Set the path to /opt/onos/config | ||
44 | + private static final String CONFIG_DIR = "../config"; | ||
45 | + private static final String DEFAULT_CONFIG_FILE = "sdnip.json"; | ||
43 | private String configFileName = DEFAULT_CONFIG_FILE; | 46 | private String configFileName = DEFAULT_CONFIG_FILE; |
47 | + | ||
44 | private Map<String, BgpSpeaker> bgpSpeakers = new ConcurrentHashMap<>(); | 48 | private Map<String, BgpSpeaker> bgpSpeakers = new ConcurrentHashMap<>(); |
45 | private Map<IpAddress, BgpPeer> bgpPeers = new ConcurrentHashMap<>(); | 49 | private Map<IpAddress, BgpPeer> bgpPeers = new ConcurrentHashMap<>(); |
46 | 50 | ||
47 | /** | 51 | /** |
48 | - * Reads the info contained in the configuration file. | 52 | + * Reads SDN-IP related information contained in the configuration file. |
49 | * | 53 | * |
50 | - * @param configFilename The name of configuration file for SDN-IP application. | 54 | + * @param configFilename the name of the configuration file for the SDN-IP |
55 | + * application | ||
51 | */ | 56 | */ |
52 | private void readConfiguration(String configFilename) { | 57 | private void readConfiguration(String configFilename) { |
53 | - File gatewaysFile = new File(configFilename); | 58 | + File configFile = new File(CONFIG_DIR, configFilename); |
54 | ObjectMapper mapper = new ObjectMapper(); | 59 | ObjectMapper mapper = new ObjectMapper(); |
55 | 60 | ||
56 | try { | 61 | try { |
57 | - Configuration config = mapper.readValue(gatewaysFile, Configuration.class); | 62 | + log.info("Loading config: {}", configFile.getAbsolutePath()); |
63 | + Configuration config = mapper.readValue(configFile, | ||
64 | + Configuration.class); | ||
58 | for (BgpSpeaker speaker : config.getBgpSpeakers()) { | 65 | for (BgpSpeaker speaker : config.getBgpSpeakers()) { |
59 | bgpSpeakers.put(speaker.name(), speaker); | 66 | bgpSpeakers.put(speaker.name(), speaker); |
60 | } | 67 | } |
... | @@ -64,13 +71,11 @@ public class SdnIpConfigReader implements SdnIpConfigService { | ... | @@ -64,13 +71,11 @@ public class SdnIpConfigReader implements SdnIpConfigService { |
64 | } catch (FileNotFoundException e) { | 71 | } catch (FileNotFoundException e) { |
65 | log.warn("Configuration file not found: {}", configFileName); | 72 | log.warn("Configuration file not found: {}", configFileName); |
66 | } catch (IOException e) { | 73 | } catch (IOException e) { |
67 | - log.error("Error reading JSON file", e); | 74 | + log.error("Error loading configuration", e); |
68 | } | 75 | } |
69 | } | 76 | } |
70 | 77 | ||
71 | public void init() { | 78 | public void init() { |
72 | - log.debug("Config file set to {}", configFileName); | ||
73 | - | ||
74 | readConfiguration(configFileName); | 79 | readConfiguration(configFileName); |
75 | } | 80 | } |
76 | 81 | ... | ... |
1 | -ONOS looks for these config files by default in $KARAF_LOG/config/ | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +The SDN-IP configuration files should be copied to directory | ||
2 | + $ONOS_HOME/tools/package/config | ||
3 | + | ||
4 | +After deployment and starting up the ONOS cluster, ONOS looks for these | ||
5 | +configuration files in /opt/onos/config on each cluster member. | ... | ... |
... | @@ -27,6 +27,7 @@ import org.onlab.onos.net.intent.constraint.BandwidthConstraint; | ... | @@ -27,6 +27,7 @@ import org.onlab.onos.net.intent.constraint.BandwidthConstraint; |
27 | import org.onlab.onos.net.intent.constraint.LambdaConstraint; | 27 | import org.onlab.onos.net.intent.constraint.LambdaConstraint; |
28 | import org.onlab.onos.net.resource.Bandwidth; | 28 | import org.onlab.onos.net.resource.Bandwidth; |
29 | import org.onlab.packet.Ethernet; | 29 | import org.onlab.packet.Ethernet; |
30 | +import org.onlab.packet.IpPrefix; | ||
30 | import org.onlab.packet.MacAddress; | 31 | import org.onlab.packet.MacAddress; |
31 | 32 | ||
32 | import static com.google.common.base.Strings.isNullOrEmpty; | 33 | import static com.google.common.base.Strings.isNullOrEmpty; |
... | @@ -48,6 +49,26 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand { | ... | @@ -48,6 +49,26 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand { |
48 | required = false, multiValued = false) | 49 | required = false, multiValued = false) |
49 | private String ethTypeString = ""; | 50 | private String ethTypeString = ""; |
50 | 51 | ||
52 | + @Option(name = "--ipProto", description = "IP Protocol", | ||
53 | + required = false, multiValued = false) | ||
54 | + private String ipProtoString = null; | ||
55 | + | ||
56 | + @Option(name = "--ipSrc", description = "Source IP Address", | ||
57 | + required = false, multiValued = false) | ||
58 | + private String srcIpString = null; | ||
59 | + | ||
60 | + @Option(name = "--ipDst", description = "Destination IP Address", | ||
61 | + required = false, multiValued = false) | ||
62 | + private String dstIpString = null; | ||
63 | + | ||
64 | + @Option(name = "--tcpSrc", description = "Source TCP Port", | ||
65 | + required = false, multiValued = false) | ||
66 | + private String srcTcpString = null; | ||
67 | + | ||
68 | + @Option(name = "--tcpDst", description = "Destination TCP Port", | ||
69 | + required = false, multiValued = false) | ||
70 | + private String dstTcpString = null; | ||
71 | + | ||
51 | @Option(name = "-b", aliases = "--bandwidth", description = "Bandwidth", | 72 | @Option(name = "-b", aliases = "--bandwidth", description = "Bandwidth", |
52 | required = false, multiValued = false) | 73 | required = false, multiValued = false) |
53 | private String bandwidthString = ""; | 74 | private String bandwidthString = ""; |
... | @@ -79,6 +100,26 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand { | ... | @@ -79,6 +100,26 @@ public abstract class ConnectivityIntentCommand extends AbstractShellCommand { |
79 | selectorBuilder.matchEthDst(MacAddress.valueOf(dstMacString)); | 100 | selectorBuilder.matchEthDst(MacAddress.valueOf(dstMacString)); |
80 | } | 101 | } |
81 | 102 | ||
103 | + if (!isNullOrEmpty(ipProtoString)) { | ||
104 | + selectorBuilder.matchIPProtocol((byte) Short.parseShort(ipProtoString)); | ||
105 | + } | ||
106 | + | ||
107 | + if (!isNullOrEmpty(srcIpString)) { | ||
108 | + selectorBuilder.matchIPSrc(IpPrefix.valueOf(srcIpString)); | ||
109 | + } | ||
110 | + | ||
111 | + if (!isNullOrEmpty(dstIpString)) { | ||
112 | + selectorBuilder.matchIPDst(IpPrefix.valueOf(dstIpString)); | ||
113 | + } | ||
114 | + | ||
115 | + if (!isNullOrEmpty(srcTcpString)) { | ||
116 | + selectorBuilder.matchTcpSrc((short) Integer.parseInt(srcTcpString)); | ||
117 | + } | ||
118 | + | ||
119 | + if (!isNullOrEmpty(dstTcpString)) { | ||
120 | + selectorBuilder.matchTcpSrc((short) Integer.parseInt(dstTcpString)); | ||
121 | + } | ||
122 | + | ||
82 | return selectorBuilder.build(); | 123 | return selectorBuilder.build(); |
83 | } | 124 | } |
84 | 125 | ... | ... |
1 | +/* | ||
2 | + * Copyright 2014 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onlab.onos.net; | ||
17 | + | ||
18 | +/** | ||
19 | + * Collection of keys for annotation. | ||
20 | + * Definitions of annotation keys needs to be here to avoid scattering. | ||
21 | + */ | ||
22 | +public final class AnnotationKeys { | ||
23 | + | ||
24 | + // Prohibit instantiation | ||
25 | + private AnnotationKeys() {} | ||
26 | + | ||
27 | + /** | ||
28 | + * Annotation key for latency. | ||
29 | + */ | ||
30 | + public static final String LATENCY = "latency"; | ||
31 | + | ||
32 | + /** | ||
33 | + * Returns the value annotated object for the specified annotation key. | ||
34 | + * The annotated value is expected to be String that can be parsed as double. | ||
35 | + * If parsing fails, the returned value will be 1.0. | ||
36 | + * | ||
37 | + * @param annotated annotated object whose annotated value is obtained | ||
38 | + * @param key key of annotation | ||
39 | + * @return double value of annotated object for the specified key | ||
40 | + */ | ||
41 | + public static double getAnnotatedValue(Annotated annotated, String key) { | ||
42 | + double value; | ||
43 | + try { | ||
44 | + value = Double.parseDouble(annotated.annotations().value(key)); | ||
45 | + } catch (NumberFormatException e) { | ||
46 | + value = 1.0; | ||
47 | + } | ||
48 | + return value; | ||
49 | + } | ||
50 | +} |
... | @@ -80,6 +80,7 @@ public class DefaultFlowEntry extends DefaultFlowRule | ... | @@ -80,6 +80,7 @@ public class DefaultFlowEntry extends DefaultFlowRule |
80 | this.state = FlowEntryState.FAILED; | 80 | this.state = FlowEntryState.FAILED; |
81 | this.errType = errType; | 81 | this.errType = errType; |
82 | this.errCode = errCode; | 82 | this.errCode = errCode; |
83 | + this.lastSeen = System.currentTimeMillis(); | ||
83 | } | 84 | } |
84 | 85 | ||
85 | @Override | 86 | @Override | ... | ... |
... | @@ -58,7 +58,7 @@ public class DefaultFlowRule implements FlowRule { | ... | @@ -58,7 +58,7 @@ public class DefaultFlowRule implements FlowRule { |
58 | } | 58 | } |
59 | 59 | ||
60 | public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector, | 60 | public DefaultFlowRule(DeviceId deviceId, TrafficSelector selector, |
61 | - TrafficTreatment treatement, int priority, ApplicationId appId, | 61 | + TrafficTreatment treatment, int priority, ApplicationId appId, |
62 | int timeout, boolean permanent) { | 62 | int timeout, boolean permanent) { |
63 | 63 | ||
64 | if (priority < FlowRule.MIN_PRIORITY) { | 64 | if (priority < FlowRule.MIN_PRIORITY) { |
... | @@ -68,7 +68,7 @@ public class DefaultFlowRule implements FlowRule { | ... | @@ -68,7 +68,7 @@ public class DefaultFlowRule implements FlowRule { |
68 | this.deviceId = deviceId; | 68 | this.deviceId = deviceId; |
69 | this.priority = priority; | 69 | this.priority = priority; |
70 | this.selector = selector; | 70 | this.selector = selector; |
71 | - this.treatment = treatement; | 71 | + this.treatment = treatment; |
72 | this.appId = appId.id(); | 72 | this.appId = appId.id(); |
73 | this.timeout = timeout; | 73 | this.timeout = timeout; |
74 | this.permanent = permanent; | 74 | this.permanent = permanent; | ... | ... |
... | @@ -63,7 +63,7 @@ public final class DefaultTrafficSelector implements TrafficSelector { | ... | @@ -63,7 +63,7 @@ public final class DefaultTrafficSelector implements TrafficSelector { |
63 | 63 | ||
64 | @Override | 64 | @Override |
65 | public int hashCode() { | 65 | public int hashCode() { |
66 | - return Objects.hash(criteria); | 66 | + return criteria.hashCode(); |
67 | } | 67 | } |
68 | 68 | ||
69 | @Override | 69 | @Override | ... | ... |
... | @@ -18,7 +18,7 @@ package org.onlab.onos.net.flow; | ... | @@ -18,7 +18,7 @@ package org.onlab.onos.net.flow; |
18 | import org.onlab.onos.core.ApplicationId; | 18 | import org.onlab.onos.core.ApplicationId; |
19 | import org.onlab.onos.net.provider.Provider; | 19 | import org.onlab.onos.net.provider.Provider; |
20 | 20 | ||
21 | -import com.google.common.util.concurrent.ListenableFuture; | 21 | +import java.util.concurrent.Future; |
22 | 22 | ||
23 | /** | 23 | /** |
24 | * Abstraction of a flow rule provider. | 24 | * Abstraction of a flow rule provider. |
... | @@ -58,6 +58,6 @@ public interface FlowRuleProvider extends Provider { | ... | @@ -58,6 +58,6 @@ public interface FlowRuleProvider extends Provider { |
58 | * @param batch a batch of flow rules | 58 | * @param batch a batch of flow rules |
59 | * @return a future indicating the status of this execution | 59 | * @return a future indicating the status of this execution |
60 | */ | 60 | */ |
61 | - ListenableFuture<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch); | 61 | + Future<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch); |
62 | 62 | ||
63 | } | 63 | } | ... | ... |
... | @@ -196,7 +196,7 @@ public final class Criteria { | ... | @@ -196,7 +196,7 @@ public final class Criteria { |
196 | 196 | ||
197 | @Override | 197 | @Override |
198 | public int hashCode() { | 198 | public int hashCode() { |
199 | - return Objects.hash(port, type()); | 199 | + return Objects.hash(type(), port); |
200 | } | 200 | } |
201 | 201 | ||
202 | @Override | 202 | @Override |
... | @@ -242,7 +242,7 @@ public final class Criteria { | ... | @@ -242,7 +242,7 @@ public final class Criteria { |
242 | 242 | ||
243 | @Override | 243 | @Override |
244 | public int hashCode() { | 244 | public int hashCode() { |
245 | - return Objects.hash(mac, type); | 245 | + return Objects.hash(type, mac); |
246 | } | 246 | } |
247 | 247 | ||
248 | @Override | 248 | @Override |
... | @@ -288,7 +288,7 @@ public final class Criteria { | ... | @@ -288,7 +288,7 @@ public final class Criteria { |
288 | 288 | ||
289 | @Override | 289 | @Override |
290 | public int hashCode() { | 290 | public int hashCode() { |
291 | - return Objects.hash(ethType, type()); | 291 | + return Objects.hash(type(), ethType); |
292 | } | 292 | } |
293 | 293 | ||
294 | @Override | 294 | @Override |
... | @@ -336,7 +336,7 @@ public final class Criteria { | ... | @@ -336,7 +336,7 @@ public final class Criteria { |
336 | 336 | ||
337 | @Override | 337 | @Override |
338 | public int hashCode() { | 338 | public int hashCode() { |
339 | - return Objects.hash(ip, type); | 339 | + return Objects.hash(type, ip); |
340 | } | 340 | } |
341 | 341 | ||
342 | @Override | 342 | @Override |
... | @@ -382,7 +382,7 @@ public final class Criteria { | ... | @@ -382,7 +382,7 @@ public final class Criteria { |
382 | 382 | ||
383 | @Override | 383 | @Override |
384 | public int hashCode() { | 384 | public int hashCode() { |
385 | - return Objects.hash(proto, type()); | 385 | + return Objects.hash(type(), proto); |
386 | } | 386 | } |
387 | 387 | ||
388 | @Override | 388 | @Override |
... | @@ -427,7 +427,7 @@ public final class Criteria { | ... | @@ -427,7 +427,7 @@ public final class Criteria { |
427 | 427 | ||
428 | @Override | 428 | @Override |
429 | public int hashCode() { | 429 | public int hashCode() { |
430 | - return Objects.hash(vlanPcp); | 430 | + return Objects.hash(type(), vlanPcp); |
431 | } | 431 | } |
432 | 432 | ||
433 | @Override | 433 | @Override |
... | @@ -474,7 +474,7 @@ public final class Criteria { | ... | @@ -474,7 +474,7 @@ public final class Criteria { |
474 | 474 | ||
475 | @Override | 475 | @Override |
476 | public int hashCode() { | 476 | public int hashCode() { |
477 | - return Objects.hash(vlanId, type()); | 477 | + return Objects.hash(type(), vlanId); |
478 | } | 478 | } |
479 | 479 | ||
480 | @Override | 480 | @Override |
... | @@ -522,7 +522,7 @@ public final class Criteria { | ... | @@ -522,7 +522,7 @@ public final class Criteria { |
522 | 522 | ||
523 | @Override | 523 | @Override |
524 | public int hashCode() { | 524 | public int hashCode() { |
525 | - return Objects.hash(tcpPort, type); | 525 | + return Objects.hash(type, tcpPort); |
526 | } | 526 | } |
527 | 527 | ||
528 | @Override | 528 | @Override |
... | @@ -568,7 +568,7 @@ public final class Criteria { | ... | @@ -568,7 +568,7 @@ public final class Criteria { |
568 | 568 | ||
569 | @Override | 569 | @Override |
570 | public int hashCode() { | 570 | public int hashCode() { |
571 | - return Objects.hash(lambda, type); | 571 | + return Objects.hash(type, lambda); |
572 | } | 572 | } |
573 | 573 | ||
574 | @Override | 574 | @Override |
... | @@ -612,7 +612,7 @@ public final class Criteria { | ... | @@ -612,7 +612,7 @@ public final class Criteria { |
612 | 612 | ||
613 | @Override | 613 | @Override |
614 | public int hashCode() { | 614 | public int hashCode() { |
615 | - return Objects.hash(signalType, type); | 615 | + return Objects.hash(type, signalType); |
616 | } | 616 | } |
617 | 617 | ||
618 | @Override | 618 | @Override | ... | ... |
... | @@ -190,7 +190,7 @@ public final class Instructions { | ... | @@ -190,7 +190,7 @@ public final class Instructions { |
190 | 190 | ||
191 | @Override | 191 | @Override |
192 | public int hashCode() { | 192 | public int hashCode() { |
193 | - return Objects.hash(port, type()); | 193 | + return Objects.hash(type(), port); |
194 | } | 194 | } |
195 | 195 | ||
196 | @Override | 196 | @Override | ... | ... |
... | @@ -70,7 +70,7 @@ public abstract class L0ModificationInstruction implements Instruction { | ... | @@ -70,7 +70,7 @@ public abstract class L0ModificationInstruction implements Instruction { |
70 | 70 | ||
71 | @Override | 71 | @Override |
72 | public int hashCode() { | 72 | public int hashCode() { |
73 | - return Objects.hash(lambda, type(), subtype); | 73 | + return Objects.hash(type(), subtype, lambda); |
74 | } | 74 | } |
75 | 75 | ||
76 | @Override | 76 | @Override | ... | ... |
... | @@ -93,7 +93,7 @@ public abstract class L2ModificationInstruction implements Instruction { | ... | @@ -93,7 +93,7 @@ public abstract class L2ModificationInstruction implements Instruction { |
93 | 93 | ||
94 | @Override | 94 | @Override |
95 | public int hashCode() { | 95 | public int hashCode() { |
96 | - return Objects.hash(mac, type(), subtype); | 96 | + return Objects.hash(type(), subtype, mac); |
97 | } | 97 | } |
98 | 98 | ||
99 | @Override | 99 | @Override |
... | @@ -142,7 +142,7 @@ public abstract class L2ModificationInstruction implements Instruction { | ... | @@ -142,7 +142,7 @@ public abstract class L2ModificationInstruction implements Instruction { |
142 | 142 | ||
143 | @Override | 143 | @Override |
144 | public int hashCode() { | 144 | public int hashCode() { |
145 | - return Objects.hash(vlanId, type(), subtype()); | 145 | + return Objects.hash(type(), subtype(), vlanId); |
146 | } | 146 | } |
147 | 147 | ||
148 | @Override | 148 | @Override |
... | @@ -191,7 +191,7 @@ public abstract class L2ModificationInstruction implements Instruction { | ... | @@ -191,7 +191,7 @@ public abstract class L2ModificationInstruction implements Instruction { |
191 | 191 | ||
192 | @Override | 192 | @Override |
193 | public int hashCode() { | 193 | public int hashCode() { |
194 | - return Objects.hash(vlanPcp, type(), subtype()); | 194 | + return Objects.hash(type(), subtype(), vlanPcp); |
195 | } | 195 | } |
196 | 196 | ||
197 | @Override | 197 | @Override | ... | ... |
... | @@ -85,7 +85,7 @@ public abstract class L3ModificationInstruction implements Instruction { | ... | @@ -85,7 +85,7 @@ public abstract class L3ModificationInstruction implements Instruction { |
85 | 85 | ||
86 | @Override | 86 | @Override |
87 | public int hashCode() { | 87 | public int hashCode() { |
88 | - return Objects.hash(ip, type(), subtype()); | 88 | + return Objects.hash(type(), subtype(), ip); |
89 | } | 89 | } |
90 | 90 | ||
91 | @Override | 91 | @Override | ... | ... |
... | @@ -23,6 +23,7 @@ import org.onlab.onos.net.flow.TrafficSelector; | ... | @@ -23,6 +23,7 @@ import org.onlab.onos.net.flow.TrafficSelector; |
23 | import org.onlab.onos.net.flow.TrafficTreatment; | 23 | import org.onlab.onos.net.flow.TrafficTreatment; |
24 | 24 | ||
25 | import java.util.Collection; | 25 | import java.util.Collection; |
26 | +import java.util.Collections; | ||
26 | import java.util.List; | 27 | import java.util.List; |
27 | 28 | ||
28 | import static com.google.common.base.Preconditions.checkNotNull; | 29 | import static com.google.common.base.Preconditions.checkNotNull; |
... | @@ -61,7 +62,7 @@ public abstract class ConnectivityIntent extends Intent { | ... | @@ -61,7 +62,7 @@ public abstract class ConnectivityIntent extends Intent { |
61 | Collection<NetworkResource> resources, | 62 | Collection<NetworkResource> resources, |
62 | TrafficSelector selector, | 63 | TrafficSelector selector, |
63 | TrafficTreatment treatment) { | 64 | TrafficTreatment treatment) { |
64 | - this(id, appId, resources, selector, treatment, null); | 65 | + this(id, appId, resources, selector, treatment, Collections.emptyList()); |
65 | } | 66 | } |
66 | 67 | ||
67 | /** | 68 | /** |
... | @@ -87,7 +88,7 @@ public abstract class ConnectivityIntent extends Intent { | ... | @@ -87,7 +88,7 @@ public abstract class ConnectivityIntent extends Intent { |
87 | super(id, appId, resources); | 88 | super(id, appId, resources); |
88 | this.selector = checkNotNull(selector); | 89 | this.selector = checkNotNull(selector); |
89 | this.treatment = checkNotNull(treatment); | 90 | this.treatment = checkNotNull(treatment); |
90 | - this.constraints = constraints; | 91 | + this.constraints = checkNotNull(constraints); |
91 | } | 92 | } |
92 | 93 | ||
93 | /** | 94 | /** |
... | @@ -97,7 +98,7 @@ public abstract class ConnectivityIntent extends Intent { | ... | @@ -97,7 +98,7 @@ public abstract class ConnectivityIntent extends Intent { |
97 | super(); | 98 | super(); |
98 | this.selector = null; | 99 | this.selector = null; |
99 | this.treatment = null; | 100 | this.treatment = null; |
100 | - this.constraints = null; | 101 | + this.constraints = Collections.emptyList(); |
101 | } | 102 | } |
102 | 103 | ||
103 | /** | 104 | /** | ... | ... |
... | @@ -21,6 +21,7 @@ import org.onlab.onos.net.HostId; | ... | @@ -21,6 +21,7 @@ import org.onlab.onos.net.HostId; |
21 | import org.onlab.onos.net.flow.TrafficSelector; | 21 | import org.onlab.onos.net.flow.TrafficSelector; |
22 | import org.onlab.onos.net.flow.TrafficTreatment; | 22 | import org.onlab.onos.net.flow.TrafficTreatment; |
23 | 23 | ||
24 | +import java.util.Collections; | ||
24 | import java.util.List; | 25 | import java.util.List; |
25 | 26 | ||
26 | import static com.google.common.base.Preconditions.checkNotNull; | 27 | import static com.google.common.base.Preconditions.checkNotNull; |
... | @@ -46,7 +47,7 @@ public final class HostToHostIntent extends ConnectivityIntent { | ... | @@ -46,7 +47,7 @@ public final class HostToHostIntent extends ConnectivityIntent { |
46 | public HostToHostIntent(ApplicationId appId, HostId one, HostId two, | 47 | public HostToHostIntent(ApplicationId appId, HostId one, HostId two, |
47 | TrafficSelector selector, | 48 | TrafficSelector selector, |
48 | TrafficTreatment treatment) { | 49 | TrafficTreatment treatment) { |
49 | - this(appId, one, two, selector, treatment, null); | 50 | + this(appId, one, two, selector, treatment, Collections.emptyList()); |
50 | } | 51 | } |
51 | 52 | ||
52 | /** | 53 | /** | ... | ... |
... | @@ -22,6 +22,7 @@ import org.onlab.onos.net.Link; | ... | @@ -22,6 +22,7 @@ import org.onlab.onos.net.Link; |
22 | import org.onlab.onos.net.flow.TrafficSelector; | 22 | import org.onlab.onos.net.flow.TrafficSelector; |
23 | import org.onlab.onos.net.flow.TrafficTreatment; | 23 | import org.onlab.onos.net.flow.TrafficTreatment; |
24 | 24 | ||
25 | +import java.util.Collections; | ||
25 | import java.util.List; | 26 | import java.util.List; |
26 | import java.util.Set; | 27 | import java.util.Set; |
27 | 28 | ||
... | @@ -51,7 +52,7 @@ public final class LinkCollectionIntent extends ConnectivityIntent { | ... | @@ -51,7 +52,7 @@ public final class LinkCollectionIntent extends ConnectivityIntent { |
51 | TrafficTreatment treatment, | 52 | TrafficTreatment treatment, |
52 | Set<Link> links, | 53 | Set<Link> links, |
53 | ConnectPoint egressPoint) { | 54 | ConnectPoint egressPoint) { |
54 | - this(appId, selector , treatment, links, egressPoint, null); | 55 | + this(appId, selector , treatment, links, egressPoint, Collections.emptyList()); |
55 | } | 56 | } |
56 | 57 | ||
57 | /** | 58 | /** | ... | ... |
... | @@ -22,6 +22,7 @@ import org.onlab.onos.net.ConnectPoint; | ... | @@ -22,6 +22,7 @@ import org.onlab.onos.net.ConnectPoint; |
22 | import org.onlab.onos.net.flow.TrafficSelector; | 22 | import org.onlab.onos.net.flow.TrafficSelector; |
23 | import org.onlab.onos.net.flow.TrafficTreatment; | 23 | import org.onlab.onos.net.flow.TrafficTreatment; |
24 | 24 | ||
25 | +import java.util.Collections; | ||
25 | import java.util.List; | 26 | import java.util.List; |
26 | import java.util.Set; | 27 | import java.util.Set; |
27 | 28 | ||
... | @@ -55,14 +56,7 @@ public final class MultiPointToSinglePointIntent extends ConnectivityIntent { | ... | @@ -55,14 +56,7 @@ public final class MultiPointToSinglePointIntent extends ConnectivityIntent { |
55 | TrafficTreatment treatment, | 56 | TrafficTreatment treatment, |
56 | Set<ConnectPoint> ingressPoints, | 57 | Set<ConnectPoint> ingressPoints, |
57 | ConnectPoint egressPoint) { | 58 | ConnectPoint egressPoint) { |
58 | - super(id(MultiPointToSinglePointIntent.class, selector, treatment, | 59 | + this(appId, selector, treatment, ingressPoints, egressPoint, Collections.emptyList()); |
59 | - ingressPoints, egressPoint), appId, null, selector, treatment); | ||
60 | - | ||
61 | - checkNotNull(ingressPoints); | ||
62 | - checkArgument(!ingressPoints.isEmpty(), "Ingress point set cannot be empty"); | ||
63 | - | ||
64 | - this.ingressPoints = Sets.newHashSet(ingressPoints); | ||
65 | - this.egressPoint = checkNotNull(egressPoint); | ||
66 | } | 60 | } |
67 | 61 | ||
68 | /** | 62 | /** | ... | ... |
... | @@ -15,6 +15,7 @@ | ... | @@ -15,6 +15,7 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.intent; | 16 | package org.onlab.onos.net.intent; |
17 | 17 | ||
18 | +import java.util.Collections; | ||
18 | import java.util.List; | 19 | import java.util.List; |
19 | 20 | ||
20 | import com.google.common.base.MoreObjects; | 21 | import com.google.common.base.MoreObjects; |
... | @@ -42,9 +43,7 @@ public class PathIntent extends ConnectivityIntent { | ... | @@ -42,9 +43,7 @@ public class PathIntent extends ConnectivityIntent { |
42 | */ | 43 | */ |
43 | public PathIntent(ApplicationId appId, TrafficSelector selector, | 44 | public PathIntent(ApplicationId appId, TrafficSelector selector, |
44 | TrafficTreatment treatment, Path path) { | 45 | TrafficTreatment treatment, Path path) { |
45 | - super(id(PathIntent.class, selector, treatment, path), appId, | 46 | + this(appId, selector, treatment, path, Collections.emptyList()); |
46 | - resources(path.links()), selector, treatment); | ||
47 | - this.path = path; | ||
48 | } | 47 | } |
49 | 48 | ||
50 | /** | 49 | /** | ... | ... |
... | @@ -21,6 +21,8 @@ import org.onlab.onos.net.resource.LinkResourceService; | ... | @@ -21,6 +21,8 @@ import org.onlab.onos.net.resource.LinkResourceService; |
21 | 21 | ||
22 | import java.util.Objects; | 22 | import java.util.Objects; |
23 | 23 | ||
24 | +import static org.onlab.onos.net.AnnotationKeys.getAnnotatedValue; | ||
25 | + | ||
24 | /** | 26 | /** |
25 | * Constraint that evaluates an arbitrary link annotated value is under the specified threshold. | 27 | * Constraint that evaluates an arbitrary link annotated value is under the specified threshold. |
26 | */ | 28 | */ |
... | @@ -41,6 +43,12 @@ public class AnnotationConstraint extends BooleanConstraint { | ... | @@ -41,6 +43,12 @@ public class AnnotationConstraint extends BooleanConstraint { |
41 | this.threshold = threshold; | 43 | this.threshold = threshold; |
42 | } | 44 | } |
43 | 45 | ||
46 | + // Constructor for serialization | ||
47 | + private AnnotationConstraint() { | ||
48 | + this.key = ""; | ||
49 | + this.threshold = 0; | ||
50 | + } | ||
51 | + | ||
44 | /** | 52 | /** |
45 | * Returns the key of link annotation this constraint designates. | 53 | * Returns the key of link annotation this constraint designates. |
46 | * @return key of link annotation | 54 | * @return key of link annotation |
... | @@ -65,25 +73,6 @@ public class AnnotationConstraint extends BooleanConstraint { | ... | @@ -65,25 +73,6 @@ public class AnnotationConstraint extends BooleanConstraint { |
65 | return value <= threshold; | 73 | return value <= threshold; |
66 | } | 74 | } |
67 | 75 | ||
68 | - /** | ||
69 | - * Returns the annotated value of the specified link. The annotated value | ||
70 | - * is expected to be String that can be parsed as double. If parsing fails, | ||
71 | - * the returned value will be 1.0. | ||
72 | - * | ||
73 | - * @param link link whose annotated value is obtained | ||
74 | - * @param key key of link annotation | ||
75 | - * @return double value of link annotation for the specified key | ||
76 | - */ | ||
77 | - private double getAnnotatedValue(Link link, String key) { | ||
78 | - double value; | ||
79 | - try { | ||
80 | - value = Double.parseDouble(link.annotations().value(key)); | ||
81 | - } catch (NumberFormatException e) { | ||
82 | - value = 1.0; | ||
83 | - } | ||
84 | - return value; | ||
85 | - } | ||
86 | - | ||
87 | @Override | 76 | @Override |
88 | public double cost(Link link, LinkResourceService resourceService) { | 77 | public double cost(Link link, LinkResourceService resourceService) { |
89 | if (isValid(link, resourceService)) { | 78 | if (isValid(link, resourceService)) { | ... | ... |
... | @@ -25,14 +25,14 @@ import java.time.Duration; | ... | @@ -25,14 +25,14 @@ import java.time.Duration; |
25 | import java.time.temporal.ChronoUnit; | 25 | import java.time.temporal.ChronoUnit; |
26 | import java.util.Objects; | 26 | import java.util.Objects; |
27 | 27 | ||
28 | +import static org.onlab.onos.net.AnnotationKeys.LATENCY; | ||
29 | +import static org.onlab.onos.net.AnnotationKeys.getAnnotatedValue; | ||
30 | + | ||
28 | /** | 31 | /** |
29 | * Constraint that evaluates the latency through a path. | 32 | * Constraint that evaluates the latency through a path. |
30 | */ | 33 | */ |
31 | public class LatencyConstraint implements Constraint { | 34 | public class LatencyConstraint implements Constraint { |
32 | 35 | ||
33 | - // TODO: formalize the key for latency all over the codes. | ||
34 | - private static final String LATENCY_KEY = "latency"; | ||
35 | - | ||
36 | private final Duration latency; | 36 | private final Duration latency; |
37 | 37 | ||
38 | /** | 38 | /** |
... | @@ -43,22 +43,18 @@ public class LatencyConstraint implements Constraint { | ... | @@ -43,22 +43,18 @@ public class LatencyConstraint implements Constraint { |
43 | this.latency = latency; | 43 | this.latency = latency; |
44 | } | 44 | } |
45 | 45 | ||
46 | + // Constructor for serialization | ||
47 | + private LatencyConstraint() { | ||
48 | + this.latency = Duration.ZERO; | ||
49 | + } | ||
50 | + | ||
46 | public Duration latency() { | 51 | public Duration latency() { |
47 | return latency; | 52 | return latency; |
48 | } | 53 | } |
49 | 54 | ||
50 | @Override | 55 | @Override |
51 | public double cost(Link link, LinkResourceService resourceService) { | 56 | public double cost(Link link, LinkResourceService resourceService) { |
52 | - String value = link.annotations().value(LATENCY_KEY); | 57 | + return getAnnotatedValue(link, LATENCY); |
53 | - | ||
54 | - double latencyInMicroSec; | ||
55 | - try { | ||
56 | - latencyInMicroSec = Double.parseDouble(value); | ||
57 | - } catch (NumberFormatException e) { | ||
58 | - latencyInMicroSec = 1.0; | ||
59 | - } | ||
60 | - | ||
61 | - return latencyInMicroSec; | ||
62 | } | 58 | } |
63 | 59 | ||
64 | @Override | 60 | @Override | ... | ... |
... | @@ -21,6 +21,7 @@ import org.onlab.onos.net.DeviceId; | ... | @@ -21,6 +21,7 @@ import org.onlab.onos.net.DeviceId; |
21 | import org.onlab.onos.net.Link; | 21 | import org.onlab.onos.net.Link; |
22 | import org.onlab.onos.net.resource.LinkResourceService; | 22 | import org.onlab.onos.net.resource.LinkResourceService; |
23 | 23 | ||
24 | +import java.util.Collections; | ||
24 | import java.util.Objects; | 25 | import java.util.Objects; |
25 | import java.util.Set; | 26 | import java.util.Set; |
26 | 27 | ||
... | @@ -39,6 +40,11 @@ public class ObstacleConstraint extends BooleanConstraint { | ... | @@ -39,6 +40,11 @@ public class ObstacleConstraint extends BooleanConstraint { |
39 | this.obstacles = ImmutableSet.copyOf(obstacles); | 40 | this.obstacles = ImmutableSet.copyOf(obstacles); |
40 | } | 41 | } |
41 | 42 | ||
43 | + // Constructor for serialization | ||
44 | + private ObstacleConstraint() { | ||
45 | + this.obstacles = Collections.emptySet(); | ||
46 | + } | ||
47 | + | ||
42 | @Override | 48 | @Override |
43 | public boolean isValid(Link link, LinkResourceService resourceService) { | 49 | public boolean isValid(Link link, LinkResourceService resourceService) { |
44 | DeviceId src = link.src().deviceId(); | 50 | DeviceId src = link.src().deviceId(); | ... | ... |
... | @@ -17,12 +17,13 @@ package org.onlab.onos.net.intent.constraint; | ... | @@ -17,12 +17,13 @@ package org.onlab.onos.net.intent.constraint; |
17 | 17 | ||
18 | import com.google.common.base.MoreObjects; | 18 | import com.google.common.base.MoreObjects; |
19 | import com.google.common.collect.ImmutableList; | 19 | import com.google.common.collect.ImmutableList; |
20 | -import org.onlab.onos.net.ElementId; | 20 | +import org.onlab.onos.net.DeviceId; |
21 | import org.onlab.onos.net.Link; | 21 | import org.onlab.onos.net.Link; |
22 | import org.onlab.onos.net.Path; | 22 | import org.onlab.onos.net.Path; |
23 | import org.onlab.onos.net.intent.Constraint; | 23 | import org.onlab.onos.net.intent.Constraint; |
24 | import org.onlab.onos.net.resource.LinkResourceService; | 24 | import org.onlab.onos.net.resource.LinkResourceService; |
25 | 25 | ||
26 | +import java.util.Collections; | ||
26 | import java.util.LinkedList; | 27 | import java.util.LinkedList; |
27 | import java.util.List; | 28 | import java.util.List; |
28 | import java.util.Objects; | 29 | import java.util.Objects; |
... | @@ -35,20 +36,25 @@ import static com.google.common.base.Preconditions.checkNotNull; | ... | @@ -35,20 +36,25 @@ import static com.google.common.base.Preconditions.checkNotNull; |
35 | */ | 36 | */ |
36 | public class WaypointConstraint implements Constraint { | 37 | public class WaypointConstraint implements Constraint { |
37 | 38 | ||
38 | - private final List<ElementId> waypoints; | 39 | + private final List<DeviceId> waypoints; |
39 | 40 | ||
40 | /** | 41 | /** |
41 | * Creates a new waypoint constraint. | 42 | * Creates a new waypoint constraint. |
42 | * | 43 | * |
43 | * @param waypoints waypoints | 44 | * @param waypoints waypoints |
44 | */ | 45 | */ |
45 | - public WaypointConstraint(ElementId... waypoints) { | 46 | + public WaypointConstraint(DeviceId... waypoints) { |
46 | checkNotNull(waypoints, "waypoints cannot be null"); | 47 | checkNotNull(waypoints, "waypoints cannot be null"); |
47 | checkArgument(waypoints.length > 0, "length of waypoints should be more than 0"); | 48 | checkArgument(waypoints.length > 0, "length of waypoints should be more than 0"); |
48 | this.waypoints = ImmutableList.copyOf(waypoints); | 49 | this.waypoints = ImmutableList.copyOf(waypoints); |
49 | } | 50 | } |
50 | 51 | ||
51 | - public List<ElementId> waypoints() { | 52 | + // Constructor for serialization |
53 | + private WaypointConstraint() { | ||
54 | + this.waypoints = Collections.emptyList(); | ||
55 | + } | ||
56 | + | ||
57 | + public List<DeviceId> waypoints() { | ||
52 | return waypoints; | 58 | return waypoints; |
53 | } | 59 | } |
54 | 60 | ||
... | @@ -60,8 +66,8 @@ public class WaypointConstraint implements Constraint { | ... | @@ -60,8 +66,8 @@ public class WaypointConstraint implements Constraint { |
60 | 66 | ||
61 | @Override | 67 | @Override |
62 | public boolean validate(Path path, LinkResourceService resourceService) { | 68 | public boolean validate(Path path, LinkResourceService resourceService) { |
63 | - LinkedList<ElementId> waypoints = new LinkedList<>(this.waypoints); | 69 | + LinkedList<DeviceId> waypoints = new LinkedList<>(this.waypoints); |
64 | - ElementId current = waypoints.poll(); | 70 | + DeviceId current = waypoints.poll(); |
65 | // This is safe because Path class ensures the number of links are more than 0 | 71 | // This is safe because Path class ensures the number of links are more than 0 |
66 | Link firstLink = path.links().get(0); | 72 | Link firstLink = path.links().get(0); |
67 | if (firstLink.src().elementId().equals(current)) { | 73 | if (firstLink.src().elementId().equals(current)) { | ... | ... |
... | @@ -37,6 +37,7 @@ import static org.easymock.EasyMock.createMock; | ... | @@ -37,6 +37,7 @@ import static org.easymock.EasyMock.createMock; |
37 | import static org.hamcrest.Matchers.closeTo; | 37 | import static org.hamcrest.Matchers.closeTo; |
38 | import static org.hamcrest.Matchers.is; | 38 | import static org.hamcrest.Matchers.is; |
39 | import static org.junit.Assert.assertThat; | 39 | import static org.junit.Assert.assertThat; |
40 | +import static org.onlab.onos.net.AnnotationKeys.LATENCY; | ||
40 | import static org.onlab.onos.net.DefaultLinkTest.cp; | 41 | import static org.onlab.onos.net.DefaultLinkTest.cp; |
41 | import static org.onlab.onos.net.DeviceId.deviceId; | 42 | import static org.onlab.onos.net.DeviceId.deviceId; |
42 | import static org.onlab.onos.net.Link.Type.DIRECT; | 43 | import static org.onlab.onos.net.Link.Type.DIRECT; |
... | @@ -51,7 +52,6 @@ public class LatencyConstraintTest { | ... | @@ -51,7 +52,6 @@ public class LatencyConstraintTest { |
51 | private static final PortNumber PN3 = PortNumber.portNumber(3); | 52 | private static final PortNumber PN3 = PortNumber.portNumber(3); |
52 | private static final PortNumber PN4 = PortNumber.portNumber(4); | 53 | private static final PortNumber PN4 = PortNumber.portNumber(4); |
53 | private static final ProviderId PROVIDER_ID = new ProviderId("of", "foo"); | 54 | private static final ProviderId PROVIDER_ID = new ProviderId("of", "foo"); |
54 | - private static final String LATENCY_KEY = "latency"; | ||
55 | private static final String LATENCY1 = "3.0"; | 55 | private static final String LATENCY1 = "3.0"; |
56 | private static final String LATENCY2 = "4.0"; | 56 | private static final String LATENCY2 = "4.0"; |
57 | 57 | ||
... | @@ -66,8 +66,8 @@ public class LatencyConstraintTest { | ... | @@ -66,8 +66,8 @@ public class LatencyConstraintTest { |
66 | public void setUp() { | 66 | public void setUp() { |
67 | linkResourceService = createMock(LinkResourceService.class); | 67 | linkResourceService = createMock(LinkResourceService.class); |
68 | 68 | ||
69 | - Annotations annotations1 = DefaultAnnotations.builder().set(LATENCY_KEY, LATENCY1).build(); | 69 | + Annotations annotations1 = DefaultAnnotations.builder().set(LATENCY, LATENCY1).build(); |
70 | - Annotations annotations2 = DefaultAnnotations.builder().set(LATENCY_KEY, LATENCY2).build(); | 70 | + Annotations annotations2 = DefaultAnnotations.builder().set(LATENCY, LATENCY2).build(); |
71 | 71 | ||
72 | link1 = new DefaultLink(PROVIDER_ID, cp(DID1, PN1), cp(DID2, PN2), DIRECT, annotations1); | 72 | link1 = new DefaultLink(PROVIDER_ID, cp(DID1, PN1), cp(DID2, PN2), DIRECT, annotations1); |
73 | link2 = new DefaultLink(PROVIDER_ID, cp(DID2, PN3), cp(DID3, PN4), DIRECT, annotations2); | 73 | link2 = new DefaultLink(PROVIDER_ID, cp(DID2, PN3), cp(DID3, PN4), DIRECT, annotations2); | ... | ... |
... | @@ -18,9 +18,13 @@ package org.onlab.onos.net.device.impl; | ... | @@ -18,9 +18,13 @@ package org.onlab.onos.net.device.impl; |
18 | import static com.google.common.base.Preconditions.checkNotNull; | 18 | import static com.google.common.base.Preconditions.checkNotNull; |
19 | import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_MASTERSHIP_CHANGED; | 19 | import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_MASTERSHIP_CHANGED; |
20 | import static org.onlab.onos.net.MastershipRole.*; | 20 | import static org.onlab.onos.net.MastershipRole.*; |
21 | +import static org.onlab.util.Tools.namedThreads; | ||
21 | import static org.slf4j.LoggerFactory.getLogger; | 22 | import static org.slf4j.LoggerFactory.getLogger; |
22 | 23 | ||
23 | import java.util.List; | 24 | import java.util.List; |
25 | +import java.util.concurrent.Executors; | ||
26 | +import java.util.concurrent.ScheduledExecutorService; | ||
27 | +import java.util.concurrent.TimeUnit; | ||
24 | 28 | ||
25 | import org.apache.felix.scr.annotations.Activate; | 29 | import org.apache.felix.scr.annotations.Activate; |
26 | import org.apache.felix.scr.annotations.Component; | 30 | import org.apache.felix.scr.annotations.Component; |
... | @@ -83,6 +87,8 @@ public class DeviceManager | ... | @@ -83,6 +87,8 @@ public class DeviceManager |
83 | 87 | ||
84 | private final MastershipListener mastershipListener = new InternalMastershipListener(); | 88 | private final MastershipListener mastershipListener = new InternalMastershipListener(); |
85 | 89 | ||
90 | + private ScheduledExecutorService backgroundService; | ||
91 | + | ||
86 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 92 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
87 | protected DeviceStore store; | 93 | protected DeviceStore store; |
88 | 94 | ||
... | @@ -102,15 +108,31 @@ public class DeviceManager | ... | @@ -102,15 +108,31 @@ public class DeviceManager |
102 | 108 | ||
103 | @Activate | 109 | @Activate |
104 | public void activate() { | 110 | public void activate() { |
111 | + backgroundService = Executors.newSingleThreadScheduledExecutor(namedThreads("device-manager-background")); | ||
112 | + | ||
105 | store.setDelegate(delegate); | 113 | store.setDelegate(delegate); |
106 | eventDispatcher.addSink(DeviceEvent.class, listenerRegistry); | 114 | eventDispatcher.addSink(DeviceEvent.class, listenerRegistry); |
107 | mastershipService.addListener(mastershipListener); | 115 | mastershipService.addListener(mastershipListener); |
108 | termService = mastershipService.requestTermService(); | 116 | termService = mastershipService.requestTermService(); |
117 | + | ||
118 | + backgroundService.scheduleWithFixedDelay(new Runnable() { | ||
119 | + | ||
120 | + @Override | ||
121 | + public void run() { | ||
122 | + try { | ||
123 | + mastershipCheck(); | ||
124 | + } catch (Exception e) { | ||
125 | + log.error("Exception thrown during integrity check", e); | ||
126 | + } | ||
127 | + } | ||
128 | + }, 1, 1, TimeUnit.MINUTES); | ||
109 | log.info("Started"); | 129 | log.info("Started"); |
110 | } | 130 | } |
111 | 131 | ||
112 | @Deactivate | 132 | @Deactivate |
113 | public void deactivate() { | 133 | public void deactivate() { |
134 | + backgroundService.shutdown(); | ||
135 | + | ||
114 | store.unsetDelegate(delegate); | 136 | store.unsetDelegate(delegate); |
115 | mastershipService.removeListener(mastershipListener); | 137 | mastershipService.removeListener(mastershipListener); |
116 | eventDispatcher.removeSink(DeviceEvent.class); | 138 | eventDispatcher.removeSink(DeviceEvent.class); |
... | @@ -172,10 +194,6 @@ public class DeviceManager | ... | @@ -172,10 +194,6 @@ public class DeviceManager |
172 | @Override | 194 | @Override |
173 | public void removeDevice(DeviceId deviceId) { | 195 | public void removeDevice(DeviceId deviceId) { |
174 | checkNotNull(deviceId, DEVICE_ID_NULL); | 196 | checkNotNull(deviceId, DEVICE_ID_NULL); |
175 | - // XXX is this intended to apply to the full global topology? | ||
176 | - // if so, we probably don't want the fact that we aren't | ||
177 | - // MASTER to get in the way, as it would do now. | ||
178 | - // FIXME: forward or broadcast and let the Master handler the event. | ||
179 | DeviceEvent event = store.removeDevice(deviceId); | 197 | DeviceEvent event = store.removeDevice(deviceId); |
180 | if (event != null) { | 198 | if (event != null) { |
181 | log.info("Device {} administratively removed", deviceId); | 199 | log.info("Device {} administratively removed", deviceId); |
... | @@ -199,6 +217,31 @@ public class DeviceManager | ... | @@ -199,6 +217,31 @@ public class DeviceManager |
199 | return new InternalDeviceProviderService(provider); | 217 | return new InternalDeviceProviderService(provider); |
200 | } | 218 | } |
201 | 219 | ||
220 | + /** | ||
221 | + * Checks if all the reachable devices have a valid mastership role. | ||
222 | + */ | ||
223 | + private void mastershipCheck() { | ||
224 | + log.debug("Checking mastership"); | ||
225 | + for (Device device : getDevices()) { | ||
226 | + final DeviceId deviceId = device.id(); | ||
227 | + log.debug("Checking device {}", deviceId); | ||
228 | + | ||
229 | + if (!isReachable(deviceId)) { | ||
230 | + continue; | ||
231 | + } | ||
232 | + | ||
233 | + if (mastershipService.getLocalRole(deviceId) != NONE) { | ||
234 | + continue; | ||
235 | + } | ||
236 | + | ||
237 | + log.info("{} is reachable but did not have a valid role, reasserting", deviceId); | ||
238 | + | ||
239 | + // isReachable but was not MASTER or STANDBY, get a role and apply | ||
240 | + // Note: NONE triggers request to MastershipService | ||
241 | + reassertRole(deviceId, NONE); | ||
242 | + } | ||
243 | + } | ||
244 | + | ||
202 | // Personalized device provider service issued to the supplied provider. | 245 | // Personalized device provider service issued to the supplied provider. |
203 | private class InternalDeviceProviderService | 246 | private class InternalDeviceProviderService |
204 | extends AbstractProviderService<DeviceProvider> | 247 | extends AbstractProviderService<DeviceProvider> |
... | @@ -418,18 +461,15 @@ public class DeviceManager | ... | @@ -418,18 +461,15 @@ public class DeviceManager |
418 | } | 461 | } |
419 | } | 462 | } |
420 | 463 | ||
421 | - // Intercepts mastership events | ||
422 | - private class InternalMastershipListener implements MastershipListener { | ||
423 | - | ||
424 | // Applies the specified role to the device; ignores NONE | 464 | // Applies the specified role to the device; ignores NONE |
425 | /** | 465 | /** |
426 | - * Apply role in reaction to mastership event. | 466 | + * Apply role to device and send probe if MASTER. |
427 | * | 467 | * |
428 | * @param deviceId device identifier | 468 | * @param deviceId device identifier |
429 | * @param newRole new role to apply to the device | 469 | * @param newRole new role to apply to the device |
430 | * @return true if the request was sent to provider | 470 | * @return true if the request was sent to provider |
431 | */ | 471 | */ |
432 | - private boolean applyRole(DeviceId deviceId, MastershipRole newRole) { | 472 | + private boolean applyRoleAndProbe(DeviceId deviceId, MastershipRole newRole) { |
433 | if (newRole.equals(MastershipRole.NONE)) { | 473 | if (newRole.equals(MastershipRole.NONE)) { |
434 | //no-op | 474 | //no-op |
435 | return true; | 475 | return true; |
... | @@ -460,6 +500,73 @@ public class DeviceManager | ... | @@ -460,6 +500,73 @@ public class DeviceManager |
460 | return true; | 500 | return true; |
461 | } | 501 | } |
462 | 502 | ||
503 | + /** | ||
504 | + * Reaasert role for specified device connected to this node. | ||
505 | + * | ||
506 | + * @param did device identifier | ||
507 | + * @param nextRole role to apply. If NONE is specified, | ||
508 | + * it will ask mastership service for a role and apply it. | ||
509 | + */ | ||
510 | + private void reassertRole(final DeviceId did, | ||
511 | + final MastershipRole nextRole) { | ||
512 | + | ||
513 | + final NodeId myNodeId = clusterService.getLocalNode().id(); | ||
514 | + MastershipRole myNextRole = nextRole; | ||
515 | + if (myNextRole == NONE) { | ||
516 | + mastershipService.requestRoleFor(did); | ||
517 | + MastershipTerm term = termService.getMastershipTerm(did); | ||
518 | + if (myNodeId.equals(term.master())) { | ||
519 | + myNextRole = MASTER; | ||
520 | + } else { | ||
521 | + myNextRole = STANDBY; | ||
522 | + } | ||
523 | + } | ||
524 | + | ||
525 | + switch (myNextRole) { | ||
526 | + case MASTER: | ||
527 | + final Device device = getDevice(did); | ||
528 | + if ((device != null) && !isAvailable(did)) { | ||
529 | + //flag the device as online. Is there a better way to do this? | ||
530 | + DefaultDeviceDescription deviceDescription | ||
531 | + = new DefaultDeviceDescription(did.uri(), | ||
532 | + device.type(), | ||
533 | + device.manufacturer(), | ||
534 | + device.hwVersion(), | ||
535 | + device.swVersion(), | ||
536 | + device.serialNumber(), | ||
537 | + device.chassisId()); | ||
538 | + DeviceEvent devEvent = | ||
539 | + store.createOrUpdateDevice(device.providerId(), did, | ||
540 | + deviceDescription); | ||
541 | + post(devEvent); | ||
542 | + } | ||
543 | + // TODO: should apply role only if there is mismatch | ||
544 | + log.info("Applying role {} to {}", myNextRole, did); | ||
545 | + if (!applyRoleAndProbe(did, MASTER)) { | ||
546 | + // immediately failed to apply role | ||
547 | + mastershipService.relinquishMastership(did); | ||
548 | + // FIXME disconnect? | ||
549 | + } | ||
550 | + break; | ||
551 | + case STANDBY: | ||
552 | + log.info("Applying role {} to {}", myNextRole, did); | ||
553 | + if (!applyRoleAndProbe(did, STANDBY)) { | ||
554 | + // immediately failed to apply role | ||
555 | + mastershipService.relinquishMastership(did); | ||
556 | + // FIXME disconnect? | ||
557 | + } | ||
558 | + break; | ||
559 | + case NONE: | ||
560 | + default: | ||
561 | + // should never reach here | ||
562 | + log.error("You didn't see anything. I did not exist."); | ||
563 | + break; | ||
564 | + } | ||
565 | + } | ||
566 | + | ||
567 | + // Intercepts mastership events | ||
568 | + private class InternalMastershipListener implements MastershipListener { | ||
569 | + | ||
463 | @Override | 570 | @Override |
464 | public void event(MastershipEvent event) { | 571 | public void event(MastershipEvent event) { |
465 | 572 | ||
... | @@ -499,55 +606,12 @@ public class DeviceManager | ... | @@ -499,55 +606,12 @@ public class DeviceManager |
499 | + "Relinquishing role. ", | 606 | + "Relinquishing role. ", |
500 | myNextRole, did); | 607 | myNextRole, did); |
501 | mastershipService.relinquishMastership(did); | 608 | mastershipService.relinquishMastership(did); |
502 | - // FIXME disconnect? | ||
503 | } | 609 | } |
504 | return; | 610 | return; |
505 | } | 611 | } |
506 | 612 | ||
507 | // device is connected to this node: | 613 | // device is connected to this node: |
508 | - | 614 | + reassertRole(did, myNextRole); |
509 | - if (myNextRole == NONE) { | ||
510 | - mastershipService.requestRoleFor(did); | ||
511 | - MastershipTerm term = termService.getMastershipTerm(did); | ||
512 | - if (myNodeId.equals(term.master())) { | ||
513 | - myNextRole = MASTER; | ||
514 | - } else { | ||
515 | - myNextRole = STANDBY; | ||
516 | - } | ||
517 | - } | ||
518 | - | ||
519 | - switch (myNextRole) { | ||
520 | - case MASTER: | ||
521 | - final Device device = getDevice(did); | ||
522 | - if ((device != null) && !isAvailable(did)) { | ||
523 | - //flag the device as online. Is there a better way to do this? | ||
524 | - DefaultDeviceDescription deviceDescription | ||
525 | - = new DefaultDeviceDescription(did.uri(), | ||
526 | - device.type(), | ||
527 | - device.manufacturer(), | ||
528 | - device.hwVersion(), | ||
529 | - device.swVersion(), | ||
530 | - device.serialNumber(), | ||
531 | - device.chassisId()); | ||
532 | - DeviceEvent devEvent = | ||
533 | - store.createOrUpdateDevice(device.providerId(), did, | ||
534 | - deviceDescription); | ||
535 | - post(devEvent); | ||
536 | - } | ||
537 | - // TODO: should apply role only if there is mismatch | ||
538 | - log.info("Applying role {} to {}", myNextRole, did); | ||
539 | - applyRole(did, MASTER); | ||
540 | - break; | ||
541 | - case STANDBY: | ||
542 | - log.info("Applying role {} to {}", myNextRole, did); | ||
543 | - applyRole(did, STANDBY); | ||
544 | - break; | ||
545 | - case NONE: | ||
546 | - default: | ||
547 | - // should never reach here | ||
548 | - log.error("You didn't see anything. I did not exist."); | ||
549 | - break; | ||
550 | - } | ||
551 | } | 615 | } |
552 | } | 616 | } |
553 | 617 | ... | ... |
... | @@ -15,21 +15,12 @@ | ... | @@ -15,21 +15,12 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.flow.impl; | 16 | package org.onlab.onos.net.flow.impl; |
17 | 17 | ||
18 | -import static com.google.common.base.Preconditions.checkNotNull; | 18 | +import com.google.common.collect.ArrayListMultimap; |
19 | -import static org.slf4j.LoggerFactory.getLogger; | 19 | +import com.google.common.collect.Iterables; |
20 | -import static org.onlab.util.Tools.namedThreads; | 20 | +import com.google.common.collect.Lists; |
21 | - | 21 | +import com.google.common.collect.Maps; |
22 | -import java.util.List; | 22 | +import com.google.common.collect.Multimap; |
23 | -import java.util.Map; | 23 | +import com.google.common.collect.Sets; |
24 | -import java.util.Set; | ||
25 | -import java.util.concurrent.CancellationException; | ||
26 | -import java.util.concurrent.ExecutionException; | ||
27 | -import java.util.concurrent.ExecutorService; | ||
28 | -import java.util.concurrent.Executors; | ||
29 | -import java.util.concurrent.Future; | ||
30 | -import java.util.concurrent.TimeUnit; | ||
31 | -import java.util.concurrent.TimeoutException; | ||
32 | -import java.util.concurrent.atomic.AtomicReference; | ||
33 | 24 | ||
34 | import org.apache.felix.scr.annotations.Activate; | 25 | import org.apache.felix.scr.annotations.Activate; |
35 | import org.apache.felix.scr.annotations.Component; | 26 | import org.apache.felix.scr.annotations.Component; |
... | @@ -64,14 +55,22 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry; | ... | @@ -64,14 +55,22 @@ import org.onlab.onos.net.provider.AbstractProviderRegistry; |
64 | import org.onlab.onos.net.provider.AbstractProviderService; | 55 | import org.onlab.onos.net.provider.AbstractProviderService; |
65 | import org.slf4j.Logger; | 56 | import org.slf4j.Logger; |
66 | 57 | ||
67 | -import com.google.common.collect.ArrayListMultimap; | 58 | +import java.util.HashSet; |
68 | -import com.google.common.collect.Iterables; | 59 | +import java.util.List; |
69 | -import com.google.common.collect.Lists; | 60 | +import java.util.Map; |
70 | -import com.google.common.collect.Maps; | 61 | +import java.util.Set; |
71 | -import com.google.common.collect.Multimap; | 62 | +import java.util.concurrent.CancellationException; |
72 | -import com.google.common.collect.Sets; | 63 | +import java.util.concurrent.ExecutionException; |
73 | -import com.google.common.util.concurrent.Futures; | 64 | +import java.util.concurrent.ExecutorService; |
74 | -import com.google.common.util.concurrent.ListenableFuture; | 65 | +import java.util.concurrent.Executors; |
66 | +import java.util.concurrent.Future; | ||
67 | +import java.util.concurrent.TimeUnit; | ||
68 | +import java.util.concurrent.TimeoutException; | ||
69 | +import java.util.concurrent.atomic.AtomicReference; | ||
70 | + | ||
71 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
72 | +import static org.onlab.util.Tools.namedThreads; | ||
73 | +import static org.slf4j.LoggerFactory.getLogger; | ||
75 | 74 | ||
76 | /** | 75 | /** |
77 | * Provides implementation of the flow NB & SB APIs. | 76 | * Provides implementation of the flow NB & SB APIs. |
... | @@ -92,8 +91,7 @@ public class FlowRuleManager | ... | @@ -92,8 +91,7 @@ public class FlowRuleManager |
92 | 91 | ||
93 | private final FlowRuleStoreDelegate delegate = new InternalStoreDelegate(); | 92 | private final FlowRuleStoreDelegate delegate = new InternalStoreDelegate(); |
94 | 93 | ||
95 | - private final ExecutorService futureListeners = | 94 | + private ExecutorService futureService; |
96 | - Executors.newCachedThreadPool(namedThreads("provider-future-listeners")); | ||
97 | 95 | ||
98 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 96 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
99 | protected FlowRuleStore store; | 97 | protected FlowRuleStore store; |
... | @@ -106,6 +104,7 @@ public class FlowRuleManager | ... | @@ -106,6 +104,7 @@ public class FlowRuleManager |
106 | 104 | ||
107 | @Activate | 105 | @Activate |
108 | public void activate() { | 106 | public void activate() { |
107 | + futureService = Executors.newCachedThreadPool(namedThreads("provider-future-listeners")); | ||
109 | store.setDelegate(delegate); | 108 | store.setDelegate(delegate); |
110 | eventDispatcher.addSink(FlowRuleEvent.class, listenerRegistry); | 109 | eventDispatcher.addSink(FlowRuleEvent.class, listenerRegistry); |
111 | log.info("Started"); | 110 | log.info("Started"); |
... | @@ -113,7 +112,7 @@ public class FlowRuleManager | ... | @@ -113,7 +112,7 @@ public class FlowRuleManager |
113 | 112 | ||
114 | @Deactivate | 113 | @Deactivate |
115 | public void deactivate() { | 114 | public void deactivate() { |
116 | - futureListeners.shutdownNow(); | 115 | + futureService.shutdownNow(); |
117 | 116 | ||
118 | store.unsetDelegate(delegate); | 117 | store.unsetDelegate(delegate); |
119 | eventDispatcher.removeSink(FlowRuleEvent.class); | 118 | eventDispatcher.removeSink(FlowRuleEvent.class); |
... | @@ -364,6 +363,9 @@ public class FlowRuleManager | ... | @@ -364,6 +363,9 @@ public class FlowRuleManager |
364 | 363 | ||
365 | // Store delegate to re-post events emitted from the store. | 364 | // Store delegate to re-post events emitted from the store. |
366 | private class InternalStoreDelegate implements FlowRuleStoreDelegate { | 365 | private class InternalStoreDelegate implements FlowRuleStoreDelegate { |
366 | + | ||
367 | + private static final int TIMEOUT = 5000; // ms | ||
368 | + | ||
367 | // TODO: Right now we only dispatch events at individual flowEntry level. | 369 | // TODO: Right now we only dispatch events at individual flowEntry level. |
368 | // It may be more efficient for also dispatch events as a batch. | 370 | // It may be more efficient for also dispatch events as a batch. |
369 | @Override | 371 | @Override |
... | @@ -384,15 +386,28 @@ public class FlowRuleManager | ... | @@ -384,15 +386,28 @@ public class FlowRuleManager |
384 | 386 | ||
385 | FlowRuleProvider flowRuleProvider = | 387 | FlowRuleProvider flowRuleProvider = |
386 | getProvider(batchOperation.getOperations().get(0).getTarget().deviceId()); | 388 | getProvider(batchOperation.getOperations().get(0).getTarget().deviceId()); |
387 | - final ListenableFuture<CompletedBatchOperation> result = | 389 | + final Future<CompletedBatchOperation> result = |
388 | flowRuleProvider.executeBatch(batchOperation); | 390 | flowRuleProvider.executeBatch(batchOperation); |
389 | - result.addListener(new Runnable() { | 391 | + futureService.submit(new Runnable() { |
390 | @Override | 392 | @Override |
391 | public void run() { | 393 | public void run() { |
392 | - store.batchOperationComplete(FlowRuleBatchEvent.completed(request, | 394 | + CompletedBatchOperation res; |
393 | - Futures.getUnchecked(result))); | 395 | + try { |
396 | + res = result.get(TIMEOUT, TimeUnit.MILLISECONDS); | ||
397 | + store.batchOperationComplete(FlowRuleBatchEvent.completed(request, res)); | ||
398 | + } catch (TimeoutException | InterruptedException | ExecutionException e) { | ||
399 | + log.warn("Something went wrong with the batch operation {}", | ||
400 | + request.batchId(), e); | ||
401 | + | ||
402 | + Set<FlowRule> failures = new HashSet<>(batchOperation.size()); | ||
403 | + for (FlowRuleBatchEntry op : batchOperation.getOperations()) { | ||
404 | + failures.add(op.getTarget()); | ||
405 | + } | ||
406 | + res = new CompletedBatchOperation(false, failures); | ||
407 | + store.batchOperationComplete(FlowRuleBatchEvent.completed(request, res)); | ||
408 | + } | ||
394 | } | 409 | } |
395 | - }, futureListeners); | 410 | + }); |
396 | break; | 411 | break; |
397 | 412 | ||
398 | case BATCH_OPERATION_COMPLETED: | 413 | case BATCH_OPERATION_COMPLETED: | ... | ... |
... | @@ -15,6 +15,8 @@ | ... | @@ -15,6 +15,8 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.net.intent.impl; | 16 | package org.onlab.onos.net.intent.impl; |
17 | 17 | ||
18 | +import com.google.common.base.Predicate; | ||
19 | +import com.google.common.collect.FluentIterable; | ||
18 | import com.google.common.collect.ImmutableList; | 20 | import com.google.common.collect.ImmutableList; |
19 | import org.apache.felix.scr.annotations.Component; | 21 | import org.apache.felix.scr.annotations.Component; |
20 | import org.apache.felix.scr.annotations.Reference; | 22 | import org.apache.felix.scr.annotations.Reference; |
... | @@ -94,11 +96,19 @@ public abstract class ConnectivityIntentCompiler<T extends ConnectivityIntent> | ... | @@ -94,11 +96,19 @@ public abstract class ConnectivityIntentCompiler<T extends ConnectivityIntent> |
94 | protected Path getPath(ConnectivityIntent intent, | 96 | protected Path getPath(ConnectivityIntent intent, |
95 | ElementId one, ElementId two) { | 97 | ElementId one, ElementId two) { |
96 | Set<Path> paths = pathService.getPaths(one, two, weight(intent.constraints())); | 98 | Set<Path> paths = pathService.getPaths(one, two, weight(intent.constraints())); |
97 | - if (paths.isEmpty()) { | 99 | + final List<Constraint> constraints = intent.constraints(); |
98 | - throw new PathNotFoundException("No packet path from " + one + " to " + two); | 100 | + ImmutableList<Path> filtered = FluentIterable.from(paths) |
101 | + .filter(new Predicate<Path>() { | ||
102 | + @Override | ||
103 | + public boolean apply(Path path) { | ||
104 | + return checkPath(path, constraints); | ||
105 | + } | ||
106 | + }).toList(); | ||
107 | + if (filtered.isEmpty()) { | ||
108 | + throw new PathNotFoundException("No packet path form " + one + " to " + two); | ||
99 | } | 109 | } |
100 | // TODO: let's be more intelligent about this eventually | 110 | // TODO: let's be more intelligent about this eventually |
101 | - return paths.iterator().next(); | 111 | + return filtered.iterator().next(); |
102 | } | 112 | } |
103 | 113 | ||
104 | /** | 114 | /** | ... | ... |
1 | +/* | ||
2 | + * Copyright 2014 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | +package org.onlab.onos.net.flow; | ||
17 | + | ||
18 | +import java.util.concurrent.TimeUnit; | ||
19 | + | ||
20 | +import org.junit.Test; | ||
21 | +import org.onlab.onos.net.intent.IntentTestsMocks; | ||
22 | + | ||
23 | +import com.google.common.testing.EqualsTester; | ||
24 | + | ||
25 | +import static org.hamcrest.MatcherAssert.assertThat; | ||
26 | +import static org.hamcrest.Matchers.greaterThan; | ||
27 | +import static org.hamcrest.Matchers.is; | ||
28 | +import static org.onlab.onos.net.NetTestTools.did; | ||
29 | + | ||
30 | +/** | ||
31 | + * Unit tests for the DefaultFlowEntry class. | ||
32 | + */ | ||
33 | +public class DefaultFlowEntryTest { | ||
34 | + private static final IntentTestsMocks.MockSelector SELECTOR = | ||
35 | + new IntentTestsMocks.MockSelector(); | ||
36 | + private static final IntentTestsMocks.MockTreatment TREATMENT = | ||
37 | + new IntentTestsMocks.MockTreatment(); | ||
38 | + | ||
39 | + private static DefaultFlowEntry makeFlowEntry(int uniqueValue) { | ||
40 | + return new DefaultFlowEntry(did("id" + Integer.toString(uniqueValue)), | ||
41 | + SELECTOR, | ||
42 | + TREATMENT, | ||
43 | + uniqueValue, | ||
44 | + FlowEntry.FlowEntryState.ADDED, | ||
45 | + uniqueValue, | ||
46 | + uniqueValue, | ||
47 | + uniqueValue, | ||
48 | + uniqueValue, | ||
49 | + uniqueValue); | ||
50 | + } | ||
51 | + | ||
52 | + final DefaultFlowEntry defaultFlowEntry1 = makeFlowEntry(1); | ||
53 | + final DefaultFlowEntry sameAsDefaultFlowEntry1 = makeFlowEntry(1); | ||
54 | + final DefaultFlowEntry defaultFlowEntry2 = makeFlowEntry(2); | ||
55 | + | ||
56 | + /** | ||
57 | + * Tests the equals, hashCode and toString methods using Guava EqualsTester. | ||
58 | + */ | ||
59 | + @Test | ||
60 | + public void testEquals() { | ||
61 | + new EqualsTester() | ||
62 | + .addEqualityGroup(defaultFlowEntry1, sameAsDefaultFlowEntry1) | ||
63 | + .addEqualityGroup(defaultFlowEntry2) | ||
64 | + .testEquals(); | ||
65 | + } | ||
66 | + | ||
67 | + /** | ||
68 | + * Tests the construction of a default flow entry from a device id. | ||
69 | + */ | ||
70 | + @Test | ||
71 | + public void testDeviceBasedObject() { | ||
72 | + assertThat(defaultFlowEntry1.deviceId(), is(did("id1"))); | ||
73 | + assertThat(defaultFlowEntry1.selector(), is(SELECTOR)); | ||
74 | + assertThat(defaultFlowEntry1.treatment(), is(TREATMENT)); | ||
75 | + assertThat(defaultFlowEntry1.timeout(), is(1)); | ||
76 | + assertThat(defaultFlowEntry1.life(), is(1L)); | ||
77 | + assertThat(defaultFlowEntry1.packets(), is(1L)); | ||
78 | + assertThat(defaultFlowEntry1.bytes(), is(1L)); | ||
79 | + assertThat(defaultFlowEntry1.state(), is(FlowEntry.FlowEntryState.ADDED)); | ||
80 | + assertThat(defaultFlowEntry1.lastSeen(), | ||
81 | + greaterThan(System.currentTimeMillis() - | ||
82 | + TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS))); | ||
83 | + } | ||
84 | + | ||
85 | + /** | ||
86 | + * Tests the setters on a default flow entry object. | ||
87 | + */ | ||
88 | + @Test | ||
89 | + public void testSetters() { | ||
90 | + final DefaultFlowEntry entry = makeFlowEntry(1); | ||
91 | + | ||
92 | + entry.setLastSeen(); | ||
93 | + entry.setState(FlowEntry.FlowEntryState.PENDING_REMOVE); | ||
94 | + entry.setPackets(11); | ||
95 | + entry.setBytes(22); | ||
96 | + entry.setLife(33); | ||
97 | + | ||
98 | + assertThat(entry.deviceId(), is(did("id1"))); | ||
99 | + assertThat(entry.selector(), is(SELECTOR)); | ||
100 | + assertThat(entry.treatment(), is(TREATMENT)); | ||
101 | + assertThat(entry.timeout(), is(1)); | ||
102 | + assertThat(entry.life(), is(33L)); | ||
103 | + assertThat(entry.packets(), is(11L)); | ||
104 | + assertThat(entry.bytes(), is(22L)); | ||
105 | + assertThat(entry.state(), is(FlowEntry.FlowEntryState.PENDING_REMOVE)); | ||
106 | + assertThat(entry.lastSeen(), | ||
107 | + greaterThan(System.currentTimeMillis() - | ||
108 | + TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS))); | ||
109 | + } | ||
110 | + | ||
111 | + /** | ||
112 | + * Tests a default flow rule built for an error. | ||
113 | + */ | ||
114 | + @Test | ||
115 | + public void testErrorObject() { | ||
116 | + final DefaultFlowEntry errorEntry = | ||
117 | + new DefaultFlowEntry(new IntentTestsMocks.MockFlowRule(1), | ||
118 | + 111, | ||
119 | + 222); | ||
120 | + assertThat(errorEntry.errType(), is(111)); | ||
121 | + assertThat(errorEntry.errCode(), is(222)); | ||
122 | + assertThat(errorEntry.state(), is(FlowEntry.FlowEntryState.FAILED)); | ||
123 | + assertThat(errorEntry.lastSeen(), | ||
124 | + greaterThan(System.currentTimeMillis() - | ||
125 | + TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS))); | ||
126 | + } | ||
127 | + | ||
128 | + /** | ||
129 | + * Tests a default flow entry constructed from a flow rule. | ||
130 | + */ | ||
131 | + @Test | ||
132 | + public void testFlowBasedObject() { | ||
133 | + final DefaultFlowEntry entry = | ||
134 | + new DefaultFlowEntry(new IntentTestsMocks.MockFlowRule(1)); | ||
135 | + assertThat(entry.priority(), is(1)); | ||
136 | + assertThat(entry.appId(), is((short) 0)); | ||
137 | + assertThat(entry.lastSeen(), | ||
138 | + greaterThan(System.currentTimeMillis() - | ||
139 | + TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS))); | ||
140 | + } | ||
141 | + | ||
142 | + /** | ||
143 | + * Tests a default flow entry constructed from a flow rule plus extra | ||
144 | + * parameters. | ||
145 | + */ | ||
146 | + @Test | ||
147 | + public void testFlowBasedObjectWithParameters() { | ||
148 | + final DefaultFlowEntry entry = | ||
149 | + new DefaultFlowEntry(new IntentTestsMocks.MockFlowRule(33), | ||
150 | + FlowEntry.FlowEntryState.REMOVED, | ||
151 | + 101, 102, 103); | ||
152 | + assertThat(entry.state(), is(FlowEntry.FlowEntryState.REMOVED)); | ||
153 | + assertThat(entry.life(), is(101L)); | ||
154 | + assertThat(entry.packets(), is(102L)); | ||
155 | + assertThat(entry.bytes(), is(103L)); | ||
156 | + assertThat(entry.lastSeen(), | ||
157 | + greaterThan(System.currentTimeMillis() - | ||
158 | + TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS))); | ||
159 | + } | ||
160 | +} |
1 | +/* | ||
2 | + * Copyright 2014 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onlab.onos.net.flow; | ||
18 | + | ||
19 | +import org.junit.Test; | ||
20 | +import org.onlab.onos.net.intent.IntentTestsMocks; | ||
21 | + | ||
22 | +import com.google.common.testing.EqualsTester; | ||
23 | + | ||
24 | +import static org.hamcrest.MatcherAssert.assertThat; | ||
25 | +import static org.hamcrest.Matchers.is; | ||
26 | +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutableBaseClass; | ||
27 | +import static org.onlab.onos.net.NetTestTools.APP_ID; | ||
28 | +import static org.onlab.onos.net.NetTestTools.did; | ||
29 | + | ||
30 | +/** | ||
31 | + * Unit tests for the default flow rule class. | ||
32 | + */ | ||
33 | +public class DefaultFlowRuleTest { | ||
34 | + private static final IntentTestsMocks.MockSelector SELECTOR = | ||
35 | + new IntentTestsMocks.MockSelector(); | ||
36 | + private static final IntentTestsMocks.MockTreatment TREATMENT = | ||
37 | + new IntentTestsMocks.MockTreatment(); | ||
38 | + | ||
39 | + final FlowRule flowRule1 = new IntentTestsMocks.MockFlowRule(1); | ||
40 | + final FlowRule sameAsFlowRule1 = new IntentTestsMocks.MockFlowRule(1); | ||
41 | + final FlowRule flowRule2 = new IntentTestsMocks.MockFlowRule(2); | ||
42 | + final DefaultFlowRule defaultFlowRule1 = new DefaultFlowRule(flowRule1); | ||
43 | + final DefaultFlowRule sameAsDefaultFlowRule1 = new DefaultFlowRule(sameAsFlowRule1); | ||
44 | + final DefaultFlowRule defaultFlowRule2 = new DefaultFlowRule(flowRule2); | ||
45 | + | ||
46 | + /** | ||
47 | + * Checks that the DefaultFlowRule class is immutable but can be inherited | ||
48 | + * from. | ||
49 | + */ | ||
50 | + @Test | ||
51 | + public void testImmutability() { | ||
52 | + assertThatClassIsImmutableBaseClass(DefaultFlowRule.class); | ||
53 | + } | ||
54 | + | ||
55 | + /** | ||
56 | + * Tests the equals, hashCode and toString methods using Guava EqualsTester. | ||
57 | + */ | ||
58 | + @Test | ||
59 | + public void testEquals() { | ||
60 | + new EqualsTester() | ||
61 | + .addEqualityGroup(defaultFlowRule1, sameAsDefaultFlowRule1) | ||
62 | + .addEqualityGroup(defaultFlowRule2) | ||
63 | + .testEquals(); | ||
64 | + } | ||
65 | + | ||
66 | + /** | ||
67 | + * Tests creation of a DefaultFlowRule using a FlowRule constructor. | ||
68 | + */ | ||
69 | + @Test | ||
70 | + public void testCreationFromFlowRule() { | ||
71 | + assertThat(defaultFlowRule1.deviceId(), is(flowRule1.deviceId())); | ||
72 | + assertThat(defaultFlowRule1.appId(), is(flowRule1.appId())); | ||
73 | + assertThat(defaultFlowRule1.id(), is(flowRule1.id())); | ||
74 | + assertThat(defaultFlowRule1.isPermanent(), is(flowRule1.isPermanent())); | ||
75 | + assertThat(defaultFlowRule1.priority(), is(flowRule1.priority())); | ||
76 | + assertThat(defaultFlowRule1.selector(), is(flowRule1.selector())); | ||
77 | + assertThat(defaultFlowRule1.treatment(), is(flowRule1.treatment())); | ||
78 | + assertThat(defaultFlowRule1.timeout(), is(flowRule1.timeout())); | ||
79 | + } | ||
80 | + | ||
81 | + /** | ||
82 | + * Tests creation of a DefaultFlowRule using a FlowId constructor. | ||
83 | + */ | ||
84 | + @Test | ||
85 | + public void testCreationWithFlowId() { | ||
86 | + final DefaultFlowRule rule = | ||
87 | + new DefaultFlowRule(did("1"), SELECTOR, | ||
88 | + TREATMENT, 22, 33, | ||
89 | + 44, false); | ||
90 | + assertThat(rule.deviceId(), is(did("1"))); | ||
91 | + assertThat(rule.id().value(), is(33L)); | ||
92 | + assertThat(rule.isPermanent(), is(false)); | ||
93 | + assertThat(rule.priority(), is(22)); | ||
94 | + assertThat(rule.selector(), is(SELECTOR)); | ||
95 | + assertThat(rule.treatment(), is(TREATMENT)); | ||
96 | + assertThat(rule.timeout(), is(44)); | ||
97 | + } | ||
98 | + | ||
99 | + /** | ||
100 | + * Tests the creation of a DefaultFlowRule using an AppId constructor. | ||
101 | + */ | ||
102 | + @Test | ||
103 | + public void testCreationWithAppId() { | ||
104 | + final DefaultFlowRule rule = | ||
105 | + new DefaultFlowRule(did("1"), SELECTOR, | ||
106 | + TREATMENT, 22, APP_ID, | ||
107 | + 44, false); | ||
108 | + assertThat(rule.deviceId(), is(did("1"))); | ||
109 | + assertThat(rule.isPermanent(), is(false)); | ||
110 | + assertThat(rule.priority(), is(22)); | ||
111 | + assertThat(rule.selector(), is(SELECTOR)); | ||
112 | + assertThat(rule.treatment(), is(TREATMENT)); | ||
113 | + assertThat(rule.timeout(), is(44)); | ||
114 | + } | ||
115 | +} |
... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
16 | package org.onlab.onos.net.intent; | 16 | package org.onlab.onos.net.intent; |
17 | 17 | ||
18 | import static org.onlab.onos.net.NetTestTools.createPath; | 18 | import static org.onlab.onos.net.NetTestTools.createPath; |
19 | +import static org.onlab.onos.net.NetTestTools.did; | ||
19 | import static org.onlab.onos.net.NetTestTools.link; | 20 | import static org.onlab.onos.net.NetTestTools.link; |
20 | 21 | ||
21 | import java.util.ArrayList; | 22 | import java.util.ArrayList; |
... | @@ -31,6 +32,8 @@ import org.onlab.onos.net.DeviceId; | ... | @@ -31,6 +32,8 @@ import org.onlab.onos.net.DeviceId; |
31 | import org.onlab.onos.net.ElementId; | 32 | import org.onlab.onos.net.ElementId; |
32 | import org.onlab.onos.net.Link; | 33 | import org.onlab.onos.net.Link; |
33 | import org.onlab.onos.net.Path; | 34 | import org.onlab.onos.net.Path; |
35 | +import org.onlab.onos.net.flow.FlowId; | ||
36 | +import org.onlab.onos.net.flow.FlowRule; | ||
34 | import org.onlab.onos.net.flow.TrafficSelector; | 37 | import org.onlab.onos.net.flow.TrafficSelector; |
35 | import org.onlab.onos.net.flow.TrafficTreatment; | 38 | import org.onlab.onos.net.flow.TrafficTreatment; |
36 | import org.onlab.onos.net.flow.criteria.Criterion; | 39 | import org.onlab.onos.net.flow.criteria.Criterion; |
... | @@ -271,4 +274,60 @@ public class IntentTestsMocks { | ... | @@ -271,4 +274,60 @@ public class IntentTestsMocks { |
271 | } | 274 | } |
272 | } | 275 | } |
273 | 276 | ||
277 | + private static final IntentTestsMocks.MockSelector SELECTOR = | ||
278 | + new IntentTestsMocks.MockSelector(); | ||
279 | + private static final IntentTestsMocks.MockTreatment TREATMENT = | ||
280 | + new IntentTestsMocks.MockTreatment(); | ||
281 | + | ||
282 | + public static class MockFlowRule implements FlowRule { | ||
283 | + | ||
284 | + int priority; | ||
285 | + public MockFlowRule(int priority) { | ||
286 | + this.priority = priority; | ||
287 | + } | ||
288 | + | ||
289 | + @Override | ||
290 | + public FlowId id() { | ||
291 | + return FlowId.valueOf(1); | ||
292 | + } | ||
293 | + | ||
294 | + @Override | ||
295 | + public short appId() { | ||
296 | + return 0; | ||
297 | + } | ||
298 | + | ||
299 | + @Override | ||
300 | + public int priority() { | ||
301 | + return priority; | ||
302 | + } | ||
303 | + | ||
304 | + @Override | ||
305 | + public DeviceId deviceId() { | ||
306 | + return did("1"); | ||
307 | + } | ||
308 | + | ||
309 | + @Override | ||
310 | + public TrafficSelector selector() { | ||
311 | + return SELECTOR; | ||
312 | + } | ||
313 | + | ||
314 | + @Override | ||
315 | + public TrafficTreatment treatment() { | ||
316 | + return TREATMENT; | ||
317 | + } | ||
318 | + | ||
319 | + @Override | ||
320 | + public int timeout() { | ||
321 | + return 0; | ||
322 | + } | ||
323 | + | ||
324 | + @Override | ||
325 | + public boolean isPermanent() { | ||
326 | + return false; | ||
327 | + } | ||
328 | + | ||
329 | + | ||
330 | + } | ||
331 | + | ||
332 | + | ||
274 | } | 333 | } | ... | ... |
... | @@ -85,6 +85,8 @@ import com.google.common.cache.Cache; | ... | @@ -85,6 +85,8 @@ import com.google.common.cache.Cache; |
85 | import com.google.common.cache.CacheBuilder; | 85 | import com.google.common.cache.CacheBuilder; |
86 | import com.google.common.cache.CacheLoader; | 86 | import com.google.common.cache.CacheLoader; |
87 | import com.google.common.cache.LoadingCache; | 87 | import com.google.common.cache.LoadingCache; |
88 | +import com.google.common.cache.RemovalListener; | ||
89 | +import com.google.common.cache.RemovalNotification; | ||
88 | import com.google.common.collect.ArrayListMultimap; | 90 | import com.google.common.collect.ArrayListMultimap; |
89 | import com.google.common.collect.ImmutableList; | 91 | import com.google.common.collect.ImmutableList; |
90 | import com.google.common.collect.ImmutableSet; | 92 | import com.google.common.collect.ImmutableSet; |
... | @@ -132,8 +134,7 @@ public class DistributedFlowRuleStore | ... | @@ -132,8 +134,7 @@ public class DistributedFlowRuleStore |
132 | private Cache<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures = | 134 | private Cache<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures = |
133 | CacheBuilder.newBuilder() | 135 | CacheBuilder.newBuilder() |
134 | .expireAfterWrite(pendingFutureTimeoutMinutes, TimeUnit.MINUTES) | 136 | .expireAfterWrite(pendingFutureTimeoutMinutes, TimeUnit.MINUTES) |
135 | - // TODO Explicitly fail the future if expired? | 137 | + .removalListener(new TimeoutFuture()) |
136 | - //.removalListener(listener) | ||
137 | .build(); | 138 | .build(); |
138 | 139 | ||
139 | // Cache of SMaps used for backup data. each SMap contain device flow table | 140 | // Cache of SMaps used for backup data. each SMap contain device flow table |
... | @@ -541,6 +542,17 @@ public class DistributedFlowRuleStore | ... | @@ -541,6 +542,17 @@ public class DistributedFlowRuleStore |
541 | log.debug("removedFromPrimary {}", removed); | 542 | log.debug("removedFromPrimary {}", removed); |
542 | } | 543 | } |
543 | 544 | ||
545 | + private static final class TimeoutFuture | ||
546 | + implements RemovalListener<Integer, SettableFuture<CompletedBatchOperation>> { | ||
547 | + @Override | ||
548 | + public void onRemoval(RemovalNotification<Integer, SettableFuture<CompletedBatchOperation>> notification) { | ||
549 | + // wrapping in ExecutionException to support Future.get | ||
550 | + notification.getValue() | ||
551 | + .setException(new ExecutionException("Timed out", | ||
552 | + new TimeoutException())); | ||
553 | + } | ||
554 | + } | ||
555 | + | ||
544 | private final class OnStoreBatch implements ClusterMessageHandler { | 556 | private final class OnStoreBatch implements ClusterMessageHandler { |
545 | private final NodeId local; | 557 | private final NodeId local; |
546 | 558 | ||
... | @@ -580,7 +592,18 @@ public class DistributedFlowRuleStore | ... | @@ -580,7 +592,18 @@ public class DistributedFlowRuleStore |
580 | 592 | ||
581 | @Override | 593 | @Override |
582 | public void run() { | 594 | public void run() { |
583 | - CompletedBatchOperation result = Futures.getUnchecked(f); | 595 | + CompletedBatchOperation result; |
596 | + try { | ||
597 | + result = f.get(); | ||
598 | + } catch (InterruptedException | ExecutionException e) { | ||
599 | + log.error("Batch operation failed", e); | ||
600 | + // create everything failed response | ||
601 | + Set<FlowRule> failures = new HashSet<>(operation.size()); | ||
602 | + for (FlowRuleBatchEntry op : operation.getOperations()) { | ||
603 | + failures.add(op.getTarget()); | ||
604 | + } | ||
605 | + result = new CompletedBatchOperation(false, failures); | ||
606 | + } | ||
584 | try { | 607 | try { |
585 | message.respond(SERIALIZER.encode(result)); | 608 | message.respond(SERIALIZER.encode(result)); |
586 | } catch (IOException e) { | 609 | } catch (IOException e) { | ... | ... |
... | @@ -72,7 +72,7 @@ public class DatabaseManager implements DatabaseService, DatabaseAdminService { | ... | @@ -72,7 +72,7 @@ public class DatabaseManager implements DatabaseService, DatabaseAdminService { |
72 | public static final String LOG_FILE_PREFIX = "/tmp/onos-copy-cat-log_"; | 72 | public static final String LOG_FILE_PREFIX = "/tmp/onos-copy-cat-log_"; |
73 | 73 | ||
74 | // Current working dir seems to be /opt/onos/apache-karaf-3.0.2 | 74 | // Current working dir seems to be /opt/onos/apache-karaf-3.0.2 |
75 | - // TODO: Get the path to /opt/onos/config | 75 | + // TODO: Set the path to /opt/onos/config |
76 | private static final String CONFIG_DIR = "../config"; | 76 | private static final String CONFIG_DIR = "../config"; |
77 | 77 | ||
78 | private static final String DEFAULT_MEMBER_FILE = "tablets.json"; | 78 | private static final String DEFAULT_MEMBER_FILE = "tablets.json"; | ... | ... |
... | @@ -75,10 +75,14 @@ import org.onlab.onos.net.intent.OpticalConnectivityIntent; | ... | @@ -75,10 +75,14 @@ import org.onlab.onos.net.intent.OpticalConnectivityIntent; |
75 | import org.onlab.onos.net.intent.OpticalPathIntent; | 75 | import org.onlab.onos.net.intent.OpticalPathIntent; |
76 | import org.onlab.onos.net.intent.PathIntent; | 76 | import org.onlab.onos.net.intent.PathIntent; |
77 | import org.onlab.onos.net.intent.PointToPointIntent; | 77 | import org.onlab.onos.net.intent.PointToPointIntent; |
78 | +import org.onlab.onos.net.intent.constraint.AnnotationConstraint; | ||
78 | import org.onlab.onos.net.intent.constraint.BandwidthConstraint; | 79 | import org.onlab.onos.net.intent.constraint.BandwidthConstraint; |
79 | import org.onlab.onos.net.intent.constraint.BooleanConstraint; | 80 | import org.onlab.onos.net.intent.constraint.BooleanConstraint; |
80 | import org.onlab.onos.net.intent.constraint.LambdaConstraint; | 81 | import org.onlab.onos.net.intent.constraint.LambdaConstraint; |
82 | +import org.onlab.onos.net.intent.constraint.LatencyConstraint; | ||
81 | import org.onlab.onos.net.intent.constraint.LinkTypeConstraint; | 83 | import org.onlab.onos.net.intent.constraint.LinkTypeConstraint; |
84 | +import org.onlab.onos.net.intent.constraint.ObstacleConstraint; | ||
85 | +import org.onlab.onos.net.intent.constraint.WaypointConstraint; | ||
82 | import org.onlab.onos.net.link.DefaultLinkDescription; | 86 | import org.onlab.onos.net.link.DefaultLinkDescription; |
83 | import org.onlab.onos.net.packet.DefaultOutboundPacket; | 87 | import org.onlab.onos.net.packet.DefaultOutboundPacket; |
84 | import org.onlab.onos.net.provider.ProviderId; | 88 | import org.onlab.onos.net.provider.ProviderId; |
... | @@ -208,9 +212,14 @@ public final class KryoNamespaces { | ... | @@ -208,9 +212,14 @@ public final class KryoNamespaces { |
208 | LinkResourceRequest.class, | 212 | LinkResourceRequest.class, |
209 | Lambda.class, | 213 | Lambda.class, |
210 | Bandwidth.class, | 214 | Bandwidth.class, |
215 | + // Constraints | ||
211 | LambdaConstraint.class, | 216 | LambdaConstraint.class, |
212 | BandwidthConstraint.class, | 217 | BandwidthConstraint.class, |
213 | LinkTypeConstraint.class, | 218 | LinkTypeConstraint.class, |
219 | + LatencyConstraint.class, | ||
220 | + WaypointConstraint.class, | ||
221 | + ObstacleConstraint.class, | ||
222 | + AnnotationConstraint.class, | ||
214 | BooleanConstraint.class | 223 | BooleanConstraint.class |
215 | ) | 224 | ) |
216 | .register(DefaultApplicationId.class, new DefaultApplicationIdSerializer()) | 225 | .register(DefaultApplicationId.class, new DefaultApplicationIdSerializer()) | ... | ... |
... | @@ -18,6 +18,8 @@ package org.onlab.onos.store.trivial.impl; | ... | @@ -18,6 +18,8 @@ package org.onlab.onos.store.trivial.impl; |
18 | import com.google.common.base.Function; | 18 | import com.google.common.base.Function; |
19 | import com.google.common.cache.Cache; | 19 | import com.google.common.cache.Cache; |
20 | import com.google.common.cache.CacheBuilder; | 20 | import com.google.common.cache.CacheBuilder; |
21 | +import com.google.common.cache.RemovalListener; | ||
22 | +import com.google.common.cache.RemovalNotification; | ||
21 | import com.google.common.collect.FluentIterable; | 23 | import com.google.common.collect.FluentIterable; |
22 | import com.google.common.util.concurrent.Futures; | 24 | import com.google.common.util.concurrent.Futures; |
23 | import com.google.common.util.concurrent.SettableFuture; | 25 | import com.google.common.util.concurrent.SettableFuture; |
... | @@ -53,8 +55,10 @@ import java.util.List; | ... | @@ -53,8 +55,10 @@ import java.util.List; |
53 | import java.util.concurrent.ConcurrentHashMap; | 55 | import java.util.concurrent.ConcurrentHashMap; |
54 | import java.util.concurrent.ConcurrentMap; | 56 | import java.util.concurrent.ConcurrentMap; |
55 | import java.util.concurrent.CopyOnWriteArrayList; | 57 | import java.util.concurrent.CopyOnWriteArrayList; |
58 | +import java.util.concurrent.ExecutionException; | ||
56 | import java.util.concurrent.Future; | 59 | import java.util.concurrent.Future; |
57 | import java.util.concurrent.TimeUnit; | 60 | import java.util.concurrent.TimeUnit; |
61 | +import java.util.concurrent.TimeoutException; | ||
58 | import java.util.concurrent.atomic.AtomicInteger; | 62 | import java.util.concurrent.atomic.AtomicInteger; |
59 | 63 | ||
60 | import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked; | 64 | import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked; |
... | @@ -86,8 +90,7 @@ public class SimpleFlowRuleStore | ... | @@ -86,8 +90,7 @@ public class SimpleFlowRuleStore |
86 | private Cache<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures = | 90 | private Cache<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures = |
87 | CacheBuilder.newBuilder() | 91 | CacheBuilder.newBuilder() |
88 | .expireAfterWrite(pendingFutureTimeoutMinutes, TimeUnit.MINUTES) | 92 | .expireAfterWrite(pendingFutureTimeoutMinutes, TimeUnit.MINUTES) |
89 | - // TODO Explicitly fail the future if expired? | 93 | + .removalListener(new TimeoutFuture()) |
90 | - //.removalListener(listener) | ||
91 | .build(); | 94 | .build(); |
92 | 95 | ||
93 | @Activate | 96 | @Activate |
... | @@ -303,4 +306,15 @@ public class SimpleFlowRuleStore | ... | @@ -303,4 +306,15 @@ public class SimpleFlowRuleStore |
303 | } | 306 | } |
304 | notifyDelegate(event); | 307 | notifyDelegate(event); |
305 | } | 308 | } |
309 | + | ||
310 | + private static final class TimeoutFuture | ||
311 | + implements RemovalListener<Integer, SettableFuture<CompletedBatchOperation>> { | ||
312 | + @Override | ||
313 | + public void onRemoval(RemovalNotification<Integer, SettableFuture<CompletedBatchOperation>> notification) { | ||
314 | + // wrapping in ExecutionException to support Future.get | ||
315 | + notification.getValue() | ||
316 | + .setException(new ExecutionException("Timed out", | ||
317 | + new TimeoutException())); | ||
318 | + } | ||
319 | + } | ||
306 | } | 320 | } | ... | ... |
... | @@ -197,6 +197,8 @@ | ... | @@ -197,6 +197,8 @@ |
197 | <feature name="onos-app-sdnip" version="1.0.0" | 197 | <feature name="onos-app-sdnip" version="1.0.0" |
198 | description="SDN-IP peering application"> | 198 | description="SDN-IP peering application"> |
199 | <feature>onos-api</feature> | 199 | <feature>onos-api</feature> |
200 | + <feature>onos-app-proxyarp</feature> | ||
201 | + <feature>onos-app-config</feature> | ||
200 | <bundle>mvn:org.onlab.onos/onos-app-sdnip/1.0.0-SNAPSHOT</bundle> | 202 | <bundle>mvn:org.onlab.onos/onos-app-sdnip/1.0.0-SNAPSHOT</bundle> |
201 | </feature> | 203 | </feature> |
202 | 204 | ||
... | @@ -225,4 +227,12 @@ | ... | @@ -225,4 +227,12 @@ |
225 | <bundle>mvn:org.onlab.onos/onos-app-metrics-topology/1.0.0-SNAPSHOT</bundle> | 227 | <bundle>mvn:org.onlab.onos/onos-app-metrics-topology/1.0.0-SNAPSHOT</bundle> |
226 | </feature> | 228 | </feature> |
227 | 229 | ||
230 | + <feature name="onos-app-demo" version="1.0.0" | ||
231 | + description="ONOS demo applications"> | ||
232 | + <feature>onos-api</feature> | ||
233 | + <bundle>mvn:org.onlab.onos/onos-app-demo/1.0.0-SNAPSHOT</bundle> | ||
234 | + </feature> | ||
235 | + | ||
236 | + | ||
237 | + | ||
228 | </features> | 238 | </features> | ... | ... |
providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
... | @@ -15,21 +15,11 @@ | ... | @@ -15,21 +15,11 @@ |
15 | */ | 15 | */ |
16 | package org.onlab.onos.provider.of.flow.impl; | 16 | package org.onlab.onos.provider.of.flow.impl; |
17 | 17 | ||
18 | -import static org.slf4j.LoggerFactory.getLogger; | 18 | +import com.google.common.collect.ArrayListMultimap; |
19 | - | 19 | +import com.google.common.collect.Maps; |
20 | -import java.util.Collections; | 20 | +import com.google.common.collect.Multimap; |
21 | -import java.util.HashMap; | 21 | +import com.google.common.collect.Sets; |
22 | -import java.util.List; | 22 | +import com.google.common.util.concurrent.ExecutionList; |
23 | -import java.util.Map; | ||
24 | -import java.util.Set; | ||
25 | -import java.util.concurrent.ConcurrentHashMap; | ||
26 | -import java.util.concurrent.CountDownLatch; | ||
27 | -import java.util.concurrent.ExecutionException; | ||
28 | -import java.util.concurrent.Executor; | ||
29 | -import java.util.concurrent.TimeUnit; | ||
30 | -import java.util.concurrent.TimeoutException; | ||
31 | -import java.util.concurrent.atomic.AtomicBoolean; | ||
32 | - | ||
33 | import org.apache.felix.scr.annotations.Activate; | 23 | import org.apache.felix.scr.annotations.Activate; |
34 | import org.apache.felix.scr.annotations.Component; | 24 | import org.apache.felix.scr.annotations.Component; |
35 | import org.apache.felix.scr.annotations.Deactivate; | 25 | import org.apache.felix.scr.annotations.Deactivate; |
... | @@ -80,15 +70,23 @@ import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg; | ... | @@ -80,15 +70,23 @@ import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg; |
80 | import org.projectfloodlight.openflow.protocol.instruction.OFInstruction; | 70 | import org.projectfloodlight.openflow.protocol.instruction.OFInstruction; |
81 | import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions; | 71 | import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions; |
82 | import org.projectfloodlight.openflow.types.OFPort; | 72 | import org.projectfloodlight.openflow.types.OFPort; |
83 | -import org.projectfloodlight.openflow.types.U32; | ||
84 | import org.slf4j.Logger; | 73 | import org.slf4j.Logger; |
85 | 74 | ||
86 | -import com.google.common.collect.ArrayListMultimap; | 75 | +import java.util.Collections; |
87 | -import com.google.common.collect.Maps; | 76 | +import java.util.HashMap; |
88 | -import com.google.common.collect.Multimap; | 77 | +import java.util.List; |
89 | -import com.google.common.collect.Sets; | 78 | +import java.util.Map; |
90 | -import com.google.common.util.concurrent.ExecutionList; | 79 | +import java.util.Set; |
91 | -import com.google.common.util.concurrent.ListenableFuture; | 80 | +import java.util.concurrent.ConcurrentHashMap; |
81 | +import java.util.concurrent.CountDownLatch; | ||
82 | +import java.util.concurrent.ExecutionException; | ||
83 | +import java.util.concurrent.Future; | ||
84 | +import java.util.concurrent.TimeUnit; | ||
85 | +import java.util.concurrent.TimeoutException; | ||
86 | +import java.util.concurrent.atomic.AtomicBoolean; | ||
87 | +import java.util.concurrent.atomic.AtomicLong; | ||
88 | + | ||
89 | +import static org.slf4j.LoggerFactory.getLogger; | ||
92 | 90 | ||
93 | /** | 91 | /** |
94 | * Provider which uses an OpenFlow controller to detect network | 92 | * Provider which uses an OpenFlow controller to detect network |
... | @@ -124,6 +122,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -124,6 +122,8 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
124 | 122 | ||
125 | private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap(); | 123 | private final Map<Dpid, FlowStatsCollector> collectors = Maps.newHashMap(); |
126 | 124 | ||
125 | + private final AtomicLong xidCounter = new AtomicLong(0); | ||
126 | + | ||
127 | /** | 127 | /** |
128 | * Creates an OpenFlow host provider. | 128 | * Creates an OpenFlow host provider. |
129 | */ | 129 | */ |
... | @@ -154,6 +154,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -154,6 +154,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
154 | 154 | ||
155 | log.info("Stopped"); | 155 | log.info("Stopped"); |
156 | } | 156 | } |
157 | + | ||
157 | @Override | 158 | @Override |
158 | public void applyFlowRule(FlowRule... flowRules) { | 159 | public void applyFlowRule(FlowRule... flowRules) { |
159 | for (int i = 0; i < flowRules.length; i++) { | 160 | for (int i = 0; i < flowRules.length; i++) { |
... | @@ -167,7 +168,6 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -167,7 +168,6 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
167 | } | 168 | } |
168 | 169 | ||
169 | 170 | ||
170 | - | ||
171 | @Override | 171 | @Override |
172 | public void removeFlowRule(FlowRule... flowRules) { | 172 | public void removeFlowRule(FlowRule... flowRules) { |
173 | for (int i = 0; i < flowRules.length; i++) { | 173 | for (int i = 0; i < flowRules.length; i++) { |
... | @@ -188,11 +188,15 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -188,11 +188,15 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
188 | } | 188 | } |
189 | 189 | ||
190 | @Override | 190 | @Override |
191 | - public ListenableFuture<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch) { | 191 | + public Future<CompletedBatchOperation> executeBatch(BatchOperation<FlowRuleBatchEntry> batch) { |
192 | final Set<Dpid> sws = | 192 | final Set<Dpid> sws = |
193 | Collections.newSetFromMap(new ConcurrentHashMap<Dpid, Boolean>()); | 193 | Collections.newSetFromMap(new ConcurrentHashMap<Dpid, Boolean>()); |
194 | final Map<Long, FlowRuleBatchEntry> fmXids = new HashMap<Long, FlowRuleBatchEntry>(); | 194 | final Map<Long, FlowRuleBatchEntry> fmXids = new HashMap<Long, FlowRuleBatchEntry>(); |
195 | - OFFlowMod mod = null; | 195 | + /* |
196 | + * Use identity hash map for reference equality as we could have equal | ||
197 | + * flow mods for different switches. | ||
198 | + */ | ||
199 | + Map<OFFlowMod, OpenFlowSwitch> mods = Maps.newIdentityHashMap(); | ||
196 | for (FlowRuleBatchEntry fbe : batch.getOperations()) { | 200 | for (FlowRuleBatchEntry fbe : batch.getOperations()) { |
197 | FlowRule flowRule = fbe.getTarget(); | 201 | FlowRule flowRule = fbe.getTarget(); |
198 | OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri())); | 202 | OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri())); |
... | @@ -208,6 +212,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -208,6 +212,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
208 | } | 212 | } |
209 | sws.add(new Dpid(sw.getId())); | 213 | sws.add(new Dpid(sw.getId())); |
210 | FlowModBuilder builder = FlowModBuilder.builder(flowRule, sw.factory()); | 214 | FlowModBuilder builder = FlowModBuilder.builder(flowRule, sw.factory()); |
215 | + OFFlowMod mod = null; | ||
211 | switch (fbe.getOperator()) { | 216 | switch (fbe.getOperator()) { |
212 | case ADD: | 217 | case ADD: |
213 | mod = builder.buildFlowAdd(); | 218 | mod = builder.buildFlowAdd(); |
... | @@ -222,19 +227,23 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -222,19 +227,23 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
222 | log.error("Unsupported batch operation {}", fbe.getOperator()); | 227 | log.error("Unsupported batch operation {}", fbe.getOperator()); |
223 | } | 228 | } |
224 | if (mod != null) { | 229 | if (mod != null) { |
225 | - sw.sendMsg(mod); | 230 | + mods.put(mod, sw); |
226 | - fmXids.put(mod.getXid(), fbe); | 231 | + fmXids.put(xidCounter.getAndIncrement(), fbe); |
227 | } else { | 232 | } else { |
228 | log.error("Conversion of flowrule {} failed.", flowRule); | 233 | log.error("Conversion of flowrule {} failed.", flowRule); |
229 | } | 234 | } |
230 | - | ||
231 | } | 235 | } |
232 | InstallationFuture installation = new InstallationFuture(sws, fmXids); | 236 | InstallationFuture installation = new InstallationFuture(sws, fmXids); |
233 | for (Long xid : fmXids.keySet()) { | 237 | for (Long xid : fmXids.keySet()) { |
234 | pendingFMs.put(xid, installation); | 238 | pendingFMs.put(xid, installation); |
235 | } | 239 | } |
236 | - pendingFutures.put(U32.f(batch.hashCode()), installation); | 240 | + pendingFutures.put(installation.xid(), installation); |
237 | - installation.verify(U32.f(batch.hashCode())); | 241 | + for (Map.Entry<OFFlowMod, OpenFlowSwitch> entry : mods.entrySet()) { |
242 | + OpenFlowSwitch sw = entry.getValue(); | ||
243 | + OFFlowMod mod = entry.getKey(); | ||
244 | + sw.sendMsg(mod); | ||
245 | + } | ||
246 | + installation.verify(); | ||
238 | return installation; | 247 | return installation; |
239 | } | 248 | } |
240 | 249 | ||
... | @@ -352,8 +361,9 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -352,8 +361,9 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
352 | 361 | ||
353 | } | 362 | } |
354 | 363 | ||
355 | - private class InstallationFuture implements ListenableFuture<CompletedBatchOperation> { | 364 | + private class InstallationFuture implements Future<CompletedBatchOperation> { |
356 | 365 | ||
366 | + private final Long xid; | ||
357 | private final Set<Dpid> sws; | 367 | private final Set<Dpid> sws; |
358 | private final AtomicBoolean ok = new AtomicBoolean(true); | 368 | private final AtomicBoolean ok = new AtomicBoolean(true); |
359 | private final Map<Long, FlowRuleBatchEntry> fms; | 369 | private final Map<Long, FlowRuleBatchEntry> fms; |
... | @@ -361,18 +371,22 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -361,18 +371,22 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
361 | private final Set<FlowEntry> offendingFlowMods = Sets.newHashSet(); | 371 | private final Set<FlowEntry> offendingFlowMods = Sets.newHashSet(); |
362 | 372 | ||
363 | private final CountDownLatch countDownLatch; | 373 | private final CountDownLatch countDownLatch; |
364 | - private Long pendingXid; | ||
365 | private BatchState state; | 374 | private BatchState state; |
366 | 375 | ||
367 | private final ExecutionList executionList = new ExecutionList(); | 376 | private final ExecutionList executionList = new ExecutionList(); |
368 | 377 | ||
369 | public InstallationFuture(Set<Dpid> sws, Map<Long, FlowRuleBatchEntry> fmXids) { | 378 | public InstallationFuture(Set<Dpid> sws, Map<Long, FlowRuleBatchEntry> fmXids) { |
379 | + this.xid = xidCounter.getAndIncrement(); | ||
370 | this.state = BatchState.STARTED; | 380 | this.state = BatchState.STARTED; |
371 | this.sws = sws; | 381 | this.sws = sws; |
372 | this.fms = fmXids; | 382 | this.fms = fmXids; |
373 | countDownLatch = new CountDownLatch(sws.size()); | 383 | countDownLatch = new CountDownLatch(sws.size()); |
374 | } | 384 | } |
375 | 385 | ||
386 | + public Long xid() { | ||
387 | + return xid; | ||
388 | + } | ||
389 | + | ||
376 | public void fail(OFErrorMsg msg, Dpid dpid) { | 390 | public void fail(OFErrorMsg msg, Dpid dpid) { |
377 | 391 | ||
378 | ok.set(false); | 392 | ok.set(false); |
... | @@ -434,13 +448,12 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -434,13 +448,12 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
434 | } | 448 | } |
435 | 449 | ||
436 | 450 | ||
437 | - public void verify(Long id) { | 451 | + public void verify() { |
438 | - pendingXid = id; | ||
439 | for (Dpid dpid : sws) { | 452 | for (Dpid dpid : sws) { |
440 | OpenFlowSwitch sw = controller.getSwitch(dpid); | 453 | OpenFlowSwitch sw = controller.getSwitch(dpid); |
441 | OFBarrierRequest.Builder builder = sw.factory() | 454 | OFBarrierRequest.Builder builder = sw.factory() |
442 | .buildBarrierRequest() | 455 | .buildBarrierRequest() |
443 | - .setXid(id); | 456 | + .setXid(xid); |
444 | sw.sendMsg(builder.build()); | 457 | sw.sendMsg(builder.build()); |
445 | } | 458 | } |
446 | } | 459 | } |
... | @@ -462,7 +475,6 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -462,7 +475,6 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
462 | } | 475 | } |
463 | 476 | ||
464 | } | 477 | } |
465 | - invokeCallbacks(); | ||
466 | return true; | 478 | return true; |
467 | } | 479 | } |
468 | 480 | ||
... | @@ -481,6 +493,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -481,6 +493,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
481 | countDownLatch.await(); | 493 | countDownLatch.await(); |
482 | this.state = BatchState.FINISHED; | 494 | this.state = BatchState.FINISHED; |
483 | CompletedBatchOperation result = new CompletedBatchOperation(ok.get(), offendingFlowMods); | 495 | CompletedBatchOperation result = new CompletedBatchOperation(ok.get(), offendingFlowMods); |
496 | + //FIXME do cleanup here | ||
484 | return result; | 497 | return result; |
485 | } | 498 | } |
486 | 499 | ||
... | @@ -491,6 +504,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -491,6 +504,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
491 | if (countDownLatch.await(timeout, unit)) { | 504 | if (countDownLatch.await(timeout, unit)) { |
492 | this.state = BatchState.FINISHED; | 505 | this.state = BatchState.FINISHED; |
493 | CompletedBatchOperation result = new CompletedBatchOperation(ok.get(), offendingFlowMods); | 506 | CompletedBatchOperation result = new CompletedBatchOperation(ok.get(), offendingFlowMods); |
507 | + // FIXME do cleanup here | ||
494 | return result; | 508 | return result; |
495 | } | 509 | } |
496 | throw new TimeoutException(); | 510 | throw new TimeoutException(); |
... | @@ -498,9 +512,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -498,9 +512,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
498 | 512 | ||
499 | private void cleanUp() { | 513 | private void cleanUp() { |
500 | if (isDone() || isCancelled()) { | 514 | if (isDone() || isCancelled()) { |
501 | - if (pendingXid != null) { | 515 | + pendingFutures.remove(xid); |
502 | - pendingFutures.remove(pendingXid); | ||
503 | - } | ||
504 | for (Long xid : fms.keySet()) { | 516 | for (Long xid : fms.keySet()) { |
505 | pendingFMs.remove(xid); | 517 | pendingFMs.remove(xid); |
506 | } | 518 | } |
... | @@ -509,21 +521,10 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr | ... | @@ -509,21 +521,10 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr |
509 | 521 | ||
510 | private void removeRequirement(Dpid dpid) { | 522 | private void removeRequirement(Dpid dpid) { |
511 | countDownLatch.countDown(); | 523 | countDownLatch.countDown(); |
512 | - if (countDownLatch.getCount() == 0) { | ||
513 | - invokeCallbacks(); | ||
514 | - } | ||
515 | sws.remove(dpid); | 524 | sws.remove(dpid); |
525 | + //FIXME don't do cleanup here | ||
516 | cleanUp(); | 526 | cleanUp(); |
517 | } | 527 | } |
518 | - | ||
519 | - @Override | ||
520 | - public void addListener(Runnable runnable, Executor executor) { | ||
521 | - executionList.add(runnable, executor); | ||
522 | - } | ||
523 | - | ||
524 | - private void invokeCallbacks() { | ||
525 | - executionList.execute(); | ||
526 | - } | ||
527 | } | 528 | } |
528 | 529 | ||
529 | } | 530 | } | ... | ... |
... | @@ -10,4 +10,5 @@ | ... | @@ -10,4 +10,5 @@ |
10 | [ "$1" = "-w" ] && shift && onos-wait-for-start $1 | 10 | [ "$1" = "-w" ] && shift && onos-wait-for-start $1 |
11 | 11 | ||
12 | [ -n "$1" ] && OCI=$(find_node $1) && shift | 12 | [ -n "$1" ] && OCI=$(find_node $1) && shift |
13 | +unset KARAF_HOME | ||
13 | client -h $OCI -u karaf "$@" 2>/dev/null | 14 | client -h $OCI -u karaf "$@" 2>/dev/null | ... | ... |
... | @@ -3,10 +3,7 @@ | ... | @@ -3,10 +3,7 @@ |
3 | # Launches ONOS GUI on the specified node. | 3 | # Launches ONOS GUI on the specified node. |
4 | # ----------------------------------------------------------------------------- | 4 | # ----------------------------------------------------------------------------- |
5 | 5 | ||
6 | -[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 | ||
7 | -. $ONOS_ROOT/tools/build/envDefaults | ||
8 | - | ||
9 | host=${1:-$OCI} | 6 | host=${1:-$OCI} |
10 | host=${host:-localhost} | 7 | host=${host:-localhost} |
11 | 8 | ||
12 | -open http://$host:8181/onos/tvue | 9 | +open http://$host:8181/onos/ui | ... | ... |
... | @@ -40,6 +40,7 @@ fi | ... | @@ -40,6 +40,7 @@ fi |
40 | # Load the cell setup | 40 | # Load the cell setup |
41 | . $ONOS_ROOT/tools/test/cells/${cell} | 41 | . $ONOS_ROOT/tools/test/cells/${cell} |
42 | 42 | ||
43 | +echo "ONOS_CELL=${ONOS_CELL}" | ||
43 | echo "ONOS_NIC=${ONOS_NIC}" | 44 | echo "ONOS_NIC=${ONOS_NIC}" |
44 | for n in {0..9}; do | 45 | for n in {0..9}; do |
45 | ocn="OC${n}" | 46 | ocn="OC${n}" | ... | ... |
... | @@ -108,33 +108,26 @@ | ... | @@ -108,33 +108,26 @@ |
108 | ], | 108 | ], |
109 | 109 | ||
110 | "links" : [ | 110 | "links" : [ |
111 | - { "src": "of:0000ffffffffff01/10", "dst": "of:0000ffffffffff02/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, | 111 | + { "src": "of:0000ffffffffff01/50", "dst": "of:0000ffffffffff02/30","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, |
112 | - { "src": "of:0000ffffffffff02/10", "dst": "of:0000ffffffffff03/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, | 112 | + { "src": "of:0000ffffffffff02/50", "dst": "of:0000ffffffffff03/30","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, |
113 | - { "src": "of:0000ffffffffff03/30", "dst": "of:0000ffffffffff04/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, | 113 | + { "src": "of:0000ffffffffff03/50", "dst": "of:0000ffffffffff04/50","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, |
114 | - { "src": "of:0000ffffffffff02/20", "dst": "of:0000ffffffffff05/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, | 114 | + { "src": "of:0000ffffffffff01/20", "dst": "of:0000ffffffffff05/50","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, |
115 | - { "src": "of:0000ffffffffff03/20", "dst": "of:0000ffffffffff06/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, | 115 | + { "src": "of:0000ffffffffff02/20", "dst": "of:0000ffffffffff05/20","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, |
116 | - { "src": "of:0000ffffffffff05/30", "dst": "of:0000ffffffffff06/20", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, | 116 | + { "src": "of:0000ffffffffff03/20", "dst": "of:0000ffffffffff06/50","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, |
117 | - { "src": "of:0000ffffffffff05/20", "dst": "of:0000ffffffffff07/21", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, | 117 | + { "src": "of:0000ffffffffff04/20", "dst": "of:0000ffffffffff06/20","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, |
118 | - { "src": "of:0000ffffffffff06/30", "dst": "of:0000ffffffffff08/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, | 118 | + { "src": "of:0000ffffffffff05/30", "dst": "of:0000ffffffffff06/40","type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, |
119 | - { "src": "of:0000ffffffffff07/30", "dst": "of:0000ffffffffff08/20", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, | 119 | + { "src": "of:0000ffffffffff05/40", "dst": "of:0000ffffffffff07/50", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, |
120 | - { "src": "of:0000ffffffffff07/20", "dst": "of:0000ffffffffff09/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, | 120 | + { "src": "of:0000ffffffffff06/30", "dst": "of:0000ffffffffff08/50", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, |
121 | - { "src": "of:0000ffffffffff08/30", "dst": "of:0000ffffffffff0A/10", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, | 121 | + { "src": "of:0000ffffffffff07/20", "dst": "of:0000ffffffffff08/30", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, |
122 | + { "src": "of:0000ffffffffff07/30", "dst": "of:0000ffffffffff09/50", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, | ||
123 | + { "src": "of:0000ffffffffff08/20", "dst": "of:0000ffffffffff0A/50", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, | ||
122 | { "src": "of:0000ffffffffff09/20", "dst": "of:0000ffffffffff0A/20", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, | 124 | { "src": "of:0000ffffffffff09/20", "dst": "of:0000ffffffffff0A/20", "type": "OPTICAL", "annotations": { "optical.waves": 80, "optical.type": "WDM", "optical.kms": 1000, "durable": "true" } }, |
123 | 125 | ||
124 | - { "src": "of:0000ffffffff0001/2", "dst": "of:0000ffffffffff01/1", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }, | 126 | + { "src": "of:0000ffffffff0001/2", "dst": "of:0000ffffffffff01/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }, |
125 | - { "src": "of:0000ffffffff0003/2", "dst": "of:0000ffffffffff03/1", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }, | 127 | + { "src": "of:0000ffffffff0002/2", "dst": "of:0000ffffffffff04/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }, |
126 | - { "src": "of:0000ffffffff0004/2", "dst": "of:0000ffffffffff04/1", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }, | 128 | + { "src": "of:0000ffffffff0003/2", "dst": "of:0000ffffffffff06/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }, |
127 | - { "src": "of:0000ffffffff0007/2", "dst": "of:0000ffffffffff07/1", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }, | 129 | + { "src": "of:0000ffffffff0004/2", "dst": "of:0000ffffffffff07/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }, |
128 | - { "src": "of:0000ffffffff0009/2", "dst": "of:0000ffffffffff09/1", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }, | 130 | + { "src": "of:0000ffffffff0005/2", "dst": "of:0000ffffffffff09/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } }, |
129 | - { "src": "of:0000ffffffff000A/2", "dst": "of:0000ffffffffff0A/1", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } } | 131 | + { "src": "of:0000ffffffff0006/2", "dst": "of:0000ffffffffff0A/10", "type": "OPTICAL", "annotations": { "bandwidth": 100000, "optical.type": "cross-connect", "durable": "true" } } |
130 | - ], | ||
131 | - | ||
132 | - "hosts" : [ | ||
133 | - { "mac": "00:00:00:00:00:01", "vlan": -1, "location": "of:0000ffffffff0001/1", "ip": "10.0.0.1" }, | ||
134 | - { "mac": "00:00:00:00:00:03", "vlan": -1, "location": "of:0000ffffffff0003/1", "ip": "10.0.0.3" }, | ||
135 | - { "mac": "00:00:00:00:00:04", "vlan": -1, "location": "of:0000ffffffff0004/1", "ip": "10.0.0.4" }, | ||
136 | - { "mac": "00:00:00:00:00:07", "vlan": -1, "location": "of:0000ffffffff0007/1", "ip": "10.0.0.7" }, | ||
137 | - { "mac": "00:00:00:00:00:09", "vlan": -1, "location": "of:0000ffffffff0009/1", "ip": "10.0.0.9" }, | ||
138 | - { "mac": "00:00:00:00:00:0A", "vlan": -1, "location": "of:0000ffffffff000A/1", "ip": "10.0.0.10" } | ||
139 | ] | 132 | ] |
140 | } | 133 | } | ... | ... |
... | @@ -43,9 +43,9 @@ public class ImmutableClassChecker { | ... | @@ -43,9 +43,9 @@ public class ImmutableClassChecker { |
43 | * @param clazz the class to check | 43 | * @param clazz the class to check |
44 | * @return true if the given class is a properly specified immutable class. | 44 | * @return true if the given class is a properly specified immutable class. |
45 | */ | 45 | */ |
46 | - private boolean isImmutableClass(Class<?> clazz) { | 46 | + private boolean isImmutableClass(Class<?> clazz, boolean allowNonFinalClass) { |
47 | // class must be declared final | 47 | // class must be declared final |
48 | - if (!Modifier.isFinal(clazz.getModifiers())) { | 48 | + if (!allowNonFinalClass && !Modifier.isFinal(clazz.getModifiers())) { |
49 | failureReason = "a class that is not final"; | 49 | failureReason = "a class that is not final"; |
50 | return false; | 50 | return false; |
51 | } | 51 | } |
... | @@ -113,16 +113,43 @@ public class ImmutableClassChecker { | ... | @@ -113,16 +113,43 @@ public class ImmutableClassChecker { |
113 | } | 113 | } |
114 | 114 | ||
115 | /** | 115 | /** |
116 | - * Assert that the given class adheres to the utility class rules. | 116 | + * Assert that the given class adheres to the immutable class rules. |
117 | * | 117 | * |
118 | * @param clazz the class to check | 118 | * @param clazz the class to check |
119 | * | 119 | * |
120 | - * @throws java.lang.AssertionError if the class is not a valid | 120 | + * @throws java.lang.AssertionError if the class is not an |
121 | - * utility class | 121 | + * immutable class |
122 | */ | 122 | */ |
123 | public static void assertThatClassIsImmutable(Class<?> clazz) { | 123 | public static void assertThatClassIsImmutable(Class<?> clazz) { |
124 | final ImmutableClassChecker checker = new ImmutableClassChecker(); | 124 | final ImmutableClassChecker checker = new ImmutableClassChecker(); |
125 | - if (!checker.isImmutableClass(clazz)) { | 125 | + if (!checker.isImmutableClass(clazz, false)) { |
126 | + final Description toDescription = new StringDescription(); | ||
127 | + final Description mismatchDescription = new StringDescription(); | ||
128 | + | ||
129 | + checker.describeTo(toDescription); | ||
130 | + checker.describeMismatch(mismatchDescription); | ||
131 | + final String reason = | ||
132 | + "\n" + | ||
133 | + "Expected: is \"" + toDescription.toString() + "\"\n" + | ||
134 | + " but : was \"" + mismatchDescription.toString() + "\""; | ||
135 | + | ||
136 | + throw new AssertionError(reason); | ||
137 | + } | ||
138 | + } | ||
139 | + | ||
140 | + /** | ||
141 | + * Assert that the given class adheres to the immutable class rules, but | ||
142 | + * is not declared final. Classes that need to be inherited from cannot be | ||
143 | + * declared final. | ||
144 | + * | ||
145 | + * @param clazz the class to check | ||
146 | + * | ||
147 | + * @throws java.lang.AssertionError if the class is not an | ||
148 | + * immutable class | ||
149 | + */ | ||
150 | + public static void assertThatClassIsImmutableBaseClass(Class<?> clazz) { | ||
151 | + final ImmutableClassChecker checker = new ImmutableClassChecker(); | ||
152 | + if (!checker.isImmutableClass(clazz, true)) { | ||
126 | final Description toDescription = new StringDescription(); | 153 | final Description toDescription = new StringDescription(); |
127 | final Description mismatchDescription = new StringDescription(); | 154 | final Description mismatchDescription = new StringDescription(); |
128 | 155 | ... | ... |
... | @@ -24,6 +24,7 @@ import org.onlab.onos.cluster.ClusterService; | ... | @@ -24,6 +24,7 @@ import org.onlab.onos.cluster.ClusterService; |
24 | import org.onlab.onos.cluster.ControllerNode; | 24 | import org.onlab.onos.cluster.ControllerNode; |
25 | import org.onlab.onos.cluster.NodeId; | 25 | import org.onlab.onos.cluster.NodeId; |
26 | import org.onlab.onos.mastership.MastershipService; | 26 | import org.onlab.onos.mastership.MastershipService; |
27 | +import org.onlab.onos.net.Annotated; | ||
27 | import org.onlab.onos.net.Annotations; | 28 | import org.onlab.onos.net.Annotations; |
28 | import org.onlab.onos.net.ConnectPoint; | 29 | import org.onlab.onos.net.ConnectPoint; |
29 | import org.onlab.onos.net.DefaultEdgeLink; | 30 | import org.onlab.onos.net.DefaultEdgeLink; |
... | @@ -45,6 +46,8 @@ import org.onlab.onos.net.link.LinkService; | ... | @@ -45,6 +46,8 @@ import org.onlab.onos.net.link.LinkService; |
45 | import org.onlab.onos.net.provider.ProviderId; | 46 | import org.onlab.onos.net.provider.ProviderId; |
46 | import org.onlab.osgi.ServiceDirectory; | 47 | import org.onlab.osgi.ServiceDirectory; |
47 | import org.onlab.packet.IpAddress; | 48 | import org.onlab.packet.IpAddress; |
49 | +import org.slf4j.Logger; | ||
50 | +import org.slf4j.LoggerFactory; | ||
48 | 51 | ||
49 | import java.util.Iterator; | 52 | import java.util.Iterator; |
50 | import java.util.Map; | 53 | import java.util.Map; |
... | @@ -68,6 +71,8 @@ import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED; | ... | @@ -68,6 +71,8 @@ import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED; |
68 | */ | 71 | */ |
69 | public abstract class TopologyMessages { | 72 | public abstract class TopologyMessages { |
70 | 73 | ||
74 | + protected static final Logger log = LoggerFactory.getLogger(TopologyMessages.class); | ||
75 | + | ||
71 | private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core", true); | 76 | private static final ProviderId PID = new ProviderId("core", "org.onlab.onos.core", true); |
72 | private static final String COMPACT = "%s/%s-%s/%s"; | 77 | private static final String COMPACT = "%s/%s-%s/%s"; |
73 | 78 | ||
... | @@ -195,7 +200,7 @@ public abstract class TopologyMessages { | ... | @@ -195,7 +200,7 @@ public abstract class TopologyMessages { |
195 | .put("id", device.id().toString()) | 200 | .put("id", device.id().toString()) |
196 | .put("type", device.type().toString().toLowerCase()) | 201 | .put("type", device.type().toString().toLowerCase()) |
197 | .put("online", deviceService.isAvailable(device.id())) | 202 | .put("online", deviceService.isAvailable(device.id())) |
198 | - .put("master", mastershipService.getMasterFor(device.id()).toString()); | 203 | + .put("master", master(device.id())); |
199 | 204 | ||
200 | // Generate labels: id, chassis id, no-label, optional-name | 205 | // Generate labels: id, chassis id, no-label, optional-name |
201 | ArrayNode labels = mapper.createArrayNode(); | 206 | ArrayNode labels = mapper.createArrayNode(); |
... | @@ -207,6 +212,7 @@ public abstract class TopologyMessages { | ... | @@ -207,6 +212,7 @@ public abstract class TopologyMessages { |
207 | // Add labels, props and stuff the payload into envelope. | 212 | // Add labels, props and stuff the payload into envelope. |
208 | payload.set("labels", labels); | 213 | payload.set("labels", labels); |
209 | payload.set("props", props(device.annotations())); | 214 | payload.set("props", props(device.annotations())); |
215 | + addGeoLocation(device, payload); | ||
210 | addMetaUi(device.id().toString(), payload); | 216 | addMetaUi(device.id().toString(), payload); |
211 | 217 | ||
212 | String type = (event.type() == DEVICE_ADDED) ? "addDevice" : | 218 | String type = (event.type() == DEVICE_ADDED) ? "addDevice" : |
... | @@ -220,6 +226,7 @@ public abstract class TopologyMessages { | ... | @@ -220,6 +226,7 @@ public abstract class TopologyMessages { |
220 | ObjectNode payload = mapper.createObjectNode() | 226 | ObjectNode payload = mapper.createObjectNode() |
221 | .put("id", compactLinkString(link)) | 227 | .put("id", compactLinkString(link)) |
222 | .put("type", link.type().toString().toLowerCase()) | 228 | .put("type", link.type().toString().toLowerCase()) |
229 | + .put("online", true) // TODO: add link state field | ||
223 | .put("linkWidth", 2) | 230 | .put("linkWidth", 2) |
224 | .put("src", link.src().deviceId().toString()) | 231 | .put("src", link.src().deviceId().toString()) |
225 | .put("srcPort", link.src().port().toString()) | 232 | .put("srcPort", link.src().port().toString()) |
... | @@ -237,10 +244,11 @@ public abstract class TopologyMessages { | ... | @@ -237,10 +244,11 @@ public abstract class TopologyMessages { |
237 | .put("id", host.id().toString()) | 244 | .put("id", host.id().toString()) |
238 | .put("ingress", compactLinkString(edgeLink(host, true))) | 245 | .put("ingress", compactLinkString(edgeLink(host, true))) |
239 | .put("egress", compactLinkString(edgeLink(host, false))); | 246 | .put("egress", compactLinkString(edgeLink(host, false))); |
240 | - payload.set("cp", location(mapper, host.location())); | 247 | + payload.set("cp", hostConnect(mapper, host.location())); |
241 | payload.set("labels", labels(mapper, ip(host.ipAddresses()), | 248 | payload.set("labels", labels(mapper, ip(host.ipAddresses()), |
242 | host.mac().toString())); | 249 | host.mac().toString())); |
243 | payload.set("props", props(host.annotations())); | 250 | payload.set("props", props(host.annotations())); |
251 | + addGeoLocation(host, payload); | ||
244 | addMetaUi(host.id().toString(), payload); | 252 | addMetaUi(host.id().toString(), payload); |
245 | 253 | ||
246 | String type = (event.type() == HOST_ADDED) ? "addHost" : | 254 | String type = (event.type() == HOST_ADDED) ? "addHost" : |
... | @@ -249,7 +257,7 @@ public abstract class TopologyMessages { | ... | @@ -249,7 +257,7 @@ public abstract class TopologyMessages { |
249 | } | 257 | } |
250 | 258 | ||
251 | // Encodes the specified host location into a JSON object. | 259 | // Encodes the specified host location into a JSON object. |
252 | - private ObjectNode location(ObjectMapper mapper, HostLocation location) { | 260 | + private ObjectNode hostConnect(ObjectMapper mapper, HostLocation location) { |
253 | return mapper.createObjectNode() | 261 | return mapper.createObjectNode() |
254 | .put("device", location.deviceId().toString()) | 262 | .put("device", location.deviceId().toString()) |
255 | .put("port", location.port().toLong()); | 263 | .put("port", location.port().toLong()); |
... | @@ -264,6 +272,12 @@ public abstract class TopologyMessages { | ... | @@ -264,6 +272,12 @@ public abstract class TopologyMessages { |
264 | return json; | 272 | return json; |
265 | } | 273 | } |
266 | 274 | ||
275 | + // Returns the name of the master node for the specified device id. | ||
276 | + private String master(DeviceId deviceId) { | ||
277 | + NodeId master = mastershipService.getMasterFor(deviceId); | ||
278 | + return master != null ? master.toString() : ""; | ||
279 | + } | ||
280 | + | ||
267 | // Generates an edge link from the specified host location. | 281 | // Generates an edge link from the specified host location. |
268 | private EdgeLink edgeLink(Host host, boolean ingress) { | 282 | private EdgeLink edgeLink(Host host, boolean ingress) { |
269 | return new DefaultEdgeLink(PID, new ConnectPoint(host.id(), portNumber(0)), | 283 | return new DefaultEdgeLink(PID, new ConnectPoint(host.id(), portNumber(0)), |
... | @@ -278,10 +292,28 @@ public abstract class TopologyMessages { | ... | @@ -278,10 +292,28 @@ public abstract class TopologyMessages { |
278 | } | 292 | } |
279 | } | 293 | } |
280 | 294 | ||
295 | + // Adds a geo location JSON to the specified payload object. | ||
296 | + private void addGeoLocation(Annotated annotated, ObjectNode payload) { | ||
297 | + Annotations annotations = annotated.annotations(); | ||
298 | + String slat = annotations.value("latitude"); | ||
299 | + String slng = annotations.value("longitude"); | ||
300 | + try { | ||
301 | + if (slat != null && slng != null && !slat.isEmpty() && !slng.isEmpty()) { | ||
302 | + double lat = Double.parseDouble(slat); | ||
303 | + double lng = Double.parseDouble(slng); | ||
304 | + ObjectNode loc = mapper.createObjectNode() | ||
305 | + .put("type", "latlng").put("lat", lat).put("lng", lng); | ||
306 | + payload.set("location", loc); | ||
307 | + } | ||
308 | + } catch (NumberFormatException e) { | ||
309 | + log.warn("Invalid geo data latitude={}; longiture={}", slat, slng); | ||
310 | + } | ||
311 | + } | ||
312 | + | ||
281 | // Updates meta UI information for the specified object. | 313 | // Updates meta UI information for the specified object. |
282 | protected void updateMetaUi(ObjectNode event) { | 314 | protected void updateMetaUi(ObjectNode event) { |
283 | ObjectNode payload = payload(event); | 315 | ObjectNode payload = payload(event); |
284 | - metaUi.put(string(payload, "id"), payload); | 316 | + metaUi.put(string(payload, "id"), (ObjectNode) payload.path("memento")); |
285 | } | 317 | } |
286 | 318 | ||
287 | // Returns device details response. | 319 | // Returns device details response. |
... | @@ -289,7 +321,6 @@ public abstract class TopologyMessages { | ... | @@ -289,7 +321,6 @@ public abstract class TopologyMessages { |
289 | Device device = deviceService.getDevice(deviceId); | 321 | Device device = deviceService.getDevice(deviceId); |
290 | Annotations annot = device.annotations(); | 322 | Annotations annot = device.annotations(); |
291 | int portCount = deviceService.getPorts(deviceId).size(); | 323 | int portCount = deviceService.getPorts(deviceId).size(); |
292 | - NodeId master = mastershipService.getMasterFor(device.id()); | ||
293 | return envelope("showDetails", sid, | 324 | return envelope("showDetails", sid, |
294 | json(deviceId.toString(), | 325 | json(deviceId.toString(), |
295 | device.type().toString().toLowerCase(), | 326 | device.type().toString().toLowerCase(), |
... | @@ -303,7 +334,7 @@ public abstract class TopologyMessages { | ... | @@ -303,7 +334,7 @@ public abstract class TopologyMessages { |
303 | new Prop("Longitude", annot.value("longitude")), | 334 | new Prop("Longitude", annot.value("longitude")), |
304 | new Prop("Ports", Integer.toString(portCount)), | 335 | new Prop("Ports", Integer.toString(portCount)), |
305 | new Separator(), | 336 | new Separator(), |
306 | - new Prop("Master", master.toString()))); | 337 | + new Prop("Master", master(deviceId)))); |
307 | } | 338 | } |
308 | 339 | ||
309 | // Returns host details response. | 340 | // Returns host details response. |
... | @@ -319,16 +350,15 @@ public abstract class TopologyMessages { | ... | @@ -319,16 +350,15 @@ public abstract class TopologyMessages { |
319 | new Prop("Longitude", annot.value("longitude")))); | 350 | new Prop("Longitude", annot.value("longitude")))); |
320 | } | 351 | } |
321 | 352 | ||
322 | - | ||
323 | // Produces a path message to the client. | 353 | // Produces a path message to the client. |
324 | - protected ObjectNode pathMessage(Path path) { | 354 | + protected ObjectNode pathMessage(Path path, String type) { |
325 | ObjectNode payload = mapper.createObjectNode(); | 355 | ObjectNode payload = mapper.createObjectNode(); |
326 | ArrayNode links = mapper.createArrayNode(); | 356 | ArrayNode links = mapper.createArrayNode(); |
327 | for (Link link : path.links()) { | 357 | for (Link link : path.links()) { |
328 | links.add(compactLinkString(link)); | 358 | links.add(compactLinkString(link)); |
329 | } | 359 | } |
330 | 360 | ||
331 | - payload.set("links", links); | 361 | + payload.put("type", type).set("links", links); |
332 | return payload; | 362 | return payload; |
333 | } | 363 | } |
334 | 364 | ... | ... |
... | @@ -110,8 +110,8 @@ public class TopologyWebSocket | ... | @@ -110,8 +110,8 @@ public class TopologyWebSocket |
110 | try { | 110 | try { |
111 | ObjectNode event = (ObjectNode) mapper.reader().readTree(data); | 111 | ObjectNode event = (ObjectNode) mapper.reader().readTree(data); |
112 | String type = string(event, "event", "unknown"); | 112 | String type = string(event, "event", "unknown"); |
113 | - if (type.equals("showDetails")) { | 113 | + if (type.equals("requestDetails")) { |
114 | - showDetails(event); | 114 | + requestDetails(event); |
115 | } else if (type.equals("updateMeta")) { | 115 | } else if (type.equals("updateMeta")) { |
116 | updateMetaUi(event); | 116 | updateMetaUi(event); |
117 | } else if (type.equals("requestPath")) { | 117 | } else if (type.equals("requestPath")) { |
... | @@ -122,7 +122,7 @@ public class TopologyWebSocket | ... | @@ -122,7 +122,7 @@ public class TopologyWebSocket |
122 | cancelTraffic(event); | 122 | cancelTraffic(event); |
123 | } | 123 | } |
124 | } catch (Exception e) { | 124 | } catch (Exception e) { |
125 | - System.out.println("WTF?! " + data); | 125 | + log.warn("Unable to parse GUI request {} due to {}", data, e); |
126 | e.printStackTrace(); | 126 | e.printStackTrace(); |
127 | } | 127 | } |
128 | } | 128 | } |
... | @@ -165,9 +165,9 @@ public class TopologyWebSocket | ... | @@ -165,9 +165,9 @@ public class TopologyWebSocket |
165 | } | 165 | } |
166 | 166 | ||
167 | // Sends back device or host details. | 167 | // Sends back device or host details. |
168 | - private void showDetails(ObjectNode event) { | 168 | + private void requestDetails(ObjectNode event) { |
169 | ObjectNode payload = payload(event); | 169 | ObjectNode payload = payload(event); |
170 | - String type = string(payload, "type", "unknown"); | 170 | + String type = string(payload, "class", "unknown"); |
171 | if (type.equals("device")) { | 171 | if (type.equals("device")) { |
172 | sendMessage(deviceDetails(deviceId(string(payload, "id")), | 172 | sendMessage(deviceDetails(deviceId(string(payload, "id")), |
173 | number(event, "sid"))); | 173 | number(event, "sid"))); |
... | @@ -282,7 +282,8 @@ public class TopologyWebSocket | ... | @@ -282,7 +282,8 @@ public class TopologyWebSocket |
282 | if (installable != null && !installable.isEmpty()) { | 282 | if (installable != null && !installable.isEmpty()) { |
283 | PathIntent pathIntent = (PathIntent) installable.iterator().next(); | 283 | PathIntent pathIntent = (PathIntent) installable.iterator().next(); |
284 | Path path = pathIntent.path(); | 284 | Path path = pathIntent.path(); |
285 | - ObjectNode payload = pathMessage(path).put("intentId", intent.id().toString()); | 285 | + ObjectNode payload = pathMessage(path, "host") |
286 | + .put("intentId", intent.id().toString()); | ||
286 | sendMessage(envelope("showPath", sid, payload)); | 287 | sendMessage(envelope("showPath", sid, payload)); |
287 | } | 288 | } |
288 | } | 289 | } | ... | ... |
... | @@ -21,7 +21,7 @@ | ... | @@ -21,7 +21,7 @@ |
21 | <display-name>ONOS GUI</display-name> | 21 | <display-name>ONOS GUI</display-name> |
22 | 22 | ||
23 | <welcome-file-list> | 23 | <welcome-file-list> |
24 | - <welcome-file>index.html</welcome-file> | 24 | + <welcome-file>index2.html</welcome-file> |
25 | </welcome-file-list> | 25 | </welcome-file-list> |
26 | 26 | ||
27 | <servlet> | 27 | <servlet> | ... | ... |
web/gui/src/main/webapp/floatPanel.css
0 → 100644
1 | +/* | ||
2 | + * Copyright 2014 Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +/* | ||
18 | + ONOS GUI -- Floating Panels -- CSS file | ||
19 | + | ||
20 | + @author Simon Hunt | ||
21 | + */ | ||
22 | + | ||
23 | +.fpanel { | ||
24 | + position: absolute; | ||
25 | + z-index: 100; | ||
26 | + display: block; | ||
27 | + top: 10%; | ||
28 | + width: 280px; | ||
29 | + right: -300px; | ||
30 | + opacity: 0; | ||
31 | + background-color: rgba(255,255,255,0.8); | ||
32 | + | ||
33 | + padding: 10px; | ||
34 | + color: black; | ||
35 | + font-size: 10pt; | ||
36 | + box-shadow: 2px 2px 16px #777; | ||
37 | +} | ||
38 | + | ||
39 | +/* TODO: light/dark themes */ | ||
40 | +.light .fpanel { | ||
41 | + | ||
42 | +} | ||
43 | +.dark .fpanel { | ||
44 | + | ||
45 | +} |
... | @@ -40,6 +40,7 @@ | ... | @@ -40,6 +40,7 @@ |
40 | <link rel="stylesheet" href="base.css"> | 40 | <link rel="stylesheet" href="base.css"> |
41 | <link rel="stylesheet" href="onos2.css"> | 41 | <link rel="stylesheet" href="onos2.css"> |
42 | <link rel="stylesheet" href="mast2.css"> | 42 | <link rel="stylesheet" href="mast2.css"> |
43 | + <link rel="stylesheet" href="floatPanel.css"> | ||
43 | 44 | ||
44 | <!-- This is where contributed stylesheets get INJECTED --> | 45 | <!-- This is where contributed stylesheets get INJECTED --> |
45 | <!-- TODO: replace with template marker and inject refs server-side --> | 46 | <!-- TODO: replace with template marker and inject refs server-side --> |
... | @@ -62,8 +63,9 @@ | ... | @@ -62,8 +63,9 @@ |
62 | <div id="view"> | 63 | <div id="view"> |
63 | <!-- NOTE: views injected here by onos.js --> | 64 | <!-- NOTE: views injected here by onos.js --> |
64 | </div> | 65 | </div> |
65 | - <div id="overlays"> | 66 | + <div id="floatPanels"> |
66 | - <!-- NOTE: overlays injected here, as needed --> | 67 | + <!-- NOTE: floating panels injected here, as needed --> |
68 | + <!-- see onos.ui.addFloatingPanel --> | ||
67 | </div> | 69 | </div> |
68 | <div id="alerts"> | 70 | <div id="alerts"> |
69 | <!-- NOTE: alert content injected here, as needed --> | 71 | <!-- NOTE: alert content injected here, as needed --> | ... | ... |
1 | +{ | ||
2 | + "event": "addDevice", | ||
3 | + "payload": { | ||
4 | + "id": "of:0000000000000003", | ||
5 | + "type": "switch", | ||
6 | + "online": true, | ||
7 | + "labels": [ | ||
8 | + "of:0000000000000003", | ||
9 | + "3", | ||
10 | + "", | ||
11 | + null | ||
12 | + ], | ||
13 | + "props": { | ||
14 | + "latitude": 123.5, | ||
15 | + "longitude": 67.8, | ||
16 | + "anotherProp": "foobar" | ||
17 | + }, | ||
18 | + "metaUi": { | ||
19 | + "xpc": 57.3, | ||
20 | + "ypc": 24.86, | ||
21 | + "and": "other properties the UI wishes to remember..." | ||
22 | + } | ||
23 | + } | ||
24 | +} |
1 | +{ | ||
2 | + "event": "showDetails", | ||
3 | + "sid": 9, | ||
4 | + "payload": { | ||
5 | + "id": "CA:4B:EE:A4:B0:33/-1", | ||
6 | + "type": "host", | ||
7 | + "propOrder": [ | ||
8 | + "MAC", | ||
9 | + "IP", | ||
10 | + "-", | ||
11 | + "Latitude", | ||
12 | + "Longitude" | ||
13 | + ], | ||
14 | + "props": { | ||
15 | + "MAC": "CA:4B:EE:A4:B0:33", | ||
16 | + "IP": "[10.0.0.1]", | ||
17 | + "-": "", | ||
18 | + "Latitude": null, | ||
19 | + "Longitude": null | ||
20 | + } | ||
21 | + } | ||
22 | +} |
1 | +{ | ||
2 | + "event": "showDetails", | ||
3 | + "sid": 37, | ||
4 | + "payload": { | ||
5 | + "id": "of:000000000000000a", | ||
6 | + "type": "switch", | ||
7 | + "propOrder": [ | ||
8 | + "Name", | ||
9 | + "Vendor", | ||
10 | + "H/W Version", | ||
11 | + "S/W Version", | ||
12 | + "Serial Number", | ||
13 | + "-", | ||
14 | + "Latitude", | ||
15 | + "Longitude", | ||
16 | + "Ports", | ||
17 | + "-", | ||
18 | + "Master" | ||
19 | + ], | ||
20 | + "props": { | ||
21 | + "Name": null, | ||
22 | + "Vendor": "Nicira, Inc.", | ||
23 | + "H/W Version": "Open vSwitch", | ||
24 | + "S/W Version": "2.0.1", | ||
25 | + "Serial Number": "None", | ||
26 | + "-": "", | ||
27 | + "Latitude": null, | ||
28 | + "Longitude": null, | ||
29 | + "Ports": "5", | ||
30 | + "Master":"local" | ||
31 | + } | ||
32 | + } | ||
33 | +} |
... | @@ -4,7 +4,11 @@ | ... | @@ -4,7 +4,11 @@ |
4 | "payload": { | 4 | "payload": { |
5 | "id": "62:4F:65:BF:FF:B3/-1", | 5 | "id": "62:4F:65:BF:FF:B3/-1", |
6 | "class": "host", | 6 | "class": "host", |
7 | - "x": 197, | 7 | + "memento": { |
8 | - "y": 177 | 8 | + "xpc": 57.3, |
9 | + "ypc": 24.86, | ||
10 | + "and": "other properties the UI wishes to remember..." | ||
11 | + } | ||
9 | } | 12 | } |
10 | } | 13 | } |
14 | + | ... | ... |
... | @@ -5,5 +5,9 @@ | ... | @@ -5,5 +5,9 @@ |
5 | "title": "Host Intent Scenario", | 5 | "title": "Host Intent Scenario", |
6 | "params": { | 6 | "params": { |
7 | "lastAuto": 0 | 7 | "lastAuto": 0 |
8 | - } | 8 | + }, |
9 | + "description": [ | ||
10 | + "Currently this is just a sketch of the event sequence,", | ||
11 | + " but is NOT YET a runnable scenario." | ||
12 | + ] | ||
9 | } | 13 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
1 | +{ | ||
2 | + "event": "removeHost", | ||
3 | + "payload": { | ||
4 | + "id": "A6:96:E5:03:52:5F/-1", | ||
5 | + "ingress": "A6:96:E5:03:52:5F/-1/0-of:0000ffffffff0008/1", | ||
6 | + "egress": "of:0000ffffffff0008/1-A6:96:E5:03:52:5F/-1/0", | ||
7 | + "cp": { | ||
8 | + "device": "of:0000ffffffff0008", | ||
9 | + "port": 1 | ||
10 | + }, | ||
11 | + "labels": [ | ||
12 | + "10.0.0.17", | ||
13 | + "A6:96:E5:03:52:5F" | ||
14 | + ], | ||
15 | + "props": {} | ||
16 | + } | ||
17 | +} |
... | @@ -4,6 +4,11 @@ | ... | @@ -4,6 +4,11 @@ |
4 | "id": "of:0000ffffffff0008", | 4 | "id": "of:0000ffffffff0008", |
5 | "type": "switch", | 5 | "type": "switch", |
6 | "online": false, | 6 | "online": false, |
7 | + "location": { | ||
8 | + "type": "latlng", | ||
9 | + "lat": 37.6, | ||
10 | + "lng": 122.3 | ||
11 | + }, | ||
7 | "labels": [ | 12 | "labels": [ |
8 | "0000ffffffff0008", | 13 | "0000ffffffff0008", |
9 | "FF:FF:FF:FF:00:08", | 14 | "FF:FF:FF:FF:00:08", | ... | ... |
... | @@ -20,6 +20,6 @@ | ... | @@ -20,6 +20,6 @@ |
20 | "10. update link (increase width, update props)", | 20 | "10. update link (increase width, update props)", |
21 | "11. update link (reduce width, update props)", | 21 | "11. update link (reduce width, update props)", |
22 | "12. remove link", | 22 | "12. remove link", |
23 | - "" | 23 | + "13. remove host (10.0.0.17)" |
24 | ] | 24 | ] |
25 | } | 25 | } | ... | ... |
... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
3 | "payload": { | 3 | "payload": { |
4 | "id": "of:0000ffffffffff04", | 4 | "id": "of:0000ffffffffff04", |
5 | "type": "roadm", | 5 | "type": "roadm", |
6 | - "online": false, | 6 | + "online": true, |
7 | "labels": [ | 7 | "labels": [ |
8 | "0000ffffffffff04", | 8 | "0000ffffffffff04", |
9 | "FF:FF:FF:FF:FF:04", | 9 | "FF:FF:FF:FF:FF:04", | ... | ... |
... | @@ -3,15 +3,15 @@ | ... | @@ -3,15 +3,15 @@ |
3 | "payload": { | 3 | "payload": { |
4 | "id": "of:0000ffffffff000A", | 4 | "id": "of:0000ffffffff000A", |
5 | "type": "switch", | 5 | "type": "switch", |
6 | - "online": false, | 6 | + "online": true, |
7 | "labels": [ | 7 | "labels": [ |
8 | "0000ffffffff000A", | 8 | "0000ffffffff000A", |
9 | "FF:FF:FF:FF:00:0A", | 9 | "FF:FF:FF:FF:00:0A", |
10 | "?" | 10 | "?" |
11 | ], | 11 | ], |
12 | "metaUi": { | 12 | "metaUi": { |
13 | - "Zx": 832, | 13 | + "x": 832, |
14 | - "Zy": 223 | 14 | + "y": 223 |
15 | } | 15 | } |
16 | } | 16 | } |
17 | } | 17 | } | ... | ... |
... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
3 | "payload": { | 3 | "payload": { |
4 | "id": "of:0000ffffffff0001", | 4 | "id": "of:0000ffffffff0001", |
5 | "type": "switch", | 5 | "type": "switch", |
6 | - "online": false, | 6 | + "online": true, |
7 | "labels": [ | 7 | "labels": [ |
8 | "0000ffffffff0001", | 8 | "0000ffffffff0001", |
9 | "FF:FF:FF:FF:00:01", | 9 | "FF:FF:FF:FF:00:01", | ... | ... |
... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
3 | "payload": { | 3 | "payload": { |
4 | "id": "of:0000ffffffffff01", | 4 | "id": "of:0000ffffffffff01", |
5 | "type": "roadm", | 5 | "type": "roadm", |
6 | - "online": false, | 6 | + "online": true, |
7 | "labels": [ | 7 | "labels": [ |
8 | "0000ffffffffff01", | 8 | "0000ffffffffff01", |
9 | "FF:FF:FF:FF:FF:01", | 9 | "FF:FF:FF:FF:FF:01", | ... | ... |
... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
3 | "payload": { | 3 | "payload": { |
4 | "id": "of:0000ffffffff0004", | 4 | "id": "of:0000ffffffff0004", |
5 | "type": "switch", | 5 | "type": "switch", |
6 | - "online": false, | 6 | + "online": true, |
7 | "labels": [ | 7 | "labels": [ |
8 | "0000ffffffff0004", | 8 | "0000ffffffff0004", |
9 | "FF:FF:FF:FF:00:04", | 9 | "FF:FF:FF:FF:00:04", | ... | ... |
... | @@ -3,15 +3,15 @@ | ... | @@ -3,15 +3,15 @@ |
3 | "payload": { | 3 | "payload": { |
4 | "id": "of:0000ffffffffff0A", | 4 | "id": "of:0000ffffffffff0A", |
5 | "type": "roadm", | 5 | "type": "roadm", |
6 | - "online": false, | 6 | + "online": true, |
7 | "labels": [ | 7 | "labels": [ |
8 | "0000ffffffffff0A", | 8 | "0000ffffffffff0A", |
9 | "FF:FF:FF:FF:FF:0A", | 9 | "FF:FF:FF:FF:FF:0A", |
10 | "?" | 10 | "?" |
11 | ], | 11 | ], |
12 | "metaUi": { | 12 | "metaUi": { |
13 | - "Zx": 840, | 13 | + "x": 840, |
14 | - "Zy": 290 | 14 | + "y": 290 |
15 | } | 15 | } |
16 | } | 16 | } |
17 | } | 17 | } | ... | ... |
... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
3 | "payload": { | 3 | "payload": { |
4 | "id": "of:0000ffffffffff09", | 4 | "id": "of:0000ffffffffff09", |
5 | "type": "roadm", | 5 | "type": "roadm", |
6 | - "online": false, | 6 | + "online": true, |
7 | "labels": [ | 7 | "labels": [ |
8 | "0000ffffffffff09", | 8 | "0000ffffffffff09", |
9 | "FF:FF:FF:FF:FF:09", | 9 | "FF:FF:FF:FF:FF:09", | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | + "id": "of:0000ffffffffff02/20-of:0000ffffffffff05/10", | ||
5 | + "type": "optical", | ||
6 | + "linkWidth": 4, | ||
4 | "src": "of:0000ffffffffff02", | 7 | "src": "of:0000ffffffffff02", |
5 | "srcPort": "20", | 8 | "srcPort": "20", |
6 | "dst": "of:0000ffffffffff05", | 9 | "dst": "of:0000ffffffffff05", |
7 | "dstPort": "10", | 10 | "dstPort": "10", |
8 | - "type": "optical", | ||
9 | - "linkWidth": 6, | ||
10 | "props" : { | 11 | "props" : { |
11 | "BW": "80 G" | 12 | "BW": "80 G" |
12 | } | 13 | } | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | + "id": "of:0000ffffffff000A/2-of:0000ffffffffff0A/1", | ||
5 | + "type": "optical", | ||
6 | + "linkWidth": 2, | ||
4 | "src": "of:0000ffffffff000A", | 7 | "src": "of:0000ffffffff000A", |
5 | "srcPort": "2", | 8 | "srcPort": "2", |
6 | "dst": "of:0000ffffffffff0A", | 9 | "dst": "of:0000ffffffffff0A", |
7 | "dstPort": "1", | 10 | "dstPort": "1", |
8 | - "type": "optical", | ||
9 | - "linkWidth": 2, | ||
10 | "props" : { | 11 | "props" : { |
11 | "BW": "100 G" | 12 | "BW": "100 G" |
12 | } | 13 | } | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | + "id": "of:0000ffffffffff03/10-of:0000ffffffffff02/10", | ||
5 | + "type": "optical", | ||
6 | + "linkWidth": 2, | ||
4 | "src": "of:0000ffffffffff03", | 7 | "src": "of:0000ffffffffff03", |
5 | "srcPort": "10", | 8 | "srcPort": "10", |
6 | "dst": "of:0000ffffffffff02", | 9 | "dst": "of:0000ffffffffff02", |
7 | "dstPort": "10", | 10 | "dstPort": "10", |
8 | - "type": "optical", | ||
9 | - "linkWidth": 2, | ||
10 | "props" : { | 11 | "props" : { |
11 | "BW": "70 G" | 12 | "BW": "70 G" |
12 | } | 13 | } | ... | ... |
... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
3 | "payload": { | 3 | "payload": { |
4 | "id": "of:0000ffffffffff08", | 4 | "id": "of:0000ffffffffff08", |
5 | "type": "roadm", | 5 | "type": "roadm", |
6 | - "online": false, | 6 | + "online": true, |
7 | "labels": [ | 7 | "labels": [ |
8 | "0000ffffffffff08", | 8 | "0000ffffffffff08", |
9 | "FF:FF:FF:FF:FF:08", | 9 | "FF:FF:FF:FF:FF:08", | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | + "id": "of:0000ffffffffff07/21-of:0000ffffffffff05/20", | ||
5 | + "type": "optical", | ||
6 | + "linkWidth": 2, | ||
4 | "src": "of:0000ffffffffff07", | 7 | "src": "of:0000ffffffffff07", |
5 | "srcPort": "21", | 8 | "srcPort": "21", |
6 | "dst": "of:0000ffffffffff05", | 9 | "dst": "of:0000ffffffffff05", |
7 | "dstPort": "20", | 10 | "dstPort": "20", |
8 | - "type": "optical", | ||
9 | - "linkWidth": 2, | ||
10 | "props" : { | 11 | "props" : { |
11 | "BW": "70 G" | 12 | "BW": "70 G" |
12 | } | 13 | } | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | + "id": "of:0000ffffffff0001/2-of:0000ffffffffff01/1", | ||
5 | + "type": "optical", | ||
6 | + "linkWidth": 2, | ||
4 | "src": "of:0000ffffffff0001", | 7 | "src": "of:0000ffffffff0001", |
5 | "srcPort": "2", | 8 | "srcPort": "2", |
6 | "dst": "of:0000ffffffffff01", | 9 | "dst": "of:0000ffffffffff01", |
7 | "dstPort": "1", | 10 | "dstPort": "1", |
8 | - "type": "optical", | ||
9 | - "linkWidth": 2, | ||
10 | "props" : { | 11 | "props" : { |
11 | "BW": "70 G" | 12 | "BW": "70 G" |
12 | } | 13 | } | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | + "id": "of:0000ffffffffff09/20-of:0000ffffffffff0A/20", | ||
5 | + "type": "optical", | ||
6 | + "linkWidth": 2, | ||
4 | "src": "of:0000ffffffffff09", | 7 | "src": "of:0000ffffffffff09", |
5 | "srcPort": "20", | 8 | "srcPort": "20", |
6 | "dst": "of:0000ffffffffff0A", | 9 | "dst": "of:0000ffffffffff0A", |
7 | "dstPort": "20", | 10 | "dstPort": "20", |
8 | - "type": "optical", | ||
9 | - "linkWidth": 2, | ||
10 | "props" : { | 11 | "props" : { |
11 | "BW": "70 G" | 12 | "BW": "70 G" |
12 | } | 13 | } | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | - "src": "of:0000ffffffffff06", | 4 | + "id": "of:0000ffffffffff07/30-of:0000ffffffffff08/20", |
5 | - "srcPort": "20", | ||
6 | - "dst": "of:0000ffffffffff05", | ||
7 | - "dstPort": "30", | ||
8 | "type": "optical", | 5 | "type": "optical", |
9 | - "linkWidth": 6, | 6 | + "linkWidth": 4, |
7 | + "src": "of:0000ffffffffff07", | ||
8 | + "srcPort": "30", | ||
9 | + "dst": "of:0000ffffffffff08", | ||
10 | + "dstPort": "20", | ||
10 | "props" : { | 11 | "props" : { |
11 | "BW": "70 G" | 12 | "BW": "70 G" |
12 | } | 13 | } | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | - "src": "of:0000ffffffffff07", | 4 | + "id": "of:0000ffffffffff02/10-of:0000ffffffffff01/10", |
5 | - "srcPort": "30", | ||
6 | - "dst": "of:0000ffffffffff08", | ||
7 | - "dstPort": "20", | ||
8 | "type": "optical", | 5 | "type": "optical", |
9 | - "linkWidth": 6, | 6 | + "linkWidth": 2, |
7 | + "src": "of:0000ffffffffff02", | ||
8 | + "srcPort": "10", | ||
9 | + "dst": "of:0000ffffffffff01", | ||
10 | + "dstPort": "10", | ||
10 | "props" : { | 11 | "props" : { |
11 | "BW": "70 G" | 12 | "BW": "70 G" |
12 | } | 13 | } | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | - "src": "of:0000ffffffffff03", | 4 | + "id": "of:0000ffffffffff04/27-of:0000ffffffffff08/10", |
5 | - "srcPort": "20", | 5 | + "src": "of:0000ffffffffff04", |
6 | - "dst": "of:0000ffffffffff06", | 6 | + "srcPort": "27", |
7 | + "dst": "of:0000ffffffffff08", | ||
7 | "dstPort": "10", | 8 | "dstPort": "10", |
8 | "type": "optical", | 9 | "type": "optical", |
9 | "linkWidth": 2, | 10 | "linkWidth": 2, |
10 | "props" : { | 11 | "props" : { |
11 | - "BW": "70 G" | 12 | + "BW": "30 G" |
12 | } | 13 | } |
13 | } | 14 | } |
14 | } | 15 | } | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | - "src": "of:0000ffffffffff02", | 4 | + "id": "of:0000ffffffff0003/2-of:0000ffffffffff03/1", |
5 | - "srcPort": "10", | ||
6 | - "dst": "of:0000ffffffffff01", | ||
7 | - "dstPort": "10", | ||
8 | "type": "optical", | 5 | "type": "optical", |
9 | "linkWidth": 2, | 6 | "linkWidth": 2, |
7 | + "src": "of:0000ffffffff0003", | ||
8 | + "srcPort": "2", | ||
9 | + "dst": "of:0000ffffffffff03", | ||
10 | + "dstPort": "1", | ||
10 | "props" : { | 11 | "props" : { |
11 | "BW": "70 G" | 12 | "BW": "70 G" |
12 | } | 13 | } | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | + "id": "of:0000ffffffffff09/1-of:0000ffffffff0009/2", | ||
5 | + "type": "optical", | ||
6 | + "linkWidth": 2, | ||
4 | "src": "of:0000ffffffffff09", | 7 | "src": "of:0000ffffffffff09", |
5 | "srcPort": "1", | 8 | "srcPort": "1", |
6 | "dst": "of:0000ffffffff0009", | 9 | "dst": "of:0000ffffffff0009", |
7 | "dstPort": "2", | 10 | "dstPort": "2", |
8 | - "type": "optical", | ||
9 | - "linkWidth": 2, | ||
10 | "props" : { | 11 | "props" : { |
11 | "BW": "70 G" | 12 | "BW": "70 G" |
12 | } | 13 | } | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | + "id": "of:0000ffffffffff03/30-of:0000ffffffffff04/10", | ||
5 | + "type": "optical", | ||
6 | + "linkWidth": 2, | ||
4 | "src": "of:0000ffffffffff03", | 7 | "src": "of:0000ffffffffff03", |
5 | "srcPort": "30", | 8 | "srcPort": "30", |
6 | "dst": "of:0000ffffffffff04", | 9 | "dst": "of:0000ffffffffff04", |
7 | "dstPort": "10", | 10 | "dstPort": "10", |
8 | - "type": "optical", | ||
9 | - "linkWidth": 2, | ||
10 | "props" : { | 11 | "props" : { |
11 | "BW": "70 G" | 12 | "BW": "70 G" |
12 | } | 13 | } | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | + "id": "of:0000ffffffffff07/20-of:0000ffffffffff09/10", | ||
5 | + "type": "optical", | ||
6 | + "linkWidth": 2, | ||
4 | "src": "of:0000ffffffffff07", | 7 | "src": "of:0000ffffffffff07", |
5 | "srcPort": "20", | 8 | "srcPort": "20", |
6 | "dst": "of:0000ffffffffff09", | 9 | "dst": "of:0000ffffffffff09", |
7 | "dstPort": "10", | 10 | "dstPort": "10", |
8 | - "type": "optical", | ||
9 | - "linkWidth": 2, | ||
10 | "props" : { | 11 | "props" : { |
11 | "BW": "70 G" | 12 | "BW": "70 G" |
12 | } | 13 | } | ... | ... |
... | @@ -3,7 +3,7 @@ | ... | @@ -3,7 +3,7 @@ |
3 | "payload": { | 3 | "payload": { |
4 | "id": "of:0000ffffffffff03", | 4 | "id": "of:0000ffffffffff03", |
5 | "type": "roadm", | 5 | "type": "roadm", |
6 | - "online": false, | 6 | + "online": true, |
7 | "labels": [ | 7 | "labels": [ |
8 | "0000ffffffffff03", | 8 | "0000ffffffffff03", |
9 | "FF:FF:FF:FF:FF:03", | 9 | "FF:FF:FF:FF:FF:03", | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | + "id": "of:0000ffffffffff0A/10-of:0000ffffffffff08/30", | ||
5 | + "type": "optical", | ||
6 | + "linkWidth": 4, | ||
4 | "src": "of:0000ffffffffff0A", | 7 | "src": "of:0000ffffffffff0A", |
5 | "srcPort": "10", | 8 | "srcPort": "10", |
6 | "dst": "of:0000ffffffffff08", | 9 | "dst": "of:0000ffffffffff08", |
7 | "dstPort": "30", | 10 | "dstPort": "30", |
8 | - "type": "optical", | ||
9 | - "linkWidth": 6, | ||
10 | "props" : { | 11 | "props" : { |
11 | "BW": "70 G" | 12 | "BW": "70 G" |
12 | } | 13 | } | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | + "id": "of:0000ffffffff0004/2-of:0000ffffffffff04/1", | ||
5 | + "type": "optical", | ||
6 | + "linkWidth": 2, | ||
4 | "src": "of:0000ffffffff0004", | 7 | "src": "of:0000ffffffff0004", |
5 | "srcPort": "2", | 8 | "srcPort": "2", |
6 | "dst": "of:0000ffffffffff04", | 9 | "dst": "of:0000ffffffffff04", |
7 | "dstPort": "1", | 10 | "dstPort": "1", |
8 | - "type": "optical", | ||
9 | - "linkWidth": 2, | ||
10 | "props" : { | 11 | "props" : { |
11 | "BW": "70 G" | 12 | "BW": "70 G" |
12 | } | 13 | } | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | + "id": "of:0000ffffffffff07/1-of:0000ffffffff0007/2", | ||
5 | + "type": "optical", | ||
6 | + "linkWidth": 2, | ||
4 | "src": "of:0000ffffffffff07", | 7 | "src": "of:0000ffffffffff07", |
5 | "srcPort": "1", | 8 | "srcPort": "1", |
6 | "dst": "of:0000ffffffff0007", | 9 | "dst": "of:0000ffffffff0007", |
7 | "dstPort": "2", | 10 | "dstPort": "2", |
8 | - "type": "optical", | ||
9 | - "linkWidth": 2, | ||
10 | "props" : { | 11 | "props" : { |
11 | "BW": "70 G" | 12 | "BW": "70 G" |
12 | } | 13 | } | ... | ... |
1 | { | 1 | { |
2 | - "event": "addLink", | 2 | + "event": "updateDevice", |
3 | "payload": { | 3 | "payload": { |
4 | - "src": "of:0000ffffffff0003", | 4 | + "id": "of:0000ffffffffff06", |
5 | - "srcPort": "2", | 5 | + "type": "roadm", |
6 | - "dst": "of:0000ffffffffff03", | 6 | + "online": true, |
7 | - "dstPort": "1", | 7 | + "labels": [ |
8 | - "type": "optical", | 8 | + "0000ffffffffff06", |
9 | - "linkWidth": 2, | 9 | + "FF:FF:FF:FF:FF:06", |
10 | - "props" : { | 10 | + "?" |
11 | - "BW": "70 G" | 11 | + ], |
12 | + "metaUi": { | ||
13 | + "x": 336, | ||
14 | + "y": 254 | ||
12 | } | 15 | } |
13 | } | 16 | } |
14 | } | 17 | } | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | + "id": "of:0000ffffffffff06/20-of:0000ffffffffff05/30", | ||
4 | "src": "of:0000ffffffffff06", | 5 | "src": "of:0000ffffffffff06", |
5 | - "srcPort": "30", | 6 | + "srcPort": "20", |
6 | - "dst": "of:0000ffffffffff08", | 7 | + "dst": "of:0000ffffffffff05", |
7 | - "dstPort": "10", | 8 | + "dstPort": "30", |
8 | "type": "optical", | 9 | "type": "optical", |
9 | - "linkWidth": 6, | 10 | + "linkWidth": 4, |
10 | "props" : { | 11 | "props" : { |
11 | "BW": "70 G" | 12 | "BW": "70 G" |
12 | } | 13 | } | ... | ... |
1 | { | 1 | { |
2 | "event": "addLink", | 2 | "event": "addLink", |
3 | "payload": { | 3 | "payload": { |
4 | - "src": "of:0000ffffffffff04", | 4 | + "id": "of:0000ffffffffff03/20-of:0000ffffffffff06/10", |
5 | - "srcPort": "27", | ||
6 | - "dst": "of:0000ffffffffff08", | ||
7 | - "dstPort": "10", | ||
8 | "type": "optical", | 5 | "type": "optical", |
9 | "linkWidth": 2, | 6 | "linkWidth": 2, |
7 | + "src": "of:0000ffffffffff03", | ||
8 | + "srcPort": "20", | ||
9 | + "dst": "of:0000ffffffffff06", | ||
10 | + "dstPort": "10", | ||
10 | "props" : { | 11 | "props" : { |
11 | - "BW": "30 G" | 12 | + "BW": "70 G" |
12 | } | 13 | } |
13 | } | 14 | } |
14 | } | 15 | } | ... | ... |
1 | +{ | ||
2 | + "event": "addLink", | ||
3 | + "payload": { | ||
4 | + "id": "of:0000ffffffffff06/30-of:0000ffffffffff08/10", | ||
5 | + "type": "optical", | ||
6 | + "linkWidth": 4, | ||
7 | + "src": "of:0000ffffffffff06", | ||
8 | + "srcPort": "30", | ||
9 | + "dst": "of:0000ffffffffff08", | ||
10 | + "dstPort": "10", | ||
11 | + "props" : { | ||
12 | + "BW": "70 G" | ||
13 | + } | ||
14 | + } | ||
15 | +} |
1 | +{ | ||
2 | + "event": "removeLink", | ||
3 | + "payload": { | ||
4 | + "id": "of:0000ffffffffff07/30-of:0000ffffffffff08/20", | ||
5 | + "type": "optical", | ||
6 | + "linkWidth": 4, | ||
7 | + "src": "of:0000ffffffffff07", | ||
8 | + "srcPort": "30", | ||
9 | + "dst": "of:0000ffffffffff08", | ||
10 | + "dstPort": "20", | ||
11 | + "props" : { | ||
12 | + "BW": "70 G" | ||
13 | + } | ||
14 | + } | ||
15 | +} |
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