blob: 6011d1196462434b5c0ed2f5339c56c70349614e [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 Tseng58e74312017-09-30 11:35:42 +0800145 private static final Interface CLIENT_INTERFACE = createInterface("C1",
146 CLIENT_CP,
147 INTERFACE_IPS,
148 CLIENT_IFACE_MAC,
149 CLIENT_VLAN,
150 null);
151
152
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700153
Yi Tseng4b013202017-09-08 17:22:51 -0700154 // Dual homing test
155 private static final ConnectPoint CLIENT_DH_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/3");
156 private static final HostLocation CLIENT_DH_LOCATION = new HostLocation(CLIENT_DH_CP, 0);
Yi Tseng58e74312017-09-30 11:35:42 +0800157 private static final Interface CLIENT_DH_INTERFACE = createInterface("C1-DH",
158 CLIENT_DH_CP,
159 INTERFACE_IPS,
160 CLIENT_IFACE_MAC,
161 CLIENT_VLAN,
162 null);
Yi Tseng4b013202017-09-08 17:22:51 -0700163
164
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700165 // DHCP client 2 (will send with option 82, so the vlan should equals to vlan from server)
166 private static final MacAddress CLIENT2_MAC = MacAddress.valueOf("00:00:00:00:00:01");
167 private static final VlanId CLIENT2_VLAN = VlanId.NONE;
Yi Tseng58e74312017-09-30 11:35:42 +0800168 private static final VlanId CLIENT2_VLAN_NATIVE = VlanId.vlanId("20");
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700169 private static final ConnectPoint CLIENT2_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
170 private static final MacAddress CLIENT2_IFACE_MAC = MacAddress.valueOf("00:00:00:00:11:01");
Yi Tseng58e74312017-09-30 11:35:42 +0800171 private static final Interface CLIENT2_INTERFACE = createInterface("C2",
172 CLIENT2_CP,
173 INTERFACE_IPS,
174 CLIENT2_IFACE_MAC,
175 CLIENT2_VLAN,
176 CLIENT2_VLAN_NATIVE);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700177
178 // Outer relay information
179 private static final Ip4Address OUTER_RELAY_IP = Ip4Address.valueOf("10.0.5.253");
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000180 private static final Ip6Address OUTER_RELAY_IP_V6 = Ip6Address.valueOf("2001:db8:1::4");
181 private static final Set<IpAddress> OUTER_RELAY_IPS = ImmutableSet.of(OUTER_RELAY_IP, OUTER_RELAY_IP_V6);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700182 private static final MacAddress OUTER_RELAY_MAC = MacAddress.valueOf("00:01:02:03:04:05");
183 private static final VlanId OUTER_RELAY_VLAN = VlanId.NONE;
184 private static final ConnectPoint OUTER_RELAY_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
185 private static final HostLocation OUTER_REPLAY_HL = new HostLocation(OUTER_RELAY_CP, 0);
186 private static final HostId OUTER_RELAY_HOST_ID = HostId.hostId(OUTER_RELAY_MAC, OUTER_RELAY_VLAN);
Charles Chan75edab72017-09-12 17:09:32 -0700187 private static final Host OUTER_RELAY_HOST = new DefaultHost(Dhcp4HandlerImpl.PROVIDER_ID,
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700188 OUTER_RELAY_HOST_ID,
189 OUTER_RELAY_MAC,
190 OUTER_RELAY_VLAN,
191 OUTER_REPLAY_HL,
192 OUTER_RELAY_IPS);
193
194 // DHCP Server
195 private static final MacAddress SERVER_MAC = MacAddress.valueOf("00:00:00:00:00:01");
196 private static final VlanId SERVER_VLAN = VlanId.NONE;
Yi Tseng58e74312017-09-30 11:35:42 +0800197 private static final VlanId SERVER_VLAN_NATIVE = VlanId.vlanId("10");
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700198 private static final ConnectPoint SERVER_CONNECT_POINT =
199 ConnectPoint.deviceConnectPoint("of:0000000000000001/5");
200 private static final HostLocation SERVER_LOCATION =
201 new HostLocation(SERVER_CONNECT_POINT, 0);
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000202 private static final Ip4Address GATEWAY_IP = Ip4Address.valueOf("10.0.5.253");
203 private static final Ip6Address GATEWAY_IP_V6 = Ip6Address.valueOf("2000::105:253");
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700204 private static final Ip4Address SERVER_IP = Ip4Address.valueOf("10.0.3.253");
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000205 private static final Ip6Address SERVER_IP_V6 = Ip6Address.valueOf("2000::103:253");
206 private static final Ip6Address SERVER_IP_V6_MCAST = Ip6Address.valueOf("ff02::1:2");
207 private static final Set<IpAddress> DHCP_SERVER_IPS = ImmutableSet.of(SERVER_IP, SERVER_IP_V6);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700208 private static final HostId SERVER_HOST_ID = HostId.hostId(SERVER_MAC, SERVER_VLAN);
Charles Chan75edab72017-09-12 17:09:32 -0700209 private static final Host SERVER_HOST = new DefaultHost(Dhcp4HandlerImpl.PROVIDER_ID,
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700210 SERVER_HOST_ID,
211 SERVER_MAC,
212 SERVER_VLAN,
213 SERVER_LOCATION,
214 DHCP_SERVER_IPS);
215 private static final MacAddress SERVER_IFACE_MAC = MacAddress.valueOf("00:00:00:00:00:01");
Yi Tseng58e74312017-09-30 11:35:42 +0800216 private static final Interface SERVER_INTERFACE = createInterface("SERVER",
217 SERVER_CONNECT_POINT,
218 INTERFACE_IPS,
219 SERVER_IFACE_MAC,
220 SERVER_VLAN,
221 SERVER_VLAN_NATIVE);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700222
Yi Tseng4fa05832017-08-17 13:08:31 -0700223 // Relay agent config
224 private static final Ip4Address RELAY_AGENT_IP = Ip4Address.valueOf("10.0.4.254");
225
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700226 // Components
227 private static final ApplicationId APP_ID = TestApplicationId.create(DhcpRelayManager.DHCP_RELAY_APP);
Yi Tsenge72fbb52017-08-02 15:03:31 -0700228 private static final DefaultDhcpRelayConfig CONFIG = new MockDefaultDhcpRelayConfig();
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000229 private static final IndirectDhcpRelayConfig CONFIG_INDIRECT = new MockIndirectDhcpRelayConfig();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700230 private static final Set<Interface> INTERFACES = ImmutableSet.of(
231 CLIENT_INTERFACE,
232 CLIENT2_INTERFACE,
Yi Tseng4b013202017-09-08 17:22:51 -0700233 SERVER_INTERFACE,
234 CLIENT_DH_INTERFACE
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700235 );
Yi Tseng2cf59912017-08-24 14:47:34 -0700236 private static final String NON_ONOS_CID = "Non-ONOS circuit ID";
Yi Tseng5479fb82017-09-01 17:24:57 -0700237 private static final VlanId IGNORED_VLAN = VlanId.vlanId("100");
238 private static final int IGNORE_CONTROL_PRIORITY = PacketPriority.CONTROL.priorityValue() + 1000;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700239
240 private DhcpRelayManager manager;
241 private MockPacketService packetService;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700242 private MockRouteStore mockRouteStore;
243 private MockDhcpRelayStore mockDhcpRelayStore;
Yi Tseng4b013202017-09-08 17:22:51 -0700244 private HostProviderService mockHostProviderService;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700245
Yi Tseng58e74312017-09-30 11:35:42 +0800246 private static Interface createInterface(String name, ConnectPoint connectPoint,
247 List<InterfaceIpAddress> interfaceIps,
248 MacAddress macAddress,
249 VlanId vlanId,
250 VlanId vlanNative) {
251
252 if (vlanId.equals(VlanId.NONE)) {
253 return new Interface(name, connectPoint, interfaceIps, macAddress, vlanId,
254 null, null, vlanNative);
255 } else {
256 return new Interface(name, connectPoint, interfaceIps, macAddress, vlanId,
257 null, ImmutableSet.of(vlanId), null);
258 }
259 }
260
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700261 @Before
262 public void setup() {
263 manager = new DhcpRelayManager();
264 manager.cfgService = createNiceMock(NetworkConfigRegistry.class);
265
Yi Tsenge72fbb52017-08-02 15:03:31 -0700266 expect(manager.cfgService.getConfig(APP_ID, DefaultDhcpRelayConfig.class))
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700267 .andReturn(CONFIG)
268 .anyTimes();
269
Yi Tsenge72fbb52017-08-02 15:03:31 -0700270 expect(manager.cfgService.getConfig(APP_ID, IndirectDhcpRelayConfig.class))
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000271 .andReturn(CONFIG_INDIRECT)
Yi Tsenge72fbb52017-08-02 15:03:31 -0700272 .anyTimes();
273
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700274 manager.coreService = createNiceMock(CoreService.class);
275 expect(manager.coreService.registerApplication(anyString()))
276 .andReturn(APP_ID).anyTimes();
277
278 manager.hostService = createNiceMock(HostService.class);
Yi Tseng4fa05832017-08-17 13:08:31 -0700279 expect(manager.hostService.getHostsByIp(anyObject())).andReturn(ImmutableSet.of(SERVER_HOST)).anyTimes();
280 expect(manager.hostService.getHost(OUTER_RELAY_HOST_ID)).andReturn(OUTER_RELAY_HOST).anyTimes();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700281
282 packetService = new MockPacketService();
283 manager.packetService = packetService;
284 manager.compCfgService = createNiceMock(ComponentConfigService.class);
Yi Tseng76365d82017-09-12 15:55:17 -0700285 manager.deviceService = createNiceMock(DeviceService.class);
286
287 Device device = createNiceMock(Device.class);
288 expect(device.is(Pipeliner.class)).andReturn(true).anyTimes();
289
290 expect(manager.deviceService.getDevice(DEV_1_ID)).andReturn(device).anyTimes();
291 expect(manager.deviceService.getDevice(DEV_2_ID)).andReturn(device).anyTimes();
292 replay(manager.deviceService, device);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700293
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700294 mockRouteStore = new MockRouteStore();
295 mockDhcpRelayStore = new MockDhcpRelayStore();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700296 manager.dhcpRelayStore = mockDhcpRelayStore;
297
298 manager.interfaceService = new MockInterfaceService();
Yi Tseng5479fb82017-09-01 17:24:57 -0700299 manager.flowObjectiveService = EasyMock.niceMock(FlowObjectiveService.class);
Yi Tseng4b013202017-09-08 17:22:51 -0700300 mockHostProviderService = createNiceMock(HostProviderService.class);
Yi Tseng51301292017-07-28 13:02:59 -0700301 Dhcp4HandlerImpl v4Handler = new Dhcp4HandlerImpl();
Yi Tseng4b013202017-09-08 17:22:51 -0700302 v4Handler.providerService = mockHostProviderService;
Yi Tseng51301292017-07-28 13:02:59 -0700303 v4Handler.dhcpRelayStore = mockDhcpRelayStore;
304 v4Handler.hostService = manager.hostService;
Yi Tseng51301292017-07-28 13:02:59 -0700305 v4Handler.interfaceService = manager.interfaceService;
306 v4Handler.packetService = manager.packetService;
307 v4Handler.routeStore = mockRouteStore;
308 manager.v4Handler = v4Handler;
309
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000310 Dhcp6HandlerImpl v6Handler = new Dhcp6HandlerImpl();
311 v6Handler.dhcpRelayStore = mockDhcpRelayStore;
312 v6Handler.hostService = manager.hostService;
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000313 v6Handler.interfaceService = manager.interfaceService;
314 v6Handler.packetService = manager.packetService;
315 v6Handler.routeStore = mockRouteStore;
Yi Tseng4b013202017-09-08 17:22:51 -0700316 v6Handler.providerService = mockHostProviderService;
Yi Tsenge72fbb52017-08-02 15:03:31 -0700317 manager.v6Handler = v6Handler;
318
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700319 // properties
320 Dictionary<String, Object> dictionary = createNiceMock(Dictionary.class);
321 expect(dictionary.get("arpEnabled")).andReturn(true).anyTimes();
322 ComponentContext context = createNiceMock(ComponentContext.class);
323 expect(context.getProperties()).andReturn(dictionary).anyTimes();
324
Yi Tseng58e74312017-09-30 11:35:42 +0800325 replay(manager.cfgService, manager.coreService, manager.hostService,
326 manager.compCfgService, dictionary, context);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700327 manager.activate(context);
328 }
329
330 @After
331 public void tearDown() {
332 manager.deactivate();
333 }
334
335 /**
336 * Relay a DHCP packet without option 82.
337 * Should add new host to host store after dhcp ack.
338 */
339 @Test
340 public void relayDhcpWithoutAgentInfo() {
Yi Tseng4b013202017-09-08 17:22:51 -0700341 replay(mockHostProviderService);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700342 // send request
343 packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT_MAC,
344 CLIENT_VLAN,
345 CLIENT_CP,
346 INTERFACE_IP.ipAddress().getIp4Address(),
347 false));
Yi Tseng4b013202017-09-08 17:22:51 -0700348 // won't trigger the host provider service
349 verify(mockHostProviderService);
350 reset(mockHostProviderService);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700351
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700352 assertEquals(0, mockRouteStore.routes.size());
353
Yi Tseng4b013202017-09-08 17:22:51 -0700354 HostId expectHostId = HostId.hostId(CLIENT_MAC, CLIENT_VLAN);
355 Capture<HostDescription> capturedHostDesc = newCapture();
356 mockHostProviderService.hostDetected(eq(expectHostId), capture(capturedHostDesc), eq(false));
357 replay(mockHostProviderService);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700358 // send ack
359 packetService.processPacket(new TestDhcpAckPacketContext(CLIENT_CP, CLIENT_MAC,
360 CLIENT_VLAN, INTERFACE_IP.ipAddress().getIp4Address(),
361 false));
Yi Tseng4b013202017-09-08 17:22:51 -0700362 verify(mockHostProviderService);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700363 assertEquals(0, mockRouteStore.routes.size());
364
Yi Tseng4b013202017-09-08 17:22:51 -0700365 HostDescription host = capturedHostDesc.getValue();
366 assertEquals(false, host.configured());
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700367 assertEquals(CLIENT_CP.deviceId(), host.location().elementId());
368 assertEquals(CLIENT_CP.port(), host.location().port());
Yi Tseng4b013202017-09-08 17:22:51 -0700369 assertEquals(1, host.ipAddress().size());
370 assertEquals(IP_FOR_CLIENT, host.ipAddress().iterator().next());
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700371 }
372
373 /**
374 * Relay a DHCP packet with option 82 (Indirectly connected host).
375 */
376 @Test
377 public void relayDhcpWithAgentInfo() {
Yi Tseng4b013202017-09-08 17:22:51 -0700378 replay(mockHostProviderService);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700379 // Assume outer dhcp relay agent exists in store already
380 // send request
381 packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT2_MAC,
382 CLIENT2_VLAN,
383 CLIENT2_CP,
384 INTERFACE_IP.ipAddress().getIp4Address(),
385 true));
Yi Tseng4b013202017-09-08 17:22:51 -0700386 // No routes
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700387 assertEquals(0, mockRouteStore.routes.size());
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700388 // send ack
389 packetService.processPacket(new TestDhcpAckPacketContext(CLIENT2_CP,
390 CLIENT2_MAC,
391 CLIENT2_VLAN,
392 INTERFACE_IP.ipAddress().getIp4Address(),
393 true));
394
Yi Tseng4b013202017-09-08 17:22:51 -0700395 // won't trigger the host provider service
396 verify(mockHostProviderService);
397 reset(mockHostProviderService);
398
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700399 assertEquals(1, mockRouteStore.routes.size());
400
401 Route route = mockRouteStore.routes.get(0);
402 assertEquals(OUTER_RELAY_IP, route.nextHop());
403 assertEquals(IP_FOR_CLIENT.toIpPrefix(), route.prefix());
404 assertEquals(Route.Source.STATIC, route.source());
405 }
406
407 @Test
Yi Tseng4fa05832017-08-17 13:08:31 -0700408 public void testWithRelayAgentConfig() throws DeserializationException {
409 manager.v4Handler
410 .setDefaultDhcpServerConfigs(ImmutableList.of(new MockDhcpServerConfig(RELAY_AGENT_IP)));
Yi Tseng4ec727d2017-08-31 11:21:00 -0700411 manager.v4Handler
412 .setIndirectDhcpServerConfigs(ImmutableList.of(new MockDhcpServerConfig(RELAY_AGENT_IP)));
Yi Tseng4fa05832017-08-17 13:08:31 -0700413 packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT2_MAC,
414 CLIENT2_VLAN,
415 CLIENT2_CP,
416 INTERFACE_IP.ipAddress().getIp4Address(),
417 true));
418 OutboundPacket outPacket = packetService.emittedPacket;
419 byte[] outData = outPacket.data().array();
420 Ethernet eth = Ethernet.deserializer().deserialize(outData, 0, outData.length);
421 IPv4 ip = (IPv4) eth.getPayload();
422 UDP udp = (UDP) ip.getPayload();
423 DHCP dhcp = (DHCP) udp.getPayload();
424 assertEquals(RELAY_AGENT_IP.toInt(), dhcp.getGatewayIPAddress());
425 }
426
427 @Test
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700428 public void testArpRequest() throws Exception {
429 packetService.processPacket(new TestArpRequestPacketContext(CLIENT_INTERFACE));
Ray Milkeybd52a052017-08-23 15:23:50 -0700430 OutboundPacket outboundPacket = packetService.emittedPacket;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700431 byte[] outPacketData = outboundPacket.data().array();
432 Ethernet eth = Ethernet.deserializer().deserialize(outPacketData, 0, outPacketData.length);
433
434 assertEquals(eth.getEtherType(), Ethernet.TYPE_ARP);
435 ARP arp = (ARP) eth.getPayload();
436 assertArrayEquals(arp.getSenderHardwareAddress(), CLIENT_INTERFACE.mac().toBytes());
437 }
438
Yi Tseng5479fb82017-09-01 17:24:57 -0700439 /**
440 * Ignores specific vlans from specific devices if config.
441 *
442 * @throws Exception the exception from this test
443 */
444 @Test
445 public void testIgnoreVlan() throws Exception {
446 ObjectMapper om = new ObjectMapper();
447 JsonNode json = om.readTree(Resources.getResource(CONFIG_FILE_PATH));
448 IgnoreDhcpConfig config = new IgnoreDhcpConfig();
449 json = json.path("apps").path(DHCP_RELAY_APP).path(IgnoreDhcpConfig.KEY);
450 config.init(APP_ID, IgnoreDhcpConfig.KEY, json, om, null);
451
452 Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
453 manager.flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
Yi Tseng76365d82017-09-12 15:55:17 -0700454 expectLastCall().times(DHCP_SELECTORS.size());
Yi Tseng5479fb82017-09-01 17:24:57 -0700455 Capture<Objective> capturedFromDev2 = newCapture(CaptureType.ALL);
456 manager.flowObjectiveService.apply(eq(DEV_2_ID), capture(capturedFromDev2));
Yi Tseng76365d82017-09-12 15:55:17 -0700457 expectLastCall().times(DHCP_SELECTORS.size());
Yi Tseng5479fb82017-09-01 17:24:57 -0700458 replay(manager.flowObjectiveService);
459 manager.updateConfig(config);
460 verify(manager.flowObjectiveService);
461
462 List<Objective> objectivesFromDev1 = capturedFromDev1.getValues();
463 List<Objective> objectivesFromDev2 = capturedFromDev2.getValues();
464
465 assertTrue(objectivesFromDev1.containsAll(objectivesFromDev2));
466 assertTrue(objectivesFromDev2.containsAll(objectivesFromDev1));
467 TrafficTreatment dropTreatment = DefaultTrafficTreatment.emptyTreatment();
468 dropTreatment.clearedDeferred();
469
470 for (int index = 0; index < objectivesFromDev1.size(); index++) {
471 TrafficSelector selector =
472 DefaultTrafficSelector.builder(DhcpRelayManager.DHCP_SELECTORS.get(index))
473 .matchVlanId(IGNORED_VLAN)
474 .build();
475 ForwardingObjective fwd = (ForwardingObjective) objectivesFromDev1.get(index);
476 assertEquals(selector, fwd.selector());
477 assertEquals(dropTreatment, fwd.treatment());
478 assertEquals(IGNORE_CONTROL_PRIORITY, fwd.priority());
479 assertEquals(ForwardingObjective.Flag.VERSATILE, fwd.flag());
480 assertEquals(Objective.Operation.ADD, fwd.op());
Yi Tseng76365d82017-09-12 15:55:17 -0700481 fwd.context().ifPresent(ctx -> {
482 ctx.onSuccess(fwd);
483 });
Yi Tseng5479fb82017-09-01 17:24:57 -0700484 }
Yi Tseng76365d82017-09-12 15:55:17 -0700485 objectivesFromDev2.forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));
Yi Tseng5479fb82017-09-01 17:24:57 -0700486 assertEquals(2, manager.ignoredVlans.size());
487 }
488
489 /**
490 * "IgnoreVlan" policy should be removed when the config removed.
491 */
492 @Test
493 public void testRemoveIgnoreVlan() {
494 manager.ignoredVlans.put(DEV_1_ID, IGNORED_VLAN);
495 manager.ignoredVlans.put(DEV_2_ID, IGNORED_VLAN);
496 IgnoreDhcpConfig config = new IgnoreDhcpConfig();
497
498 Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
499 manager.flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
Yi Tseng76365d82017-09-12 15:55:17 -0700500 expectLastCall().times(DHCP_SELECTORS.size());
Yi Tseng5479fb82017-09-01 17:24:57 -0700501 Capture<Objective> capturedFromDev2 = newCapture(CaptureType.ALL);
502 manager.flowObjectiveService.apply(eq(DEV_2_ID), capture(capturedFromDev2));
Yi Tseng76365d82017-09-12 15:55:17 -0700503 expectLastCall().times(DHCP_SELECTORS.size());
Yi Tseng5479fb82017-09-01 17:24:57 -0700504 replay(manager.flowObjectiveService);
505 manager.removeConfig(config);
506 verify(manager.flowObjectiveService);
507
508 List<Objective> objectivesFromDev1 = capturedFromDev1.getValues();
509 List<Objective> objectivesFromDev2 = capturedFromDev2.getValues();
510
511 assertTrue(objectivesFromDev1.containsAll(objectivesFromDev2));
512 assertTrue(objectivesFromDev2.containsAll(objectivesFromDev1));
513 TrafficTreatment dropTreatment = DefaultTrafficTreatment.emptyTreatment();
514 dropTreatment.clearedDeferred();
515
516 for (int index = 0; index < objectivesFromDev1.size(); index++) {
517 TrafficSelector selector =
518 DefaultTrafficSelector.builder(DhcpRelayManager.DHCP_SELECTORS.get(index))
519 .matchVlanId(IGNORED_VLAN)
520 .build();
521 ForwardingObjective fwd = (ForwardingObjective) objectivesFromDev1.get(index);
522 assertEquals(selector, fwd.selector());
523 assertEquals(dropTreatment, fwd.treatment());
524 assertEquals(IGNORE_CONTROL_PRIORITY, fwd.priority());
525 assertEquals(ForwardingObjective.Flag.VERSATILE, fwd.flag());
526 assertEquals(Objective.Operation.REMOVE, fwd.op());
Yi Tseng76365d82017-09-12 15:55:17 -0700527 fwd.context().ifPresent(ctx -> {
528 ctx.onSuccess(fwd);
529 });
Yi Tseng5479fb82017-09-01 17:24:57 -0700530 }
Yi Tseng76365d82017-09-12 15:55:17 -0700531 objectivesFromDev2.forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));
Yi Tseng5479fb82017-09-01 17:24:57 -0700532 assertEquals(0, manager.ignoredVlans.size());
533 }
534
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000535 /**
Yi Tseng76365d82017-09-12 15:55:17 -0700536 * Should ignore ignore rules installation when device not available.
537 */
538 @Test
539 public void testIgnoreUnknownDevice() throws IOException {
540 reset(manager.deviceService);
541 Device device = createNiceMock(Device.class);
542 expect(device.is(Pipeliner.class)).andReturn(true).anyTimes();
543
544 expect(manager.deviceService.getDevice(DEV_1_ID)).andReturn(device).anyTimes();
545 expect(manager.deviceService.getDevice(DEV_2_ID)).andReturn(null).anyTimes();
546
547 ObjectMapper om = new ObjectMapper();
548 JsonNode json = om.readTree(Resources.getResource(CONFIG_FILE_PATH));
549 IgnoreDhcpConfig config = new IgnoreDhcpConfig();
550 json = json.path("apps").path(DHCP_RELAY_APP).path(IgnoreDhcpConfig.KEY);
551 config.init(APP_ID, IgnoreDhcpConfig.KEY, json, om, null);
552
553 Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
554 manager.flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
555 expectLastCall().times(DHCP_SELECTORS.size());
556 replay(manager.flowObjectiveService, manager.deviceService, device);
557
558 manager.updateConfig(config);
559 capturedFromDev1.getValues().forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));
560
561 assertEquals(1, manager.ignoredVlans.size());
562 }
563
564 /**
565 * Should try install ignore rules when device comes up.
566 */
567 @Test
568 public void testInstallIgnoreRuleWhenDeviceComesUp() throws IOException {
569 ObjectMapper om = new ObjectMapper();
570 JsonNode json = om.readTree(Resources.getResource(CONFIG_FILE_PATH));
571 IgnoreDhcpConfig config = new IgnoreDhcpConfig();
572 json = json.path("apps").path(DHCP_RELAY_APP).path(IgnoreDhcpConfig.KEY);
573 config.init(APP_ID, IgnoreDhcpConfig.KEY, json, om, null);
574
575 reset(manager.cfgService, manager.flowObjectiveService, manager.deviceService);
576 expect(manager.cfgService.getConfig(APP_ID, IgnoreDhcpConfig.class))
577 .andReturn(config).anyTimes();
578
579 Device device = createNiceMock(Device.class);
580 expect(device.is(Pipeliner.class)).andReturn(true).anyTimes();
581 expect(device.id()).andReturn(DEV_1_ID).anyTimes();
582 expect(manager.deviceService.getDevice(DEV_1_ID)).andReturn(device).anyTimes();
583 DeviceEvent event = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, device);
584 Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
585 manager.flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
586 expectLastCall().times(DHCP_SELECTORS.size());
587 replay(manager.cfgService, manager.flowObjectiveService, manager.deviceService, device);
588 assertEquals(0, manager.ignoredVlans.size());
589 manager.deviceListener.event(event);
590 capturedFromDev1.getValues().forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));
591 assertEquals(1, manager.ignoredVlans.size());
592 }
593
594 /**
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000595 * Relay a DHCP6 packet without relay option
596 * Note: Should add new host to host store after dhcp ack.
597 */
598 @Test
599 public void relayDhcp6WithoutAgentInfo() {
Yi Tseng4b013202017-09-08 17:22:51 -0700600 replay(mockHostProviderService);
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000601 // send request
602 packetService.processPacket(new TestDhcp6RequestPacketContext(CLIENT_MAC,
603 VlanId.NONE,
604 CLIENT_CP,
605 INTERFACE_IP_V6.ipAddress().getIp6Address(),
606 0));
607
Yi Tseng4b013202017-09-08 17:22:51 -0700608 verify(mockHostProviderService);
609 reset(mockHostProviderService);
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000610 assertEquals(0, mockRouteStore.routes.size());
611
Yi Tseng4b013202017-09-08 17:22:51 -0700612 Capture<HostDescription> capturedHostDesc = newCapture();
613 mockHostProviderService.hostDetected(eq(HostId.hostId(CLIENT_MAC, CLIENT_VLAN)),
614 capture(capturedHostDesc), eq(false));
615 replay(mockHostProviderService);
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000616 // send reply
617 packetService.processPacket(new TestDhcp6ReplyPacketContext(CLIENT_CP, CLIENT_MAC,
618 CLIENT_VLAN,
619 INTERFACE_IP_V6.ipAddress().getIp6Address(),
620 0));
Yi Tseng4b013202017-09-08 17:22:51 -0700621 verify(mockHostProviderService);
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000622 assertEquals(0, mockRouteStore.routes.size());
623
Yi Tseng4b013202017-09-08 17:22:51 -0700624 HostDescription host = capturedHostDesc.getValue();
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000625 assertEquals(CLIENT_VLAN, host.vlan());
626 assertEquals(CLIENT_CP.deviceId(), host.location().elementId());
627 assertEquals(CLIENT_CP.port(), host.location().port());
Yi Tseng4b013202017-09-08 17:22:51 -0700628 assertEquals(1, host.ipAddress().size());
629 assertEquals(IP_FOR_CLIENT_V6, host.ipAddress().iterator().next());
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000630 }
631
632 /**
633 * Relay a DHCP6 packet with Relay Message opion (Indirectly connected host).
634 */
635 @Test
636 public void relayDhcp6WithAgentInfo() {
Yi Tseng4b013202017-09-08 17:22:51 -0700637 replay(mockHostProviderService);
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000638 // Assume outer dhcp6 relay agent exists in store already
639 // send request
640 packetService.processPacket(new TestDhcp6RequestPacketContext(CLIENT2_MAC,
641 CLIENT2_VLAN,
642 CLIENT2_CP,
643 INTERFACE_IP_V6.ipAddress().getIp6Address(),
644 1));
645
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000646 assertEquals(0, mockRouteStore.routes.size());
647
648 // send reply
649 packetService.processPacket(new TestDhcp6ReplyPacketContext(CLIENT2_CP,
650 CLIENT2_MAC,
651 CLIENT2_VLAN,
652 INTERFACE_IP_V6.ipAddress().getIp6Address(),
653 1));
654
Yi Tseng4b013202017-09-08 17:22:51 -0700655 // won't trigger the host provider service
656 verify(mockHostProviderService);
657 reset(mockHostProviderService);
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000658 assertEquals(2, mockRouteStore.routes.size()); // ipAddress and prefix
659
660 Route route = mockRouteStore.routes.get(0);
661 assertEquals(OUTER_RELAY_IP_V6, route.nextHop());
662 assertEquals(IP_FOR_CLIENT_V6.toIpPrefix(), route.prefix());
663 assertEquals(Route.Source.STATIC, route.source());
664 }
Yi Tseng4b013202017-09-08 17:22:51 -0700665
666 @Test
667 public void testDhcp4DualHome() {
668 PacketContext packetContext =
669 new TestDhcpAckPacketContext(CLIENT_DH_CP, CLIENT_MAC, CLIENT_VLAN,
670 INTERFACE_IP.ipAddress().getIp4Address(),
671 false);
672 reset(manager.hostService);
673 expect(manager.hostService.getHost(CLIENT_HOST_ID)).andReturn(EXISTS_HOST).anyTimes();
674 Capture<HostDescription> capturedHostDesc = newCapture();
675 mockHostProviderService.hostDetected(eq(CLIENT_HOST_ID), capture(capturedHostDesc), eq(false));
676 replay(mockHostProviderService, manager.hostService);
677 packetService.processPacket(packetContext);
678 verify(mockHostProviderService);
679
680 HostDescription hostDesc = capturedHostDesc.getValue();
681 Set<HostLocation> hostLocations = hostDesc.locations();
682 assertEquals(2, hostLocations.size());
683 assertTrue(hostLocations.contains(CLIENT_LOCATION));
684 assertTrue(hostLocations.contains(CLIENT_DH_LOCATION));
685 }
686
687 @Test
688 public void testDhcp6DualHome() {
689 PacketContext packetContext =
690 new TestDhcp6ReplyPacketContext(CLIENT_DH_CP, CLIENT_MAC, CLIENT_VLAN,
691 INTERFACE_IP_V6.ipAddress().getIp6Address(),
692 0);
693 reset(manager.hostService);
694 expect(manager.hostService.getHostsByIp(CLIENT_LL_IP_V6)).andReturn(ImmutableSet.of(EXISTS_HOST)).anyTimes();
695
696 // FIXME: currently DHCPv6 has a bug, we can't get correct vlan of client......
697 // XXX: The vlan relied from DHCP6 handler might be wrong, do hack here
698 HostId hostId = HostId.hostId(CLIENT_MAC, VlanId.NONE);
699 expect(manager.hostService.getHost(hostId)).andReturn(EXISTS_HOST).anyTimes();
700
701 // XXX: sometimes this will work, sometimes not
702 expect(manager.hostService.getHost(CLIENT_HOST_ID)).andReturn(EXISTS_HOST).anyTimes();
703
704 Capture<HostDescription> capturedHostDesc = newCapture();
705
706 // XXX: also a hack here
707 mockHostProviderService.hostDetected(eq(hostId), capture(capturedHostDesc), eq(false));
708 expectLastCall().anyTimes();
709
710 mockHostProviderService.hostDetected(eq(CLIENT_HOST_ID), capture(capturedHostDesc), eq(false));
711 expectLastCall().anyTimes();
712 replay(mockHostProviderService, manager.hostService);
713 packetService.processPacket(packetContext);
714 verify(mockHostProviderService);
715
716 HostDescription hostDesc = capturedHostDesc.getValue();
717 Set<HostLocation> hostLocations = hostDesc.locations();
718 assertEquals(2, hostLocations.size());
719 assertTrue(hostLocations.contains(CLIENT_LOCATION));
720 assertTrue(hostLocations.contains(CLIENT_DH_LOCATION));
721 }
722
Yi Tsenge72fbb52017-08-02 15:03:31 -0700723 private static class MockDefaultDhcpRelayConfig extends DefaultDhcpRelayConfig {
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700724 @Override
725 public boolean isValid() {
726 return true;
727 }
728
729 @Override
Yi Tsenge72fbb52017-08-02 15:03:31 -0700730 public List<DhcpServerConfig> dhcpServerConfigs() {
Yi Tseng4fa05832017-08-17 13:08:31 -0700731 return ImmutableList.of(new MockDhcpServerConfig(null));
Yi Tsenge72fbb52017-08-02 15:03:31 -0700732 }
733 }
734
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000735 private static class MockIndirectDhcpRelayConfig extends IndirectDhcpRelayConfig {
736 @Override
737 public boolean isValid() {
738 return true;
739 }
740
741 @Override
742 public List<DhcpServerConfig> dhcpServerConfigs() {
743 return ImmutableList.of(new MockDhcpServerConfig(null));
744 }
745 }
746
Yi Tsenge72fbb52017-08-02 15:03:31 -0700747 private static class MockDhcpServerConfig extends DhcpServerConfig {
Yi Tseng4fa05832017-08-17 13:08:31 -0700748 Ip4Address relayAgentIp;
749
750 /**
751 * Create mocked version DHCP server config.
752 *
753 * @param relayAgentIp the relay agent Ip config; null if we don't need it
754 */
755 public MockDhcpServerConfig(Ip4Address relayAgentIp) {
756 this.relayAgentIp = relayAgentIp;
757 }
758
759 @Override
760 public Optional<Ip4Address> getRelayAgentIp4() {
761 return Optional.ofNullable(relayAgentIp);
762 }
763
Yi Tsenge72fbb52017-08-02 15:03:31 -0700764 @Override
765 public Optional<ConnectPoint> getDhcpServerConnectPoint() {
766 return Optional.of(SERVER_CONNECT_POINT);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700767 }
768
Yi Tsenge72fbb52017-08-02 15:03:31 -0700769 @Override
770 public Optional<Ip4Address> getDhcpServerIp4() {
771 return Optional.of(SERVER_IP);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700772 }
Kalhee Kim1b5094f2017-09-05 19:05:06 +0000773
774 @Override
775 public Optional<Ip4Address> getDhcpGatewayIp4() {
776 return Optional.of(GATEWAY_IP);
777 }
778
779 @Override
780 public Optional<Ip6Address> getDhcpServerIp6() {
781 return Optional.of(SERVER_IP_V6);
782 }
783
784 @Override
785 public Optional<Ip6Address> getDhcpGatewayIp6() {
786 return Optional.of(GATEWAY_IP_V6);
787 }
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700788 }
789
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700790 private class MockRouteStore extends RouteStoreAdapter {
791 private List<Route> routes = Lists.newArrayList();
792
793 @Override
794 public void updateRoute(Route route) {
795 routes.add(route);
796 }
797 }
798
799 private class MockInterfaceService extends InterfaceServiceAdapter {
800
801 @Override
802 public Set<Interface> getInterfaces() {
803 return INTERFACES;
804 }
805
806 @Override
807 public Set<Interface> getInterfacesByIp(IpAddress ip) {
808 return INTERFACES.stream()
809 .filter(iface -> {
810 return iface.ipAddressesList().stream()
811 .anyMatch(ifaceIp -> ifaceIp.ipAddress().equals(ip));
812 })
813 .collect(Collectors.toSet());
814 }
815
816 @Override
817 public Set<Interface> getInterfacesByPort(ConnectPoint port) {
818 return INTERFACES.stream()
819 .filter(iface -> iface.connectPoint().equals(port))
820 .collect(Collectors.toSet());
821 }
822 }
823
824 private class MockDhcpRelayStore implements DhcpRelayStore {
825 StoreDelegate<DhcpRelayStoreEvent> delegate;
826 private Map<HostId, DhcpRecord> records = Maps.newHashMap();
827
828 @Override
829 public void updateDhcpRecord(HostId hostId, DhcpRecord dhcpRecord) {
830 records.put(hostId, dhcpRecord);
831 DhcpRelayStoreEvent event = new DhcpRelayStoreEvent(DhcpRelayStoreEvent.Type.UPDATED,
832 dhcpRecord);
833 if (delegate != null) {
834 delegate.notify(event);
835 }
836 }
837
838 @Override
839 public Optional<DhcpRecord> getDhcpRecord(HostId hostId) {
840 return Optional.ofNullable(records.get(hostId));
841 }
842
843 @Override
844 public Collection<DhcpRecord> getDhcpRecords() {
845 return records.values();
846 }
847
848 @Override
849 public Optional<DhcpRecord> removeDhcpRecord(HostId hostId) {
850 DhcpRecord dhcpRecord = records.remove(hostId);
851 if (dhcpRecord != null) {
852 DhcpRelayStoreEvent event = new DhcpRelayStoreEvent(DhcpRelayStoreEvent.Type.REMOVED,
853 dhcpRecord);
854 if (delegate != null) {
855 delegate.notify(event);
856 }
857 }
858 return Optional.ofNullable(dhcpRecord);
859 }
860
861 @Override
862 public void setDelegate(StoreDelegate<DhcpRelayStoreEvent> delegate) {
863 this.delegate = delegate;
864 }
865
866 @Override
867 public void unsetDelegate(StoreDelegate<DhcpRelayStoreEvent> delegate) {
868 this.delegate = null;
869 }
870
871 @Override
872 public boolean hasDelegate() {
873 return this.delegate != null;
874 }
875 }
876
877 private class MockPacketService extends PacketServiceAdapter {
878 Set<PacketProcessor> packetProcessors = Sets.newHashSet();
Ray Milkeybd52a052017-08-23 15:23:50 -0700879 OutboundPacket emittedPacket;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700880
881 @Override
882 public void addProcessor(PacketProcessor processor, int priority) {
883 packetProcessors.add(processor);
884 }
885
886 public void processPacket(PacketContext packetContext) {
887 packetProcessors.forEach(p -> p.process(packetContext));
888 }
889
890 @Override
891 public void emit(OutboundPacket packet) {
Ray Milkeybd52a052017-08-23 15:23:50 -0700892 this.emittedPacket = packet;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700893 }
894 }
895
896
897
898 /**
899 * Generates DHCP REQUEST packet.
900 */
901 private class TestDhcpRequestPacketContext extends PacketContextAdapter {
902
903
904 private InboundPacket inPacket;
905
906 public TestDhcpRequestPacketContext(MacAddress clientMac, VlanId vlanId,
907 ConnectPoint clientCp,
908 Ip4Address clientGwAddr,
909 boolean withNonOnosRelayInfo) {
910 super(0, null, null, false);
911 byte[] dhcpMsgType = new byte[1];
912 dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPREQUEST.getValue();
913
914 DhcpOption dhcpOption = new DhcpOption();
915 dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
916 dhcpOption.setData(dhcpMsgType);
917 dhcpOption.setLength((byte) 1);
918 DhcpOption endOption = new DhcpOption();
919 endOption.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
920
921 DHCP dhcp = new DHCP();
922 dhcp.setHardwareType(DHCP.HWTYPE_ETHERNET);
923 dhcp.setHardwareAddressLength((byte) 6);
924 dhcp.setClientHardwareAddress(clientMac.toBytes());
925 if (withNonOnosRelayInfo) {
926 DhcpRelayAgentOption relayOption = new DhcpRelayAgentOption();
927 DhcpOption circuitIdOption = new DhcpOption();
928 CircuitId circuitId = new CircuitId("Custom option", VlanId.NONE);
929 byte[] cid = circuitId.serialize();
930 circuitIdOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
931 circuitIdOption.setLength((byte) cid.length);
932 circuitIdOption.setData(cid);
933 relayOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
934 relayOption.addSubOption(circuitIdOption);
935 dhcp.setOptions(ImmutableList.of(dhcpOption, relayOption, endOption));
936 dhcp.setGatewayIPAddress(OUTER_RELAY_IP.getIp4Address().toInt());
937 } else {
938 dhcp.setOptions(ImmutableList.of(dhcpOption, endOption));
939 }
940
941
942 UDP udp = new UDP();
943 udp.setPayload(dhcp);
944 udp.setSourcePort(UDP.DHCP_CLIENT_PORT);
945 udp.setDestinationPort(UDP.DHCP_SERVER_PORT);
946
947 IPv4 ipv4 = new IPv4();
948 ipv4.setPayload(udp);
949 ipv4.setDestinationAddress(SERVER_IP.toInt());
950 ipv4.setSourceAddress(clientGwAddr.toInt());
951
952 Ethernet eth = new Ethernet();
953 if (withNonOnosRelayInfo) {
954 eth.setEtherType(Ethernet.TYPE_IPV4)
955 .setVlanID(vlanId.toShort())
956 .setSourceMACAddress(OUTER_RELAY_MAC)
957 .setDestinationMACAddress(MacAddress.BROADCAST)
958 .setPayload(ipv4);
959 } else {
960 eth.setEtherType(Ethernet.TYPE_IPV4)
961 .setVlanID(vlanId.toShort())
962 .setSourceMACAddress(clientMac)
963 .setDestinationMACAddress(MacAddress.BROADCAST)
964 .setPayload(ipv4);
965 }
966
967 this.inPacket = new DefaultInboundPacket(clientCp, eth,
968 ByteBuffer.wrap(eth.serialize()));
969 }
970
971 @Override
972 public InboundPacket inPacket() {
973 return this.inPacket;
974 }
975 }
976
977 /**
978 * Generates DHCP ACK packet.
979 */
980 private class TestDhcpAckPacketContext extends PacketContextAdapter {
981 private InboundPacket inPacket;
982
983 public TestDhcpAckPacketContext(ConnectPoint clientCp, MacAddress clientMac,
984 VlanId clientVlan, Ip4Address clientGwAddr,
985 boolean withNonOnosRelayInfo) {
986 super(0, null, null, false);
987
988 byte[] dhcpMsgType = new byte[1];
989 dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPACK.getValue();
990
991 DhcpOption dhcpOption = new DhcpOption();
992 dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
993 dhcpOption.setData(dhcpMsgType);
994 dhcpOption.setLength((byte) 1);
995
996 DhcpOption endOption = new DhcpOption();
997 endOption.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
998
999 DHCP dhcp = new DHCP();
1000 if (withNonOnosRelayInfo) {
1001 DhcpRelayAgentOption relayOption = new DhcpRelayAgentOption();
1002 DhcpOption circuitIdOption = new DhcpOption();
Yi Tseng2cf59912017-08-24 14:47:34 -07001003 String circuitId = NON_ONOS_CID;
1004 byte[] cid = circuitId.getBytes(Charsets.US_ASCII);
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001005 circuitIdOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
1006 circuitIdOption.setLength((byte) cid.length);
1007 circuitIdOption.setData(cid);
1008 relayOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
1009 relayOption.addSubOption(circuitIdOption);
1010 dhcp.setOptions(ImmutableList.of(dhcpOption, relayOption, endOption));
1011 dhcp.setGatewayIPAddress(OUTER_RELAY_IP.getIp4Address().toInt());
1012 } else {
1013 CircuitId cid = new CircuitId(clientCp.toString(), clientVlan);
1014 byte[] circuitId = cid.serialize();
1015 DhcpOption circuitIdSubOption = new DhcpOption();
1016 circuitIdSubOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
1017 circuitIdSubOption.setData(circuitId);
1018 circuitIdSubOption.setLength((byte) circuitId.length);
1019
1020 DhcpRelayAgentOption relayInfoOption = new DhcpRelayAgentOption();
1021 relayInfoOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
1022 relayInfoOption.addSubOption(circuitIdSubOption);
1023 dhcp.setOptions(ImmutableList.of(dhcpOption, relayInfoOption, endOption));
1024 dhcp.setGatewayIPAddress(clientGwAddr.toInt());
1025 }
1026 dhcp.setHardwareType(DHCP.HWTYPE_ETHERNET);
1027 dhcp.setHardwareAddressLength((byte) 6);
1028 dhcp.setClientHardwareAddress(clientMac.toBytes());
1029 dhcp.setYourIPAddress(IP_FOR_CLIENT.toInt());
1030
1031 UDP udp = new UDP();
1032 udp.setPayload(dhcp);
1033 udp.setSourcePort(UDP.DHCP_SERVER_PORT);
1034 udp.setDestinationPort(UDP.DHCP_CLIENT_PORT);
1035 IPv4 ipv4 = new IPv4();
1036 ipv4.setPayload(udp);
1037 ipv4.setDestinationAddress(IP_FOR_CLIENT.toString());
1038 ipv4.setSourceAddress(SERVER_IP.toString());
1039 Ethernet eth = new Ethernet();
1040 if (withNonOnosRelayInfo) {
1041 eth.setEtherType(Ethernet.TYPE_IPV4)
1042 .setVlanID(SERVER_VLAN.toShort())
1043 .setSourceMACAddress(SERVER_MAC)
1044 .setDestinationMACAddress(OUTER_RELAY_MAC)
1045 .setPayload(ipv4);
1046 } else {
1047 eth.setEtherType(Ethernet.TYPE_IPV4)
1048 .setVlanID(SERVER_VLAN.toShort())
1049 .setSourceMACAddress(SERVER_MAC)
1050 .setDestinationMACAddress(CLIENT_MAC)
1051 .setPayload(ipv4);
1052 }
1053
1054 this.inPacket = new DefaultInboundPacket(SERVER_CONNECT_POINT, eth,
1055 ByteBuffer.wrap(eth.serialize()));
1056
1057 }
1058
1059 @Override
1060 public InboundPacket inPacket() {
1061 return this.inPacket;
1062 }
1063 }
1064
1065 private class TestArpRequestPacketContext extends PacketContextAdapter {
1066 private InboundPacket inPacket;
1067
1068 public TestArpRequestPacketContext(Interface fromInterface) {
1069 super(0, null, null, false);
1070 ARP arp = new ARP();
1071 arp.setOpCode(ARP.OP_REQUEST);
1072
1073 IpAddress targetIp = fromInterface.ipAddressesList().get(0).ipAddress();
1074 arp.setTargetProtocolAddress(targetIp.toOctets());
1075 arp.setTargetHardwareAddress(MacAddress.BROADCAST.toBytes());
1076 arp.setSenderHardwareAddress(MacAddress.NONE.toBytes());
1077 arp.setSenderProtocolAddress(Ip4Address.valueOf(0).toOctets());
1078 arp.setHardwareAddressLength((byte) MacAddress.MAC_ADDRESS_LENGTH);
1079 Ethernet eth = new Ethernet();
1080 eth.setEtherType(Ethernet.TYPE_ARP);
1081 eth.setSourceMACAddress(MacAddress.NONE);
1082 eth.setDestinationMACAddress(MacAddress.BROADCAST);
1083 eth.setVlanID(fromInterface.vlan().toShort());
1084 eth.setPayload(arp);
1085
1086 this.inPacket = new DefaultInboundPacket(fromInterface.connectPoint(), eth,
1087 ByteBuffer.wrap(eth.serialize()));
1088 }
1089
1090 @Override
1091 public InboundPacket inPacket() {
1092 return this.inPacket;
1093 }
1094 }
Kalhee Kim1b5094f2017-09-05 19:05:06 +00001095
1096 /**
1097 * Generates DHCP6 REQUEST packet.
1098 */
1099 private void buildDhcp6Packet(DHCP6 dhcp6, byte msgType, Ip6Address ip6Addr, IpPrefix prefix) {
1100
1101 // build address option
1102 Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
1103 iaAddressOption.setCode(DHCP6.OptionCode.IAADDR.value());
1104 iaAddressOption.setIp6Address(ip6Addr);
1105 iaAddressOption.setPreferredLifetime(3600);
1106 iaAddressOption.setValidLifetime(1200);
1107 iaAddressOption.setLength((short) Dhcp6IaAddressOption.DEFAULT_LEN);
1108
1109 Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
1110 iaNaOption.setCode(DHCP6.OptionCode.IA_NA.value());
1111 iaNaOption.setIaId(0);
1112 iaNaOption.setT1(302400);
1113 iaNaOption.setT2(483840);
1114 List<Dhcp6Option> iaNaSubOptions = new ArrayList<Dhcp6Option>();
1115 iaNaSubOptions.add(iaAddressOption);
1116 iaNaOption.setOptions(iaNaSubOptions);
1117 iaNaOption.setLength((short) (Dhcp6IaNaOption.DEFAULT_LEN + iaAddressOption.getLength()));
1118
1119 // build prefix option
1120 Dhcp6IaPrefixOption iaPrefixOption = new Dhcp6IaPrefixOption();
1121 iaPrefixOption.setCode(DHCP6.OptionCode.IAPREFIX.value());
1122 iaPrefixOption.setIp6Prefix(prefix.address().getIp6Address());
1123 iaPrefixOption.setPrefixLength((byte) prefix.prefixLength());
1124 iaPrefixOption.setPreferredLifetime(3601);
1125 iaPrefixOption.setValidLifetime(1201);
1126 iaPrefixOption.setLength((short) Dhcp6IaPrefixOption.DEFAULT_LEN);
1127
1128 Dhcp6IaPdOption iaPdOption = new Dhcp6IaPdOption();
1129 iaPdOption.setCode(DHCP6.OptionCode.IA_PD.value());
1130 iaPdOption.setIaId(0);
1131 iaPdOption.setT1(302401);
1132 iaPdOption.setT2(483841);
1133 List<Dhcp6Option> iaPdSubOptions = new ArrayList<Dhcp6Option>();
1134 iaPdSubOptions.add(iaPrefixOption);
1135 iaPdOption.setOptions(iaPdSubOptions);
1136 iaPdOption.setLength((short) (Dhcp6IaPdOption.DEFAULT_LEN + iaPrefixOption.getLength()));
1137
1138 dhcp6.setMsgType(msgType);
1139 List<Dhcp6Option> dhcp6Options = new ArrayList<Dhcp6Option>();
1140 dhcp6Options.add(iaNaOption);
1141 dhcp6Options.add(iaPdOption);
1142 dhcp6.setOptions(dhcp6Options);
1143
1144 }
1145
1146 private void buildRelayMsg(DHCP6 dhcp6Relay, byte msgType, Ip6Address linkAddr,
1147 Ip6Address peerAddr, byte hop, byte[] interfaceIdBytes,
1148 DHCP6 dhcp6Payload) {
1149
1150 dhcp6Relay.setMsgType(msgType);
1151
1152 dhcp6Relay.setLinkAddress(linkAddr.toOctets());
1153 dhcp6Relay.setPeerAddress(peerAddr.toOctets());
1154 dhcp6Relay.setHopCount(hop);
1155 List<Dhcp6Option> options = new ArrayList<Dhcp6Option>();
1156
1157 // interfaceId option
1158 Dhcp6Option interfaceId = new Dhcp6Option();
1159 interfaceId.setCode(DHCP6.OptionCode.INTERFACE_ID.value());
1160
1161
1162 interfaceId.setData(interfaceIdBytes);
1163 interfaceId.setLength((short) interfaceIdBytes.length);
1164 Dhcp6InterfaceIdOption interfaceIdOption = new Dhcp6InterfaceIdOption(interfaceId);
1165 ByteBuffer bb = ByteBuffer.wrap(interfaceIdBytes);
1166
1167 byte[] macAddr = new byte[MacAddress.MAC_ADDRESS_LENGTH];
1168 byte[] port = new byte[21];
1169 bb.get(macAddr);
1170 bb.get(); // separator
1171 bb.get(port);
1172 interfaceIdOption.setMacAddress(MacAddress.valueOf(macAddr));
1173 interfaceIdOption.setInPort(port);
1174
1175 options.add(interfaceIdOption);
1176
1177 // relay message option
1178 Dhcp6Option relayMsgOption = new Dhcp6Option();
1179 relayMsgOption.setCode(DHCP6.OptionCode.RELAY_MSG.value());
1180 byte[] dhcp6PayloadByte = dhcp6Payload.serialize();
1181 relayMsgOption.setLength((short) dhcp6PayloadByte.length);
1182 relayMsgOption.setPayload(dhcp6Payload);
1183 Dhcp6RelayOption relayOpt = new Dhcp6RelayOption(relayMsgOption);
1184
1185 options.add(relayOpt);
1186
1187 dhcp6Relay.setOptions(options);
1188 }
1189 private byte[] buildInterfaceId(MacAddress clientMac, ConnectPoint clientCp) {
1190 String inPortString = "-" + clientCp.toString();
1191 byte[] clientSoureMacBytes = clientMac.toBytes();
1192 byte[] inPortStringBytes = inPortString.getBytes();
1193 byte[] interfaceIdBytes = new byte[clientSoureMacBytes.length + inPortStringBytes.length];
1194
1195 System.arraycopy(clientSoureMacBytes, 0, interfaceIdBytes, 0, clientSoureMacBytes.length);
1196 System.arraycopy(inPortStringBytes, 0, interfaceIdBytes, clientSoureMacBytes.length, inPortStringBytes.length);
1197
1198 return interfaceIdBytes;
1199 }
1200
1201 private class TestDhcp6RequestPacketContext extends PacketContextAdapter {
1202
1203
1204 private InboundPacket inPacket;
1205
1206
1207 public TestDhcp6RequestPacketContext(MacAddress clientMac, VlanId vlanId,
1208 ConnectPoint clientCp,
1209 Ip6Address clientGwAddr,
1210 int relayLevel) {
1211 super(0, null, null, false);
1212
1213 DHCP6 dhcp6 = new DHCP6();
1214 if (relayLevel > 0) {
1215 DHCP6 dhcp6Payload = new DHCP6();
1216 buildDhcp6Packet(dhcp6Payload, DHCP6.MsgType.REQUEST.value(),
1217 IP_FOR_CLIENT_V6,
1218 PREFIX_FOR_ZERO);
1219 DHCP6 dhcp6Parent = null;
1220 DHCP6 dhcp6Child = dhcp6Payload;
1221 for (int i = 0; i < relayLevel; i++) {
1222 dhcp6Parent = new DHCP6();
1223 byte[] interfaceId = buildInterfaceId(clientMac, clientCp);
1224 buildRelayMsg(dhcp6Parent, DHCP6.MsgType.RELAY_FORW.value(),
1225 INTERFACE_IP_V6.ipAddress().getIp6Address(),
1226 OUTER_RELAY_IP_V6,
1227 (byte) (relayLevel - 1), interfaceId,
1228 dhcp6Child);
1229 dhcp6Child = dhcp6Parent;
1230 }
1231 if (dhcp6Parent != null) {
1232 dhcp6 = dhcp6Parent;
1233 }
1234 } else {
1235 buildDhcp6Packet(dhcp6, DHCP6.MsgType.REQUEST.value(),
1236 IP_FOR_CLIENT_V6,
1237 PREFIX_FOR_ZERO);
1238 }
1239
1240 UDP udp = new UDP();
1241 udp.setPayload(dhcp6);
1242 if (relayLevel > 0) {
1243 udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
1244 } else {
1245 udp.setSourcePort(UDP.DHCP_V6_CLIENT_PORT);
1246 }
1247 udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
1248
1249 IPv6 ipv6 = new IPv6();
1250 ipv6.setPayload(udp);
1251 ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
1252 ipv6.setDestinationAddress(SERVER_IP_V6_MCAST.toOctets());
1253 ipv6.setSourceAddress(clientGwAddr.toOctets());
1254
1255 Ethernet eth = new Ethernet();
1256 if (relayLevel > 0) {
1257 eth.setEtherType(Ethernet.TYPE_IPV6)
1258 .setVlanID(vlanId.toShort())
1259 .setSourceMACAddress(OUTER_RELAY_MAC)
1260 .setDestinationMACAddress(MacAddress.valueOf("33:33:00:01:00:02"))
1261 .setPayload(ipv6);
1262 } else {
1263 eth.setEtherType(Ethernet.TYPE_IPV6)
1264 .setVlanID(vlanId.toShort())
1265 .setSourceMACAddress(clientMac)
1266 .setDestinationMACAddress(MacAddress.valueOf("33:33:00:01:00:02"))
1267 .setPayload(ipv6);
1268 }
1269 this.inPacket = new DefaultInboundPacket(clientCp, eth,
1270 ByteBuffer.wrap(eth.serialize()));
1271 }
1272
1273 @Override
1274 public InboundPacket inPacket() {
1275 return this.inPacket;
1276 }
1277 }
1278
1279 /**
1280 * Generates DHCP6 REPLY packet.
1281 */
1282
1283 private class TestDhcp6ReplyPacketContext extends PacketContextAdapter {
1284 private InboundPacket inPacket;
1285
1286 public TestDhcp6ReplyPacketContext(ConnectPoint clientCp, MacAddress clientMac,
1287 VlanId clientVlan, Ip6Address clientGwAddr,
1288 int relayLevel) {
1289 super(0, null, null, false);
1290
1291
1292 DHCP6 dhcp6Payload = new DHCP6();
1293 buildDhcp6Packet(dhcp6Payload, DHCP6.MsgType.REPLY.value(),
1294 IP_FOR_CLIENT_V6,
1295 PREFIX_FOR_CLIENT_V6);
1296 byte[] interfaceId = buildInterfaceId(clientMac, clientCp);
1297 DHCP6 dhcp6 = new DHCP6();
1298 buildRelayMsg(dhcp6, DHCP6.MsgType.RELAY_REPL.value(),
Yi Tseng4b013202017-09-08 17:22:51 -07001299 INTERFACE_IP_V6.ipAddress().getIp6Address(),
1300 CLIENT_LL_IP_V6,
1301 (byte) 0, interfaceId,
1302 dhcp6Payload);
Kalhee Kim1b5094f2017-09-05 19:05:06 +00001303
1304 DHCP6 dhcp6Parent = null;
1305 DHCP6 dhcp6Child = dhcp6;
1306 for (int i = 0; i < relayLevel; i++) { // relayLevel 0 : no relay
1307 dhcp6Parent = new DHCP6();
1308
1309 buildRelayMsg(dhcp6Parent, DHCP6.MsgType.RELAY_REPL.value(),
1310 INTERFACE_IP_V6.ipAddress().getIp6Address(),
1311 OUTER_RELAY_IP_V6,
1312 (byte) relayLevel, interfaceId,
1313 dhcp6Child);
1314
1315 dhcp6Child = dhcp6Parent;
1316 }
1317 if (dhcp6Parent != null) {
1318 dhcp6 = dhcp6Parent;
1319 }
1320
1321
1322 UDP udp = new UDP();
1323 udp.setPayload(dhcp6);
1324 udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
1325 udp.setDestinationPort(UDP.DHCP_V6_CLIENT_PORT);
1326 IPv6 ipv6 = new IPv6();
1327 ipv6.setPayload(udp);
1328 ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
1329 ipv6.setDestinationAddress(IP_FOR_CLIENT_V6.toOctets());
1330 ipv6.setSourceAddress(SERVER_IP_V6.toOctets());
1331 Ethernet eth = new Ethernet();
1332 if (relayLevel > 0) {
1333 eth.setEtherType(Ethernet.TYPE_IPV6)
1334 .setVlanID(SERVER_VLAN.toShort())
1335 .setSourceMACAddress(SERVER_MAC)
1336 .setDestinationMACAddress(OUTER_RELAY_MAC)
1337 .setPayload(ipv6);
1338 } else {
1339 eth.setEtherType(Ethernet.TYPE_IPV6)
1340 .setVlanID(SERVER_VLAN.toShort())
1341 .setSourceMACAddress(SERVER_MAC)
1342 .setDestinationMACAddress(CLIENT_MAC)
1343 .setPayload(ipv6);
1344 }
1345
1346 this.inPacket = new DefaultInboundPacket(SERVER_CONNECT_POINT, eth,
1347 ByteBuffer.wrap(eth.serialize()));
1348
1349 }
1350
1351 @Override
1352 public InboundPacket inPacket() {
1353 return this.inPacket;
1354 }
1355 }
1356
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001357}