blob: 7c45df3e7bd825a9a57d4d0866252c8ff4029cfb [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;
Yi Tseng3dca0f82018-04-03 14:33:03 +080042import org.onosproject.net.group.GroupProviderRegistry;
43import org.onosproject.net.group.GroupProviderService;
Thomas Vachuskac40d4632015-04-09 16:55:03 -070044import org.onosproject.net.host.HostProvider;
45import org.onosproject.net.host.HostProviderRegistry;
46import org.onosproject.net.host.HostProviderService;
47import org.onosproject.net.host.HostService;
48import org.onosproject.net.link.LinkProvider;
49import org.onosproject.net.link.LinkProviderRegistry;
50import org.onosproject.net.link.LinkProviderService;
51import org.onosproject.net.link.LinkService;
52import org.onosproject.net.packet.PacketProviderRegistry;
53import org.onosproject.net.packet.PacketProviderService;
54import org.onosproject.net.provider.AbstractProvider;
55import org.onosproject.net.provider.ProviderId;
56import org.osgi.service.component.ComponentContext;
57import org.slf4j.Logger;
58
59import java.util.Dictionary;
Thomas Vachuska8e038eb2016-02-23 23:28:23 -080060import java.util.Objects;
Thomas Vachuskac40d4632015-04-09 16:55:03 -070061import java.util.Properties;
62
63import static com.google.common.base.Strings.isNullOrEmpty;
64import static org.onlab.util.Tools.delay;
65import static org.onlab.util.Tools.get;
66import static org.onosproject.net.DeviceId.deviceId;
67import static org.onosproject.net.MastershipRole.MASTER;
68import static org.onosproject.net.MastershipRole.NONE;
69import static org.slf4j.LoggerFactory.getLogger;
70
71/**
72 * Provider of a fake network environment, i.e. devices, links, hosts, etc.
73 * To be used for benchmarking only.
74 */
75@Component(immediate = true)
76@Service(value = NullProviders.class)
77public class NullProviders {
78
79 private static final Logger log = getLogger(NullProviders.class);
80
81 static final String SCHEME = "null";
82 static final String PROVIDER_ID = "org.onosproject.provider.nil";
83
84 private static final String FORMAT =
85 "Settings: enabled={}, topoShape={}, deviceCount={}, " +
86 "hostCount={}, packetRate={}, mutationRate={}";
87
88
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 protected ClusterService clusterService;
91
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 protected MastershipAdminService mastershipService;
94
95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 protected ComponentConfigService cfgService;
97
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected DeviceAdminService deviceService;
100
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected HostService hostService;
103
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected LinkService linkService;
106
107
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected DeviceProviderRegistry deviceProviderRegistry;
110
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 protected HostProviderRegistry hostProviderRegistry;
113
114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 protected LinkProviderRegistry linkProviderRegistry;
116
117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 protected FlowRuleProviderRegistry flowRuleProviderRegistry;
119
120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Yi Tseng3dca0f82018-04-03 14:33:03 +0800121 protected GroupProviderRegistry groupProviderRegistry;
122
123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700124 protected PacketProviderRegistry packetProviderRegistry;
125
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700126 private final NullDeviceProvider deviceProvider = new NullDeviceProvider();
127 private final NullLinkProvider linkProvider = new NullLinkProvider();
128 private final NullHostProvider hostProvider = new NullHostProvider();
129 private final NullFlowRuleProvider flowRuleProvider = new NullFlowRuleProvider();
Yi Tseng3dca0f82018-04-03 14:33:03 +0800130 private final NullGroupProvider groupProvider = new NullGroupProvider();
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700131 private final NullPacketProvider packetProvider = new NullPacketProvider();
132 private final TopologyMutationDriver topologyMutationDriver = new TopologyMutationDriver();
133
134 private DeviceProviderService deviceProviderService;
135 private HostProviderService hostProviderService;
136 private LinkProviderService linkProviderService;
137 private FlowRuleProviderService flowRuleProviderService;
Yi Tseng3dca0f82018-04-03 14:33:03 +0800138 private GroupProviderService groupProviderService;
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700139 private PacketProviderService packetProviderService;
140
141 private TopologySimulator simulator;
142
143 @Property(name = "enabled", boolValue = false,
144 label = "Enables or disables the provider")
145 private boolean enabled = false;
146
147 private static final String DEFAULT_TOPO_SHAPE = "configured";
148 @Property(name = "topoShape", value = DEFAULT_TOPO_SHAPE,
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800149 label = "Topology shape: configured, linear, reroute, tree, spineleaf, mesh, grid")
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700150 private String topoShape = DEFAULT_TOPO_SHAPE;
151
152 private static final int DEFAULT_DEVICE_COUNT = 10;
153 @Property(name = "deviceCount", intValue = DEFAULT_DEVICE_COUNT,
154 label = "Number of devices to generate")
155 private int deviceCount = DEFAULT_DEVICE_COUNT;
156
157 private static final int DEFAULT_HOST_COUNT = 5;
158 @Property(name = "hostCount", intValue = DEFAULT_HOST_COUNT,
159 label = "Number of host to generate per device")
160 private int hostCount = DEFAULT_HOST_COUNT;
161
Thomas Vachuskac3cdf902016-04-13 13:44:09 -0700162 private static final int DEFAULT_PACKET_RATE = 0;
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700163 @Property(name = "packetRate", intValue = DEFAULT_PACKET_RATE,
164 label = "Packet-in/s rate; 0 for no packets")
165 private int packetRate = DEFAULT_PACKET_RATE;
166
167 private static final double DEFAULT_MUTATION_RATE = 0;
168 @Property(name = "mutationRate", doubleValue = DEFAULT_MUTATION_RATE,
169 label = "Link event/s topology mutation rate; 0 for no mutations")
170 private double mutationRate = DEFAULT_MUTATION_RATE;
171
172 private static final String DEFAULT_MASTERSHIP = "random";
173 @Property(name = "mastership", value = DEFAULT_MASTERSHIP,
174 label = "Mastership given as 'random' or 'node1=dpid,dpid/node2=dpid,...'")
175 private String mastership = DEFAULT_MASTERSHIP;
176
177
178 @Activate
Thomas Vachuska41fe1ec2015-12-03 23:17:02 -0800179 public void activate() {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700180 cfgService.registerProperties(getClass());
181
182 deviceProviderService = deviceProviderRegistry.register(deviceProvider);
183 hostProviderService = hostProviderRegistry.register(hostProvider);
184 linkProviderService = linkProviderRegistry.register(linkProvider);
185 flowRuleProviderService = flowRuleProviderRegistry.register(flowRuleProvider);
Yi Tseng3dca0f82018-04-03 14:33:03 +0800186 groupProviderService = groupProviderRegistry.register(groupProvider);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700187 packetProviderService = packetProviderRegistry.register(packetProvider);
188 log.info("Started");
189 }
190
191 @Deactivate
Thomas Vachuska41fe1ec2015-12-03 23:17:02 -0800192 public void deactivate() {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700193 cfgService.unregisterProperties(getClass(), false);
194 tearDown();
195
196 deviceProviderRegistry.unregister(deviceProvider);
197 hostProviderRegistry.unregister(hostProvider);
198 linkProviderRegistry.unregister(linkProvider);
199 flowRuleProviderRegistry.unregister(flowRuleProvider);
Yi Tseng3dca0f82018-04-03 14:33:03 +0800200 groupProviderRegistry.unregister(groupProvider);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700201 packetProviderRegistry.unregister(packetProvider);
202
203 deviceProviderService = null;
204 hostProviderService = null;
205 linkProviderService = null;
206 flowRuleProviderService = null;
Yi Tseng3dca0f82018-04-03 14:33:03 +0800207 groupProviderService = null;
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700208 packetProviderService = null;
209
210 log.info("Stopped");
211 }
212
213 @Modified
214 public void modified(ComponentContext context) {
215 Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
216
217 boolean newEnabled;
218 int newDeviceCount, newHostCount, newPacketRate;
219 double newMutationRate;
220 String newTopoShape, newMastership;
221 try {
222 String s = get(properties, "enabled");
223 newEnabled = isNullOrEmpty(s) ? enabled : Boolean.parseBoolean(s.trim());
224
225 newTopoShape = get(properties, "topoShape");
226 newMastership = get(properties, "mastership");
227
228 s = get(properties, "deviceCount");
229 newDeviceCount = isNullOrEmpty(s) ? deviceCount : Integer.parseInt(s.trim());
230
231 s = get(properties, "hostCount");
232 newHostCount = isNullOrEmpty(s) ? hostCount : Integer.parseInt(s.trim());
233
234 s = get(properties, "packetRate");
235 newPacketRate = isNullOrEmpty(s) ? packetRate : Integer.parseInt(s.trim());
236
237 s = get(properties, "mutationRate");
238 newMutationRate = isNullOrEmpty(s) ? mutationRate : Double.parseDouble(s.trim());
239
240 } catch (NumberFormatException e) {
241 log.warn(e.getMessage());
242 newEnabled = enabled;
243 newTopoShape = topoShape;
244 newDeviceCount = deviceCount;
245 newHostCount = hostCount;
246 newPacketRate = packetRate;
247 newMutationRate = mutationRate;
248 newMastership = mastership;
249 }
250
251 // Any change in the following parameters implies hard restart
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800252 if (newEnabled != enabled || !Objects.equals(newTopoShape, topoShape) ||
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700253 newDeviceCount != deviceCount || newHostCount != hostCount) {
254 enabled = newEnabled;
255 topoShape = newTopoShape;
256 deviceCount = newDeviceCount;
257 hostCount = newHostCount;
258 packetRate = newPacketRate;
259 mutationRate = newMutationRate;
260 restartSimulation();
261 }
262
263 // Any change in the following parameters implies just a rate change
264 if (newPacketRate != packetRate || newMutationRate != mutationRate) {
265 packetRate = newPacketRate;
266 mutationRate = newMutationRate;
267 adjustRates();
268 }
269
270 // Any change in mastership implies just reassignments.
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800271 if (!Objects.equals(newMastership, mastership)) {
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700272 mastership = newMastership;
273 reassignMastership();
274 }
275
276 log.info(FORMAT, enabled, topoShape, deviceCount, hostCount,
277 packetRate, mutationRate);
278 }
279
280 /**
Thomas Vachuska5c6ed222016-06-29 11:02:22 +0200281 * Returns the currently active topology simulator.
282 *
283 * @return current simulator; null if none is active
284 */
285 public TopologySimulator currentSimulator() {
286 return simulator;
287 }
288
289 /**
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700290 * Severs the link between the specified end-points in both directions.
291 *
292 * @param one link endpoint
293 * @param two link endpoint
294 */
295 public void severLink(ConnectPoint one, ConnectPoint two) {
296 if (enabled) {
297 topologyMutationDriver.severLink(one, two);
298 }
299 }
300
301 /**
302 * Severs the link between the specified end-points in both directions.
303 *
304 * @param one link endpoint
305 * @param two link endpoint
306 */
307 public void repairLink(ConnectPoint one, ConnectPoint two) {
308 if (enabled) {
309 topologyMutationDriver.repairLink(one, two);
310 }
311 }
312
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800313 /**
314 * Fails the specified device.
315 *
316 * @param deviceId device identifier
317 */
318 public void failDevice(DeviceId deviceId) {
319 if (enabled) {
320 topologyMutationDriver.failDevice(deviceId);
321 }
322 }
323
324 /**
325 * Repairs the specified device.
326 *
327 * @param deviceId device identifier
328 */
329 public void repairDevice(DeviceId deviceId) {
330 if (enabled) {
331 topologyMutationDriver.repairDevice(deviceId);
332 }
333 }
334
335
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700336 // Resets simulation based on the current configuration parameters.
337 private void restartSimulation() {
338 tearDown();
339 if (enabled) {
340 setUp();
341 }
342 }
343
344 // Sets up the topology simulation and all providers.
345 private void setUp() {
346 simulator = selectSimulator(topoShape);
347 simulator.init(topoShape, deviceCount, hostCount,
348 new DefaultServiceDirectory(),
349 deviceProviderService, hostProviderService,
350 linkProviderService);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700351 flowRuleProvider.start(flowRuleProviderService);
Yi Tseng3dca0f82018-04-03 14:33:03 +0800352 groupProvider.start(groupProviderService);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700353 packetProvider.start(packetRate, hostService, deviceService,
354 packetProviderService);
Thomas Vachuska1cbd65e2016-06-25 16:27:57 +0200355 simulator.setUpTopology();
Yi Tseng3dca0f82018-04-03 14:33:03 +0800356 groupProvider.initDevicesGroupTable(simulator.deviceIds);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700357 topologyMutationDriver.start(mutationRate, linkService, deviceService,
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800358 linkProviderService, deviceProviderService,
359 simulator);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700360 }
361
362 // Selects the simulator based on the specified name.
363 private TopologySimulator selectSimulator(String topoShape) {
364 if (topoShape.matches("linear([,].*|$)")) {
365 return new LinearTopologySimulator();
366 } else if (topoShape.matches("centipede([,].*|$)")) {
367 return new CentipedeTopologySimulator();
368 } else if (topoShape.matches("reroute([,].*|$)")) {
369 return new RerouteTopologySimulator();
370 } else if (topoShape.matches("tree([,].*|$)")) {
371 return new TreeTopologySimulator();
Thomas Vachuska59da18d2015-07-07 17:44:21 -0700372 } else if (topoShape.matches("agglink([,].*|$)")) {
373 return new AggLinkTopologySimulator();
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700374 } else if (topoShape.matches("spineleaf([,].*|$)")) {
375 return new SpineLeafTopologySimulator();
376 } else if (topoShape.matches("mesh([,].*|$)")) {
377 return new MeshTopologySimulator();
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800378 } else if (topoShape.matches("grid([,].*|$)")) {
379 return new GridTopologySimulator();
Andreas Pantelopoulos620d3d72016-11-08 22:18:59 +0100380 } else if (topoShape.matches("fattree([,].*|$)")) {
381 return new FatTreeTopologySimulator();
hyunmin no97174182016-12-13 21:14:30 +0900382 } else if (topoShape.matches("chordal([,].*|$)")) {
383 return new ChordalTopologySimulator();
Thomas Vachuska5c6ed222016-06-29 11:02:22 +0200384 } else if (topoShape.matches("custom([,].*|$)")) {
385 return new CustomTopologySimulator();
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700386 } else {
387 return new ConfiguredTopologySimulator();
388 }
389 }
390
391 // Shuts down the topology simulator and all providers.
392 private void tearDown() {
393 if (simulator != null) {
394 topologyMutationDriver.stop();
395 packetProvider.stop();
396 flowRuleProvider.stop();
Yi Tseng3dca0f82018-04-03 14:33:03 +0800397 groupProvider.stop();
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700398 delay(500);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700399 simulator.tearDownTopology();
400 simulator = null;
Thomas Vachuskacab29d22018-02-21 15:47:29 -0800401
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700402 }
403 }
404
405 // Changes packet and mutation rates.
406 private void adjustRates() {
407 packetProvider.adjustRate(packetRate);
408 topologyMutationDriver.adjustRate(mutationRate);
409 }
410
411 // Re-assigns mastership roles.
412 private void reassignMastership() {
413 if (mastership.equals(DEFAULT_MASTERSHIP)) {
414 mastershipService.balanceRoles();
415 } else {
416 NodeId localNode = clusterService.getLocalNode().id();
417 rejectMastership();
418 String[] nodeSpecs = mastership.split("/");
419 for (int i = 0; i < nodeSpecs.length; i++) {
420 String[] specs = nodeSpecs[i].split("=");
421 if (specs[0].equals(localNode.toString())) {
422 String[] ids = specs[1].split(",");
423 for (String id : ids) {
424 mastershipService.setRole(localNode, deviceId(id), MASTER);
425 }
426 break;
427 }
428 }
429 }
430 }
431
432 // Rejects mastership of all devices.
433 private void rejectMastership() {
434 NodeId localNode = clusterService.getLocalNode().id();
435 deviceService.getDevices()
436 .forEach(device -> mastershipService.setRole(localNode, device.id(),
437 NONE));
438 }
439
440 // Null provider base class.
441 abstract static class AbstractNullProvider extends AbstractProvider {
442 protected AbstractNullProvider() {
443 super(new ProviderId(SCHEME, PROVIDER_ID));
444 }
445 }
446
447 // Device provider facade.
448 private class NullDeviceProvider extends AbstractNullProvider implements DeviceProvider {
449 @Override
450 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
451 deviceProviderService.receivedRoleReply(deviceId, newRole, newRole);
452 }
453
454 @Override
455 public boolean isReachable(DeviceId deviceId) {
Thomas Vachuskab1906d22018-02-14 16:50:16 -0800456 return simulator != null &&
457 (simulator.contains(deviceId) || !deviceService.getPorts(deviceId).isEmpty()) &&
458 (simulator instanceof CustomTopologySimulator ||
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800459 topologyMutationDriver.isReachable(deviceId));
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700460 }
461
462 @Override
463 public void triggerProbe(DeviceId deviceId) {
464 }
Saurav Dasa2d37502016-03-25 17:50:40 -0700465
466 @Override
467 public void changePortState(DeviceId deviceId, PortNumber portNumber,
468 boolean enable) {
469 // TODO maybe required
470 }
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700471 }
472
473 // Host provider facade.
474 private class NullHostProvider extends AbstractNullProvider implements HostProvider {
475 @Override
476 public void triggerProbe(Host host) {
477 }
478 }
479
480 // Host provider facade.
481 private class NullLinkProvider extends AbstractNullProvider implements LinkProvider {
482 }
483
484}