blob: fe2cbffdd73eef768a32671d80ddaadc45a18c68 [file] [log] [blame]
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001/*
2 * Copyright 2017-present Open Networking Laboratory
3 *
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();
189
190 manager.hostStore = mockHostStore;
191 manager.routeStore = mockRouteStore;
192 manager.dhcpRelayStore = mockDhcpRelayStore;
193
194 manager.interfaceService = new MockInterfaceService();
195
196 // properties
197 Dictionary<String, Object> dictionary = createNiceMock(Dictionary.class);
198 expect(dictionary.get("arpEnabled")).andReturn(true).anyTimes();
199 ComponentContext context = createNiceMock(ComponentContext.class);
200 expect(context.getProperties()).andReturn(dictionary).anyTimes();
201
202 EasyMock.replay(manager.cfgService, manager.coreService, manager.hostService,
203 manager.compCfgService, dictionary, context);
204 manager.activate(context);
205 }
206
207 @After
208 public void tearDown() {
209 manager.deactivate();
210 }
211
212 /**
213 * Relay a DHCP packet without option 82.
214 * Should add new host to host store after dhcp ack.
215 */
216 @Test
217 public void relayDhcpWithoutAgentInfo() {
218 // send request
219 packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT_MAC,
220 CLIENT_VLAN,
221 CLIENT_CP,
222 INTERFACE_IP.ipAddress().getIp4Address(),
223 false));
224
225 Set<Host> hosts = ImmutableSet.copyOf(mockHostStore.getHosts());
226 assertEquals(0, hosts.size());
227 assertEquals(0, mockRouteStore.routes.size());
228
229 // send ack
230 packetService.processPacket(new TestDhcpAckPacketContext(CLIENT_CP, CLIENT_MAC,
231 CLIENT_VLAN, INTERFACE_IP.ipAddress().getIp4Address(),
232 false));
233 hosts = ImmutableSet.copyOf(mockHostStore.getHosts());
234 assertEquals(1, hosts.size());
235 assertEquals(0, mockRouteStore.routes.size());
236
237 Host host = hosts.iterator().next();
238 assertEquals(CLIENT_MAC, host.mac());
239 assertEquals(CLIENT_VLAN, host.vlan());
240 assertEquals(CLIENT_CP.deviceId(), host.location().elementId());
241 assertEquals(CLIENT_CP.port(), host.location().port());
242 assertEquals(1, host.ipAddresses().size());
243 assertEquals(IP_FOR_CLIENT, host.ipAddresses().iterator().next());
244 assertEquals(HostId.hostId(CLIENT_MAC, CLIENT_VLAN), host.id());
245 }
246
247 /**
248 * Relay a DHCP packet with option 82 (Indirectly connected host).
249 */
250 @Test
251 public void relayDhcpWithAgentInfo() {
252 // Assume outer dhcp relay agent exists in store already
253 // send request
254 packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT2_MAC,
255 CLIENT2_VLAN,
256 CLIENT2_CP,
257 INTERFACE_IP.ipAddress().getIp4Address(),
258 true));
259
260 Set<Host> hosts = ImmutableSet.copyOf(mockHostStore.getHosts());
261 assertEquals(0, hosts.size());
262 assertEquals(0, mockRouteStore.routes.size());
263
264 // send ack
265 packetService.processPacket(new TestDhcpAckPacketContext(CLIENT2_CP,
266 CLIENT2_MAC,
267 CLIENT2_VLAN,
268 INTERFACE_IP.ipAddress().getIp4Address(),
269 true));
270
271 hosts = ImmutableSet.copyOf(mockHostStore.getHosts());
272 assertEquals(0, hosts.size());
273 assertEquals(1, mockRouteStore.routes.size());
274
275 Route route = mockRouteStore.routes.get(0);
276 assertEquals(OUTER_RELAY_IP, route.nextHop());
277 assertEquals(IP_FOR_CLIENT.toIpPrefix(), route.prefix());
278 assertEquals(Route.Source.STATIC, route.source());
279 }
280
281 @Test
282 public void testArpRequest() throws Exception {
283 packetService.processPacket(new TestArpRequestPacketContext(CLIENT_INTERFACE));
284 OutboundPacket outboundPacket = packetService.emitedPacket;
285 byte[] outPacketData = outboundPacket.data().array();
286 Ethernet eth = Ethernet.deserializer().deserialize(outPacketData, 0, outPacketData.length);
287
288 assertEquals(eth.getEtherType(), Ethernet.TYPE_ARP);
289 ARP arp = (ARP) eth.getPayload();
290 assertArrayEquals(arp.getSenderHardwareAddress(), CLIENT_INTERFACE.mac().toBytes());
291 }
292
293 private static class MockDhcpRelayConfig extends DhcpRelayConfig {
294 @Override
295 public boolean isValid() {
296 return true;
297 }
298
299 @Override
300 public ConnectPoint getDhcpServerConnectPoint() {
301 return SERVER_CONNECT_POINT;
302 }
303
304 public Ip4Address getDhcpServerIp() {
305 return SERVER_IP;
306 }
307
308 public Ip4Address getDhcpGatewayIp() {
309 return null;
310 }
311 }
312
313 private class MockHostStore extends HostStoreAdapter {
314
315 private final Map<HostId, HostDescription> hosts = Maps.newHashMap();
316
317 @Override
318 public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
319 HostDescription hostDescription,
320 boolean replaceIps) {
321 hosts.put(hostId, hostDescription);
322
323 // not necessary to return host event in this test.
324 return null;
325 }
326
327 public HostDescription hostDesc(HostId hostId) {
328 return hosts.get(hostId);
329 }
330
331 @Override
332 public Iterable<Host> getHosts() {
333 return hosts.values().stream()
334 .map(hd -> new DefaultHost(DhcpRelayManager.PROVIDER_ID,
335 HostId.hostId(hd.hwAddress(), hd.vlan()),
336 hd.hwAddress(),
337 hd.vlan(), hd.locations(),
338 hd.ipAddress(), false))
339 .collect(Collectors.toList());
340 }
341 }
342
343 private class MockRouteStore extends RouteStoreAdapter {
344 private List<Route> routes = Lists.newArrayList();
345
346 @Override
347 public void updateRoute(Route route) {
348 routes.add(route);
349 }
350 }
351
352 private class MockInterfaceService extends InterfaceServiceAdapter {
353
354 @Override
355 public Set<Interface> getInterfaces() {
356 return INTERFACES;
357 }
358
359 @Override
360 public Set<Interface> getInterfacesByIp(IpAddress ip) {
361 return INTERFACES.stream()
362 .filter(iface -> {
363 return iface.ipAddressesList().stream()
364 .anyMatch(ifaceIp -> ifaceIp.ipAddress().equals(ip));
365 })
366 .collect(Collectors.toSet());
367 }
368
369 @Override
370 public Set<Interface> getInterfacesByPort(ConnectPoint port) {
371 return INTERFACES.stream()
372 .filter(iface -> iface.connectPoint().equals(port))
373 .collect(Collectors.toSet());
374 }
375 }
376
377 private class MockDhcpRelayStore implements DhcpRelayStore {
378 StoreDelegate<DhcpRelayStoreEvent> delegate;
379 private Map<HostId, DhcpRecord> records = Maps.newHashMap();
380
381 @Override
382 public void updateDhcpRecord(HostId hostId, DhcpRecord dhcpRecord) {
383 records.put(hostId, dhcpRecord);
384 DhcpRelayStoreEvent event = new DhcpRelayStoreEvent(DhcpRelayStoreEvent.Type.UPDATED,
385 dhcpRecord);
386 if (delegate != null) {
387 delegate.notify(event);
388 }
389 }
390
391 @Override
392 public Optional<DhcpRecord> getDhcpRecord(HostId hostId) {
393 return Optional.ofNullable(records.get(hostId));
394 }
395
396 @Override
397 public Collection<DhcpRecord> getDhcpRecords() {
398 return records.values();
399 }
400
401 @Override
402 public Optional<DhcpRecord> removeDhcpRecord(HostId hostId) {
403 DhcpRecord dhcpRecord = records.remove(hostId);
404 if (dhcpRecord != null) {
405 DhcpRelayStoreEvent event = new DhcpRelayStoreEvent(DhcpRelayStoreEvent.Type.REMOVED,
406 dhcpRecord);
407 if (delegate != null) {
408 delegate.notify(event);
409 }
410 }
411 return Optional.ofNullable(dhcpRecord);
412 }
413
414 @Override
415 public void setDelegate(StoreDelegate<DhcpRelayStoreEvent> delegate) {
416 this.delegate = delegate;
417 }
418
419 @Override
420 public void unsetDelegate(StoreDelegate<DhcpRelayStoreEvent> delegate) {
421 this.delegate = null;
422 }
423
424 @Override
425 public boolean hasDelegate() {
426 return this.delegate != null;
427 }
428 }
429
430 private class MockPacketService extends PacketServiceAdapter {
431 Set<PacketProcessor> packetProcessors = Sets.newHashSet();
432 OutboundPacket emitedPacket;
433
434 @Override
435 public void addProcessor(PacketProcessor processor, int priority) {
436 packetProcessors.add(processor);
437 }
438
439 public void processPacket(PacketContext packetContext) {
440 packetProcessors.forEach(p -> p.process(packetContext));
441 }
442
443 @Override
444 public void emit(OutboundPacket packet) {
445 this.emitedPacket = packet;
446 }
447 }
448
449
450
451 /**
452 * Generates DHCP REQUEST packet.
453 */
454 private class TestDhcpRequestPacketContext extends PacketContextAdapter {
455
456
457 private InboundPacket inPacket;
458
459 public TestDhcpRequestPacketContext(MacAddress clientMac, VlanId vlanId,
460 ConnectPoint clientCp,
461 Ip4Address clientGwAddr,
462 boolean withNonOnosRelayInfo) {
463 super(0, null, null, false);
464 byte[] dhcpMsgType = new byte[1];
465 dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPREQUEST.getValue();
466
467 DhcpOption dhcpOption = new DhcpOption();
468 dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
469 dhcpOption.setData(dhcpMsgType);
470 dhcpOption.setLength((byte) 1);
471 DhcpOption endOption = new DhcpOption();
472 endOption.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
473
474 DHCP dhcp = new DHCP();
475 dhcp.setHardwareType(DHCP.HWTYPE_ETHERNET);
476 dhcp.setHardwareAddressLength((byte) 6);
477 dhcp.setClientHardwareAddress(clientMac.toBytes());
478 if (withNonOnosRelayInfo) {
479 DhcpRelayAgentOption relayOption = new DhcpRelayAgentOption();
480 DhcpOption circuitIdOption = new DhcpOption();
481 CircuitId circuitId = new CircuitId("Custom option", VlanId.NONE);
482 byte[] cid = circuitId.serialize();
483 circuitIdOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
484 circuitIdOption.setLength((byte) cid.length);
485 circuitIdOption.setData(cid);
486 relayOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
487 relayOption.addSubOption(circuitIdOption);
488 dhcp.setOptions(ImmutableList.of(dhcpOption, relayOption, endOption));
489 dhcp.setGatewayIPAddress(OUTER_RELAY_IP.getIp4Address().toInt());
490 } else {
491 dhcp.setOptions(ImmutableList.of(dhcpOption, endOption));
492 }
493
494
495 UDP udp = new UDP();
496 udp.setPayload(dhcp);
497 udp.setSourcePort(UDP.DHCP_CLIENT_PORT);
498 udp.setDestinationPort(UDP.DHCP_SERVER_PORT);
499
500 IPv4 ipv4 = new IPv4();
501 ipv4.setPayload(udp);
502 ipv4.setDestinationAddress(SERVER_IP.toInt());
503 ipv4.setSourceAddress(clientGwAddr.toInt());
504
505 Ethernet eth = new Ethernet();
506 if (withNonOnosRelayInfo) {
507 eth.setEtherType(Ethernet.TYPE_IPV4)
508 .setVlanID(vlanId.toShort())
509 .setSourceMACAddress(OUTER_RELAY_MAC)
510 .setDestinationMACAddress(MacAddress.BROADCAST)
511 .setPayload(ipv4);
512 } else {
513 eth.setEtherType(Ethernet.TYPE_IPV4)
514 .setVlanID(vlanId.toShort())
515 .setSourceMACAddress(clientMac)
516 .setDestinationMACAddress(MacAddress.BROADCAST)
517 .setPayload(ipv4);
518 }
519
520 this.inPacket = new DefaultInboundPacket(clientCp, eth,
521 ByteBuffer.wrap(eth.serialize()));
522 }
523
524 @Override
525 public InboundPacket inPacket() {
526 return this.inPacket;
527 }
528 }
529
530 /**
531 * Generates DHCP ACK packet.
532 */
533 private class TestDhcpAckPacketContext extends PacketContextAdapter {
534 private InboundPacket inPacket;
535
536 public TestDhcpAckPacketContext(ConnectPoint clientCp, MacAddress clientMac,
537 VlanId clientVlan, Ip4Address clientGwAddr,
538 boolean withNonOnosRelayInfo) {
539 super(0, null, null, false);
540
541 byte[] dhcpMsgType = new byte[1];
542 dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPACK.getValue();
543
544 DhcpOption dhcpOption = new DhcpOption();
545 dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
546 dhcpOption.setData(dhcpMsgType);
547 dhcpOption.setLength((byte) 1);
548
549 DhcpOption endOption = new DhcpOption();
550 endOption.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
551
552 DHCP dhcp = new DHCP();
553 if (withNonOnosRelayInfo) {
554 DhcpRelayAgentOption relayOption = new DhcpRelayAgentOption();
555 DhcpOption circuitIdOption = new DhcpOption();
556 CircuitId circuitId = new CircuitId("Custom cid", VlanId.NONE);
557 byte[] cid = circuitId.serialize();
558 circuitIdOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
559 circuitIdOption.setLength((byte) cid.length);
560 circuitIdOption.setData(cid);
561 relayOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
562 relayOption.addSubOption(circuitIdOption);
563 dhcp.setOptions(ImmutableList.of(dhcpOption, relayOption, endOption));
564 dhcp.setGatewayIPAddress(OUTER_RELAY_IP.getIp4Address().toInt());
565 } else {
566 CircuitId cid = new CircuitId(clientCp.toString(), clientVlan);
567 byte[] circuitId = cid.serialize();
568 DhcpOption circuitIdSubOption = new DhcpOption();
569 circuitIdSubOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
570 circuitIdSubOption.setData(circuitId);
571 circuitIdSubOption.setLength((byte) circuitId.length);
572
573 DhcpRelayAgentOption relayInfoOption = new DhcpRelayAgentOption();
574 relayInfoOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
575 relayInfoOption.addSubOption(circuitIdSubOption);
576 dhcp.setOptions(ImmutableList.of(dhcpOption, relayInfoOption, endOption));
577 dhcp.setGatewayIPAddress(clientGwAddr.toInt());
578 }
579 dhcp.setHardwareType(DHCP.HWTYPE_ETHERNET);
580 dhcp.setHardwareAddressLength((byte) 6);
581 dhcp.setClientHardwareAddress(clientMac.toBytes());
582 dhcp.setYourIPAddress(IP_FOR_CLIENT.toInt());
583
584 UDP udp = new UDP();
585 udp.setPayload(dhcp);
586 udp.setSourcePort(UDP.DHCP_SERVER_PORT);
587 udp.setDestinationPort(UDP.DHCP_CLIENT_PORT);
588 IPv4 ipv4 = new IPv4();
589 ipv4.setPayload(udp);
590 ipv4.setDestinationAddress(IP_FOR_CLIENT.toString());
591 ipv4.setSourceAddress(SERVER_IP.toString());
592 Ethernet eth = new Ethernet();
593 if (withNonOnosRelayInfo) {
594 eth.setEtherType(Ethernet.TYPE_IPV4)
595 .setVlanID(SERVER_VLAN.toShort())
596 .setSourceMACAddress(SERVER_MAC)
597 .setDestinationMACAddress(OUTER_RELAY_MAC)
598 .setPayload(ipv4);
599 } else {
600 eth.setEtherType(Ethernet.TYPE_IPV4)
601 .setVlanID(SERVER_VLAN.toShort())
602 .setSourceMACAddress(SERVER_MAC)
603 .setDestinationMACAddress(CLIENT_MAC)
604 .setPayload(ipv4);
605 }
606
607 this.inPacket = new DefaultInboundPacket(SERVER_CONNECT_POINT, eth,
608 ByteBuffer.wrap(eth.serialize()));
609
610 }
611
612 @Override
613 public InboundPacket inPacket() {
614 return this.inPacket;
615 }
616 }
617
618 private class TestArpRequestPacketContext extends PacketContextAdapter {
619 private InboundPacket inPacket;
620
621 public TestArpRequestPacketContext(Interface fromInterface) {
622 super(0, null, null, false);
623 ARP arp = new ARP();
624 arp.setOpCode(ARP.OP_REQUEST);
625
626 IpAddress targetIp = fromInterface.ipAddressesList().get(0).ipAddress();
627 arp.setTargetProtocolAddress(targetIp.toOctets());
628 arp.setTargetHardwareAddress(MacAddress.BROADCAST.toBytes());
629 arp.setSenderHardwareAddress(MacAddress.NONE.toBytes());
630 arp.setSenderProtocolAddress(Ip4Address.valueOf(0).toOctets());
631 arp.setHardwareAddressLength((byte) MacAddress.MAC_ADDRESS_LENGTH);
632 Ethernet eth = new Ethernet();
633 eth.setEtherType(Ethernet.TYPE_ARP);
634 eth.setSourceMACAddress(MacAddress.NONE);
635 eth.setDestinationMACAddress(MacAddress.BROADCAST);
636 eth.setVlanID(fromInterface.vlan().toShort());
637 eth.setPayload(arp);
638
639 this.inPacket = new DefaultInboundPacket(fromInterface.connectPoint(), eth,
640 ByteBuffer.wrap(eth.serialize()));
641 }
642
643 @Override
644 public InboundPacket inPacket() {
645 return this.inPacket;
646 }
647 }
648}