blob: 5911fa8564e9e648664faa8640a074c9a92db25d [file] [log] [blame]
Brian O'Connor66cfbfa2015-02-17 18:17:32 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Brian O'Connor66cfbfa2015-02-17 18:17:32 -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 */
16package org.onosproject.cli.net;
17
Ray Milkey3e3ec5f2015-03-17 17:00:38 -070018import java.util.EnumSet;
19import java.util.List;
20import java.util.concurrent.CountDownLatch;
21import java.util.concurrent.atomic.AtomicLong;
22
Brian O'Connor66cfbfa2015-02-17 18:17:32 -080023import org.apache.karaf.shell.commands.Argument;
24import org.apache.karaf.shell.commands.Command;
25import org.onlab.packet.Ethernet;
26import org.onlab.packet.MacAddress;
27import org.onosproject.cli.AbstractShellCommand;
28import org.onosproject.net.ConnectPoint;
29import org.onosproject.net.DeviceId;
30import org.onosproject.net.PortNumber;
31import org.onosproject.net.flow.DefaultTrafficSelector;
32import org.onosproject.net.flow.DefaultTrafficTreatment;
33import org.onosproject.net.flow.TrafficSelector;
34import org.onosproject.net.flow.TrafficTreatment;
35import org.onosproject.net.intent.Intent;
36import org.onosproject.net.intent.IntentEvent;
37import org.onosproject.net.intent.IntentEvent.Type;
38import org.onosproject.net.intent.IntentListener;
39import org.onosproject.net.intent.IntentService;
40import org.onosproject.net.intent.Key;
41import org.onosproject.net.intent.PointToPointIntent;
42
Ray Milkey3e3ec5f2015-03-17 17:00:38 -070043import com.google.common.collect.Lists;
Brian O'Connor66cfbfa2015-02-17 18:17:32 -080044
45import static org.onlab.util.Tools.delay;
46import static org.onosproject.net.DeviceId.deviceId;
47import static org.onosproject.net.PortNumber.portNumber;
48
49/**
50 * Installs point-to-point connectivity intents.
51 */
52@Command(scope = "onos", name = "cycle-intents",
53 description = "Installs random intents to test throughput")
54public class IntentCycleCommand extends AbstractShellCommand
55 implements IntentListener {
56
57 @Argument(index = 0, name = "ingressDevice",
58 description = "Ingress Device/Port Description",
59 required = true, multiValued = false)
60 String ingressDeviceString = null;
61
62 @Argument(index = 1, name = "egressDevice",
63 description = "Egress Device/Port Description",
64 required = true, multiValued = false)
65 String egressDeviceString = null;
66
67 @Argument(index = 2, name = "numberOfIntents",
68 description = "Number of intents to install/withdraw",
69 required = true, multiValued = false)
70 String numberOfIntents = null;
71
72 @Argument(index = 3, name = "keyOffset",
73 description = "Starting point for first key (default: 1)",
74 required = false, multiValued = false)
75 String keyOffsetStr = null;
76
77 private IntentService service;
78 private CountDownLatch latch;
79 private volatile long start, end;
80 private int count;
81 private int keyOffset;
82 private long submitCounter = 0;
83 private AtomicLong eventCounter = new AtomicLong(0);
84 private boolean add;
85
86 @Override
87 protected void execute() {
88 service = get(IntentService.class);
89
90
91 DeviceId ingressDeviceId = deviceId(getDeviceId(ingressDeviceString));
92 PortNumber ingressPortNumber = portNumber(getPortNumber(ingressDeviceString));
93 ConnectPoint ingress = new ConnectPoint(ingressDeviceId, ingressPortNumber);
94
95 DeviceId egressDeviceId = deviceId(getDeviceId(egressDeviceString));
96 PortNumber egressPortNumber = portNumber(getPortNumber(egressDeviceString));
97 ConnectPoint egress = new ConnectPoint(egressDeviceId, egressPortNumber);
98
99 count = Integer.parseInt(numberOfIntents);
100 keyOffset = (keyOffsetStr != null) ? Integer.parseInt(keyOffsetStr) : 1;
101
102 service.addListener(this);
103
104 List<Intent> operations = generateIntents(ingress, egress);
105
106 add = true;
107 start = System.currentTimeMillis();
108 while (start + 10000 > System.currentTimeMillis()) {
109 submitIntents(operations);
110 }
111 delay(5000);
112 printResults();
113
114 add = false;
115 submitIntents(operations);
116
117 service.removeListener(this);
118 }
119
120 private List<Intent> generateIntents(ConnectPoint ingress, ConnectPoint egress) {
121 TrafficSelector.Builder selectorBldr = DefaultTrafficSelector.builder()
122 .matchEthType(Ethernet.TYPE_IPV4);
Brian O'Connor6b528132015-03-10 16:39:52 -0700123 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
Brian O'Connor66cfbfa2015-02-17 18:17:32 -0800124
125 List<Intent> intents = Lists.newArrayList();
126 for (int i = 0; i < count; i++) {
127 TrafficSelector selector = selectorBldr
128 .matchEthSrc(MacAddress.valueOf(i + keyOffset))
129 .build();
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700130 intents.add(
131 PointToPointIntent.builder()
132 .appId(appId())
133 .key(Key.of(i + keyOffset, appId()))
134 .selector(selector)
135 .treatment(treatment)
136 .ingressPoint(ingress)
137 .egressPoint(egress)
138 .build());
139
Brian O'Connor66cfbfa2015-02-17 18:17:32 -0800140
141 }
142 return intents;
143 }
144
145 private void submitIntents(List<Intent> intents) {
146 for (Intent intent : intents) {
147 if (add) {
148 submitCounter++;
149 service.submit(intent);
150 } else {
151 service.withdraw(intent);
152 }
153 }
154 }
155
156 private void printResults() {
157 //long delta = end - start;
158 //String text = add ? "install" : "withdraw";
159 print("count: %s / %s", eventCounter, Long.valueOf(submitCounter));
160 //print("Time to %s %d intents: %d ms", text, count, delta);
161 }
162
163 /**
164 * Extracts the port number portion of the ConnectPoint.
165 *
166 * @param deviceString string representing the device/port
167 * @return port number as a string, empty string if the port is not found
168 */
169 private String getPortNumber(String deviceString) {
170 int slash = deviceString.indexOf('/');
171 if (slash <= 0) {
172 return "";
173 }
174 return deviceString.substring(slash + 1, deviceString.length());
175 }
176
177 /**
178 * Extracts the device ID portion of the ConnectPoint.
179 *
180 * @param deviceString string representing the device/port
181 * @return device ID string
182 */
183 private String getDeviceId(String deviceString) {
184 int slash = deviceString.indexOf('/');
185 if (slash <= 0) {
186 return "";
187 }
188 return deviceString.substring(0, slash);
189 }
190
191 private static final EnumSet<Type> IGNORE_EVENT
192 = EnumSet.of(Type.INSTALL_REQ, Type.WITHDRAW_REQ);
193 @Override
194 public synchronized void event(IntentEvent event) {
195 if (!appId().equals(event.subject().appId())) {
196 // not my event, ignore
197 return;
198 }
199 Type expected = add ? Type.INSTALLED : Type.WITHDRAWN;
200 if (event.type() == expected) {
201 eventCounter.getAndIncrement();
202 } else if (IGNORE_EVENT.contains(event.type())) {
203 log.info("Unexpected intent event: {}", event);
204 }
205 }
206}