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