Ayaka Koshibe
Committed by Gerrit Code Review

NullLinkProvider to generate link events. This provider

currently chains null devices together in a linear topology.

The tunable parameters for this provider are:
  - flicker = [default false]  : flap the links by sending LinkEvents
  - eventRate = [default 3000] : time between LinkEvents, in msec

Reference: ONOS-446

Change-Id: I865c1c43c3216d9b64d67bda7c118bb041d5b1c9
...@@ -31,4 +31,11 @@ ...@@ -31,4 +31,11 @@
31 31
32 <description>ONOS Null link provider</description> 32 <description>ONOS Null link provider</description>
33 33
34 + <dependencies>
35 + <dependency>
36 + <groupId>org.osgi</groupId>
37 + <artifactId>org.osgi.compendium</artifactId>
38 + </dependency>
39 + </dependencies>
40 +
34 </project> 41 </project>
......
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.link.impl;
17 +
18 +import static com.google.common.base.Strings.isNullOrEmpty;
19 +import static org.onlab.util.Tools.delay;
20 +import static org.onlab.util.Tools.namedThreads;
21 +import static org.slf4j.LoggerFactory.getLogger;
22 +
23 +import java.util.Dictionary;
24 +import java.util.List;
25 +import java.util.concurrent.ConcurrentMap;
26 +import java.util.concurrent.ExecutorService;
27 +import java.util.concurrent.Executors;
28 +import java.util.concurrent.TimeUnit;
29 +
30 +import org.apache.felix.scr.annotations.Activate;
31 +import org.apache.felix.scr.annotations.Component;
32 +import org.apache.felix.scr.annotations.Deactivate;
33 +import org.apache.felix.scr.annotations.Property;
34 +import org.apache.felix.scr.annotations.Reference;
35 +import org.apache.felix.scr.annotations.ReferenceCardinality;
36 +import org.onosproject.net.ConnectPoint;
37 +import org.onosproject.net.Device;
38 +import org.onosproject.net.DeviceId;
39 +import org.onosproject.net.Link;
40 +import org.onosproject.net.PortNumber;
41 +import org.onosproject.net.device.DeviceEvent;
42 +import org.onosproject.net.device.DeviceListener;
43 +import org.onosproject.net.device.DeviceService;
44 +import org.onosproject.net.link.DefaultLinkDescription;
45 +import org.onosproject.net.link.LinkDescription;
46 +import org.onosproject.net.link.LinkProvider;
47 +import org.onosproject.net.link.LinkProviderRegistry;
48 +import org.onosproject.net.link.LinkProviderService;
49 +import org.onosproject.net.provider.AbstractProvider;
50 +import org.onosproject.net.provider.ProviderId;
51 +import org.osgi.service.component.ComponentContext;
52 +import org.slf4j.Logger;
53 +
54 +import com.google.common.collect.Lists;
55 +import com.google.common.collect.Maps;
56 +
57 +/**
58 + * Provider which advertises fake/nonexistent links to the core. To be used for
59 + * benchmarking only.
60 + */
61 +@Component(immediate = true)
62 +public class NullLinkProvider extends AbstractProvider implements LinkProvider {
63 +
64 + private final Logger log = getLogger(getClass());
65 +
66 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
67 + protected DeviceService deviceService;
68 +
69 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
70 + protected LinkProviderRegistry providerRegistry;
71 +
72 + private LinkProviderService providerService;
73 +
74 + private static final boolean FLICKER = false;
75 + private static final int DEFAULT_RATE = 3000;
76 + // For now, static switch port values
77 + private static final PortNumber SRCPORT = PortNumber.portNumber(5);
78 + private static final PortNumber DSTPORT = PortNumber.portNumber(6);
79 +
80 + private final InternalLinkProvider linkProvider = new InternalLinkProvider();
81 +
82 + // Link descriptions
83 + private final ConcurrentMap<ConnectPoint, LinkDescription> descriptions = Maps
84 + .newConcurrentMap();
85 +
86 + // Device ID's that have been seen so far
87 + private final List<DeviceId> devices = Lists.newArrayList();
88 +
89 + private ExecutorService linkDriver = Executors.newFixedThreadPool(1,
90 + namedThreads("null-link-driver"));
91 +
92 + // If true, 'flickers' links by alternating link up/down events at eventRate
93 + @Property(name = "flicker", boolValue = FLICKER,
94 + label = "Setting to flap links")
95 + private boolean flicker = FLICKER;
96 +
97 + // For flicker = true, duration between events in msec.
98 + @Property(name = "eventRate", intValue = DEFAULT_RATE,
99 + label = "Duration between Link Event")
100 + private int eventRate = 3000;
101 +
102 + public NullLinkProvider() {
103 + super(new ProviderId("null", "org.onosproject.provider.nil"));
104 + }
105 +
106 + @Activate
107 + public void activate(ComponentContext context) {
108 + providerService = providerRegistry.register(this);
109 + deviceService.addListener(linkProvider);
110 + modified(context);
111 + if (flicker) {
112 + linkDriver.submit(new LinkDriver());
113 + }
114 + log.info("started");
115 + }
116 +
117 + @Deactivate
118 + public void deactivate(ComponentContext context) {
119 + if (flicker) {
120 + try {
121 + linkDriver.awaitTermination(1000, TimeUnit.MILLISECONDS);
122 + } catch (InterruptedException e) {
123 + log.error("LinkBuilder did not terminate");
124 + }
125 + linkDriver.shutdownNow();
126 + }
127 + deviceService.removeListener(linkProvider);
128 + providerRegistry.unregister(this);
129 + deviceService = null;
130 +
131 + log.info("stopped");
132 + }
133 +
134 + public void modified(ComponentContext context) {
135 + if (context == null) {
136 + log.info("No configs, using defaults: flicker={}, eventRate={}",
137 + FLICKER, DEFAULT_RATE);
138 + return;
139 + }
140 + Dictionary<?, ?> properties = context.getProperties();
141 +
142 + boolean flickSetting;
143 + int newRate;
144 + try {
145 + String s = (String) properties.get("flicker");
146 + flickSetting = isNullOrEmpty(s) ? flicker : Boolean.valueOf(s);
147 + s = (String) properties.get("eventRate");
148 + newRate = isNullOrEmpty(s) ? eventRate : Integer.valueOf(s);
149 + } catch (Exception e) {
150 + log.warn(e.getMessage());
151 + flickSetting = flicker;
152 + newRate = eventRate;
153 + }
154 +
155 + if (flicker != flickSetting) {
156 + flicker = flickSetting;
157 + }
158 +
159 + if (flicker) {
160 + if (eventRate != newRate) {
161 + eventRate = newRate;
162 + }
163 + linkDriver.submit(new LinkDriver());
164 + }
165 + log.info("Using new settings: flicker={}, eventRate={}", flicker,
166 + eventRate);
167 + }
168 +
169 + /**
170 + * Adds links as devices are found, and generates LinkEvents.
171 + */
172 + private class InternalLinkProvider implements DeviceListener {
173 +
174 + @Override
175 + public void event(DeviceEvent event) {
176 + switch (event.type()) {
177 + case DEVICE_ADDED:
178 + addLink(event.subject());
179 + break;
180 + case DEVICE_REMOVED:
181 + removeLink(event.subject());
182 + break;
183 + default:
184 + break;
185 + }
186 + }
187 +
188 + private void addLink(Device current) {
189 + devices.add(current.id());
190 + // No link if only one device
191 + if (devices.size() == 1) {
192 + return;
193 + }
194 +
195 + // Attach new device to the last-seen device
196 + DeviceId prev = devices.get(devices.size() - 2);
197 + ConnectPoint src = new ConnectPoint(prev, SRCPORT);
198 + ConnectPoint dst = new ConnectPoint(current.id(), DSTPORT);
199 +
200 + LinkDescription fdesc = new DefaultLinkDescription(src, dst,
201 + Link.Type.DIRECT);
202 + LinkDescription rdesc = new DefaultLinkDescription(dst, src,
203 + Link.Type.DIRECT);
204 + descriptions.put(src, fdesc);
205 + descriptions.put(dst, rdesc);
206 +
207 + providerService.linkDetected(fdesc);
208 + providerService.linkDetected(rdesc);
209 + }
210 +
211 + private void removeLink(Device device) {
212 + providerService.linksVanished(device.id());
213 + devices.remove(device.id());
214 + }
215 + }
216 +
217 + /**
218 + * Generates link events using fake links.
219 + */
220 + private class LinkDriver implements Runnable {
221 +
222 + @Override
223 + public void run() {
224 + while (!linkDriver.isShutdown()) {
225 + for (LinkDescription desc : descriptions.values()) {
226 + providerService.linkVanished(desc);
227 + delay(eventRate);
228 + providerService.linkDetected(desc);
229 + delay(eventRate);
230 + }
231 + }
232 + }
233 + }
234 +}
1 +# Sample configurations for the NullLinkProvider.
2 +
3 +#
4 +# If enabled, generates LinkDetected and LinkVanished events
5 +# to make the link appear to be flapping.
6 +#
7 +# flicker = true
8 +
9 +#
10 +# If enabled, sets the time between LinkEvent generation,
11 +# in milliseconds.
12 +#
13 +# eventRate = 2000