blob: b4f8d534c592e346c7503ab932b8270c37f55bda [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.packet.impl;
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070017
alshabibb452fd72015-04-22 20:46:20 -070018import com.google.common.collect.Lists;
19import com.google.common.collect.Sets;
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070020import org.junit.After;
21import org.junit.Before;
22import org.junit.Test;
alshabibb452fd72015-04-22 20:46:20 -070023import org.onlab.packet.ARP;
24import org.onlab.packet.Ethernet;
Marc De Leenheerb9311372015-07-09 11:36:49 -070025import org.onosproject.net.Device;
Brian O'Connorabafb502014-12-02 22:26:20 -080026import org.onosproject.net.DeviceId;
27import org.onosproject.net.PortNumber;
28import org.onosproject.net.flow.DefaultTrafficTreatment;
29import org.onosproject.net.flow.TrafficTreatment;
30import org.onosproject.net.flow.instructions.Instruction;
31import org.onosproject.net.flow.instructions.Instructions;
32import org.onosproject.net.packet.DefaultOutboundPacket;
33import org.onosproject.net.packet.OutboundPacket;
34import org.onosproject.net.packet.PacketContext;
35import org.onosproject.net.packet.PacketProvider;
36import org.onosproject.net.packet.PacketProviderRegistry;
37import org.onosproject.net.packet.PacketProviderService;
38import org.onosproject.net.provider.ProviderId;
39import org.onosproject.openflow.controller.DefaultOpenFlowPacketContext;
40import org.onosproject.openflow.controller.Dpid;
Anton Chigrinbf14b372019-01-14 17:29:56 +020041import org.onosproject.openflow.controller.OpenFlowClassifierListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080042import org.onosproject.openflow.controller.OpenFlowController;
43import org.onosproject.openflow.controller.OpenFlowEventListener;
Jian Lia78cdb22016-04-21 13:03:58 -070044import org.onosproject.openflow.controller.OpenFlowMessageListener;
Brian O'Connorabafb502014-12-02 22:26:20 -080045import org.onosproject.openflow.controller.OpenFlowPacketContext;
46import org.onosproject.openflow.controller.OpenFlowSwitch;
47import org.onosproject.openflow.controller.OpenFlowSwitchListener;
48import org.onosproject.openflow.controller.PacketListener;
49import org.onosproject.openflow.controller.RoleState;
Thiago Santos11d10622019-01-30 14:44:32 -080050import org.projectfloodlight.openflow.protocol.OFActionType;
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070051import org.projectfloodlight.openflow.protocol.OFFactory;
52import org.projectfloodlight.openflow.protocol.OFMessage;
Jordi Ortizaa8de492016-12-01 00:21:36 +010053import org.projectfloodlight.openflow.protocol.OFMeterFeatures;
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070054import org.projectfloodlight.openflow.protocol.OFPacketIn;
55import org.projectfloodlight.openflow.protocol.OFPacketInReason;
Thiago Santos11d10622019-01-30 14:44:32 -080056import org.projectfloodlight.openflow.protocol.OFPacketOut;
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070057import org.projectfloodlight.openflow.protocol.OFPortDesc;
Thiago Santos11d10622019-01-30 14:44:32 -080058import org.projectfloodlight.openflow.protocol.OFType;
59import org.projectfloodlight.openflow.protocol.action.OFAction;
60import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070061import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
62import org.projectfloodlight.openflow.types.MacAddress;
63import org.projectfloodlight.openflow.types.OFBufferId;
64import org.projectfloodlight.openflow.types.OFPort;
65
alshabibb452fd72015-04-22 20:46:20 -070066import java.nio.ByteBuffer;
67import java.util.ArrayList;
68import java.util.List;
69import java.util.Set;
Marc De Leenheer8aba62f2017-04-25 14:33:37 -070070import java.util.concurrent.CompletableFuture;
alshabibb452fd72015-04-22 20:46:20 -070071
72import static org.junit.Assert.*;
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070073
74
75public class OpenFlowPacketProviderTest {
76
77 private static final int PN1 = 100;
78 private static final int PN2 = 200;
79 private static final int PN3 = 300;
80 private static final short VLANID = (short) 100;
Thiago Santos11d10622019-01-30 14:44:32 -080081 private static final int IN_PORT_PN = 1;
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070082
83 private static final DeviceId DID = DeviceId.deviceId("of:1");
84 private static final DeviceId DID_MISSING = DeviceId.deviceId("of:2");
85 private static final DeviceId DID_WRONG = DeviceId.deviceId("test:1");
86 private static final PortNumber P1 = PortNumber.portNumber(PN1);
87 private static final PortNumber P2 = PortNumber.portNumber(PN2);
88 private static final PortNumber P3 = PortNumber.portNumber(PN3);
Thiago Santos11d10622019-01-30 14:44:32 -080089 private static final PortNumber IN_PORT = PortNumber.portNumber(IN_PORT_PN);
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070090
91 private static final Instruction INST1 = Instructions.createOutput(P1);
92 private static final Instruction INST2 = Instructions.createOutput(P2);
93 private static final Instruction INST3 = Instructions.createOutput(P3);
Thiago Santosa4a17cb2019-01-30 14:23:58 -080094 private static final Instruction INST_ALL = Instructions.createOutput(PortNumber.ALL);
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070095
96 private static final OFPortDesc PD1 = portDesc(PN1);
97 private static final OFPortDesc PD2 = portDesc(PN2);
Thiago Santosa4a17cb2019-01-30 14:23:58 -080098 private static final OFPortDesc PD_ALL = portDesc((int) PortNumber.ALL.toLong());
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070099
100 private static final List<OFPortDesc> PLIST = Lists.newArrayList(PD1, PD2);
101 private static final TrafficTreatment TR = treatment(INST1, INST2);
Thiago Santosa4a17cb2019-01-30 14:23:58 -0800102 private static final List<OFPortDesc> PLIST_ALL = Lists.newArrayList(PD_ALL);
103 private static final TrafficTreatment TR_ALL = treatment(INST_ALL);
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700104 private static final TrafficTreatment TR_MISSING = treatment(INST1, INST3);
105
Jian Li68c4fc42016-01-11 16:07:03 -0800106 private static final byte[] ANY = new byte[] {0, 0, 0, 0};
Yuta HIGUCHI10681f62014-09-21 17:49:46 -0700107
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700108 private final OpenFlowPacketProvider provider = new OpenFlowPacketProvider();
109 private final TestPacketRegistry registry = new TestPacketRegistry();
110 private final TestController controller = new TestController();
111
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700112 private final TestOpenFlowSwitch sw = new TestOpenFlowSwitch();
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700113
114 @Before
115 public void startUp() {
116 provider.providerRegistry = registry;
117 provider.controller = controller;
118 provider.activate();
119 assertNotNull("listener should be registered", registry.listener);
120 }
121
122 @After
123 public void teardown() {
124 provider.deactivate();
125 assertNull("listeners shouldn't be registered", registry.listener);
126 provider.controller = null;
127 provider.providerRegistry = null;
128 }
129
130 @Test(expected = IllegalArgumentException.class)
Ayaka Koshibe91c9bc72014-09-19 12:52:24 -0700131 public void wrongScheme() {
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700132 sw.setRole(RoleState.MASTER);
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700133 OutboundPacket schemeFailPkt = outPacket(DID_WRONG, TR, null);
134 provider.emit(schemeFailPkt);
135 assertEquals("message sent incorrectly", 0, sw.sent.size());
136 }
137
138 @Test
139 public void emit() {
140
141 MacAddress mac1 = MacAddress.of("00:00:00:11:00:01");
142 MacAddress mac2 = MacAddress.of("00:00:00:22:00:02");
143
144 ARP arp = new ARP();
Yuta HIGUCHI10681f62014-09-21 17:49:46 -0700145 arp.setSenderProtocolAddress(ANY)
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700146 .setSenderHardwareAddress(mac1.getBytes())
147 .setTargetHardwareAddress(mac2.getBytes())
Yuta HIGUCHI10681f62014-09-21 17:49:46 -0700148 .setTargetProtocolAddress(ANY)
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700149 .setHardwareType((short) 0)
150 .setProtocolType((short) 0)
151 .setHardwareAddressLength((byte) 6)
152 .setProtocolAddressLength((byte) 4)
153 .setOpCode((byte) 0);
154
155 Ethernet eth = new Ethernet();
156 eth.setVlanID(VLANID)
157 .setEtherType(Ethernet.TYPE_ARP)
158 .setSourceMACAddress("00:00:00:11:00:01")
159 .setDestinationMACAddress("00:00:00:22:00:02")
160 .setPayload(arp);
161
162 //the should-be working setup.
163 OutboundPacket passPkt = outPacket(DID, TR, eth);
164 sw.setRole(RoleState.MASTER);
165 provider.emit(passPkt);
166 assertEquals("invalid switch", sw, controller.current);
167 assertEquals("message not sent", PLIST.size(), sw.sent.size());
168 sw.sent.clear();
169
Thiago Santos11d10622019-01-30 14:44:32 -0800170 //Send with different IN_PORT
171 OutboundPacket inPortPkt = outPacket(DID, TR_ALL, eth, IN_PORT);
Thiago Santosa4a17cb2019-01-30 14:23:58 -0800172 sw.setRole(RoleState.MASTER);
173 provider.emit(inPortPkt);
174 assertEquals("invalid switch", sw, controller.current);
175 assertEquals("message not sent", PLIST_ALL.size(), sw.sent.size());
Thiago Santos11d10622019-01-30 14:44:32 -0800176 OFMessage ofMessage = sw.sent.get(0);
177 assertEquals("Wrong OF message type", OFType.PACKET_OUT, ofMessage.getType());
178 OFPacketOut packetOut = (OFPacketOut) ofMessage;
179 assertEquals("Wrong in port", OFPort.of(IN_PORT_PN), packetOut.getInPort());
180 assertEquals("Unexpected number of actions", 1, packetOut.getActions().size());
181 OFAction ofAction = packetOut.getActions().get(0);
182 assertEquals("Packet out action should be type output", OFActionType.OUTPUT, ofAction.getType());
183 OFActionOutput ofActionOutput = (OFActionOutput) ofAction;
184 assertEquals("Output should be ALL", OFPort.ALL, ofActionOutput.getPort());
Thiago Santosa4a17cb2019-01-30 14:23:58 -0800185 sw.sent.clear();
186
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700187 //wrong Role
alshabib6eb438a2014-10-01 16:39:37 -0700188 //sw.setRole(RoleState.SLAVE);
189 //provider.emit(passPkt);
190 //assertEquals("invalid switch", sw, controller.current);
191 //assertEquals("message sent incorrectly", 0, sw.sent.size());
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700192
alshabib6eb438a2014-10-01 16:39:37 -0700193 //sw.setRole(RoleState.MASTER);
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700194
195 //missing switch
196 OutboundPacket swFailPkt = outPacket(DID_MISSING, TR, eth);
197 provider.emit(swFailPkt);
198 assertNull("invalid switch", controller.current);
199 assertEquals("message sent incorrectly", 0, sw.sent.size());
200
201 //to missing port
alshabibb5522ff2014-09-29 19:20:00 -0700202 //OutboundPacket portFailPkt = outPacket(DID, TR_MISSING, eth);
203 //provider.emit(portFailPkt);
204 //assertEquals("extra message sent", 1, sw.sent.size());
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700205
206 }
207
208 @Test
209 public void handlePacket() {
210 OFPacketIn pkt = sw.factory().buildPacketIn()
211 .setBufferId(OFBufferId.NO_BUFFER)
212 .setInPort(OFPort.NO_MASK)
213 .setReason(OFPacketInReason.INVALID_TTL)
214 .build();
215
216 controller.processPacket(null, pkt);
217 assertNotNull("message unprocessed", registry.ctx);
218
219 }
220
221 private static OFPortDesc portDesc(int port) {
222 OFPortDesc.Builder builder = OFFactoryVer10.INSTANCE.buildPortDesc();
223 builder.setPortNo(OFPort.of(port));
224
225 return builder.build();
226 }
227
Yuta HIGUCHIe7e71a82018-05-18 16:36:43 -0700228 private static TrafficTreatment treatment(Instruction... insts) {
tom9a693fd2014-10-03 11:32:19 -0700229 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700230 for (Instruction i : insts) {
231 builder.add(i);
232 }
233 return builder.build();
234 }
235
236 private static OutboundPacket outPacket(
237 DeviceId d, TrafficTreatment t, Ethernet e) {
238 ByteBuffer buf = null;
239 if (e != null) {
240 buf = ByteBuffer.wrap(e.serialize());
241 }
242 return new DefaultOutboundPacket(d, t, buf);
243 }
244
Thiago Santosa4a17cb2019-01-30 14:23:58 -0800245 private OutboundPacket outPacket(DeviceId d, TrafficTreatment t, Ethernet e,
246 PortNumber inPort) {
247 ByteBuffer buf = null;
248 if (e != null) {
249 buf = ByteBuffer.wrap(e.serialize());
250 }
251 return new DefaultOutboundPacket(d, t, buf, inPort);
252 }
253
254
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700255 private class TestPacketRegistry implements PacketProviderRegistry {
256
257 PacketProvider listener = null;
258 PacketContext ctx = null;
259
260 @Override
261 public PacketProviderService register(PacketProvider provider) {
262 listener = provider;
263 return new TestPacketProviderService();
264 }
265
266 @Override
267 public void unregister(PacketProvider provider) {
268 listener = null;
269 }
270
271 @Override
272 public Set<ProviderId> getProviders() {
273 return Sets.newHashSet(listener.id());
274 }
275
276 private class TestPacketProviderService implements PacketProviderService {
277
278 @Override
279 public PacketProvider provider() {
280 return null;
281 }
282
283 @Override
284 public void processPacket(PacketContext context) {
285 ctx = context;
286 }
287
288 }
289 }
290
291 private class TestController implements OpenFlowController {
292
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700293 PacketListener pktListener;
294 OpenFlowSwitch current;
295
296 @Override
297 public Iterable<OpenFlowSwitch> getSwitches() {
298 return null;
299 }
300
301 @Override
302 public Iterable<OpenFlowSwitch> getMasterSwitches() {
303 return null;
304 }
305
306 @Override
307 public Iterable<OpenFlowSwitch> getEqualSwitches() {
308 return null;
309 }
310
311 @Override
312 public OpenFlowSwitch getSwitch(Dpid dpid) {
313 if (dpid.equals(Dpid.dpid(DID.uri()))) {
314 current = sw;
315 } else {
316 current = null;
317 }
318 return current;
319 }
320
321 @Override
322 public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
323 return null;
324 }
325
326 @Override
327 public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
328 return null;
329 }
330
331 @Override
332 public void addListener(OpenFlowSwitchListener listener) {
333 }
334
335 @Override
336 public void removeListener(OpenFlowSwitchListener listener) {
337 }
338
339 @Override
Jian Lia78cdb22016-04-21 13:03:58 -0700340 public void addMessageListener(OpenFlowMessageListener listener) {
341
342 }
343
344 @Override
345 public void removeMessageListener(OpenFlowMessageListener listener) {
346
347 }
348
349 @Override
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700350 public void addPacketListener(int priority, PacketListener listener) {
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700351 pktListener = listener;
352 }
353
354 @Override
355 public void removePacketListener(PacketListener listener) {
356 }
357
358 @Override
359 public void addEventListener(OpenFlowEventListener listener) {
360 }
361
362 @Override
363 public void removeEventListener(OpenFlowEventListener listener) {
364 }
365
366 @Override
367 public void write(Dpid dpid, OFMessage msg) {
368 }
369
370 @Override
Marc De Leenheer8aba62f2017-04-25 14:33:37 -0700371 public CompletableFuture<OFMessage> writeResponse(Dpid dpid, OFMessage msg) {
372 return null;
373 }
374
375 @Override
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700376 public void processPacket(Dpid dpid, OFMessage msg) {
377 OpenFlowPacketContext pktCtx =
378 DefaultOpenFlowPacketContext.
379 packetContextFromPacketIn(sw, (OFPacketIn) msg);
380 pktListener.handlePacket(pktCtx);
381 }
382
383 @Override
384 public void setRole(Dpid dpid, RoleState role) {
385 }
386
Anton Chigrinbf14b372019-01-14 17:29:56 +0200387 @Override
388 public void removeClassifierListener(OpenFlowClassifierListener listener) {
389 }
390
391 @Override
392 public void addClassifierListener(OpenFlowClassifierListener listener) {
393 }
394
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700395 }
396
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700397 private class TestOpenFlowSwitch implements OpenFlowSwitch {
398
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700399 RoleState state;
Yuta HIGUCHIe7e71a82018-05-18 16:36:43 -0700400 List<OFMessage> sent = new ArrayList<>();
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700401 OFFactory factory = OFFactoryVer10.INSTANCE;
402
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700403 @Override
404 public void sendMsg(OFMessage msg) {
405 sent.add(msg);
406 }
407
408 @Override
409 public void sendMsg(List<OFMessage> msgs) {
410 }
411
412 @Override
413 public void handleMessage(OFMessage fromSwitch) {
414 }
415
416 @Override
417 public void setRole(RoleState role) {
418 state = role;
419 }
420
421 @Override
422 public RoleState getRole() {
423 return state;
424 }
425
426 @Override
427 public List<OFPortDesc> getPorts() {
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700428 return PLIST;
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700429 }
430
431 @Override
Jordi Ortizaa8de492016-12-01 00:21:36 +0100432 public OFMeterFeatures getMeterFeatures() {
433 return null;
434 }
435
436 @Override
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700437 public OFFactory factory() {
438 return factory;
439 }
440
441 @Override
442 public String getStringId() {
443 return null;
444 }
445
446 @Override
447 public long getId() {
448 return 0;
449 }
450
451 @Override
Ray Milkeyd3edd032015-01-16 11:38:58 -0800452 public String manufacturerDescription() {
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700453 return null;
454 }
455
456 @Override
457 public String datapathDescription() {
458 return null;
459 }
460
461 @Override
462 public String hardwareDescription() {
463 return null;
464 }
465
466 @Override
467 public String softwareDescription() {
468 return null;
469 }
470
471 @Override
472 public String serialNumber() {
473 return null;
474 }
475
476 @Override
Yuta HIGUCHI69a27352014-10-31 15:48:37 -0700477 public boolean isConnected() {
478 return true;
479 }
480
481 @Override
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700482 public void disconnectSwitch() {
483 }
484
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700485 @Override
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700486 public void returnRoleReply(RoleState requested, RoleState reponse) {
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700487 }
Anton Chigrinbf14b372019-01-14 17:29:56 +0200488
Marc De Leenheerb9311372015-07-09 11:36:49 -0700489 @Override
490 public Device.Type deviceType() {
491 return Device.Type.SWITCH;
492 }
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700493
Ray Milkeye53f1712015-01-16 09:17:16 -0800494 @Override
495 public String channelId() {
496 return "1.2.3.4:1";
497 }
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700498 }
499
500}