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