Consolidating null providers and making them fully configurable and integrated w…
…ith the ConfigProvider to allow arbitrary topologies. Change-Id: I899e27a9771af4013a3ce6da7f683a4927ffb438
Showing
40 changed files
with
2445 additions
and
84 deletions
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.cli; | ||
17 | + | ||
18 | +import org.apache.karaf.shell.console.completer.StringsCompleter; | ||
19 | + | ||
20 | +import java.util.List; | ||
21 | +import java.util.SortedSet; | ||
22 | + | ||
23 | +/** | ||
24 | + * Abstraction of a completer with preset choices. | ||
25 | + */ | ||
26 | +public abstract class AbstractChoicesCompleter extends AbstractCompleter { | ||
27 | + | ||
28 | + protected abstract List<String> choices(); | ||
29 | + | ||
30 | + @Override | ||
31 | + public int complete(String buffer, int cursor, List<String> candidates) { | ||
32 | + StringsCompleter delegate = new StringsCompleter(); | ||
33 | + SortedSet<String> strings = delegate.getStrings(); | ||
34 | + choices().forEach(strings::add); | ||
35 | + return delegate.complete(buffer, cursor, candidates); | ||
36 | + } | ||
37 | + | ||
38 | +} |
... | @@ -13,7 +13,7 @@ | ... | @@ -13,7 +13,7 @@ |
13 | * See the License for the specific language governing permissions and | 13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | -package org.onosproject.cli.net; | 16 | +package org.onosproject.cli; |
17 | 17 | ||
18 | import org.apache.felix.service.command.CommandSession; | 18 | import org.apache.felix.service.command.CommandSession; |
19 | import org.apache.karaf.shell.console.CommandSessionHolder; | 19 | import org.apache.karaf.shell.console.CommandSessionHolder; | ... | ... |
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.cli; | ||
17 | + | ||
18 | +import com.google.common.collect.ImmutableList; | ||
19 | + | ||
20 | +import java.util.List; | ||
21 | + | ||
22 | +/** | ||
23 | + * Start/stop command completer. | ||
24 | + */ | ||
25 | +public class StartStopCompleter extends AbstractChoicesCompleter { | ||
26 | + | ||
27 | + public static final String START = "start"; | ||
28 | + public static final String STOP = "stop"; | ||
29 | + | ||
30 | + @Override | ||
31 | + public List<String> choices() { | ||
32 | + return ImmutableList.of(START, STOP); | ||
33 | + } | ||
34 | +} |
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.cli; | ||
17 | + | ||
18 | +import com.google.common.collect.ImmutableList; | ||
19 | + | ||
20 | +import java.util.List; | ||
21 | + | ||
22 | +/** | ||
23 | + * Up/down command completer. | ||
24 | + */ | ||
25 | +public class UpDownCompleter extends AbstractChoicesCompleter { | ||
26 | + | ||
27 | + public static final String UP = "up"; | ||
28 | + public static final String DOWN = "down"; | ||
29 | + | ||
30 | + @Override | ||
31 | + public List<String> choices() { | ||
32 | + return ImmutableList.of(UP, DOWN); | ||
33 | + } | ||
34 | +} |
... | @@ -15,30 +15,20 @@ | ... | @@ -15,30 +15,20 @@ |
15 | */ | 15 | */ |
16 | package org.onosproject.cli.app; | 16 | package org.onosproject.cli.app; |
17 | 17 | ||
18 | -import org.apache.karaf.shell.console.Completer; | 18 | +import com.google.common.collect.ImmutableList; |
19 | -import org.apache.karaf.shell.console.completer.StringsCompleter; | 19 | +import org.onosproject.cli.AbstractChoicesCompleter; |
20 | 20 | ||
21 | import java.util.List; | 21 | import java.util.List; |
22 | -import java.util.SortedSet; | ||
23 | 22 | ||
24 | import static org.onosproject.cli.app.ApplicationCommand.*; | 23 | import static org.onosproject.cli.app.ApplicationCommand.*; |
25 | 24 | ||
26 | /** | 25 | /** |
27 | - * Application name completer. | 26 | + * Application command completer. |
28 | */ | 27 | */ |
29 | -public class ApplicationCommandCompleter implements Completer { | 28 | +public class ApplicationCommandCompleter extends AbstractChoicesCompleter { |
30 | @Override | 29 | @Override |
31 | - public int complete(String buffer, int cursor, List<String> candidates) { | 30 | + public List<String> choices() { |
32 | - // Delegate string completer | 31 | + return ImmutableList.of(INSTALL, UNINSTALL, ACTIVATE, DEACTIVATE); |
33 | - StringsCompleter delegate = new StringsCompleter(); | ||
34 | - SortedSet<String> strings = delegate.getStrings(); | ||
35 | - strings.add(INSTALL); | ||
36 | - strings.add(UNINSTALL); | ||
37 | - strings.add(ACTIVATE); | ||
38 | - strings.add(DEACTIVATE); | ||
39 | - | ||
40 | - // Now let the completer do the work for figuring out what to offer. | ||
41 | - return delegate.complete(buffer, cursor, candidates); | ||
42 | } | 32 | } |
43 | 33 | ||
44 | } | 34 | } | ... | ... |
... | @@ -19,7 +19,7 @@ import org.apache.karaf.shell.console.completer.ArgumentCompleter; | ... | @@ -19,7 +19,7 @@ import org.apache.karaf.shell.console.completer.ArgumentCompleter; |
19 | import org.apache.karaf.shell.console.completer.StringsCompleter; | 19 | import org.apache.karaf.shell.console.completer.StringsCompleter; |
20 | import org.onosproject.app.ApplicationService; | 20 | import org.onosproject.app.ApplicationService; |
21 | import org.onosproject.app.ApplicationState; | 21 | import org.onosproject.app.ApplicationState; |
22 | -import org.onosproject.cli.net.AbstractCompleter; | 22 | +import org.onosproject.cli.AbstractCompleter; |
23 | import org.onosproject.core.Application; | 23 | import org.onosproject.core.Application; |
24 | 24 | ||
25 | import java.util.Iterator; | 25 | import java.util.Iterator; | ... | ... |
... | @@ -19,7 +19,7 @@ import org.apache.karaf.shell.console.completer.ArgumentCompleter; | ... | @@ -19,7 +19,7 @@ import org.apache.karaf.shell.console.completer.ArgumentCompleter; |
19 | import org.apache.karaf.shell.console.completer.StringsCompleter; | 19 | import org.apache.karaf.shell.console.completer.StringsCompleter; |
20 | import org.onosproject.cfg.ComponentConfigService; | 20 | import org.onosproject.cfg.ComponentConfigService; |
21 | import org.onosproject.cfg.ConfigProperty; | 21 | import org.onosproject.cfg.ConfigProperty; |
22 | -import org.onosproject.cli.net.AbstractCompleter; | 22 | +import org.onosproject.cli.AbstractCompleter; |
23 | 23 | ||
24 | import java.util.List; | 24 | import java.util.List; |
25 | import java.util.Set; | 25 | import java.util.Set; | ... | ... |
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.cli.net; | ||
17 | + | ||
18 | +import org.apache.karaf.shell.console.completer.ArgumentCompleter; | ||
19 | +import org.apache.karaf.shell.console.completer.StringsCompleter; | ||
20 | +import org.onosproject.cli.AbstractCompleter; | ||
21 | +import org.onosproject.cli.AbstractShellCommand; | ||
22 | +import org.onosproject.net.ConnectPoint; | ||
23 | +import org.onosproject.net.link.LinkService; | ||
24 | + | ||
25 | +import java.util.List; | ||
26 | +import java.util.SortedSet; | ||
27 | + | ||
28 | +import static org.onosproject.cli.net.AddPointToPointIntentCommand.getDeviceId; | ||
29 | +import static org.onosproject.cli.net.AddPointToPointIntentCommand.getPortNumber; | ||
30 | +import static org.onosproject.net.DeviceId.deviceId; | ||
31 | +import static org.onosproject.net.PortNumber.portNumber; | ||
32 | + | ||
33 | +/** | ||
34 | + * Link end-point completer. | ||
35 | + */ | ||
36 | +public class LinkDstCompleter extends AbstractCompleter { | ||
37 | + @Override | ||
38 | + public int complete(String buffer, int cursor, List<String> candidates) { | ||
39 | + // Delegate string completer | ||
40 | + StringsCompleter delegate = new StringsCompleter(); | ||
41 | + | ||
42 | + // Fetch our service and feed it's offerings to the string completer | ||
43 | + LinkService service = AbstractShellCommand.get(LinkService.class); | ||
44 | + | ||
45 | + // Link source the previous argument. | ||
46 | + ArgumentCompleter.ArgumentList list = getArgumentList(); | ||
47 | + String srcArg = list.getArguments()[list.getCursorArgumentIndex() - 1]; | ||
48 | + | ||
49 | + // Generate the device ID/port number identifiers | ||
50 | + SortedSet<String> strings = delegate.getStrings(); | ||
51 | + try { | ||
52 | + ConnectPoint src = new ConnectPoint(deviceId(getDeviceId(srcArg)), | ||
53 | + portNumber(getPortNumber(srcArg))); | ||
54 | + service.getEgressLinks(src) | ||
55 | + .forEach(link -> strings.add(link.dst().elementId().toString() + | ||
56 | + "/" + link.dst().port())); | ||
57 | + } catch (NumberFormatException e) { | ||
58 | + System.err.println("Invalid connect-point"); | ||
59 | + } | ||
60 | + | ||
61 | + // Now let the completer do the work for figuring out what to offer. | ||
62 | + return delegate.complete(buffer, cursor, candidates); | ||
63 | + } | ||
64 | + | ||
65 | +} |
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.cli.net; | ||
17 | + | ||
18 | +import org.apache.karaf.shell.console.completer.StringsCompleter; | ||
19 | +import org.onosproject.cli.AbstractCompleter; | ||
20 | +import org.onosproject.cli.AbstractShellCommand; | ||
21 | +import org.onosproject.net.link.LinkService; | ||
22 | + | ||
23 | +import java.util.List; | ||
24 | +import java.util.SortedSet; | ||
25 | + | ||
26 | +/** | ||
27 | + * Link end-point completer. | ||
28 | + */ | ||
29 | +public class LinkSrcCompleter extends AbstractCompleter { | ||
30 | + @Override | ||
31 | + public int complete(String buffer, int cursor, List<String> candidates) { | ||
32 | + // Delegate string completer | ||
33 | + StringsCompleter delegate = new StringsCompleter(); | ||
34 | + | ||
35 | + // Fetch our service and feed it's offerings to the string completer | ||
36 | + LinkService service = AbstractShellCommand.get(LinkService.class); | ||
37 | + | ||
38 | + // Generate the device ID/port number identifiers | ||
39 | + SortedSet<String> strings = delegate.getStrings(); | ||
40 | + service.getLinks() | ||
41 | + .forEach(link -> strings.add(link.src().elementId().toString() + | ||
42 | + "/" + link.src().port())); | ||
43 | + | ||
44 | + // Now let the completer do the work for figuring out what to offer. | ||
45 | + return delegate.complete(buffer, cursor, candidates); | ||
46 | + } | ||
47 | + | ||
48 | +} |
... | @@ -332,4 +332,7 @@ | ... | @@ -332,4 +332,7 @@ |
332 | <bean id="ipProtocolCompleter" class="org.onosproject.cli.net.IpProtocolCompleter"/> | 332 | <bean id="ipProtocolCompleter" class="org.onosproject.cli.net.IpProtocolCompleter"/> |
333 | <bean id="driverNameCompleter" class="org.onosproject.cli.net.DriverNameCompleter"/> | 333 | <bean id="driverNameCompleter" class="org.onosproject.cli.net.DriverNameCompleter"/> |
334 | 334 | ||
335 | + <bean id="startStopCompleter" class="org.onosproject.cli.StartStopCompleter"/> | ||
336 | + <bean id="upDownCompleter" class="org.onosproject.cli.UpDownCompleter"/> | ||
337 | + | ||
335 | </blueprint> | 338 | </blueprint> | ... | ... |
... | @@ -20,7 +20,7 @@ import org.onosproject.net.DeviceId; | ... | @@ -20,7 +20,7 @@ import org.onosproject.net.DeviceId; |
20 | /** | 20 | /** |
21 | * Service for administering the inventory of infrastructure devices. | 21 | * Service for administering the inventory of infrastructure devices. |
22 | */ | 22 | */ |
23 | -public interface DeviceAdminService { | 23 | +public interface DeviceAdminService extends DeviceService { |
24 | 24 | ||
25 | /** | 25 | /** |
26 | * Removes the device with the specified identifier. | 26 | * Removes the device with the specified identifier. | ... | ... |
... | @@ -21,7 +21,7 @@ import org.onosproject.net.HostId; | ... | @@ -21,7 +21,7 @@ import org.onosproject.net.HostId; |
21 | /** | 21 | /** |
22 | * Service for administering the inventory of end-station hosts. | 22 | * Service for administering the inventory of end-station hosts. |
23 | */ | 23 | */ |
24 | -public interface HostAdminService { | 24 | +public interface HostAdminService extends HostService { |
25 | 25 | ||
26 | /** | 26 | /** |
27 | * Removes the end-station host with the specified identifier. | 27 | * Removes the end-station host with the specified identifier. | ... | ... |
... | @@ -21,7 +21,7 @@ import org.onosproject.net.DeviceId; | ... | @@ -21,7 +21,7 @@ import org.onosproject.net.DeviceId; |
21 | /** | 21 | /** |
22 | * Service for administering the inventory of infrastructure links. | 22 | * Service for administering the inventory of infrastructure links. |
23 | */ | 23 | */ |
24 | -public interface LinkAdminService { | 24 | +public interface LinkAdminService extends LinkService { |
25 | 25 | ||
26 | /** | 26 | /** |
27 | * Removes all infrastructure links leading to and from the | 27 | * Removes all infrastructure links leading to and from the | ... | ... |
... | @@ -705,7 +705,8 @@ public class DistributedGroupStore | ... | @@ -705,7 +705,8 @@ public class DistributedGroupStore |
705 | remove(new GroupStoreKeyMapKey(deviceId, group.appCookie())); | 705 | remove(new GroupStoreKeyMapKey(deviceId, group.appCookie())); |
706 | } | 706 | } |
707 | } else { | 707 | } else { |
708 | - if (deviceAuditStatus.get(deviceId)) { | 708 | + Boolean audited = deviceAuditStatus.get(deviceId); |
709 | + if (audited != null && audited) { | ||
709 | log.debug("deviceInitialAuditCompleted: Clearing AUDIT " | 710 | log.debug("deviceInitialAuditCompleted: Clearing AUDIT " |
710 | + "status for device {}", deviceId); | 711 | + "status for device {}", deviceId); |
711 | deviceAuditStatus.put(deviceId, false); | 712 | deviceAuditStatus.put(deviceId, false); |
... | @@ -717,8 +718,8 @@ public class DistributedGroupStore | ... | @@ -717,8 +718,8 @@ public class DistributedGroupStore |
717 | @Override | 718 | @Override |
718 | public boolean deviceInitialAuditStatus(DeviceId deviceId) { | 719 | public boolean deviceInitialAuditStatus(DeviceId deviceId) { |
719 | synchronized (deviceAuditStatus) { | 720 | synchronized (deviceAuditStatus) { |
720 | - return (deviceAuditStatus.get(deviceId) != null) | 721 | + Boolean audited = deviceAuditStatus.get(deviceId); |
721 | - ? deviceAuditStatus.get(deviceId) : false; | 722 | + return audited != null && audited; |
722 | } | 723 | } |
723 | } | 724 | } |
724 | 725 | ... | ... |
... | @@ -79,7 +79,7 @@ | ... | @@ -79,7 +79,7 @@ |
79 | <group> | 79 | <group> |
80 | <title>Null Providers</title> | 80 | <title>Null Providers</title> |
81 | <packages> | 81 | <packages> |
82 | - org.onosproject.provider.nil.* | 82 | + org.onosproject.provider.nil:org.onosproject.provider.nil.* |
83 | </packages> | 83 | </packages> |
84 | </group> | 84 | </group> |
85 | <group> | 85 | <group> | ... | ... |
... | @@ -131,13 +131,7 @@ | ... | @@ -131,13 +131,7 @@ |
131 | <feature name="onos-null" version="@FEATURE-VERSION" | 131 | <feature name="onos-null" version="@FEATURE-VERSION" |
132 | description="ONOS Null providers"> | 132 | description="ONOS Null providers"> |
133 | <feature>onos-api</feature> | 133 | <feature>onos-api</feature> |
134 | - | 134 | + <bundle>mvn:org.onosproject/onos-null-provider/@ONOS-VERSION</bundle> |
135 | - <bundle>mvn:org.onosproject/onos-null-provider-device/@ONOS-VERSION</bundle> | ||
136 | - <bundle>mvn:org.onosproject/onos-null-provider-link/@ONOS-VERSION</bundle> | ||
137 | - <bundle>mvn:org.onosproject/onos-null-provider-host/@ONOS-VERSION</bundle> | ||
138 | - <bundle>mvn:org.onosproject/onos-null-provider-packet/@ONOS-VERSION</bundle> | ||
139 | - <bundle>mvn:org.onosproject/onos-null-provider-flow/@ONOS-VERSION</bundle> | ||
140 | - | ||
141 | </feature> | 135 | </feature> |
142 | 136 | ||
143 | <feature name="onos-openflow" version="@FEATURE-VERSION" | 137 | <feature name="onos-openflow" version="@FEATURE-VERSION" | ... | ... |
... | @@ -26,20 +26,25 @@ | ... | @@ -26,20 +26,25 @@ |
26 | <relativePath>../pom.xml</relativePath> | 26 | <relativePath>../pom.xml</relativePath> |
27 | </parent> | 27 | </parent> |
28 | 28 | ||
29 | - <artifactId>onos-null-providers</artifactId> | 29 | + <artifactId>onos-null-provider</artifactId> |
30 | - <packaging>pom</packaging> | 30 | + <packaging>bundle</packaging> |
31 | 31 | ||
32 | <description>ONOS null protocol adapters</description> | 32 | <description>ONOS null protocol adapters</description> |
33 | 33 | ||
34 | - <modules> | ||
35 | - <module>device</module> | ||
36 | - <module>link</module> | ||
37 | - <module>host</module> | ||
38 | - <module>packet</module> | ||
39 | - <module>flow</module> | ||
40 | - </modules> | ||
41 | - | ||
42 | <dependencies> | 34 | <dependencies> |
35 | + <dependency> | ||
36 | + <groupId>org.osgi</groupId> | ||
37 | + <artifactId>org.osgi.compendium</artifactId> | ||
38 | + </dependency> | ||
39 | + <dependency> | ||
40 | + <groupId>org.apache.karaf.shell</groupId> | ||
41 | + <artifactId>org.apache.karaf.shell.console</artifactId> | ||
42 | + </dependency> | ||
43 | + <dependency> | ||
44 | + <groupId>org.onosproject</groupId> | ||
45 | + <artifactId>onos-cli</artifactId> | ||
46 | + <version>${project.version}</version> | ||
47 | + </dependency> | ||
43 | 48 | ||
44 | <dependency> | 49 | <dependency> |
45 | <groupId>org.onosproject</groupId> | 50 | <groupId>org.onosproject</groupId> | ... | ... |
providers/null/src/main/java/org/onosproject/provider/nil/CentipedeTopologySimulator.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.provider.nil; | ||
17 | + | ||
18 | +/** | ||
19 | + * Linear topology with hosts on every device. | ||
20 | + */ | ||
21 | +public class CentipedeTopologySimulator extends LinearTopologySimulator { | ||
22 | + | ||
23 | + /** | ||
24 | + * Creates simulated hosts. | ||
25 | + */ | ||
26 | + protected void createHosts() { | ||
27 | + deviceIds.forEach(id -> createHosts(id, infrastructurePorts)); | ||
28 | + } | ||
29 | + | ||
30 | +} |
providers/null/src/main/java/org/onosproject/provider/nil/ConfiguredTopologySimulator.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.provider.nil; | ||
17 | + | ||
18 | +/** | ||
19 | + * Topology simulator which operates on topology configured via the REST API | ||
20 | + * config service. | ||
21 | + */ | ||
22 | +public class ConfiguredTopologySimulator extends TopologySimulator { | ||
23 | + | ||
24 | + @Override | ||
25 | + protected void createDevices() { | ||
26 | + deviceService.getDevices() | ||
27 | + .forEach(device -> deviceProviderService | ||
28 | + .deviceConnected(device.id(), description(device))); | ||
29 | + } | ||
30 | + | ||
31 | + @Override | ||
32 | + protected void createLinks() { | ||
33 | + linkService.getLinks() | ||
34 | + .forEach(link -> linkProviderService | ||
35 | + .linkDetected(description(link))); | ||
36 | + } | ||
37 | + | ||
38 | + @Override | ||
39 | + protected void createHosts() { | ||
40 | + hostService.getHosts() | ||
41 | + .forEach(host -> hostProviderService | ||
42 | + .hostDetected(host.id(), description(host))); | ||
43 | + } | ||
44 | +} |
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.provider.nil; | ||
17 | + | ||
18 | +import static com.google.common.base.Preconditions.checkArgument; | ||
19 | + | ||
20 | +/** | ||
21 | + * Linear topology simulator. | ||
22 | + */ | ||
23 | +public class LinearTopologySimulator extends TopologySimulator { | ||
24 | + | ||
25 | + @Override | ||
26 | + protected void processTopoShape(String shape) { | ||
27 | + super.processTopoShape(shape); | ||
28 | + deviceCount = (topoShape.length == 1) ? deviceCount : Integer.parseInt(topoShape[1]); | ||
29 | + } | ||
30 | + | ||
31 | + @Override | ||
32 | + public void setUpTopology() { | ||
33 | + checkArgument(deviceCount > 1, "There must be at least 2 devices"); | ||
34 | + | ||
35 | + prepareForDeviceEvents(deviceCount); | ||
36 | + createDevices(); | ||
37 | + waitForDeviceEvents(); | ||
38 | + | ||
39 | + createLinks(); | ||
40 | + createHosts(); | ||
41 | + } | ||
42 | + | ||
43 | + @Override | ||
44 | + protected void createLinks() { | ||
45 | + for (int i = 0, n = deviceCount - 1; i < n; i++) { | ||
46 | + createLink(i, i + 1); | ||
47 | + } | ||
48 | + } | ||
49 | + | ||
50 | + @Override | ||
51 | + protected void createHosts() { | ||
52 | + createHosts(deviceIds.get(0), infrastructurePorts); | ||
53 | + createHosts(deviceIds.get(deviceCount - 1), infrastructurePorts); | ||
54 | + } | ||
55 | + | ||
56 | +} |
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.provider.nil; | ||
17 | + | ||
18 | +/** | ||
19 | + * Full mesh topology with hosts at each device. | ||
20 | + */ | ||
21 | +public class MeshTopologySimulator extends TopologySimulator { | ||
22 | + | ||
23 | + @Override | ||
24 | + protected void processTopoShape(String shape) { | ||
25 | + super.processTopoShape(shape); | ||
26 | + // FIXME: implement this | ||
27 | + } | ||
28 | + | ||
29 | + @Override | ||
30 | + public void setUpTopology() { | ||
31 | + // FIXME: implement this | ||
32 | + // checkArgument(FIXME, "There must be at least ..."); | ||
33 | + super.setUpTopology(); | ||
34 | + } | ||
35 | + | ||
36 | + @Override | ||
37 | + protected void createLinks() { | ||
38 | + } | ||
39 | + | ||
40 | + @Override | ||
41 | + protected void createHosts() { | ||
42 | + } | ||
43 | + | ||
44 | +} |
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.provider.nil; | ||
17 | + | ||
18 | +import com.google.common.collect.Sets; | ||
19 | +import org.jboss.netty.util.HashedWheelTimer; | ||
20 | +import org.jboss.netty.util.Timeout; | ||
21 | +import org.jboss.netty.util.TimerTask; | ||
22 | +import org.onlab.util.Timer; | ||
23 | +import org.onosproject.core.ApplicationId; | ||
24 | +import org.onosproject.net.DeviceId; | ||
25 | +import org.onosproject.net.flow.CompletedBatchOperation; | ||
26 | +import org.onosproject.net.flow.DefaultFlowEntry; | ||
27 | +import org.onosproject.net.flow.FlowEntry; | ||
28 | +import org.onosproject.net.flow.FlowRule; | ||
29 | +import org.onosproject.net.flow.FlowRuleBatchEntry; | ||
30 | +import org.onosproject.net.flow.FlowRuleBatchOperation; | ||
31 | +import org.onosproject.net.flow.FlowRuleProvider; | ||
32 | +import org.onosproject.net.flow.FlowRuleProviderService; | ||
33 | +import org.slf4j.Logger; | ||
34 | + | ||
35 | +import java.util.Collections; | ||
36 | +import java.util.Set; | ||
37 | +import java.util.concurrent.ConcurrentHashMap; | ||
38 | +import java.util.concurrent.ConcurrentMap; | ||
39 | +import java.util.concurrent.TimeUnit; | ||
40 | + | ||
41 | +import static org.slf4j.LoggerFactory.getLogger; | ||
42 | + | ||
43 | +/** | ||
44 | + * Null provider to accept any flow and report them. | ||
45 | + */ | ||
46 | +class NullFlowRuleProvider extends NullProviders.AbstractNullProvider | ||
47 | + implements FlowRuleProvider { | ||
48 | + | ||
49 | + private final Logger log = getLogger(getClass()); | ||
50 | + | ||
51 | + private ConcurrentMap<DeviceId, Set<FlowEntry>> flowTable = new ConcurrentHashMap<>(); | ||
52 | + | ||
53 | + private FlowRuleProviderService providerService; | ||
54 | + | ||
55 | + private HashedWheelTimer timer = Timer.getTimer(); | ||
56 | + private Timeout timeout; | ||
57 | + | ||
58 | + /** | ||
59 | + * Starts the flow rule provider simulation. | ||
60 | + * | ||
61 | + * @param providerService flow rule provider service | ||
62 | + */ | ||
63 | + void start(FlowRuleProviderService providerService) { | ||
64 | + this.providerService = providerService; | ||
65 | + timeout = timer.newTimeout(new StatisticTask(), 5, TimeUnit.SECONDS); | ||
66 | + } | ||
67 | + | ||
68 | + /** | ||
69 | + * Stops the flow rule provider simulation. | ||
70 | + */ | ||
71 | + void stop() { | ||
72 | + timeout.cancel(); | ||
73 | + } | ||
74 | + | ||
75 | + @Override | ||
76 | + public void applyFlowRule(FlowRule... flowRules) { | ||
77 | + // FIXME: invoke executeBatch | ||
78 | + } | ||
79 | + | ||
80 | + @Override | ||
81 | + public void removeFlowRule(FlowRule... flowRules) { | ||
82 | + // FIXME: invoke executeBatch | ||
83 | + } | ||
84 | + | ||
85 | + @Override | ||
86 | + public void removeRulesById(ApplicationId id, FlowRule... flowRules) { | ||
87 | + throw new UnsupportedOperationException("Cannot remove by appId from null provider"); | ||
88 | + } | ||
89 | + | ||
90 | + @Override | ||
91 | + public void executeBatch(FlowRuleBatchOperation batch) { | ||
92 | + // TODO: consider checking mastership | ||
93 | + Set<FlowEntry> entries = | ||
94 | + flowTable.getOrDefault(batch.deviceId(), | ||
95 | + Sets.newConcurrentHashSet()); | ||
96 | + for (FlowRuleBatchEntry fbe : batch.getOperations()) { | ||
97 | + switch (fbe.operator()) { | ||
98 | + case ADD: | ||
99 | + entries.add(new DefaultFlowEntry(fbe.target())); | ||
100 | + break; | ||
101 | + case REMOVE: | ||
102 | + entries.remove(new DefaultFlowEntry(fbe.target())); | ||
103 | + break; | ||
104 | + case MODIFY: | ||
105 | + FlowEntry entry = new DefaultFlowEntry(fbe.target()); | ||
106 | + entries.remove(entry); | ||
107 | + entries.add(entry); | ||
108 | + break; | ||
109 | + default: | ||
110 | + log.error("Unknown flow operation: {}", fbe); | ||
111 | + } | ||
112 | + } | ||
113 | + flowTable.put(batch.deviceId(), entries); | ||
114 | + CompletedBatchOperation op = | ||
115 | + new CompletedBatchOperation(true, Collections.emptySet(), | ||
116 | + batch.deviceId()); | ||
117 | + providerService.batchOperationCompleted(batch.id(), op); | ||
118 | + } | ||
119 | + | ||
120 | + // Periodically reports flow rule statistics. | ||
121 | + private class StatisticTask implements TimerTask { | ||
122 | + @Override | ||
123 | + public void run(Timeout to) throws Exception { | ||
124 | + for (DeviceId devId : flowTable.keySet()) { | ||
125 | + Set<FlowEntry> entries = | ||
126 | + flowTable.getOrDefault(devId, Collections.emptySet()); | ||
127 | + providerService.pushFlowMetrics(devId, entries); | ||
128 | + } | ||
129 | + timeout = timer.newTimeout(to.getTask(), 5, TimeUnit.SECONDS); | ||
130 | + } | ||
131 | + } | ||
132 | +} |
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.provider.nil; | ||
17 | + | ||
18 | +import org.jboss.netty.util.HashedWheelTimer; | ||
19 | +import org.jboss.netty.util.Timeout; | ||
20 | +import org.jboss.netty.util.TimerTask; | ||
21 | +import org.onlab.packet.Ethernet; | ||
22 | +import org.onlab.packet.ICMP; | ||
23 | +import org.onlab.util.Timer; | ||
24 | +import org.onosproject.net.ConnectPoint; | ||
25 | +import org.onosproject.net.Device; | ||
26 | +import org.onosproject.net.PortNumber; | ||
27 | +import org.onosproject.net.device.DeviceAdminService; | ||
28 | +import org.onosproject.net.host.HostService; | ||
29 | +import org.onosproject.net.packet.DefaultInboundPacket; | ||
30 | +import org.onosproject.net.packet.DefaultPacketContext; | ||
31 | +import org.onosproject.net.packet.InboundPacket; | ||
32 | +import org.onosproject.net.packet.OutboundPacket; | ||
33 | +import org.onosproject.net.packet.PacketProvider; | ||
34 | +import org.onosproject.net.packet.PacketProviderService; | ||
35 | +import org.slf4j.Logger; | ||
36 | + | ||
37 | +import java.nio.ByteBuffer; | ||
38 | +import java.util.List; | ||
39 | +import java.util.concurrent.TimeUnit; | ||
40 | +import java.util.stream.Collectors; | ||
41 | + | ||
42 | +import static com.google.common.collect.ImmutableList.copyOf; | ||
43 | +import static java.util.concurrent.TimeUnit.SECONDS; | ||
44 | +import static org.onosproject.net.MastershipRole.MASTER; | ||
45 | +import static org.slf4j.LoggerFactory.getLogger; | ||
46 | + | ||
47 | +/** | ||
48 | + * Provider which generates simulated packets and acts as a sink for outbound | ||
49 | + * packets. To be used for benchmarking only. | ||
50 | + */ | ||
51 | +class NullPacketProvider extends NullProviders.AbstractNullProvider | ||
52 | + implements PacketProvider { | ||
53 | + | ||
54 | + private static final int INITIAL_DELAY = 5; | ||
55 | + private final Logger log = getLogger(getClass()); | ||
56 | + | ||
57 | + // Arbitrary host src/dst | ||
58 | + private static final int SRC_HOST = 2; | ||
59 | + private static final int DST_HOST = 5; | ||
60 | + | ||
61 | + // Time between event firing, in milliseconds | ||
62 | + private int delay; | ||
63 | + | ||
64 | + // TODO: use host service to pick legitimate hosts connected to devices | ||
65 | + private HostService hostService; | ||
66 | + private PacketProviderService providerService; | ||
67 | + | ||
68 | + private List<Device> devices; | ||
69 | + private int currentDevice = 0; | ||
70 | + | ||
71 | + private HashedWheelTimer timer = Timer.getTimer(); | ||
72 | + private Timeout timeout; | ||
73 | + | ||
74 | + /** | ||
75 | + * Starts the packet generation process. | ||
76 | + * | ||
77 | + * @param packetRate packets per second | ||
78 | + * @param hostService host service | ||
79 | + * @param deviceService device service | ||
80 | + * @param providerService packet provider service | ||
81 | + */ | ||
82 | + void start(int packetRate, HostService hostService, | ||
83 | + DeviceAdminService deviceService, | ||
84 | + PacketProviderService providerService) { | ||
85 | + this.hostService = hostService; | ||
86 | + this.providerService = providerService; | ||
87 | + | ||
88 | + this.devices = copyOf(deviceService.getDevices()).stream() | ||
89 | + .filter(d -> deviceService.getRole(d.id()) == MASTER) | ||
90 | + .collect(Collectors.toList()); | ||
91 | + | ||
92 | + adjustRate(packetRate); | ||
93 | + timeout = timer.newTimeout(new PacketDriverTask(), INITIAL_DELAY, SECONDS); | ||
94 | + } | ||
95 | + | ||
96 | + /** | ||
97 | + * Adjusts packet rate. | ||
98 | + * | ||
99 | + * @param packetRate new packet rate | ||
100 | + */ | ||
101 | + void adjustRate(int packetRate) { | ||
102 | + delay = 1000 / packetRate; | ||
103 | + log.info("Settings: packetRate={}, delay={}", packetRate, delay); | ||
104 | + } | ||
105 | + | ||
106 | + /** | ||
107 | + * Stops the packet generation process. | ||
108 | + */ | ||
109 | + void stop() { | ||
110 | + if (timeout != null) { | ||
111 | + timeout.cancel(); | ||
112 | + } | ||
113 | + } | ||
114 | + | ||
115 | + @Override | ||
116 | + public void emit(OutboundPacket packet) { | ||
117 | + // We don't have a network to emit to. Keep a counter here, maybe? | ||
118 | + } | ||
119 | + | ||
120 | + /** | ||
121 | + * Generates packet events at a given rate. | ||
122 | + */ | ||
123 | + private class PacketDriverTask implements TimerTask { | ||
124 | + | ||
125 | + // Filler echo request | ||
126 | + ICMP icmp; | ||
127 | + Ethernet eth; | ||
128 | + | ||
129 | + public PacketDriverTask() { | ||
130 | + icmp = new ICMP(); | ||
131 | + icmp.setIcmpType((byte) 8).setIcmpCode((byte) 0).setChecksum((short) 0); | ||
132 | + eth = new Ethernet(); | ||
133 | + eth.setEtherType(Ethernet.TYPE_IPV4); | ||
134 | + eth.setPayload(icmp); | ||
135 | + } | ||
136 | + | ||
137 | + @Override | ||
138 | + public void run(Timeout to) { | ||
139 | + if (!devices.isEmpty()) { | ||
140 | + sendEvent(devices.get(currentDevice)); | ||
141 | + currentDevice = (currentDevice + 1) % devices.size(); | ||
142 | + timeout = timer.newTimeout(to.getTask(), delay, TimeUnit.MILLISECONDS); | ||
143 | + } | ||
144 | + } | ||
145 | + | ||
146 | + private void sendEvent(Device device) { | ||
147 | + // Make it look like things came from ports attached to hosts | ||
148 | + eth.setSourceMACAddress("00:00:10:00:00:0" + SRC_HOST) | ||
149 | + .setDestinationMACAddress("00:00:10:00:00:0" + DST_HOST); | ||
150 | + InboundPacket inPkt = new DefaultInboundPacket( | ||
151 | + new ConnectPoint(device.id(), PortNumber.portNumber(SRC_HOST)), | ||
152 | + eth, ByteBuffer.wrap(eth.serialize())); | ||
153 | + providerService.processPacket(new NullPacketContext(inPkt, null)); | ||
154 | + } | ||
155 | + } | ||
156 | + | ||
157 | + // Minimal PacketContext to make core and applications happy. | ||
158 | + private final class NullPacketContext extends DefaultPacketContext { | ||
159 | + private NullPacketContext(InboundPacket inPkt, OutboundPacket outPkt) { | ||
160 | + super(System.currentTimeMillis(), inPkt, outPkt, false); | ||
161 | + } | ||
162 | + | ||
163 | + @Override | ||
164 | + public void send() { | ||
165 | + // We don't send anything out. | ||
166 | + } | ||
167 | + } | ||
168 | + | ||
169 | +} |
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.provider.nil; | ||
17 | + | ||
18 | +import org.apache.felix.scr.annotations.Activate; | ||
19 | +import org.apache.felix.scr.annotations.Component; | ||
20 | +import org.apache.felix.scr.annotations.Deactivate; | ||
21 | +import org.apache.felix.scr.annotations.Modified; | ||
22 | +import org.apache.felix.scr.annotations.Property; | ||
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.osgi.DefaultServiceDirectory; | ||
27 | +import org.onosproject.cfg.ComponentConfigService; | ||
28 | +import org.onosproject.cluster.ClusterService; | ||
29 | +import org.onosproject.cluster.NodeId; | ||
30 | +import org.onosproject.mastership.MastershipAdminService; | ||
31 | +import org.onosproject.net.ConnectPoint; | ||
32 | +import org.onosproject.net.DeviceId; | ||
33 | +import org.onosproject.net.Host; | ||
34 | +import org.onosproject.net.MastershipRole; | ||
35 | +import org.onosproject.net.device.DeviceAdminService; | ||
36 | +import org.onosproject.net.device.DeviceProvider; | ||
37 | +import org.onosproject.net.device.DeviceProviderRegistry; | ||
38 | +import org.onosproject.net.device.DeviceProviderService; | ||
39 | +import org.onosproject.net.flow.FlowRuleProviderRegistry; | ||
40 | +import org.onosproject.net.flow.FlowRuleProviderService; | ||
41 | +import org.onosproject.net.host.HostProvider; | ||
42 | +import org.onosproject.net.host.HostProviderRegistry; | ||
43 | +import org.onosproject.net.host.HostProviderService; | ||
44 | +import org.onosproject.net.host.HostService; | ||
45 | +import org.onosproject.net.link.LinkProvider; | ||
46 | +import org.onosproject.net.link.LinkProviderRegistry; | ||
47 | +import org.onosproject.net.link.LinkProviderService; | ||
48 | +import org.onosproject.net.link.LinkService; | ||
49 | +import org.onosproject.net.packet.PacketProviderRegistry; | ||
50 | +import org.onosproject.net.packet.PacketProviderService; | ||
51 | +import org.onosproject.net.provider.AbstractProvider; | ||
52 | +import org.onosproject.net.provider.ProviderId; | ||
53 | +import org.osgi.service.component.ComponentContext; | ||
54 | +import org.slf4j.Logger; | ||
55 | + | ||
56 | +import java.util.Dictionary; | ||
57 | +import java.util.Properties; | ||
58 | + | ||
59 | +import static com.google.common.base.Strings.isNullOrEmpty; | ||
60 | +import static org.onlab.util.Tools.delay; | ||
61 | +import static org.onlab.util.Tools.get; | ||
62 | +import static org.onosproject.net.DeviceId.deviceId; | ||
63 | +import static org.onosproject.net.MastershipRole.MASTER; | ||
64 | +import static org.onosproject.net.MastershipRole.NONE; | ||
65 | +import static org.slf4j.LoggerFactory.getLogger; | ||
66 | + | ||
67 | +/** | ||
68 | + * Provider of a fake network environment, i.e. devices, links, hosts, etc. | ||
69 | + * To be used for benchmarking only. | ||
70 | + */ | ||
71 | +@Component(immediate = true) | ||
72 | +@Service(value = NullProviders.class) | ||
73 | +public class NullProviders { | ||
74 | + | ||
75 | + private static final Logger log = getLogger(NullProviders.class); | ||
76 | + | ||
77 | + static final String SCHEME = "null"; | ||
78 | + static final String PROVIDER_ID = "org.onosproject.provider.nil"; | ||
79 | + | ||
80 | + private static final String FORMAT = | ||
81 | + "Settings: enabled={}, topoShape={}, deviceCount={}, " + | ||
82 | + "hostCount={}, packetRate={}, mutationRate={}"; | ||
83 | + | ||
84 | + | ||
85 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
86 | + protected ClusterService clusterService; | ||
87 | + | ||
88 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
89 | + protected MastershipAdminService mastershipService; | ||
90 | + | ||
91 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
92 | + protected ComponentConfigService cfgService; | ||
93 | + | ||
94 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
95 | + protected DeviceAdminService deviceService; | ||
96 | + | ||
97 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
98 | + protected HostService hostService; | ||
99 | + | ||
100 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
101 | + protected LinkService linkService; | ||
102 | + | ||
103 | + | ||
104 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
105 | + protected DeviceProviderRegistry deviceProviderRegistry; | ||
106 | + | ||
107 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
108 | + protected HostProviderRegistry hostProviderRegistry; | ||
109 | + | ||
110 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
111 | + protected LinkProviderRegistry linkProviderRegistry; | ||
112 | + | ||
113 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
114 | + protected FlowRuleProviderRegistry flowRuleProviderRegistry; | ||
115 | + | ||
116 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
117 | + protected PacketProviderRegistry packetProviderRegistry; | ||
118 | + | ||
119 | + | ||
120 | + private final NullDeviceProvider deviceProvider = new NullDeviceProvider(); | ||
121 | + private final NullLinkProvider linkProvider = new NullLinkProvider(); | ||
122 | + private final NullHostProvider hostProvider = new NullHostProvider(); | ||
123 | + private final NullFlowRuleProvider flowRuleProvider = new NullFlowRuleProvider(); | ||
124 | + private final NullPacketProvider packetProvider = new NullPacketProvider(); | ||
125 | + private final TopologyMutationDriver topologyMutationDriver = new TopologyMutationDriver(); | ||
126 | + | ||
127 | + private DeviceProviderService deviceProviderService; | ||
128 | + private HostProviderService hostProviderService; | ||
129 | + private LinkProviderService linkProviderService; | ||
130 | + private FlowRuleProviderService flowRuleProviderService; | ||
131 | + private PacketProviderService packetProviderService; | ||
132 | + | ||
133 | + private TopologySimulator simulator; | ||
134 | + | ||
135 | + @Property(name = "enabled", boolValue = false, | ||
136 | + label = "Enables or disables the provider") | ||
137 | + private boolean enabled = false; | ||
138 | + | ||
139 | + private static final String DEFAULT_TOPO_SHAPE = "configured"; | ||
140 | + @Property(name = "topoShape", value = DEFAULT_TOPO_SHAPE, | ||
141 | + label = "Topology shape: configured, linear, reroute, tree, spineleaf, mesh") | ||
142 | + private String topoShape = DEFAULT_TOPO_SHAPE; | ||
143 | + | ||
144 | + private static final int DEFAULT_DEVICE_COUNT = 10; | ||
145 | + @Property(name = "deviceCount", intValue = DEFAULT_DEVICE_COUNT, | ||
146 | + label = "Number of devices to generate") | ||
147 | + private int deviceCount = DEFAULT_DEVICE_COUNT; | ||
148 | + | ||
149 | + private static final int DEFAULT_HOST_COUNT = 5; | ||
150 | + @Property(name = "hostCount", intValue = DEFAULT_HOST_COUNT, | ||
151 | + label = "Number of host to generate per device") | ||
152 | + private int hostCount = DEFAULT_HOST_COUNT; | ||
153 | + | ||
154 | + private static final int DEFAULT_PACKET_RATE = 5; | ||
155 | + @Property(name = "packetRate", intValue = DEFAULT_PACKET_RATE, | ||
156 | + label = "Packet-in/s rate; 0 for no packets") | ||
157 | + private int packetRate = DEFAULT_PACKET_RATE; | ||
158 | + | ||
159 | + private static final double DEFAULT_MUTATION_RATE = 0; | ||
160 | + @Property(name = "mutationRate", doubleValue = DEFAULT_MUTATION_RATE, | ||
161 | + label = "Link event/s topology mutation rate; 0 for no mutations") | ||
162 | + private double mutationRate = DEFAULT_MUTATION_RATE; | ||
163 | + | ||
164 | + private static final String DEFAULT_MASTERSHIP = "random"; | ||
165 | + @Property(name = "mastership", value = DEFAULT_MASTERSHIP, | ||
166 | + label = "Mastership given as 'random' or 'node1=dpid,dpid/node2=dpid,...'") | ||
167 | + private String mastership = DEFAULT_MASTERSHIP; | ||
168 | + | ||
169 | + | ||
170 | + @Activate | ||
171 | + public void activate(ComponentContext context) { | ||
172 | + cfgService.registerProperties(getClass()); | ||
173 | + | ||
174 | + deviceProviderService = deviceProviderRegistry.register(deviceProvider); | ||
175 | + hostProviderService = hostProviderRegistry.register(hostProvider); | ||
176 | + linkProviderService = linkProviderRegistry.register(linkProvider); | ||
177 | + flowRuleProviderService = flowRuleProviderRegistry.register(flowRuleProvider); | ||
178 | + packetProviderService = packetProviderRegistry.register(packetProvider); | ||
179 | + log.info("Started"); | ||
180 | + } | ||
181 | + | ||
182 | + @Deactivate | ||
183 | + public void deactivate(ComponentContext context) { | ||
184 | + cfgService.unregisterProperties(getClass(), false); | ||
185 | + tearDown(); | ||
186 | + | ||
187 | + deviceProviderRegistry.unregister(deviceProvider); | ||
188 | + hostProviderRegistry.unregister(hostProvider); | ||
189 | + linkProviderRegistry.unregister(linkProvider); | ||
190 | + flowRuleProviderRegistry.unregister(flowRuleProvider); | ||
191 | + packetProviderRegistry.unregister(packetProvider); | ||
192 | + | ||
193 | + deviceProviderService = null; | ||
194 | + hostProviderService = null; | ||
195 | + linkProviderService = null; | ||
196 | + flowRuleProviderService = null; | ||
197 | + packetProviderService = null; | ||
198 | + | ||
199 | + log.info("Stopped"); | ||
200 | + } | ||
201 | + | ||
202 | + @Modified | ||
203 | + public void modified(ComponentContext context) { | ||
204 | + Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties(); | ||
205 | + | ||
206 | + boolean newEnabled; | ||
207 | + int newDeviceCount, newHostCount, newPacketRate; | ||
208 | + double newMutationRate; | ||
209 | + String newTopoShape, newMastership; | ||
210 | + try { | ||
211 | + String s = get(properties, "enabled"); | ||
212 | + newEnabled = isNullOrEmpty(s) ? enabled : Boolean.parseBoolean(s.trim()); | ||
213 | + | ||
214 | + newTopoShape = get(properties, "topoShape"); | ||
215 | + newMastership = get(properties, "mastership"); | ||
216 | + | ||
217 | + s = get(properties, "deviceCount"); | ||
218 | + newDeviceCount = isNullOrEmpty(s) ? deviceCount : Integer.parseInt(s.trim()); | ||
219 | + | ||
220 | + s = get(properties, "hostCount"); | ||
221 | + newHostCount = isNullOrEmpty(s) ? hostCount : Integer.parseInt(s.trim()); | ||
222 | + | ||
223 | + s = get(properties, "packetRate"); | ||
224 | + newPacketRate = isNullOrEmpty(s) ? packetRate : Integer.parseInt(s.trim()); | ||
225 | + | ||
226 | + s = get(properties, "mutationRate"); | ||
227 | + newMutationRate = isNullOrEmpty(s) ? mutationRate : Double.parseDouble(s.trim()); | ||
228 | + | ||
229 | + } catch (NumberFormatException e) { | ||
230 | + log.warn(e.getMessage()); | ||
231 | + newEnabled = enabled; | ||
232 | + newTopoShape = topoShape; | ||
233 | + newDeviceCount = deviceCount; | ||
234 | + newHostCount = hostCount; | ||
235 | + newPacketRate = packetRate; | ||
236 | + newMutationRate = mutationRate; | ||
237 | + newMastership = mastership; | ||
238 | + } | ||
239 | + | ||
240 | + // Any change in the following parameters implies hard restart | ||
241 | + if (newEnabled != enabled || !newTopoShape.equals(topoShape) || | ||
242 | + newDeviceCount != deviceCount || newHostCount != hostCount) { | ||
243 | + enabled = newEnabled; | ||
244 | + topoShape = newTopoShape; | ||
245 | + deviceCount = newDeviceCount; | ||
246 | + hostCount = newHostCount; | ||
247 | + packetRate = newPacketRate; | ||
248 | + mutationRate = newMutationRate; | ||
249 | + restartSimulation(); | ||
250 | + } | ||
251 | + | ||
252 | + // Any change in the following parameters implies just a rate change | ||
253 | + if (newPacketRate != packetRate || newMutationRate != mutationRate) { | ||
254 | + packetRate = newPacketRate; | ||
255 | + mutationRate = newMutationRate; | ||
256 | + adjustRates(); | ||
257 | + } | ||
258 | + | ||
259 | + // Any change in mastership implies just reassignments. | ||
260 | + if (!newMastership.equals(mastership)) { | ||
261 | + mastership = newMastership; | ||
262 | + reassignMastership(); | ||
263 | + } | ||
264 | + | ||
265 | + log.info(FORMAT, enabled, topoShape, deviceCount, hostCount, | ||
266 | + packetRate, mutationRate); | ||
267 | + } | ||
268 | + | ||
269 | + /** | ||
270 | + * Severs the link between the specified end-points in both directions. | ||
271 | + * | ||
272 | + * @param one link endpoint | ||
273 | + * @param two link endpoint | ||
274 | + */ | ||
275 | + public void severLink(ConnectPoint one, ConnectPoint two) { | ||
276 | + if (enabled) { | ||
277 | + topologyMutationDriver.severLink(one, two); | ||
278 | + } | ||
279 | + } | ||
280 | + | ||
281 | + /** | ||
282 | + * Severs the link between the specified end-points in both directions. | ||
283 | + * | ||
284 | + * @param one link endpoint | ||
285 | + * @param two link endpoint | ||
286 | + */ | ||
287 | + public void repairLink(ConnectPoint one, ConnectPoint two) { | ||
288 | + if (enabled) { | ||
289 | + topologyMutationDriver.repairLink(one, two); | ||
290 | + } | ||
291 | + } | ||
292 | + | ||
293 | + // Resets simulation based on the current configuration parameters. | ||
294 | + private void restartSimulation() { | ||
295 | + tearDown(); | ||
296 | + if (enabled) { | ||
297 | + setUp(); | ||
298 | + } | ||
299 | + } | ||
300 | + | ||
301 | + // Sets up the topology simulation and all providers. | ||
302 | + private void setUp() { | ||
303 | + simulator = selectSimulator(topoShape); | ||
304 | + simulator.init(topoShape, deviceCount, hostCount, | ||
305 | + new DefaultServiceDirectory(), | ||
306 | + deviceProviderService, hostProviderService, | ||
307 | + linkProviderService); | ||
308 | + simulator.setUpTopology(); | ||
309 | + flowRuleProvider.start(flowRuleProviderService); | ||
310 | + packetProvider.start(packetRate, hostService, deviceService, | ||
311 | + packetProviderService); | ||
312 | + topologyMutationDriver.start(mutationRate, linkService, deviceService, | ||
313 | + linkProviderService); | ||
314 | + } | ||
315 | + | ||
316 | + // Selects the simulator based on the specified name. | ||
317 | + private TopologySimulator selectSimulator(String topoShape) { | ||
318 | + if (topoShape.matches("linear([,].*|$)")) { | ||
319 | + return new LinearTopologySimulator(); | ||
320 | + } else if (topoShape.matches("centipede([,].*|$)")) { | ||
321 | + return new CentipedeTopologySimulator(); | ||
322 | + } else if (topoShape.matches("reroute([,].*|$)")) { | ||
323 | + return new RerouteTopologySimulator(); | ||
324 | + } else if (topoShape.matches("tree([,].*|$)")) { | ||
325 | + return new TreeTopologySimulator(); | ||
326 | + } else if (topoShape.matches("spineleaf([,].*|$)")) { | ||
327 | + return new SpineLeafTopologySimulator(); | ||
328 | + } else if (topoShape.matches("mesh([,].*|$)")) { | ||
329 | + return new MeshTopologySimulator(); | ||
330 | + } else { | ||
331 | + return new ConfiguredTopologySimulator(); | ||
332 | + } | ||
333 | + } | ||
334 | + | ||
335 | + // Shuts down the topology simulator and all providers. | ||
336 | + private void tearDown() { | ||
337 | + if (simulator != null) { | ||
338 | + topologyMutationDriver.stop(); | ||
339 | + packetProvider.stop(); | ||
340 | + flowRuleProvider.stop(); | ||
341 | + delay(500); | ||
342 | + rejectMastership(); | ||
343 | + simulator.tearDownTopology(); | ||
344 | + simulator = null; | ||
345 | + } | ||
346 | + } | ||
347 | + | ||
348 | + // Changes packet and mutation rates. | ||
349 | + private void adjustRates() { | ||
350 | + packetProvider.adjustRate(packetRate); | ||
351 | + topologyMutationDriver.adjustRate(mutationRate); | ||
352 | + } | ||
353 | + | ||
354 | + // Re-assigns mastership roles. | ||
355 | + private void reassignMastership() { | ||
356 | + if (mastership.equals(DEFAULT_MASTERSHIP)) { | ||
357 | + mastershipService.balanceRoles(); | ||
358 | + } else { | ||
359 | + NodeId localNode = clusterService.getLocalNode().id(); | ||
360 | + rejectMastership(); | ||
361 | + String[] nodeSpecs = mastership.split("/"); | ||
362 | + for (int i = 0; i < nodeSpecs.length; i++) { | ||
363 | + String[] specs = nodeSpecs[i].split("="); | ||
364 | + if (specs[0].equals(localNode.toString())) { | ||
365 | + String[] ids = specs[1].split(","); | ||
366 | + for (String id : ids) { | ||
367 | + mastershipService.setRole(localNode, deviceId(id), MASTER); | ||
368 | + } | ||
369 | + break; | ||
370 | + } | ||
371 | + } | ||
372 | + } | ||
373 | + } | ||
374 | + | ||
375 | + // Rejects mastership of all devices. | ||
376 | + private void rejectMastership() { | ||
377 | + NodeId localNode = clusterService.getLocalNode().id(); | ||
378 | + deviceService.getDevices() | ||
379 | + .forEach(device -> mastershipService.setRole(localNode, device.id(), | ||
380 | + NONE)); | ||
381 | + } | ||
382 | + | ||
383 | + // Null provider base class. | ||
384 | + abstract static class AbstractNullProvider extends AbstractProvider { | ||
385 | + protected AbstractNullProvider() { | ||
386 | + super(new ProviderId(SCHEME, PROVIDER_ID)); | ||
387 | + } | ||
388 | + } | ||
389 | + | ||
390 | + // Device provider facade. | ||
391 | + private class NullDeviceProvider extends AbstractNullProvider implements DeviceProvider { | ||
392 | + @Override | ||
393 | + public void roleChanged(DeviceId deviceId, MastershipRole newRole) { | ||
394 | + deviceProviderService.receivedRoleReply(deviceId, newRole, newRole); | ||
395 | + } | ||
396 | + | ||
397 | + @Override | ||
398 | + public boolean isReachable(DeviceId deviceId) { | ||
399 | + return topoShape.equals("configured") || deviceService.isAvailable(deviceId); | ||
400 | + } | ||
401 | + | ||
402 | + @Override | ||
403 | + public void triggerProbe(DeviceId deviceId) { | ||
404 | + } | ||
405 | + } | ||
406 | + | ||
407 | + // Host provider facade. | ||
408 | + private class NullHostProvider extends AbstractNullProvider implements HostProvider { | ||
409 | + @Override | ||
410 | + public void triggerProbe(Host host) { | ||
411 | + } | ||
412 | + } | ||
413 | + | ||
414 | + // Host provider facade. | ||
415 | + private class NullLinkProvider extends AbstractNullProvider implements LinkProvider { | ||
416 | + } | ||
417 | + | ||
418 | +} |
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.provider.nil; | ||
17 | + | ||
18 | +import static com.google.common.base.Preconditions.checkArgument; | ||
19 | + | ||
20 | +/** | ||
21 | + * Re-routable linear topology simulator with an alternate path in the middle. | ||
22 | + */ | ||
23 | +public class RerouteTopologySimulator extends LinearTopologySimulator { | ||
24 | + | ||
25 | + @Override | ||
26 | + protected void processTopoShape(String shape) { | ||
27 | + super.processTopoShape(shape); | ||
28 | + infrastructurePorts = 3; | ||
29 | + deviceCount = (topoShape.length == 1) ? deviceCount : Integer.parseInt(topoShape[1]); | ||
30 | + } | ||
31 | + | ||
32 | + @Override | ||
33 | + public void setUpTopology() { | ||
34 | + checkArgument(deviceCount > 2, "There must be at least 3 devices"); | ||
35 | + super.setUpTopology(); | ||
36 | + } | ||
37 | + | ||
38 | + @Override | ||
39 | + protected void createLinks() { | ||
40 | + for (int i = 0, n = deviceCount - 2; i < n; i++) { | ||
41 | + createLink(i, i + 1); | ||
42 | + } | ||
43 | + int middle = (deviceCount - 1) / 2; | ||
44 | + int alternate = deviceCount - 1; | ||
45 | + createLink(middle - 1, alternate); | ||
46 | + createLink(middle, alternate); | ||
47 | + } | ||
48 | + | ||
49 | + @Override | ||
50 | + protected void createHosts() { | ||
51 | + createHosts(deviceIds.get(0), infrastructurePorts); | ||
52 | + createHosts(deviceIds.get(deviceCount - 2), infrastructurePorts); | ||
53 | + } | ||
54 | + | ||
55 | +} |
providers/null/src/main/java/org/onosproject/provider/nil/SpineLeafTopologySimulator.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.provider.nil; | ||
17 | + | ||
18 | +/** | ||
19 | + * Spine-leaf topology with hosts at the leaf devices. | ||
20 | + */ | ||
21 | +public class SpineLeafTopologySimulator extends TopologySimulator { | ||
22 | + | ||
23 | + @Override | ||
24 | + protected void processTopoShape(String shape) { | ||
25 | + super.processTopoShape(shape); | ||
26 | + // FIXME: implement this | ||
27 | + } | ||
28 | + | ||
29 | + @Override | ||
30 | + public void setUpTopology() { | ||
31 | + // checkArgument(FIXME, "There must be at least one spine tier"); | ||
32 | + super.setUpTopology(); | ||
33 | + } | ||
34 | + | ||
35 | + @Override | ||
36 | + protected void createLinks() { | ||
37 | + } | ||
38 | + | ||
39 | + @Override | ||
40 | + protected void createHosts() { | ||
41 | + } | ||
42 | + | ||
43 | +} |
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.provider.nil; | ||
17 | + | ||
18 | +import com.google.common.collect.Lists; | ||
19 | +import org.onosproject.net.ConnectPoint; | ||
20 | +import org.onosproject.net.device.DeviceService; | ||
21 | +import org.onosproject.net.link.DefaultLinkDescription; | ||
22 | +import org.onosproject.net.link.LinkDescription; | ||
23 | +import org.onosproject.net.link.LinkProviderService; | ||
24 | +import org.onosproject.net.link.LinkService; | ||
25 | +import org.slf4j.Logger; | ||
26 | +import org.slf4j.LoggerFactory; | ||
27 | + | ||
28 | +import java.util.List; | ||
29 | +import java.util.Random; | ||
30 | +import java.util.concurrent.ExecutorService; | ||
31 | +import java.util.stream.Collectors; | ||
32 | + | ||
33 | +import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; | ||
34 | +import static org.onlab.util.Tools.delay; | ||
35 | +import static org.onlab.util.Tools.groupedThreads; | ||
36 | +import static org.onosproject.net.Link.Type.DIRECT; | ||
37 | +import static org.onosproject.net.MastershipRole.MASTER; | ||
38 | +import static org.onosproject.provider.nil.TopologySimulator.description; | ||
39 | + | ||
40 | +/** | ||
41 | + * Drives topology mutations at a specified rate of events per second. | ||
42 | + */ | ||
43 | +class TopologyMutationDriver implements Runnable { | ||
44 | + | ||
45 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
46 | + | ||
47 | + private static final int WAIT_DELAY = 2_000; | ||
48 | + private static final int MAX_DOWN_LINKS = 5; | ||
49 | + | ||
50 | + private final Random random = new Random(); | ||
51 | + | ||
52 | + private volatile boolean stopped = true; | ||
53 | + | ||
54 | + private double mutationRate; | ||
55 | + private int millis, nanos; | ||
56 | + | ||
57 | + private LinkService linkService; | ||
58 | + private DeviceService deviceService; | ||
59 | + private LinkProviderService linkProviderService; | ||
60 | + | ||
61 | + private List<LinkDescription> activeLinks; | ||
62 | + private List<LinkDescription> inactiveLinks; | ||
63 | + | ||
64 | + private final ExecutorService executor = | ||
65 | + newSingleThreadScheduledExecutor(groupedThreads("onos/null", "topo-mutator")); | ||
66 | + | ||
67 | + /** | ||
68 | + * Starts the mutation process. | ||
69 | + * | ||
70 | + * @param mutationRate link events per second | ||
71 | + * @param linkService link service | ||
72 | + * @param deviceService device service | ||
73 | + * @param linkProviderService link provider service | ||
74 | + */ | ||
75 | + void start(double mutationRate, | ||
76 | + LinkService linkService, DeviceService deviceService, | ||
77 | + LinkProviderService linkProviderService) { | ||
78 | + stopped = false; | ||
79 | + this.linkService = linkService; | ||
80 | + this.deviceService = deviceService; | ||
81 | + this.linkProviderService = linkProviderService; | ||
82 | + activeLinks = reduceLinks(); | ||
83 | + inactiveLinks = Lists.newArrayList(); | ||
84 | + adjustRate(mutationRate); | ||
85 | + executor.submit(this); | ||
86 | + } | ||
87 | + | ||
88 | + /** | ||
89 | + * Adjusts the topology mutation rate. | ||
90 | + * | ||
91 | + * @param mutationRate new topology mutation rate | ||
92 | + */ | ||
93 | + void adjustRate(double mutationRate) { | ||
94 | + this.mutationRate = mutationRate; | ||
95 | + if (mutationRate > 0) { | ||
96 | + this.millis = (int) (1_000 / mutationRate / 2); | ||
97 | + this.nanos = (int) (1_000_000 / mutationRate / 2) % 1_000_000; | ||
98 | + } else { | ||
99 | + this.millis = 0; | ||
100 | + this.nanos = 0; | ||
101 | + } | ||
102 | + log.info("Settings: millis={}, nanos={}", millis, nanos); | ||
103 | + } | ||
104 | + | ||
105 | + /** | ||
106 | + * Stops the mutation process. | ||
107 | + */ | ||
108 | + void stop() { | ||
109 | + stopped = true; | ||
110 | + } | ||
111 | + | ||
112 | + /** | ||
113 | + * Severs the link between the specified end-points in both directions. | ||
114 | + * | ||
115 | + * @param one link endpoint | ||
116 | + * @param two link endpoint | ||
117 | + */ | ||
118 | + void severLink(ConnectPoint one, ConnectPoint two) { | ||
119 | + LinkDescription link = new DefaultLinkDescription(one, two, DIRECT); | ||
120 | + linkProviderService.linkVanished(link); | ||
121 | + linkProviderService.linkVanished(reverse(link)); | ||
122 | + | ||
123 | + } | ||
124 | + | ||
125 | + /** | ||
126 | + * Repairs the link between the specified end-points in both directions. | ||
127 | + * | ||
128 | + * @param one link endpoint | ||
129 | + * @param two link endpoint | ||
130 | + */ | ||
131 | + void repairLink(ConnectPoint one, ConnectPoint two) { | ||
132 | + LinkDescription link = new DefaultLinkDescription(one, two, DIRECT); | ||
133 | + linkProviderService.linkDetected(link); | ||
134 | + linkProviderService.linkDetected(reverse(link)); | ||
135 | + } | ||
136 | + | ||
137 | + @Override | ||
138 | + public void run() { | ||
139 | + delay(WAIT_DELAY); | ||
140 | + | ||
141 | + while (!stopped) { | ||
142 | + if (mutationRate > 0 && inactiveLinks.isEmpty()) { | ||
143 | + primeInactiveLinks(); | ||
144 | + } else if (mutationRate <= 0 && !inactiveLinks.isEmpty()) { | ||
145 | + repairInactiveLinks(); | ||
146 | + } else if (inactiveLinks.isEmpty()) { | ||
147 | + delay(WAIT_DELAY); | ||
148 | + | ||
149 | + } else { | ||
150 | + activeLinks.add(repairLink()); | ||
151 | + pause(); | ||
152 | + inactiveLinks.add(severLink()); | ||
153 | + pause(); | ||
154 | + } | ||
155 | + } | ||
156 | + } | ||
157 | + | ||
158 | + // Primes the inactive links with a few random links. | ||
159 | + private void primeInactiveLinks() { | ||
160 | + for (int i = 0, n = Math.min(MAX_DOWN_LINKS, activeLinks.size()); i < n; i++) { | ||
161 | + inactiveLinks.add(severLink()); | ||
162 | + } | ||
163 | + } | ||
164 | + | ||
165 | + // Repairs all inactive links. | ||
166 | + private void repairInactiveLinks() { | ||
167 | + while (!inactiveLinks.isEmpty()) { | ||
168 | + repairLink(); | ||
169 | + } | ||
170 | + } | ||
171 | + | ||
172 | + // Picks a random active link and severs it. | ||
173 | + private LinkDescription severLink() { | ||
174 | + LinkDescription link = getRandomLink(activeLinks); | ||
175 | + linkProviderService.linkVanished(link); | ||
176 | + linkProviderService.linkVanished(reverse(link)); | ||
177 | + return link; | ||
178 | + } | ||
179 | + | ||
180 | + // Picks a random inactive link and repairs it. | ||
181 | + private LinkDescription repairLink() { | ||
182 | + LinkDescription link = getRandomLink(inactiveLinks); | ||
183 | + linkProviderService.linkDetected(link); | ||
184 | + linkProviderService.linkDetected(reverse(link)); | ||
185 | + return link; | ||
186 | + } | ||
187 | + | ||
188 | + // Produces a reverse of the specified link. | ||
189 | + private LinkDescription reverse(LinkDescription link) { | ||
190 | + return new DefaultLinkDescription(link.dst(), link.src(), link.type()); | ||
191 | + } | ||
192 | + | ||
193 | + // Returns a random link from the specified list of links. | ||
194 | + private LinkDescription getRandomLink(List<LinkDescription> links) { | ||
195 | + return links.remove(random.nextInt(links.size())); | ||
196 | + } | ||
197 | + | ||
198 | + // Reduces the given list of links to just a single link in each original pair. | ||
199 | + private List<LinkDescription> reduceLinks() { | ||
200 | + List<LinkDescription> links = Lists.newArrayList(); | ||
201 | + linkService.getLinks().forEach(link -> links.add(description(link))); | ||
202 | + return links.stream() | ||
203 | + .filter(this::isOurLink) | ||
204 | + .filter(this::isRightDirection) | ||
205 | + .collect(Collectors.toList()); | ||
206 | + } | ||
207 | + | ||
208 | + // Returns true if the specified link is ours. | ||
209 | + private boolean isOurLink(LinkDescription linkDescription) { | ||
210 | + return deviceService.getRole(linkDescription.src().deviceId()) == MASTER; | ||
211 | + } | ||
212 | + | ||
213 | + // Returns true if the link source is greater than the link destination. | ||
214 | + private boolean isRightDirection(LinkDescription link) { | ||
215 | + return link.src().deviceId().toString().compareTo(link.dst().deviceId().toString()) > 0; | ||
216 | + } | ||
217 | + | ||
218 | + // Pauses the current thread for the pre-computed time of millis & nanos. | ||
219 | + private void pause() { | ||
220 | + delay(millis, nanos); | ||
221 | + } | ||
222 | + | ||
223 | +} |
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.provider.nil; | ||
17 | + | ||
18 | +import com.google.common.collect.Lists; | ||
19 | +import org.onlab.osgi.ServiceDirectory; | ||
20 | +import org.onlab.packet.ChassisId; | ||
21 | +import org.onlab.packet.IpAddress; | ||
22 | +import org.onlab.packet.MacAddress; | ||
23 | +import org.onlab.packet.VlanId; | ||
24 | +import org.onosproject.cluster.ClusterService; | ||
25 | +import org.onosproject.cluster.NodeId; | ||
26 | +import org.onosproject.mastership.MastershipService; | ||
27 | +import org.onosproject.net.ConnectPoint; | ||
28 | +import org.onosproject.net.Device; | ||
29 | +import org.onosproject.net.DeviceId; | ||
30 | +import org.onosproject.net.Host; | ||
31 | +import org.onosproject.net.HostId; | ||
32 | +import org.onosproject.net.HostLocation; | ||
33 | +import org.onosproject.net.Link; | ||
34 | +import org.onosproject.net.Port; | ||
35 | +import org.onosproject.net.PortNumber; | ||
36 | +import org.onosproject.net.device.DefaultDeviceDescription; | ||
37 | +import org.onosproject.net.device.DefaultPortDescription; | ||
38 | +import org.onosproject.net.device.DeviceAdminService; | ||
39 | +import org.onosproject.net.device.DeviceDescription; | ||
40 | +import org.onosproject.net.device.DeviceEvent; | ||
41 | +import org.onosproject.net.device.DeviceListener; | ||
42 | +import org.onosproject.net.device.DeviceProviderService; | ||
43 | +import org.onosproject.net.device.PortDescription; | ||
44 | +import org.onosproject.net.host.DefaultHostDescription; | ||
45 | +import org.onosproject.net.host.HostDescription; | ||
46 | +import org.onosproject.net.host.HostProviderService; | ||
47 | +import org.onosproject.net.host.HostService; | ||
48 | +import org.onosproject.net.link.DefaultLinkDescription; | ||
49 | +import org.onosproject.net.link.LinkProviderService; | ||
50 | +import org.onosproject.net.link.LinkService; | ||
51 | +import org.slf4j.Logger; | ||
52 | +import org.slf4j.LoggerFactory; | ||
53 | + | ||
54 | +import java.util.List; | ||
55 | +import java.util.concurrent.CountDownLatch; | ||
56 | +import java.util.concurrent.TimeUnit; | ||
57 | + | ||
58 | +import static org.onlab.util.Tools.toHex; | ||
59 | +import static org.onosproject.net.HostId.hostId; | ||
60 | +import static org.onosproject.net.Link.Type.DIRECT; | ||
61 | +import static org.onosproject.net.PortNumber.portNumber; | ||
62 | +import static org.onosproject.net.device.DeviceEvent.Type.*; | ||
63 | +import static org.onosproject.provider.nil.NullProviders.SCHEME; | ||
64 | + | ||
65 | +/** | ||
66 | + * Abstraction of a provider capable to simulate some network topology. | ||
67 | + */ | ||
68 | +public abstract class TopologySimulator { | ||
69 | + | ||
70 | + protected final Logger log = LoggerFactory.getLogger(getClass()); | ||
71 | + | ||
72 | + protected String[] topoShape; | ||
73 | + protected int deviceCount; | ||
74 | + protected int hostCount; | ||
75 | + | ||
76 | + protected ServiceDirectory directory; | ||
77 | + protected NodeId localNode; | ||
78 | + | ||
79 | + protected ClusterService clusterService; | ||
80 | + protected MastershipService mastershipService; | ||
81 | + | ||
82 | + protected DeviceAdminService deviceService; | ||
83 | + protected HostService hostService; | ||
84 | + protected LinkService linkService; | ||
85 | + | ||
86 | + protected DeviceProviderService deviceProviderService; | ||
87 | + protected HostProviderService hostProviderService; | ||
88 | + protected LinkProviderService linkProviderService; | ||
89 | + | ||
90 | + protected int maxWaitSeconds = 1; | ||
91 | + protected int infrastructurePorts = 2; | ||
92 | + protected CountDownLatch deviceLatch; | ||
93 | + | ||
94 | + protected final List<DeviceId> deviceIds = Lists.newArrayList(); | ||
95 | + | ||
96 | + private DeviceListener deviceEventCounter = new DeviceEventCounter(); | ||
97 | + | ||
98 | + /** | ||
99 | + * Initializes a new topology simulator with access to the specified service | ||
100 | + * directory and various provider services. | ||
101 | + * | ||
102 | + * @param topoShape topology shape specifier | ||
103 | + * @param deviceCount number of devices in the topology | ||
104 | + * @param hostCount number of hosts per device | ||
105 | + * @param directory service directory | ||
106 | + * @param deviceProviderService device provider service | ||
107 | + * @param hostProviderService host provider service | ||
108 | + * @param linkProviderService link provider service | ||
109 | + */ | ||
110 | + protected void init(String topoShape, int deviceCount, int hostCount, | ||
111 | + ServiceDirectory directory, | ||
112 | + DeviceProviderService deviceProviderService, | ||
113 | + HostProviderService hostProviderService, | ||
114 | + LinkProviderService linkProviderService) { | ||
115 | + this.deviceCount = deviceCount; | ||
116 | + this.hostCount = hostCount; | ||
117 | + this.directory = directory; | ||
118 | + | ||
119 | + this.clusterService = directory.get(ClusterService.class); | ||
120 | + this.mastershipService = directory.get(MastershipService.class); | ||
121 | + | ||
122 | + this.deviceService = directory.get(DeviceAdminService.class); | ||
123 | + this.hostService = directory.get(HostService.class); | ||
124 | + this.linkService = directory.get(LinkService.class); | ||
125 | + this.deviceProviderService = deviceProviderService; | ||
126 | + this.hostProviderService = hostProviderService; | ||
127 | + this.linkProviderService = linkProviderService; | ||
128 | + | ||
129 | + localNode = clusterService.getLocalNode().id(); | ||
130 | + | ||
131 | + processTopoShape(topoShape); | ||
132 | + } | ||
133 | + | ||
134 | + /** | ||
135 | + * Processes the topology shape specifier. | ||
136 | + * | ||
137 | + * @param shape topology shape specifier | ||
138 | + */ | ||
139 | + protected void processTopoShape(String shape) { | ||
140 | + this.topoShape = shape.split(","); | ||
141 | + } | ||
142 | + | ||
143 | + /** | ||
144 | + * Sets up network topology simulation. | ||
145 | + */ | ||
146 | + public void setUpTopology() { | ||
147 | + prepareForDeviceEvents(deviceCount); | ||
148 | + createDevices(); | ||
149 | + waitForDeviceEvents(); | ||
150 | + | ||
151 | + createLinks(); | ||
152 | + createHosts(); | ||
153 | + } | ||
154 | + | ||
155 | + /** | ||
156 | + * Creates simulated devices. | ||
157 | + */ | ||
158 | + protected void createDevices() { | ||
159 | + for (int i = 0; i < deviceCount; i++) { | ||
160 | + createDevice(i + 1); | ||
161 | + } | ||
162 | + } | ||
163 | + | ||
164 | + /** | ||
165 | + * Creates simulated links. | ||
166 | + */ | ||
167 | + protected abstract void createLinks(); | ||
168 | + | ||
169 | + /** | ||
170 | + * Creates simulated hosts. | ||
171 | + */ | ||
172 | + protected abstract void createHosts(); | ||
173 | + | ||
174 | + /** | ||
175 | + * Creates simulated device. | ||
176 | + * | ||
177 | + * @param i index of the device id in the list. | ||
178 | + */ | ||
179 | + protected void createDevice(int i) { | ||
180 | + DeviceId id = DeviceId.deviceId(SCHEME + ":" + toHex(i)); | ||
181 | + DeviceDescription desc = | ||
182 | + new DefaultDeviceDescription(id.uri(), Device.Type.SWITCH, | ||
183 | + "ON.Lab", "0.1", "0.1", "1234", | ||
184 | + new ChassisId(i)); | ||
185 | + deviceProviderService.deviceConnected(id, desc); | ||
186 | + deviceProviderService.updatePorts(id, buildPorts(hostCount + infrastructurePorts)); | ||
187 | + deviceIds.add(id); | ||
188 | + } | ||
189 | + | ||
190 | + /** | ||
191 | + * Creates simulated link between two devices. | ||
192 | + * | ||
193 | + * @param i index of one simulated device | ||
194 | + * @param j index of another simulated device | ||
195 | + */ | ||
196 | + protected void createLink(int i, int j) { | ||
197 | + ConnectPoint one = new ConnectPoint(deviceIds.get(i), PortNumber.portNumber(1)); | ||
198 | + ConnectPoint two = new ConnectPoint(deviceIds.get(j), PortNumber.portNumber(2)); | ||
199 | + linkProviderService.linkDetected(new DefaultLinkDescription(one, two, DIRECT)); | ||
200 | + linkProviderService.linkDetected(new DefaultLinkDescription(two, one, DIRECT)); | ||
201 | + } | ||
202 | + | ||
203 | + /** | ||
204 | + * Creates simularted hosts for the specified device. | ||
205 | + * | ||
206 | + * @param deviceId device identifier | ||
207 | + * @param portOffset port offset where to start attaching hosts | ||
208 | + */ | ||
209 | + protected void createHosts(DeviceId deviceId, int portOffset) { | ||
210 | + String s = deviceId.toString(); | ||
211 | + byte dByte = Byte.parseByte(s.substring(s.length() - 1), 16); | ||
212 | + // TODO: this limits the simulation to 256 devices & 256 hosts/device. | ||
213 | + byte[] macBytes = new byte[]{0, 0, 0, 0, dByte, 0}; | ||
214 | + byte[] ipBytes = new byte[]{(byte) 192, (byte) 168, dByte, 0}; | ||
215 | + | ||
216 | + for (int i = 0; i < hostCount; i++) { | ||
217 | + int port = portOffset + i + 1; | ||
218 | + macBytes[5] = (byte) (i + 1); | ||
219 | + ipBytes[3] = (byte) (i + 1); | ||
220 | + HostId id = hostId(MacAddress.valueOf(macBytes), VlanId.NONE); | ||
221 | + IpAddress ip = IpAddress.valueOf(IpAddress.Version.INET, ipBytes); | ||
222 | + hostProviderService.hostDetected(id, description(id, ip, deviceId, port)); | ||
223 | + } | ||
224 | + } | ||
225 | + | ||
226 | + /** | ||
227 | + * Prepares to count device added/available/removed events. | ||
228 | + * | ||
229 | + * @param count number of events to count | ||
230 | + */ | ||
231 | + protected void prepareForDeviceEvents(int count) { | ||
232 | + deviceLatch = new CountDownLatch(count); | ||
233 | + deviceService.addListener(deviceEventCounter); | ||
234 | + } | ||
235 | + | ||
236 | + /** | ||
237 | + * Waits for all expected device added/available/removed events. | ||
238 | + */ | ||
239 | + protected void waitForDeviceEvents() { | ||
240 | + try { | ||
241 | + deviceLatch.await(maxWaitSeconds, TimeUnit.SECONDS); | ||
242 | + } catch (InterruptedException e) { | ||
243 | + log.warn("Device events did not arrive in time"); | ||
244 | + } | ||
245 | + deviceService.removeListener(deviceEventCounter); | ||
246 | + } | ||
247 | + | ||
248 | + | ||
249 | + /** | ||
250 | + * Tears down network topology simulation. | ||
251 | + */ | ||
252 | + public void tearDownTopology() { | ||
253 | + removeHosts(); | ||
254 | + removeLinks(); | ||
255 | + removeDevices(); | ||
256 | + } | ||
257 | + | ||
258 | + /** | ||
259 | + * Removes any hosts previously advertised by this provider. | ||
260 | + */ | ||
261 | + protected void removeHosts() { | ||
262 | + hostService.getHosts() | ||
263 | + .forEach(host -> hostProviderService.hostVanished(host.id())); | ||
264 | + } | ||
265 | + | ||
266 | + /** | ||
267 | + * Removes any links previously advertised by this provider. | ||
268 | + */ | ||
269 | + protected void removeLinks() { | ||
270 | + linkService.getLinks() | ||
271 | + .forEach(link -> linkProviderService.linkVanished(description(link))); | ||
272 | + } | ||
273 | + | ||
274 | + /** | ||
275 | + * Removes any devices previously advertised by this provider. | ||
276 | + */ | ||
277 | + protected void removeDevices() { | ||
278 | + prepareForDeviceEvents(deviceService.getDeviceCount()); | ||
279 | + deviceService.getDevices() | ||
280 | + .forEach(device -> deviceService.removeDevice(device.id())); | ||
281 | + waitForDeviceEvents(); | ||
282 | + } | ||
283 | + | ||
284 | + | ||
285 | + /** | ||
286 | + * Produces a device description from the given device. | ||
287 | + * | ||
288 | + * @param device device to copy | ||
289 | + * @return device description | ||
290 | + */ | ||
291 | + static DeviceDescription description(Device device) { | ||
292 | + return new DefaultDeviceDescription(device.id().uri(), device.type(), | ||
293 | + device.manufacturer(), | ||
294 | + device.hwVersion(), device.swVersion(), | ||
295 | + device.serialNumber(), device.chassisId()); | ||
296 | + } | ||
297 | + | ||
298 | + /** | ||
299 | + * Produces a link description from the given link. | ||
300 | + * | ||
301 | + * @param link link to copy | ||
302 | + * @return link description | ||
303 | + */ | ||
304 | + static DefaultLinkDescription description(Link link) { | ||
305 | + return new DefaultLinkDescription(link.src(), link.dst(), link.type()); | ||
306 | + } | ||
307 | + | ||
308 | + /** | ||
309 | + * Produces a host description from the given host. | ||
310 | + * | ||
311 | + * @param host host to copy | ||
312 | + * @return host description | ||
313 | + */ | ||
314 | + static DefaultHostDescription description(Host host) { | ||
315 | + return new DefaultHostDescription(host.mac(), host.vlan(), host.location(), | ||
316 | + host.ipAddresses()); | ||
317 | + } | ||
318 | + | ||
319 | + /** | ||
320 | + * Generates a host description from the given id and location information. | ||
321 | + * | ||
322 | + * @param hostId host identifier | ||
323 | + * @param ip host IP | ||
324 | + * @param deviceId edge device | ||
325 | + * @param port edge port | ||
326 | + * @return host description | ||
327 | + */ | ||
328 | + static HostDescription description(HostId hostId, IpAddress ip, | ||
329 | + DeviceId deviceId, int port) { | ||
330 | + HostLocation location = new HostLocation(deviceId, portNumber(port), 0L); | ||
331 | + return new DefaultHostDescription(hostId.mac(), hostId.vlanId(), location, ip); | ||
332 | + } | ||
333 | + | ||
334 | + /** | ||
335 | + * Generates a list of a configured number of ports. | ||
336 | + * | ||
337 | + * @param portCount number of ports | ||
338 | + * @return list of ports | ||
339 | + */ | ||
340 | + protected List<PortDescription> buildPorts(int portCount) { | ||
341 | + List<PortDescription> ports = Lists.newArrayList(); | ||
342 | + for (int i = 0; i < portCount; i++) { | ||
343 | + ports.add(new DefaultPortDescription(PortNumber.portNumber(i), true, | ||
344 | + Port.Type.COPPER, 0)); | ||
345 | + } | ||
346 | + return ports; | ||
347 | + } | ||
348 | + | ||
349 | + // Counts down number of device added/available/removed events. | ||
350 | + private class DeviceEventCounter implements DeviceListener { | ||
351 | + @Override | ||
352 | + public void event(DeviceEvent event) { | ||
353 | + DeviceEvent.Type type = event.type(); | ||
354 | + if (type == DEVICE_ADDED || type == DEVICE_REMOVED || | ||
355 | + type == DEVICE_AVAILABILITY_CHANGED) { | ||
356 | + deviceLatch.countDown(); | ||
357 | + } | ||
358 | + } | ||
359 | + } | ||
360 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.provider.nil; | ||
17 | + | ||
18 | +import static com.google.common.base.Preconditions.checkArgument; | ||
19 | + | ||
20 | +/** | ||
21 | + * Tree topology with hosts at the leaf devices. | ||
22 | + */ | ||
23 | +public class TreeTopologySimulator extends TopologySimulator { | ||
24 | + | ||
25 | + private int[] tierMultiplier; | ||
26 | + private int[] tierDeviceCount; | ||
27 | + private int[] tierOffset; | ||
28 | + | ||
29 | + @Override | ||
30 | + protected void processTopoShape(String shape) { | ||
31 | + super.processTopoShape(shape); | ||
32 | + tierOffset = new int[topoShape.length]; | ||
33 | + tierMultiplier = new int[topoShape.length]; | ||
34 | + tierDeviceCount = new int[topoShape.length]; | ||
35 | + | ||
36 | + deviceCount = 1; | ||
37 | + | ||
38 | + tierOffset[0] = 0; | ||
39 | + tierMultiplier[0] = 1; | ||
40 | + tierDeviceCount[0] = deviceCount; | ||
41 | + | ||
42 | + for (int i = 1; i < topoShape.length; i++) { | ||
43 | + tierOffset[i] = deviceCount; | ||
44 | + tierMultiplier[i] = Integer.parseInt(topoShape[i]); | ||
45 | + tierDeviceCount[i] = tierDeviceCount[i - 1] * tierMultiplier[i]; | ||
46 | + deviceCount = deviceCount + tierDeviceCount[i]; | ||
47 | + } | ||
48 | + } | ||
49 | + | ||
50 | + @Override | ||
51 | + public void setUpTopology() { | ||
52 | + checkArgument(tierDeviceCount.length > 0, "There must be at least one tree tier"); | ||
53 | + super.setUpTopology(); | ||
54 | + } | ||
55 | + | ||
56 | + @Override | ||
57 | + protected void createLinks() { | ||
58 | + for (int t = 1; t < tierOffset.length; t++) { | ||
59 | + int child = tierOffset[t]; | ||
60 | + for (int parent = tierOffset[t - 1]; parent < tierOffset[t]; parent++) { | ||
61 | + for (int i = 0; i < tierMultiplier[t]; i++) { | ||
62 | + createLink(parent, child); | ||
63 | + child++; | ||
64 | + } | ||
65 | + } | ||
66 | + } | ||
67 | + } | ||
68 | + | ||
69 | + @Override | ||
70 | + protected void createHosts() { | ||
71 | + for (int i = tierOffset[tierOffset.length - 1]; i < deviceCount; i++) { | ||
72 | + createHosts(deviceIds.get(i), hostCount); | ||
73 | + } | ||
74 | + } | ||
75 | +} |
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.provider.nil.cli; | ||
17 | + | ||
18 | +import org.apache.karaf.shell.commands.Argument; | ||
19 | +import org.apache.karaf.shell.commands.Command; | ||
20 | +import org.onosproject.cfg.ComponentConfigService; | ||
21 | +import org.onosproject.cli.AbstractShellCommand; | ||
22 | +import org.onosproject.provider.nil.NullProviders; | ||
23 | + | ||
24 | +import static org.onosproject.cli.StartStopCompleter.START; | ||
25 | + | ||
26 | +/** | ||
27 | + * Starts or stops topology simulation. | ||
28 | + */ | ||
29 | +@Command(scope = "onos", name = "null-simulation", | ||
30 | + description = "Starts or stops topology simulation") | ||
31 | +public class NullControlCommand extends AbstractShellCommand { | ||
32 | + | ||
33 | + @Argument(index = 0, name = "cmd", description = "Control command: start/stop", | ||
34 | + required = true, multiValued = false) | ||
35 | + String cmd = null; | ||
36 | + | ||
37 | + @Argument(index = 1, name = "topoShape", | ||
38 | + description = "Topology shape: e.g. configured, linear, reroute, centipede, tree, spineleaf, mesh", | ||
39 | + required = false, multiValued = false) | ||
40 | + String topoShape = null; | ||
41 | + | ||
42 | + @Override | ||
43 | + protected void execute() { | ||
44 | + ComponentConfigService service = get(ComponentConfigService.class); | ||
45 | + if (topoShape != null) { | ||
46 | + service.setProperty(NullProviders.class.getName(), "topoShape", topoShape); | ||
47 | + } | ||
48 | + service.setProperty(NullProviders.class.getName(), "enabled", | ||
49 | + cmd.equals(START) ? "true" : "false"); | ||
50 | + } | ||
51 | + | ||
52 | +} |
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.provider.nil.cli; | ||
17 | + | ||
18 | +import org.apache.karaf.shell.commands.Argument; | ||
19 | +import org.apache.karaf.shell.commands.Command; | ||
20 | +import org.onosproject.cli.AbstractShellCommand; | ||
21 | +import org.onosproject.net.ConnectPoint; | ||
22 | +import org.onosproject.net.DeviceId; | ||
23 | +import org.onosproject.net.PortNumber; | ||
24 | +import org.onosproject.provider.nil.NullProviders; | ||
25 | + | ||
26 | +import static org.onosproject.cli.UpDownCompleter.DOWN; | ||
27 | +import static org.onosproject.cli.UpDownCompleter.UP; | ||
28 | +import static org.onosproject.cli.net.AddPointToPointIntentCommand.getDeviceId; | ||
29 | +import static org.onosproject.cli.net.AddPointToPointIntentCommand.getPortNumber; | ||
30 | +import static org.onosproject.net.DeviceId.deviceId; | ||
31 | +import static org.onosproject.net.PortNumber.portNumber; | ||
32 | + | ||
33 | +/** | ||
34 | + * Servers or repairs a simulated link. | ||
35 | + */ | ||
36 | +@Command(scope = "onos", name = "null-link", | ||
37 | + description = "Severs or repairs a simulated link") | ||
38 | +public class NullLinkCommand extends AbstractShellCommand { | ||
39 | + | ||
40 | + @Argument(index = 0, name = "one", description = "One link end-point as device/port", | ||
41 | + required = true, multiValued = false) | ||
42 | + String one = null; | ||
43 | + | ||
44 | + @Argument(index = 1, name = "two", description = "Another link end-point as device/port", | ||
45 | + required = true, multiValued = false) | ||
46 | + String two = null; | ||
47 | + | ||
48 | + @Argument(index = 2, name = "cmd", description = "up/down", | ||
49 | + required = true, multiValued = false) | ||
50 | + String cmd = null; | ||
51 | + | ||
52 | + | ||
53 | + @Override | ||
54 | + protected void execute() { | ||
55 | + NullProviders service = get(NullProviders.class); | ||
56 | + | ||
57 | + try { | ||
58 | + DeviceId oneId = deviceId(getDeviceId(one)); | ||
59 | + PortNumber onePort = portNumber(getPortNumber(one)); | ||
60 | + ConnectPoint onePoint = new ConnectPoint(oneId, onePort); | ||
61 | + | ||
62 | + DeviceId twoId = deviceId(getDeviceId(two)); | ||
63 | + PortNumber twoPort = portNumber(getPortNumber(two)); | ||
64 | + ConnectPoint twoPoint = new ConnectPoint(twoId, twoPort); | ||
65 | + | ||
66 | + if (cmd.equals(UP)) { | ||
67 | + service.repairLink(onePoint, twoPoint); | ||
68 | + } else if (cmd.equals(DOWN)) { | ||
69 | + service.severLink(onePoint, twoPoint); | ||
70 | + } else { | ||
71 | + error("Illegal command %s; must be up or down", cmd); | ||
72 | + } | ||
73 | + } catch (NumberFormatException e) { | ||
74 | + error("Invalid port number specified", e); | ||
75 | + } | ||
76 | + } | ||
77 | + | ||
78 | +} |
providers/null/src/main/java/org/onosproject/provider/nil/cli/TopologyShapeCompleter.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2015 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.onosproject.provider.nil.cli; | ||
17 | + | ||
18 | +import com.google.common.collect.ImmutableList; | ||
19 | +import org.onosproject.cli.AbstractChoicesCompleter; | ||
20 | + | ||
21 | +import java.util.List; | ||
22 | + | ||
23 | +/** | ||
24 | + * Topology shape completer. | ||
25 | + */ | ||
26 | +public class TopologyShapeCompleter extends AbstractChoicesCompleter { | ||
27 | + @Override | ||
28 | + public List<String> choices() { | ||
29 | + return ImmutableList.of("configured", "linear", "reroute", "centipede", | ||
30 | + "tree", "spineleaf", "mesh"); | ||
31 | + } | ||
32 | +} |
1 | +/* | ||
2 | + * Copyright 2015 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 | + * Null provider CLI commands and completers. | ||
19 | + */ | ||
20 | +package org.onosproject.provider.nil.cli; |
1 | +/* | ||
2 | + * Copyright 2015 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 | + * Set of null south-bound providers which permit simulating a network | ||
19 | + * topology using fake devices, links, hosts, etc. | ||
20 | + */ | ||
21 | +package org.onosproject.provider.nil; |
1 | +<!-- | ||
2 | + ~ Copyright 2015 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 | +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> | ||
17 | + | ||
18 | + <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0"> | ||
19 | + <command> | ||
20 | + <action class="org.onosproject.provider.nil.cli.NullControlCommand"/> | ||
21 | + <completers> | ||
22 | + <ref component-id="startStopCompleter"/> | ||
23 | + <ref component-id="topoShapeCompleter"/> | ||
24 | + <null/> | ||
25 | + </completers> | ||
26 | + </command> | ||
27 | + <command> | ||
28 | + <action class="org.onosproject.provider.nil.cli.NullLinkCommand"/> | ||
29 | + <completers> | ||
30 | + <ref component-id="linkSrcCompleter"/> | ||
31 | + <ref component-id="linkDstCompleter"/> | ||
32 | + <ref component-id="upDownCompleter"/> | ||
33 | + <null/> | ||
34 | + </completers> | ||
35 | + </command> | ||
36 | + </command-bundle> | ||
37 | + | ||
38 | + <bean id="startStopCompleter" class="org.onosproject.cli.StartStopCompleter"/> | ||
39 | + <bean id="upDownCompleter" class="org.onosproject.cli.UpDownCompleter"/> | ||
40 | + <bean id="topoShapeCompleter" class="org.onosproject.provider.nil.cli.TopologyShapeCompleter"/> | ||
41 | + <bean id="linkSrcCompleter" class="org.onosproject.cli.net.LinkSrcCompleter"/> | ||
42 | + <bean id="linkDstCompleter" class="org.onosproject.cli.net.LinkDstCompleter"/> | ||
43 | + | ||
44 | +</blueprint> |
tools/test/topos/attmpls-sim.json
0 → 100644
1 | +{ | ||
2 | + "devices": [ | ||
3 | + { "alias": "s1", "uri": "null:0000000000000001", "mac": "000000000001", "annotations": { "name": "CMBR", "latitude": 42.373730, "longitude": -71.109734 }, "type": "SWITCH" }, | ||
4 | + { "alias": "s2", "uri": "null:0000000000000002", "mac": "000000000002", "annotations": { "name": "CHCG", "latitude": 41.877461, "longitude": -87.642892 }, "type": "SWITCH" }, | ||
5 | + { "alias": "s3", "uri": "null:0000000000000003", "mac": "000000000003", "annotations": { "name": "CLEV", "latitude": 41.498928, "longitude": -81.695217 }, "type": "SWITCH" }, | ||
6 | + { "alias": "s4", "uri": "null:0000000000000004", "mac": "000000000004", "annotations": { "name": "RLGH", "latitude": 35.780150, "longitude": -78.644026 }, "type": "SWITCH" }, | ||
7 | + { "alias": "s5", "uri": "null:0000000000000005", "mac": "000000000005", "annotations": { "name": "ATLN", "latitude": 33.749017, "longitude": -84.394168 }, "type": "SWITCH" }, | ||
8 | + { "alias": "s6", "uri": "null:0000000000000006", "mac": "000000000006", "annotations": { "name": "PHLA", "latitude": 39.952906, "longitude": -75.172278 }, "type": "SWITCH" }, | ||
9 | + { "alias": "s7", "uri": "null:0000000000000007", "mac": "000000000007", "annotations": { "name": "WASH", "latitude": 38.906696, "longitude": -77.035509 }, "type": "SWITCH" }, | ||
10 | + { "alias": "s8", "uri": "null:0000000000000008", "mac": "000000000008", "annotations": { "name": "NSVL", "latitude": 36.166410, "longitude": -86.787305 }, "type": "SWITCH" }, | ||
11 | + { "alias": "s9", "uri": "null:0000000000000009", "mac": "000000000009", "annotations": { "name": "STLS", "latitude": 38.626418, "longitude": -90.198143 }, "type": "SWITCH" }, | ||
12 | + { "alias": "s10", "uri": "null:000000000000000a", "mac": "00000000000a", "annotations": { "name": "NWOR", "latitude": 29.951475, "longitude": -90.078434 }, "type": "SWITCH" }, | ||
13 | + { "alias": "s11", "uri": "null:000000000000000b", "mac": "00000000000b", "annotations": { "name": "HSTN", "latitude": 29.763249, "longitude": -95.368332 }, "type": "SWITCH" }, | ||
14 | + { "alias": "s12", "uri": "null:000000000000000c", "mac": "00000000000c", "annotations": { "name": "SNAN", "latitude": 29.424331, "longitude": -98.491745 }, "type": "SWITCH" }, | ||
15 | + { "alias": "s13", "uri": "null:000000000000000d", "mac": "00000000000d", "annotations": { "name": "DLLS", "latitude": 32.777665, "longitude": -96.802064 }, "type": "SWITCH" }, | ||
16 | + { "alias": "s14", "uri": "null:000000000000000e", "mac": "00000000000e", "annotations": { "name": "ORLD", "latitude": 28.538641, "longitude": -81.381110 }, "type": "SWITCH" }, | ||
17 | + { "alias": "s15", "uri": "null:000000000000000f", "mac": "00000000000f", "annotations": { "name": "DNVR", "latitude": 39.736623, "longitude": -104.984887 }, "type": "SWITCH" }, | ||
18 | + { "alias": "s16", "uri": "null:0000000000000010", "mac": "000000000010", "annotations": { "name": "KSCY", "latitude": 39.100725, "longitude": -94.581228 }, "type": "SWITCH" }, | ||
19 | + { "alias": "s17", "uri": "null:0000000000000011", "mac": "000000000011", "annotations": { "name": "SNFN", "latitude": 37.779751, "longitude": -122.409791 }, "type": "SWITCH" }, | ||
20 | + { "alias": "s18", "uri": "null:0000000000000012", "mac": "000000000012", "annotations": { "name": "SCRM", "latitude": 38.581001, "longitude": -121.497844 }, "type": "SWITCH" }, | ||
21 | + { "alias": "s19", "uri": "null:0000000000000013", "mac": "000000000013", "annotations": { "name": "PTLD", "latitude": 45.523317, "longitude": -122.677768 }, "type": "SWITCH" }, | ||
22 | + { "alias": "s20", "uri": "null:0000000000000014", "mac": "000000000014", "annotations": { "name": "STTL", "latitude": 47.607326, "longitude": -122.331786 }, "type": "SWITCH" }, | ||
23 | + { "alias": "s21", "uri": "null:0000000000000015", "mac": "000000000015", "annotations": { "name": "SLKC", "latitude": 40.759577, "longitude": -111.895079 }, "type": "SWITCH" }, | ||
24 | + { "alias": "s22", "uri": "null:0000000000000016", "mac": "000000000016", "annotations": { "name": "LA03", "latitude": 34.056346, "longitude": -118.235951 }, "type": "SWITCH" }, | ||
25 | + { "alias": "s23", "uri": "null:0000000000000017", "mac": "000000000017", "annotations": { "name": "SNDG", "latitude": 32.714564, "longitude": -117.153528 }, "type": "SWITCH" }, | ||
26 | + { "alias": "s24", "uri": "null:0000000000000018", "mac": "000000000018", "annotations": { "name": "PHNX", "latitude": 33.448289, "longitude": -112.076299 }, "type": "SWITCH" }, | ||
27 | + { "alias": "s25", "uri": "null:0000000000000019", "mac": "000000000019", "annotations": { "name": "NY54", "latitude": 40.728270, "longitude": -73.994483 }, "type": "SWITCH" } | ||
28 | + ], | ||
29 | + | ||
30 | + "hosts": [ | ||
31 | + { "alias": "h1", "mac": "00:00:00:00:00:01", "vlan": -1, "location": "null:0000000000000001/1", "ip": "10.0.0.1", "annotations": { "name": "CMBR", "latitude": 43.355715, "longitude": -69.528243 } }, | ||
32 | + { "alias": "h2", "mac": "00:00:00:00:00:02", "vlan": -1, "location": "null:0000000000000002/1", "ip": "10.0.0.2", "annotations": { "name": "CHCG", "latitude": 43.632679, "longitude": -88.772526 } }, | ||
33 | + { "alias": "h3", "mac": "00:00:00:00:00:03", "vlan": -1, "location": "null:0000000000000003/1", "ip": "10.0.0.3", "annotations": { "name": "CLEV", "latitude": 42.756945, "longitude": -79.831317 } }, | ||
34 | + { "alias": "h4", "mac": "00:00:00:00:00:04", "vlan": -1, "location": "null:0000000000000004/1", "ip": "10.0.0.4", "annotations": { "name": "RLGH", "latitude": 36.972249, "longitude": -76.667163 } }, | ||
35 | + { "alias": "h5", "mac": "00:00:00:00:00:05", "vlan": -1, "location": "null:0000000000000005/1", "ip": "10.0.0.5", "annotations": { "name": "ATLN", "latitude": 35.427493, "longitude": -83.885831 } }, | ||
36 | + { "alias": "h6", "mac": "00:00:00:00:00:06", "vlan": -1, "location": "null:0000000000000006/1", "ip": "10.0.0.6", "annotations": { "name": "PHLA", "latitude": 39.208113, "longitude": -73.421341 } }, | ||
37 | + { "alias": "h7", "mac": "00:00:00:00:00:07", "vlan": -1, "location": "null:0000000000000007/1", "ip": "10.0.0.7", "annotations": { "name": "WASH", "latitude": 40.133860, "longitude": -79.238299 } }, | ||
38 | + { "alias": "h8", "mac": "00:00:00:00:00:08", "vlan": -1, "location": "null:0000000000000008/1", "ip": "10.0.0.8", "annotations": { "name": "NSVL", "latitude": 37.407589, "longitude": -84.415068 } }, | ||
39 | + { "alias": "h9", "mac": "00:00:00:00:00:09", "vlan": -1, "location": "null:0000000000000009/1", "ip": "10.0.0.9", "annotations": { "name": "STLS", "latitude": 40.066810, "longitude": -90.932405 } }, | ||
40 | + { "alias": "h10", "mac": "00:00:00:00:00:0a", "vlan": -1, "location": "null:000000000000000a/1", "ip": "10.0.0.10", "annotations": { "name": "NWOR", "latitude": 31.470982, "longitude": -88.779353 } }, | ||
41 | + { "alias": "h11", "mac": "00:00:00:00:00:0b", "vlan": -1, "location": "null:000000000000000b/1", "ip": "10.0.0.11", "annotations": { "name": "HSTN", "latitude": 31.136858, "longitude": -94.351656 } }, | ||
42 | + { "alias": "h12", "mac": "00:00:00:00:00:0c", "vlan": -1, "location": "null:000000000000000c/1", "ip": "10.0.0.12", "annotations": { "name": "SNAN", "latitude": 28.040975, "longitude": -99.169527 } }, | ||
43 | + { "alias": "h13", "mac": "00:00:00:00:00:0d", "vlan": -1, "location": "null:000000000000000d/1", "ip": "10.0.0.13", "annotations": { "name": "DLLS", "latitude": 31.899825, "longitude": -99.287263 } }, | ||
44 | + { "alias": "h14", "mac": "00:00:00:00:00:0e", "vlan": -1, "location": "null:000000000000000e/1", "ip": "10.0.0.14", "annotations": { "name": "ORLD", "latitude": 26.670509, "longitude": -81.291920 } }, | ||
45 | + { "alias": "h15", "mac": "00:00:00:00:00:0f", "vlan": -1, "location": "null:000000000000000f/1", "ip": "10.0.0.15", "annotations": { "name": "DNVR", "latitude": 40.888148, "longitude": -103.459878 } }, | ||
46 | + { "alias": "h16", "mac": "00:00:00:00:00:10", "vlan": -1, "location": "null:0000000000000010/1", "ip": "10.0.0.16", "annotations": { "name": "KSCY", "latitude": 40.545088, "longitude": -93.734002 } }, | ||
47 | + { "alias": "h17", "mac": "00:00:00:00:00:11", "vlan": -1, "location": "null:0000000000000011/1", "ip": "10.0.0.17", "annotations": { "name": "SNFN", "latitude": 39.081743, "longitude": -124.330172 } }, | ||
48 | + { "alias": "h18", "mac": "00:00:00:00:00:12", "vlan": -1, "location": "null:0000000000000012/1", "ip": "10.0.0.18", "annotations": { "name": "SCRM", "latitude": 40.107468, "longitude": -120.424689 } }, | ||
49 | + { "alias": "h19", "mac": "00:00:00:00:00:13", "vlan": -1, "location": "null:0000000000000013/1", "ip": "10.0.0.19", "annotations": { "name": "PTLD", "latitude": 44.383051, "longitude": -124.767594 } }, | ||
50 | + { "alias": "h20", "mac": "00:00:00:00:00:14", "vlan": -1, "location": "null:0000000000000014/1", "ip": "10.0.0.20", "annotations": { "name": "STTL", "latitude": 48.832627, "longitude": -120.298441 } }, | ||
51 | + { "alias": "h21", "mac": "00:00:00:00:00:15", "vlan": -1, "location": "null:0000000000000015/1", "ip": "10.0.0.21", "annotations": { "name": "SLKC", "latitude": 42.301734, "longitude": -111.217297 } }, | ||
52 | + { "alias": "h22", "mac": "00:00:00:00:00:16", "vlan": -1, "location": "null:0000000000000016/1", "ip": "10.0.0.22", "annotations": { "name": "LA03", "latitude": 33.224634, "longitude": -121.532943 } }, | ||
53 | + { "alias": "h23", "mac": "00:00:00:00:00:17", "vlan": -1, "location": "null:0000000000000017/1", "ip": "10.0.0.23", "annotations": { "name": "SNDG", "latitude": 31.834607, "longitude": -118.847982 } }, | ||
54 | + { "alias": "h24", "mac": "00:00:00:00:00:18", "vlan": -1, "location": "null:0000000000000018/1", "ip": "10.0.0.24", "annotations": { "name": "PHNX", "latitude": 34.662290, "longitude": -110.946662 } }, | ||
55 | + { "alias": "h25", "mac": "00:00:00:00:00:19", "vlan": -1, "location": "null:0000000000000019/1", "ip": "10.0.0.25", "annotations": { "name": "NY54", "latitude": 42.395459, "longitude": -75.293563 } } | ||
56 | + ], | ||
57 | + | ||
58 | + "links": [ | ||
59 | + { "src": "null:0000000000000019/2", "dst": "null:0000000000000001/2", "annotations": { "durable": "true" }}, | ||
60 | + { "src": "null:0000000000000019/3", "dst": "null:0000000000000002/10", "annotations": { "durable": "true" }}, | ||
61 | + { "src": "null:0000000000000019/4", "dst": "null:0000000000000006/3", "annotations": { "durable": "true" }}, | ||
62 | + { "src": "null:0000000000000019/5", "dst": "null:0000000000000007/2", "annotations": { "durable": "true" }}, | ||
63 | + { "src": "null:0000000000000001/2", "dst": "null:0000000000000006/4", "annotations": { "durable": "true" }}, | ||
64 | + { "src": "null:0000000000000002/2", "dst": "null:0000000000000003/5", "annotations": { "durable": "true" }}, | ||
65 | + { "src": "null:0000000000000002/3", "dst": "null:0000000000000006/5", "annotations": { "durable": "true" }}, | ||
66 | + { "src": "null:0000000000000002/4", "dst": "null:0000000000000009/2", "annotations": { "durable": "true" }}, | ||
67 | + { "src": "null:0000000000000002/5", "dst": "null:000000000000000f/5", "annotations": { "durable": "true" }}, | ||
68 | + { "src": "null:0000000000000002/6", "dst": "null:0000000000000010/3", "annotations": { "durable": "true" }}, | ||
69 | + { "src": "null:0000000000000002/7", "dst": "null:0000000000000011/7", "annotations": { "durable": "true" }}, | ||
70 | + { "src": "null:0000000000000002/8", "dst": "null:0000000000000014/2", "annotations": { "durable": "true" }}, | ||
71 | + { "src": "null:0000000000000002/9", "dst": "null:0000000000000015/3", "annotations": { "durable": "true" }}, | ||
72 | + { "src": "null:0000000000000003/2", "dst": "null:0000000000000008/4", "annotations": { "durable": "true" }}, | ||
73 | + { "src": "null:0000000000000003/3", "dst": "null:0000000000000009/5", "annotations": { "durable": "true" }}, | ||
74 | + { "src": "null:0000000000000003/4", "dst": "null:0000000000000006/6", "annotations": { "durable": "true" }}, | ||
75 | + { "src": "null:0000000000000004/2", "dst": "null:0000000000000005/7", "annotations": { "durable": "true" }}, | ||
76 | + { "src": "null:0000000000000004/3", "dst": "null:0000000000000007/3", "annotations": { "durable": "true" }}, | ||
77 | + { "src": "null:0000000000000005/2", "dst": "null:0000000000000007/4", "annotations": { "durable": "true" }}, | ||
78 | + { "src": "null:0000000000000005/3", "dst": "null:0000000000000008/5", "annotations": { "durable": "true" }}, | ||
79 | + { "src": "null:0000000000000005/4", "dst": "null:0000000000000009/3", "annotations": { "durable": "true" }}, | ||
80 | + { "src": "null:0000000000000005/5", "dst": "null:000000000000000d/6", "annotations": { "durable": "true" }}, | ||
81 | + { "src": "null:0000000000000005/6", "dst": "null:000000000000000e/2", "annotations": { "durable": "true" }}, | ||
82 | + { "src": "null:0000000000000006/2", "dst": "null:0000000000000007/4", "annotations": { "durable": "true" }}, | ||
83 | + { "src": "null:0000000000000008/2", "dst": "null:0000000000000009/6", "annotations": { "durable": "true" }}, | ||
84 | + { "src": "null:0000000000000008/3", "dst": "null:000000000000000d/7", "annotations": { "durable": "true" }}, | ||
85 | + { "src": "null:0000000000000009/2", "dst": "null:000000000000000d/8", "annotations": { "durable": "true" }}, | ||
86 | + { "src": "null:0000000000000009/3", "dst": "null:0000000000000010/4", "annotations": { "durable": "true" }}, | ||
87 | + { "src": "null:0000000000000009/4", "dst": "null:0000000000000016/5", "annotations": { "durable": "true" }}, | ||
88 | + { "src": "null:000000000000000a/2", "dst": "null:000000000000000b/5", "annotations": { "durable": "true" }}, | ||
89 | + { "src": "null:000000000000000a/3", "dst": "null:000000000000000d/9", "annotations": { "durable": "true" }}, | ||
90 | + { "src": "null:000000000000000a/4", "dst": "null:000000000000000e/3", "annotations": { "durable": "true" }}, | ||
91 | + { "src": "null:000000000000000b/2", "dst": "null:000000000000000c/4", "annotations": { "durable": "true" }}, | ||
92 | + { "src": "null:000000000000000b/3", "dst": "null:000000000000000d/10", "annotations": { "durable": "true" }}, | ||
93 | + { "src": "null:000000000000000b/4", "dst": "null:000000000000000e/4", "annotations": { "durable": "true" }}, | ||
94 | + { "src": "null:000000000000000c/2", "dst": "null:0000000000000018/2", "annotations": { "durable": "true" }}, | ||
95 | + { "src": "null:000000000000000c/3", "dst": "null:000000000000000d/6", "annotations": { "durable": "true" }}, | ||
96 | + { "src": "null:000000000000000d/2", "dst": "null:000000000000000f/5", "annotations": { "durable": "true" }}, | ||
97 | + { "src": "null:000000000000000d/3", "dst": "null:0000000000000010/5", "annotations": { "durable": "true" }}, | ||
98 | + { "src": "null:000000000000000d/4", "dst": "null:0000000000000011/8", "annotations": { "durable": "true" }}, | ||
99 | + { "src": "null:000000000000000d/5", "dst": "null:0000000000000016/6", "annotations": { "durable": "true" }}, | ||
100 | + { "src": "null:000000000000000f/2", "dst": "null:0000000000000010/6", "annotations": { "durable": "true" }}, | ||
101 | + { "src": "null:000000000000000f/3", "dst": "null:0000000000000011/9", "annotations": { "durable": "true" }}, | ||
102 | + { "src": "null:000000000000000f/4", "dst": "null:0000000000000015/4", "annotations": { "durable": "true" }}, | ||
103 | + { "src": "null:0000000000000010/2", "dst": "null:0000000000000011/10", "annotations": { "durable": "true" }}, | ||
104 | + { "src": "null:0000000000000011/2", "dst": "null:0000000000000012/3", "annotations": { "durable": "true" }}, | ||
105 | + { "src": "null:0000000000000011/3", "dst": "null:0000000000000013/3", "annotations": { "durable": "true" }}, | ||
106 | + { "src": "null:0000000000000011/4", "dst": "null:0000000000000014/3", "annotations": { "durable": "true" }}, | ||
107 | + { "src": "null:0000000000000011/5", "dst": "null:0000000000000015/4", "annotations": { "durable": "true" }}, | ||
108 | + { "src": "null:0000000000000011/6", "dst": "null:0000000000000016/7", "annotations": { "durable": "true" }}, | ||
109 | + { "src": "null:0000000000000012/2", "dst": "null:0000000000000015/5", "annotations": { "durable": "true" }}, | ||
110 | + { "src": "null:0000000000000013/2", "dst": "null:0000000000000014/4", "annotations": { "durable": "true" }}, | ||
111 | + { "src": "null:0000000000000015/2", "dst": "null:0000000000000016/8", "annotations": { "durable": "true" }}, | ||
112 | + { "src": "null:0000000000000016/2", "dst": "null:0000000000000017/3", "annotations": { "durable": "true" }}, | ||
113 | + { "src": "null:0000000000000016/3", "dst": "null:0000000000000018/3", "annotations": { "durable": "true" }}, | ||
114 | + { "src": "null:0000000000000017/2", "dst": "null:0000000000000018/5", "annotations": { "durable": "true" }} | ||
115 | + ] | ||
116 | +} |
... | @@ -192,6 +192,20 @@ public abstract class Tools { | ... | @@ -192,6 +192,20 @@ public abstract class Tools { |
192 | } | 192 | } |
193 | 193 | ||
194 | /** | 194 | /** |
195 | + * Suspends the current thread for a specified number of millis and nanos. | ||
196 | + * | ||
197 | + * @param ms number of millis | ||
198 | + * @param nanos number of nanos | ||
199 | + */ | ||
200 | + public static void delay(int ms, int nanos) { | ||
201 | + try { | ||
202 | + Thread.sleep(ms, nanos); | ||
203 | + } catch (InterruptedException e) { | ||
204 | + throw new RuntimeException("Interrupted", e); | ||
205 | + } | ||
206 | + } | ||
207 | + | ||
208 | + /** | ||
195 | * Slurps the contents of a file into a list of strings, one per line. | 209 | * Slurps the contents of a file into a list of strings, one per line. |
196 | * | 210 | * |
197 | * @param path file path | 211 | * @param path file path | ... | ... |
... | @@ -16,6 +16,11 @@ | ... | @@ -16,6 +16,11 @@ |
16 | package org.onosproject.rest; | 16 | package org.onosproject.rest; |
17 | 17 | ||
18 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | +import com.google.common.collect.Lists; | ||
20 | +import org.onlab.packet.ChassisId; | ||
21 | +import org.onlab.packet.IpAddress; | ||
22 | +import org.onlab.packet.MacAddress; | ||
23 | +import org.onlab.packet.VlanId; | ||
19 | import org.onosproject.net.ConnectPoint; | 24 | import org.onosproject.net.ConnectPoint; |
20 | import org.onosproject.net.DefaultAnnotations; | 25 | import org.onosproject.net.DefaultAnnotations; |
21 | import org.onosproject.net.Device; | 26 | import org.onosproject.net.Device; |
... | @@ -30,9 +35,12 @@ import org.onosproject.net.SparseAnnotations; | ... | @@ -30,9 +35,12 @@ import org.onosproject.net.SparseAnnotations; |
30 | import org.onosproject.net.device.DefaultDeviceDescription; | 35 | import org.onosproject.net.device.DefaultDeviceDescription; |
31 | import org.onosproject.net.device.DefaultPortDescription; | 36 | import org.onosproject.net.device.DefaultPortDescription; |
32 | import org.onosproject.net.device.DeviceDescription; | 37 | import org.onosproject.net.device.DeviceDescription; |
38 | +import org.onosproject.net.device.DeviceEvent; | ||
39 | +import org.onosproject.net.device.DeviceListener; | ||
33 | import org.onosproject.net.device.DeviceProvider; | 40 | import org.onosproject.net.device.DeviceProvider; |
34 | import org.onosproject.net.device.DeviceProviderRegistry; | 41 | import org.onosproject.net.device.DeviceProviderRegistry; |
35 | import org.onosproject.net.device.DeviceProviderService; | 42 | import org.onosproject.net.device.DeviceProviderService; |
43 | +import org.onosproject.net.device.DeviceService; | ||
36 | import org.onosproject.net.device.PortDescription; | 44 | import org.onosproject.net.device.PortDescription; |
37 | import org.onosproject.net.host.DefaultHostDescription; | 45 | import org.onosproject.net.host.DefaultHostDescription; |
38 | import org.onosproject.net.host.HostProvider; | 46 | import org.onosproject.net.host.HostProvider; |
... | @@ -43,10 +51,8 @@ import org.onosproject.net.link.LinkProvider; | ... | @@ -43,10 +51,8 @@ import org.onosproject.net.link.LinkProvider; |
43 | import org.onosproject.net.link.LinkProviderRegistry; | 51 | import org.onosproject.net.link.LinkProviderRegistry; |
44 | import org.onosproject.net.link.LinkProviderService; | 52 | import org.onosproject.net.link.LinkProviderService; |
45 | import org.onosproject.net.provider.ProviderId; | 53 | import org.onosproject.net.provider.ProviderId; |
46 | -import org.onlab.packet.ChassisId; | 54 | +import org.slf4j.Logger; |
47 | -import org.onlab.packet.IpAddress; | 55 | +import org.slf4j.LoggerFactory; |
48 | -import org.onlab.packet.MacAddress; | ||
49 | -import org.onlab.packet.VlanId; | ||
50 | 56 | ||
51 | import java.net.URI; | 57 | import java.net.URI; |
52 | import java.util.ArrayList; | 58 | import java.util.ArrayList; |
... | @@ -54,37 +60,60 @@ import java.util.HashSet; | ... | @@ -54,37 +60,60 @@ import java.util.HashSet; |
54 | import java.util.Iterator; | 60 | import java.util.Iterator; |
55 | import java.util.List; | 61 | import java.util.List; |
56 | import java.util.Set; | 62 | import java.util.Set; |
63 | +import java.util.concurrent.CountDownLatch; | ||
64 | +import java.util.concurrent.TimeUnit; | ||
65 | +import java.util.stream.Collectors; | ||
57 | 66 | ||
58 | import static com.google.common.base.Preconditions.checkNotNull; | 67 | import static com.google.common.base.Preconditions.checkNotNull; |
59 | import static org.onosproject.net.DeviceId.deviceId; | 68 | import static org.onosproject.net.DeviceId.deviceId; |
60 | import static org.onosproject.net.PortNumber.portNumber; | 69 | import static org.onosproject.net.PortNumber.portNumber; |
70 | +import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED; | ||
71 | +import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED; | ||
61 | 72 | ||
62 | /** | 73 | /** |
63 | * Provider of devices and links parsed from a JSON configuration structure. | 74 | * Provider of devices and links parsed from a JSON configuration structure. |
64 | */ | 75 | */ |
65 | class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { | 76 | class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { |
66 | 77 | ||
78 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
79 | + | ||
67 | private static final ProviderId PID = | 80 | private static final ProviderId PID = |
68 | new ProviderId("cfg", "org.onosproject.rest", true); | 81 | new ProviderId("cfg", "org.onosproject.rest", true); |
69 | 82 | ||
83 | + private static final String UNKNOWN = "unknown"; | ||
84 | + | ||
85 | + private CountDownLatch deviceLatch; | ||
86 | + | ||
70 | private final JsonNode cfg; | 87 | private final JsonNode cfg; |
88 | + private final DeviceService deviceService; | ||
89 | + | ||
71 | private final DeviceProviderRegistry deviceProviderRegistry; | 90 | private final DeviceProviderRegistry deviceProviderRegistry; |
72 | private final LinkProviderRegistry linkProviderRegistry; | 91 | private final LinkProviderRegistry linkProviderRegistry; |
73 | private final HostProviderRegistry hostProviderRegistry; | 92 | private final HostProviderRegistry hostProviderRegistry; |
74 | 93 | ||
94 | + private DeviceProviderService deviceProviderService; | ||
95 | + private LinkProviderService linkProviderService; | ||
96 | + private HostProviderService hostProviderService; | ||
97 | + | ||
98 | + private DeviceListener deviceEventCounter = new DeviceEventCounter(); | ||
99 | + private List<ConnectPoint> connectPoints = Lists.newArrayList(); | ||
100 | + | ||
75 | /** | 101 | /** |
76 | * Creates a new configuration provider. | 102 | * Creates a new configuration provider. |
77 | * | 103 | * |
78 | * @param cfg JSON configuration | 104 | * @param cfg JSON configuration |
105 | + * @param deviceService device service | ||
79 | * @param deviceProviderRegistry device provider registry | 106 | * @param deviceProviderRegistry device provider registry |
80 | * @param linkProviderRegistry link provider registry | 107 | * @param linkProviderRegistry link provider registry |
81 | * @param hostProviderRegistry host provider registry | 108 | * @param hostProviderRegistry host provider registry |
82 | */ | 109 | */ |
83 | ConfigProvider(JsonNode cfg, | 110 | ConfigProvider(JsonNode cfg, |
111 | + DeviceService deviceService, | ||
84 | DeviceProviderRegistry deviceProviderRegistry, | 112 | DeviceProviderRegistry deviceProviderRegistry, |
85 | LinkProviderRegistry linkProviderRegistry, | 113 | LinkProviderRegistry linkProviderRegistry, |
86 | HostProviderRegistry hostProviderRegistry) { | 114 | HostProviderRegistry hostProviderRegistry) { |
87 | this.cfg = checkNotNull(cfg, "Configuration cannot be null"); | 115 | this.cfg = checkNotNull(cfg, "Configuration cannot be null"); |
116 | + this.deviceService = checkNotNull(deviceService, "Device service cannot be null"); | ||
88 | this.deviceProviderRegistry = checkNotNull(deviceProviderRegistry, "Device provider registry cannot be null"); | 117 | this.deviceProviderRegistry = checkNotNull(deviceProviderRegistry, "Device provider registry cannot be null"); |
89 | this.linkProviderRegistry = checkNotNull(linkProviderRegistry, "Link provider registry cannot be null"); | 118 | this.linkProviderRegistry = checkNotNull(linkProviderRegistry, "Link provider registry cannot be null"); |
90 | this.hostProviderRegistry = checkNotNull(hostProviderRegistry, "Host provider registry cannot be null"); | 119 | this.hostProviderRegistry = checkNotNull(hostProviderRegistry, "Host provider registry cannot be null"); |
... | @@ -94,56 +123,74 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { | ... | @@ -94,56 +123,74 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { |
94 | * Parses the given JSON and provides links as configured. | 123 | * Parses the given JSON and provides links as configured. |
95 | */ | 124 | */ |
96 | void parse() { | 125 | void parse() { |
126 | + try { | ||
127 | + register(); | ||
97 | parseDevices(); | 128 | parseDevices(); |
98 | parseLinks(); | 129 | parseLinks(); |
99 | parseHosts(); | 130 | parseHosts(); |
131 | + addMissingPorts(); | ||
132 | + } finally { | ||
133 | + unregister(); | ||
134 | + } | ||
135 | + } | ||
136 | + | ||
137 | + private void register() { | ||
138 | + deviceProviderService = deviceProviderRegistry.register(this); | ||
139 | + linkProviderService = linkProviderRegistry.register(this); | ||
140 | + hostProviderService = hostProviderRegistry.register(this); | ||
141 | + } | ||
142 | + | ||
143 | + private void unregister() { | ||
144 | + deviceProviderRegistry.unregister(this); | ||
145 | + linkProviderRegistry.unregister(this); | ||
146 | + hostProviderRegistry.unregister(this); | ||
100 | } | 147 | } |
101 | 148 | ||
102 | // Parses the given JSON and provides devices. | 149 | // Parses the given JSON and provides devices. |
103 | private void parseDevices() { | 150 | private void parseDevices() { |
104 | try { | 151 | try { |
105 | - DeviceProviderService dps = deviceProviderRegistry.register(this); | ||
106 | JsonNode nodes = cfg.get("devices"); | 152 | JsonNode nodes = cfg.get("devices"); |
107 | if (nodes != null) { | 153 | if (nodes != null) { |
154 | + prepareForDeviceEvents(nodes.size()); | ||
108 | for (JsonNode node : nodes) { | 155 | for (JsonNode node : nodes) { |
109 | - parseDevice(dps, node); | 156 | + parseDevice(node); |
110 | } | 157 | } |
111 | } | 158 | } |
112 | } finally { | 159 | } finally { |
113 | - deviceProviderRegistry.unregister(this); | 160 | + waitForDeviceEvents(); |
114 | } | 161 | } |
115 | } | 162 | } |
116 | 163 | ||
117 | // Parses the given node with device data and supplies the device. | 164 | // Parses the given node with device data and supplies the device. |
118 | - private void parseDevice(DeviceProviderService dps, JsonNode node) { | 165 | + private void parseDevice(JsonNode node) { |
119 | URI uri = URI.create(get(node, "uri")); | 166 | URI uri = URI.create(get(node, "uri")); |
120 | - Device.Type type = Device.Type.valueOf(get(node, "type")); | 167 | + Device.Type type = Device.Type.valueOf(get(node, "type", "SWITCH")); |
121 | - String mfr = get(node, "mfr"); | 168 | + String mfr = get(node, "mfr", UNKNOWN); |
122 | - String hw = get(node, "hw"); | 169 | + String hw = get(node, "hw", UNKNOWN); |
123 | - String sw = get(node, "sw"); | 170 | + String sw = get(node, "sw", UNKNOWN); |
124 | - String serial = get(node, "serial"); | 171 | + String serial = get(node, "serial", UNKNOWN); |
125 | - ChassisId cid = new ChassisId(get(node, "mac")); | 172 | + ChassisId cid = new ChassisId(get(node, "mac", "000000000000")); |
126 | SparseAnnotations annotations = annotations(node.get("annotations")); | 173 | SparseAnnotations annotations = annotations(node.get("annotations")); |
127 | 174 | ||
128 | DeviceDescription desc = | 175 | DeviceDescription desc = |
129 | new DefaultDeviceDescription(uri, type, mfr, hw, sw, serial, | 176 | new DefaultDeviceDescription(uri, type, mfr, hw, sw, serial, |
130 | cid, annotations); | 177 | cid, annotations); |
131 | DeviceId deviceId = deviceId(uri); | 178 | DeviceId deviceId = deviceId(uri); |
132 | - dps.deviceConnected(deviceId, desc); | 179 | + deviceProviderService.deviceConnected(deviceId, desc); |
133 | 180 | ||
134 | JsonNode ports = node.get("ports"); | 181 | JsonNode ports = node.get("ports"); |
135 | if (ports != null) { | 182 | if (ports != null) { |
136 | - parsePorts(dps, deviceId, ports); | 183 | + parsePorts(deviceId, ports); |
137 | } | 184 | } |
138 | } | 185 | } |
139 | 186 | ||
140 | // Parses the given node with list of device ports. | 187 | // Parses the given node with list of device ports. |
141 | - private void parsePorts(DeviceProviderService dps, DeviceId deviceId, JsonNode nodes) { | 188 | + private void parsePorts(DeviceId deviceId, JsonNode nodes) { |
142 | List<PortDescription> ports = new ArrayList<>(); | 189 | List<PortDescription> ports = new ArrayList<>(); |
143 | for (JsonNode node : nodes) { | 190 | for (JsonNode node : nodes) { |
144 | ports.add(parsePort(node)); | 191 | ports.add(parsePort(node)); |
145 | } | 192 | } |
146 | - dps.updatePorts(deviceId, ports); | 193 | + deviceProviderService.updatePorts(deviceId, ports); |
147 | } | 194 | } |
148 | 195 | ||
149 | // Parses the given node with port information. | 196 | // Parses the given node with port information. |
... | @@ -156,43 +203,41 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { | ... | @@ -156,43 +203,41 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { |
156 | 203 | ||
157 | // Parses the given JSON and provides links as configured. | 204 | // Parses the given JSON and provides links as configured. |
158 | private void parseLinks() { | 205 | private void parseLinks() { |
159 | - try { | ||
160 | - LinkProviderService lps = linkProviderRegistry.register(this); | ||
161 | JsonNode nodes = cfg.get("links"); | 206 | JsonNode nodes = cfg.get("links"); |
162 | if (nodes != null) { | 207 | if (nodes != null) { |
163 | for (JsonNode node : nodes) { | 208 | for (JsonNode node : nodes) { |
164 | - parseLink(lps, node, false); | 209 | + parseLink(node, false); |
165 | if (!node.has("halfplex")) { | 210 | if (!node.has("halfplex")) { |
166 | - parseLink(lps, node, true); | 211 | + parseLink(node, true); |
167 | - } | ||
168 | } | 212 | } |
169 | } | 213 | } |
170 | - } finally { | ||
171 | - linkProviderRegistry.unregister(this); | ||
172 | } | 214 | } |
173 | } | 215 | } |
174 | 216 | ||
175 | // Parses the given node with link data and supplies the link. | 217 | // Parses the given node with link data and supplies the link. |
176 | - private void parseLink(LinkProviderService lps, JsonNode node, boolean reverse) { | 218 | + private void parseLink(JsonNode node, boolean reverse) { |
177 | ConnectPoint src = connectPoint(get(node, "src")); | 219 | ConnectPoint src = connectPoint(get(node, "src")); |
178 | ConnectPoint dst = connectPoint(get(node, "dst")); | 220 | ConnectPoint dst = connectPoint(get(node, "dst")); |
179 | - Link.Type type = Link.Type.valueOf(get(node, "type")); | 221 | + Link.Type type = Link.Type.valueOf(get(node, "type", "DIRECT")); |
180 | SparseAnnotations annotations = annotations(node.get("annotations")); | 222 | SparseAnnotations annotations = annotations(node.get("annotations")); |
181 | 223 | ||
182 | DefaultLinkDescription desc = reverse ? | 224 | DefaultLinkDescription desc = reverse ? |
183 | new DefaultLinkDescription(dst, src, type, annotations) : | 225 | new DefaultLinkDescription(dst, src, type, annotations) : |
184 | new DefaultLinkDescription(src, dst, type, annotations); | 226 | new DefaultLinkDescription(src, dst, type, annotations); |
185 | - lps.linkDetected(desc); | 227 | + linkProviderService.linkDetected(desc); |
228 | + | ||
229 | + connectPoints.add(src); | ||
230 | + connectPoints.add(dst); | ||
186 | } | 231 | } |
187 | 232 | ||
188 | // Parses the given JSON and provides hosts as configured. | 233 | // Parses the given JSON and provides hosts as configured. |
189 | private void parseHosts() { | 234 | private void parseHosts() { |
190 | try { | 235 | try { |
191 | - HostProviderService hps = hostProviderRegistry.register(this); | ||
192 | JsonNode nodes = cfg.get("hosts"); | 236 | JsonNode nodes = cfg.get("hosts"); |
193 | if (nodes != null) { | 237 | if (nodes != null) { |
194 | for (JsonNode node : nodes) { | 238 | for (JsonNode node : nodes) { |
195 | - parseHost(hps, node); | 239 | + parseHost(node); |
240 | + parseHost(node); // FIXME: hack to make sure host positions take | ||
196 | } | 241 | } |
197 | } | 242 | } |
198 | } finally { | 243 | } finally { |
... | @@ -201,14 +246,14 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { | ... | @@ -201,14 +246,14 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { |
201 | } | 246 | } |
202 | 247 | ||
203 | // Parses the given node with host data and supplies the host. | 248 | // Parses the given node with host data and supplies the host. |
204 | - private void parseHost(HostProviderService hps, JsonNode node) { | 249 | + private void parseHost(JsonNode node) { |
205 | MacAddress mac = MacAddress.valueOf(get(node, "mac")); | 250 | MacAddress mac = MacAddress.valueOf(get(node, "mac")); |
206 | - VlanId vlanId = VlanId.vlanId(node.get("vlan").shortValue()); | 251 | + VlanId vlanId = VlanId.vlanId((short) node.get("vlan").asInt(VlanId.UNTAGGED)); |
207 | HostId hostId = HostId.hostId(mac, vlanId); | 252 | HostId hostId = HostId.hostId(mac, vlanId); |
208 | SparseAnnotations annotations = annotations(node.get("annotations")); | 253 | SparseAnnotations annotations = annotations(node.get("annotations")); |
209 | HostLocation location = new HostLocation(connectPoint(get(node, "location")), 0); | 254 | HostLocation location = new HostLocation(connectPoint(get(node, "location")), 0); |
210 | 255 | ||
211 | - String[] ipStrings = get(node, "ip").split(","); | 256 | + String[] ipStrings = get(node, "ip", "").split(","); |
212 | Set<IpAddress> ips = new HashSet<>(); | 257 | Set<IpAddress> ips = new HashSet<>(); |
213 | for (String ip : ipStrings) { | 258 | for (String ip : ipStrings) { |
214 | ips.add(IpAddress.valueOf(ip.trim())); | 259 | ips.add(IpAddress.valueOf(ip.trim())); |
... | @@ -216,9 +261,45 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { | ... | @@ -216,9 +261,45 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { |
216 | 261 | ||
217 | DefaultHostDescription desc = | 262 | DefaultHostDescription desc = |
218 | new DefaultHostDescription(mac, vlanId, location, ips, annotations); | 263 | new DefaultHostDescription(mac, vlanId, location, ips, annotations); |
219 | - hps.hostDetected(hostId, desc); | 264 | + hostProviderService.hostDetected(hostId, desc); |
265 | + | ||
266 | + connectPoints.add(location); | ||
267 | + } | ||
268 | + | ||
269 | + // Adds any missing device ports for configured links and host locations. | ||
270 | + private void addMissingPorts() { | ||
271 | + deviceService.getDevices().forEach(this::addMissingPorts); | ||
220 | } | 272 | } |
221 | 273 | ||
274 | + // Adds any missing device ports. | ||
275 | + private void addMissingPorts(Device device) { | ||
276 | + List<Port> ports = deviceService.getPorts(device.id()); | ||
277 | + Set<ConnectPoint> existing = ports.stream() | ||
278 | + .map(p -> new ConnectPoint(device.id(), p.number())) | ||
279 | + .collect(Collectors.toSet()); | ||
280 | + Set<ConnectPoint> missing = connectPoints.stream() | ||
281 | + .filter(cp -> !existing.contains(cp)) | ||
282 | + .collect(Collectors.toSet()); | ||
283 | + | ||
284 | + if (!missing.isEmpty()) { | ||
285 | + List<PortDescription> newPorts = Lists.newArrayList(); | ||
286 | + ports.forEach(p -> newPorts.add(description(p))); | ||
287 | + missing.forEach(cp -> newPorts.add(description(cp))); | ||
288 | + deviceProviderService.updatePorts(device.id(), newPorts); | ||
289 | + } | ||
290 | + } | ||
291 | + | ||
292 | + // Creates a port description from the specified port. | ||
293 | + private PortDescription description(Port p) { | ||
294 | + return new DefaultPortDescription(p.number(), p.isEnabled(), p.type(), p.portSpeed()); | ||
295 | + } | ||
296 | + | ||
297 | + // Creates a port description from the specified connection point. | ||
298 | + private PortDescription description(ConnectPoint cp) { | ||
299 | + return new DefaultPortDescription(cp.port(), true); | ||
300 | + } | ||
301 | + | ||
302 | + | ||
222 | // Produces set of annotations from the given JSON node. | 303 | // Produces set of annotations from the given JSON node. |
223 | private SparseAnnotations annotations(JsonNode node) { | 304 | private SparseAnnotations annotations(JsonNode node) { |
224 | if (node == null) { | 305 | if (node == null) { |
... | @@ -246,12 +327,18 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { | ... | @@ -246,12 +327,18 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { |
246 | return node.path(name).asText(); | 327 | return node.path(name).asText(); |
247 | } | 328 | } |
248 | 329 | ||
249 | - @Override | 330 | + // Returns string form of the named property in the given JSON object. |
250 | - public void triggerProbe(DeviceId deviceId) { | 331 | + private String get(JsonNode node, String name, String defaultValue) { |
332 | + return node.path(name).asText(defaultValue); | ||
251 | } | 333 | } |
252 | 334 | ||
253 | @Override | 335 | @Override |
254 | public void roleChanged(DeviceId device, MastershipRole newRole) { | 336 | public void roleChanged(DeviceId device, MastershipRole newRole) { |
337 | + deviceProviderService.receivedRoleReply(device, newRole, newRole); | ||
338 | + } | ||
339 | + | ||
340 | + @Override | ||
341 | + public void triggerProbe(DeviceId deviceId) { | ||
255 | } | 342 | } |
256 | 343 | ||
257 | @Override | 344 | @Override |
... | @@ -265,6 +352,40 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { | ... | @@ -265,6 +352,40 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider { |
265 | 352 | ||
266 | @Override | 353 | @Override |
267 | public boolean isReachable(DeviceId device) { | 354 | public boolean isReachable(DeviceId device) { |
268 | - return false; | 355 | + return true; |
269 | } | 356 | } |
357 | + | ||
358 | + /** | ||
359 | + * Prepares to count device added/available/removed events. | ||
360 | + * | ||
361 | + * @param count number of events to count | ||
362 | + */ | ||
363 | + protected void prepareForDeviceEvents(int count) { | ||
364 | + deviceLatch = new CountDownLatch(count); | ||
365 | + deviceService.addListener(deviceEventCounter); | ||
366 | + } | ||
367 | + | ||
368 | + /** | ||
369 | + * Waits for all expected device added/available/removed events. | ||
370 | + */ | ||
371 | + protected void waitForDeviceEvents() { | ||
372 | + try { | ||
373 | + deviceLatch.await(2, TimeUnit.SECONDS); | ||
374 | + } catch (InterruptedException e) { | ||
375 | + log.warn("Device events did not arrive in time"); | ||
376 | + } | ||
377 | + deviceService.removeListener(deviceEventCounter); | ||
378 | + } | ||
379 | + | ||
380 | + // Counts down number of device added/available/removed events. | ||
381 | + private class DeviceEventCounter implements DeviceListener { | ||
382 | + @Override | ||
383 | + public void event(DeviceEvent event) { | ||
384 | + DeviceEvent.Type type = event.type(); | ||
385 | + if (type == DEVICE_ADDED || type == DEVICE_AVAILABILITY_CHANGED) { | ||
386 | + deviceLatch.countDown(); | ||
387 | + } | ||
388 | + } | ||
389 | + } | ||
390 | + | ||
270 | } | 391 | } | ... | ... |
... | @@ -18,6 +18,7 @@ package org.onosproject.rest; | ... | @@ -18,6 +18,7 @@ package org.onosproject.rest; |
18 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | import com.fasterxml.jackson.databind.ObjectMapper; | 19 | import com.fasterxml.jackson.databind.ObjectMapper; |
20 | import org.onosproject.net.device.DeviceProviderRegistry; | 20 | import org.onosproject.net.device.DeviceProviderRegistry; |
21 | +import org.onosproject.net.device.DeviceService; | ||
21 | import org.onosproject.net.host.HostProviderRegistry; | 22 | import org.onosproject.net.host.HostProviderRegistry; |
22 | import org.onosproject.net.link.LinkProviderRegistry; | 23 | import org.onosproject.net.link.LinkProviderRegistry; |
23 | import org.onlab.rest.BaseResource; | 24 | import org.onlab.rest.BaseResource; |
... | @@ -40,9 +41,9 @@ import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; | ... | @@ -40,9 +41,9 @@ import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; |
40 | * devices, ports and links. | 41 | * devices, ports and links. |
41 | */ | 42 | */ |
42 | @Path("config") | 43 | @Path("config") |
43 | -public class ConfigResource extends BaseResource { | 44 | +public class ConfigWebResource extends BaseResource { |
44 | 45 | ||
45 | - private static Logger log = LoggerFactory.getLogger(ConfigResource.class); | 46 | + private static Logger log = LoggerFactory.getLogger(ConfigWebResource.class); |
46 | 47 | ||
47 | @POST | 48 | @POST |
48 | @Path("topology") | 49 | @Path("topology") |
... | @@ -52,7 +53,8 @@ public class ConfigResource extends BaseResource { | ... | @@ -52,7 +53,8 @@ public class ConfigResource extends BaseResource { |
52 | try { | 53 | try { |
53 | ObjectMapper mapper = new ObjectMapper(); | 54 | ObjectMapper mapper = new ObjectMapper(); |
54 | JsonNode cfg = mapper.readTree(input); | 55 | JsonNode cfg = mapper.readTree(input); |
55 | - new ConfigProvider(cfg, get(DeviceProviderRegistry.class), | 56 | + new ConfigProvider(cfg, get(DeviceService.class), |
57 | + get(DeviceProviderRegistry.class), | ||
56 | get(LinkProviderRegistry.class), | 58 | get(LinkProviderRegistry.class), |
57 | get(HostProviderRegistry.class)).parse(); | 59 | get(HostProviderRegistry.class)).parse(); |
58 | return Response.ok().build(); | 60 | return Response.ok().build(); | ... | ... |
... | @@ -72,7 +72,7 @@ | ... | @@ -72,7 +72,7 @@ |
72 | org.onosproject.rest.IntentsWebResource, | 72 | org.onosproject.rest.IntentsWebResource, |
73 | org.onosproject.rest.FlowsWebResource, | 73 | org.onosproject.rest.FlowsWebResource, |
74 | org.onosproject.rest.TopologyWebResource, | 74 | org.onosproject.rest.TopologyWebResource, |
75 | - org.onosproject.rest.ConfigResource, | 75 | + org.onosproject.rest.ConfigWebResource, |
76 | org.onosproject.rest.PathsWebResource | 76 | org.onosproject.rest.PathsWebResource |
77 | </param-value> | 77 | </param-value> |
78 | </init-param> | 78 | </init-param> | ... | ... |
-
Please register or login to post a comment