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