blob: 05c44512d309a0ff8f57683cb2865abe64a5f5d3 [file] [log] [blame]
alshabibab984662014-12-04 18:56:18 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
alshabibab984662014-12-04 18:56:18 -08003 *
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 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.cli.net;
alshabib5afcbd72014-10-30 16:28:40 +010017
Ray Milkey9f87e512016-01-05 10:00:22 -080018import java.util.ArrayList;
19import java.util.concurrent.CountDownLatch;
20import java.util.concurrent.TimeUnit;
21
Brian O'Connor72cb19a2015-01-16 16:14:41 -080022import org.apache.commons.lang.math.RandomUtils;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070023import org.apache.karaf.shell.api.action.Argument;
24import org.apache.karaf.shell.api.action.Command;
25import org.apache.karaf.shell.api.action.lifecycle.Service;
Brian O'Connor72cb19a2015-01-16 16:14:41 -080026import org.onlab.packet.MacAddress;
Brian O'Connorabafb502014-12-02 22:26:20 -080027import org.onosproject.cli.AbstractShellCommand;
Brian O'Connor72cb19a2015-01-16 16:14:41 -080028import org.onosproject.core.ApplicationId;
29import org.onosproject.core.CoreService;
Brian O'Connorabafb502014-12-02 22:26:20 -080030import org.onosproject.net.Device;
31import org.onosproject.net.PortNumber;
32import org.onosproject.net.device.DeviceService;
Brian O'Connorabafb502014-12-02 22:26:20 -080033import org.onosproject.net.flow.DefaultFlowRule;
34import org.onosproject.net.flow.DefaultTrafficSelector;
35import org.onosproject.net.flow.DefaultTrafficTreatment;
Yuta HIGUCHI160732b2017-05-22 16:36:43 -070036import org.onosproject.net.flow.FlowEntry.FlowEntryState;
Ray Milkeyd13a37b2015-06-12 11:55:17 -070037import org.onosproject.net.flow.FlowRule;
Brian O'Connor72cb19a2015-01-16 16:14:41 -080038import org.onosproject.net.flow.FlowRuleOperations;
39import org.onosproject.net.flow.FlowRuleOperationsContext;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.flow.FlowRuleService;
41import org.onosproject.net.flow.TrafficSelector;
42import org.onosproject.net.flow.TrafficTreatment;
alshabib5afcbd72014-10-30 16:28:40 +010043
Ray Milkey9f87e512016-01-05 10:00:22 -080044import com.fasterxml.jackson.databind.ObjectMapper;
45import com.fasterxml.jackson.databind.node.ArrayNode;
46import com.fasterxml.jackson.databind.node.ObjectNode;
47import com.google.common.base.Stopwatch;
Yuta HIGUCHI160732b2017-05-22 16:36:43 -070048import com.google.common.collect.Iterables;
Ray Milkey9f87e512016-01-05 10:00:22 -080049import com.google.common.collect.Lists;
Yuta HIGUCHI160732b2017-05-22 16:36:43 -070050import com.google.common.collect.Streams;
Ray Milkey9f87e512016-01-05 10:00:22 -080051
alshabib5afcbd72014-10-30 16:28:40 +010052/**
Charles M.C. Chan6f5bdc62015-04-22 01:21:09 +080053 * Installs bulk flows.
alshabib5afcbd72014-10-30 16:28:40 +010054 */
Ray Milkeyd84f89b2018-08-17 14:54:17 -070055@Service
suibin zhangcb7f0d12015-08-10 11:14:15 -070056@Command(scope = "onos", name = "add-test-flows",
Ray Milkey82895d72015-01-22 17:06:00 -080057 description = "Installs a number of test flow rules - for testing only")
suibin zhangcb7f0d12015-08-10 11:14:15 -070058public class AddTestFlowsCommand extends AbstractShellCommand {
alshabib5afcbd72014-10-30 16:28:40 +010059
Carmelo Casconec9b39d62017-08-24 13:35:02 +020060 private static final int MAX_OUT_PORT = 254;
Deepa Vaddireddy2f4883d2016-06-07 22:51:01 +053061
Brian O'Connor72cb19a2015-01-16 16:14:41 -080062 private CountDownLatch latch;
63
alshabib5afcbd72014-10-30 16:28:40 +010064 @Argument(index = 0, name = "flowPerDevice", description = "Number of flows to add per device",
65 required = true, multiValued = false)
66 String flows = null;
67
alshabib3460da12014-10-30 17:26:49 +010068 @Argument(index = 1, name = "numOfRuns", description = "Number of iterations",
69 required = true, multiValued = false)
70 String numOfRuns = null;
alshabib5afcbd72014-10-30 16:28:40 +010071
72 @Override
Ray Milkeyd84f89b2018-08-17 14:54:17 -070073 protected void doExecute() {
alshabib5afcbd72014-10-30 16:28:40 +010074 FlowRuleService flowService = get(FlowRuleService.class);
75 DeviceService deviceService = get(DeviceService.class);
Brian O'Connor72cb19a2015-01-16 16:14:41 -080076 CoreService coreService = get(CoreService.class);
77
78 ApplicationId appId = coreService.registerApplication("onos.test.flow.installer");
alshabib5afcbd72014-10-30 16:28:40 +010079
80 int flowsPerDevice = Integer.parseInt(flows);
alshabib3460da12014-10-30 17:26:49 +010081 int num = Integer.parseInt(numOfRuns);
alshabib5afcbd72014-10-30 16:28:40 +010082
alshabib3460da12014-10-30 17:26:49 +010083 ArrayList<Long> results = Lists.newArrayList();
alshabib5afcbd72014-10-30 16:28:40 +010084 Iterable<Device> devices = deviceService.getDevices();
85 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Deepa Vaddireddy2f4883d2016-06-07 22:51:01 +053086 .setOutput(PortNumber.portNumber(RandomUtils.nextInt(MAX_OUT_PORT))).build();
alshabib5afcbd72014-10-30 16:28:40 +010087 TrafficSelector.Builder sbuilder;
Brian O'Connor72cb19a2015-01-16 16:14:41 -080088 FlowRuleOperations.Builder rules = FlowRuleOperations.builder();
89 FlowRuleOperations.Builder remove = FlowRuleOperations.builder();
90
alshabib5afcbd72014-10-30 16:28:40 +010091 for (Device d : devices) {
Ray Milkey3717e602018-02-01 13:49:47 -080092 for (long i = 0; i < flowsPerDevice; i++) {
alshabib5afcbd72014-10-30 16:28:40 +010093 sbuilder = DefaultTrafficSelector.builder();
Brian O'Connor72cb19a2015-01-16 16:14:41 -080094
95 sbuilder.matchEthSrc(MacAddress.valueOf(RandomUtils.nextInt() * i))
96 .matchEthDst(MacAddress.valueOf((Integer.MAX_VALUE - i) * RandomUtils.nextInt()));
97
98
Carolina Fernandezfb4b04a2016-12-24 14:48:16 +010099 int randomPriority = RandomUtils.nextInt(
100 FlowRule.MAX_PRIORITY - FlowRule.MIN_PRIORITY + 1) + FlowRule.MIN_PRIORITY;
Ray Milkeyd13a37b2015-06-12 11:55:17 -0700101
102 FlowRule addRule = DefaultFlowRule.builder()
103 .forDevice(d.id())
104 .withSelector(sbuilder.build())
105 .withTreatment(treatment)
106 .withPriority(randomPriority)
107 .fromApp(appId)
108 .makeTemporary(10)
109 .build();
110 FlowRule removeRule = DefaultFlowRule.builder()
111 .forDevice(d.id())
112 .withSelector(sbuilder.build())
113 .withTreatment(treatment)
114 .withPriority(randomPriority)
115 .fromApp(appId)
116 .makeTemporary(10)
117 .build();
118
119 rules.add(addRule);
120 remove.remove(removeRule);
alshabib5afcbd72014-10-30 16:28:40 +0100121
122 }
123 }
Yuta HIGUCHI160732b2017-05-22 16:36:43 -0700124 // close stages
125 rules.newStage();
126 remove.newStage();
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800127
alshabib3460da12014-10-30 17:26:49 +0100128 for (int i = 0; i < num; i++) {
Yuta HIGUCHI160732b2017-05-22 16:36:43 -0700129 printProgress("Run %d:", i);
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800130 latch = new CountDownLatch(2);
Yuta HIGUCHI160732b2017-05-22 16:36:43 -0700131 final CountDownLatch addSuccess = new CountDownLatch(1);
132 printProgress("..batch add request");
133 Stopwatch add = Stopwatch.createStarted();
134
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800135 flowService.apply(rules.build(new FlowRuleOperationsContext() {
136
137 private final Stopwatch timer = Stopwatch.createStarted();
138
139 @Override
140 public void onSuccess(FlowRuleOperations ops) {
141
142 timer.stop();
Yuta HIGUCHI160732b2017-05-22 16:36:43 -0700143 printProgress("..add success");
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800144 results.add(timer.elapsed(TimeUnit.MILLISECONDS));
145 if (results.size() == num) {
146 if (outputJson()) {
147 print("%s", json(new ObjectMapper(), true, results));
148 } else {
149 printTime(true, results);
150 }
151 }
152 latch.countDown();
Yuta HIGUCHI160732b2017-05-22 16:36:43 -0700153 addSuccess.countDown();
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800154 }
155 }));
156
Yuta HIGUCHI160732b2017-05-22 16:36:43 -0700157 try {
158 addSuccess.await();
159 // wait until all flows reaches ADDED state
160 while (!Streams.stream(flowService.getFlowEntriesById(appId))
161 .allMatch(fr -> fr.state() == FlowEntryState.ADDED)) {
162 Thread.sleep(100);
163 }
164 add.stop();
165 printProgress("..completed %d ± 100 ms", add.elapsed(TimeUnit.MILLISECONDS));
166 } catch (InterruptedException e1) {
167 printProgress("Interrupted");
168 Thread.currentThread().interrupt();
169 }
170
171 printProgress("..cleaning up");
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800172 flowService.apply(remove.build(new FlowRuleOperationsContext() {
173 @Override
174 public void onSuccess(FlowRuleOperations ops) {
175 latch.countDown();
176 }
177 }));
Yuta HIGUCHI160732b2017-05-22 16:36:43 -0700178
alshabib3460da12014-10-30 17:26:49 +0100179 try {
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800180 latch.await();
Yuta HIGUCHI160732b2017-05-22 16:36:43 -0700181 while (!Iterables.isEmpty(flowService.getFlowEntriesById(appId))) {
182 Thread.sleep(500);
183 }
Brian O'Connor72cb19a2015-01-16 16:14:41 -0800184 } catch (InterruptedException e) {
Yuta HIGUCHI160732b2017-05-22 16:36:43 -0700185 printProgress("Interrupted.");
186 Thread.currentThread().interrupt();
alshabib3460da12014-10-30 17:26:49 +0100187 }
Yuta HIGUCHI160732b2017-05-22 16:36:43 -0700188 }
189 if (outputJson()) {
190 print("%s", json(new ObjectMapper(), true, results));
191 } else {
192 printTime(true, results);
alshabib5afcbd72014-10-30 16:28:40 +0100193 }
alshabib5afcbd72014-10-30 16:28:40 +0100194 }
195
alshabib3460da12014-10-30 17:26:49 +0100196 private Object json(ObjectMapper mapper, boolean isSuccess, ArrayList<Long> elapsed) {
197 ObjectNode result = mapper.createObjectNode();
198 result.put("Success", isSuccess);
199 ArrayNode node = result.putArray("elapsed-time");
200 for (Long v : elapsed) {
201 node.add(v);
202 }
203 return result;
204 }
205
Yuta HIGUCHI160732b2017-05-22 16:36:43 -0700206 private void printProgress(String format, Object... args) {
207 if (!outputJson()) {
208 print(format, args);
209 }
210 }
211
212
alshabib3460da12014-10-30 17:26:49 +0100213 private void printTime(boolean isSuccess, ArrayList<Long> elapsed) {
214 print("Run is %s.", isSuccess ? "success" : "failure");
215 for (int i = 0; i < elapsed.size(); i++) {
Yuta HIGUCHI160732b2017-05-22 16:36:43 -0700216 print(" Run %s : %s ms", i, elapsed.get(i));
alshabib3460da12014-10-30 17:26:49 +0100217 }
218 }
alshabib5afcbd72014-10-30 16:28:40 +0100219}