blob: 109f669bf9e25e46feecf5173a0614cc4bf3d7c8 [file] [log] [blame]
Brian O'Connor66cfbfa2015-02-17 18:17:32 -08001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
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
18import com.google.common.collect.Lists;
19import org.apache.karaf.shell.commands.Argument;
20import org.apache.karaf.shell.commands.Command;
21import org.onlab.packet.Ethernet;
22import org.onlab.packet.MacAddress;
23import org.onosproject.cli.AbstractShellCommand;
24import org.onosproject.net.ConnectPoint;
25import org.onosproject.net.DeviceId;
26import org.onosproject.net.PortNumber;
27import org.onosproject.net.flow.DefaultTrafficSelector;
28import org.onosproject.net.flow.DefaultTrafficTreatment;
29import org.onosproject.net.flow.TrafficSelector;
30import org.onosproject.net.flow.TrafficTreatment;
31import org.onosproject.net.intent.Intent;
32import org.onosproject.net.intent.IntentEvent;
33import org.onosproject.net.intent.IntentEvent.Type;
34import org.onosproject.net.intent.IntentListener;
35import org.onosproject.net.intent.IntentService;
36import org.onosproject.net.intent.Key;
37import org.onosproject.net.intent.PointToPointIntent;
38
39import java.util.Collections;
40import java.util.EnumSet;
41import java.util.List;
42import java.util.concurrent.CountDownLatch;
43import java.util.concurrent.atomic.AtomicLong;
44
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();
130 intents.add(new PointToPointIntent(appId(), Key.of(i + keyOffset, appId()),
131 selector, treatment,
132 ingress, egress,
133 Collections.emptyList()));
134
135 }
136 return intents;
137 }
138
139 private void submitIntents(List<Intent> intents) {
140 for (Intent intent : intents) {
141 if (add) {
142 submitCounter++;
143 service.submit(intent);
144 } else {
145 service.withdraw(intent);
146 }
147 }
148 }
149
150 private void printResults() {
151 //long delta = end - start;
152 //String text = add ? "install" : "withdraw";
153 print("count: %s / %s", eventCounter, Long.valueOf(submitCounter));
154 //print("Time to %s %d intents: %d ms", text, count, delta);
155 }
156
157 /**
158 * Extracts the port number portion of the ConnectPoint.
159 *
160 * @param deviceString string representing the device/port
161 * @return port number as a string, empty string if the port is not found
162 */
163 private String getPortNumber(String deviceString) {
164 int slash = deviceString.indexOf('/');
165 if (slash <= 0) {
166 return "";
167 }
168 return deviceString.substring(slash + 1, deviceString.length());
169 }
170
171 /**
172 * Extracts the device ID portion of the ConnectPoint.
173 *
174 * @param deviceString string representing the device/port
175 * @return device ID string
176 */
177 private String getDeviceId(String deviceString) {
178 int slash = deviceString.indexOf('/');
179 if (slash <= 0) {
180 return "";
181 }
182 return deviceString.substring(0, slash);
183 }
184
185 private static final EnumSet<Type> IGNORE_EVENT
186 = EnumSet.of(Type.INSTALL_REQ, Type.WITHDRAW_REQ);
187 @Override
188 public synchronized void event(IntentEvent event) {
189 if (!appId().equals(event.subject().appId())) {
190 // not my event, ignore
191 return;
192 }
193 Type expected = add ? Type.INSTALLED : Type.WITHDRAWN;
194 if (event.type() == expected) {
195 eventCounter.getAndIncrement();
196 } else if (IGNORE_EVENT.contains(event.type())) {
197 log.info("Unexpected intent event: {}", event);
198 }
199 }
200}