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