blob: 3772bdbad4362e27b55aba1c05e32fc8de7aa1fa [file] [log] [blame]
Thomas Vachuskab6451472015-03-31 16:03:56 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Thomas Vachuskab6451472015-03-31 16:03:56 -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.demo;
17
Ray Milkeyb68bbbc2017-12-18 10:05:49 -080018import java.security.SecureRandom;
Ray Milkeyd13a37b2015-06-12 11:55:17 -070019import java.util.Collection;
20import java.util.Collections;
sivachidambaram subramanianf773b652017-05-09 14:40:04 +053021import java.util.HashMap;
22import java.util.Map;
23import java.util.concurrent.atomic.AtomicLong;
Ray Milkeyd13a37b2015-06-12 11:55:17 -070024import java.util.HashSet;
25import java.util.Iterator;
26import java.util.LinkedList;
27import java.util.List;
28import java.util.Objects;
29import java.util.Optional;
30import java.util.Random;
31import java.util.Set;
32import java.util.concurrent.Callable;
33import java.util.concurrent.CountDownLatch;
34import java.util.concurrent.ExecutionException;
35import java.util.concurrent.ExecutorService;
36import java.util.concurrent.Executors;
37import java.util.concurrent.Future;
38import java.util.concurrent.TimeUnit;
39import java.util.concurrent.TimeoutException;
40
Thomas Vachuskab6451472015-03-31 16:03:56 -070041import org.apache.commons.lang.math.RandomUtils;
42import org.apache.felix.scr.annotations.Activate;
43import org.apache.felix.scr.annotations.Component;
44import org.apache.felix.scr.annotations.Deactivate;
45import org.apache.felix.scr.annotations.Reference;
46import org.apache.felix.scr.annotations.ReferenceCardinality;
47import org.apache.felix.scr.annotations.Service;
48import org.onlab.packet.MacAddress;
49import org.onosproject.cluster.ClusterService;
50import org.onosproject.cluster.ControllerNode;
51import org.onosproject.cluster.NodeId;
52import org.onosproject.core.ApplicationId;
53import org.onosproject.core.CoreService;
54import org.onosproject.mastership.MastershipService;
55import org.onosproject.net.Device;
56import org.onosproject.net.Host;
57import org.onosproject.net.HostId;
58import org.onosproject.net.MastershipRole;
59import org.onosproject.net.PortNumber;
60import org.onosproject.net.device.DeviceService;
61import org.onosproject.net.flow.DefaultFlowRule;
62import org.onosproject.net.flow.DefaultTrafficSelector;
63import org.onosproject.net.flow.DefaultTrafficTreatment;
Ray Milkeyd13a37b2015-06-12 11:55:17 -070064import org.onosproject.net.flow.FlowRule;
Thomas Vachuskab6451472015-03-31 16:03:56 -070065import org.onosproject.net.flow.FlowRuleOperations;
66import org.onosproject.net.flow.FlowRuleOperationsContext;
67import org.onosproject.net.flow.FlowRuleService;
68import org.onosproject.net.flow.TrafficSelector;
69import org.onosproject.net.flow.TrafficTreatment;
Sivachidambaram Subramanian89a09ec2017-07-11 09:46:34 +000070import org.onosproject.net.flow.criteria.Criterion;
sivachidambaram subramanianf773b652017-05-09 14:40:04 +053071import org.onosproject.net.flow.instructions.Instructions;
72import org.onosproject.net.flowobjective.FlowObjectiveService;
73import org.onosproject.net.flowobjective.DefaultFilteringObjective;
74import org.onosproject.net.flowobjective.DefaultForwardingObjective;
75import org.onosproject.net.flowobjective.ForwardingObjective;
76import org.onosproject.net.flowobjective.FilteringObjective;
77import org.onosproject.net.flowobjective.DefaultObjectiveContext;
78import org.onosproject.net.flowobjective.ObjectiveContext;
79import org.onosproject.net.DeviceId;
Thomas Vachuskab6451472015-03-31 16:03:56 -070080import org.onosproject.net.host.HostService;
81import org.onosproject.net.intent.Constraint;
82import org.onosproject.net.intent.HostToHostIntent;
83import org.onosproject.net.intent.Intent;
84import org.onosproject.net.intent.IntentService;
85import org.slf4j.Logger;
86
Ray Milkeyd13a37b2015-06-12 11:55:17 -070087import com.fasterxml.jackson.databind.JsonNode;
88import com.fasterxml.jackson.databind.ObjectMapper;
89import com.fasterxml.jackson.databind.node.ObjectNode;
90import com.google.common.base.Predicate;
91import com.google.common.base.Stopwatch;
92import com.google.common.collect.FluentIterable;
93import com.google.common.collect.Lists;
94import com.google.common.collect.Sets;
95import com.google.common.util.concurrent.ThreadFactoryBuilder;
Thomas Vachuskab6451472015-03-31 16:03:56 -070096
97import static org.slf4j.LoggerFactory.getLogger;
98
99/**
100 * Application to set up demos.
101 */
102@Component(immediate = true)
103@Service
Jonathan Hartd9df7bd2015-11-10 17:10:25 -0800104public class DemoInstaller implements DemoApi {
Thomas Vachuskab6451472015-03-31 16:03:56 -0700105
106 private final Logger log = getLogger(getClass());
107
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected CoreService coreService;
110
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 protected IntentService intentService;
113
114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 protected HostService hostService;
116
117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 protected MastershipService mastershipService;
119
120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 protected ClusterService clusterService;
122
123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
124 protected DeviceService deviceService;
125
126 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
127 protected FlowRuleService flowService;
128
sivachidambaram subramanianf773b652017-05-09 14:40:04 +0530129 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
130 protected FlowObjectiveService objectiveService;
131
Thomas Vachuskab6451472015-03-31 16:03:56 -0700132 private ExecutorService worker;
133
134 private ExecutorService installWorker;
135
136 private ApplicationId appId;
137
138 private final Set<Intent> existingIntents = new HashSet<>();
139 private RandomInstaller randomInstaller;
140
141 private ObjectMapper mapper = new ObjectMapper();
142
sivachidambaram subramanianf773b652017-05-09 14:40:04 +0530143 private AtomicLong macIndex;
Thomas Vachuskab6451472015-03-31 16:03:56 -0700144
145
146 @Activate
147 public void activate() {
148 String nodeId = clusterService.getLocalNode().ip().toString();
149 appId = coreService.registerApplication("org.onosproject.demo.installer."
150 + nodeId);
151 worker = Executors.newFixedThreadPool(1,
152 new ThreadFactoryBuilder()
153 .setNameFormat("demo-app-worker")
154 .build());
155 log.info("Started with Application ID {}", appId.id());
156 }
157
158 @Deactivate
159 public void deactivate() {
160 shutdownAndAwaitTermination(worker);
161 if (installWorker != null && !installWorker.isShutdown()) {
162 shutdownAndAwaitTermination(installWorker);
163 }
164 log.info("Stopped");
165 }
166
167 @Override
168 public JsonNode flowTest(Optional<JsonNode> params) {
169 int flowsPerDevice = 1000;
170 int neighbours = 0;
171 boolean remove = true;
172 if (params.isPresent()) {
173 flowsPerDevice = params.get().get("flowsPerDevice").asInt();
174 neighbours = params.get().get("neighbours").asInt();
175 remove = params.get().get("remove").asBoolean();
176 }
177
178 Future<JsonNode> future = worker.submit(new FlowTest(flowsPerDevice, neighbours, remove));
179
180 try {
181 return future.get(10, TimeUnit.SECONDS);
182 } catch (InterruptedException | ExecutionException | TimeoutException e) {
183 ObjectNode node = mapper.createObjectNode();
184 node.put("Error", e.getMessage());
185 return node;
186 }
187 }
188
189 @Override
sivachidambaram subramanianf773b652017-05-09 14:40:04 +0530190 public JsonNode flowObjTest(Optional<JsonNode> params) {
191 int flowObjPerDevice = 1000;
192 int neighbours = 0;
193 boolean remove = true;
194 String typeObj = "forward";
195 if (params.isPresent()) {
196 flowObjPerDevice = params.get().get("flowObjPerDevice").asInt();
197 neighbours = params.get().get("neighbours").asInt();
198 remove = params.get().get("remove").asBoolean();
199 typeObj = params.get().get("typeObj").asText().toString();
200 }
201
202 Future<JsonNode> future = worker.submit(new FlowObjTest(flowObjPerDevice, neighbours, remove, typeObj));
203
204 try {
205 return future.get(10, TimeUnit.SECONDS);
206 } catch (InterruptedException | ExecutionException | TimeoutException e) {
207 ObjectNode node = mapper.createObjectNode();
208 node.put("Error", e.getMessage());
209 return node;
210 }
211 }
212
213 @Override
Thomas Vachuskab6451472015-03-31 16:03:56 -0700214 public void setup(InstallType type, Optional<JsonNode> runParams) {
215 switch (type) {
216 case MESH:
217 log.debug("Installing mesh intents");
218 worker.execute(new MeshInstaller());
219 break;
220 case RANDOM:
221 //check that we do not have a random installer running
222 if (installWorker == null || installWorker.isShutdown()) {
223 installWorker = Executors.newFixedThreadPool(1,
224 new ThreadFactoryBuilder()
225 .setNameFormat("random-worker")
226 .build());
227 log.debug("Installing random sequence of intents");
228 randomInstaller = new RandomInstaller(runParams);
229 installWorker.execute(randomInstaller);
230 } else {
231 log.warn("Random installer is already running");
232 }
233 break;
234 default:
235 throw new IllegalArgumentException("What is it you want exactly?");
236 }
237 }
238
239 @Override
240 public void tearDown() {
241 worker.submit(new UnInstaller());
242 }
243
244
245 /**
246 * Simply installs a mesh of intents from all the hosts existing in the network.
247 */
248 private class MeshInstaller implements Runnable {
249
250 @Override
251 public void run() {
252 TrafficSelector selector = DefaultTrafficSelector.emptySelector();
253 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
254 List<Constraint> constraint = Lists.newArrayList();
255 List<Host> hosts = Lists.newArrayList(hostService.getHosts());
256 while (!hosts.isEmpty()) {
257 Host src = hosts.remove(0);
258 for (Host dst : hosts) {
259 HostToHostIntent intent = HostToHostIntent.builder()
260 .appId(appId)
261 .one(src.id())
262 .two(dst.id())
263 .selector(selector)
264 .treatment(treatment)
265 .constraints(constraint)
266 .build();
267 existingIntents.add(intent);
268 intentService.submit(intent);
269 }
270 }
271 }
272 }
273
274 /**
275 * Randomly installs and withdraws intents.
276 */
277 private class RandomInstaller implements Runnable {
278
279 private final boolean isLocal;
280 private final Set<Host> hosts;
281
Ray Milkeyb68bbbc2017-12-18 10:05:49 -0800282 private final Random random = new SecureRandom();
Thomas Vachuskab6451472015-03-31 16:03:56 -0700283
284 private Set<HostPair> uninstalledOrWithdrawn;
285 private Set<HostPair> installed;
286
287 private CountDownLatch latch;
288
289 //used to wait on a batch to be processed.
290 private static final int ITERATIONMAX = 50000000;
291
292
293 public RandomInstaller(Optional<JsonNode> runParams) {
294 /*
295 Check if we have params and honour them. Otherwise
296 set defaults to processing only local stuff and
297 all local hosts.
298 */
299 if (runParams.isPresent()) {
300 JsonNode node = runParams.get();
301 isLocal = node.get("local").asBoolean();
302 hosts = node.get("hosts") == null ? Sets.newHashSet(hostService.getHosts()) :
303 constructHostIds(node.get("hosts").elements());
304 } else {
305 isLocal = true;
306 hosts = Sets.newHashSet(hostService.getHosts());
307 }
308
309 //construct list of intents.
310 installed = Sets.newHashSet();
311 if (isLocal) {
312 uninstalledOrWithdrawn = buildPairs(pruneHostsByMasterShip());
313 } else {
314 uninstalledOrWithdrawn = buildPairs(hosts);
315 }
316
317 }
318
319 private Set<Host> constructHostIds(Iterator<JsonNode> elements) {
320 Set<Host> hostIds = Sets.newHashSet();
321 JsonNode n;
322 while (elements.hasNext()) {
323 n = elements.next();
324 hostIds.add(hostService.getHost(HostId.hostId(n.textValue())));
325 }
326 return hostIds;
327 }
328
329 @Override
330 public void run() {
331 if (!installWorker.isShutdown()) {
332 randomize();
333 latch = new CountDownLatch(1);
334 try {
335 trackIntents();
336 } catch (InterruptedException e) {
337 shutdown();
338 }
339 }
340
341 }
342
343
344 /**
345 * Check whether the previously submitted batch is in progress
346 * and if yes submit the next one. If things hang, wait for at
347 * most 5 seconds and bail.
348 * @throws InterruptedException if the thread go interupted
349 */
350 private void trackIntents() throws InterruptedException {
351 //FIXME
352 // TODO generate keys for each set of intents to allow manager to throttle
353 // TODO may also look into the store to see how many operations are pending
354
355 //if everything is good proceed.
356 if (!installWorker.isShutdown()) {
357 installWorker.execute(this);
358 }
359
360 }
361
362 public void shutdown() {
363 log.warn("Shutting down random installer!");
364 cleanUp();
365 }
366
367
368 /**
369 * Shuffle the uninstalled and installed list (separately) and select
370 * a random number of them and install or uninstall them respectively.
371 */
372 private void randomize() {
373 List<HostPair> hostList = new LinkedList<>(uninstalledOrWithdrawn);
374 Collections.shuffle(hostList);
375 List<HostPair> toInstall = hostList.subList(0,
376 random.nextInt(hostList.size() - 1));
377 List<HostPair> toRemove;
378 if (!installed.isEmpty()) {
379 hostList = new LinkedList<>(installed);
380 Collections.shuffle(hostList);
381 toRemove = hostList.subList(0,
382 random.nextInt(hostList.size() - 1));
383 uninstallIntents(toRemove);
384 }
385 installIntents(toInstall);
386
387 }
388
389 private void installIntents(List<HostPair> toInstall) {
390 for (HostPair pair : toInstall) {
391 installed.add(pair);
392 uninstalledOrWithdrawn.remove(pair);
393 intentService.submit(pair.h2hIntent());
394 }
395 }
396
397 private void uninstallIntents(Collection<HostPair> toRemove) {
398 for (HostPair pair : toRemove) {
399 installed.remove(pair);
400 uninstalledOrWithdrawn.add(pair);
401 intentService.withdraw(pair.h2hIntent());
402 }
403 }
404
405 /**
406 * Take everything and remove it all.
407 */
408 private void cleanUp() {
409 List<HostPair> allPairs = Lists.newArrayList(installed);
410 allPairs.addAll(uninstalledOrWithdrawn);
411 for (HostPair pair : allPairs) {
412 intentService.withdraw(pair.h2hIntent());
413 }
414 }
415
416
417 private Set<HostPair> buildPairs(Set<Host> hosts) {
418 Set<HostPair> pairs = Sets.newHashSet();
419 Iterator<Host> it = Sets.newHashSet(hosts).iterator();
420 while (it.hasNext()) {
421 Host src = it.next();
422 it.remove();
423 for (Host dst : hosts) {
424 pairs.add(new HostPair(src, dst));
425 }
426 }
427 return pairs;
428 }
429
430 private Set<Host> pruneHostsByMasterShip() {
431 return FluentIterable.from(hosts)
432 .filter(hasLocalMaster())
433 .toSet();
434
435 }
436
437 private Predicate<? super Host> hasLocalMaster() {
Sho SHIMIZU74626412015-09-11 11:46:27 -0700438 return host -> mastershipService.getLocalRole(
439 host.location().deviceId()).equals(MastershipRole.MASTER);
Thomas Vachuskab6451472015-03-31 16:03:56 -0700440 }
441
442
443 /**
444 * Simple class representing a pair of hosts and precomputes the associated
445 * h2h intent.
446 */
447 private class HostPair {
448
449 private final Host src;
450 private final Host dst;
451
452 private final TrafficSelector selector = DefaultTrafficSelector.emptySelector();
453 private final TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
454 private final List<Constraint> constraint = Lists.newArrayList();
455 private final HostToHostIntent intent;
456
457 public HostPair(Host src, Host dst) {
458 this.src = src;
459 this.dst = dst;
460 this.intent = HostToHostIntent.builder()
461 .appId(appId)
462 .one(src.id())
463 .two(dst.id())
464 .selector(selector)
465 .treatment(treatment)
466 .constraints(constraint)
467 .build();
468 }
469
470 public HostToHostIntent h2hIntent() {
471 return intent;
472 }
473
474 @Override
475 public boolean equals(Object o) {
476 if (this == o) {
477 return true;
478 }
479 if (o == null || getClass() != o.getClass()) {
480 return false;
481 }
482
483 HostPair hostPair = (HostPair) o;
484
485 return Objects.equals(src, hostPair.src) &&
486 Objects.equals(dst, hostPair.dst);
487
488 }
489
490 @Override
491 public int hashCode() {
492 return Objects.hash(src, dst);
493 }
494
495
496 }
497
498 }
499
500 /**
501 * Remove anything that is running and clear it all out.
502 */
503 private class UnInstaller implements Runnable {
504 @Override
505 public void run() {
506 if (!existingIntents.isEmpty()) {
507 clearExistingIntents();
508 }
509
510 if (installWorker != null && !installWorker.isShutdown()) {
511 shutdownAndAwaitTermination(installWorker);
512 randomInstaller.shutdown();
513 }
514 }
515
516 private void clearExistingIntents() {
517 for (Intent i : existingIntents) {
518 intentService.withdraw(i);
519 }
520 existingIntents.clear();
521 }
522 }
523
524 /**
525 * Shutdown a pool cleanly if possible.
526 *
527 * @param pool an executorService
528 */
529 private void shutdownAndAwaitTermination(ExecutorService pool) {
530 pool.shutdown(); // Disable new tasks from being submitted
531 try {
532 // Wait a while for existing tasks to terminate
533 if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
534 pool.shutdownNow(); // Cancel currently executing tasks
535 // Wait a while for tasks to respond to being cancelled
536 if (!pool.awaitTermination(10, TimeUnit.SECONDS)) {
537 log.error("Pool did not terminate");
538 }
539 }
540 } catch (Exception ie) {
541 // (Re-)Cancel if current thread also interrupted
542 pool.shutdownNow();
543 // Preserve interrupt status
544 Thread.currentThread().interrupt();
545 }
546 }
547
548 private class FlowTest implements Callable<JsonNode> {
549 private final int flowPerDevice;
550 private final int neighbours;
551 private final boolean remove;
552 private FlowRuleOperations.Builder adds;
553 private FlowRuleOperations.Builder removes;
554
555 public FlowTest(int flowsPerDevice, int neighbours, boolean remove) {
556 this.flowPerDevice = flowsPerDevice;
557 this.neighbours = neighbours;
558 this.remove = remove;
559 prepareInstallation();
560 }
561
562 private void prepareInstallation() {
563 Set<ControllerNode> instances = Sets.newHashSet(clusterService.getNodes());
564 instances.remove(clusterService.getLocalNode());
565 Set<NodeId> acceptableNodes = Sets.newHashSet();
566 if (neighbours >= instances.size()) {
567 instances.forEach(instance -> acceptableNodes.add(instance.id()));
568 } else {
569 Iterator<ControllerNode> nodes = instances.iterator();
570 for (int i = neighbours; i > 0; i--) {
571 acceptableNodes.add(nodes.next().id());
572 }
573 }
574 acceptableNodes.add(clusterService.getLocalNode().id());
575
576 Set<Device> devices = Sets.newHashSet();
577 for (Device dev : deviceService.getDevices()) {
578 if (acceptableNodes.contains(
579 mastershipService.getMasterFor(dev.id()))) {
580 devices.add(dev);
581 }
582 }
583
584 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
585 .setOutput(PortNumber.portNumber(RandomUtils.nextInt())).build();
586 TrafficSelector.Builder sbuilder;
587 FlowRuleOperations.Builder rules = FlowRuleOperations.builder();
588 FlowRuleOperations.Builder remove = FlowRuleOperations.builder();
589
590 for (Device d : devices) {
Ray Milkey3717e602018-02-01 13:49:47 -0800591 for (long i = 0; i < this.flowPerDevice; i++) {
Thomas Vachuskab6451472015-03-31 16:03:56 -0700592 sbuilder = DefaultTrafficSelector.builder();
593
594 sbuilder.matchEthSrc(MacAddress.valueOf(RandomUtils.nextInt() * i))
595 .matchEthDst(MacAddress.valueOf((Integer.MAX_VALUE - i) * RandomUtils.nextInt()));
596
597
YPZhang47309762016-06-17 16:27:41 -0700598 int randomPriority = RandomUtils.nextInt(FlowRule.MAX_PRIORITY);
Ray Milkeyd13a37b2015-06-12 11:55:17 -0700599 FlowRule f = DefaultFlowRule.builder()
600 .forDevice(d.id())
601 .withSelector(sbuilder.build())
602 .withTreatment(treatment)
603 .withPriority(randomPriority)
604 .fromApp(appId)
605 .makeTemporary(10)
606 .build();
Thomas Vachuskab6451472015-03-31 16:03:56 -0700607 rules.add(f);
608 remove.remove(f);
609
610 }
611 }
612
613 this.adds = rules;
614 this.removes = remove;
615 }
616
617 @Override
618 public JsonNode call() throws Exception {
619 ObjectNode node = mapper.createObjectNode();
620 CountDownLatch latch = new CountDownLatch(1);
621 flowService.apply(adds.build(new FlowRuleOperationsContext() {
622
623 private final Stopwatch timer = Stopwatch.createStarted();
624
625 @Override
626 public void onSuccess(FlowRuleOperations ops) {
627
628 long elapsed = timer.elapsed(TimeUnit.MILLISECONDS);
629 node.put("elapsed", elapsed);
630
631
632 latch.countDown();
633 }
634 }));
635
636 latch.await(10, TimeUnit.SECONDS);
637 if (this.remove) {
638 flowService.apply(removes.build());
639 }
640 return node;
641 }
642 }
sivachidambaram subramanianf773b652017-05-09 14:40:04 +0530643
644 private class FlowObjTest implements Callable<JsonNode> {
645 private final int flowObjPerDevice;
646 private final int neighbours;
647 private final boolean remove;
648 private final String typeObj;
649 Map<DeviceId, Set<ForwardingObjective.Builder>> forwardingObj = new HashMap<>();
650 Map<DeviceId, Set<FilteringObjective.Builder>> filteringObj = new HashMap<>();
651
652 public FlowObjTest(int flowObjPerDevice, int neighbours, boolean remove, String typeObj) {
653 this.flowObjPerDevice = flowObjPerDevice;
654 this.neighbours = neighbours;
655 this.remove = remove;
656 this.typeObj = typeObj;
657 prepareInstallation();
658 }
659
660 private void prepareInstallation() {
661 Set<ControllerNode> instances = Sets.newHashSet(clusterService.getNodes());
662 instances.remove(clusterService.getLocalNode());
663 Set<NodeId> acceptableNodes = Sets.newHashSet();
664 macIndex = new AtomicLong(0);
665 if (neighbours >= instances.size()) {
666 instances.forEach(instance -> acceptableNodes.add(instance.id()));
667 } else {
668 Iterator<ControllerNode> nodes = instances.iterator();
669 for (int i = neighbours; i > 0; i--) {
670 acceptableNodes.add(nodes.next().id());
671 }
672 }
673 acceptableNodes.add(clusterService.getLocalNode().id());
674
675 Set<Device> devices = Sets.newHashSet();
676 for (Device dev : deviceService.getDevices()) {
677 if (acceptableNodes.contains(
678 mastershipService.getMasterFor(dev.id()))) {
679 devices.add(dev);
680 }
681 }
682 for (Device device : devices) {
683 switch (this.typeObj) {
684 case "forward":
685 forwardingObj.put(device.id(), createForward(flowObjPerDevice));
686 break;
687 case "filter":
688 filteringObj.put(device.id(), createFilter(flowObjPerDevice));
689 break;
690 default:
691 log.warn("Unsupported Flow Objective Type");
692 break;
693 }
694 }
695 }
696
697 /*
698 * Method to create forwarding flow objectives.
699 */
700 private Set<ForwardingObjective.Builder> createForward(int flowObjPerDevice) {
701 Set<ForwardingObjective.Builder> fObj = new HashSet<>();
702 for (int i = 0; i < flowObjPerDevice; i++) {
703 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
704 sbuilder.matchEthSrc(MacAddress.valueOf(macIndex.incrementAndGet()));
705 sbuilder.matchInPort(PortNumber.portNumber(2));
706
707 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
708 tbuilder.add(Instructions.createOutput(PortNumber.portNumber(3)));
709
710 ForwardingObjective.Builder fobBuilder = DefaultForwardingObjective.builder();
711 fobBuilder.withFlag(ForwardingObjective.Flag.SPECIFIC)
712 .withSelector(sbuilder.build())
713 .withTreatment(tbuilder.build())
714 .withPriority(i + 1)
715 .fromApp(appId)
716 .makePermanent();
717
718 fObj.add(fobBuilder);
719 }
720 return fObj;
721 }
722
723 /*
724 *Method to install forwarding flow objectives.
725 */
726 private ObjectNode installForward() {
727 ObjectNode node = mapper.createObjectNode();
728 long addStartTime = System.currentTimeMillis();
Sivachidambaram Subramanian89a09ec2017-07-11 09:46:34 +0000729 int totalFlowObj = (flowObjPerDevice * forwardingObj.keySet().size());
sivachidambaram subramanianf773b652017-05-09 14:40:04 +0530730 CountDownLatch installationLatch = new CountDownLatch(totalFlowObj);
731 for (DeviceId dId : forwardingObj.keySet()) {
732 Set<ForwardingObjective.Builder> fObjs = forwardingObj.get(dId);
733 for (ForwardingObjective.Builder builder : fObjs) {
734 ObjectiveContext context = new DefaultObjectiveContext(
735 (objective -> {
736 installationLatch.countDown();
737 })
738 );
739 objectiveService.forward(dId, builder.add(context));
740 }
741 }
742
743 try {
Sivachidambaram Subramanian89a09ec2017-07-11 09:46:34 +0000744 installationLatch.await(10, TimeUnit.SECONDS);
sivachidambaram subramanianf773b652017-05-09 14:40:04 +0530745 } catch (InterruptedException e) {
746 Thread.interrupted();
747 }
748
749 node.put("elapsed", System.currentTimeMillis() - addStartTime);
750 log.info("{} Forward Flow Objectives elapsed -> {} ms",
751 totalFlowObj, (System.currentTimeMillis() - addStartTime));
752
753 if (this.remove) {
754 for (DeviceId dId : forwardingObj.keySet()) {
755 Set<ForwardingObjective.Builder> fObjs = forwardingObj.get(dId);
756 for (ForwardingObjective.Builder builder : fObjs) {
757 objectiveService.forward(dId, builder.remove());
758 }
759 }
760 }
761 return node;
762
763 }
764
765 /*
766 * Method to create filtering flow objectives.
767 */
768 private Set<FilteringObjective.Builder> createFilter(int flowObjPerDevice) {
769 Set<FilteringObjective.Builder> filterObjSet = new HashSet<>();
770 for (int i = 0; i < flowObjPerDevice; i++) {
771 TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
772 tbuilder.add(Instructions.createOutput(PortNumber.portNumber(2)));
Sivachidambaram Subramanian89a09ec2017-07-11 09:46:34 +0000773 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
Ray Milkey3717e602018-02-01 13:49:47 -0800774 sbuilder.matchInPort(PortNumber.portNumber(i + 3L));
Sivachidambaram Subramanian89a09ec2017-07-11 09:46:34 +0000775 sbuilder.matchEthDst(MacAddress.valueOf("12:00:00:00:00:10"));
sivachidambaram subramanianf773b652017-05-09 14:40:04 +0530776
777 FilteringObjective.Builder fobBuilder = DefaultFilteringObjective.builder();
778 fobBuilder.fromApp(appId)
Sivachidambaram Subramanian89a09ec2017-07-11 09:46:34 +0000779 .withKey(sbuilder.build().getCriterion(Criterion.Type.IN_PORT))
780 .addCondition(sbuilder.build().getCriterion(Criterion.Type.ETH_DST))
sivachidambaram subramanianf773b652017-05-09 14:40:04 +0530781 .withMeta(tbuilder.build())
782 .permit()
783 .withPriority(i + 1)
784 .makePermanent();
785
786 filterObjSet.add(fobBuilder);
787 }
788
789 return filterObjSet;
790 }
791
792 /*
793 * Method to install filtering flow objectives.
794 */
795 private ObjectNode installFilter() {
796 ObjectNode node = mapper.createObjectNode();
797 long addStartTime = System.currentTimeMillis();
Sivachidambaram Subramanian89a09ec2017-07-11 09:46:34 +0000798 int totalFlowObj = (flowObjPerDevice * filteringObj.keySet().size());
sivachidambaram subramanianf773b652017-05-09 14:40:04 +0530799 CountDownLatch installationLatch = new CountDownLatch(totalFlowObj);
800 for (DeviceId dId : filteringObj.keySet()) {
801 Set<FilteringObjective.Builder> fObjs = filteringObj.get(dId);
802 for (FilteringObjective.Builder builder : fObjs) {
803 ObjectiveContext context = new DefaultObjectiveContext(
804 (objective -> {
805 installationLatch.countDown();
806 })
807 );
808 objectiveService.filter(dId, builder.add(context));
809 }
810 }
811
812 try {
Sivachidambaram Subramanian89a09ec2017-07-11 09:46:34 +0000813 installationLatch.await(10, TimeUnit.SECONDS);
sivachidambaram subramanianf773b652017-05-09 14:40:04 +0530814 } catch (InterruptedException e) {
815 Thread.interrupted();
816 }
817
818 node.put("elapsed", System.currentTimeMillis() - addStartTime);
819 log.info("{} Filter Flow Objectives elapsed -> {} ms",
820 totalFlowObj, (System.currentTimeMillis() - addStartTime));
821
822 if (this.remove) {
823 for (DeviceId dId : filteringObj.keySet()) {
824 Set<FilteringObjective.Builder> fObjs = filteringObj.get(dId);
825 for (FilteringObjective.Builder builder : fObjs) {
826 objectiveService.filter(dId, builder.remove());
827 }
828 }
829 }
830 return node;
831 }
832
833
834 @Override
835 public JsonNode call() throws Exception {
836 ObjectNode node = mapper.createObjectNode();
837 switch (this.typeObj) {
838 case "forward":
839 node = installForward();
840 break;
841 case "filter":
842 node = installFilter();
843 break;
844 default:
845 log.warn("Unsupported Flow Objective Type");
846 }
847 return node;
848 }
849 }
Thomas Vachuskab6451472015-03-31 16:03:56 -0700850}
851
852