blob: a0869c4988156118e38f15325933d44d115136df [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
Thomas Vachuska781d18b2014-10-27 10:31:25 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * 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
Thomas Vachuska781d18b2014-10-27 10:31:25 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * 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.
Thomas Vachuska781d18b2014-10-27 10:31:25 -070015 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.provider.of.device.impl;
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -070017
alshabibb452fd72015-04-22 20:46:20 -070018import com.google.common.collect.HashMultimap;
Thomas Vachuskad07c0922015-10-06 14:48:06 -070019import com.google.common.collect.ImmutableSet;
alshabibb452fd72015-04-22 20:46:20 -070020import com.google.common.collect.Lists;
21import com.google.common.collect.Multimap;
Dusan Pajinbab8a5e2015-07-24 17:37:19 +020022
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -070023import org.junit.After;
24import org.junit.Before;
25import org.junit.Test;
Dusan Pajinbab8a5e2015-07-24 17:37:19 +020026import org.onosproject.cfg.ComponentConfigAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080027import org.onosproject.net.DefaultDevice;
28import org.onosproject.net.Device;
29import org.onosproject.net.DeviceId;
30import org.onosproject.net.MastershipRole;
31import org.onosproject.net.device.DeviceDescription;
32import org.onosproject.net.device.DeviceProvider;
33import org.onosproject.net.device.DeviceProviderRegistry;
34import org.onosproject.net.device.DeviceProviderService;
Thomas Vachuska164ecf62018-05-08 17:29:55 -070035import org.onosproject.net.device.DeviceServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080036import org.onosproject.net.device.PortDescription;
sangho538108b2015-04-08 14:29:20 -070037import org.onosproject.net.device.PortStatistics;
Victor Silvaac8dab02016-11-28 16:33:08 -030038import org.onosproject.net.driver.DriverServiceAdapter;
Brian O'Connorabafb502014-12-02 22:26:20 -080039import org.onosproject.net.provider.ProviderId;
40import org.onosproject.openflow.controller.Dpid;
41import org.onosproject.openflow.controller.OpenFlowController;
42import org.onosproject.openflow.controller.OpenFlowEventListener;
Jian Lia78cdb22016-04-21 13:03:58 -070043import org.onosproject.openflow.controller.OpenFlowMessageListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080044import org.onosproject.openflow.controller.OpenFlowSwitch;
45import org.onosproject.openflow.controller.OpenFlowSwitchListener;
46import org.onosproject.openflow.controller.PacketListener;
47import org.onosproject.openflow.controller.RoleState;
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -070048import org.projectfloodlight.openflow.protocol.OFFactory;
49import org.projectfloodlight.openflow.protocol.OFMessage;
Jordi Ortizaa8de492016-12-01 00:21:36 +010050import org.projectfloodlight.openflow.protocol.OFMeterFeatures;
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -070051import org.projectfloodlight.openflow.protocol.OFPortDesc;
52import org.projectfloodlight.openflow.protocol.OFPortReason;
53import org.projectfloodlight.openflow.protocol.OFPortStatus;
54import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
55import org.projectfloodlight.openflow.types.OFPort;
56
alshabibb452fd72015-04-22 20:46:20 -070057import java.util.ArrayList;
58import java.util.Collection;
59import java.util.HashMap;
60import java.util.HashSet;
61import java.util.List;
62import java.util.Map;
63import java.util.Set;
Marc De Leenheer8aba62f2017-04-25 14:33:37 -070064import java.util.concurrent.CompletableFuture;
alshabibb452fd72015-04-22 20:46:20 -070065
66import static org.junit.Assert.*;
67import static org.onosproject.net.Device.Type.SWITCH;
68import static org.onosproject.net.MastershipRole.*;
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -070069
70public class OpenFlowDeviceProviderTest {
71
72 private static final ProviderId PID = new ProviderId("of", "test");
73 private static final DeviceId DID1 = DeviceId.deviceId("of:0000000000000001");
74 private static final Dpid DPID1 = Dpid.dpid(DID1.uri());
75
76 private static final OFPortDesc PD1 = portDesc(1);
77 private static final OFPortDesc PD2 = portDesc(2);
78 private static final OFPortDesc PD3 = portDesc(3);
79
80 private static final List<OFPortDesc> PLIST = Lists.newArrayList(PD1, PD2);
81
82 private static final Device DEV1 =
alshabib7911a052014-10-16 17:49:37 -070083 new DefaultDevice(PID, DID1, SWITCH, "", "", "", "", null);
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -070084
85 private static final TestOpenFlowSwitch SW1 = new TestOpenFlowSwitch();
86
87 private final OpenFlowDeviceProvider provider = new OpenFlowDeviceProvider();
88 private final TestDeviceRegistry registry = new TestDeviceRegistry();
89 private final TestController controller = new TestController();
90
91 @Before
92 public void startUp() {
93 provider.providerRegistry = registry;
94 provider.controller = controller;
Dusan Pajinbab8a5e2015-07-24 17:37:19 +020095 provider.cfgService = new ComponentConfigAdapter();
Victor Silvaac8dab02016-11-28 16:33:08 -030096 provider.driverService = new DriverServiceAdapter();
Thomas Vachuska164ecf62018-05-08 17:29:55 -070097 provider.deviceService = new DeviceServiceAdapter();
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -070098 controller.switchMap.put(DPID1, SW1);
Dusan Pajinbab8a5e2015-07-24 17:37:19 +020099 provider.activate(null);
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700100 assertNotNull("provider should be registered", registry.provider);
101 assertNotNull("listener should be registered", controller.listener);
102 assertEquals("devices not added", 1, registry.connected.size());
103 assertEquals("ports not added", 2, registry.ports.get(DID1).size());
104 }
105
106 @After
107 public void tearDown() {
Dusan Pajinbab8a5e2015-07-24 17:37:19 +0200108 provider.deactivate(null);
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700109 assertNull("listener should be removed", controller.listener);
110 provider.controller = null;
111 provider.providerRegistry = null;
112 }
113
114 @Test
115 public void roleChanged() {
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700116 provider.roleChanged(DID1, MASTER);
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700117 assertEquals("Should be MASTER", RoleState.MASTER, controller.roleMap.get(DPID1));
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700118 provider.roleChanged(DID1, STANDBY);
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700119 assertEquals("Should be EQUAL", RoleState.EQUAL, controller.roleMap.get(DPID1));
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700120 provider.roleChanged(DID1, NONE);
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700121 assertEquals("Should be SLAVE", RoleState.SLAVE, controller.roleMap.get(DPID1));
122 }
123
Sithara Punnassery81afbf12016-02-11 17:36:25 -0800124 //sending a features req, msg will be added to sent
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700125 @Test
126 public void triggerProbe() {
Sithara Punnassery81afbf12016-02-11 17:36:25 -0800127 int cur = SW1.sent.size();
128 provider.triggerProbe(DID1);
129 assertEquals("OF message not sent", cur + 1, SW1.sent.size());
130 }
alshabib4785eec2014-12-04 16:45:45 -0800131
Sithara Punnassery81afbf12016-02-11 17:36:25 -0800132 //test receiving features reply
133 @Test
134 public void switchChanged() {
135 controller.listener.switchChanged(DPID1);
136 Collection<PortDescription> updatedDescr = registry.ports.values();
137 for (PortDescription pd : updatedDescr) {
138 assertNotNull("Switch change not handled by the provider service", pd);
139 }
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700140 }
141
142 @Test
143 public void switchRemoved() {
144 controller.listener.switchRemoved(DPID1);
145 assertTrue("device not removed", registry.connected.isEmpty());
146 }
147
148 @Test
149 public void portChanged() {
150 OFPortStatus stat = SW1.factory().buildPortStatus()
151 .setReason(OFPortReason.ADD)
152 .setDesc(PD3)
153 .build();
154 controller.listener.portChanged(DPID1, stat);
Ayaka Koshibe39a04802014-09-22 10:23:54 -0700155 assertNotNull("never went throught the provider service", registry.descr);
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700156 assertEquals("port status unhandled", 3, registry.ports.get(DID1).size());
157 }
158
Ayaka Koshibe32402f32014-09-25 11:08:54 -0700159 @Test
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700160 public void receivedRoleReply() {
161 // check translation capabilities
162 controller.listener.receivedRoleReply(DPID1, RoleState.MASTER, RoleState.MASTER);
Ayaka Koshibe32402f32014-09-25 11:08:54 -0700163 assertEquals("wrong role reported", DPID1, registry.roles.get(MASTER));
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700164 controller.listener.receivedRoleReply(DPID1, RoleState.EQUAL, RoleState.MASTER);
Ayaka Koshibe32402f32014-09-25 11:08:54 -0700165 assertEquals("wrong role reported", DPID1, registry.roles.get(STANDBY));
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700166 controller.listener.receivedRoleReply(DPID1, RoleState.SLAVE, RoleState.MASTER);
Ayaka Koshibe32402f32014-09-25 11:08:54 -0700167 assertEquals("wrong role reported", DPID1, registry.roles.get(NONE));
168 }
169
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700170 private static OFPortDesc portDesc(int port) {
171 OFPortDesc.Builder builder = OFFactoryVer10.INSTANCE.buildPortDesc();
172 builder.setPortNo(OFPort.of(port));
173
174 return builder.build();
175 }
176
177 private class TestDeviceRegistry implements DeviceProviderRegistry {
178 DeviceProvider provider;
Ayaka Koshibe32402f32014-09-25 11:08:54 -0700179
180 Set<DeviceId> connected = new HashSet<>();
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700181 Multimap<DeviceId, PortDescription> ports = HashMultimap.create();
Ayaka Koshibe39a04802014-09-22 10:23:54 -0700182 PortDescription descr = null;
Ayaka Koshibe32402f32014-09-25 11:08:54 -0700183 Map<MastershipRole, Dpid> roles = new HashMap<>();
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700184
185 @Override
186 public DeviceProviderService register(DeviceProvider provider) {
187 this.provider = provider;
188 return new TestProviderService();
189 }
190
191 @Override
192 public void unregister(DeviceProvider provider) {
193 }
194
195 @Override
196 public Set<ProviderId> getProviders() {
197 return null;
198 }
199
200 private class TestProviderService implements DeviceProviderService {
201
202 @Override
203 public DeviceProvider provider() {
204 return null;
205 }
206
207 @Override
208 public void deviceConnected(DeviceId deviceId,
209 DeviceDescription deviceDescription) {
210 connected.add(deviceId);
211 }
212
213 @Override
214 public void deviceDisconnected(DeviceId deviceId) {
215 connected.remove(deviceId);
216 ports.removeAll(deviceId);
217 }
218
219 @Override
220 public void updatePorts(DeviceId deviceId,
221 List<PortDescription> portDescriptions) {
222 for (PortDescription p : portDescriptions) {
223 ports.put(deviceId, p);
224 }
225 }
226
227 @Override
228 public void portStatusChanged(DeviceId deviceId,
229 PortDescription portDescription) {
Ayaka Koshibe39a04802014-09-22 10:23:54 -0700230 ports.put(deviceId, portDescription);
231 descr = portDescription;
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700232 }
233
tom3f2bbd72014-09-24 12:07:58 -0700234 @Override
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700235 public void receivedRoleReply(DeviceId deviceId,
236 MastershipRole requested, MastershipRole response) {
237 roles.put(requested, Dpid.dpid(deviceId.uri()));
tom3f2bbd72014-09-24 12:07:58 -0700238 }
239
sangho538108b2015-04-08 14:29:20 -0700240 @Override
241 public void updatePortStatistics(DeviceId deviceId, Collection<PortStatistics> portStatistics) {
242
243 }
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700244 }
245 }
246
247 private class TestController implements OpenFlowController {
248 OpenFlowSwitchListener listener = null;
249 Map<Dpid, RoleState> roleMap = new HashMap<Dpid, RoleState>();
250 Map<Dpid, OpenFlowSwitch> switchMap = new HashMap<Dpid, OpenFlowSwitch>();
251
252 @Override
253 public Iterable<OpenFlowSwitch> getSwitches() {
254 return switchMap.values();
255 }
256
257 @Override
258 public Iterable<OpenFlowSwitch> getMasterSwitches() {
Thomas Vachuskad07c0922015-10-06 14:48:06 -0700259 return ImmutableSet.of();
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700260 }
261
262 @Override
263 public Iterable<OpenFlowSwitch> getEqualSwitches() {
264 return null;
265 }
266
267 @Override
268 public OpenFlowSwitch getSwitch(Dpid dpid) {
269 return switchMap.get(dpid);
270 }
271
272 @Override
273 public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
274 return null;
275 }
276
277 @Override
278 public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
279
280 return null;
281 }
282
283 @Override
284 public void addListener(OpenFlowSwitchListener listener) {
285 this.listener = listener;
286 }
287
288 @Override
289 public void removeListener(OpenFlowSwitchListener listener) {
290 this.listener = null;
291 }
292
293 @Override
Jian Lia78cdb22016-04-21 13:03:58 -0700294 public void addMessageListener(OpenFlowMessageListener listener) {
295
296 }
297
298 @Override
299 public void removeMessageListener(OpenFlowMessageListener listener) {
300
301 }
302
303 @Override
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700304 public void addPacketListener(int priority, PacketListener listener) {
305 }
306
307 @Override
308 public void removePacketListener(PacketListener listener) {
309 }
310
311 @Override
312 public void addEventListener(OpenFlowEventListener listener) {
313 }
314
315 @Override
316 public void removeEventListener(OpenFlowEventListener listener) {
317 }
318
319 @Override
320 public void write(Dpid dpid, OFMessage msg) {
321 }
322
323 @Override
Marc De Leenheer8aba62f2017-04-25 14:33:37 -0700324 public CompletableFuture<OFMessage> writeResponse(Dpid dpid, OFMessage msg) {
325 return null;
326 }
327
328 @Override
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700329 public void processPacket(Dpid dpid, OFMessage msg) {
330 }
331
332 @Override
333 public void setRole(Dpid dpid, RoleState role) {
334 roleMap.put(dpid, role);
335 }
336 }
337
338 private static class TestOpenFlowSwitch implements OpenFlowSwitch {
339
340 RoleState state;
341 List<OFMessage> sent = new ArrayList<OFMessage>();
342 OFFactory factory = OFFactoryVer10.INSTANCE;
343
344 @Override
345 public void sendMsg(OFMessage msg) {
346 sent.add(msg);
347 }
348
349 @Override
350 public void sendMsg(List<OFMessage> msgs) {
351 }
352
353 @Override
354 public void handleMessage(OFMessage fromSwitch) {
Sithara Punnassery81afbf12016-02-11 17:36:25 -0800355
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700356 }
357
358 @Override
359 public void setRole(RoleState role) {
360 state = role;
361 }
362
363 @Override
364 public RoleState getRole() {
365 return state;
366 }
367
368 @Override
369 public List<OFPortDesc> getPorts() {
370 return PLIST;
371 }
372
373 @Override
Jordi Ortizaa8de492016-12-01 00:21:36 +0100374 public OFMeterFeatures getMeterFeatures() {
375 return null;
376 }
377
378 @Override
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700379 public OFFactory factory() {
380 return factory;
381 }
382
383 @Override
384 public String getStringId() {
385 return null;
386 }
387
388 @Override
389 public long getId() {
390 return DPID1.value();
391 }
392
393 @Override
Ray Milkeyd3edd032015-01-16 11:38:58 -0800394 public String manufacturerDescription() {
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700395 return null;
396 }
397
398 @Override
399 public String datapathDescription() {
400 return null;
401 }
402
403 @Override
404 public String hardwareDescription() {
405 return null;
406 }
407
408 @Override
409 public String softwareDescription() {
410 return null;
411 }
412
413 @Override
414 public String serialNumber() {
415 return null;
416 }
417
418 @Override
Yuta HIGUCHI69a27352014-10-31 15:48:37 -0700419 public boolean isConnected() {
420 return true;
421 }
422
423 @Override
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700424 public void disconnectSwitch() {
425 }
426
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700427 @Override
Marc De Leenheerb9311372015-07-09 11:36:49 -0700428 public Device.Type deviceType() {
429 return Device.Type.SWITCH;
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700430 }
431
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700432 @Override
Ray Milkeye53f1712015-01-16 09:17:16 -0800433 public void returnRoleReply(RoleState requested, RoleState response) {
434 }
435
436 @Override
437 public String channelId() {
438 return "1.2.3.4:1";
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700439 }
440
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700441 }
442
443}