Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
Showing
117 changed files
with
1603 additions
and
351 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 |
... | @@ -55,7 +71,7 @@ public class BandwidthCalendarResource extends BaseResource { | ... | @@ -55,7 +71,7 @@ public class BandwidthCalendarResource extends BaseResource { |
55 | 71 | ||
56 | log.info("Receiving Create Intent request..."); | 72 | log.info("Receiving Create Intent request..."); |
57 | log.info("Path Constraints: Src = {} SrcPort = {} Dest = {} DestPort = {} BW = {}", | 73 | log.info("Path Constraints: Src = {} SrcPort = {} Dest = {} DestPort = {} BW = {}", |
58 | - src, srcPort, dst, dstPort, bandwidth); | 74 | + src, srcPort, dst, dstPort, bandwidth); |
59 | 75 | ||
60 | IntentService service = get(IntentService.class); | 76 | IntentService service = get(IntentService.class); |
61 | 77 | ||
... | @@ -66,36 +82,50 @@ public class BandwidthCalendarResource extends BaseResource { | ... | @@ -66,36 +82,50 @@ public class BandwidthCalendarResource extends BaseResource { |
66 | TrafficTreatment treatment = builder().build(); | 82 | TrafficTreatment treatment = builder().build(); |
67 | 83 | ||
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 | ||
76 | - return Response.ok(reply).build(); | 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"; | ||
98 | + return Response.ok(reply).build(); | ||
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(); | ||
77 | } | 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) { |
86 | - String reply = "ok\n"; | 113 | + service.withdraw(intent); |
87 | - return Response.ok(reply).build(); | 114 | + String reply = "ok\n"; |
115 | + return Response.ok(reply).build(); | ||
116 | + } | ||
117 | + return Response.status(Response.Status.NOT_FOUND).build(); | ||
88 | } | 118 | } |
89 | 119 | ||
90 | @javax.ws.rs.Path("/modification/{intentId}/{bandwidth}") | 120 | @javax.ws.rs.Path("/modification/{intentId}/{bandwidth}") |
91 | @POST | 121 | @POST |
92 | public Response modifyBandwidth(@PathParam("intentId") String intentId, | 122 | public Response modifyBandwidth(@PathParam("intentId") String intentId, |
93 | - @PathParam("bandwidth") String bandwidth) { | 123 | + @PathParam("bandwidth") String bandwidth) { |
94 | 124 | ||
95 | log.info("Receiving Modify request..."); | 125 | log.info("Receiving Modify request..."); |
96 | log.info("Modify bw for intentId = {} with new bandwidth = {}", intentId, bandwidth); | 126 | log.info("Modify bw for intentId = {} with new bandwidth = {}", intentId, bandwidth); |
97 | 127 | ||
98 | - String reply = "ok\n"; | 128 | + String reply = "ok\n"; |
99 | return Response.ok(reply).build(); | 129 | return Response.ok(reply).build(); |
100 | } | 130 | } |
101 | 131 | ||
... | @@ -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,52 +63,9 @@ public class NetworkConfigReader { | ... | @@ -60,52 +63,9 @@ 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 | - ConnectPoint cp = new ConnectPoint( | ||
71 | - DeviceId.deviceId(dpidToUri(entry.getDpid())), | ||
72 | - PortNumber.portNumber(entry.getPortNumber())); | ||
73 | - | ||
74 | - Set<InterfaceIpAddress> interfaceIpAddresses = new HashSet<>(); | ||
75 | - | ||
76 | - for (String strIp : entry.getIpAddresses()) { | ||
77 | - // Get the IP address and the subnet mask length | ||
78 | - try { | ||
79 | - String[] splits = strIp.split("/"); | ||
80 | - if (splits.length != 2) { | ||
81 | - throw new IllegalArgumentException("Invalid IP address and prefix length format"); | ||
82 | - } | ||
83 | - // NOTE: IpPrefix will mask-out the bits after the prefix length. | ||
84 | - IpPrefix subnet = IpPrefix.valueOf(strIp); | ||
85 | - IpAddress addr = IpAddress.valueOf(splits[0]); | ||
86 | - InterfaceIpAddress ia = | ||
87 | - new InterfaceIpAddress(addr, subnet); | ||
88 | - interfaceIpAddresses.add(ia); | ||
89 | - } catch (IllegalArgumentException e) { | ||
90 | - log.warn("Bad format for IP address in config: {}", strIp); | ||
91 | - } | ||
92 | - } | ||
93 | - | ||
94 | - MacAddress macAddress = null; | ||
95 | - if (entry.getMacAddress() != null) { | ||
96 | - try { | ||
97 | - macAddress = MacAddress.valueOf(entry.getMacAddress()); | ||
98 | - } catch (IllegalArgumentException e) { | ||
99 | - log.warn("Bad format for MAC address in config: {}", | ||
100 | - entry.getMacAddress()); | ||
101 | - } | ||
102 | - } | ||
103 | - | ||
104 | - PortAddresses addresses = new PortAddresses(cp, | ||
105 | - interfaceIpAddresses, macAddress); | ||
106 | - | ||
107 | - hostAdminService.bindAddressesToPort(addresses); | ||
108 | - } | ||
109 | } | 69 | } |
110 | } | 70 | } |
111 | 71 | ||
... | @@ -114,12 +74,17 @@ public class NetworkConfigReader { | ... | @@ -114,12 +74,17 @@ public class NetworkConfigReader { |
114 | log.info("Stopped"); | 74 | log.info("Stopped"); |
115 | } | 75 | } |
116 | 76 | ||
77 | + /** | ||
78 | + * Reads the network configuration. | ||
79 | + * | ||
80 | + * @return the network configuration on success, otherwise null | ||
81 | + */ | ||
117 | private AddressConfiguration readNetworkConfig() { | 82 | private AddressConfiguration readNetworkConfig() { |
118 | - File configFile = new File(configFileName); | 83 | + File configFile = new File(CONFIG_DIR, configFileName); |
119 | - | ||
120 | ObjectMapper mapper = new ObjectMapper(); | 84 | ObjectMapper mapper = new ObjectMapper(); |
121 | 85 | ||
122 | try { | 86 | try { |
87 | + log.info("Loading config: {}", configFile.getAbsolutePath()); | ||
123 | AddressConfiguration config = | 88 | AddressConfiguration config = |
124 | mapper.readValue(configFile, AddressConfiguration.class); | 89 | mapper.readValue(configFile, AddressConfiguration.class); |
125 | 90 | ||
... | @@ -127,12 +92,58 @@ public class NetworkConfigReader { | ... | @@ -127,12 +92,58 @@ public class NetworkConfigReader { |
127 | } catch (FileNotFoundException e) { | 92 | } catch (FileNotFoundException e) { |
128 | log.warn("Configuration file not found: {}", configFileName); | 93 | log.warn("Configuration file not found: {}", configFileName); |
129 | } catch (IOException e) { | 94 | } catch (IOException e) { |
130 | - log.error("Unable to read config from file:", e); | 95 | + log.error("Error loading configuration", e); |
131 | } | 96 | } |
132 | 97 | ||
133 | return null; | 98 | return null; |
134 | } | 99 | } |
135 | 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()) { | ||
108 | + ConnectPoint cp = new ConnectPoint( | ||
109 | + DeviceId.deviceId(dpidToUri(entry.getDpid())), | ||
110 | + PortNumber.portNumber(entry.getPortNumber())); | ||
111 | + | ||
112 | + Set<InterfaceIpAddress> interfaceIpAddresses = new HashSet<>(); | ||
113 | + for (String strIp : entry.getIpAddresses()) { | ||
114 | + // Get the IP address and the subnet mask length | ||
115 | + try { | ||
116 | + String[] splits = strIp.split("/"); | ||
117 | + if (splits.length != 2) { | ||
118 | + throw new IllegalArgumentException("Invalid IP address and prefix length format"); | ||
119 | + } | ||
120 | + // NOTE: IpPrefix will mask-out the bits after the prefix length. | ||
121 | + IpPrefix subnet = IpPrefix.valueOf(strIp); | ||
122 | + IpAddress addr = IpAddress.valueOf(splits[0]); | ||
123 | + InterfaceIpAddress ia = | ||
124 | + new InterfaceIpAddress(addr, subnet); | ||
125 | + interfaceIpAddresses.add(ia); | ||
126 | + } catch (IllegalArgumentException e) { | ||
127 | + log.warn("Bad format for IP address in config: {}", strIp); | ||
128 | + } | ||
129 | + } | ||
130 | + | ||
131 | + MacAddress macAddress = null; | ||
132 | + if (entry.getMacAddress() != null) { | ||
133 | + try { | ||
134 | + macAddress = MacAddress.valueOf(entry.getMacAddress()); | ||
135 | + } catch (IllegalArgumentException e) { | ||
136 | + log.warn("Bad format for MAC address in config: {}", | ||
137 | + entry.getMacAddress()); | ||
138 | + } | ||
139 | + } | ||
140 | + | ||
141 | + PortAddresses addresses = new PortAddresses(cp, | ||
142 | + interfaceIpAddresses, macAddress); | ||
143 | + hostAdminService.bindAddressesToPort(addresses); | ||
144 | + } | ||
145 | + } | ||
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(":", ""); |
138 | } | 149 | } | ... | ... |
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); | ... | ... |
This diff is collapsed. Click to expand it.
... | @@ -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
This diff is collapsed. Click to expand it.
... | @@ -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 | -} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
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,16 @@ public class ImmutableClassChecker { | ... | @@ -113,16 +113,16 @@ 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(); | 126 | final Description toDescription = new StringDescription(); |
127 | final Description mismatchDescription = new StringDescription(); | 127 | final Description mismatchDescription = new StringDescription(); |
128 | 128 | ||
... | @@ -136,4 +136,31 @@ public class ImmutableClassChecker { | ... | @@ -136,4 +136,31 @@ public class ImmutableClassChecker { |
136 | throw new AssertionError(reason); | 136 | throw new AssertionError(reason); |
137 | } | 137 | } |
138 | } | 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)) { | ||
153 | + final Description toDescription = new StringDescription(); | ||
154 | + final Description mismatchDescription = new StringDescription(); | ||
155 | + | ||
156 | + checker.describeTo(toDescription); | ||
157 | + checker.describeMismatch(mismatchDescription); | ||
158 | + final String reason = | ||
159 | + "\n" + | ||
160 | + "Expected: is \"" + toDescription.toString() + "\"\n" + | ||
161 | + " but : was \"" + mismatchDescription.toString() + "\""; | ||
162 | + | ||
163 | + throw new AssertionError(reason); | ||
164 | + } | ||
165 | + } | ||
139 | } | 166 | } | ... | ... |
... | @@ -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 | -} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
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