blob: fa764fbda4a36c7786eb7d019c5797a0ae3008c6 [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;
Ray Milkeya2cf3a12018-02-15 16:13:56 -080029import org.onosproject.net.FilteredConnectPoint;
Brian O'Connor66cfbfa2015-02-17 18:17:32 -080030import 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;
HelloONOS0b5b35d2017-04-05 18:47:47 +090078 private volatile long start;
Brian O'Connor66cfbfa2015-02-17 18:17:32 -080079 private int count;
80 private int keyOffset;
81 private long submitCounter = 0;
82 private AtomicLong eventCounter = new AtomicLong(0);
83 private boolean add;
84
85 @Override
86 protected void execute() {
87 service = get(IntentService.class);
88
89
90 DeviceId ingressDeviceId = deviceId(getDeviceId(ingressDeviceString));
91 PortNumber ingressPortNumber = portNumber(getPortNumber(ingressDeviceString));
92 ConnectPoint ingress = new ConnectPoint(ingressDeviceId, ingressPortNumber);
93
94 DeviceId egressDeviceId = deviceId(getDeviceId(egressDeviceString));
95 PortNumber egressPortNumber = portNumber(getPortNumber(egressDeviceString));
96 ConnectPoint egress = new ConnectPoint(egressDeviceId, egressPortNumber);
97
98 count = Integer.parseInt(numberOfIntents);
99 keyOffset = (keyOffsetStr != null) ? Integer.parseInt(keyOffsetStr) : 1;
100
101 service.addListener(this);
102
103 List<Intent> operations = generateIntents(ingress, egress);
104
105 add = true;
106 start = System.currentTimeMillis();
107 while (start + 10000 > System.currentTimeMillis()) {
108 submitIntents(operations);
109 }
110 delay(5000);
111 printResults();
112
113 add = false;
114 submitIntents(operations);
115
116 service.removeListener(this);
117 }
118
119 private List<Intent> generateIntents(ConnectPoint ingress, ConnectPoint egress) {
120 TrafficSelector.Builder selectorBldr = DefaultTrafficSelector.builder()
121 .matchEthType(Ethernet.TYPE_IPV4);
Brian O'Connor6b528132015-03-10 16:39:52 -0700122 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
Brian O'Connor66cfbfa2015-02-17 18:17:32 -0800123
124 List<Intent> intents = Lists.newArrayList();
Ray Milkey3717e602018-02-01 13:49:47 -0800125 for (long i = 0; i < count; i++) {
Brian O'Connor66cfbfa2015-02-17 18:17:32 -0800126 TrafficSelector selector = selectorBldr
127 .matchEthSrc(MacAddress.valueOf(i + keyOffset))
128 .build();
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700129 intents.add(
130 PointToPointIntent.builder()
131 .appId(appId())
132 .key(Key.of(i + keyOffset, appId()))
133 .selector(selector)
134 .treatment(treatment)
Ray Milkeya2cf3a12018-02-15 16:13:56 -0800135 .filteredIngressPoint(new FilteredConnectPoint(ingress))
136 .filteredEgressPoint(new FilteredConnectPoint(egress))
Ray Milkey3e3ec5f2015-03-17 17:00:38 -0700137 .build());
138
Brian O'Connor66cfbfa2015-02-17 18:17:32 -0800139
140 }
141 return intents;
142 }
143
144 private void submitIntents(List<Intent> intents) {
145 for (Intent intent : intents) {
146 if (add) {
147 submitCounter++;
148 service.submit(intent);
149 } else {
150 service.withdraw(intent);
151 }
152 }
153 }
154
155 private void printResults() {
Brian O'Connor66cfbfa2015-02-17 18:17:32 -0800156 print("count: %s / %s", eventCounter, Long.valueOf(submitCounter));
Brian O'Connor66cfbfa2015-02-17 18:17:32 -0800157 }
158
159 /**
160 * Extracts the port number portion of the ConnectPoint.
161 *
162 * @param deviceString string representing the device/port
163 * @return port number as a string, empty string if the port is not found
164 */
165 private String getPortNumber(String deviceString) {
166 int slash = deviceString.indexOf('/');
167 if (slash <= 0) {
168 return "";
169 }
170 return deviceString.substring(slash + 1, deviceString.length());
171 }
172
173 /**
174 * Extracts the device ID portion of the ConnectPoint.
175 *
176 * @param deviceString string representing the device/port
177 * @return device ID string
178 */
179 private String getDeviceId(String deviceString) {
180 int slash = deviceString.indexOf('/');
181 if (slash <= 0) {
182 return "";
183 }
184 return deviceString.substring(0, slash);
185 }
186
187 private static final EnumSet<Type> IGNORE_EVENT
188 = EnumSet.of(Type.INSTALL_REQ, Type.WITHDRAW_REQ);
189 @Override
190 public synchronized void event(IntentEvent event) {
191 if (!appId().equals(event.subject().appId())) {
192 // not my event, ignore
193 return;
194 }
195 Type expected = add ? Type.INSTALLED : Type.WITHDRAWN;
196 if (event.type() == expected) {
197 eventCounter.getAndIncrement();
198 } else if (IGNORE_EVENT.contains(event.type())) {
199 log.info("Unexpected intent event: {}", event);
200 }
201 }
202}