blob: 2d553e2733207188e5d1f47ec33bba4c2a0b577f [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
Yi Tseng5479fb82017-09-01 17:24:57 -070018import com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.ObjectMapper;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070020import com.google.common.collect.ImmutableList;
21import com.google.common.collect.ImmutableSet;
22import com.google.common.collect.Lists;
23import com.google.common.collect.Maps;
24import com.google.common.collect.Sets;
Yi Tseng5479fb82017-09-01 17:24:57 -070025import com.google.common.io.Resources;
Yi Tseng2cf59912017-08-24 14:47:34 -070026import org.apache.commons.io.Charsets;
Yi Tseng5479fb82017-09-01 17:24:57 -070027import org.easymock.Capture;
28import org.easymock.CaptureType;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070029import org.easymock.EasyMock;
30import org.junit.After;
31import org.junit.Before;
32import org.junit.Test;
33import org.onlab.packet.ARP;
34import org.onlab.packet.DHCP;
Yi Tseng4fa05832017-08-17 13:08:31 -070035import org.onlab.packet.DeserializationException;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070036import org.onlab.packet.Ethernet;
37import org.onlab.packet.IPv4;
38import org.onlab.packet.Ip4Address;
Kalhee Kim1b5094f2017-09-05 19:05:06 +000039import org.onlab.packet.Ip6Address;
40import org.onlab.packet.IpPrefix;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070041import org.onlab.packet.IpAddress;
42import org.onlab.packet.MacAddress;
43import org.onlab.packet.UDP;
44import org.onlab.packet.VlanId;
45import org.onlab.packet.dhcp.CircuitId;
46import org.onlab.packet.dhcp.DhcpOption;
47import org.onlab.packet.dhcp.DhcpRelayAgentOption;
Kalhee Kim1b5094f2017-09-05 19:05:06 +000048import org.onlab.packet.dhcp.Dhcp6InterfaceIdOption;
49import org.onlab.packet.dhcp.Dhcp6RelayOption;
50import org.onlab.packet.dhcp.Dhcp6IaNaOption;
51import org.onlab.packet.dhcp.Dhcp6IaPdOption;
52import org.onlab.packet.dhcp.Dhcp6IaAddressOption;
53import org.onlab.packet.dhcp.Dhcp6IaPrefixOption;
54import org.onlab.packet.dhcp.Dhcp6Option;
55import org.onosproject.net.ConnectPoint;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070056import org.onosproject.TestApplicationId;
57import org.onosproject.cfg.ComponentConfigService;
58import org.onosproject.core.ApplicationId;
59import org.onosproject.core.CoreService;
Yi Tsenge72fbb52017-08-02 15:03:31 -070060import org.onosproject.dhcprelay.config.DefaultDhcpRelayConfig;
61import org.onosproject.dhcprelay.config.DhcpServerConfig;
Yi Tseng5479fb82017-09-01 17:24:57 -070062import org.onosproject.dhcprelay.config.IgnoreDhcpConfig;
Yi Tsenge72fbb52017-08-02 15:03:31 -070063import org.onosproject.dhcprelay.config.IndirectDhcpRelayConfig;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070064import org.onosproject.dhcprelay.store.DhcpRecord;
65import org.onosproject.dhcprelay.store.DhcpRelayStore;
66import org.onosproject.dhcprelay.store.DhcpRelayStoreEvent;
Yi Tseng76365d82017-09-12 15:55:17 -070067import org.onosproject.net.Device;
Yi Tseng5479fb82017-09-01 17:24:57 -070068import org.onosproject.net.DeviceId;
Yi Tseng76365d82017-09-12 15:55:17 -070069import org.onosproject.net.behaviour.Pipeliner;
70import org.onosproject.net.device.DeviceEvent;
71import org.onosproject.net.device.DeviceService;
Yi Tseng5479fb82017-09-01 17:24:57 -070072import org.onosproject.net.flow.DefaultTrafficSelector;
73import org.onosproject.net.flow.DefaultTrafficTreatment;
74import org.onosproject.net.flow.TrafficSelector;
75import org.onosproject.net.flow.TrafficTreatment;
76import org.onosproject.net.flowobjective.FlowObjectiveService;
77import org.onosproject.net.flowobjective.ForwardingObjective;
78import org.onosproject.net.flowobjective.Objective;
Yi Tseng4b013202017-09-08 17:22:51 -070079import org.onosproject.net.host.HostProviderService;
Ray Milkeyfacf2862017-08-03 11:58:29 -070080import org.onosproject.net.intf.Interface;
81import org.onosproject.net.intf.InterfaceServiceAdapter;
Yi Tseng5479fb82017-09-01 17:24:57 -070082import org.onosproject.net.packet.PacketPriority;
Ray Milkey69ec8712017-08-08 13:00:43 -070083import org.onosproject.routeservice.Route;
84import org.onosproject.routeservice.RouteStoreAdapter;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070085import org.onosproject.net.DefaultHost;
86import org.onosproject.net.Host;
87import org.onosproject.net.HostId;
88import org.onosproject.net.HostLocation;
89import org.onosproject.net.config.NetworkConfigRegistry;
90import org.onosproject.net.host.HostDescription;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070091import org.onosproject.net.host.HostService;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070092import org.onosproject.net.host.InterfaceIpAddress;
93import org.onosproject.net.packet.DefaultInboundPacket;
94import org.onosproject.net.packet.InboundPacket;
95import org.onosproject.net.packet.OutboundPacket;
96import org.onosproject.net.packet.PacketContext;
97import org.onosproject.net.packet.PacketContextAdapter;
98import org.onosproject.net.packet.PacketProcessor;
99import org.onosproject.net.packet.PacketServiceAdapter;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700100import org.onosproject.store.StoreDelegate;
101import org.osgi.service.component.ComponentContext;
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000102import org.onlab.packet.DHCP6;
103import org.onlab.packet.IPv6;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700104
Yi Tseng76365d82017-09-12 15:55:17 -0700105import java.io.IOException;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700106import java.nio.ByteBuffer;
107import java.util.Collection;
108import java.util.Dictionary;
109import java.util.List;
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000110import java.util.ArrayList;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700111import java.util.Map;
112import java.util.Optional;
113import java.util.Set;
114import java.util.stream.Collectors;
115
116import static org.easymock.EasyMock.*;
117import static org.junit.Assert.*;
Yi Tseng5479fb82017-09-01 17:24:57 -0700118import static org.onosproject.dhcprelay.DhcpRelayManager.DHCP_RELAY_APP;
Yi Tseng76365d82017-09-12 15:55:17 -0700119import static org.onosproject.dhcprelay.DhcpRelayManager.DHCP_SELECTORS;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700120
121public class DhcpRelayManagerTest {
Yi Tseng5479fb82017-09-01 17:24:57 -0700122 private static final String CONFIG_FILE_PATH = "dhcp-relay.json";
123 private static final DeviceId DEV_1_ID = DeviceId.deviceId("of:0000000000000001");
124 private static final DeviceId DEV_2_ID = DeviceId.deviceId("of:0000000000000002");
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700125 // Ip address for interfaces
126 private static final InterfaceIpAddress INTERFACE_IP = InterfaceIpAddress.valueOf("10.0.3.254/32");
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000127 private static final InterfaceIpAddress INTERFACE_IP_V6 = InterfaceIpAddress.valueOf("2001:db8:1::254/128");
128 private static final List<InterfaceIpAddress> INTERFACE_IPS = ImmutableList.of(INTERFACE_IP, INTERFACE_IP_V6);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700129
130 // DHCP client (will send without option 82)
131 private static final Ip4Address IP_FOR_CLIENT = Ip4Address.valueOf("10.0.0.1");
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000132 private static final Ip6Address IP_FOR_CLIENT_V6 = Ip6Address.valueOf("2001:db8:1::110");
133 private static final IpPrefix PREFIX_FOR_CLIENT_V6 = IpPrefix.valueOf("2001:db8:10::/56");
134 private static final IpPrefix PREFIX_FOR_ZERO = IpPrefix.valueOf("::/0");
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700135 private static final MacAddress CLIENT_MAC = MacAddress.valueOf("00:00:00:00:00:01");
136 private static final VlanId CLIENT_VLAN = VlanId.vlanId("100");
137 private static final ConnectPoint CLIENT_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
138 private static final MacAddress CLIENT_IFACE_MAC = MacAddress.valueOf("00:00:00:00:11:01");
Yi Tseng4b013202017-09-08 17:22:51 -0700139 private static final HostLocation CLIENT_LOCATION = new HostLocation(CLIENT_CP, 0);
140 private static final HostId CLIENT_HOST_ID = HostId.hostId(CLIENT_MAC, CLIENT_VLAN);
141 private static final Ip6Address CLIENT_LL_IP_V6 = Ip6Address.valueOf("fe80::200:00ff:fe00:0001");
Charles Chan75edab72017-09-12 17:09:32 -0700142 private static final Host EXISTS_HOST = new DefaultHost(Dhcp4HandlerImpl.PROVIDER_ID,
Yi Tseng4b013202017-09-08 17:22:51 -0700143 CLIENT_HOST_ID, CLIENT_MAC, CLIENT_VLAN,
144 CLIENT_LOCATION, ImmutableSet.of(CLIENT_LL_IP_V6));
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700145 private static final Interface CLIENT_INTERFACE = new Interface("C1",
146 CLIENT_CP,
147 INTERFACE_IPS,
148 CLIENT_IFACE_MAC,
149 CLIENT_VLAN);
150
Yi Tseng4b013202017-09-08 17:22:51 -0700151 // Dual homing test
152 private static final ConnectPoint CLIENT_DH_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/3");
153 private static final HostLocation CLIENT_DH_LOCATION = new HostLocation(CLIENT_DH_CP, 0);
154 private static final Interface CLIENT_DH_INTERFACE = new Interface("C1-DH",
155 CLIENT_DH_CP,
156 INTERFACE_IPS,
157 CLIENT_IFACE_MAC,
158 CLIENT_VLAN);
159
160
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700161 // DHCP client 2 (will send with option 82, so the vlan should equals to vlan from server)
162 private static final MacAddress CLIENT2_MAC = MacAddress.valueOf("00:00:00:00:00:01");
163 private static final VlanId CLIENT2_VLAN = VlanId.NONE;
164 private static final ConnectPoint CLIENT2_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
165 private static final MacAddress CLIENT2_IFACE_MAC = MacAddress.valueOf("00:00:00:00:11:01");
166 private static final Interface CLIENT2_INTERFACE = new Interface("C2",
167 CLIENT2_CP,
168 INTERFACE_IPS,
169 CLIENT2_IFACE_MAC,
170 CLIENT2_VLAN);
171
172 // Outer relay information
173 private static final Ip4Address OUTER_RELAY_IP = Ip4Address.valueOf("10.0.5.253");
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000174 private static final Ip6Address OUTER_RELAY_IP_V6 = Ip6Address.valueOf("2001:db8:1::4");
175 private static final Set<IpAddress> OUTER_RELAY_IPS = ImmutableSet.of(OUTER_RELAY_IP, OUTER_RELAY_IP_V6);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700176 private static final MacAddress OUTER_RELAY_MAC = MacAddress.valueOf("00:01:02:03:04:05");
177 private static final VlanId OUTER_RELAY_VLAN = VlanId.NONE;
178 private static final ConnectPoint OUTER_RELAY_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
179 private static final HostLocation OUTER_REPLAY_HL = new HostLocation(OUTER_RELAY_CP, 0);
180 private static final HostId OUTER_RELAY_HOST_ID = HostId.hostId(OUTER_RELAY_MAC, OUTER_RELAY_VLAN);
Charles Chan75edab72017-09-12 17:09:32 -0700181 private static final Host OUTER_RELAY_HOST = new DefaultHost(Dhcp4HandlerImpl.PROVIDER_ID,
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700182 OUTER_RELAY_HOST_ID,
183 OUTER_RELAY_MAC,
184 OUTER_RELAY_VLAN,
185 OUTER_REPLAY_HL,
186 OUTER_RELAY_IPS);
187
188 // DHCP Server
189 private static final MacAddress SERVER_MAC = MacAddress.valueOf("00:00:00:00:00:01");
190 private static final VlanId SERVER_VLAN = VlanId.NONE;
191 private static final ConnectPoint SERVER_CONNECT_POINT =
192 ConnectPoint.deviceConnectPoint("of:0000000000000001/5");
193 private static final HostLocation SERVER_LOCATION =
194 new HostLocation(SERVER_CONNECT_POINT, 0);
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000195 private static final Ip4Address GATEWAY_IP = Ip4Address.valueOf("10.0.5.253");
196 private static final Ip6Address GATEWAY_IP_V6 = Ip6Address.valueOf("2000::105:253");
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700197 private static final Ip4Address SERVER_IP = Ip4Address.valueOf("10.0.3.253");
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000198 private static final Ip6Address SERVER_IP_V6 = Ip6Address.valueOf("2000::103:253");
199 private static final Ip6Address SERVER_IP_V6_MCAST = Ip6Address.valueOf("ff02::1:2");
200 private static final Set<IpAddress> DHCP_SERVER_IPS = ImmutableSet.of(SERVER_IP, SERVER_IP_V6);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700201 private static final HostId SERVER_HOST_ID = HostId.hostId(SERVER_MAC, SERVER_VLAN);
Charles Chan75edab72017-09-12 17:09:32 -0700202 private static final Host SERVER_HOST = new DefaultHost(Dhcp4HandlerImpl.PROVIDER_ID,
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700203 SERVER_HOST_ID,
204 SERVER_MAC,
205 SERVER_VLAN,
206 SERVER_LOCATION,
207 DHCP_SERVER_IPS);
208 private static final MacAddress SERVER_IFACE_MAC = MacAddress.valueOf("00:00:00:00:00:01");
209 private static final Interface SERVER_INTERFACE = new Interface("SERVER",
210 SERVER_CONNECT_POINT,
211 INTERFACE_IPS,
212 SERVER_IFACE_MAC,
213 SERVER_VLAN);
214
Yi Tseng4fa05832017-08-17 13:08:31 -0700215 // Relay agent config
216 private static final Ip4Address RELAY_AGENT_IP = Ip4Address.valueOf("10.0.4.254");
217
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700218 // Components
219 private static final ApplicationId APP_ID = TestApplicationId.create(DhcpRelayManager.DHCP_RELAY_APP);
Yi Tsenge72fbb52017-08-02 15:03:31 -0700220 private static final DefaultDhcpRelayConfig CONFIG = new MockDefaultDhcpRelayConfig();
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000221 private static final IndirectDhcpRelayConfig CONFIG_INDIRECT = new MockIndirectDhcpRelayConfig();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700222 private static final Set<Interface> INTERFACES = ImmutableSet.of(
223 CLIENT_INTERFACE,
224 CLIENT2_INTERFACE,
Yi Tseng4b013202017-09-08 17:22:51 -0700225 SERVER_INTERFACE,
226 CLIENT_DH_INTERFACE
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700227 );
Yi Tseng2cf59912017-08-24 14:47:34 -0700228 private static final String NON_ONOS_CID = "Non-ONOS circuit ID";
Yi Tseng5479fb82017-09-01 17:24:57 -0700229 private static final VlanId IGNORED_VLAN = VlanId.vlanId("100");
230 private static final int IGNORE_CONTROL_PRIORITY = PacketPriority.CONTROL.priorityValue() + 1000;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700231
232 private DhcpRelayManager manager;
233 private MockPacketService packetService;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700234 private MockRouteStore mockRouteStore;
235 private MockDhcpRelayStore mockDhcpRelayStore;
Yi Tseng4b013202017-09-08 17:22:51 -0700236 private HostProviderService mockHostProviderService;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700237
238 @Before
239 public void setup() {
240 manager = new DhcpRelayManager();
241 manager.cfgService = createNiceMock(NetworkConfigRegistry.class);
242
Yi Tsenge72fbb52017-08-02 15:03:31 -0700243 expect(manager.cfgService.getConfig(APP_ID, DefaultDhcpRelayConfig.class))
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700244 .andReturn(CONFIG)
245 .anyTimes();
246
Yi Tsenge72fbb52017-08-02 15:03:31 -0700247 // TODO: add indirect test
248 expect(manager.cfgService.getConfig(APP_ID, IndirectDhcpRelayConfig.class))
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000249 .andReturn(CONFIG_INDIRECT)
Yi Tsenge72fbb52017-08-02 15:03:31 -0700250 .anyTimes();
251
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700252 manager.coreService = createNiceMock(CoreService.class);
253 expect(manager.coreService.registerApplication(anyString()))
254 .andReturn(APP_ID).anyTimes();
255
256 manager.hostService = createNiceMock(HostService.class);
Yi Tseng4fa05832017-08-17 13:08:31 -0700257 expect(manager.hostService.getHostsByIp(anyObject())).andReturn(ImmutableSet.of(SERVER_HOST)).anyTimes();
258 expect(manager.hostService.getHost(OUTER_RELAY_HOST_ID)).andReturn(OUTER_RELAY_HOST).anyTimes();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700259
260 packetService = new MockPacketService();
261 manager.packetService = packetService;
262 manager.compCfgService = createNiceMock(ComponentConfigService.class);
Yi Tseng76365d82017-09-12 15:55:17 -0700263 manager.deviceService = createNiceMock(DeviceService.class);
264
265 Device device = createNiceMock(Device.class);
266 expect(device.is(Pipeliner.class)).andReturn(true).anyTimes();
267
268 expect(manager.deviceService.getDevice(DEV_1_ID)).andReturn(device).anyTimes();
269 expect(manager.deviceService.getDevice(DEV_2_ID)).andReturn(device).anyTimes();
270 replay(manager.deviceService, device);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700271
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700272 mockRouteStore = new MockRouteStore();
273 mockDhcpRelayStore = new MockDhcpRelayStore();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700274 manager.dhcpRelayStore = mockDhcpRelayStore;
275
276 manager.interfaceService = new MockInterfaceService();
Yi Tseng5479fb82017-09-01 17:24:57 -0700277 manager.flowObjectiveService = EasyMock.niceMock(FlowObjectiveService.class);
Yi Tseng4b013202017-09-08 17:22:51 -0700278 mockHostProviderService = createNiceMock(HostProviderService.class);
Yi Tseng51301292017-07-28 13:02:59 -0700279 Dhcp4HandlerImpl v4Handler = new Dhcp4HandlerImpl();
Yi Tseng4b013202017-09-08 17:22:51 -0700280 v4Handler.providerService = mockHostProviderService;
Yi Tseng51301292017-07-28 13:02:59 -0700281 v4Handler.dhcpRelayStore = mockDhcpRelayStore;
282 v4Handler.hostService = manager.hostService;
Yi Tseng51301292017-07-28 13:02:59 -0700283 v4Handler.interfaceService = manager.interfaceService;
284 v4Handler.packetService = manager.packetService;
285 v4Handler.routeStore = mockRouteStore;
286 manager.v4Handler = v4Handler;
287
288 // TODO: initialize v6 handler.
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000289 //DhcpHandler v6Handler = createNiceMock(DhcpHandler.class);
290 Dhcp6HandlerImpl v6Handler = new Dhcp6HandlerImpl();
291 v6Handler.dhcpRelayStore = mockDhcpRelayStore;
292 v6Handler.hostService = manager.hostService;
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000293 v6Handler.interfaceService = manager.interfaceService;
294 v6Handler.packetService = manager.packetService;
295 v6Handler.routeStore = mockRouteStore;
Yi Tseng4b013202017-09-08 17:22:51 -0700296 v6Handler.providerService = mockHostProviderService;
Yi Tsenge72fbb52017-08-02 15:03:31 -0700297 manager.v6Handler = v6Handler;
298
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700299 // properties
300 Dictionary<String, Object> dictionary = createNiceMock(Dictionary.class);
301 expect(dictionary.get("arpEnabled")).andReturn(true).anyTimes();
302 ComponentContext context = createNiceMock(ComponentContext.class);
303 expect(context.getProperties()).andReturn(dictionary).anyTimes();
304
305 EasyMock.replay(manager.cfgService, manager.coreService, manager.hostService,
306 manager.compCfgService, dictionary, context);
307 manager.activate(context);
308 }
309
310 @After
311 public void tearDown() {
312 manager.deactivate();
313 }
314
315 /**
316 * Relay a DHCP packet without option 82.
317 * Should add new host to host store after dhcp ack.
318 */
319 @Test
320 public void relayDhcpWithoutAgentInfo() {
Yi Tseng4b013202017-09-08 17:22:51 -0700321 replay(mockHostProviderService);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700322 // send request
323 packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT_MAC,
324 CLIENT_VLAN,
325 CLIENT_CP,
326 INTERFACE_IP.ipAddress().getIp4Address(),
327 false));
Yi Tseng4b013202017-09-08 17:22:51 -0700328 // won't trigger the host provider service
329 verify(mockHostProviderService);
330 reset(mockHostProviderService);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700331
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700332 assertEquals(0, mockRouteStore.routes.size());
333
Yi Tseng4b013202017-09-08 17:22:51 -0700334 HostId expectHostId = HostId.hostId(CLIENT_MAC, CLIENT_VLAN);
335 Capture<HostDescription> capturedHostDesc = newCapture();
336 mockHostProviderService.hostDetected(eq(expectHostId), capture(capturedHostDesc), eq(false));
337 replay(mockHostProviderService);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700338 // send ack
339 packetService.processPacket(new TestDhcpAckPacketContext(CLIENT_CP, CLIENT_MAC,
340 CLIENT_VLAN, INTERFACE_IP.ipAddress().getIp4Address(),
341 false));
Yi Tseng4b013202017-09-08 17:22:51 -0700342 verify(mockHostProviderService);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700343 assertEquals(0, mockRouteStore.routes.size());
344
Yi Tseng4b013202017-09-08 17:22:51 -0700345 HostDescription host = capturedHostDesc.getValue();
346 assertEquals(false, host.configured());
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700347 assertEquals(CLIENT_CP.deviceId(), host.location().elementId());
348 assertEquals(CLIENT_CP.port(), host.location().port());
Yi Tseng4b013202017-09-08 17:22:51 -0700349 assertEquals(1, host.ipAddress().size());
350 assertEquals(IP_FOR_CLIENT, host.ipAddress().iterator().next());
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700351 }
352
353 /**
354 * Relay a DHCP packet with option 82 (Indirectly connected host).
355 */
356 @Test
357 public void relayDhcpWithAgentInfo() {
Yi Tseng4b013202017-09-08 17:22:51 -0700358 replay(mockHostProviderService);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700359 // Assume outer dhcp relay agent exists in store already
360 // send request
361 packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT2_MAC,
362 CLIENT2_VLAN,
363 CLIENT2_CP,
364 INTERFACE_IP.ipAddress().getIp4Address(),
365 true));
Yi Tseng4b013202017-09-08 17:22:51 -0700366 // No routes
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700367 assertEquals(0, mockRouteStore.routes.size());
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700368 // send ack
369 packetService.processPacket(new TestDhcpAckPacketContext(CLIENT2_CP,
370 CLIENT2_MAC,
371 CLIENT2_VLAN,
372 INTERFACE_IP.ipAddress().getIp4Address(),
373 true));
374
Yi Tseng4b013202017-09-08 17:22:51 -0700375 // won't trigger the host provider service
376 verify(mockHostProviderService);
377 reset(mockHostProviderService);
378
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700379 assertEquals(1, mockRouteStore.routes.size());
380
381 Route route = mockRouteStore.routes.get(0);
382 assertEquals(OUTER_RELAY_IP, route.nextHop());
383 assertEquals(IP_FOR_CLIENT.toIpPrefix(), route.prefix());
384 assertEquals(Route.Source.STATIC, route.source());
385 }
386
387 @Test
Yi Tseng4fa05832017-08-17 13:08:31 -0700388 public void testWithRelayAgentConfig() throws DeserializationException {
389 manager.v4Handler
390 .setDefaultDhcpServerConfigs(ImmutableList.of(new MockDhcpServerConfig(RELAY_AGENT_IP)));
Yi Tseng4ec727d2017-08-31 11:21:00 -0700391 manager.v4Handler
392 .setIndirectDhcpServerConfigs(ImmutableList.of(new MockDhcpServerConfig(RELAY_AGENT_IP)));
Yi Tseng4fa05832017-08-17 13:08:31 -0700393 packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT2_MAC,
394 CLIENT2_VLAN,
395 CLIENT2_CP,
396 INTERFACE_IP.ipAddress().getIp4Address(),
397 true));
398 OutboundPacket outPacket = packetService.emittedPacket;
399 byte[] outData = outPacket.data().array();
400 Ethernet eth = Ethernet.deserializer().deserialize(outData, 0, outData.length);
401 IPv4 ip = (IPv4) eth.getPayload();
402 UDP udp = (UDP) ip.getPayload();
403 DHCP dhcp = (DHCP) udp.getPayload();
404 assertEquals(RELAY_AGENT_IP.toInt(), dhcp.getGatewayIPAddress());
405 }
406
407 @Test
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700408 public void testArpRequest() throws Exception {
409 packetService.processPacket(new TestArpRequestPacketContext(CLIENT_INTERFACE));
Ray Milkeybd52a052017-08-23 15:23:50 -0700410 OutboundPacket outboundPacket = packetService.emittedPacket;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700411 byte[] outPacketData = outboundPacket.data().array();
412 Ethernet eth = Ethernet.deserializer().deserialize(outPacketData, 0, outPacketData.length);
413
414 assertEquals(eth.getEtherType(), Ethernet.TYPE_ARP);
415 ARP arp = (ARP) eth.getPayload();
416 assertArrayEquals(arp.getSenderHardwareAddress(), CLIENT_INTERFACE.mac().toBytes());
417 }
418
Yi Tseng5479fb82017-09-01 17:24:57 -0700419 /**
420 * Ignores specific vlans from specific devices if config.
421 *
422 * @throws Exception the exception from this test
423 */
424 @Test
425 public void testIgnoreVlan() throws Exception {
426 ObjectMapper om = new ObjectMapper();
427 JsonNode json = om.readTree(Resources.getResource(CONFIG_FILE_PATH));
428 IgnoreDhcpConfig config = new IgnoreDhcpConfig();
429 json = json.path("apps").path(DHCP_RELAY_APP).path(IgnoreDhcpConfig.KEY);
430 config.init(APP_ID, IgnoreDhcpConfig.KEY, json, om, null);
431
432 Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
433 manager.flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
Yi Tseng76365d82017-09-12 15:55:17 -0700434 expectLastCall().times(DHCP_SELECTORS.size());
Yi Tseng5479fb82017-09-01 17:24:57 -0700435 Capture<Objective> capturedFromDev2 = newCapture(CaptureType.ALL);
436 manager.flowObjectiveService.apply(eq(DEV_2_ID), capture(capturedFromDev2));
Yi Tseng76365d82017-09-12 15:55:17 -0700437 expectLastCall().times(DHCP_SELECTORS.size());
Yi Tseng5479fb82017-09-01 17:24:57 -0700438 replay(manager.flowObjectiveService);
439 manager.updateConfig(config);
440 verify(manager.flowObjectiveService);
441
442 List<Objective> objectivesFromDev1 = capturedFromDev1.getValues();
443 List<Objective> objectivesFromDev2 = capturedFromDev2.getValues();
444
445 assertTrue(objectivesFromDev1.containsAll(objectivesFromDev2));
446 assertTrue(objectivesFromDev2.containsAll(objectivesFromDev1));
447 TrafficTreatment dropTreatment = DefaultTrafficTreatment.emptyTreatment();
448 dropTreatment.clearedDeferred();
449
450 for (int index = 0; index < objectivesFromDev1.size(); index++) {
451 TrafficSelector selector =
452 DefaultTrafficSelector.builder(DhcpRelayManager.DHCP_SELECTORS.get(index))
453 .matchVlanId(IGNORED_VLAN)
454 .build();
455 ForwardingObjective fwd = (ForwardingObjective) objectivesFromDev1.get(index);
456 assertEquals(selector, fwd.selector());
457 assertEquals(dropTreatment, fwd.treatment());
458 assertEquals(IGNORE_CONTROL_PRIORITY, fwd.priority());
459 assertEquals(ForwardingObjective.Flag.VERSATILE, fwd.flag());
460 assertEquals(Objective.Operation.ADD, fwd.op());
Yi Tseng76365d82017-09-12 15:55:17 -0700461 fwd.context().ifPresent(ctx -> {
462 ctx.onSuccess(fwd);
463 });
Yi Tseng5479fb82017-09-01 17:24:57 -0700464 }
Yi Tseng76365d82017-09-12 15:55:17 -0700465 objectivesFromDev2.forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));
Yi Tseng5479fb82017-09-01 17:24:57 -0700466 assertEquals(2, manager.ignoredVlans.size());
467 }
468
469 /**
470 * "IgnoreVlan" policy should be removed when the config removed.
471 */
472 @Test
473 public void testRemoveIgnoreVlan() {
474 manager.ignoredVlans.put(DEV_1_ID, IGNORED_VLAN);
475 manager.ignoredVlans.put(DEV_2_ID, IGNORED_VLAN);
476 IgnoreDhcpConfig config = new IgnoreDhcpConfig();
477
478 Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
479 manager.flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
Yi Tseng76365d82017-09-12 15:55:17 -0700480 expectLastCall().times(DHCP_SELECTORS.size());
Yi Tseng5479fb82017-09-01 17:24:57 -0700481 Capture<Objective> capturedFromDev2 = newCapture(CaptureType.ALL);
482 manager.flowObjectiveService.apply(eq(DEV_2_ID), capture(capturedFromDev2));
Yi Tseng76365d82017-09-12 15:55:17 -0700483 expectLastCall().times(DHCP_SELECTORS.size());
Yi Tseng5479fb82017-09-01 17:24:57 -0700484 replay(manager.flowObjectiveService);
485 manager.removeConfig(config);
486 verify(manager.flowObjectiveService);
487
488 List<Objective> objectivesFromDev1 = capturedFromDev1.getValues();
489 List<Objective> objectivesFromDev2 = capturedFromDev2.getValues();
490
491 assertTrue(objectivesFromDev1.containsAll(objectivesFromDev2));
492 assertTrue(objectivesFromDev2.containsAll(objectivesFromDev1));
493 TrafficTreatment dropTreatment = DefaultTrafficTreatment.emptyTreatment();
494 dropTreatment.clearedDeferred();
495
496 for (int index = 0; index < objectivesFromDev1.size(); index++) {
497 TrafficSelector selector =
498 DefaultTrafficSelector.builder(DhcpRelayManager.DHCP_SELECTORS.get(index))
499 .matchVlanId(IGNORED_VLAN)
500 .build();
501 ForwardingObjective fwd = (ForwardingObjective) objectivesFromDev1.get(index);
502 assertEquals(selector, fwd.selector());
503 assertEquals(dropTreatment, fwd.treatment());
504 assertEquals(IGNORE_CONTROL_PRIORITY, fwd.priority());
505 assertEquals(ForwardingObjective.Flag.VERSATILE, fwd.flag());
506 assertEquals(Objective.Operation.REMOVE, fwd.op());
Yi Tseng76365d82017-09-12 15:55:17 -0700507 fwd.context().ifPresent(ctx -> {
508 ctx.onSuccess(fwd);
509 });
Yi Tseng5479fb82017-09-01 17:24:57 -0700510 }
Yi Tseng76365d82017-09-12 15:55:17 -0700511 objectivesFromDev2.forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));
Yi Tseng5479fb82017-09-01 17:24:57 -0700512 assertEquals(0, manager.ignoredVlans.size());
513 }
514
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000515 /**
Yi Tseng76365d82017-09-12 15:55:17 -0700516 * Should ignore ignore rules installation when device not available.
517 */
518 @Test
519 public void testIgnoreUnknownDevice() throws IOException {
520 reset(manager.deviceService);
521 Device device = createNiceMock(Device.class);
522 expect(device.is(Pipeliner.class)).andReturn(true).anyTimes();
523
524 expect(manager.deviceService.getDevice(DEV_1_ID)).andReturn(device).anyTimes();
525 expect(manager.deviceService.getDevice(DEV_2_ID)).andReturn(null).anyTimes();
526
527 ObjectMapper om = new ObjectMapper();
528 JsonNode json = om.readTree(Resources.getResource(CONFIG_FILE_PATH));
529 IgnoreDhcpConfig config = new IgnoreDhcpConfig();
530 json = json.path("apps").path(DHCP_RELAY_APP).path(IgnoreDhcpConfig.KEY);
531 config.init(APP_ID, IgnoreDhcpConfig.KEY, json, om, null);
532
533 Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
534 manager.flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
535 expectLastCall().times(DHCP_SELECTORS.size());
536 replay(manager.flowObjectiveService, manager.deviceService, device);
537
538 manager.updateConfig(config);
539 capturedFromDev1.getValues().forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));
540
541 assertEquals(1, manager.ignoredVlans.size());
542 }
543
544 /**
545 * Should try install ignore rules when device comes up.
546 */
547 @Test
548 public void testInstallIgnoreRuleWhenDeviceComesUp() throws IOException {
549 ObjectMapper om = new ObjectMapper();
550 JsonNode json = om.readTree(Resources.getResource(CONFIG_FILE_PATH));
551 IgnoreDhcpConfig config = new IgnoreDhcpConfig();
552 json = json.path("apps").path(DHCP_RELAY_APP).path(IgnoreDhcpConfig.KEY);
553 config.init(APP_ID, IgnoreDhcpConfig.KEY, json, om, null);
554
555 reset(manager.cfgService, manager.flowObjectiveService, manager.deviceService);
556 expect(manager.cfgService.getConfig(APP_ID, IgnoreDhcpConfig.class))
557 .andReturn(config).anyTimes();
558
559 Device device = createNiceMock(Device.class);
560 expect(device.is(Pipeliner.class)).andReturn(true).anyTimes();
561 expect(device.id()).andReturn(DEV_1_ID).anyTimes();
562 expect(manager.deviceService.getDevice(DEV_1_ID)).andReturn(device).anyTimes();
563 DeviceEvent event = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, device);
564 Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
565 manager.flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
566 expectLastCall().times(DHCP_SELECTORS.size());
567 replay(manager.cfgService, manager.flowObjectiveService, manager.deviceService, device);
568 assertEquals(0, manager.ignoredVlans.size());
569 manager.deviceListener.event(event);
570 capturedFromDev1.getValues().forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));
571 assertEquals(1, manager.ignoredVlans.size());
572 }
573
574 /**
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000575 * Relay a DHCP6 packet without relay option
576 * Note: Should add new host to host store after dhcp ack.
577 */
578 @Test
579 public void relayDhcp6WithoutAgentInfo() {
Yi Tseng4b013202017-09-08 17:22:51 -0700580 replay(mockHostProviderService);
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000581 // send request
582 packetService.processPacket(new TestDhcp6RequestPacketContext(CLIENT_MAC,
583 VlanId.NONE,
584 CLIENT_CP,
585 INTERFACE_IP_V6.ipAddress().getIp6Address(),
586 0));
587
Yi Tseng4b013202017-09-08 17:22:51 -0700588 verify(mockHostProviderService);
589 reset(mockHostProviderService);
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000590 assertEquals(0, mockRouteStore.routes.size());
591
Yi Tseng4b013202017-09-08 17:22:51 -0700592 Capture<HostDescription> capturedHostDesc = newCapture();
593 mockHostProviderService.hostDetected(eq(HostId.hostId(CLIENT_MAC, CLIENT_VLAN)),
594 capture(capturedHostDesc), eq(false));
595 replay(mockHostProviderService);
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000596 // send reply
597 packetService.processPacket(new TestDhcp6ReplyPacketContext(CLIENT_CP, CLIENT_MAC,
598 CLIENT_VLAN,
599 INTERFACE_IP_V6.ipAddress().getIp6Address(),
600 0));
Yi Tseng4b013202017-09-08 17:22:51 -0700601 verify(mockHostProviderService);
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000602 assertEquals(0, mockRouteStore.routes.size());
603
Yi Tseng4b013202017-09-08 17:22:51 -0700604 HostDescription host = capturedHostDesc.getValue();
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000605 assertEquals(CLIENT_VLAN, host.vlan());
606 assertEquals(CLIENT_CP.deviceId(), host.location().elementId());
607 assertEquals(CLIENT_CP.port(), host.location().port());
Yi Tseng4b013202017-09-08 17:22:51 -0700608 assertEquals(1, host.ipAddress().size());
609 assertEquals(IP_FOR_CLIENT_V6, host.ipAddress().iterator().next());
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000610 }
611
612 /**
613 * Relay a DHCP6 packet with Relay Message opion (Indirectly connected host).
614 */
615 @Test
616 public void relayDhcp6WithAgentInfo() {
Yi Tseng4b013202017-09-08 17:22:51 -0700617 replay(mockHostProviderService);
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000618 // Assume outer dhcp6 relay agent exists in store already
619 // send request
620 packetService.processPacket(new TestDhcp6RequestPacketContext(CLIENT2_MAC,
621 CLIENT2_VLAN,
622 CLIENT2_CP,
623 INTERFACE_IP_V6.ipAddress().getIp6Address(),
624 1));
625
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000626 assertEquals(0, mockRouteStore.routes.size());
627
628 // send reply
629 packetService.processPacket(new TestDhcp6ReplyPacketContext(CLIENT2_CP,
630 CLIENT2_MAC,
631 CLIENT2_VLAN,
632 INTERFACE_IP_V6.ipAddress().getIp6Address(),
633 1));
634
Yi Tseng4b013202017-09-08 17:22:51 -0700635 // won't trigger the host provider service
636 verify(mockHostProviderService);
637 reset(mockHostProviderService);
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000638 assertEquals(2, mockRouteStore.routes.size()); // ipAddress and prefix
639
640 Route route = mockRouteStore.routes.get(0);
641 assertEquals(OUTER_RELAY_IP_V6, route.nextHop());
642 assertEquals(IP_FOR_CLIENT_V6.toIpPrefix(), route.prefix());
643 assertEquals(Route.Source.STATIC, route.source());
644 }
Yi Tseng4b013202017-09-08 17:22:51 -0700645
646 @Test
647 public void testDhcp4DualHome() {
648 PacketContext packetContext =
649 new TestDhcpAckPacketContext(CLIENT_DH_CP, CLIENT_MAC, CLIENT_VLAN,
650 INTERFACE_IP.ipAddress().getIp4Address(),
651 false);
652 reset(manager.hostService);
653 expect(manager.hostService.getHost(CLIENT_HOST_ID)).andReturn(EXISTS_HOST).anyTimes();
654 Capture<HostDescription> capturedHostDesc = newCapture();
655 mockHostProviderService.hostDetected(eq(CLIENT_HOST_ID), capture(capturedHostDesc), eq(false));
656 replay(mockHostProviderService, manager.hostService);
657 packetService.processPacket(packetContext);
658 verify(mockHostProviderService);
659
660 HostDescription hostDesc = capturedHostDesc.getValue();
661 Set<HostLocation> hostLocations = hostDesc.locations();
662 assertEquals(2, hostLocations.size());
663 assertTrue(hostLocations.contains(CLIENT_LOCATION));
664 assertTrue(hostLocations.contains(CLIENT_DH_LOCATION));
665 }
666
667 @Test
668 public void testDhcp6DualHome() {
669 PacketContext packetContext =
670 new TestDhcp6ReplyPacketContext(CLIENT_DH_CP, CLIENT_MAC, CLIENT_VLAN,
671 INTERFACE_IP_V6.ipAddress().getIp6Address(),
672 0);
673 reset(manager.hostService);
674 expect(manager.hostService.getHostsByIp(CLIENT_LL_IP_V6)).andReturn(ImmutableSet.of(EXISTS_HOST)).anyTimes();
675
676 // FIXME: currently DHCPv6 has a bug, we can't get correct vlan of client......
677 // XXX: The vlan relied from DHCP6 handler might be wrong, do hack here
678 HostId hostId = HostId.hostId(CLIENT_MAC, VlanId.NONE);
679 expect(manager.hostService.getHost(hostId)).andReturn(EXISTS_HOST).anyTimes();
680
681 // XXX: sometimes this will work, sometimes not
682 expect(manager.hostService.getHost(CLIENT_HOST_ID)).andReturn(EXISTS_HOST).anyTimes();
683
684 Capture<HostDescription> capturedHostDesc = newCapture();
685
686 // XXX: also a hack here
687 mockHostProviderService.hostDetected(eq(hostId), capture(capturedHostDesc), eq(false));
688 expectLastCall().anyTimes();
689
690 mockHostProviderService.hostDetected(eq(CLIENT_HOST_ID), capture(capturedHostDesc), eq(false));
691 expectLastCall().anyTimes();
692 replay(mockHostProviderService, manager.hostService);
693 packetService.processPacket(packetContext);
694 verify(mockHostProviderService);
695
696 HostDescription hostDesc = capturedHostDesc.getValue();
697 Set<HostLocation> hostLocations = hostDesc.locations();
698 assertEquals(2, hostLocations.size());
699 assertTrue(hostLocations.contains(CLIENT_LOCATION));
700 assertTrue(hostLocations.contains(CLIENT_DH_LOCATION));
701 }
702
Yi Tsenge72fbb52017-08-02 15:03:31 -0700703 private static class MockDefaultDhcpRelayConfig extends DefaultDhcpRelayConfig {
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700704 @Override
705 public boolean isValid() {
706 return true;
707 }
708
709 @Override
Yi Tsenge72fbb52017-08-02 15:03:31 -0700710 public List<DhcpServerConfig> dhcpServerConfigs() {
Yi Tseng4fa05832017-08-17 13:08:31 -0700711 return ImmutableList.of(new MockDhcpServerConfig(null));
Yi Tsenge72fbb52017-08-02 15:03:31 -0700712 }
713 }
714
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000715 private static class MockIndirectDhcpRelayConfig extends IndirectDhcpRelayConfig {
716 @Override
717 public boolean isValid() {
718 return true;
719 }
720
721 @Override
722 public List<DhcpServerConfig> dhcpServerConfigs() {
723 return ImmutableList.of(new MockDhcpServerConfig(null));
724 }
725 }
726
Yi Tsenge72fbb52017-08-02 15:03:31 -0700727 private static class MockDhcpServerConfig extends DhcpServerConfig {
Yi Tseng4fa05832017-08-17 13:08:31 -0700728 Ip4Address relayAgentIp;
729
730 /**
731 * Create mocked version DHCP server config.
732 *
733 * @param relayAgentIp the relay agent Ip config; null if we don't need it
734 */
735 public MockDhcpServerConfig(Ip4Address relayAgentIp) {
736 this.relayAgentIp = relayAgentIp;
737 }
738
739 @Override
740 public Optional<Ip4Address> getRelayAgentIp4() {
741 return Optional.ofNullable(relayAgentIp);
742 }
743
Yi Tsenge72fbb52017-08-02 15:03:31 -0700744 @Override
745 public Optional<ConnectPoint> getDhcpServerConnectPoint() {
746 return Optional.of(SERVER_CONNECT_POINT);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700747 }
748
Yi Tsenge72fbb52017-08-02 15:03:31 -0700749 @Override
750 public Optional<Ip4Address> getDhcpServerIp4() {
751 return Optional.of(SERVER_IP);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700752 }
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000753
754 @Override
755 public Optional<Ip4Address> getDhcpGatewayIp4() {
756 return Optional.of(GATEWAY_IP);
757 }
758
759 @Override
760 public Optional<Ip6Address> getDhcpServerIp6() {
761 return Optional.of(SERVER_IP_V6);
762 }
763
764 @Override
765 public Optional<Ip6Address> getDhcpGatewayIp6() {
766 return Optional.of(GATEWAY_IP_V6);
767 }
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700768 }
769
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700770 private class MockRouteStore extends RouteStoreAdapter {
771 private List<Route> routes = Lists.newArrayList();
772
773 @Override
774 public void updateRoute(Route route) {
775 routes.add(route);
776 }
777 }
778
779 private class MockInterfaceService extends InterfaceServiceAdapter {
780
781 @Override
782 public Set<Interface> getInterfaces() {
783 return INTERFACES;
784 }
785
786 @Override
787 public Set<Interface> getInterfacesByIp(IpAddress ip) {
788 return INTERFACES.stream()
789 .filter(iface -> {
790 return iface.ipAddressesList().stream()
791 .anyMatch(ifaceIp -> ifaceIp.ipAddress().equals(ip));
792 })
793 .collect(Collectors.toSet());
794 }
795
796 @Override
797 public Set<Interface> getInterfacesByPort(ConnectPoint port) {
798 return INTERFACES.stream()
799 .filter(iface -> iface.connectPoint().equals(port))
800 .collect(Collectors.toSet());
801 }
802 }
803
804 private class MockDhcpRelayStore implements DhcpRelayStore {
805 StoreDelegate<DhcpRelayStoreEvent> delegate;
806 private Map<HostId, DhcpRecord> records = Maps.newHashMap();
807
808 @Override
809 public void updateDhcpRecord(HostId hostId, DhcpRecord dhcpRecord) {
810 records.put(hostId, dhcpRecord);
811 DhcpRelayStoreEvent event = new DhcpRelayStoreEvent(DhcpRelayStoreEvent.Type.UPDATED,
812 dhcpRecord);
813 if (delegate != null) {
814 delegate.notify(event);
815 }
816 }
817
818 @Override
819 public Optional<DhcpRecord> getDhcpRecord(HostId hostId) {
820 return Optional.ofNullable(records.get(hostId));
821 }
822
823 @Override
824 public Collection<DhcpRecord> getDhcpRecords() {
825 return records.values();
826 }
827
828 @Override
829 public Optional<DhcpRecord> removeDhcpRecord(HostId hostId) {
830 DhcpRecord dhcpRecord = records.remove(hostId);
831 if (dhcpRecord != null) {
832 DhcpRelayStoreEvent event = new DhcpRelayStoreEvent(DhcpRelayStoreEvent.Type.REMOVED,
833 dhcpRecord);
834 if (delegate != null) {
835 delegate.notify(event);
836 }
837 }
838 return Optional.ofNullable(dhcpRecord);
839 }
840
841 @Override
842 public void setDelegate(StoreDelegate<DhcpRelayStoreEvent> delegate) {
843 this.delegate = delegate;
844 }
845
846 @Override
847 public void unsetDelegate(StoreDelegate<DhcpRelayStoreEvent> delegate) {
848 this.delegate = null;
849 }
850
851 @Override
852 public boolean hasDelegate() {
853 return this.delegate != null;
854 }
855 }
856
857 private class MockPacketService extends PacketServiceAdapter {
858 Set<PacketProcessor> packetProcessors = Sets.newHashSet();
Ray Milkeybd52a052017-08-23 15:23:50 -0700859 OutboundPacket emittedPacket;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700860
861 @Override
862 public void addProcessor(PacketProcessor processor, int priority) {
863 packetProcessors.add(processor);
864 }
865
866 public void processPacket(PacketContext packetContext) {
867 packetProcessors.forEach(p -> p.process(packetContext));
868 }
869
870 @Override
871 public void emit(OutboundPacket packet) {
Ray Milkeybd52a052017-08-23 15:23:50 -0700872 this.emittedPacket = packet;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700873 }
874 }
875
876
877
878 /**
879 * Generates DHCP REQUEST packet.
880 */
881 private class TestDhcpRequestPacketContext extends PacketContextAdapter {
882
883
884 private InboundPacket inPacket;
885
886 public TestDhcpRequestPacketContext(MacAddress clientMac, VlanId vlanId,
887 ConnectPoint clientCp,
888 Ip4Address clientGwAddr,
889 boolean withNonOnosRelayInfo) {
890 super(0, null, null, false);
891 byte[] dhcpMsgType = new byte[1];
892 dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPREQUEST.getValue();
893
894 DhcpOption dhcpOption = new DhcpOption();
895 dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
896 dhcpOption.setData(dhcpMsgType);
897 dhcpOption.setLength((byte) 1);
898 DhcpOption endOption = new DhcpOption();
899 endOption.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
900
901 DHCP dhcp = new DHCP();
902 dhcp.setHardwareType(DHCP.HWTYPE_ETHERNET);
903 dhcp.setHardwareAddressLength((byte) 6);
904 dhcp.setClientHardwareAddress(clientMac.toBytes());
905 if (withNonOnosRelayInfo) {
906 DhcpRelayAgentOption relayOption = new DhcpRelayAgentOption();
907 DhcpOption circuitIdOption = new DhcpOption();
908 CircuitId circuitId = new CircuitId("Custom option", VlanId.NONE);
909 byte[] cid = circuitId.serialize();
910 circuitIdOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
911 circuitIdOption.setLength((byte) cid.length);
912 circuitIdOption.setData(cid);
913 relayOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
914 relayOption.addSubOption(circuitIdOption);
915 dhcp.setOptions(ImmutableList.of(dhcpOption, relayOption, endOption));
916 dhcp.setGatewayIPAddress(OUTER_RELAY_IP.getIp4Address().toInt());
917 } else {
918 dhcp.setOptions(ImmutableList.of(dhcpOption, endOption));
919 }
920
921
922 UDP udp = new UDP();
923 udp.setPayload(dhcp);
924 udp.setSourcePort(UDP.DHCP_CLIENT_PORT);
925 udp.setDestinationPort(UDP.DHCP_SERVER_PORT);
926
927 IPv4 ipv4 = new IPv4();
928 ipv4.setPayload(udp);
929 ipv4.setDestinationAddress(SERVER_IP.toInt());
930 ipv4.setSourceAddress(clientGwAddr.toInt());
931
932 Ethernet eth = new Ethernet();
933 if (withNonOnosRelayInfo) {
934 eth.setEtherType(Ethernet.TYPE_IPV4)
935 .setVlanID(vlanId.toShort())
936 .setSourceMACAddress(OUTER_RELAY_MAC)
937 .setDestinationMACAddress(MacAddress.BROADCAST)
938 .setPayload(ipv4);
939 } else {
940 eth.setEtherType(Ethernet.TYPE_IPV4)
941 .setVlanID(vlanId.toShort())
942 .setSourceMACAddress(clientMac)
943 .setDestinationMACAddress(MacAddress.BROADCAST)
944 .setPayload(ipv4);
945 }
946
947 this.inPacket = new DefaultInboundPacket(clientCp, eth,
948 ByteBuffer.wrap(eth.serialize()));
949 }
950
951 @Override
952 public InboundPacket inPacket() {
953 return this.inPacket;
954 }
955 }
956
957 /**
958 * Generates DHCP ACK packet.
959 */
960 private class TestDhcpAckPacketContext extends PacketContextAdapter {
961 private InboundPacket inPacket;
962
963 public TestDhcpAckPacketContext(ConnectPoint clientCp, MacAddress clientMac,
964 VlanId clientVlan, Ip4Address clientGwAddr,
965 boolean withNonOnosRelayInfo) {
966 super(0, null, null, false);
967
968 byte[] dhcpMsgType = new byte[1];
969 dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPACK.getValue();
970
971 DhcpOption dhcpOption = new DhcpOption();
972 dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
973 dhcpOption.setData(dhcpMsgType);
974 dhcpOption.setLength((byte) 1);
975
976 DhcpOption endOption = new DhcpOption();
977 endOption.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
978
979 DHCP dhcp = new DHCP();
980 if (withNonOnosRelayInfo) {
981 DhcpRelayAgentOption relayOption = new DhcpRelayAgentOption();
982 DhcpOption circuitIdOption = new DhcpOption();
Yi Tseng2cf59912017-08-24 14:47:34 -0700983 String circuitId = NON_ONOS_CID;
984 byte[] cid = circuitId.getBytes(Charsets.US_ASCII);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700985 circuitIdOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
986 circuitIdOption.setLength((byte) cid.length);
987 circuitIdOption.setData(cid);
988 relayOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
989 relayOption.addSubOption(circuitIdOption);
990 dhcp.setOptions(ImmutableList.of(dhcpOption, relayOption, endOption));
991 dhcp.setGatewayIPAddress(OUTER_RELAY_IP.getIp4Address().toInt());
992 } else {
993 CircuitId cid = new CircuitId(clientCp.toString(), clientVlan);
994 byte[] circuitId = cid.serialize();
995 DhcpOption circuitIdSubOption = new DhcpOption();
996 circuitIdSubOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
997 circuitIdSubOption.setData(circuitId);
998 circuitIdSubOption.setLength((byte) circuitId.length);
999
1000 DhcpRelayAgentOption relayInfoOption = new DhcpRelayAgentOption();
1001 relayInfoOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
1002 relayInfoOption.addSubOption(circuitIdSubOption);
1003 dhcp.setOptions(ImmutableList.of(dhcpOption, relayInfoOption, endOption));
1004 dhcp.setGatewayIPAddress(clientGwAddr.toInt());
1005 }
1006 dhcp.setHardwareType(DHCP.HWTYPE_ETHERNET);
1007 dhcp.setHardwareAddressLength((byte) 6);
1008 dhcp.setClientHardwareAddress(clientMac.toBytes());
1009 dhcp.setYourIPAddress(IP_FOR_CLIENT.toInt());
1010
1011 UDP udp = new UDP();
1012 udp.setPayload(dhcp);
1013 udp.setSourcePort(UDP.DHCP_SERVER_PORT);
1014 udp.setDestinationPort(UDP.DHCP_CLIENT_PORT);
1015 IPv4 ipv4 = new IPv4();
1016 ipv4.setPayload(udp);
1017 ipv4.setDestinationAddress(IP_FOR_CLIENT.toString());
1018 ipv4.setSourceAddress(SERVER_IP.toString());
1019 Ethernet eth = new Ethernet();
1020 if (withNonOnosRelayInfo) {
1021 eth.setEtherType(Ethernet.TYPE_IPV4)
1022 .setVlanID(SERVER_VLAN.toShort())
1023 .setSourceMACAddress(SERVER_MAC)
1024 .setDestinationMACAddress(OUTER_RELAY_MAC)
1025 .setPayload(ipv4);
1026 } else {
1027 eth.setEtherType(Ethernet.TYPE_IPV4)
1028 .setVlanID(SERVER_VLAN.toShort())
1029 .setSourceMACAddress(SERVER_MAC)
1030 .setDestinationMACAddress(CLIENT_MAC)
1031 .setPayload(ipv4);
1032 }
1033
1034 this.inPacket = new DefaultInboundPacket(SERVER_CONNECT_POINT, eth,
1035 ByteBuffer.wrap(eth.serialize()));
1036
1037 }
1038
1039 @Override
1040 public InboundPacket inPacket() {
1041 return this.inPacket;
1042 }
1043 }
1044
1045 private class TestArpRequestPacketContext extends PacketContextAdapter {
1046 private InboundPacket inPacket;
1047
1048 public TestArpRequestPacketContext(Interface fromInterface) {
1049 super(0, null, null, false);
1050 ARP arp = new ARP();
1051 arp.setOpCode(ARP.OP_REQUEST);
1052
1053 IpAddress targetIp = fromInterface.ipAddressesList().get(0).ipAddress();
1054 arp.setTargetProtocolAddress(targetIp.toOctets());
1055 arp.setTargetHardwareAddress(MacAddress.BROADCAST.toBytes());
1056 arp.setSenderHardwareAddress(MacAddress.NONE.toBytes());
1057 arp.setSenderProtocolAddress(Ip4Address.valueOf(0).toOctets());
1058 arp.setHardwareAddressLength((byte) MacAddress.MAC_ADDRESS_LENGTH);
1059 Ethernet eth = new Ethernet();
1060 eth.setEtherType(Ethernet.TYPE_ARP);
1061 eth.setSourceMACAddress(MacAddress.NONE);
1062 eth.setDestinationMACAddress(MacAddress.BROADCAST);
1063 eth.setVlanID(fromInterface.vlan().toShort());
1064 eth.setPayload(arp);
1065
1066 this.inPacket = new DefaultInboundPacket(fromInterface.connectPoint(), eth,
1067 ByteBuffer.wrap(eth.serialize()));
1068 }
1069
1070 @Override
1071 public InboundPacket inPacket() {
1072 return this.inPacket;
1073 }
1074 }
Kalhee Kim1b5094f2017-09-05 19:05:06 +00001075
1076 /**
1077 * Generates DHCP6 REQUEST packet.
1078 */
1079 private void buildDhcp6Packet(DHCP6 dhcp6, byte msgType, Ip6Address ip6Addr, IpPrefix prefix) {
1080
1081 // build address option
1082 Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
1083 iaAddressOption.setCode(DHCP6.OptionCode.IAADDR.value());
1084 iaAddressOption.setIp6Address(ip6Addr);
1085 iaAddressOption.setPreferredLifetime(3600);
1086 iaAddressOption.setValidLifetime(1200);
1087 iaAddressOption.setLength((short) Dhcp6IaAddressOption.DEFAULT_LEN);
1088
1089 Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
1090 iaNaOption.setCode(DHCP6.OptionCode.IA_NA.value());
1091 iaNaOption.setIaId(0);
1092 iaNaOption.setT1(302400);
1093 iaNaOption.setT2(483840);
1094 List<Dhcp6Option> iaNaSubOptions = new ArrayList<Dhcp6Option>();
1095 iaNaSubOptions.add(iaAddressOption);
1096 iaNaOption.setOptions(iaNaSubOptions);
1097 iaNaOption.setLength((short) (Dhcp6IaNaOption.DEFAULT_LEN + iaAddressOption.getLength()));
1098
1099 // build prefix option
1100 Dhcp6IaPrefixOption iaPrefixOption = new Dhcp6IaPrefixOption();
1101 iaPrefixOption.setCode(DHCP6.OptionCode.IAPREFIX.value());
1102 iaPrefixOption.setIp6Prefix(prefix.address().getIp6Address());
1103 iaPrefixOption.setPrefixLength((byte) prefix.prefixLength());
1104 iaPrefixOption.setPreferredLifetime(3601);
1105 iaPrefixOption.setValidLifetime(1201);
1106 iaPrefixOption.setLength((short) Dhcp6IaPrefixOption.DEFAULT_LEN);
1107
1108 Dhcp6IaPdOption iaPdOption = new Dhcp6IaPdOption();
1109 iaPdOption.setCode(DHCP6.OptionCode.IA_PD.value());
1110 iaPdOption.setIaId(0);
1111 iaPdOption.setT1(302401);
1112 iaPdOption.setT2(483841);
1113 List<Dhcp6Option> iaPdSubOptions = new ArrayList<Dhcp6Option>();
1114 iaPdSubOptions.add(iaPrefixOption);
1115 iaPdOption.setOptions(iaPdSubOptions);
1116 iaPdOption.setLength((short) (Dhcp6IaPdOption.DEFAULT_LEN + iaPrefixOption.getLength()));
1117
1118 dhcp6.setMsgType(msgType);
1119 List<Dhcp6Option> dhcp6Options = new ArrayList<Dhcp6Option>();
1120 dhcp6Options.add(iaNaOption);
1121 dhcp6Options.add(iaPdOption);
1122 dhcp6.setOptions(dhcp6Options);
1123
1124 }
1125
1126 private void buildRelayMsg(DHCP6 dhcp6Relay, byte msgType, Ip6Address linkAddr,
1127 Ip6Address peerAddr, byte hop, byte[] interfaceIdBytes,
1128 DHCP6 dhcp6Payload) {
1129
1130 dhcp6Relay.setMsgType(msgType);
1131
1132 dhcp6Relay.setLinkAddress(linkAddr.toOctets());
1133 dhcp6Relay.setPeerAddress(peerAddr.toOctets());
1134 dhcp6Relay.setHopCount(hop);
1135 List<Dhcp6Option> options = new ArrayList<Dhcp6Option>();
1136
1137 // interfaceId option
1138 Dhcp6Option interfaceId = new Dhcp6Option();
1139 interfaceId.setCode(DHCP6.OptionCode.INTERFACE_ID.value());
1140
1141
1142 interfaceId.setData(interfaceIdBytes);
1143 interfaceId.setLength((short) interfaceIdBytes.length);
1144 Dhcp6InterfaceIdOption interfaceIdOption = new Dhcp6InterfaceIdOption(interfaceId);
1145 ByteBuffer bb = ByteBuffer.wrap(interfaceIdBytes);
1146
1147 byte[] macAddr = new byte[MacAddress.MAC_ADDRESS_LENGTH];
1148 byte[] port = new byte[21];
1149 bb.get(macAddr);
1150 bb.get(); // separator
1151 bb.get(port);
1152 interfaceIdOption.setMacAddress(MacAddress.valueOf(macAddr));
1153 interfaceIdOption.setInPort(port);
1154
1155 options.add(interfaceIdOption);
1156
1157 // relay message option
1158 Dhcp6Option relayMsgOption = new Dhcp6Option();
1159 relayMsgOption.setCode(DHCP6.OptionCode.RELAY_MSG.value());
1160 byte[] dhcp6PayloadByte = dhcp6Payload.serialize();
1161 relayMsgOption.setLength((short) dhcp6PayloadByte.length);
1162 relayMsgOption.setPayload(dhcp6Payload);
1163 Dhcp6RelayOption relayOpt = new Dhcp6RelayOption(relayMsgOption);
1164
1165 options.add(relayOpt);
1166
1167 dhcp6Relay.setOptions(options);
1168 }
1169 private byte[] buildInterfaceId(MacAddress clientMac, ConnectPoint clientCp) {
1170 String inPortString = "-" + clientCp.toString();
1171 byte[] clientSoureMacBytes = clientMac.toBytes();
1172 byte[] inPortStringBytes = inPortString.getBytes();
1173 byte[] interfaceIdBytes = new byte[clientSoureMacBytes.length + inPortStringBytes.length];
1174
1175 System.arraycopy(clientSoureMacBytes, 0, interfaceIdBytes, 0, clientSoureMacBytes.length);
1176 System.arraycopy(inPortStringBytes, 0, interfaceIdBytes, clientSoureMacBytes.length, inPortStringBytes.length);
1177
1178 return interfaceIdBytes;
1179 }
1180
1181 private class TestDhcp6RequestPacketContext extends PacketContextAdapter {
1182
1183
1184 private InboundPacket inPacket;
1185
1186
1187 public TestDhcp6RequestPacketContext(MacAddress clientMac, VlanId vlanId,
1188 ConnectPoint clientCp,
1189 Ip6Address clientGwAddr,
1190 int relayLevel) {
1191 super(0, null, null, false);
1192
1193 DHCP6 dhcp6 = new DHCP6();
1194 if (relayLevel > 0) {
1195 DHCP6 dhcp6Payload = new DHCP6();
1196 buildDhcp6Packet(dhcp6Payload, DHCP6.MsgType.REQUEST.value(),
1197 IP_FOR_CLIENT_V6,
1198 PREFIX_FOR_ZERO);
1199 DHCP6 dhcp6Parent = null;
1200 DHCP6 dhcp6Child = dhcp6Payload;
1201 for (int i = 0; i < relayLevel; i++) {
1202 dhcp6Parent = new DHCP6();
1203 byte[] interfaceId = buildInterfaceId(clientMac, clientCp);
1204 buildRelayMsg(dhcp6Parent, DHCP6.MsgType.RELAY_FORW.value(),
1205 INTERFACE_IP_V6.ipAddress().getIp6Address(),
1206 OUTER_RELAY_IP_V6,
1207 (byte) (relayLevel - 1), interfaceId,
1208 dhcp6Child);
1209 dhcp6Child = dhcp6Parent;
1210 }
1211 if (dhcp6Parent != null) {
1212 dhcp6 = dhcp6Parent;
1213 }
1214 } else {
1215 buildDhcp6Packet(dhcp6, DHCP6.MsgType.REQUEST.value(),
1216 IP_FOR_CLIENT_V6,
1217 PREFIX_FOR_ZERO);
1218 }
1219
1220 UDP udp = new UDP();
1221 udp.setPayload(dhcp6);
1222 if (relayLevel > 0) {
1223 udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
1224 } else {
1225 udp.setSourcePort(UDP.DHCP_V6_CLIENT_PORT);
1226 }
1227 udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
1228
1229 IPv6 ipv6 = new IPv6();
1230 ipv6.setPayload(udp);
1231 ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
1232 ipv6.setDestinationAddress(SERVER_IP_V6_MCAST.toOctets());
1233 ipv6.setSourceAddress(clientGwAddr.toOctets());
1234
1235 Ethernet eth = new Ethernet();
1236 if (relayLevel > 0) {
1237 eth.setEtherType(Ethernet.TYPE_IPV6)
1238 .setVlanID(vlanId.toShort())
1239 .setSourceMACAddress(OUTER_RELAY_MAC)
1240 .setDestinationMACAddress(MacAddress.valueOf("33:33:00:01:00:02"))
1241 .setPayload(ipv6);
1242 } else {
1243 eth.setEtherType(Ethernet.TYPE_IPV6)
1244 .setVlanID(vlanId.toShort())
1245 .setSourceMACAddress(clientMac)
1246 .setDestinationMACAddress(MacAddress.valueOf("33:33:00:01:00:02"))
1247 .setPayload(ipv6);
1248 }
1249 this.inPacket = new DefaultInboundPacket(clientCp, eth,
1250 ByteBuffer.wrap(eth.serialize()));
1251 }
1252
1253 @Override
1254 public InboundPacket inPacket() {
1255 return this.inPacket;
1256 }
1257 }
1258
1259 /**
1260 * Generates DHCP6 REPLY packet.
1261 */
1262
1263 private class TestDhcp6ReplyPacketContext extends PacketContextAdapter {
1264 private InboundPacket inPacket;
1265
1266 public TestDhcp6ReplyPacketContext(ConnectPoint clientCp, MacAddress clientMac,
1267 VlanId clientVlan, Ip6Address clientGwAddr,
1268 int relayLevel) {
1269 super(0, null, null, false);
1270
1271
1272 DHCP6 dhcp6Payload = new DHCP6();
1273 buildDhcp6Packet(dhcp6Payload, DHCP6.MsgType.REPLY.value(),
1274 IP_FOR_CLIENT_V6,
1275 PREFIX_FOR_CLIENT_V6);
1276 byte[] interfaceId = buildInterfaceId(clientMac, clientCp);
1277 DHCP6 dhcp6 = new DHCP6();
1278 buildRelayMsg(dhcp6, DHCP6.MsgType.RELAY_REPL.value(),
Yi Tseng4b013202017-09-08 17:22:51 -07001279 INTERFACE_IP_V6.ipAddress().getIp6Address(),
1280 CLIENT_LL_IP_V6,
1281 (byte) 0, interfaceId,
1282 dhcp6Payload);
Kalhee Kim1b5094f2017-09-05 19:05:06 +00001283
1284 DHCP6 dhcp6Parent = null;
1285 DHCP6 dhcp6Child = dhcp6;
1286 for (int i = 0; i < relayLevel; i++) { // relayLevel 0 : no relay
1287 dhcp6Parent = new DHCP6();
1288
1289 buildRelayMsg(dhcp6Parent, DHCP6.MsgType.RELAY_REPL.value(),
1290 INTERFACE_IP_V6.ipAddress().getIp6Address(),
1291 OUTER_RELAY_IP_V6,
1292 (byte) relayLevel, interfaceId,
1293 dhcp6Child);
1294
1295 dhcp6Child = dhcp6Parent;
1296 }
1297 if (dhcp6Parent != null) {
1298 dhcp6 = dhcp6Parent;
1299 }
1300
1301
1302 UDP udp = new UDP();
1303 udp.setPayload(dhcp6);
1304 udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
1305 udp.setDestinationPort(UDP.DHCP_V6_CLIENT_PORT);
1306 IPv6 ipv6 = new IPv6();
1307 ipv6.setPayload(udp);
1308 ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
1309 ipv6.setDestinationAddress(IP_FOR_CLIENT_V6.toOctets());
1310 ipv6.setSourceAddress(SERVER_IP_V6.toOctets());
1311 Ethernet eth = new Ethernet();
1312 if (relayLevel > 0) {
1313 eth.setEtherType(Ethernet.TYPE_IPV6)
1314 .setVlanID(SERVER_VLAN.toShort())
1315 .setSourceMACAddress(SERVER_MAC)
1316 .setDestinationMACAddress(OUTER_RELAY_MAC)
1317 .setPayload(ipv6);
1318 } else {
1319 eth.setEtherType(Ethernet.TYPE_IPV6)
1320 .setVlanID(SERVER_VLAN.toShort())
1321 .setSourceMACAddress(SERVER_MAC)
1322 .setDestinationMACAddress(CLIENT_MAC)
1323 .setPayload(ipv6);
1324 }
1325
1326 this.inPacket = new DefaultInboundPacket(SERVER_CONNECT_POINT, eth,
1327 ByteBuffer.wrap(eth.serialize()));
1328
1329 }
1330
1331 @Override
1332 public InboundPacket inPacket() {
1333 return this.inPacket;
1334 }
1335 }
1336
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001337}