blob: 1b4fe937344c9c1b76185eef4fbaf9ca026093dd [file] [log] [blame]
Thomas Vachuska781d18b2014-10-27 10:31:25 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
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;
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.OpenFlowPacketContext;
45import org.onosproject.openflow.controller.OpenFlowSwitch;
46import org.onosproject.openflow.controller.OpenFlowSwitchListener;
47import org.onosproject.openflow.controller.PacketListener;
48import org.onosproject.openflow.controller.RoleState;
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070049import org.projectfloodlight.openflow.protocol.OFFactory;
50import org.projectfloodlight.openflow.protocol.OFMessage;
51import org.projectfloodlight.openflow.protocol.OFPacketIn;
52import org.projectfloodlight.openflow.protocol.OFPacketInReason;
53import org.projectfloodlight.openflow.protocol.OFPortDesc;
54import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
55import org.projectfloodlight.openflow.types.MacAddress;
56import org.projectfloodlight.openflow.types.OFBufferId;
57import org.projectfloodlight.openflow.types.OFPort;
58
alshabibb452fd72015-04-22 20:46:20 -070059import java.nio.ByteBuffer;
60import java.util.ArrayList;
61import java.util.List;
62import java.util.Set;
63
64import static org.junit.Assert.*;
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070065
66
67public class OpenFlowPacketProviderTest {
68
69 private static final int PN1 = 100;
70 private static final int PN2 = 200;
71 private static final int PN3 = 300;
72 private static final short VLANID = (short) 100;
73
74 private static final DeviceId DID = DeviceId.deviceId("of:1");
75 private static final DeviceId DID_MISSING = DeviceId.deviceId("of:2");
76 private static final DeviceId DID_WRONG = DeviceId.deviceId("test:1");
77 private static final PortNumber P1 = PortNumber.portNumber(PN1);
78 private static final PortNumber P2 = PortNumber.portNumber(PN2);
79 private static final PortNumber P3 = PortNumber.portNumber(PN3);
80
81 private static final Instruction INST1 = Instructions.createOutput(P1);
82 private static final Instruction INST2 = Instructions.createOutput(P2);
83 private static final Instruction INST3 = Instructions.createOutput(P3);
84
85 private static final OFPortDesc PD1 = portDesc(PN1);
86 private static final OFPortDesc PD2 = portDesc(PN2);
87
88 private static final List<OFPortDesc> PLIST = Lists.newArrayList(PD1, PD2);
89 private static final TrafficTreatment TR = treatment(INST1, INST2);
90 private static final TrafficTreatment TR_MISSING = treatment(INST1, INST3);
91
Jian Li68c4fc42016-01-11 16:07:03 -080092 private static final byte[] ANY = new byte[] {0, 0, 0, 0};
Yuta HIGUCHI10681f62014-09-21 17:49:46 -070093
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070094 private final OpenFlowPacketProvider provider = new OpenFlowPacketProvider();
95 private final TestPacketRegistry registry = new TestPacketRegistry();
96 private final TestController controller = new TestController();
97
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -070098 private final TestOpenFlowSwitch sw = new TestOpenFlowSwitch();
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070099
100 @Before
101 public void startUp() {
102 provider.providerRegistry = registry;
103 provider.controller = controller;
104 provider.activate();
105 assertNotNull("listener should be registered", registry.listener);
106 }
107
108 @After
109 public void teardown() {
110 provider.deactivate();
111 assertNull("listeners shouldn't be registered", registry.listener);
112 provider.controller = null;
113 provider.providerRegistry = null;
114 }
115
116 @Test(expected = IllegalArgumentException.class)
Ayaka Koshibe91c9bc72014-09-19 12:52:24 -0700117 public void wrongScheme() {
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700118 sw.setRole(RoleState.MASTER);
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700119 OutboundPacket schemeFailPkt = outPacket(DID_WRONG, TR, null);
120 provider.emit(schemeFailPkt);
121 assertEquals("message sent incorrectly", 0, sw.sent.size());
122 }
123
124 @Test
125 public void emit() {
126
127 MacAddress mac1 = MacAddress.of("00:00:00:11:00:01");
128 MacAddress mac2 = MacAddress.of("00:00:00:22:00:02");
129
130 ARP arp = new ARP();
Yuta HIGUCHI10681f62014-09-21 17:49:46 -0700131 arp.setSenderProtocolAddress(ANY)
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700132 .setSenderHardwareAddress(mac1.getBytes())
133 .setTargetHardwareAddress(mac2.getBytes())
Yuta HIGUCHI10681f62014-09-21 17:49:46 -0700134 .setTargetProtocolAddress(ANY)
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700135 .setHardwareType((short) 0)
136 .setProtocolType((short) 0)
137 .setHardwareAddressLength((byte) 6)
138 .setProtocolAddressLength((byte) 4)
139 .setOpCode((byte) 0);
140
141 Ethernet eth = new Ethernet();
142 eth.setVlanID(VLANID)
143 .setEtherType(Ethernet.TYPE_ARP)
144 .setSourceMACAddress("00:00:00:11:00:01")
145 .setDestinationMACAddress("00:00:00:22:00:02")
146 .setPayload(arp);
147
148 //the should-be working setup.
149 OutboundPacket passPkt = outPacket(DID, TR, eth);
150 sw.setRole(RoleState.MASTER);
151 provider.emit(passPkt);
152 assertEquals("invalid switch", sw, controller.current);
153 assertEquals("message not sent", PLIST.size(), sw.sent.size());
154 sw.sent.clear();
155
156 //wrong Role
alshabib6eb438a2014-10-01 16:39:37 -0700157 //sw.setRole(RoleState.SLAVE);
158 //provider.emit(passPkt);
159 //assertEquals("invalid switch", sw, controller.current);
160 //assertEquals("message sent incorrectly", 0, sw.sent.size());
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700161
alshabib6eb438a2014-10-01 16:39:37 -0700162 //sw.setRole(RoleState.MASTER);
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700163
164 //missing switch
165 OutboundPacket swFailPkt = outPacket(DID_MISSING, TR, eth);
166 provider.emit(swFailPkt);
167 assertNull("invalid switch", controller.current);
168 assertEquals("message sent incorrectly", 0, sw.sent.size());
169
170 //to missing port
alshabibb5522ff2014-09-29 19:20:00 -0700171 //OutboundPacket portFailPkt = outPacket(DID, TR_MISSING, eth);
172 //provider.emit(portFailPkt);
173 //assertEquals("extra message sent", 1, sw.sent.size());
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700174
175 }
176
177 @Test
178 public void handlePacket() {
179 OFPacketIn pkt = sw.factory().buildPacketIn()
180 .setBufferId(OFBufferId.NO_BUFFER)
181 .setInPort(OFPort.NO_MASK)
182 .setReason(OFPacketInReason.INVALID_TTL)
183 .build();
184
185 controller.processPacket(null, pkt);
186 assertNotNull("message unprocessed", registry.ctx);
187
188 }
189
190 private static OFPortDesc portDesc(int port) {
191 OFPortDesc.Builder builder = OFFactoryVer10.INSTANCE.buildPortDesc();
192 builder.setPortNo(OFPort.of(port));
193
194 return builder.build();
195 }
196
197 private static TrafficTreatment treatment(Instruction ... insts) {
tom9a693fd2014-10-03 11:32:19 -0700198 TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700199 for (Instruction i : insts) {
200 builder.add(i);
201 }
202 return builder.build();
203 }
204
205 private static OutboundPacket outPacket(
206 DeviceId d, TrafficTreatment t, Ethernet e) {
207 ByteBuffer buf = null;
208 if (e != null) {
209 buf = ByteBuffer.wrap(e.serialize());
210 }
211 return new DefaultOutboundPacket(d, t, buf);
212 }
213
214 private class TestPacketRegistry implements PacketProviderRegistry {
215
216 PacketProvider listener = null;
217 PacketContext ctx = null;
218
219 @Override
220 public PacketProviderService register(PacketProvider provider) {
221 listener = provider;
222 return new TestPacketProviderService();
223 }
224
225 @Override
226 public void unregister(PacketProvider provider) {
227 listener = null;
228 }
229
230 @Override
231 public Set<ProviderId> getProviders() {
232 return Sets.newHashSet(listener.id());
233 }
234
235 private class TestPacketProviderService implements PacketProviderService {
236
237 @Override
238 public PacketProvider provider() {
239 return null;
240 }
241
242 @Override
243 public void processPacket(PacketContext context) {
244 ctx = context;
245 }
246
247 }
248 }
249
250 private class TestController implements OpenFlowController {
251
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700252 PacketListener pktListener;
253 OpenFlowSwitch current;
254
255 @Override
256 public Iterable<OpenFlowSwitch> getSwitches() {
257 return null;
258 }
259
260 @Override
261 public Iterable<OpenFlowSwitch> getMasterSwitches() {
262 return null;
263 }
264
265 @Override
266 public Iterable<OpenFlowSwitch> getEqualSwitches() {
267 return null;
268 }
269
270 @Override
271 public OpenFlowSwitch getSwitch(Dpid dpid) {
272 if (dpid.equals(Dpid.dpid(DID.uri()))) {
273 current = sw;
274 } else {
275 current = null;
276 }
277 return current;
278 }
279
280 @Override
281 public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
282 return null;
283 }
284
285 @Override
286 public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
287 return null;
288 }
289
290 @Override
291 public void addListener(OpenFlowSwitchListener listener) {
292 }
293
294 @Override
295 public void removeListener(OpenFlowSwitchListener listener) {
296 }
297
298 @Override
Jian Lia78cdb22016-04-21 13:03:58 -0700299 public void addMessageListener(OpenFlowMessageListener listener) {
300
301 }
302
303 @Override
304 public void removeMessageListener(OpenFlowMessageListener listener) {
305
306 }
307
308 @Override
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700309 public void addPacketListener(int priority, PacketListener listener) {
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700310 pktListener = listener;
311 }
312
313 @Override
314 public void removePacketListener(PacketListener listener) {
315 }
316
317 @Override
318 public void addEventListener(OpenFlowEventListener listener) {
319 }
320
321 @Override
322 public void removeEventListener(OpenFlowEventListener listener) {
323 }
324
325 @Override
326 public void write(Dpid dpid, OFMessage msg) {
327 }
328
329 @Override
330 public void processPacket(Dpid dpid, OFMessage msg) {
331 OpenFlowPacketContext pktCtx =
332 DefaultOpenFlowPacketContext.
333 packetContextFromPacketIn(sw, (OFPacketIn) msg);
334 pktListener.handlePacket(pktCtx);
335 }
336
337 @Override
338 public void setRole(Dpid dpid, RoleState role) {
339 }
340
341 }
342
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700343 private class TestOpenFlowSwitch implements OpenFlowSwitch {
344
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700345 RoleState state;
346 List<OFMessage> sent = new ArrayList<OFMessage>();
347 OFFactory factory = OFFactoryVer10.INSTANCE;
348
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700349 @Override
350 public void sendMsg(OFMessage msg) {
351 sent.add(msg);
352 }
353
354 @Override
355 public void sendMsg(List<OFMessage> msgs) {
356 }
357
358 @Override
359 public void handleMessage(OFMessage fromSwitch) {
360 }
361
362 @Override
363 public void setRole(RoleState role) {
364 state = role;
365 }
366
367 @Override
368 public RoleState getRole() {
369 return state;
370 }
371
372 @Override
373 public List<OFPortDesc> getPorts() {
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700374 return PLIST;
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700375 }
376
377 @Override
378 public OFFactory factory() {
379 return factory;
380 }
381
382 @Override
383 public String getStringId() {
384 return null;
385 }
386
387 @Override
388 public long getId() {
389 return 0;
390 }
391
392 @Override
Ray Milkeyd3edd032015-01-16 11:38:58 -0800393 public String manufacturerDescription() {
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700394 return null;
395 }
396
397 @Override
398 public String datapathDescription() {
399 return null;
400 }
401
402 @Override
403 public String hardwareDescription() {
404 return null;
405 }
406
407 @Override
408 public String softwareDescription() {
409 return null;
410 }
411
412 @Override
413 public String serialNumber() {
414 return null;
415 }
416
417 @Override
Yuta HIGUCHI69a27352014-10-31 15:48:37 -0700418 public boolean isConnected() {
419 return true;
420 }
421
422 @Override
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700423 public void disconnectSwitch() {
424 }
425
Ayaka Koshibeab91cc42014-09-25 10:20:52 -0700426 @Override
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700427 public void returnRoleReply(RoleState requested, RoleState reponse) {
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700428 }
Marc De Leenheerb9311372015-07-09 11:36:49 -0700429 @Override
430 public Device.Type deviceType() {
431 return Device.Type.SWITCH;
432 }
Praseed Balakrishnana22eadf2014-10-20 14:21:45 -0700433
Ray Milkeye53f1712015-01-16 09:17:16 -0800434 @Override
435 public String channelId() {
436 return "1.2.3.4:1";
437 }
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700438 }
439
440}