blob: e117ba63df3a217184252cc6c95256a2b395691f [file] [log] [blame]
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -07001package org.onlab.onos.provider.of.packet.impl;
2
3import static org.junit.Assert.assertEquals;
4import static org.junit.Assert.assertNotNull;
5import static org.junit.Assert.assertNull;
6
7import java.nio.ByteBuffer;
8import java.util.ArrayList;
9import java.util.List;
10import java.util.Set;
11
12import org.junit.After;
13import org.junit.Before;
14import org.junit.Test;
15import org.onlab.onos.net.DeviceId;
16import org.onlab.onos.net.PortNumber;
17import org.onlab.onos.net.flow.DefaultTrafficTreatment;
18import org.onlab.onos.net.flow.TrafficTreatment;
19import org.onlab.onos.net.flow.instructions.Instruction;
20import org.onlab.onos.net.flow.instructions.Instructions;
21import org.onlab.onos.net.packet.DefaultOutboundPacket;
22import org.onlab.onos.net.packet.OutboundPacket;
23import org.onlab.onos.net.packet.PacketContext;
24import org.onlab.onos.net.packet.PacketProvider;
25import org.onlab.onos.net.packet.PacketProviderRegistry;
26import org.onlab.onos.net.packet.PacketProviderService;
27import org.onlab.onos.net.provider.ProviderId;
28import org.onlab.onos.openflow.controller.DefaultOpenFlowPacketContext;
29import org.onlab.onos.openflow.controller.Dpid;
30import org.onlab.onos.openflow.controller.OpenFlowController;
31import org.onlab.onos.openflow.controller.OpenFlowEventListener;
32import org.onlab.onos.openflow.controller.OpenFlowPacketContext;
33import org.onlab.onos.openflow.controller.OpenFlowSwitch;
34import org.onlab.onos.openflow.controller.OpenFlowSwitchListener;
35import org.onlab.onos.openflow.controller.PacketListener;
36import org.onlab.onos.openflow.controller.RoleState;
37import org.onlab.packet.ARP;
38import org.onlab.packet.Ethernet;
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -070039import org.onlab.packet.IpPrefix;
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070040import org.projectfloodlight.openflow.protocol.OFFactory;
41import org.projectfloodlight.openflow.protocol.OFMessage;
42import org.projectfloodlight.openflow.protocol.OFPacketIn;
43import org.projectfloodlight.openflow.protocol.OFPacketInReason;
44import org.projectfloodlight.openflow.protocol.OFPortDesc;
45import org.projectfloodlight.openflow.protocol.ver10.OFFactoryVer10;
46import org.projectfloodlight.openflow.types.MacAddress;
47import org.projectfloodlight.openflow.types.OFBufferId;
48import org.projectfloodlight.openflow.types.OFPort;
49
50import com.google.common.collect.Lists;
51import com.google.common.collect.Sets;
52
53
54public class OpenFlowPacketProviderTest {
55
56 private static final int PN1 = 100;
57 private static final int PN2 = 200;
58 private static final int PN3 = 300;
59 private static final short VLANID = (short) 100;
60
61 private static final DeviceId DID = DeviceId.deviceId("of:1");
62 private static final DeviceId DID_MISSING = DeviceId.deviceId("of:2");
63 private static final DeviceId DID_WRONG = DeviceId.deviceId("test:1");
64 private static final PortNumber P1 = PortNumber.portNumber(PN1);
65 private static final PortNumber P2 = PortNumber.portNumber(PN2);
66 private static final PortNumber P3 = PortNumber.portNumber(PN3);
67
68 private static final Instruction INST1 = Instructions.createOutput(P1);
69 private static final Instruction INST2 = Instructions.createOutput(P2);
70 private static final Instruction INST3 = Instructions.createOutput(P3);
71
72 private static final OFPortDesc PD1 = portDesc(PN1);
73 private static final OFPortDesc PD2 = portDesc(PN2);
74
75 private static final List<OFPortDesc> PLIST = Lists.newArrayList(PD1, PD2);
76 private static final TrafficTreatment TR = treatment(INST1, INST2);
77 private static final TrafficTreatment TR_MISSING = treatment(INST1, INST3);
78
79 private final OpenFlowPacketProvider provider = new OpenFlowPacketProvider();
80 private final TestPacketRegistry registry = new TestPacketRegistry();
81 private final TestController controller = new TestController();
82
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -070083 private final TestOpenFlowSwitch sw = new TestOpenFlowSwitch();
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -070084
85 @Before
86 public void startUp() {
87 provider.providerRegistry = registry;
88 provider.controller = controller;
89 provider.activate();
90 assertNotNull("listener should be registered", registry.listener);
91 }
92
93 @After
94 public void teardown() {
95 provider.deactivate();
96 assertNull("listeners shouldn't be registered", registry.listener);
97 provider.controller = null;
98 provider.providerRegistry = null;
99 }
100
101 @Test(expected = IllegalArgumentException.class)
Ayaka Koshibe91c9bc72014-09-19 12:52:24 -0700102 public void wrongScheme() {
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700103 sw.setRole(RoleState.MASTER);
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700104 OutboundPacket schemeFailPkt = outPacket(DID_WRONG, TR, null);
105 provider.emit(schemeFailPkt);
106 assertEquals("message sent incorrectly", 0, sw.sent.size());
107 }
108
109 @Test
110 public void emit() {
111
112 MacAddress mac1 = MacAddress.of("00:00:00:11:00:01");
113 MacAddress mac2 = MacAddress.of("00:00:00:22:00:02");
114
115 ARP arp = new ARP();
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700116 arp.setSenderProtocolAddress(IpPrefix.ANY)
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700117 .setSenderHardwareAddress(mac1.getBytes())
118 .setTargetHardwareAddress(mac2.getBytes())
Ayaka Koshibe1d56fe42014-09-19 16:51:58 -0700119 .setTargetProtocolAddress(IpPrefix.ANY)
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700120 .setHardwareType((short) 0)
121 .setProtocolType((short) 0)
122 .setHardwareAddressLength((byte) 6)
123 .setProtocolAddressLength((byte) 4)
124 .setOpCode((byte) 0);
125
126 Ethernet eth = new Ethernet();
127 eth.setVlanID(VLANID)
128 .setEtherType(Ethernet.TYPE_ARP)
129 .setSourceMACAddress("00:00:00:11:00:01")
130 .setDestinationMACAddress("00:00:00:22:00:02")
131 .setPayload(arp);
132
133 //the should-be working setup.
134 OutboundPacket passPkt = outPacket(DID, TR, eth);
135 sw.setRole(RoleState.MASTER);
136 provider.emit(passPkt);
137 assertEquals("invalid switch", sw, controller.current);
138 assertEquals("message not sent", PLIST.size(), sw.sent.size());
139 sw.sent.clear();
140
141 //wrong Role
142 sw.setRole(RoleState.SLAVE);
143 provider.emit(passPkt);
144 assertEquals("invalid switch", sw, controller.current);
145 assertEquals("message sent incorrectly", 0, sw.sent.size());
146
147 sw.setRole(RoleState.MASTER);
148
149 //missing switch
150 OutboundPacket swFailPkt = outPacket(DID_MISSING, TR, eth);
151 provider.emit(swFailPkt);
152 assertNull("invalid switch", controller.current);
153 assertEquals("message sent incorrectly", 0, sw.sent.size());
154
155 //to missing port
156 OutboundPacket portFailPkt = outPacket(DID, TR_MISSING, eth);
157 provider.emit(portFailPkt);
158 assertEquals("extra message sent", 1, sw.sent.size());
159
160 }
161
162 @Test
163 public void handlePacket() {
164 OFPacketIn pkt = sw.factory().buildPacketIn()
165 .setBufferId(OFBufferId.NO_BUFFER)
166 .setInPort(OFPort.NO_MASK)
167 .setReason(OFPacketInReason.INVALID_TTL)
168 .build();
169
170 controller.processPacket(null, pkt);
171 assertNotNull("message unprocessed", registry.ctx);
172
173 }
174
175 private static OFPortDesc portDesc(int port) {
176 OFPortDesc.Builder builder = OFFactoryVer10.INSTANCE.buildPortDesc();
177 builder.setPortNo(OFPort.of(port));
178
179 return builder.build();
180 }
181
182 private static TrafficTreatment treatment(Instruction ... insts) {
183 TrafficTreatment.Builder builder = new DefaultTrafficTreatment.Builder();
184 for (Instruction i : insts) {
185 builder.add(i);
186 }
187 return builder.build();
188 }
189
190 private static OutboundPacket outPacket(
191 DeviceId d, TrafficTreatment t, Ethernet e) {
192 ByteBuffer buf = null;
193 if (e != null) {
194 buf = ByteBuffer.wrap(e.serialize());
195 }
196 return new DefaultOutboundPacket(d, t, buf);
197 }
198
199 private class TestPacketRegistry implements PacketProviderRegistry {
200
201 PacketProvider listener = null;
202 PacketContext ctx = null;
203
204 @Override
205 public PacketProviderService register(PacketProvider provider) {
206 listener = provider;
207 return new TestPacketProviderService();
208 }
209
210 @Override
211 public void unregister(PacketProvider provider) {
212 listener = null;
213 }
214
215 @Override
216 public Set<ProviderId> getProviders() {
217 return Sets.newHashSet(listener.id());
218 }
219
220 private class TestPacketProviderService implements PacketProviderService {
221
222 @Override
223 public PacketProvider provider() {
224 return null;
225 }
226
227 @Override
228 public void processPacket(PacketContext context) {
229 ctx = context;
230 }
231
232 }
233 }
234
235 private class TestController implements OpenFlowController {
236
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700237 PacketListener pktListener;
238 OpenFlowSwitch current;
239
240 @Override
241 public Iterable<OpenFlowSwitch> getSwitches() {
242 return null;
243 }
244
245 @Override
246 public Iterable<OpenFlowSwitch> getMasterSwitches() {
247 return null;
248 }
249
250 @Override
251 public Iterable<OpenFlowSwitch> getEqualSwitches() {
252 return null;
253 }
254
255 @Override
256 public OpenFlowSwitch getSwitch(Dpid dpid) {
257 if (dpid.equals(Dpid.dpid(DID.uri()))) {
258 current = sw;
259 } else {
260 current = null;
261 }
262 return current;
263 }
264
265 @Override
266 public OpenFlowSwitch getMasterSwitch(Dpid dpid) {
267 return null;
268 }
269
270 @Override
271 public OpenFlowSwitch getEqualSwitch(Dpid dpid) {
272 return null;
273 }
274
275 @Override
276 public void addListener(OpenFlowSwitchListener listener) {
277 }
278
279 @Override
280 public void removeListener(OpenFlowSwitchListener listener) {
281 }
282
283 @Override
284 public void addPacketListener(int priority, PacketListener listener) {
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700285 pktListener = listener;
286 }
287
288 @Override
289 public void removePacketListener(PacketListener listener) {
290 }
291
292 @Override
293 public void addEventListener(OpenFlowEventListener listener) {
294 }
295
296 @Override
297 public void removeEventListener(OpenFlowEventListener listener) {
298 }
299
300 @Override
301 public void write(Dpid dpid, OFMessage msg) {
302 }
303
304 @Override
305 public void processPacket(Dpid dpid, OFMessage msg) {
306 OpenFlowPacketContext pktCtx =
307 DefaultOpenFlowPacketContext.
308 packetContextFromPacketIn(sw, (OFPacketIn) msg);
309 pktListener.handlePacket(pktCtx);
310 }
311
312 @Override
313 public void setRole(Dpid dpid, RoleState role) {
314 }
315
316 }
317
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700318 private class TestOpenFlowSwitch implements OpenFlowSwitch {
319
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700320 RoleState state;
321 List<OFMessage> sent = new ArrayList<OFMessage>();
322 OFFactory factory = OFFactoryVer10.INSTANCE;
323
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700324 @Override
325 public void sendMsg(OFMessage msg) {
326 sent.add(msg);
327 }
328
329 @Override
330 public void sendMsg(List<OFMessage> msgs) {
331 }
332
333 @Override
334 public void handleMessage(OFMessage fromSwitch) {
335 }
336
337 @Override
338 public void setRole(RoleState role) {
339 state = role;
340 }
341
342 @Override
343 public RoleState getRole() {
344 return state;
345 }
346
347 @Override
348 public List<OFPortDesc> getPorts() {
Ayaka Koshibe0380d4c2014-09-19 16:03:07 -0700349 return PLIST;
Ayaka Koshibe96ca09d2014-09-19 12:06:14 -0700350 }
351
352 @Override
353 public OFFactory factory() {
354 return factory;
355 }
356
357 @Override
358 public String getStringId() {
359 return null;
360 }
361
362 @Override
363 public long getId() {
364 return 0;
365 }
366
367 @Override
368 public String manfacturerDescription() {
369 return null;
370 }
371
372 @Override
373 public String datapathDescription() {
374 return null;
375 }
376
377 @Override
378 public String hardwareDescription() {
379 return null;
380 }
381
382 @Override
383 public String softwareDescription() {
384 return null;
385 }
386
387 @Override
388 public String serialNumber() {
389 return null;
390 }
391
392 @Override
393 public void disconnectSwitch() {
394 }
395
396 }
397
398}