Committed by
Gerrit Code Review
Polling link provider
The provider is capable of polling the environment using the device driver behaviour (LinkDiscovery) Change-Id: Ia09f866299d38c4de9b13201c9cf63b03909164a
Showing
10 changed files
with
805 additions
and
0 deletions
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.net.behaviour; | ||
18 | + | ||
19 | +import org.onosproject.net.driver.HandlerBehaviour; | ||
20 | +import org.onosproject.net.link.LinkDescription; | ||
21 | + | ||
22 | +import java.util.Set; | ||
23 | + | ||
24 | +/** | ||
25 | + * A HandlerBehaviour to discover links. | ||
26 | + */ | ||
27 | +public interface LinkDiscovery extends HandlerBehaviour { | ||
28 | + | ||
29 | + | ||
30 | + /** | ||
31 | + * Returns set of discovered {@link LinkDescription}. | ||
32 | + * @return set of LinkDescription. | ||
33 | + */ | ||
34 | + Set<LinkDescription> getLinks(); | ||
35 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
providers/link/BUCK
0 → 100644
1 | +COMPILE_DEPS = [ | ||
2 | + '//lib:CORE_DEPS', | ||
3 | +] | ||
4 | + | ||
5 | +TEST_DEPS = [ | ||
6 | + '//lib:TEST_ADAPTERS', | ||
7 | + '//utils/osgi:onlab-osgi-tests', | ||
8 | +] | ||
9 | + | ||
10 | +osgi_jar_with_tests ( | ||
11 | + deps = COMPILE_DEPS, | ||
12 | + test_deps = TEST_DEPS, | ||
13 | +) | ||
14 | + | ||
15 | +onos_app ( | ||
16 | + app_name = 'org.onosproject.linkdiscovery', | ||
17 | + title = 'Link Discovery Provider', | ||
18 | + category = 'Provider', | ||
19 | + url = 'http://onosproject.org', | ||
20 | + description = 'ONOS link discovery provider.', | ||
21 | +) | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
providers/link/app.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | + | ||
3 | +<!-- | ||
4 | + ~ Copyright 2016-present Open Networking Laboratory | ||
5 | + ~ | ||
6 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
7 | + ~ you may not use this file except in compliance with the License. | ||
8 | + ~ You may obtain a copy of the License at | ||
9 | + ~ | ||
10 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
11 | + ~ | ||
12 | + ~ Unless required by applicable law or agreed to in writing, software | ||
13 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
14 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
15 | + ~ See the License for the specific language governing permissions and | ||
16 | + ~ limitations under the License. | ||
17 | + --> | ||
18 | +<app name="org.onosproject.linkdiscovery" origin="acino.eu" version="${project.version}" | ||
19 | + category="Provider" url="http://onosproject.org" title="ONOS link discovery provider" | ||
20 | + featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features" | ||
21 | + features="${project.artifactId}"> | ||
22 | + <description>${project.description}</description> | ||
23 | + <artifact>mvn:${project.groupId}/onos-linkdiscovery-provider/${project.version}</artifact> | ||
24 | +</app> |
providers/link/features.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
2 | + | ||
3 | +<!-- | ||
4 | + ~ Copyright 2016-present Open Networking Laboratory | ||
5 | + ~ | ||
6 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
7 | + ~ you may not use this file except in compliance with the License. | ||
8 | + ~ You may obtain a copy of the License at | ||
9 | + ~ | ||
10 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
11 | + ~ | ||
12 | + ~ Unless required by applicable law or agreed to in writing, software | ||
13 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
14 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
15 | + ~ See the License for the specific language governing permissions and | ||
16 | + ~ limitations under the License. | ||
17 | + --><features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}"> | ||
18 | + <feature name="${project.artifactId}" version="${project.version}" | ||
19 | + description="${project.description}"> | ||
20 | + <feature>onos-api</feature> | ||
21 | + <bundle>mvn:${project.groupId}/onos-linkdiscovery-provider/${project.version}</bundle> | ||
22 | + </feature> | ||
23 | +</features> | ||
24 | + |
providers/link/pom.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
2 | +<!-- | ||
3 | + ~ Copyright 2016-present Open Networking Laboratory | ||
4 | + ~ | ||
5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + ~ you may not use this file except in compliance with the License. | ||
7 | + ~ You may obtain a copy of the License at | ||
8 | + ~ | ||
9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + ~ | ||
11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + ~ See the License for the specific language governing permissions and | ||
15 | + ~ limitations under the License. | ||
16 | + --> | ||
17 | + | ||
18 | +<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
19 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
20 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
21 | + <modelVersion>4.0.0</modelVersion> | ||
22 | + | ||
23 | + <parent> | ||
24 | + <groupId>org.onosproject</groupId> | ||
25 | + <artifactId>onos-providers</artifactId> | ||
26 | + <version>1.7.0-SNAPSHOT</version> | ||
27 | + </parent> | ||
28 | + | ||
29 | + | ||
30 | + <artifactId>onos-linkdiscovery-provider</artifactId> | ||
31 | + <packaging>bundle</packaging> | ||
32 | + | ||
33 | + <properties> | ||
34 | + <onos.app.name>org.onosproject.linkdiscovery</onos.app.name> | ||
35 | + <onos.app.title>Link Discovery Provider</onos.app.title> | ||
36 | + <onos.app.origin>acino.eu</onos.app.origin> | ||
37 | + <onos.app.category>Provider</onos.app.category> | ||
38 | + <onos.app.readme>ONOS link discovery provider.</onos.app.readme> | ||
39 | + </properties> | ||
40 | + | ||
41 | + <description>ONOS link discovery provider</description> | ||
42 | + | ||
43 | + <dependencies> | ||
44 | + <dependency> | ||
45 | + <groupId>org.osgi</groupId> | ||
46 | + <artifactId>org.osgi.compendium</artifactId> | ||
47 | + </dependency> | ||
48 | + <dependency> | ||
49 | + <groupId>org.onosproject</groupId> | ||
50 | + <artifactId>onlab-osgi</artifactId> | ||
51 | + <version>${project.version}</version> | ||
52 | + <classifier>tests</classifier> | ||
53 | + <scope>test</scope> | ||
54 | + </dependency> | ||
55 | + <dependency> | ||
56 | + <groupId>org.onosproject</groupId> | ||
57 | + <artifactId>onlab-junit</artifactId> | ||
58 | + <scope>test</scope> | ||
59 | + </dependency> | ||
60 | + <dependency> | ||
61 | + <groupId>org.easymock</groupId> | ||
62 | + <artifactId>easymock</artifactId> | ||
63 | + <scope>test</scope> | ||
64 | + </dependency> | ||
65 | + <dependency> | ||
66 | + <groupId>org.onosproject</groupId> | ||
67 | + <artifactId>onos-api</artifactId> | ||
68 | + <classifier>tests</classifier> | ||
69 | + <scope>test</scope> | ||
70 | + </dependency> | ||
71 | + </dependencies> | ||
72 | + | ||
73 | +</project> | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
providers/link/src/main/java/org/onosproject/provider/linkdiscovery/impl/LinkDiscoveryProvider.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.provider.linkdiscovery.impl; | ||
18 | + | ||
19 | +import org.apache.felix.scr.annotations.Activate; | ||
20 | +import org.apache.felix.scr.annotations.Component; | ||
21 | +import org.apache.felix.scr.annotations.Deactivate; | ||
22 | +import org.apache.felix.scr.annotations.Modified; | ||
23 | +import org.apache.felix.scr.annotations.Property; | ||
24 | +import org.apache.felix.scr.annotations.Reference; | ||
25 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
26 | +import org.onosproject.cfg.ComponentConfigService; | ||
27 | +import org.onosproject.core.ApplicationId; | ||
28 | +import org.onosproject.core.CoreService; | ||
29 | +import org.onosproject.mastership.MastershipService; | ||
30 | +import org.onosproject.net.AnnotationKeys; | ||
31 | +import org.onosproject.net.DefaultAnnotations; | ||
32 | +import org.onosproject.net.Device; | ||
33 | +import org.onosproject.net.DeviceId; | ||
34 | +import org.onosproject.net.Link; | ||
35 | +import org.onosproject.net.behaviour.LinkDiscovery; | ||
36 | +import org.onosproject.net.device.DeviceEvent; | ||
37 | +import org.onosproject.net.device.DeviceListener; | ||
38 | +import org.onosproject.net.device.DeviceService; | ||
39 | +import org.onosproject.net.link.DefaultLinkDescription; | ||
40 | +import org.onosproject.net.link.LinkDescription; | ||
41 | +import org.onosproject.net.link.LinkProvider; | ||
42 | +import org.onosproject.net.link.LinkProviderRegistry; | ||
43 | +import org.onosproject.net.link.LinkProviderService; | ||
44 | +import org.onosproject.net.link.LinkService; | ||
45 | +import org.onosproject.net.provider.AbstractProvider; | ||
46 | +import org.onosproject.net.provider.ProviderId; | ||
47 | +import org.osgi.service.component.ComponentContext; | ||
48 | +import org.slf4j.Logger; | ||
49 | + | ||
50 | +import java.util.Dictionary; | ||
51 | +import java.util.HashSet; | ||
52 | +import java.util.Set; | ||
53 | +import java.util.concurrent.ScheduledExecutorService; | ||
54 | +import java.util.concurrent.ScheduledFuture; | ||
55 | +import java.util.stream.Collectors; | ||
56 | + | ||
57 | +import static com.google.common.base.Strings.isNullOrEmpty; | ||
58 | +import static java.util.concurrent.Executors.newScheduledThreadPool; | ||
59 | +import static java.util.concurrent.TimeUnit.SECONDS; | ||
60 | +import static org.onlab.util.Tools.get; | ||
61 | +import static org.onlab.util.Tools.groupedThreads; | ||
62 | +import static org.slf4j.LoggerFactory.getLogger; | ||
63 | + | ||
64 | +/** | ||
65 | + * Link provider capable of polling the environment using the device driver | ||
66 | + * {@link LinkDiscovery} behaviour. | ||
67 | + */ | ||
68 | +@Component(immediate = true) | ||
69 | +public class LinkDiscoveryProvider extends AbstractProvider | ||
70 | + implements LinkProvider { | ||
71 | + | ||
72 | + protected static final String APP_NAME = "org.onosproject.linkdiscovery"; | ||
73 | + protected static final String SCHEME_NAME = "linkdiscovery"; | ||
74 | + private static final String LINK_PROVIDER_PACKAGE = "org.onosproject.provider.linkdiscovery"; | ||
75 | + private final Logger log = getLogger(getClass()); | ||
76 | + private static final int DEFAULT_POLL_DELAY_SECONDS = 20; | ||
77 | + @Property(name = "linkPollDelaySeconds", intValue = DEFAULT_POLL_DELAY_SECONDS, | ||
78 | + label = "Initial delay (in seconds) for polling link discovery") | ||
79 | + protected static int linkPollDelaySeconds = DEFAULT_POLL_DELAY_SECONDS; | ||
80 | + private static final int DEFAULT_POLL_FREQUENCY_SECONDS = 10; | ||
81 | + @Property(name = "linkPollFrequencySeconds", intValue = DEFAULT_POLL_FREQUENCY_SECONDS, | ||
82 | + label = "Frequency (in seconds) for polling link discovery") | ||
83 | + protected static int linkPollFrequencySeconds = DEFAULT_POLL_FREQUENCY_SECONDS; | ||
84 | + | ||
85 | + | ||
86 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
87 | + protected LinkProviderRegistry providerRegistry; | ||
88 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
89 | + protected CoreService coreService; | ||
90 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
91 | + protected LinkService linkService; | ||
92 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
93 | + protected MastershipService mastershipService; | ||
94 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
95 | + protected DeviceService deviceService; | ||
96 | + protected ScheduledExecutorService executor = | ||
97 | + newScheduledThreadPool(2, groupedThreads("onos/netconf-link", | ||
98 | + "discovery-%d")); | ||
99 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
100 | + protected ComponentConfigService cfgService; | ||
101 | + | ||
102 | + protected LinkProviderService providerService; | ||
103 | + private InternalDeviceListener deviceListener = new InternalDeviceListener(); | ||
104 | + private ApplicationId appId; | ||
105 | + private ScheduledFuture<?> scheduledTask; | ||
106 | + | ||
107 | + /** | ||
108 | + * Creates a provider with the supplied identifier. | ||
109 | + */ | ||
110 | + public LinkDiscoveryProvider() { | ||
111 | + super(new ProviderId(SCHEME_NAME, LINK_PROVIDER_PACKAGE)); | ||
112 | + } | ||
113 | + | ||
114 | + @Activate | ||
115 | + public void activate(ComponentContext context) { | ||
116 | + providerService = providerRegistry.register(this); | ||
117 | + appId = coreService.registerApplication(APP_NAME); | ||
118 | + deviceService.addListener(deviceListener); | ||
119 | + cfgService.registerProperties(getClass()); | ||
120 | + | ||
121 | + if (context == null) { | ||
122 | + linkPollFrequencySeconds = DEFAULT_POLL_FREQUENCY_SECONDS; | ||
123 | + log.info("No component configuration"); | ||
124 | + } else { | ||
125 | + Dictionary<?, ?> properties = context.getProperties(); | ||
126 | + linkPollFrequencySeconds = | ||
127 | + getNewPollFrequency(properties, linkPollFrequencySeconds); | ||
128 | + } | ||
129 | + scheduledTask = schedulePolling(); | ||
130 | + log.info("Started"); | ||
131 | + } | ||
132 | + | ||
133 | + @Deactivate | ||
134 | + public void deactivate() { | ||
135 | + cfgService.unregisterProperties(getClass(), false); | ||
136 | + deviceService.removeListener(deviceListener); | ||
137 | + providerRegistry.unregister(this); | ||
138 | + providerService = null; | ||
139 | + scheduledTask.cancel(true); | ||
140 | + executor.shutdown(); | ||
141 | + log.info("Stopped"); | ||
142 | + } | ||
143 | + | ||
144 | + @Modified | ||
145 | + public void modified(ComponentContext context) { | ||
146 | + if (context == null) { | ||
147 | + log.info("No component configuration"); | ||
148 | + return; | ||
149 | + } else { | ||
150 | + Dictionary<?, ?> properties = context.getProperties(); | ||
151 | + | ||
152 | + int newPollFrequency = getNewPollFrequency(properties, linkPollFrequencySeconds); | ||
153 | + int newPollDelay = getNewPollDealy(properties, linkPollDelaySeconds); | ||
154 | + if (newPollFrequency != linkPollFrequencySeconds || | ||
155 | + newPollDelay != linkPollDelaySeconds) { | ||
156 | + linkPollFrequencySeconds = newPollFrequency; | ||
157 | + linkPollDelaySeconds = newPollDelay; | ||
158 | + //stops the old scheduled task | ||
159 | + scheduledTask.cancel(true); | ||
160 | + //schedules new task at the new polling rate | ||
161 | + scheduledTask = schedulePolling(); | ||
162 | + } | ||
163 | + } | ||
164 | + log.info("Modified"); | ||
165 | + } | ||
166 | + | ||
167 | + private int getNewPollFrequency(Dictionary<?, ?> properties, int pollFrequency) { | ||
168 | + int newPollFrequency; | ||
169 | + try { | ||
170 | + String s = get(properties, "linkPollFrequencySeconds"); | ||
171 | + newPollFrequency = isNullOrEmpty(s) ? pollFrequency : Integer.parseInt(s.trim()); | ||
172 | + } catch (NumberFormatException | ClassCastException e) { | ||
173 | + newPollFrequency = DEFAULT_POLL_FREQUENCY_SECONDS; | ||
174 | + } | ||
175 | + return newPollFrequency; | ||
176 | + } | ||
177 | + | ||
178 | + private int getNewPollDealy(Dictionary<?, ?> properties, int pollDelay) { | ||
179 | + int newPollFrequency; | ||
180 | + try { | ||
181 | + String s = get(properties, "linkPollDelaySeconds"); | ||
182 | + newPollFrequency = isNullOrEmpty(s) ? pollDelay : Integer.parseInt(s.trim()); | ||
183 | + } catch (NumberFormatException | ClassCastException e) { | ||
184 | + newPollFrequency = DEFAULT_POLL_DELAY_SECONDS; | ||
185 | + } | ||
186 | + return newPollFrequency; | ||
187 | + } | ||
188 | + | ||
189 | + private ScheduledFuture schedulePolling() { | ||
190 | + return executor.scheduleAtFixedRate(this::discoverLinksTasks, | ||
191 | + linkPollDelaySeconds, | ||
192 | + linkPollFrequencySeconds, | ||
193 | + SECONDS); | ||
194 | + } | ||
195 | + | ||
196 | + private void discoverLinksTasks() { | ||
197 | + deviceService.getAvailableDevices().forEach(device -> { | ||
198 | + if (isSupported(device)) { | ||
199 | + evaluateLinks(device.id(), device.as(LinkDiscovery.class).getLinks()); | ||
200 | + } | ||
201 | + }); | ||
202 | + } | ||
203 | + | ||
204 | + private void evaluateLinks(DeviceId deviceId, Set<LinkDescription> discoveredLinksDesc) { | ||
205 | + //The provider will get only existing links related to LinkDiscovery | ||
206 | + Set<Link> storedLinks = linkService.getDeviceEgressLinks(deviceId) | ||
207 | + .stream() | ||
208 | + .filter(link -> { | ||
209 | + String value = link.annotations().value(AnnotationKeys.PROTOCOL); | ||
210 | + if (value != null && value.equals(SCHEME_NAME.toUpperCase())) { | ||
211 | + return true; | ||
212 | + } | ||
213 | + return false; | ||
214 | + }) | ||
215 | + .collect(Collectors.toSet()); | ||
216 | + | ||
217 | + //Convert Link to LinkDescription for comparison | ||
218 | + Set<LinkDescription> storedLinkDescs = new HashSet<>(); | ||
219 | + storedLinks.forEach(link -> storedLinkDescs | ||
220 | + .add(new DefaultLinkDescription( | ||
221 | + link.src(), link.dst(), link.type(), link.isExpected(), | ||
222 | + DefaultAnnotations.builder().putAll(link.annotations()).build()))); | ||
223 | + log.debug("Current stored links provider related {}", storedLinks); | ||
224 | + | ||
225 | + //Add the correct annotation for comparison | ||
226 | + Set<LinkDescription> discoveredLinkDescsAnn = new HashSet<>(); | ||
227 | + | ||
228 | + discoveredLinksDesc.forEach(linkDesc -> discoveredLinkDescsAnn | ||
229 | + .add(new DefaultLinkDescription( | ||
230 | + linkDesc.src(), linkDesc.dst(), linkDesc.type(), false, | ||
231 | + DefaultAnnotations.builder().putAll(linkDesc.annotations()) | ||
232 | + .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase()) | ||
233 | + .build()))); | ||
234 | + | ||
235 | + Set<LinkDescription> linkDescsToBeRemoved = new HashSet<>(storedLinkDescs); | ||
236 | + linkDescsToBeRemoved.removeAll(discoveredLinkDescsAnn); | ||
237 | + log.debug("Links to be removed {}", linkDescsToBeRemoved); | ||
238 | + linkDescsToBeRemoved.forEach(linkDesc -> | ||
239 | + providerService.linkVanished(linkDesc)); | ||
240 | + | ||
241 | + Set<LinkDescription> linksToBeAdded = new HashSet<>(discoveredLinkDescsAnn); | ||
242 | + linksToBeAdded.removeAll(storedLinkDescs); | ||
243 | + log.debug("Links to be added {}", linksToBeAdded); | ||
244 | + linksToBeAdded.forEach(linkDesc -> providerService.linkDetected(linkDesc) | ||
245 | + ); | ||
246 | + } | ||
247 | + | ||
248 | + protected boolean isSupported(Device device) { | ||
249 | + boolean supported = mastershipService.isLocalMaster(device.id()) | ||
250 | + && device.is(LinkDiscovery.class); | ||
251 | + if (!supported) { | ||
252 | + log.debug("Device {} does not support LinkDiscovery", device); | ||
253 | + } | ||
254 | + return supported; | ||
255 | + } | ||
256 | + | ||
257 | + /** | ||
258 | + * Listener for core device events. | ||
259 | + */ | ||
260 | + private class InternalDeviceListener implements DeviceListener { | ||
261 | + @Override | ||
262 | + public void event(DeviceEvent event) { | ||
263 | + if ((event.type() == DeviceEvent.Type.DEVICE_ADDED)) { | ||
264 | + executor.execute(() -> event.subject().as(LinkDiscovery.class).getLinks() | ||
265 | + .forEach(linkDesc -> { | ||
266 | + providerService.linkDetected(new DefaultLinkDescription( | ||
267 | + linkDesc.src(), linkDesc.dst(), linkDesc.type(), false, | ||
268 | + DefaultAnnotations.builder() | ||
269 | + .putAll(linkDesc.annotations()) | ||
270 | + .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase()) | ||
271 | + .build())); | ||
272 | + })); | ||
273 | + } | ||
274 | + } | ||
275 | + | ||
276 | + @Override | ||
277 | + public boolean isRelevant(DeviceEvent event) { | ||
278 | + return isSupported(event.subject()); | ||
279 | + } | ||
280 | + } | ||
281 | +} |
providers/link/src/main/java/org/onosproject/provider/linkdiscovery/impl/package-info.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2016-present 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 | + * Provider that uses LinkDiscovery {@link org.onosproject.net.behaviour.LinkDiscovery} | ||
19 | + * to poll the network environment as a means of link discovery. | ||
20 | + */ | ||
21 | +package org.onosproject.provider.linkdiscovery.impl; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * Copyright 2016-present 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.linkdiscovery.impl; | ||
17 | + | ||
18 | +import com.google.common.collect.ImmutableSet; | ||
19 | +import org.junit.Before; | ||
20 | +import org.junit.Test; | ||
21 | +import org.onlab.osgi.ComponentContextAdapter; | ||
22 | +import org.onlab.packet.ChassisId; | ||
23 | +import org.onosproject.cfg.ComponentConfigAdapter; | ||
24 | +import org.onosproject.core.ApplicationId; | ||
25 | +import org.onosproject.core.CoreService; | ||
26 | +import org.onosproject.core.DefaultApplicationId; | ||
27 | +import org.onosproject.mastership.MastershipService; | ||
28 | +import org.onosproject.mastership.MastershipServiceAdapter; | ||
29 | +import org.onosproject.net.AbstractProjectableModel; | ||
30 | +import org.onosproject.net.AnnotationKeys; | ||
31 | +import org.onosproject.net.Annotations; | ||
32 | +import org.onosproject.net.ConnectPoint; | ||
33 | +import org.onosproject.net.DefaultAnnotations; | ||
34 | +import org.onosproject.net.DefaultDevice; | ||
35 | +import org.onosproject.net.DefaultLink; | ||
36 | +import org.onosproject.net.Device; | ||
37 | +import org.onosproject.net.DeviceId; | ||
38 | +import org.onosproject.net.Link; | ||
39 | +import org.onosproject.net.LinkKey; | ||
40 | +import org.onosproject.net.PortNumber; | ||
41 | +import org.onosproject.net.behaviour.LinkDiscovery; | ||
42 | +import org.onosproject.net.device.DeviceListener; | ||
43 | +import org.onosproject.net.device.DeviceServiceAdapter; | ||
44 | +import org.onosproject.net.driver.AbstractHandlerBehaviour; | ||
45 | +import org.onosproject.net.driver.Behaviour; | ||
46 | +import org.onosproject.net.driver.Driver; | ||
47 | +import org.onosproject.net.driver.DriverAdapter; | ||
48 | +import org.onosproject.net.driver.DriverHandler; | ||
49 | +import org.onosproject.net.driver.DriverServiceAdapter; | ||
50 | +import org.onosproject.net.link.DefaultLinkDescription; | ||
51 | +import org.onosproject.net.link.LinkDescription; | ||
52 | +import org.onosproject.net.link.LinkProviderRegistryAdapter; | ||
53 | +import org.onosproject.net.link.LinkProviderServiceAdapter; | ||
54 | +import org.onosproject.net.link.LinkServiceAdapter; | ||
55 | +import org.onosproject.net.provider.ProviderId; | ||
56 | + | ||
57 | +import java.util.Dictionary; | ||
58 | +import java.util.HashSet; | ||
59 | +import java.util.Hashtable; | ||
60 | +import java.util.Set; | ||
61 | + | ||
62 | +import static org.easymock.EasyMock.*; | ||
63 | +import static org.junit.Assert.*; | ||
64 | +import static org.onlab.junit.TestTools.assertAfter; | ||
65 | +import static org.onosproject.provider.linkdiscovery.impl.LinkDiscoveryProvider.APP_NAME; | ||
66 | +import static org.onosproject.provider.linkdiscovery.impl.LinkDiscoveryProvider.SCHEME_NAME; | ||
67 | + | ||
68 | +/** | ||
69 | + * Test for polling mechanism of the NetconfLinkProvider. | ||
70 | + */ | ||
71 | +public class LinkDiscoveryProviderTest { | ||
72 | + | ||
73 | + private static final ComponentContextAdapter CONTEXT = | ||
74 | + new ComponentContextAdapter() { | ||
75 | + @Override | ||
76 | + public Dictionary getProperties() { | ||
77 | + Hashtable<String, Integer> props = new Hashtable<>(); | ||
78 | + props.put("linkPollFrequencySeconds", 2); | ||
79 | + props.put("linkPollDelaySeconds", 1); | ||
80 | + return props; | ||
81 | + } | ||
82 | + }; | ||
83 | + // Network Mocks | ||
84 | + private static final DeviceId DEVICE_ID_1 = DeviceId.deviceId("netconf:1.1.1.1"); | ||
85 | + private static final DeviceId DEVICE_ID_2 = DeviceId.deviceId("netconf:1.1.1.2"); | ||
86 | + private static final ConnectPoint CP11 = new ConnectPoint(DEVICE_ID_1, PortNumber.portNumber(1)); | ||
87 | + private static final ConnectPoint CP12 = new ConnectPoint(DEVICE_ID_1, PortNumber.portNumber(2)); | ||
88 | + private static final ConnectPoint CP13 = new ConnectPoint(DEVICE_ID_1, PortNumber.portNumber(3)); | ||
89 | + private static final ConnectPoint CP14 = new ConnectPoint(DEVICE_ID_1, PortNumber.portNumber(4)); | ||
90 | + private static final ConnectPoint CP21 = new ConnectPoint(DEVICE_ID_2, PortNumber.portNumber(1)); | ||
91 | + private static final ConnectPoint CP22 = new ConnectPoint(DEVICE_ID_2, PortNumber.portNumber(2)); | ||
92 | + private static final ConnectPoint CP23 = new ConnectPoint(DEVICE_ID_2, PortNumber.portNumber(3)); | ||
93 | + private static final ConnectPoint CP24 = new ConnectPoint(DEVICE_ID_2, PortNumber.portNumber(4)); | ||
94 | + private static final DefaultAnnotations DEVICE_ANNOTATIONS = DefaultAnnotations.builder() | ||
95 | + .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase()).build(); | ||
96 | + private static final DefaultAnnotations LINK_ANNOTATIONS = DefaultAnnotations.builder() | ||
97 | + .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase()).build(); | ||
98 | + private static final LinkKey LINKKEY1 = LinkKey.linkKey(CP11, CP21); | ||
99 | + private static final LinkDescription LINK1 = new DefaultLinkDescription(CP11, CP21, | ||
100 | + Link.Type.DIRECT, | ||
101 | + LINK_ANNOTATIONS); | ||
102 | + private static final LinkKey LINKKEY2 = LinkKey.linkKey(CP12, CP22); | ||
103 | + private static final LinkDescription LINK2 = new DefaultLinkDescription(CP12, CP22, | ||
104 | + Link.Type.DIRECT, | ||
105 | + LINK_ANNOTATIONS); | ||
106 | + private static final LinkKey LINKKEY3 = LinkKey.linkKey(CP13, CP23); | ||
107 | + private static final LinkDescription LINK3 = new DefaultLinkDescription(CP13, CP23, | ||
108 | + Link.Type.DIRECT, | ||
109 | + DefaultAnnotations.builder() | ||
110 | + .build()); | ||
111 | + private static final LinkKey LINKKEY4 = LinkKey.linkKey(CP14, CP24); | ||
112 | + private static final LinkDescription LINK4 = new DefaultLinkDescription(CP14, CP24, | ||
113 | + Link.Type.DIRECT, | ||
114 | + DefaultAnnotations.builder().build()); | ||
115 | + //Service Mocks | ||
116 | + private final MockDeviceService deviceService = new MockDeviceService(); | ||
117 | + private final LinkProviderRegistryAdapter linkRegistry = new LinkProviderRegistryAdapter(); | ||
118 | + private final MastershipService mastershipService = new MockMastershipService(); | ||
119 | + private final MockLinkService linkService = new MockLinkService(); | ||
120 | + private final Driver driver = new MockDriver(); | ||
121 | + //Provider related classes | ||
122 | + private LinkProviderServiceAdapter providerService; | ||
123 | + private CoreService coreService; | ||
124 | + private LinkDiscoveryProvider provider = new LinkDiscoveryProvider(); | ||
125 | + private final Device device1 = new MockDevice(provider.id(), DEVICE_ID_1, Device.Type.SWITCH, | ||
126 | + "foo.inc", "0", "0", "0", new ChassisId(), | ||
127 | + DEVICE_ANNOTATIONS); | ||
128 | + private Set<DeviceListener> deviceListeners = new HashSet<>(); | ||
129 | + private ApplicationId appId = | ||
130 | + new DefaultApplicationId(100, APP_NAME); | ||
131 | + private TestLink testLink = new TestLink(); | ||
132 | + | ||
133 | + @Before | ||
134 | + public void setUp() { | ||
135 | + coreService = createMock(CoreService.class); | ||
136 | + expect(coreService.registerApplication(appId.name())) | ||
137 | + .andReturn(appId).anyTimes(); | ||
138 | + replay(coreService); | ||
139 | + provider.coreService = coreService; | ||
140 | + provider.providerRegistry = linkRegistry; | ||
141 | + provider.deviceService = deviceService; | ||
142 | + provider.mastershipService = mastershipService; | ||
143 | + provider.linkService = linkService; | ||
144 | + provider.cfgService = new ComponentConfigAdapter(); | ||
145 | + AbstractProjectableModel.setDriverService(null, new DriverServiceAdapter()); | ||
146 | + provider.activate(null); | ||
147 | + providerService = linkRegistry.registeredProvider(); | ||
148 | + } | ||
149 | + | ||
150 | + @Test | ||
151 | + public void activate() throws Exception { | ||
152 | + assertFalse("Provider should be registered", linkRegistry.getProviders().contains(provider)); | ||
153 | + assertEquals("Device service should be registered", provider.deviceService, deviceService); | ||
154 | + assertEquals("Device listener should be added", 1, deviceListeners.size()); | ||
155 | + assertNotNull("Registration expected", providerService); | ||
156 | + assertEquals("Incorrect provider", provider, providerService.provider()); | ||
157 | + assertFalse("Executor should be running", provider.executor.isShutdown()); | ||
158 | + assertFalse("Executor should be running", provider.executor.isTerminated()); | ||
159 | + assertEquals("Incorrect polling frequency, should be default", 10, | ||
160 | + provider.linkPollFrequencySeconds); | ||
161 | + assertEquals("Incorrect polling delay , should be default", 20, | ||
162 | + provider.linkPollDelaySeconds); | ||
163 | + } | ||
164 | + | ||
165 | + @Test | ||
166 | + public void modified() throws Exception { | ||
167 | + provider.modified(CONTEXT); | ||
168 | + assertEquals("Incorrect polling frequency, should be default", 2, | ||
169 | + provider.linkPollFrequencySeconds); | ||
170 | + assertEquals("Incorrect polling delay , should be default", 1, | ||
171 | + provider.linkPollDelaySeconds); | ||
172 | + | ||
173 | + } | ||
174 | + | ||
175 | + | ||
176 | + @Test | ||
177 | + public void deactivate() throws Exception { | ||
178 | + provider.deactivate(); | ||
179 | + assertEquals("Device listener should be removed", 0, deviceListeners.size()); | ||
180 | + assertFalse("Provider should not be registered", linkRegistry.getProviders().contains(provider)); | ||
181 | + assertTrue(provider.executor.isShutdown()); | ||
182 | + assertNull(provider.providerService); | ||
183 | + } | ||
184 | + | ||
185 | + | ||
186 | + @Test | ||
187 | + public void linksTestForStoredDevice() { | ||
188 | + provider.modified(CONTEXT); | ||
189 | + providerService.discoveredLinkDescriptions().put(LINKKEY1, LINK1); | ||
190 | + providerService.discoveredLinkDescriptions().put(LINKKEY2, LINK2); | ||
191 | + providerService.discoveredLinkDescriptions().put(LINKKEY4, LINK4); | ||
192 | + testLink.addLinkDesc(LINK2); | ||
193 | + testLink.addLinkDesc(LINK3); | ||
194 | + assertAfter(1100, () -> { | ||
195 | + assertEquals("Total number of link must be 3", 3, providerService.discoveredLinkDescriptions().size()); | ||
196 | + assertFalse("Link1 should be removed", | ||
197 | + providerService.discoveredLinkDescriptions().containsKey(LINKKEY1)); | ||
198 | + assertTrue("Link2 should be present", | ||
199 | + providerService.discoveredLinkDescriptions().containsKey(LINKKEY2)); | ||
200 | + assertTrue("Link3 should be added", | ||
201 | + providerService.discoveredLinkDescriptions().containsKey(LINKKEY3)); | ||
202 | + assertEquals("Link3 should be annotated", SCHEME_NAME.toUpperCase(), | ||
203 | + providerService.discoveredLinkDescriptions() | ||
204 | + .get(LINKKEY3).annotations().value(AnnotationKeys.PROTOCOL)); | ||
205 | + assertTrue("Link4 should be present because it is not related to the LinkDiscovery", | ||
206 | + providerService.discoveredLinkDescriptions().containsKey(LINKKEY4)); | ||
207 | + | ||
208 | + }); | ||
209 | + clear(); | ||
210 | + } | ||
211 | + | ||
212 | + private void clear() { | ||
213 | + testLink.clearLinkDesc(); | ||
214 | + providerService.discoveredLinkDescriptions().clear(); | ||
215 | + providerService.discoveredLinks().clear(); | ||
216 | + } | ||
217 | + | ||
218 | + private class MockDeviceService extends DeviceServiceAdapter { | ||
219 | + | ||
220 | + @Override | ||
221 | + public Iterable<Device> getAvailableDevices() { | ||
222 | + return ImmutableSet.of(device1); | ||
223 | + } | ||
224 | + | ||
225 | + @Override | ||
226 | + public void addListener(DeviceListener listener) { | ||
227 | + deviceListeners.add(listener); | ||
228 | + } | ||
229 | + | ||
230 | + @Override | ||
231 | + public void removeListener(DeviceListener listener) { | ||
232 | + deviceListeners.remove(listener); | ||
233 | + } | ||
234 | + } | ||
235 | + | ||
236 | + private class MockMastershipService extends MastershipServiceAdapter { | ||
237 | + | ||
238 | + @Override | ||
239 | + public boolean isLocalMaster(DeviceId deviceId) { | ||
240 | + return true; | ||
241 | + } | ||
242 | + } | ||
243 | + | ||
244 | + private class MockLinkService extends LinkServiceAdapter { | ||
245 | + @Override | ||
246 | + public Set<Link> getDeviceEgressLinks(DeviceId deviceId) { | ||
247 | + Set<Link> links = new HashSet<>(); | ||
248 | + providerService.discoveredLinkDescriptions().values() | ||
249 | + .forEach(x -> links.add(DefaultLink.builder() | ||
250 | + .providerId(provider.id()) | ||
251 | + .src(x.src()) | ||
252 | + .dst(x.dst()) | ||
253 | + .type(x.type()) | ||
254 | + .isExpected(x.isExpected()) | ||
255 | + .annotations(x.annotations()).build())); | ||
256 | + return ImmutableSet.copyOf(links); | ||
257 | + } | ||
258 | + } | ||
259 | + | ||
260 | + private class MockDevice extends DefaultDevice { | ||
261 | + | ||
262 | + public MockDevice(ProviderId providerId, DeviceId id, Type type, | ||
263 | + String manufacturer, String hwVersion, String swVersion, | ||
264 | + String serialNumber, ChassisId chassisId, Annotations... annotations) { | ||
265 | + super(providerId, id, type, manufacturer, hwVersion, swVersion, serialNumber, | ||
266 | + chassisId, annotations); | ||
267 | + } | ||
268 | + | ||
269 | + @Override | ||
270 | + protected Driver locateDriver() { | ||
271 | + return driver; | ||
272 | + } | ||
273 | + | ||
274 | + @Override | ||
275 | + public Driver driver() { | ||
276 | + return driver; | ||
277 | + } | ||
278 | + } | ||
279 | + | ||
280 | + private class MockDriver extends DriverAdapter { | ||
281 | + @Override | ||
282 | + public <T extends Behaviour> T createBehaviour(DriverHandler handler, Class<T> behaviourClass) { | ||
283 | + | ||
284 | + return (T) testLink; | ||
285 | + } | ||
286 | + } | ||
287 | + | ||
288 | + private class TestLink extends AbstractHandlerBehaviour implements LinkDiscovery { | ||
289 | + Set<LinkDescription> linkDescriptions = new HashSet<>(); | ||
290 | + | ||
291 | + @Override | ||
292 | + public Set<LinkDescription> getLinks() { | ||
293 | + return ImmutableSet.copyOf(linkDescriptions); | ||
294 | + } | ||
295 | + | ||
296 | + private void addLinkDesc(LinkDescription link) { | ||
297 | + linkDescriptions.add(link); | ||
298 | + } | ||
299 | + | ||
300 | + private void clearLinkDesc() { | ||
301 | + linkDescriptions.clear(); | ||
302 | + } | ||
303 | + | ||
304 | + } | ||
305 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
providers/link/src/test/java/org/onosproject/provider/linkdiscovery/impl/package-info.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2016-present 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 | + * Test package for the Link Discovery Provider. | ||
19 | + */ | ||
20 | +package org.onosproject.provider.linkdiscovery.impl; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or login to post a comment