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