blob: 45cfa23c28c21f8867a85148ea0ad050efa0d9e5 [file] [log] [blame]
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Yi Tseng7a38f9a2017-06-09 14:36:40 -07003 *
4 * 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
7 *
8 * 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.
15 */
16package org.onosproject.dhcprelay;
17
18import com.google.common.collect.ImmutableList;
19import com.google.common.collect.ImmutableSet;
20import com.google.common.collect.Lists;
21import com.google.common.collect.Maps;
22import com.google.common.collect.Sets;
Yi Tseng2cf59912017-08-24 14:47:34 -070023import org.apache.commons.io.Charsets;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070024import org.easymock.EasyMock;
25import org.junit.After;
26import org.junit.Before;
27import org.junit.Test;
28import org.onlab.packet.ARP;
29import org.onlab.packet.DHCP;
Yi Tseng4fa05832017-08-17 13:08:31 -070030import org.onlab.packet.DeserializationException;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070031import org.onlab.packet.Ethernet;
32import org.onlab.packet.IPv4;
33import org.onlab.packet.Ip4Address;
34import org.onlab.packet.IpAddress;
35import org.onlab.packet.MacAddress;
36import org.onlab.packet.UDP;
37import org.onlab.packet.VlanId;
38import org.onlab.packet.dhcp.CircuitId;
39import org.onlab.packet.dhcp.DhcpOption;
40import org.onlab.packet.dhcp.DhcpRelayAgentOption;
41import org.onosproject.TestApplicationId;
42import org.onosproject.cfg.ComponentConfigService;
43import org.onosproject.core.ApplicationId;
44import org.onosproject.core.CoreService;
Yi Tsenge72fbb52017-08-02 15:03:31 -070045import org.onosproject.dhcprelay.api.DhcpHandler;
46import org.onosproject.dhcprelay.config.DefaultDhcpRelayConfig;
47import org.onosproject.dhcprelay.config.DhcpServerConfig;
48import org.onosproject.dhcprelay.config.IndirectDhcpRelayConfig;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070049import org.onosproject.dhcprelay.store.DhcpRecord;
50import org.onosproject.dhcprelay.store.DhcpRelayStore;
51import org.onosproject.dhcprelay.store.DhcpRelayStoreEvent;
Ray Milkeyfacf2862017-08-03 11:58:29 -070052import org.onosproject.net.intf.Interface;
53import org.onosproject.net.intf.InterfaceServiceAdapter;
Ray Milkey69ec8712017-08-08 13:00:43 -070054import org.onosproject.routeservice.Route;
55import org.onosproject.routeservice.RouteStoreAdapter;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070056import org.onosproject.net.ConnectPoint;
57import org.onosproject.net.DefaultHost;
58import org.onosproject.net.Host;
59import org.onosproject.net.HostId;
60import org.onosproject.net.HostLocation;
61import org.onosproject.net.config.NetworkConfigRegistry;
62import org.onosproject.net.host.HostDescription;
63import org.onosproject.net.host.HostEvent;
64import org.onosproject.net.host.HostService;
65import org.onosproject.net.host.HostStoreAdapter;
66import org.onosproject.net.host.InterfaceIpAddress;
67import org.onosproject.net.packet.DefaultInboundPacket;
68import org.onosproject.net.packet.InboundPacket;
69import org.onosproject.net.packet.OutboundPacket;
70import org.onosproject.net.packet.PacketContext;
71import org.onosproject.net.packet.PacketContextAdapter;
72import org.onosproject.net.packet.PacketProcessor;
73import org.onosproject.net.packet.PacketServiceAdapter;
74import org.onosproject.net.provider.ProviderId;
75import org.onosproject.store.StoreDelegate;
76import org.osgi.service.component.ComponentContext;
77
78import java.nio.ByteBuffer;
79import java.util.Collection;
80import java.util.Dictionary;
81import java.util.List;
82import java.util.Map;
83import java.util.Optional;
84import java.util.Set;
85import java.util.stream.Collectors;
86
87import static org.easymock.EasyMock.*;
88import static org.junit.Assert.*;
89
90public class DhcpRelayManagerTest {
91 // Ip address for interfaces
92 private static final InterfaceIpAddress INTERFACE_IP = InterfaceIpAddress.valueOf("10.0.3.254/32");
93 private static final List<InterfaceIpAddress> INTERFACE_IPS = ImmutableList.of(INTERFACE_IP);
94
95 // DHCP client (will send without option 82)
96 private static final Ip4Address IP_FOR_CLIENT = Ip4Address.valueOf("10.0.0.1");
97 private static final MacAddress CLIENT_MAC = MacAddress.valueOf("00:00:00:00:00:01");
98 private static final VlanId CLIENT_VLAN = VlanId.vlanId("100");
99 private static final ConnectPoint CLIENT_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
100 private static final MacAddress CLIENT_IFACE_MAC = MacAddress.valueOf("00:00:00:00:11:01");
101 private static final Interface CLIENT_INTERFACE = new Interface("C1",
102 CLIENT_CP,
103 INTERFACE_IPS,
104 CLIENT_IFACE_MAC,
105 CLIENT_VLAN);
106
107 // DHCP client 2 (will send with option 82, so the vlan should equals to vlan from server)
108 private static final MacAddress CLIENT2_MAC = MacAddress.valueOf("00:00:00:00:00:01");
109 private static final VlanId CLIENT2_VLAN = VlanId.NONE;
110 private static final ConnectPoint CLIENT2_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
111 private static final MacAddress CLIENT2_IFACE_MAC = MacAddress.valueOf("00:00:00:00:11:01");
112 private static final Interface CLIENT2_INTERFACE = new Interface("C2",
113 CLIENT2_CP,
114 INTERFACE_IPS,
115 CLIENT2_IFACE_MAC,
116 CLIENT2_VLAN);
117
118 // Outer relay information
119 private static final Ip4Address OUTER_RELAY_IP = Ip4Address.valueOf("10.0.5.253");
120 private static final Set<IpAddress> OUTER_RELAY_IPS = ImmutableSet.of(OUTER_RELAY_IP);
121 private static final MacAddress OUTER_RELAY_MAC = MacAddress.valueOf("00:01:02:03:04:05");
122 private static final VlanId OUTER_RELAY_VLAN = VlanId.NONE;
123 private static final ConnectPoint OUTER_RELAY_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
124 private static final HostLocation OUTER_REPLAY_HL = new HostLocation(OUTER_RELAY_CP, 0);
125 private static final HostId OUTER_RELAY_HOST_ID = HostId.hostId(OUTER_RELAY_MAC, OUTER_RELAY_VLAN);
126 private static final Host OUTER_RELAY_HOST = new DefaultHost(DhcpRelayManager.PROVIDER_ID,
127 OUTER_RELAY_HOST_ID,
128 OUTER_RELAY_MAC,
129 OUTER_RELAY_VLAN,
130 OUTER_REPLAY_HL,
131 OUTER_RELAY_IPS);
132
133 // DHCP Server
134 private static final MacAddress SERVER_MAC = MacAddress.valueOf("00:00:00:00:00:01");
135 private static final VlanId SERVER_VLAN = VlanId.NONE;
136 private static final ConnectPoint SERVER_CONNECT_POINT =
137 ConnectPoint.deviceConnectPoint("of:0000000000000001/5");
138 private static final HostLocation SERVER_LOCATION =
139 new HostLocation(SERVER_CONNECT_POINT, 0);
140 private static final Ip4Address SERVER_IP = Ip4Address.valueOf("10.0.3.253");
141 private static final Set<IpAddress> DHCP_SERVER_IPS = ImmutableSet.of(SERVER_IP);
142 private static final HostId SERVER_HOST_ID = HostId.hostId(SERVER_MAC, SERVER_VLAN);
143 private static final Host SERVER_HOST = new DefaultHost(DhcpRelayManager.PROVIDER_ID,
144 SERVER_HOST_ID,
145 SERVER_MAC,
146 SERVER_VLAN,
147 SERVER_LOCATION,
148 DHCP_SERVER_IPS);
149 private static final MacAddress SERVER_IFACE_MAC = MacAddress.valueOf("00:00:00:00:00:01");
150 private static final Interface SERVER_INTERFACE = new Interface("SERVER",
151 SERVER_CONNECT_POINT,
152 INTERFACE_IPS,
153 SERVER_IFACE_MAC,
154 SERVER_VLAN);
155
Yi Tseng4fa05832017-08-17 13:08:31 -0700156 // Relay agent config
157 private static final Ip4Address RELAY_AGENT_IP = Ip4Address.valueOf("10.0.4.254");
158
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700159 // Components
160 private static final ApplicationId APP_ID = TestApplicationId.create(DhcpRelayManager.DHCP_RELAY_APP);
Yi Tsenge72fbb52017-08-02 15:03:31 -0700161 private static final DefaultDhcpRelayConfig CONFIG = new MockDefaultDhcpRelayConfig();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700162 private static final Set<Interface> INTERFACES = ImmutableSet.of(
163 CLIENT_INTERFACE,
164 CLIENT2_INTERFACE,
165 SERVER_INTERFACE
166 );
Yi Tseng2cf59912017-08-24 14:47:34 -0700167 private static final String NON_ONOS_CID = "Non-ONOS circuit ID";
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700168
169 private DhcpRelayManager manager;
170 private MockPacketService packetService;
171 private MockHostStore mockHostStore;
172 private MockRouteStore mockRouteStore;
173 private MockDhcpRelayStore mockDhcpRelayStore;
174
175 @Before
176 public void setup() {
177 manager = new DhcpRelayManager();
178 manager.cfgService = createNiceMock(NetworkConfigRegistry.class);
179
Yi Tsenge72fbb52017-08-02 15:03:31 -0700180 expect(manager.cfgService.getConfig(APP_ID, DefaultDhcpRelayConfig.class))
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700181 .andReturn(CONFIG)
182 .anyTimes();
183
Yi Tsenge72fbb52017-08-02 15:03:31 -0700184 // TODO: add indirect test
185 expect(manager.cfgService.getConfig(APP_ID, IndirectDhcpRelayConfig.class))
186 .andReturn(null)
187 .anyTimes();
188
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700189 manager.coreService = createNiceMock(CoreService.class);
190 expect(manager.coreService.registerApplication(anyString()))
191 .andReturn(APP_ID).anyTimes();
192
193 manager.hostService = createNiceMock(HostService.class);
Yi Tseng4fa05832017-08-17 13:08:31 -0700194 expect(manager.hostService.getHostsByIp(anyObject())).andReturn(ImmutableSet.of(SERVER_HOST)).anyTimes();
195 expect(manager.hostService.getHost(OUTER_RELAY_HOST_ID)).andReturn(OUTER_RELAY_HOST).anyTimes();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700196
197 packetService = new MockPacketService();
198 manager.packetService = packetService;
199 manager.compCfgService = createNiceMock(ComponentConfigService.class);
200
201 mockHostStore = new MockHostStore();
202 mockRouteStore = new MockRouteStore();
203 mockDhcpRelayStore = new MockDhcpRelayStore();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700204 manager.dhcpRelayStore = mockDhcpRelayStore;
205
206 manager.interfaceService = new MockInterfaceService();
207
Yi Tseng51301292017-07-28 13:02:59 -0700208 Dhcp4HandlerImpl v4Handler = new Dhcp4HandlerImpl();
209 v4Handler.dhcpRelayStore = mockDhcpRelayStore;
210 v4Handler.hostService = manager.hostService;
211 v4Handler.hostStore = mockHostStore;
212 v4Handler.interfaceService = manager.interfaceService;
213 v4Handler.packetService = manager.packetService;
214 v4Handler.routeStore = mockRouteStore;
215 manager.v4Handler = v4Handler;
216
217 // TODO: initialize v6 handler.
Yi Tsenge72fbb52017-08-02 15:03:31 -0700218 DhcpHandler v6Handler = createNiceMock(DhcpHandler.class);
219 manager.v6Handler = v6Handler;
220
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700221 // properties
222 Dictionary<String, Object> dictionary = createNiceMock(Dictionary.class);
223 expect(dictionary.get("arpEnabled")).andReturn(true).anyTimes();
224 ComponentContext context = createNiceMock(ComponentContext.class);
225 expect(context.getProperties()).andReturn(dictionary).anyTimes();
226
227 EasyMock.replay(manager.cfgService, manager.coreService, manager.hostService,
228 manager.compCfgService, dictionary, context);
229 manager.activate(context);
230 }
231
232 @After
233 public void tearDown() {
234 manager.deactivate();
235 }
236
237 /**
238 * Relay a DHCP packet without option 82.
239 * Should add new host to host store after dhcp ack.
240 */
241 @Test
242 public void relayDhcpWithoutAgentInfo() {
243 // send request
244 packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT_MAC,
245 CLIENT_VLAN,
246 CLIENT_CP,
247 INTERFACE_IP.ipAddress().getIp4Address(),
248 false));
249
250 Set<Host> hosts = ImmutableSet.copyOf(mockHostStore.getHosts());
251 assertEquals(0, hosts.size());
252 assertEquals(0, mockRouteStore.routes.size());
253
254 // send ack
255 packetService.processPacket(new TestDhcpAckPacketContext(CLIENT_CP, CLIENT_MAC,
256 CLIENT_VLAN, INTERFACE_IP.ipAddress().getIp4Address(),
257 false));
258 hosts = ImmutableSet.copyOf(mockHostStore.getHosts());
259 assertEquals(1, hosts.size());
260 assertEquals(0, mockRouteStore.routes.size());
261
262 Host host = hosts.iterator().next();
263 assertEquals(CLIENT_MAC, host.mac());
264 assertEquals(CLIENT_VLAN, host.vlan());
265 assertEquals(CLIENT_CP.deviceId(), host.location().elementId());
266 assertEquals(CLIENT_CP.port(), host.location().port());
267 assertEquals(1, host.ipAddresses().size());
268 assertEquals(IP_FOR_CLIENT, host.ipAddresses().iterator().next());
269 assertEquals(HostId.hostId(CLIENT_MAC, CLIENT_VLAN), host.id());
270 }
271
272 /**
273 * Relay a DHCP packet with option 82 (Indirectly connected host).
274 */
275 @Test
276 public void relayDhcpWithAgentInfo() {
277 // Assume outer dhcp relay agent exists in store already
278 // send request
279 packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT2_MAC,
280 CLIENT2_VLAN,
281 CLIENT2_CP,
282 INTERFACE_IP.ipAddress().getIp4Address(),
283 true));
284
285 Set<Host> hosts = ImmutableSet.copyOf(mockHostStore.getHosts());
286 assertEquals(0, hosts.size());
287 assertEquals(0, mockRouteStore.routes.size());
288
289 // send ack
290 packetService.processPacket(new TestDhcpAckPacketContext(CLIENT2_CP,
291 CLIENT2_MAC,
292 CLIENT2_VLAN,
293 INTERFACE_IP.ipAddress().getIp4Address(),
294 true));
295
296 hosts = ImmutableSet.copyOf(mockHostStore.getHosts());
297 assertEquals(0, hosts.size());
298 assertEquals(1, mockRouteStore.routes.size());
299
300 Route route = mockRouteStore.routes.get(0);
301 assertEquals(OUTER_RELAY_IP, route.nextHop());
302 assertEquals(IP_FOR_CLIENT.toIpPrefix(), route.prefix());
303 assertEquals(Route.Source.STATIC, route.source());
304 }
305
306 @Test
Yi Tseng4fa05832017-08-17 13:08:31 -0700307 public void testWithRelayAgentConfig() throws DeserializationException {
308 manager.v4Handler
309 .setDefaultDhcpServerConfigs(ImmutableList.of(new MockDhcpServerConfig(RELAY_AGENT_IP)));
310 packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT2_MAC,
311 CLIENT2_VLAN,
312 CLIENT2_CP,
313 INTERFACE_IP.ipAddress().getIp4Address(),
314 true));
315 OutboundPacket outPacket = packetService.emittedPacket;
316 byte[] outData = outPacket.data().array();
317 Ethernet eth = Ethernet.deserializer().deserialize(outData, 0, outData.length);
318 IPv4 ip = (IPv4) eth.getPayload();
319 UDP udp = (UDP) ip.getPayload();
320 DHCP dhcp = (DHCP) udp.getPayload();
321 assertEquals(RELAY_AGENT_IP.toInt(), dhcp.getGatewayIPAddress());
322 }
323
324 @Test
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700325 public void testArpRequest() throws Exception {
326 packetService.processPacket(new TestArpRequestPacketContext(CLIENT_INTERFACE));
Ray Milkeybd52a052017-08-23 15:23:50 -0700327 OutboundPacket outboundPacket = packetService.emittedPacket;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700328 byte[] outPacketData = outboundPacket.data().array();
329 Ethernet eth = Ethernet.deserializer().deserialize(outPacketData, 0, outPacketData.length);
330
331 assertEquals(eth.getEtherType(), Ethernet.TYPE_ARP);
332 ARP arp = (ARP) eth.getPayload();
333 assertArrayEquals(arp.getSenderHardwareAddress(), CLIENT_INTERFACE.mac().toBytes());
334 }
335
Yi Tsenge72fbb52017-08-02 15:03:31 -0700336 private static class MockDefaultDhcpRelayConfig extends DefaultDhcpRelayConfig {
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700337 @Override
338 public boolean isValid() {
339 return true;
340 }
341
342 @Override
Yi Tsenge72fbb52017-08-02 15:03:31 -0700343 public List<DhcpServerConfig> dhcpServerConfigs() {
Yi Tseng4fa05832017-08-17 13:08:31 -0700344 return ImmutableList.of(new MockDhcpServerConfig(null));
Yi Tsenge72fbb52017-08-02 15:03:31 -0700345 }
346 }
347
348 private static class MockDhcpServerConfig extends DhcpServerConfig {
Yi Tseng4fa05832017-08-17 13:08:31 -0700349 Ip4Address relayAgentIp;
350
351 /**
352 * Create mocked version DHCP server config.
353 *
354 * @param relayAgentIp the relay agent Ip config; null if we don't need it
355 */
356 public MockDhcpServerConfig(Ip4Address relayAgentIp) {
357 this.relayAgentIp = relayAgentIp;
358 }
359
360 @Override
361 public Optional<Ip4Address> getRelayAgentIp4() {
362 return Optional.ofNullable(relayAgentIp);
363 }
364
Yi Tsenge72fbb52017-08-02 15:03:31 -0700365 @Override
366 public Optional<ConnectPoint> getDhcpServerConnectPoint() {
367 return Optional.of(SERVER_CONNECT_POINT);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700368 }
369
Yi Tsenge72fbb52017-08-02 15:03:31 -0700370 @Override
371 public Optional<Ip4Address> getDhcpServerIp4() {
372 return Optional.of(SERVER_IP);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700373 }
374 }
375
376 private class MockHostStore extends HostStoreAdapter {
377
378 private final Map<HostId, HostDescription> hosts = Maps.newHashMap();
379
380 @Override
381 public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
382 HostDescription hostDescription,
383 boolean replaceIps) {
384 hosts.put(hostId, hostDescription);
385
386 // not necessary to return host event in this test.
387 return null;
388 }
389
390 public HostDescription hostDesc(HostId hostId) {
391 return hosts.get(hostId);
392 }
393
394 @Override
395 public Iterable<Host> getHosts() {
396 return hosts.values().stream()
397 .map(hd -> new DefaultHost(DhcpRelayManager.PROVIDER_ID,
398 HostId.hostId(hd.hwAddress(), hd.vlan()),
399 hd.hwAddress(),
400 hd.vlan(), hd.locations(),
401 hd.ipAddress(), false))
402 .collect(Collectors.toList());
403 }
404 }
405
406 private class MockRouteStore extends RouteStoreAdapter {
407 private List<Route> routes = Lists.newArrayList();
408
409 @Override
410 public void updateRoute(Route route) {
411 routes.add(route);
412 }
413 }
414
415 private class MockInterfaceService extends InterfaceServiceAdapter {
416
417 @Override
418 public Set<Interface> getInterfaces() {
419 return INTERFACES;
420 }
421
422 @Override
423 public Set<Interface> getInterfacesByIp(IpAddress ip) {
424 return INTERFACES.stream()
425 .filter(iface -> {
426 return iface.ipAddressesList().stream()
427 .anyMatch(ifaceIp -> ifaceIp.ipAddress().equals(ip));
428 })
429 .collect(Collectors.toSet());
430 }
431
432 @Override
433 public Set<Interface> getInterfacesByPort(ConnectPoint port) {
434 return INTERFACES.stream()
435 .filter(iface -> iface.connectPoint().equals(port))
436 .collect(Collectors.toSet());
437 }
438 }
439
440 private class MockDhcpRelayStore implements DhcpRelayStore {
441 StoreDelegate<DhcpRelayStoreEvent> delegate;
442 private Map<HostId, DhcpRecord> records = Maps.newHashMap();
443
444 @Override
445 public void updateDhcpRecord(HostId hostId, DhcpRecord dhcpRecord) {
446 records.put(hostId, dhcpRecord);
447 DhcpRelayStoreEvent event = new DhcpRelayStoreEvent(DhcpRelayStoreEvent.Type.UPDATED,
448 dhcpRecord);
449 if (delegate != null) {
450 delegate.notify(event);
451 }
452 }
453
454 @Override
455 public Optional<DhcpRecord> getDhcpRecord(HostId hostId) {
456 return Optional.ofNullable(records.get(hostId));
457 }
458
459 @Override
460 public Collection<DhcpRecord> getDhcpRecords() {
461 return records.values();
462 }
463
464 @Override
465 public Optional<DhcpRecord> removeDhcpRecord(HostId hostId) {
466 DhcpRecord dhcpRecord = records.remove(hostId);
467 if (dhcpRecord != null) {
468 DhcpRelayStoreEvent event = new DhcpRelayStoreEvent(DhcpRelayStoreEvent.Type.REMOVED,
469 dhcpRecord);
470 if (delegate != null) {
471 delegate.notify(event);
472 }
473 }
474 return Optional.ofNullable(dhcpRecord);
475 }
476
477 @Override
478 public void setDelegate(StoreDelegate<DhcpRelayStoreEvent> delegate) {
479 this.delegate = delegate;
480 }
481
482 @Override
483 public void unsetDelegate(StoreDelegate<DhcpRelayStoreEvent> delegate) {
484 this.delegate = null;
485 }
486
487 @Override
488 public boolean hasDelegate() {
489 return this.delegate != null;
490 }
491 }
492
493 private class MockPacketService extends PacketServiceAdapter {
494 Set<PacketProcessor> packetProcessors = Sets.newHashSet();
Ray Milkeybd52a052017-08-23 15:23:50 -0700495 OutboundPacket emittedPacket;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700496
497 @Override
498 public void addProcessor(PacketProcessor processor, int priority) {
499 packetProcessors.add(processor);
500 }
501
502 public void processPacket(PacketContext packetContext) {
503 packetProcessors.forEach(p -> p.process(packetContext));
504 }
505
506 @Override
507 public void emit(OutboundPacket packet) {
Ray Milkeybd52a052017-08-23 15:23:50 -0700508 this.emittedPacket = packet;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700509 }
510 }
511
512
513
514 /**
515 * Generates DHCP REQUEST packet.
516 */
517 private class TestDhcpRequestPacketContext extends PacketContextAdapter {
518
519
520 private InboundPacket inPacket;
521
522 public TestDhcpRequestPacketContext(MacAddress clientMac, VlanId vlanId,
523 ConnectPoint clientCp,
524 Ip4Address clientGwAddr,
525 boolean withNonOnosRelayInfo) {
526 super(0, null, null, false);
527 byte[] dhcpMsgType = new byte[1];
528 dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPREQUEST.getValue();
529
530 DhcpOption dhcpOption = new DhcpOption();
531 dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
532 dhcpOption.setData(dhcpMsgType);
533 dhcpOption.setLength((byte) 1);
534 DhcpOption endOption = new DhcpOption();
535 endOption.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
536
537 DHCP dhcp = new DHCP();
538 dhcp.setHardwareType(DHCP.HWTYPE_ETHERNET);
539 dhcp.setHardwareAddressLength((byte) 6);
540 dhcp.setClientHardwareAddress(clientMac.toBytes());
541 if (withNonOnosRelayInfo) {
542 DhcpRelayAgentOption relayOption = new DhcpRelayAgentOption();
543 DhcpOption circuitIdOption = new DhcpOption();
544 CircuitId circuitId = new CircuitId("Custom option", VlanId.NONE);
545 byte[] cid = circuitId.serialize();
546 circuitIdOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
547 circuitIdOption.setLength((byte) cid.length);
548 circuitIdOption.setData(cid);
549 relayOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
550 relayOption.addSubOption(circuitIdOption);
551 dhcp.setOptions(ImmutableList.of(dhcpOption, relayOption, endOption));
552 dhcp.setGatewayIPAddress(OUTER_RELAY_IP.getIp4Address().toInt());
553 } else {
554 dhcp.setOptions(ImmutableList.of(dhcpOption, endOption));
555 }
556
557
558 UDP udp = new UDP();
559 udp.setPayload(dhcp);
560 udp.setSourcePort(UDP.DHCP_CLIENT_PORT);
561 udp.setDestinationPort(UDP.DHCP_SERVER_PORT);
562
563 IPv4 ipv4 = new IPv4();
564 ipv4.setPayload(udp);
565 ipv4.setDestinationAddress(SERVER_IP.toInt());
566 ipv4.setSourceAddress(clientGwAddr.toInt());
567
568 Ethernet eth = new Ethernet();
569 if (withNonOnosRelayInfo) {
570 eth.setEtherType(Ethernet.TYPE_IPV4)
571 .setVlanID(vlanId.toShort())
572 .setSourceMACAddress(OUTER_RELAY_MAC)
573 .setDestinationMACAddress(MacAddress.BROADCAST)
574 .setPayload(ipv4);
575 } else {
576 eth.setEtherType(Ethernet.TYPE_IPV4)
577 .setVlanID(vlanId.toShort())
578 .setSourceMACAddress(clientMac)
579 .setDestinationMACAddress(MacAddress.BROADCAST)
580 .setPayload(ipv4);
581 }
582
583 this.inPacket = new DefaultInboundPacket(clientCp, eth,
584 ByteBuffer.wrap(eth.serialize()));
585 }
586
587 @Override
588 public InboundPacket inPacket() {
589 return this.inPacket;
590 }
591 }
592
593 /**
594 * Generates DHCP ACK packet.
595 */
596 private class TestDhcpAckPacketContext extends PacketContextAdapter {
597 private InboundPacket inPacket;
598
599 public TestDhcpAckPacketContext(ConnectPoint clientCp, MacAddress clientMac,
600 VlanId clientVlan, Ip4Address clientGwAddr,
601 boolean withNonOnosRelayInfo) {
602 super(0, null, null, false);
603
604 byte[] dhcpMsgType = new byte[1];
605 dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPACK.getValue();
606
607 DhcpOption dhcpOption = new DhcpOption();
608 dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
609 dhcpOption.setData(dhcpMsgType);
610 dhcpOption.setLength((byte) 1);
611
612 DhcpOption endOption = new DhcpOption();
613 endOption.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
614
615 DHCP dhcp = new DHCP();
616 if (withNonOnosRelayInfo) {
617 DhcpRelayAgentOption relayOption = new DhcpRelayAgentOption();
618 DhcpOption circuitIdOption = new DhcpOption();
Yi Tseng2cf59912017-08-24 14:47:34 -0700619 String circuitId = NON_ONOS_CID;
620 byte[] cid = circuitId.getBytes(Charsets.US_ASCII);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700621 circuitIdOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
622 circuitIdOption.setLength((byte) cid.length);
623 circuitIdOption.setData(cid);
624 relayOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
625 relayOption.addSubOption(circuitIdOption);
626 dhcp.setOptions(ImmutableList.of(dhcpOption, relayOption, endOption));
627 dhcp.setGatewayIPAddress(OUTER_RELAY_IP.getIp4Address().toInt());
628 } else {
629 CircuitId cid = new CircuitId(clientCp.toString(), clientVlan);
630 byte[] circuitId = cid.serialize();
631 DhcpOption circuitIdSubOption = new DhcpOption();
632 circuitIdSubOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
633 circuitIdSubOption.setData(circuitId);
634 circuitIdSubOption.setLength((byte) circuitId.length);
635
636 DhcpRelayAgentOption relayInfoOption = new DhcpRelayAgentOption();
637 relayInfoOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
638 relayInfoOption.addSubOption(circuitIdSubOption);
639 dhcp.setOptions(ImmutableList.of(dhcpOption, relayInfoOption, endOption));
640 dhcp.setGatewayIPAddress(clientGwAddr.toInt());
641 }
642 dhcp.setHardwareType(DHCP.HWTYPE_ETHERNET);
643 dhcp.setHardwareAddressLength((byte) 6);
644 dhcp.setClientHardwareAddress(clientMac.toBytes());
645 dhcp.setYourIPAddress(IP_FOR_CLIENT.toInt());
646
647 UDP udp = new UDP();
648 udp.setPayload(dhcp);
649 udp.setSourcePort(UDP.DHCP_SERVER_PORT);
650 udp.setDestinationPort(UDP.DHCP_CLIENT_PORT);
651 IPv4 ipv4 = new IPv4();
652 ipv4.setPayload(udp);
653 ipv4.setDestinationAddress(IP_FOR_CLIENT.toString());
654 ipv4.setSourceAddress(SERVER_IP.toString());
655 Ethernet eth = new Ethernet();
656 if (withNonOnosRelayInfo) {
657 eth.setEtherType(Ethernet.TYPE_IPV4)
658 .setVlanID(SERVER_VLAN.toShort())
659 .setSourceMACAddress(SERVER_MAC)
660 .setDestinationMACAddress(OUTER_RELAY_MAC)
661 .setPayload(ipv4);
662 } else {
663 eth.setEtherType(Ethernet.TYPE_IPV4)
664 .setVlanID(SERVER_VLAN.toShort())
665 .setSourceMACAddress(SERVER_MAC)
666 .setDestinationMACAddress(CLIENT_MAC)
667 .setPayload(ipv4);
668 }
669
670 this.inPacket = new DefaultInboundPacket(SERVER_CONNECT_POINT, eth,
671 ByteBuffer.wrap(eth.serialize()));
672
673 }
674
675 @Override
676 public InboundPacket inPacket() {
677 return this.inPacket;
678 }
679 }
680
681 private class TestArpRequestPacketContext extends PacketContextAdapter {
682 private InboundPacket inPacket;
683
684 public TestArpRequestPacketContext(Interface fromInterface) {
685 super(0, null, null, false);
686 ARP arp = new ARP();
687 arp.setOpCode(ARP.OP_REQUEST);
688
689 IpAddress targetIp = fromInterface.ipAddressesList().get(0).ipAddress();
690 arp.setTargetProtocolAddress(targetIp.toOctets());
691 arp.setTargetHardwareAddress(MacAddress.BROADCAST.toBytes());
692 arp.setSenderHardwareAddress(MacAddress.NONE.toBytes());
693 arp.setSenderProtocolAddress(Ip4Address.valueOf(0).toOctets());
694 arp.setHardwareAddressLength((byte) MacAddress.MAC_ADDRESS_LENGTH);
695 Ethernet eth = new Ethernet();
696 eth.setEtherType(Ethernet.TYPE_ARP);
697 eth.setSourceMACAddress(MacAddress.NONE);
698 eth.setDestinationMACAddress(MacAddress.BROADCAST);
699 eth.setVlanID(fromInterface.vlan().toShort());
700 eth.setPayload(arp);
701
702 this.inPacket = new DefaultInboundPacket(fromInterface.connectPoint(), eth,
703 ByteBuffer.wrap(eth.serialize()));
704 }
705
706 @Override
707 public InboundPacket inPacket() {
708 return this.inPacket;
709 }
710 }
711}