blob: 6ecac8e05262d4af38e3436c067bff2da58ab2be [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;
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
155 private static final int DEFAULT_PACKET_RATE = 5;
156 @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 /**
271 * Severs the link between the specified end-points in both directions.
272 *
273 * @param one link endpoint
274 * @param two link endpoint
275 */
276 public void severLink(ConnectPoint one, ConnectPoint two) {
277 if (enabled) {
278 topologyMutationDriver.severLink(one, two);
279 }
280 }
281
282 /**
283 * Severs the link between the specified end-points in both directions.
284 *
285 * @param one link endpoint
286 * @param two link endpoint
287 */
288 public void repairLink(ConnectPoint one, ConnectPoint two) {
289 if (enabled) {
290 topologyMutationDriver.repairLink(one, two);
291 }
292 }
293
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800294 /**
295 * Fails the specified device.
296 *
297 * @param deviceId device identifier
298 */
299 public void failDevice(DeviceId deviceId) {
300 if (enabled) {
301 topologyMutationDriver.failDevice(deviceId);
302 }
303 }
304
305 /**
306 * Repairs the specified device.
307 *
308 * @param deviceId device identifier
309 */
310 public void repairDevice(DeviceId deviceId) {
311 if (enabled) {
312 topologyMutationDriver.repairDevice(deviceId);
313 }
314 }
315
316
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700317 // Resets simulation based on the current configuration parameters.
318 private void restartSimulation() {
319 tearDown();
320 if (enabled) {
321 setUp();
322 }
323 }
324
325 // Sets up the topology simulation and all providers.
326 private void setUp() {
327 simulator = selectSimulator(topoShape);
328 simulator.init(topoShape, deviceCount, hostCount,
329 new DefaultServiceDirectory(),
330 deviceProviderService, hostProviderService,
331 linkProviderService);
332 simulator.setUpTopology();
333 flowRuleProvider.start(flowRuleProviderService);
334 packetProvider.start(packetRate, hostService, deviceService,
335 packetProviderService);
336 topologyMutationDriver.start(mutationRate, linkService, deviceService,
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800337 linkProviderService, deviceProviderService,
338 simulator);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700339 }
340
341 // Selects the simulator based on the specified name.
342 private TopologySimulator selectSimulator(String topoShape) {
343 if (topoShape.matches("linear([,].*|$)")) {
344 return new LinearTopologySimulator();
345 } else if (topoShape.matches("centipede([,].*|$)")) {
346 return new CentipedeTopologySimulator();
347 } else if (topoShape.matches("reroute([,].*|$)")) {
348 return new RerouteTopologySimulator();
349 } else if (topoShape.matches("tree([,].*|$)")) {
350 return new TreeTopologySimulator();
Thomas Vachuska59da18d2015-07-07 17:44:21 -0700351 } else if (topoShape.matches("agglink([,].*|$)")) {
352 return new AggLinkTopologySimulator();
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700353 } else if (topoShape.matches("spineleaf([,].*|$)")) {
354 return new SpineLeafTopologySimulator();
355 } else if (topoShape.matches("mesh([,].*|$)")) {
356 return new MeshTopologySimulator();
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800357 } else if (topoShape.matches("grid([,].*|$)")) {
358 return new GridTopologySimulator();
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700359 } else {
360 return new ConfiguredTopologySimulator();
361 }
362 }
363
364 // Shuts down the topology simulator and all providers.
365 private void tearDown() {
366 if (simulator != null) {
367 topologyMutationDriver.stop();
368 packetProvider.stop();
369 flowRuleProvider.stop();
370 delay(500);
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700371 simulator.tearDownTopology();
372 simulator = null;
373 }
374 }
375
376 // Changes packet and mutation rates.
377 private void adjustRates() {
378 packetProvider.adjustRate(packetRate);
379 topologyMutationDriver.adjustRate(mutationRate);
380 }
381
382 // Re-assigns mastership roles.
383 private void reassignMastership() {
384 if (mastership.equals(DEFAULT_MASTERSHIP)) {
385 mastershipService.balanceRoles();
386 } else {
387 NodeId localNode = clusterService.getLocalNode().id();
388 rejectMastership();
389 String[] nodeSpecs = mastership.split("/");
390 for (int i = 0; i < nodeSpecs.length; i++) {
391 String[] specs = nodeSpecs[i].split("=");
392 if (specs[0].equals(localNode.toString())) {
393 String[] ids = specs[1].split(",");
394 for (String id : ids) {
395 mastershipService.setRole(localNode, deviceId(id), MASTER);
396 }
397 break;
398 }
399 }
400 }
401 }
402
403 // Rejects mastership of all devices.
404 private void rejectMastership() {
405 NodeId localNode = clusterService.getLocalNode().id();
406 deviceService.getDevices()
407 .forEach(device -> mastershipService.setRole(localNode, device.id(),
408 NONE));
409 }
410
411 // Null provider base class.
412 abstract static class AbstractNullProvider extends AbstractProvider {
413 protected AbstractNullProvider() {
414 super(new ProviderId(SCHEME, PROVIDER_ID));
415 }
416 }
417
418 // Device provider facade.
419 private class NullDeviceProvider extends AbstractNullProvider implements DeviceProvider {
420 @Override
421 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
422 deviceProviderService.receivedRoleReply(deviceId, newRole, newRole);
423 }
424
425 @Override
426 public boolean isReachable(DeviceId deviceId) {
Thomas Vachuska5f429d62015-05-28 15:34:36 -0700427 return topoShape.equals("configured") ||
Thomas Vachuska8e038eb2016-02-23 23:28:23 -0800428 (simulator != null && simulator.contains(deviceId) &&
429 topologyMutationDriver.isReachable(deviceId));
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700430 }
431
432 @Override
433 public void triggerProbe(DeviceId deviceId) {
434 }
Saurav Dasa2d37502016-03-25 17:50:40 -0700435
436 @Override
437 public void changePortState(DeviceId deviceId, PortNumber portNumber,
438 boolean enable) {
439 // TODO maybe required
440 }
Thomas Vachuskac40d4632015-04-09 16:55:03 -0700441 }
442
443 // Host provider facade.
444 private class NullHostProvider extends AbstractNullProvider implements HostProvider {
445 @Override
446 public void triggerProbe(Host host) {
447 }
448 }
449
450 // Host provider facade.
451 private class NullLinkProvider extends AbstractNullProvider implements LinkProvider {
452 }
453
454}