blob: 7313f128d9c3e099a2c9e142ae6eea63f8a176ac [file] [log] [blame]
Thomas Vachuskac40d4632015-04-09 16:55:03 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Thomas Vachuskac40d4632015-04-09 16:55:03 -07003 *
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;
Saurav Dasa2d37502016-03-25 17:50:40 -070035import org.onosproject.net.PortNumber;
Thomas Vachuskac40d4632015-04-09 16:55:03 -070036import org.onosproject.net.device.DeviceAdminService;
37import org.onosproject.net.device.DeviceProvider;
38import org.onosproject.net.device.DeviceProviderRegistry;
39import org.onosproject.net.device.DeviceProviderService;
40import org.onosproject.net.flow.FlowRuleProviderRegistry;
41import org.onosproject.net.flow.FlowRuleProviderService;
42import org.onosproject.net.host.HostProvider;
43import org.onosproject.net.host.HostProviderRegistry;
44import org.onosproject.net.host.HostProviderService;
45import org.onosproject.net.host.HostService;
46import org.onosproject.net.link.LinkProvider;
47import org.onosproject.net.link.LinkProviderRegistry;
48import org.onosproject.net.link.LinkProviderService;
49import org.onosproject.net.link.LinkService;
50import org.onosproject.net.packet.PacketProviderRegistry;
51import org.onosproject.net.packet.PacketProviderService;
52import org.onosproject.net.provider.AbstractProvider;
53import org.onosproject.net.provider.ProviderId;
54import org.osgi.service.component.ComponentContext;
55import org.slf4j.Logger;
56
57import java.util.Dictionary;
Thomas Vachuska8e038eb2016-02-23 23:28:23 -080058import java.util.Objects;
Thomas Vachuskac40d4632015-04-09 16:55:03 -070059import java.util.Properties;
60
61import static com.google.common.base.Strings.isNullOrEmpty;
62import static org.onlab.util.Tools.delay;
63import static org.onlab.util.Tools.get;
64import static org.onosproject.net.DeviceId.deviceId;
65import static org.onosproject.net.MastershipRole.MASTER;
66import static org.onosproject.net.MastershipRole.NONE;
67import static org.slf4j.LoggerFactory.getLogger;
68
69/**
70 * Provider of a fake network environment, i.e. devices, links, hosts, etc.
71 * To be used for benchmarking only.
72 */
73@Component(immediate = true)
74@Service(value = NullProviders.class)
75public class NullProviders {
76
77 private static final Logger log = getLogger(NullProviders.class);
78
79 static final String SCHEME = "null";
80 static final String PROVIDER_ID = "org.onosproject.provider.nil";
81
82 private static final String FORMAT =
83 "Settings: enabled={}, topoShape={}, deviceCount={}, " +
84 "hostCount={}, packetRate={}, mutationRate={}";
85
86
87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
88 protected ClusterService clusterService;
89
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 protected MastershipAdminService mastershipService;
92
93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected ComponentConfigService cfgService;
95
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected DeviceAdminService deviceService;
98
99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected HostService hostService;
101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 protected LinkService linkService;
104
105
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
107 protected DeviceProviderRegistry deviceProviderRegistry;
108
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 protected HostProviderRegistry hostProviderRegistry;
111
112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 protected LinkProviderRegistry linkProviderRegistry;
114
115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
116 protected FlowRuleProviderRegistry flowRuleProviderRegistry;
117
118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 protected PacketProviderRegistry packetProviderRegistry;
120
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700121 private final NullDeviceProvider deviceProvider = new NullDeviceProvider();
122 private final NullLinkProvider linkProvider = new NullLinkProvider();
123 private final NullHostProvider hostProvider = new NullHostProvider();
124 private final NullFlowRuleProvider flowRuleProvider = new NullFlowRuleProvider();
125 private final NullPacketProvider packetProvider = new NullPacketProvider();
126 private final TopologyMutationDriver topologyMutationDriver = new TopologyMutationDriver();
127
128 private DeviceProviderService deviceProviderService;
129 private HostProviderService hostProviderService;
130 private LinkProviderService linkProviderService;
131 private FlowRuleProviderService flowRuleProviderService;
132 private PacketProviderService packetProviderService;
133
134 private TopologySimulator simulator;
135
136 @Property(name = "enabled", boolValue = false,
137 label = "Enables or disables the provider")
138 private boolean enabled = false;
139
140 private static final String DEFAULT_TOPO_SHAPE = "configured";
141 @Property(name = "topoShape", value = DEFAULT_TOPO_SHAPE,
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800142 label = "Topology shape: configured, linear, reroute, tree, spineleaf, mesh, grid")
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700143 private String topoShape = DEFAULT_TOPO_SHAPE;
144
145 private static final int DEFAULT_DEVICE_COUNT = 10;
146 @Property(name = "deviceCount", intValue = DEFAULT_DEVICE_COUNT,
147 label = "Number of devices to generate")
148 private int deviceCount = DEFAULT_DEVICE_COUNT;
149
150 private static final int DEFAULT_HOST_COUNT = 5;
151 @Property(name = "hostCount", intValue = DEFAULT_HOST_COUNT,
152 label = "Number of host to generate per device")
153 private int hostCount = DEFAULT_HOST_COUNT;
154
Thomas Vachuskac3cdf902016-04-13 13:44:09 -0700155 private static final int DEFAULT_PACKET_RATE = 0;
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700156 @Property(name = "packetRate", intValue = DEFAULT_PACKET_RATE,
157 label = "Packet-in/s rate; 0 for no packets")
158 private int packetRate = DEFAULT_PACKET_RATE;
159
160 private static final double DEFAULT_MUTATION_RATE = 0;
161 @Property(name = "mutationRate", doubleValue = DEFAULT_MUTATION_RATE,
162 label = "Link event/s topology mutation rate; 0 for no mutations")
163 private double mutationRate = DEFAULT_MUTATION_RATE;
164
165 private static final String DEFAULT_MASTERSHIP = "random";
166 @Property(name = "mastership", value = DEFAULT_MASTERSHIP,
167 label = "Mastership given as 'random' or 'node1=dpid,dpid/node2=dpid,...'")
168 private String mastership = DEFAULT_MASTERSHIP;
169
170
171 @Activate
Thomas Vachuska41fe1ec2015-12-03 23:17:02 -0800172 public void activate() {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700173 cfgService.registerProperties(getClass());
174
175 deviceProviderService = deviceProviderRegistry.register(deviceProvider);
176 hostProviderService = hostProviderRegistry.register(hostProvider);
177 linkProviderService = linkProviderRegistry.register(linkProvider);
178 flowRuleProviderService = flowRuleProviderRegistry.register(flowRuleProvider);
179 packetProviderService = packetProviderRegistry.register(packetProvider);
180 log.info("Started");
181 }
182
183 @Deactivate
Thomas Vachuska41fe1ec2015-12-03 23:17:02 -0800184 public void deactivate() {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700185 cfgService.unregisterProperties(getClass(), false);
186 tearDown();
187
188 deviceProviderRegistry.unregister(deviceProvider);
189 hostProviderRegistry.unregister(hostProvider);
190 linkProviderRegistry.unregister(linkProvider);
191 flowRuleProviderRegistry.unregister(flowRuleProvider);
192 packetProviderRegistry.unregister(packetProvider);
193
194 deviceProviderService = null;
195 hostProviderService = null;
196 linkProviderService = null;
197 flowRuleProviderService = null;
198 packetProviderService = null;
199
200 log.info("Stopped");
201 }
202
203 @Modified
204 public void modified(ComponentContext context) {
205 Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
206
207 boolean newEnabled;
208 int newDeviceCount, newHostCount, newPacketRate;
209 double newMutationRate;
210 String newTopoShape, newMastership;
211 try {
212 String s = get(properties, "enabled");
213 newEnabled = isNullOrEmpty(s) ? enabled : Boolean.parseBoolean(s.trim());
214
215 newTopoShape = get(properties, "topoShape");
216 newMastership = get(properties, "mastership");
217
218 s = get(properties, "deviceCount");
219 newDeviceCount = isNullOrEmpty(s) ? deviceCount : Integer.parseInt(s.trim());
220
221 s = get(properties, "hostCount");
222 newHostCount = isNullOrEmpty(s) ? hostCount : Integer.parseInt(s.trim());
223
224 s = get(properties, "packetRate");
225 newPacketRate = isNullOrEmpty(s) ? packetRate : Integer.parseInt(s.trim());
226
227 s = get(properties, "mutationRate");
228 newMutationRate = isNullOrEmpty(s) ? mutationRate : Double.parseDouble(s.trim());
229
230 } catch (NumberFormatException e) {
231 log.warn(e.getMessage());
232 newEnabled = enabled;
233 newTopoShape = topoShape;
234 newDeviceCount = deviceCount;
235 newHostCount = hostCount;
236 newPacketRate = packetRate;
237 newMutationRate = mutationRate;
238 newMastership = mastership;
239 }
240
241 // Any change in the following parameters implies hard restart
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800242 if (newEnabled != enabled || !Objects.equals(newTopoShape, topoShape) ||
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700243 newDeviceCount != deviceCount || newHostCount != hostCount) {
244 enabled = newEnabled;
245 topoShape = newTopoShape;
246 deviceCount = newDeviceCount;
247 hostCount = newHostCount;
248 packetRate = newPacketRate;
249 mutationRate = newMutationRate;
250 restartSimulation();
251 }
252
253 // Any change in the following parameters implies just a rate change
254 if (newPacketRate != packetRate || newMutationRate != mutationRate) {
255 packetRate = newPacketRate;
256 mutationRate = newMutationRate;
257 adjustRates();
258 }
259
260 // Any change in mastership implies just reassignments.
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800261 if (!Objects.equals(newMastership, mastership)) {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700262 mastership = newMastership;
263 reassignMastership();
264 }
265
266 log.info(FORMAT, enabled, topoShape, deviceCount, hostCount,
267 packetRate, mutationRate);
268 }
269
270 /**
Thomas Vachuska5c6ed222016-06-29 11:02:22 +0200271 * Returns the currently active topology simulator.
272 *
273 * @return current simulator; null if none is active
274 */
275 public TopologySimulator currentSimulator() {
276 return simulator;
277 }
278
279 /**
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700280 * Severs the link between the specified end-points in both directions.
281 *
282 * @param one link endpoint
283 * @param two link endpoint
284 */
285 public void severLink(ConnectPoint one, ConnectPoint two) {
286 if (enabled) {
287 topologyMutationDriver.severLink(one, two);
288 }
289 }
290
291 /**
292 * Severs the link between the specified end-points in both directions.
293 *
294 * @param one link endpoint
295 * @param two link endpoint
296 */
297 public void repairLink(ConnectPoint one, ConnectPoint two) {
298 if (enabled) {
299 topologyMutationDriver.repairLink(one, two);
300 }
301 }
302
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800303 /**
304 * Fails the specified device.
305 *
306 * @param deviceId device identifier
307 */
308 public void failDevice(DeviceId deviceId) {
309 if (enabled) {
310 topologyMutationDriver.failDevice(deviceId);
311 }
312 }
313
314 /**
315 * Repairs the specified device.
316 *
317 * @param deviceId device identifier
318 */
319 public void repairDevice(DeviceId deviceId) {
320 if (enabled) {
321 topologyMutationDriver.repairDevice(deviceId);
322 }
323 }
324
325
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700326 // Resets simulation based on the current configuration parameters.
327 private void restartSimulation() {
328 tearDown();
329 if (enabled) {
330 setUp();
331 }
332 }
333
334 // Sets up the topology simulation and all providers.
335 private void setUp() {
336 simulator = selectSimulator(topoShape);
337 simulator.init(topoShape, deviceCount, hostCount,
338 new DefaultServiceDirectory(),
339 deviceProviderService, hostProviderService,
340 linkProviderService);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700341 flowRuleProvider.start(flowRuleProviderService);
342 packetProvider.start(packetRate, hostService, deviceService,
343 packetProviderService);
Thomas Vachuska1cbd65e2016-06-25 16:27:57 +0200344 simulator.setUpTopology();
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700345 topologyMutationDriver.start(mutationRate, linkService, deviceService,
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800346 linkProviderService, deviceProviderService,
347 simulator);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700348 }
349
350 // Selects the simulator based on the specified name.
351 private TopologySimulator selectSimulator(String topoShape) {
352 if (topoShape.matches("linear([,].*|$)")) {
353 return new LinearTopologySimulator();
354 } else if (topoShape.matches("centipede([,].*|$)")) {
355 return new CentipedeTopologySimulator();
356 } else if (topoShape.matches("reroute([,].*|$)")) {
357 return new RerouteTopologySimulator();
358 } else if (topoShape.matches("tree([,].*|$)")) {
359 return new TreeTopologySimulator();
Thomas Vachuska59da18d2015-07-07 17:44:21 -0700360 } else if (topoShape.matches("agglink([,].*|$)")) {
361 return new AggLinkTopologySimulator();
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700362 } else if (topoShape.matches("spineleaf([,].*|$)")) {
363 return new SpineLeafTopologySimulator();
364 } else if (topoShape.matches("mesh([,].*|$)")) {
365 return new MeshTopologySimulator();
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800366 } else if (topoShape.matches("grid([,].*|$)")) {
367 return new GridTopologySimulator();
Andreas Pantelopoulos620d3d72016-11-08 22:18:59 +0100368 } else if (topoShape.matches("fattree([,].*|$)")) {
369 return new FatTreeTopologySimulator();
hyunmin no97174182016-12-13 21:14:30 +0900370 } else if (topoShape.matches("chordal([,].*|$)")) {
371 return new ChordalTopologySimulator();
Thomas Vachuska5c6ed222016-06-29 11:02:22 +0200372 } else if (topoShape.matches("custom([,].*|$)")) {
373 return new CustomTopologySimulator();
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700374 } else {
375 return new ConfiguredTopologySimulator();
376 }
377 }
378
379 // Shuts down the topology simulator and all providers.
380 private void tearDown() {
381 if (simulator != null) {
382 topologyMutationDriver.stop();
383 packetProvider.stop();
384 flowRuleProvider.stop();
385 delay(500);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700386 simulator.tearDownTopology();
387 simulator = null;
388 }
389 }
390
391 // Changes packet and mutation rates.
392 private void adjustRates() {
393 packetProvider.adjustRate(packetRate);
394 topologyMutationDriver.adjustRate(mutationRate);
395 }
396
397 // Re-assigns mastership roles.
398 private void reassignMastership() {
399 if (mastership.equals(DEFAULT_MASTERSHIP)) {
400 mastershipService.balanceRoles();
401 } else {
402 NodeId localNode = clusterService.getLocalNode().id();
403 rejectMastership();
404 String[] nodeSpecs = mastership.split("/");
405 for (int i = 0; i < nodeSpecs.length; i++) {
406 String[] specs = nodeSpecs[i].split("=");
407 if (specs[0].equals(localNode.toString())) {
408 String[] ids = specs[1].split(",");
409 for (String id : ids) {
410 mastershipService.setRole(localNode, deviceId(id), MASTER);
411 }
412 break;
413 }
414 }
415 }
416 }
417
418 // Rejects mastership of all devices.
419 private void rejectMastership() {
420 NodeId localNode = clusterService.getLocalNode().id();
421 deviceService.getDevices()
422 .forEach(device -> mastershipService.setRole(localNode, device.id(),
423 NONE));
424 }
425
426 // Null provider base class.
427 abstract static class AbstractNullProvider extends AbstractProvider {
428 protected AbstractNullProvider() {
429 super(new ProviderId(SCHEME, PROVIDER_ID));
430 }
431 }
432
433 // Device provider facade.
434 private class NullDeviceProvider extends AbstractNullProvider implements DeviceProvider {
435 @Override
436 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
437 deviceProviderService.receivedRoleReply(deviceId, newRole, newRole);
438 }
439
440 @Override
441 public boolean isReachable(DeviceId deviceId) {
Thomas Vachuska4a315162018-02-14 16:50:16 -0800442 return simulator != null &&
443 (simulator.contains(deviceId) || !deviceService.getPorts(deviceId).isEmpty()) &&
444 (simulator instanceof CustomTopologySimulator ||
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800445 topologyMutationDriver.isReachable(deviceId));
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700446 }
447
448 @Override
449 public void triggerProbe(DeviceId deviceId) {
450 }
Saurav Dasa2d37502016-03-25 17:50:40 -0700451
452 @Override
453 public void changePortState(DeviceId deviceId, PortNumber portNumber,
454 boolean enable) {
455 // TODO maybe required
456 }
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700457 }
458
459 // Host provider facade.
460 private class NullHostProvider extends AbstractNullProvider implements HostProvider {
461 @Override
462 public void triggerProbe(Host host) {
463 }
464 }
465
466 // Host provider facade.
467 private class NullLinkProvider extends AbstractNullProvider implements LinkProvider {
468 }
469
470}