blob: 32afe4e160d9b365846523790a35c0128a22d42f [file] [log] [blame]
Umesh Krishnaswamy345ee992012-12-13 20:29:48 -08001package net.floodlightcontroller.virtualnetwork;
2
3import static org.easymock.EasyMock.*;
4
5import java.util.List;
6
7import org.easymock.EasyMock;
8import org.junit.Before;
9import org.junit.Test;
10import org.openflow.protocol.OFMatch;
11import org.openflow.protocol.OFPacketIn;
12import org.openflow.protocol.OFType;
13import org.openflow.protocol.OFPacketIn.OFPacketInReason;
14
15import net.floodlightcontroller.core.FloodlightContext;
16import net.floodlightcontroller.core.IFloodlightProviderService;
17import net.floodlightcontroller.core.IOFMessageListener;
18import net.floodlightcontroller.core.IListener.Command;
19import net.floodlightcontroller.core.IOFSwitch;
20import net.floodlightcontroller.core.module.FloodlightModuleContext;
21import net.floodlightcontroller.core.test.MockThreadPoolService;
22import net.floodlightcontroller.core.test.PacketFactory;
23import net.floodlightcontroller.devicemanager.IDeviceService;
24import net.floodlightcontroller.devicemanager.IEntityClassifierService;
25import net.floodlightcontroller.devicemanager.internal.DefaultEntityClassifier;
26import net.floodlightcontroller.devicemanager.test.MockDeviceManager;
27import net.floodlightcontroller.flowcache.FlowReconcileManager;
28import net.floodlightcontroller.flowcache.IFlowReconcileService;
29import net.floodlightcontroller.packet.Data;
30import net.floodlightcontroller.packet.Ethernet;
31import net.floodlightcontroller.packet.IPacket;
32import net.floodlightcontroller.packet.IPv4;
33import net.floodlightcontroller.packet.UDP;
34import net.floodlightcontroller.restserver.IRestApiService;
35import net.floodlightcontroller.restserver.RestApiServer;
36import net.floodlightcontroller.test.FloodlightTestCase;
37import net.floodlightcontroller.threadpool.IThreadPoolService;
38import net.floodlightcontroller.topology.ITopologyService;
39import net.floodlightcontroller.util.MACAddress;
40import net.floodlightcontroller.virtualnetwork.VirtualNetworkFilter;
41
42public class VirtualNetworkFilterTest extends FloodlightTestCase {
43 protected VirtualNetworkFilter vns;
44 protected MockDeviceManager deviceService;
45
46 protected static String guid1 = "guid1";
47 protected static String net1 = "net1";
48 protected static String gw1 = "1.1.1.1";
49 protected static String guid2 = "guid2";
50 protected static String net2 = "net2";
51 protected static String guid3 = "guid3";
52 protected static String net3 = "net3";
53 protected static String gw2 = "2.2.2.2";
54
55 protected static MACAddress mac1 =
56 new MACAddress(Ethernet.toMACAddress("00:11:22:33:44:55"));
57 protected static MACAddress mac2 =
58 new MACAddress(Ethernet.toMACAddress("00:11:22:33:44:66"));
59 protected static MACAddress mac3 =
60 new MACAddress(Ethernet.toMACAddress("00:11:22:33:44:77"));
61 protected static MACAddress mac4 =
62 new MACAddress(Ethernet.toMACAddress("00:11:22:33:44:88"));
63 protected static String hostPort1 = "port1";
64 protected static String hostPort2 = "port2";
65 protected static String hostPort3 = "port3";
66 protected static String hostPort4 = "port4";
67
68 // For testing forwarding behavior
69 protected IOFSwitch sw1;
70 protected FloodlightContext cntx;
71 protected OFPacketIn mac1ToMac2PacketIn;
72 protected IPacket mac1ToMac2PacketIntestPacket;
73 protected byte[] mac1ToMac2PacketIntestPacketSerialized;
74 protected OFPacketIn mac1ToMac4PacketIn;
75 protected IPacket mac1ToMac4PacketIntestPacket;
76 protected byte[] mac1ToMac4PacketIntestPacketSerialized;
77 protected OFPacketIn mac1ToGwPacketIn;
78 protected IPacket mac1ToGwPacketIntestPacket;
79 protected byte[] mac1ToGwPacketIntestPacketSerialized;
80 protected OFPacketIn packetInDHCPDiscoveryRequest;
81
82 @Before
83 public void setUp() throws Exception {
84 super.setUp();
85
86 // Module loading stuff
87 FloodlightModuleContext fmc = new FloodlightModuleContext();
88 RestApiServer restApi = new RestApiServer();
89 deviceService = new MockDeviceManager();
90 FlowReconcileManager frm = new FlowReconcileManager();
91 MockThreadPoolService tps = new MockThreadPoolService();
92 ITopologyService topology = createMock(ITopologyService.class);
93 vns = new VirtualNetworkFilter();
94 DefaultEntityClassifier entityClassifier = new DefaultEntityClassifier();
95 fmc.addService(IRestApiService.class, restApi);
96 fmc.addService(IFloodlightProviderService.class, getMockFloodlightProvider());
97 fmc.addService(IDeviceService.class, deviceService);
98 fmc.addService(IFlowReconcileService.class, frm);
99 fmc.addService(IThreadPoolService.class, tps);
100 fmc.addService(IEntityClassifierService.class, entityClassifier);
101 fmc.addService(ITopologyService.class, topology);
102 tps.init(fmc);
103 frm.init(fmc);
104 deviceService.init(fmc);
105 restApi.init(fmc);
106 getMockFloodlightProvider().init(fmc);
107 entityClassifier.init(fmc);
108 tps.startUp(fmc);
109 vns.init(fmc);
110 frm.startUp(fmc);
111 deviceService.startUp(fmc);
112 restApi.startUp(fmc);
113 getMockFloodlightProvider().startUp(fmc);
114 vns.startUp(fmc);
115 entityClassifier.startUp(fmc);
116
117 topology.addListener(deviceService);
118 expectLastCall().times(1);
119 replay(topology);
120 // Mock switches
121 //fastWilcards mocked as this constant
122 int fastWildcards =
123 OFMatch.OFPFW_IN_PORT |
124 OFMatch.OFPFW_NW_PROTO |
125 OFMatch.OFPFW_TP_SRC |
126 OFMatch.OFPFW_TP_DST |
127 OFMatch.OFPFW_NW_SRC_ALL |
128 OFMatch.OFPFW_NW_DST_ALL |
129 OFMatch.OFPFW_NW_TOS;
130 sw1 = EasyMock.createNiceMock(IOFSwitch.class);
131 expect(sw1.getId()).andReturn(1L).anyTimes();
132 expect(sw1.getAttribute(IOFSwitch.PROP_FASTWILDCARDS)).andReturn((Integer)fastWildcards).anyTimes();
133 expect(sw1.hasAttribute(IOFSwitch.PROP_SUPPORTS_OFPP_TABLE)).andReturn(true).anyTimes();
134 replay(sw1);
135
136 // Mock packets
137 // Mock from MAC1 -> MAC2
138 mac1ToMac2PacketIntestPacket = new Ethernet()
139 .setDestinationMACAddress(mac2.toBytes())
140 .setSourceMACAddress(mac1.toBytes())
141 .setEtherType(Ethernet.TYPE_IPv4)
142 .setPayload(
143 new IPv4()
144 .setTtl((byte) 128)
145 .setSourceAddress("192.168.1.1")
146 .setDestinationAddress("192.168.1.2")
147 .setPayload(new UDP()
148 .setSourcePort((short) 5000)
149 .setDestinationPort((short) 5001)
150 .setPayload(new Data(new byte[] {0x01}))));
151 mac1ToMac2PacketIntestPacketSerialized = mac1ToMac2PacketIntestPacket.serialize();
152 mac1ToMac2PacketIn =
153 ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory().
154 getMessage(OFType.PACKET_IN))
155 .setBufferId(-1)
156 .setInPort((short) 1)
157 .setPacketData(mac1ToMac2PacketIntestPacketSerialized)
158 .setReason(OFPacketInReason.NO_MATCH)
159 .setTotalLength((short) mac1ToMac2PacketIntestPacketSerialized.length);
160
161 // Mock from MAC1 -> MAC4
162 mac1ToMac4PacketIntestPacket = new Ethernet()
163 .setDestinationMACAddress(mac4.toBytes())
164 .setSourceMACAddress(mac1.toBytes())
165 .setEtherType(Ethernet.TYPE_IPv4)
166 .setPayload(
167 new IPv4()
168 .setTtl((byte) 128)
169 .setSourceAddress("192.168.1.1")
170 .setDestinationAddress("192.168.1.2")
171 .setPayload(new UDP()
172 .setSourcePort((short) 5000)
173 .setDestinationPort((short) 5001)
174 .setPayload(new Data(new byte[] {0x01}))));
175 mac1ToMac4PacketIntestPacketSerialized = mac1ToMac4PacketIntestPacket.serialize();
176 mac1ToMac4PacketIn =
177 ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory().
178 getMessage(OFType.PACKET_IN))
179 .setBufferId(-1)
180 .setInPort((short) 1)
181 .setPacketData(mac1ToMac4PacketIntestPacketSerialized)
182 .setReason(OFPacketInReason.NO_MATCH)
183 .setTotalLength((short) mac1ToMac4PacketIntestPacketSerialized.length);
184
185 // Mock from MAC1 to gateway1
186 mac1ToGwPacketIntestPacket = new Ethernet()
187 .setDestinationMACAddress("00:11:33:33:44:55") // mac shouldn't matter, can't be other host
188 .setSourceMACAddress(mac1.toBytes())
189 .setEtherType(Ethernet.TYPE_IPv4)
190 .setPayload(
191 new IPv4()
192 .setTtl((byte) 128)
193 .setSourceAddress("192.168.1.1")
194 .setDestinationAddress(gw1)
195 .setPayload(new UDP()
196 .setSourcePort((short) 5000)
197 .setDestinationPort((short) 5001)
198 .setPayload(new Data(new byte[] {0x01}))));
199 mac1ToGwPacketIntestPacketSerialized = mac1ToGwPacketIntestPacket.serialize();
200 mac1ToGwPacketIn =
201 ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory().
202 getMessage(OFType.PACKET_IN))
203 .setBufferId(-1)
204 .setInPort((short) 1)
205 .setPacketData(mac1ToGwPacketIntestPacketSerialized)
206 .setReason(OFPacketInReason.NO_MATCH)
207 .setTotalLength((short) mac1ToGwPacketIntestPacketSerialized.length);
208 }
209
210 @Test
211 public void testCreateNetwork() {
212 // Test creating a network with all parameters
213 vns.createNetwork(guid1, net1, IPv4.toIPv4Address(gw1));
214 assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid1));
215 assertTrue(vns.nameToGuid.get(net1).equals(guid1));
216 assertTrue(vns.guidToGateway.get(guid1).equals(IPv4.toIPv4Address(gw1)));
217 assertTrue(vns.vNetsByGuid.get(guid1).name.equals(net1));
218 assertTrue(vns.vNetsByGuid.get(guid1).guid.equals(guid1));
219 assertTrue(vns.vNetsByGuid.get(guid1).gateway.equals(gw1));
220 assertTrue(vns.vNetsByGuid.get(guid1).hosts.size()==0);
221
222 // Test creating network without a gateway
223 vns.createNetwork(guid2, net2, null);
224 assertTrue(vns.nameToGuid.get(net2).equals(guid2));
225 assertTrue(vns.guidToGateway.get(guid2) == null);
226 assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).size() == 1);
227 assertTrue(vns.vNetsByGuid.get(guid2).name.equals(net2));
228 assertTrue(vns.vNetsByGuid.get(guid2).guid.equals(guid2));
229 assertTrue(vns.vNetsByGuid.get(guid2).gateway == null);
230 assertTrue(vns.vNetsByGuid.get(guid2).hosts.size()==0);
231
232 // Test creating a network that shares the gateway with net1
233 vns.createNetwork(guid3, net3, IPv4.toIPv4Address(gw1));
234 assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid1));
235 assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid3));
236 assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).size() == 2);
237 assertTrue(vns.nameToGuid.get(net3).equals(guid3));
238 assertTrue(vns.guidToGateway.get(guid3).equals(IPv4.toIPv4Address(gw1)));
239 assertTrue(vns.vNetsByGuid.get(guid3).name.equals(net3));
240 assertTrue(vns.vNetsByGuid.get(guid3).guid.equals(guid3));
241 assertTrue(vns.vNetsByGuid.get(guid3).gateway.equals(gw1));
242 assertTrue(vns.vNetsByGuid.get(guid3).hosts.size()==0);
243
244 }
245
246 @Test
247 public void testModifyNetwork() {
248 // Create some networks
249
250 testCreateNetwork();
251 // Modify net2 to add a gateway
252 vns.createNetwork(guid2, net2, IPv4.toIPv4Address(gw1));
253 assertTrue(vns.nameToGuid.get(net2).equals(guid2));
254 assertTrue(vns.guidToGateway.get(guid2).equals(IPv4.toIPv4Address(gw1)));
255 assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid1));
256 assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid2));
257 assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid3));
258 assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).size() == 3);
259 // Modify net2 to change it's name
260 vns.createNetwork(guid2, "newnet2", null);
261 // Make sure the gateway is still there
262 assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid2));
263 assertTrue(vns.vNetsByGuid.get(guid2).gateway.equals(gw1));
264 // make sure the new name mapping was learned
265 assertTrue(vns.nameToGuid.get("newnet2").equals(guid2));
266 assertTrue(vns.vNetsByGuid.get(guid2).name.equals("newnet2"));
267 // and the old one was deleted
268 assertFalse(vns.nameToGuid.containsKey(net2));
269 }
270
271 @Test
272 public void testDeleteNetwork() {
273 testModifyNetwork();
274 // Delete newnet2
275 vns.deleteNetwork(guid2);
276 assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid1));
277 assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid3));
278 assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).size() == 2);
279 assertFalse(vns.nameToGuid.containsKey(net2));
280 assertFalse(vns.guidToGateway.containsKey(net2));
281 assertTrue(vns.vNetsByGuid.get(guid2)==null);
282 }
283
284 @Test
285 public void testAddHost() {
286 testModifyNetwork();
287 vns.addHost(mac1, guid1, hostPort1);
288 assertTrue(vns.macToGuid.get(mac1).equals(guid1));
289 assertTrue(vns.portToMac.get(hostPort1).equals(mac1));
290 assertTrue(vns.vNetsByGuid.get(guid1).hosts.contains(mac1));
291 vns.addHost(mac2, guid1, hostPort2);
292 assertTrue(vns.macToGuid.get(mac2).equals(guid1));
293 assertTrue(vns.portToMac.get(hostPort2).equals(mac2));
294 assertTrue(vns.vNetsByGuid.get(guid1).hosts.contains(mac2));
295 vns.addHost(mac3, guid3, hostPort3);
296 vns.addHost(mac4, guid3, hostPort4);
297 assertTrue(vns.vNetsByGuid.get(guid3).hosts.contains(mac4));
298 }
299
300 @Test
301 public void testDeleteHost() {
302 testAddHost();
303
304 String host1Guid = vns.macToGuid.get(mac1);
305 vns.deleteHost(mac1, null);
306 assertFalse(vns.macToGuid.containsKey(mac1));
307 assertFalse(vns.portToMac.containsKey(hostPort1));
308 assertFalse(vns.vNetsByGuid.get(host1Guid).hosts.contains(mac1));
309
310 String host2Guid = vns.macToGuid.get(vns.portToMac.get(hostPort2));
311 vns.deleteHost(null, hostPort2);
312 assertFalse(vns.macToGuid.containsKey(mac2));
313 assertFalse(vns.portToMac.containsKey(hostPort2));
314 assertFalse(vns.vNetsByGuid.get(host2Guid).hosts.contains(mac2));
315
316 String host3Guid = vns.macToGuid.get(mac3);
317 vns.deleteHost(mac3, hostPort3);
318 assertFalse(vns.macToGuid.containsKey(mac3));
319 assertFalse(vns.portToMac.containsKey(hostPort3));
320 assertFalse(vns.vNetsByGuid.get(host3Guid).hosts.contains(mac3));
321
322 }
323
324 @Test
325 public void testForwarding() {
326 testAddHost();
327 // make sure mac1 can communicate with mac2
328 IOFMessageListener listener = getVirtualNetworkListener();
329 cntx = new FloodlightContext();
330 IFloodlightProviderService.bcStore.put(cntx,
331 IFloodlightProviderService.CONTEXT_PI_PAYLOAD,
332 (Ethernet)mac1ToMac2PacketIntestPacket);
333 Command ret = listener.receive(sw1, mac1ToMac2PacketIn, cntx);
334 assertTrue(ret == Command.CONTINUE);
335 // make sure mac1 can't communicate with mac4
336 cntx = new FloodlightContext();
337 IFloodlightProviderService.bcStore.put(cntx,
338 IFloodlightProviderService.CONTEXT_PI_PAYLOAD,
339 (Ethernet)mac1ToMac4PacketIntestPacket);
340 ret = listener.receive(sw1, mac1ToMac4PacketIn, cntx);
341 assertTrue(ret == Command.STOP);
342 }
343
344 @Test
345 public void testDefaultGateway() {
346 testAddHost();
347 IOFMessageListener listener = getVirtualNetworkListener();
348 cntx = new FloodlightContext();
349 IFloodlightProviderService.bcStore.put(cntx,
350 IFloodlightProviderService.CONTEXT_PI_PAYLOAD,
351 (Ethernet)mac1ToGwPacketIntestPacket);
352 deviceService.learnEntity(((Ethernet)mac1ToGwPacketIntestPacket).getDestinationMAC().toLong(),
353 null, IPv4.toIPv4Address(gw1), null, null);
354 Command ret = listener.receive(sw1, mac1ToGwPacketIn, cntx);
355 assertTrue(ret == Command.CONTINUE);
356 }
357
358 @Test
359 public void testDhcp() {
360 IOFMessageListener listener = getVirtualNetworkListener();
361 Ethernet dhcpPacket = PacketFactory.DhcpDiscoveryRequestEthernet(mac1);
362 OFPacketIn dhcpPacketOf = PacketFactory.DhcpDiscoveryRequestOFPacketIn(mac1);
363 cntx = new FloodlightContext();
364 IFloodlightProviderService.bcStore.put(cntx,
365 IFloodlightProviderService.CONTEXT_PI_PAYLOAD,
366 dhcpPacket);
367 Command ret = listener.receive(sw1, dhcpPacketOf, cntx);
368 assertTrue(ret == Command.CONTINUE);
369 }
370
371 protected IOFMessageListener getVirtualNetworkListener() {
372 List<IOFMessageListener> listeners = mockFloodlightProvider.getListeners().get(OFType.PACKET_IN);
373 return listeners.get(listeners.indexOf(vns));
374 }
375}