blob: fb1823d39a9d0388dd6d561f0ba7ef98ff89b9c6 [file] [log] [blame]
Thomas Vachuskac40d4632015-04-09 16:55:03 -07001/*
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 */
16package org.onosproject.provider.nil;
17
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Modified;
22import org.apache.felix.scr.annotations.Property;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.apache.felix.scr.annotations.Service;
26import org.onlab.osgi.DefaultServiceDirectory;
27import org.onosproject.cfg.ComponentConfigService;
28import org.onosproject.cluster.ClusterService;
29import org.onosproject.cluster.NodeId;
30import org.onosproject.mastership.MastershipAdminService;
31import org.onosproject.net.ConnectPoint;
32import org.onosproject.net.DeviceId;
33import org.onosproject.net.Host;
34import org.onosproject.net.MastershipRole;
35import org.onosproject.net.device.DeviceAdminService;
36import org.onosproject.net.device.DeviceProvider;
37import org.onosproject.net.device.DeviceProviderRegistry;
38import org.onosproject.net.device.DeviceProviderService;
39import org.onosproject.net.flow.FlowRuleProviderRegistry;
40import org.onosproject.net.flow.FlowRuleProviderService;
41import org.onosproject.net.host.HostProvider;
42import org.onosproject.net.host.HostProviderRegistry;
43import org.onosproject.net.host.HostProviderService;
44import org.onosproject.net.host.HostService;
45import org.onosproject.net.link.LinkProvider;
46import org.onosproject.net.link.LinkProviderRegistry;
47import org.onosproject.net.link.LinkProviderService;
48import org.onosproject.net.link.LinkService;
49import org.onosproject.net.packet.PacketProviderRegistry;
50import org.onosproject.net.packet.PacketProviderService;
51import org.onosproject.net.provider.AbstractProvider;
52import org.onosproject.net.provider.ProviderId;
53import org.osgi.service.component.ComponentContext;
54import org.slf4j.Logger;
55
56import java.util.Dictionary;
Thomas Vachuska8e038eb2016-02-23 23:28:23 -080057import java.util.Objects;
Thomas Vachuskac40d4632015-04-09 16:55:03 -070058import java.util.Properties;
59
60import static com.google.common.base.Strings.isNullOrEmpty;
61import static org.onlab.util.Tools.delay;
62import static org.onlab.util.Tools.get;
63import static org.onosproject.net.DeviceId.deviceId;
64import static org.onosproject.net.MastershipRole.MASTER;
65import static org.onosproject.net.MastershipRole.NONE;
66import static org.slf4j.LoggerFactory.getLogger;
67
68/**
69 * Provider of a fake network environment, i.e. devices, links, hosts, etc.
70 * To be used for benchmarking only.
71 */
72@Component(immediate = true)
73@Service(value = NullProviders.class)
74public class NullProviders {
75
76 private static final Logger log = getLogger(NullProviders.class);
77
78 static final String SCHEME = "null";
79 static final String PROVIDER_ID = "org.onosproject.provider.nil";
80
81 private static final String FORMAT =
82 "Settings: enabled={}, topoShape={}, deviceCount={}, " +
83 "hostCount={}, packetRate={}, mutationRate={}";
84
85
86 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
87 protected ClusterService clusterService;
88
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 protected MastershipAdminService mastershipService;
91
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 protected ComponentConfigService cfgService;
94
95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 protected DeviceAdminService deviceService;
97
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected HostService hostService;
100
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected LinkService linkService;
103
104
105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
106 protected DeviceProviderRegistry deviceProviderRegistry;
107
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected HostProviderRegistry hostProviderRegistry;
110
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 protected LinkProviderRegistry linkProviderRegistry;
113
114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 protected FlowRuleProviderRegistry flowRuleProviderRegistry;
116
117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 protected PacketProviderRegistry packetProviderRegistry;
119
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700120 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,
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800141 label = "Topology shape: configured, linear, reroute, tree, spineleaf, mesh, grid")
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700142 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
Thomas Vachuska41fe1ec2015-12-03 23:17:02 -0800171 public void activate() {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700172 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
Thomas Vachuska41fe1ec2015-12-03 23:17:02 -0800183 public void deactivate() {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700184 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
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800241 if (newEnabled != enabled || !Objects.equals(newTopoShape, topoShape) ||
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700242 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.
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800260 if (!Objects.equals(newMastership, mastership)) {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700261 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
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800293 /**
294 * Fails the specified device.
295 *
296 * @param deviceId device identifier
297 */
298 public void failDevice(DeviceId deviceId) {
299 if (enabled) {
300 topologyMutationDriver.failDevice(deviceId);
301 }
302 }
303
304 /**
305 * Repairs the specified device.
306 *
307 * @param deviceId device identifier
308 */
309 public void repairDevice(DeviceId deviceId) {
310 if (enabled) {
311 topologyMutationDriver.repairDevice(deviceId);
312 }
313 }
314
315
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700316 // Resets simulation based on the current configuration parameters.
317 private void restartSimulation() {
318 tearDown();
319 if (enabled) {
320 setUp();
321 }
322 }
323
324 // Sets up the topology simulation and all providers.
325 private void setUp() {
326 simulator = selectSimulator(topoShape);
327 simulator.init(topoShape, deviceCount, hostCount,
328 new DefaultServiceDirectory(),
329 deviceProviderService, hostProviderService,
330 linkProviderService);
331 simulator.setUpTopology();
332 flowRuleProvider.start(flowRuleProviderService);
333 packetProvider.start(packetRate, hostService, deviceService,
334 packetProviderService);
335 topologyMutationDriver.start(mutationRate, linkService, deviceService,
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800336 linkProviderService, deviceProviderService,
337 simulator);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700338 }
339
340 // Selects the simulator based on the specified name.
341 private TopologySimulator selectSimulator(String topoShape) {
342 if (topoShape.matches("linear([,].*|$)")) {
343 return new LinearTopologySimulator();
344 } else if (topoShape.matches("centipede([,].*|$)")) {
345 return new CentipedeTopologySimulator();
346 } else if (topoShape.matches("reroute([,].*|$)")) {
347 return new RerouteTopologySimulator();
348 } else if (topoShape.matches("tree([,].*|$)")) {
349 return new TreeTopologySimulator();
Thomas Vachuska59da18d2015-07-07 17:44:21 -0700350 } else if (topoShape.matches("agglink([,].*|$)")) {
351 return new AggLinkTopologySimulator();
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700352 } else if (topoShape.matches("spineleaf([,].*|$)")) {
353 return new SpineLeafTopologySimulator();
354 } else if (topoShape.matches("mesh([,].*|$)")) {
355 return new MeshTopologySimulator();
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800356 } else if (topoShape.matches("grid([,].*|$)")) {
357 return new GridTopologySimulator();
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700358 } else {
359 return new ConfiguredTopologySimulator();
360 }
361 }
362
363 // Shuts down the topology simulator and all providers.
364 private void tearDown() {
365 if (simulator != null) {
366 topologyMutationDriver.stop();
367 packetProvider.stop();
368 flowRuleProvider.stop();
369 delay(500);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700370 simulator.tearDownTopology();
371 simulator = null;
372 }
373 }
374
375 // Changes packet and mutation rates.
376 private void adjustRates() {
377 packetProvider.adjustRate(packetRate);
378 topologyMutationDriver.adjustRate(mutationRate);
379 }
380
381 // Re-assigns mastership roles.
382 private void reassignMastership() {
383 if (mastership.equals(DEFAULT_MASTERSHIP)) {
384 mastershipService.balanceRoles();
385 } else {
386 NodeId localNode = clusterService.getLocalNode().id();
387 rejectMastership();
388 String[] nodeSpecs = mastership.split("/");
389 for (int i = 0; i < nodeSpecs.length; i++) {
390 String[] specs = nodeSpecs[i].split("=");
391 if (specs[0].equals(localNode.toString())) {
392 String[] ids = specs[1].split(",");
393 for (String id : ids) {
394 mastershipService.setRole(localNode, deviceId(id), MASTER);
395 }
396 break;
397 }
398 }
399 }
400 }
401
402 // Rejects mastership of all devices.
403 private void rejectMastership() {
404 NodeId localNode = clusterService.getLocalNode().id();
405 deviceService.getDevices()
406 .forEach(device -> mastershipService.setRole(localNode, device.id(),
407 NONE));
408 }
409
410 // Null provider base class.
411 abstract static class AbstractNullProvider extends AbstractProvider {
412 protected AbstractNullProvider() {
413 super(new ProviderId(SCHEME, PROVIDER_ID));
414 }
415 }
416
417 // Device provider facade.
418 private class NullDeviceProvider extends AbstractNullProvider implements DeviceProvider {
419 @Override
420 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
421 deviceProviderService.receivedRoleReply(deviceId, newRole, newRole);
422 }
423
424 @Override
425 public boolean isReachable(DeviceId deviceId) {
Thomas Vachuska5f429d62015-05-28 15:34:36 -0700426 return topoShape.equals("configured") ||
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800427 (simulator != null && simulator.contains(deviceId) &&
428 topologyMutationDriver.isReachable(deviceId));
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700429 }
430
431 @Override
432 public void triggerProbe(DeviceId deviceId) {
433 }
434 }
435
436 // Host provider facade.
437 private class NullHostProvider extends AbstractNullProvider implements HostProvider {
438 @Override
439 public void triggerProbe(Host host) {
440 }
441 }
442
443 // Host provider facade.
444 private class NullLinkProvider extends AbstractNullProvider implements LinkProvider {
445 }
446
447}