blob: ba943f937e90cf1a94f92c2c41a7c00b13b2f94e [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 Tseng51f1be92017-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 Tseng525ff402017-10-23 19:39:39 -070025import com.google.common.collect.Streams;
Yi Tseng51f1be92017-09-01 17:24:57 -070026import com.google.common.io.Resources;
Yi Tseng440e2b72017-08-24 14:47:34 -070027import org.apache.commons.io.Charsets;
Yi Tseng25bfe372017-11-03 16:27:32 -070028import org.apache.commons.lang3.tuple.Pair;
Yi Tseng51f1be92017-09-01 17:24:57 -070029import org.easymock.Capture;
30import org.easymock.CaptureType;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070031import org.easymock.EasyMock;
32import org.junit.After;
33import org.junit.Before;
34import org.junit.Test;
35import org.onlab.packet.ARP;
36import org.onlab.packet.DHCP;
Yi Tseng3df7f9d2017-08-17 13:08:31 -070037import org.onlab.packet.DeserializationException;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070038import org.onlab.packet.Ethernet;
39import org.onlab.packet.IPv4;
40import org.onlab.packet.Ip4Address;
Kalhee Kim45fede42017-09-05 19:05:06 +000041import org.onlab.packet.Ip6Address;
42import org.onlab.packet.IpPrefix;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070043import org.onlab.packet.IpAddress;
44import org.onlab.packet.MacAddress;
45import org.onlab.packet.UDP;
46import org.onlab.packet.VlanId;
47import org.onlab.packet.dhcp.CircuitId;
48import org.onlab.packet.dhcp.DhcpOption;
49import org.onlab.packet.dhcp.DhcpRelayAgentOption;
Kalhee Kim45fede42017-09-05 19:05:06 +000050import org.onlab.packet.dhcp.Dhcp6InterfaceIdOption;
51import org.onlab.packet.dhcp.Dhcp6RelayOption;
52import org.onlab.packet.dhcp.Dhcp6IaNaOption;
53import org.onlab.packet.dhcp.Dhcp6IaPdOption;
54import org.onlab.packet.dhcp.Dhcp6IaAddressOption;
55import org.onlab.packet.dhcp.Dhcp6IaPrefixOption;
56import org.onlab.packet.dhcp.Dhcp6Option;
Kalhee Kim495c9b22017-11-07 16:32:09 +000057import org.onlab.packet.dhcp.Dhcp6ClientIdOption;
58import org.onlab.packet.dhcp.Dhcp6Duid;
Kalhee Kimd94ceea2017-11-29 19:03:02 +000059import org.onosproject.dhcprelay.store.DhcpRelayStore;
60import org.onosproject.dhcprelay.store.DhcpRecord;
61import org.onosproject.dhcprelay.store.DhcpRelayStoreEvent;
62import org.onosproject.dhcprelay.store.DhcpRelayCounters;
63import org.onosproject.dhcprelay.store.DhcpRelayCountersStore;
Kalhee Kim45fede42017-09-05 19:05:06 +000064import org.onosproject.net.ConnectPoint;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070065import org.onosproject.TestApplicationId;
66import org.onosproject.cfg.ComponentConfigService;
67import org.onosproject.core.ApplicationId;
68import org.onosproject.core.CoreService;
Yi Tseng483ac6f2017-08-02 15:03:31 -070069import org.onosproject.dhcprelay.config.DefaultDhcpRelayConfig;
70import org.onosproject.dhcprelay.config.DhcpServerConfig;
Yi Tseng51f1be92017-09-01 17:24:57 -070071import org.onosproject.dhcprelay.config.IgnoreDhcpConfig;
Yi Tseng483ac6f2017-08-02 15:03:31 -070072import org.onosproject.dhcprelay.config.IndirectDhcpRelayConfig;
Yi Tseng127ffe52017-09-12 15:55:17 -070073import org.onosproject.net.Device;
Yi Tseng51f1be92017-09-01 17:24:57 -070074import org.onosproject.net.DeviceId;
Yi Tseng127ffe52017-09-12 15:55:17 -070075import org.onosproject.net.behaviour.Pipeliner;
76import org.onosproject.net.device.DeviceEvent;
77import org.onosproject.net.device.DeviceService;
Yi Tseng51f1be92017-09-01 17:24:57 -070078import org.onosproject.net.flow.DefaultTrafficSelector;
79import org.onosproject.net.flow.DefaultTrafficTreatment;
80import org.onosproject.net.flow.TrafficSelector;
Yi Tseng51f1be92017-09-01 17:24:57 -070081import org.onosproject.net.flowobjective.FlowObjectiveService;
82import org.onosproject.net.flowobjective.ForwardingObjective;
83import org.onosproject.net.flowobjective.Objective;
Yi Tsengaa417a62017-09-08 17:22:51 -070084import org.onosproject.net.host.HostProviderService;
Ray Milkeyfacf2862017-08-03 11:58:29 -070085import org.onosproject.net.intf.Interface;
86import org.onosproject.net.intf.InterfaceServiceAdapter;
Yi Tseng51f1be92017-09-01 17:24:57 -070087import org.onosproject.net.packet.PacketPriority;
Ray Milkey69ec8712017-08-08 13:00:43 -070088import org.onosproject.routeservice.Route;
89import org.onosproject.routeservice.RouteStoreAdapter;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070090import org.onosproject.net.DefaultHost;
91import org.onosproject.net.Host;
92import org.onosproject.net.HostId;
93import org.onosproject.net.HostLocation;
94import org.onosproject.net.config.NetworkConfigRegistry;
95import org.onosproject.net.host.HostDescription;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070096import org.onosproject.net.host.HostService;
Yi Tseng7a38f9a2017-06-09 14:36:40 -070097import org.onosproject.net.host.InterfaceIpAddress;
98import org.onosproject.net.packet.DefaultInboundPacket;
99import org.onosproject.net.packet.InboundPacket;
100import org.onosproject.net.packet.OutboundPacket;
101import org.onosproject.net.packet.PacketContext;
102import org.onosproject.net.packet.PacketContextAdapter;
103import org.onosproject.net.packet.PacketProcessor;
104import org.onosproject.net.packet.PacketServiceAdapter;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700105import org.onosproject.store.StoreDelegate;
Kalhee Kimba366062017-11-07 16:32:09 +0000106
107
108
109
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700110import org.osgi.service.component.ComponentContext;
Kalhee Kim45fede42017-09-05 19:05:06 +0000111import org.onlab.packet.DHCP6;
112import org.onlab.packet.IPv6;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700113
Yi Tseng127ffe52017-09-12 15:55:17 -0700114import java.io.IOException;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700115import java.nio.ByteBuffer;
116import java.util.Collection;
117import java.util.Dictionary;
118import java.util.List;
Kalhee Kim45fede42017-09-05 19:05:06 +0000119import java.util.ArrayList;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700120import java.util.Map;
121import java.util.Optional;
122import java.util.Set;
123import java.util.stream.Collectors;
124
125import static org.easymock.EasyMock.*;
126import static org.junit.Assert.*;
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000127import static org.onlab.junit.TestTools.assertAfter;
Yi Tseng51f1be92017-09-01 17:24:57 -0700128import static org.onosproject.dhcprelay.DhcpRelayManager.DHCP_RELAY_APP;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700129
130public class DhcpRelayManagerTest {
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000131 private static final int EVENT_PROCESSING_MS = 1000;
Kalhee Kima0b8f652017-10-18 22:00:30 +0000132 private static final short VLAN_LEN = 2;
133 private static final short SEPARATOR_LEN = 1;
Yi Tseng51f1be92017-09-01 17:24:57 -0700134 private static final String CONFIG_FILE_PATH = "dhcp-relay.json";
135 private static final DeviceId DEV_1_ID = DeviceId.deviceId("of:0000000000000001");
136 private static final DeviceId DEV_2_ID = DeviceId.deviceId("of:0000000000000002");
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700137 // Ip address for interfaces
138 private static final InterfaceIpAddress INTERFACE_IP = InterfaceIpAddress.valueOf("10.0.3.254/32");
Kalhee Kim45fede42017-09-05 19:05:06 +0000139 private static final InterfaceIpAddress INTERFACE_IP_V6 = InterfaceIpAddress.valueOf("2001:db8:1::254/128");
140 private static final List<InterfaceIpAddress> INTERFACE_IPS = ImmutableList.of(INTERFACE_IP, INTERFACE_IP_V6);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700141
142 // DHCP client (will send without option 82)
143 private static final Ip4Address IP_FOR_CLIENT = Ip4Address.valueOf("10.0.0.1");
Kalhee Kim45fede42017-09-05 19:05:06 +0000144 private static final Ip6Address IP_FOR_CLIENT_V6 = Ip6Address.valueOf("2001:db8:1::110");
145 private static final IpPrefix PREFIX_FOR_CLIENT_V6 = IpPrefix.valueOf("2001:db8:10::/56");
146 private static final IpPrefix PREFIX_FOR_ZERO = IpPrefix.valueOf("::/0");
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700147 private static final MacAddress CLIENT_MAC = MacAddress.valueOf("00:00:00:00:00:01");
148 private static final VlanId CLIENT_VLAN = VlanId.vlanId("100");
149 private static final ConnectPoint CLIENT_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/1");
150 private static final MacAddress CLIENT_IFACE_MAC = MacAddress.valueOf("00:00:00:00:11:01");
Yi Tsengaa417a62017-09-08 17:22:51 -0700151 private static final HostLocation CLIENT_LOCATION = new HostLocation(CLIENT_CP, 0);
152 private static final HostId CLIENT_HOST_ID = HostId.hostId(CLIENT_MAC, CLIENT_VLAN);
153 private static final Ip6Address CLIENT_LL_IP_V6 = Ip6Address.valueOf("fe80::200:00ff:fe00:0001");
Charles Chand988c282017-09-12 17:09:32 -0700154 private static final Host EXISTS_HOST = new DefaultHost(Dhcp4HandlerImpl.PROVIDER_ID,
Yi Tsengaa417a62017-09-08 17:22:51 -0700155 CLIENT_HOST_ID, CLIENT_MAC, CLIENT_VLAN,
156 CLIENT_LOCATION, ImmutableSet.of(CLIENT_LL_IP_V6));
Yi Tseng4025a102017-09-30 11:35:42 +0800157 private static final Interface CLIENT_INTERFACE = createInterface("C1",
158 CLIENT_CP,
159 INTERFACE_IPS,
160 CLIENT_IFACE_MAC,
161 CLIENT_VLAN,
162 null);
163
164
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700165
Yi Tsengaa417a62017-09-08 17:22:51 -0700166 // Dual homing test
167 private static final ConnectPoint CLIENT_DH_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/3");
168 private static final HostLocation CLIENT_DH_LOCATION = new HostLocation(CLIENT_DH_CP, 0);
Yi Tseng4025a102017-09-30 11:35:42 +0800169 private static final Interface CLIENT_DH_INTERFACE = createInterface("C1-DH",
170 CLIENT_DH_CP,
171 INTERFACE_IPS,
172 CLIENT_IFACE_MAC,
173 CLIENT_VLAN,
174 null);
Yi Tsengaa417a62017-09-08 17:22:51 -0700175
176
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700177 // DHCP client 2 (will send with option 82, so the vlan should equals to vlan from server)
178 private static final MacAddress CLIENT2_MAC = MacAddress.valueOf("00:00:00:00:00:01");
179 private static final VlanId CLIENT2_VLAN = VlanId.NONE;
Yi Tseng4025a102017-09-30 11:35:42 +0800180 private static final VlanId CLIENT2_VLAN_NATIVE = VlanId.vlanId("20");
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700181 private static final ConnectPoint CLIENT2_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
182 private static final MacAddress CLIENT2_IFACE_MAC = MacAddress.valueOf("00:00:00:00:11:01");
Yi Tseng4025a102017-09-30 11:35:42 +0800183 private static final Interface CLIENT2_INTERFACE = createInterface("C2",
184 CLIENT2_CP,
185 INTERFACE_IPS,
186 CLIENT2_IFACE_MAC,
187 CLIENT2_VLAN,
188 CLIENT2_VLAN_NATIVE);
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +0000189 private static final VlanId CLIENT_BOGUS_VLAN = VlanId.vlanId("108");
190
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700191 // Outer relay information
Kalhee Kim121ba922017-11-01 17:56:44 +0000192 private static final Ip4Address OUTER_RELAY_IP = Ip4Address.valueOf("10.0.6.253");
Kalhee Kim45fede42017-09-05 19:05:06 +0000193 private static final Ip6Address OUTER_RELAY_IP_V6 = Ip6Address.valueOf("2001:db8:1::4");
Kalhee Kim121ba922017-11-01 17:56:44 +0000194 private static final Ip6Address OUTER_RELAY_LL_IP_V6 = Ip6Address.valueOf("fe80::200:0102:0304:0501");
195 private static final Set<IpAddress> OUTER_RELAY_IPS = ImmutableSet.of(OUTER_RELAY_IP,
196 OUTER_RELAY_IP_V6,
197 OUTER_RELAY_LL_IP_V6);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700198 private static final MacAddress OUTER_RELAY_MAC = MacAddress.valueOf("00:01:02:03:04:05");
199 private static final VlanId OUTER_RELAY_VLAN = VlanId.NONE;
200 private static final ConnectPoint OUTER_RELAY_CP = ConnectPoint.deviceConnectPoint("of:0000000000000001/2");
201 private static final HostLocation OUTER_REPLAY_HL = new HostLocation(OUTER_RELAY_CP, 0);
202 private static final HostId OUTER_RELAY_HOST_ID = HostId.hostId(OUTER_RELAY_MAC, OUTER_RELAY_VLAN);
Charles Chand988c282017-09-12 17:09:32 -0700203 private static final Host OUTER_RELAY_HOST = new DefaultHost(Dhcp4HandlerImpl.PROVIDER_ID,
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700204 OUTER_RELAY_HOST_ID,
205 OUTER_RELAY_MAC,
206 OUTER_RELAY_VLAN,
207 OUTER_REPLAY_HL,
208 OUTER_RELAY_IPS);
209
210 // DHCP Server
211 private static final MacAddress SERVER_MAC = MacAddress.valueOf("00:00:00:00:00:01");
212 private static final VlanId SERVER_VLAN = VlanId.NONE;
Yi Tseng4025a102017-09-30 11:35:42 +0800213 private static final VlanId SERVER_VLAN_NATIVE = VlanId.vlanId("10");
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700214 private static final ConnectPoint SERVER_CONNECT_POINT =
215 ConnectPoint.deviceConnectPoint("of:0000000000000001/5");
216 private static final HostLocation SERVER_LOCATION =
217 new HostLocation(SERVER_CONNECT_POINT, 0);
Kalhee Kim45fede42017-09-05 19:05:06 +0000218 private static final Ip4Address GATEWAY_IP = Ip4Address.valueOf("10.0.5.253");
219 private static final Ip6Address GATEWAY_IP_V6 = Ip6Address.valueOf("2000::105:253");
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700220 private static final Ip4Address SERVER_IP = Ip4Address.valueOf("10.0.3.253");
Kalhee Kim45fede42017-09-05 19:05:06 +0000221 private static final Ip6Address SERVER_IP_V6 = Ip6Address.valueOf("2000::103:253");
222 private static final Ip6Address SERVER_IP_V6_MCAST = Ip6Address.valueOf("ff02::1:2");
223 private static final Set<IpAddress> DHCP_SERVER_IPS = ImmutableSet.of(SERVER_IP, SERVER_IP_V6);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700224 private static final HostId SERVER_HOST_ID = HostId.hostId(SERVER_MAC, SERVER_VLAN);
Charles Chand988c282017-09-12 17:09:32 -0700225 private static final Host SERVER_HOST = new DefaultHost(Dhcp4HandlerImpl.PROVIDER_ID,
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700226 SERVER_HOST_ID,
227 SERVER_MAC,
228 SERVER_VLAN,
229 SERVER_LOCATION,
230 DHCP_SERVER_IPS);
231 private static final MacAddress SERVER_IFACE_MAC = MacAddress.valueOf("00:00:00:00:00:01");
Yi Tseng4025a102017-09-30 11:35:42 +0800232 private static final Interface SERVER_INTERFACE = createInterface("SERVER",
233 SERVER_CONNECT_POINT,
234 INTERFACE_IPS,
235 SERVER_IFACE_MAC,
236 SERVER_VLAN,
237 SERVER_VLAN_NATIVE);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700238
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700239 // Relay agent config
240 private static final Ip4Address RELAY_AGENT_IP = Ip4Address.valueOf("10.0.4.254");
241
Yi Tseng525ff402017-10-23 19:39:39 -0700242 private static final List<TrafficSelector> DHCP_SELECTORS = buildClientDhcpSelectors();
243
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700244 // Components
245 private static final ApplicationId APP_ID = TestApplicationId.create(DhcpRelayManager.DHCP_RELAY_APP);
Yi Tseng483ac6f2017-08-02 15:03:31 -0700246 private static final DefaultDhcpRelayConfig CONFIG = new MockDefaultDhcpRelayConfig();
Kalhee Kim45fede42017-09-05 19:05:06 +0000247 private static final IndirectDhcpRelayConfig CONFIG_INDIRECT = new MockIndirectDhcpRelayConfig();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700248 private static final Set<Interface> INTERFACES = ImmutableSet.of(
249 CLIENT_INTERFACE,
250 CLIENT2_INTERFACE,
Yi Tsengaa417a62017-09-08 17:22:51 -0700251 SERVER_INTERFACE,
252 CLIENT_DH_INTERFACE
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700253 );
Yi Tseng440e2b72017-08-24 14:47:34 -0700254 private static final String NON_ONOS_CID = "Non-ONOS circuit ID";
Yi Tseng51f1be92017-09-01 17:24:57 -0700255 private static final VlanId IGNORED_VLAN = VlanId.vlanId("100");
256 private static final int IGNORE_CONTROL_PRIORITY = PacketPriority.CONTROL.priorityValue() + 1000;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700257
258 private DhcpRelayManager manager;
259 private MockPacketService packetService;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700260 private MockRouteStore mockRouteStore;
261 private MockDhcpRelayStore mockDhcpRelayStore;
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000262 private MockDhcpRelayCountersStore mockDhcpRelayCountersStore;
Yi Tsengaa417a62017-09-08 17:22:51 -0700263 private HostProviderService mockHostProviderService;
Yi Tseng525ff402017-10-23 19:39:39 -0700264 private FlowObjectiveService flowObjectiveService;
265 private DeviceService deviceService;
266 private Dhcp4HandlerImpl v4Handler;
267 private Dhcp6HandlerImpl v6Handler;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700268
Yi Tseng4025a102017-09-30 11:35:42 +0800269 private static Interface createInterface(String name, ConnectPoint connectPoint,
270 List<InterfaceIpAddress> interfaceIps,
271 MacAddress macAddress,
272 VlanId vlanId,
273 VlanId vlanNative) {
274
275 if (vlanId.equals(VlanId.NONE)) {
276 return new Interface(name, connectPoint, interfaceIps, macAddress, vlanId,
277 null, null, vlanNative);
278 } else {
279 return new Interface(name, connectPoint, interfaceIps, macAddress, vlanId,
280 null, ImmutableSet.of(vlanId), null);
281 }
282 }
283
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700284 @Before
285 public void setup() {
286 manager = new DhcpRelayManager();
287 manager.cfgService = createNiceMock(NetworkConfigRegistry.class);
288
Yi Tseng483ac6f2017-08-02 15:03:31 -0700289 expect(manager.cfgService.getConfig(APP_ID, DefaultDhcpRelayConfig.class))
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700290 .andReturn(CONFIG)
291 .anyTimes();
292
Yi Tseng483ac6f2017-08-02 15:03:31 -0700293 expect(manager.cfgService.getConfig(APP_ID, IndirectDhcpRelayConfig.class))
Kalhee Kim45fede42017-09-05 19:05:06 +0000294 .andReturn(CONFIG_INDIRECT)
Yi Tseng483ac6f2017-08-02 15:03:31 -0700295 .anyTimes();
296
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700297 manager.coreService = createNiceMock(CoreService.class);
298 expect(manager.coreService.registerApplication(anyString()))
299 .andReturn(APP_ID).anyTimes();
300
301 manager.hostService = createNiceMock(HostService.class);
Kalhee Kim121ba922017-11-01 17:56:44 +0000302
303 expect(manager.hostService.getHostsByIp(OUTER_RELAY_IP_V6))
304 .andReturn(ImmutableSet.of(OUTER_RELAY_HOST)).anyTimes();
305 expect(manager.hostService.getHostsByIp(SERVER_IP))
306 .andReturn(ImmutableSet.of(SERVER_HOST)).anyTimes();
307 expect(manager.hostService.getHostsByIp(SERVER_IP_V6))
308 .andReturn(ImmutableSet.of(SERVER_HOST)).anyTimes();
309 expect(manager.hostService.getHostsByIp(GATEWAY_IP))
310 .andReturn(ImmutableSet.of(SERVER_HOST)).anyTimes();
311 expect(manager.hostService.getHostsByIp(GATEWAY_IP_V6))
312 .andReturn(ImmutableSet.of(SERVER_HOST)).anyTimes();
313 expect(manager.hostService.getHostsByIp(CLIENT_LL_IP_V6))
314 .andReturn(ImmutableSet.of(EXISTS_HOST)).anyTimes();
315
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700316 expect(manager.hostService.getHost(OUTER_RELAY_HOST_ID)).andReturn(OUTER_RELAY_HOST).anyTimes();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700317
318 packetService = new MockPacketService();
319 manager.packetService = packetService;
320 manager.compCfgService = createNiceMock(ComponentConfigService.class);
Yi Tseng525ff402017-10-23 19:39:39 -0700321 deviceService = createNiceMock(DeviceService.class);
Yi Tseng127ffe52017-09-12 15:55:17 -0700322
323 Device device = createNiceMock(Device.class);
324 expect(device.is(Pipeliner.class)).andReturn(true).anyTimes();
325
Yi Tseng525ff402017-10-23 19:39:39 -0700326 expect(deviceService.getDevice(DEV_1_ID)).andReturn(device).anyTimes();
327 expect(deviceService.getDevice(DEV_2_ID)).andReturn(device).anyTimes();
328 replay(deviceService, device);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700329
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700330 mockRouteStore = new MockRouteStore();
331 mockDhcpRelayStore = new MockDhcpRelayStore();
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000332 mockDhcpRelayCountersStore = new MockDhcpRelayCountersStore();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700333
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000334 manager.dhcpRelayStore = mockDhcpRelayStore;
335
336 manager.deviceService = deviceService;
Kalhee Kimba366062017-11-07 16:32:09 +0000337
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700338 manager.interfaceService = new MockInterfaceService();
Yi Tseng525ff402017-10-23 19:39:39 -0700339 flowObjectiveService = EasyMock.niceMock(FlowObjectiveService.class);
Yi Tsengaa417a62017-09-08 17:22:51 -0700340 mockHostProviderService = createNiceMock(HostProviderService.class);
Yi Tseng525ff402017-10-23 19:39:39 -0700341 v4Handler = new Dhcp4HandlerImpl();
Yi Tsengaa417a62017-09-08 17:22:51 -0700342 v4Handler.providerService = mockHostProviderService;
Yi Tseng51301292017-07-28 13:02:59 -0700343 v4Handler.dhcpRelayStore = mockDhcpRelayStore;
344 v4Handler.hostService = manager.hostService;
Yi Tseng51301292017-07-28 13:02:59 -0700345 v4Handler.interfaceService = manager.interfaceService;
346 v4Handler.packetService = manager.packetService;
347 v4Handler.routeStore = mockRouteStore;
Yi Tseng525ff402017-10-23 19:39:39 -0700348 v4Handler.coreService = createNiceMock(CoreService.class);
349 v4Handler.flowObjectiveService = flowObjectiveService;
350 v4Handler.appId = TestApplicationId.create(Dhcp4HandlerImpl.DHCP_V4_RELAY_APP);
351 v4Handler.deviceService = deviceService;
Yi Tseng51301292017-07-28 13:02:59 -0700352 manager.v4Handler = v4Handler;
353
Yi Tseng525ff402017-10-23 19:39:39 -0700354 v6Handler = new Dhcp6HandlerImpl();
Kalhee Kim45fede42017-09-05 19:05:06 +0000355 v6Handler.dhcpRelayStore = mockDhcpRelayStore;
Kalhee Kimd94ceea2017-11-29 19:03:02 +0000356 v6Handler.dhcpRelayCountersStore = mockDhcpRelayCountersStore;
Kalhee Kim45fede42017-09-05 19:05:06 +0000357 v6Handler.hostService = manager.hostService;
Kalhee Kim45fede42017-09-05 19:05:06 +0000358 v6Handler.interfaceService = manager.interfaceService;
359 v6Handler.packetService = manager.packetService;
360 v6Handler.routeStore = mockRouteStore;
Yi Tsengaa417a62017-09-08 17:22:51 -0700361 v6Handler.providerService = mockHostProviderService;
Yi Tseng525ff402017-10-23 19:39:39 -0700362 v6Handler.coreService = createNiceMock(CoreService.class);
363 v6Handler.flowObjectiveService = flowObjectiveService;
364 v6Handler.appId = TestApplicationId.create(Dhcp6HandlerImpl.DHCP_V6_RELAY_APP);
365 v6Handler.deviceService = deviceService;
Yi Tseng483ac6f2017-08-02 15:03:31 -0700366 manager.v6Handler = v6Handler;
367
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700368 // properties
369 Dictionary<String, Object> dictionary = createNiceMock(Dictionary.class);
370 expect(dictionary.get("arpEnabled")).andReturn(true).anyTimes();
Kalhee Kim495c9b22017-11-07 16:32:09 +0000371 expect(dictionary.get("dhcpPollInterval")).andReturn(120).anyTimes();
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700372 ComponentContext context = createNiceMock(ComponentContext.class);
373 expect(context.getProperties()).andReturn(dictionary).anyTimes();
374
Yi Tseng4025a102017-09-30 11:35:42 +0800375 replay(manager.cfgService, manager.coreService, manager.hostService,
376 manager.compCfgService, dictionary, context);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700377 manager.activate(context);
378 }
379
380 @After
381 public void tearDown() {
382 manager.deactivate();
383 }
384
385 /**
386 * Relay a DHCP packet without option 82.
387 * Should add new host to host store after dhcp ack.
388 */
389 @Test
390 public void relayDhcpWithoutAgentInfo() {
Yi Tsengaa417a62017-09-08 17:22:51 -0700391 replay(mockHostProviderService);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700392 // send request
393 packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT_MAC,
394 CLIENT_VLAN,
395 CLIENT_CP,
396 INTERFACE_IP.ipAddress().getIp4Address(),
397 false));
Yi Tsengaa417a62017-09-08 17:22:51 -0700398 // won't trigger the host provider service
399 verify(mockHostProviderService);
400 reset(mockHostProviderService);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700401
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700402 assertEquals(0, mockRouteStore.routes.size());
403
Yi Tsengaa417a62017-09-08 17:22:51 -0700404 HostId expectHostId = HostId.hostId(CLIENT_MAC, CLIENT_VLAN);
405 Capture<HostDescription> capturedHostDesc = newCapture();
406 mockHostProviderService.hostDetected(eq(expectHostId), capture(capturedHostDesc), eq(false));
407 replay(mockHostProviderService);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700408 // send ack
409 packetService.processPacket(new TestDhcpAckPacketContext(CLIENT_CP, CLIENT_MAC,
410 CLIENT_VLAN, INTERFACE_IP.ipAddress().getIp4Address(),
411 false));
Yi Tsengaa417a62017-09-08 17:22:51 -0700412 verify(mockHostProviderService);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700413 assertEquals(0, mockRouteStore.routes.size());
414
Yi Tsengaa417a62017-09-08 17:22:51 -0700415 HostDescription host = capturedHostDesc.getValue();
416 assertEquals(false, host.configured());
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700417 assertEquals(CLIENT_CP.deviceId(), host.location().elementId());
418 assertEquals(CLIENT_CP.port(), host.location().port());
Yi Tsengaa417a62017-09-08 17:22:51 -0700419 assertEquals(1, host.ipAddress().size());
420 assertEquals(IP_FOR_CLIENT, host.ipAddress().iterator().next());
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700421 }
422
423 /**
424 * Relay a DHCP packet with option 82 (Indirectly connected host).
425 */
426 @Test
427 public void relayDhcpWithAgentInfo() {
Yi Tsengaa417a62017-09-08 17:22:51 -0700428 replay(mockHostProviderService);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700429 // Assume outer dhcp relay agent exists in store already
430 // send request
431 packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT2_MAC,
432 CLIENT2_VLAN,
433 CLIENT2_CP,
434 INTERFACE_IP.ipAddress().getIp4Address(),
435 true));
Yi Tsengaa417a62017-09-08 17:22:51 -0700436 // No routes
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700437 assertEquals(0, mockRouteStore.routes.size());
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700438 // send ack
439 packetService.processPacket(new TestDhcpAckPacketContext(CLIENT2_CP,
440 CLIENT2_MAC,
441 CLIENT2_VLAN,
442 INTERFACE_IP.ipAddress().getIp4Address(),
443 true));
444
Yi Tsengaa417a62017-09-08 17:22:51 -0700445 // won't trigger the host provider service
446 verify(mockHostProviderService);
447 reset(mockHostProviderService);
448
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700449 assertEquals(1, mockRouteStore.routes.size());
450
451 Route route = mockRouteStore.routes.get(0);
452 assertEquals(OUTER_RELAY_IP, route.nextHop());
453 assertEquals(IP_FOR_CLIENT.toIpPrefix(), route.prefix());
Charles Chan6305b692018-04-04 11:43:54 -0700454 assertEquals(Route.Source.DHCP, route.source());
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700455 }
456
457 @Test
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700458 public void testWithRelayAgentConfig() throws DeserializationException {
459 manager.v4Handler
460 .setDefaultDhcpServerConfigs(ImmutableList.of(new MockDhcpServerConfig(RELAY_AGENT_IP)));
Yi Tseng4f2a0462017-08-31 11:21:00 -0700461 manager.v4Handler
462 .setIndirectDhcpServerConfigs(ImmutableList.of(new MockDhcpServerConfig(RELAY_AGENT_IP)));
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700463 packetService.processPacket(new TestDhcpRequestPacketContext(CLIENT2_MAC,
464 CLIENT2_VLAN,
465 CLIENT2_CP,
466 INTERFACE_IP.ipAddress().getIp4Address(),
467 true));
468 OutboundPacket outPacket = packetService.emittedPacket;
469 byte[] outData = outPacket.data().array();
470 Ethernet eth = Ethernet.deserializer().deserialize(outData, 0, outData.length);
471 IPv4 ip = (IPv4) eth.getPayload();
472 UDP udp = (UDP) ip.getPayload();
473 DHCP dhcp = (DHCP) udp.getPayload();
474 assertEquals(RELAY_AGENT_IP.toInt(), dhcp.getGatewayIPAddress());
475 }
476
477 @Test
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700478 public void testArpRequest() throws Exception {
479 packetService.processPacket(new TestArpRequestPacketContext(CLIENT_INTERFACE));
Ray Milkeyc108a6b2017-08-23 15:23:50 -0700480 OutboundPacket outboundPacket = packetService.emittedPacket;
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700481 byte[] outPacketData = outboundPacket.data().array();
482 Ethernet eth = Ethernet.deserializer().deserialize(outPacketData, 0, outPacketData.length);
483
484 assertEquals(eth.getEtherType(), Ethernet.TYPE_ARP);
485 ARP arp = (ARP) eth.getPayload();
486 assertArrayEquals(arp.getSenderHardwareAddress(), CLIENT_INTERFACE.mac().toBytes());
487 }
488
Yi Tseng51f1be92017-09-01 17:24:57 -0700489 /**
490 * Ignores specific vlans from specific devices if config.
491 *
492 * @throws Exception the exception from this test
493 */
494 @Test
495 public void testIgnoreVlan() throws Exception {
496 ObjectMapper om = new ObjectMapper();
497 JsonNode json = om.readTree(Resources.getResource(CONFIG_FILE_PATH));
498 IgnoreDhcpConfig config = new IgnoreDhcpConfig();
499 json = json.path("apps").path(DHCP_RELAY_APP).path(IgnoreDhcpConfig.KEY);
500 config.init(APP_ID, IgnoreDhcpConfig.KEY, json, om, null);
501
502 Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
Yi Tseng525ff402017-10-23 19:39:39 -0700503 flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
Yi Tseng127ffe52017-09-12 15:55:17 -0700504 expectLastCall().times(DHCP_SELECTORS.size());
Yi Tseng51f1be92017-09-01 17:24:57 -0700505 Capture<Objective> capturedFromDev2 = newCapture(CaptureType.ALL);
Yi Tseng525ff402017-10-23 19:39:39 -0700506 flowObjectiveService.apply(eq(DEV_2_ID), capture(capturedFromDev2));
Yi Tseng127ffe52017-09-12 15:55:17 -0700507 expectLastCall().times(DHCP_SELECTORS.size());
Yi Tseng525ff402017-10-23 19:39:39 -0700508 replay(flowObjectiveService);
Yi Tseng51f1be92017-09-01 17:24:57 -0700509 manager.updateConfig(config);
Yi Tseng525ff402017-10-23 19:39:39 -0700510 verify(flowObjectiveService);
Yi Tseng51f1be92017-09-01 17:24:57 -0700511
512 List<Objective> objectivesFromDev1 = capturedFromDev1.getValues();
513 List<Objective> objectivesFromDev2 = capturedFromDev2.getValues();
514
515 assertTrue(objectivesFromDev1.containsAll(objectivesFromDev2));
516 assertTrue(objectivesFromDev2.containsAll(objectivesFromDev1));
Yi Tseng51f1be92017-09-01 17:24:57 -0700517
518 for (int index = 0; index < objectivesFromDev1.size(); index++) {
519 TrafficSelector selector =
Yi Tseng525ff402017-10-23 19:39:39 -0700520 DefaultTrafficSelector.builder(DHCP_SELECTORS.get(index))
Yi Tseng51f1be92017-09-01 17:24:57 -0700521 .matchVlanId(IGNORED_VLAN)
522 .build();
523 ForwardingObjective fwd = (ForwardingObjective) objectivesFromDev1.get(index);
524 assertEquals(selector, fwd.selector());
Yi Tsengdbabeed2017-11-29 10:49:20 -0800525 assertEquals(DefaultTrafficTreatment.emptyTreatment(), fwd.treatment());
Yi Tseng51f1be92017-09-01 17:24:57 -0700526 assertEquals(IGNORE_CONTROL_PRIORITY, fwd.priority());
527 assertEquals(ForwardingObjective.Flag.VERSATILE, fwd.flag());
528 assertEquals(Objective.Operation.ADD, fwd.op());
Yi Tseng127ffe52017-09-12 15:55:17 -0700529 fwd.context().ifPresent(ctx -> {
530 ctx.onSuccess(fwd);
531 });
Yi Tseng51f1be92017-09-01 17:24:57 -0700532 }
Yi Tseng127ffe52017-09-12 15:55:17 -0700533 objectivesFromDev2.forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));
Yi Tseng525ff402017-10-23 19:39:39 -0700534 assertEquals(2, v4Handler.ignoredVlans.size());
535 assertEquals(2, v6Handler.ignoredVlans.size());
Yi Tseng51f1be92017-09-01 17:24:57 -0700536 }
537
538 /**
539 * "IgnoreVlan" policy should be removed when the config removed.
540 */
541 @Test
542 public void testRemoveIgnoreVlan() {
Yi Tseng525ff402017-10-23 19:39:39 -0700543 v4Handler.ignoredVlans.put(DEV_1_ID, IGNORED_VLAN);
544 v4Handler.ignoredVlans.put(DEV_2_ID, IGNORED_VLAN);
545 v6Handler.ignoredVlans.put(DEV_1_ID, IGNORED_VLAN);
546 v6Handler.ignoredVlans.put(DEV_2_ID, IGNORED_VLAN);
Yi Tseng51f1be92017-09-01 17:24:57 -0700547 IgnoreDhcpConfig config = new IgnoreDhcpConfig();
548
549 Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
Yi Tseng525ff402017-10-23 19:39:39 -0700550 flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
Yi Tseng127ffe52017-09-12 15:55:17 -0700551 expectLastCall().times(DHCP_SELECTORS.size());
Yi Tseng51f1be92017-09-01 17:24:57 -0700552 Capture<Objective> capturedFromDev2 = newCapture(CaptureType.ALL);
Yi Tseng525ff402017-10-23 19:39:39 -0700553 flowObjectiveService.apply(eq(DEV_2_ID), capture(capturedFromDev2));
Yi Tseng127ffe52017-09-12 15:55:17 -0700554 expectLastCall().times(DHCP_SELECTORS.size());
Yi Tseng525ff402017-10-23 19:39:39 -0700555 replay(flowObjectiveService);
Yi Tseng51f1be92017-09-01 17:24:57 -0700556 manager.removeConfig(config);
Yi Tseng525ff402017-10-23 19:39:39 -0700557 verify(flowObjectiveService);
Yi Tseng51f1be92017-09-01 17:24:57 -0700558
559 List<Objective> objectivesFromDev1 = capturedFromDev1.getValues();
560 List<Objective> objectivesFromDev2 = capturedFromDev2.getValues();
561
562 assertTrue(objectivesFromDev1.containsAll(objectivesFromDev2));
563 assertTrue(objectivesFromDev2.containsAll(objectivesFromDev1));
Yi Tseng51f1be92017-09-01 17:24:57 -0700564
565 for (int index = 0; index < objectivesFromDev1.size(); index++) {
566 TrafficSelector selector =
Yi Tseng525ff402017-10-23 19:39:39 -0700567 DefaultTrafficSelector.builder(DHCP_SELECTORS.get(index))
Yi Tseng51f1be92017-09-01 17:24:57 -0700568 .matchVlanId(IGNORED_VLAN)
569 .build();
570 ForwardingObjective fwd = (ForwardingObjective) objectivesFromDev1.get(index);
571 assertEquals(selector, fwd.selector());
Yi Tsengdbabeed2017-11-29 10:49:20 -0800572 assertEquals(DefaultTrafficTreatment.emptyTreatment(), fwd.treatment());
Yi Tseng51f1be92017-09-01 17:24:57 -0700573 assertEquals(IGNORE_CONTROL_PRIORITY, fwd.priority());
574 assertEquals(ForwardingObjective.Flag.VERSATILE, fwd.flag());
575 assertEquals(Objective.Operation.REMOVE, fwd.op());
Yi Tseng127ffe52017-09-12 15:55:17 -0700576 fwd.context().ifPresent(ctx -> {
577 ctx.onSuccess(fwd);
578 });
Yi Tseng51f1be92017-09-01 17:24:57 -0700579 }
Yi Tseng127ffe52017-09-12 15:55:17 -0700580 objectivesFromDev2.forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));
Yi Tseng525ff402017-10-23 19:39:39 -0700581 assertEquals(0, v4Handler.ignoredVlans.size());
582 assertEquals(0, v6Handler.ignoredVlans.size());
Yi Tseng51f1be92017-09-01 17:24:57 -0700583 }
584
Kalhee Kim45fede42017-09-05 19:05:06 +0000585 /**
Yi Tseng127ffe52017-09-12 15:55:17 -0700586 * Should ignore ignore rules installation when device not available.
587 */
588 @Test
589 public void testIgnoreUnknownDevice() throws IOException {
590 reset(manager.deviceService);
591 Device device = createNiceMock(Device.class);
592 expect(device.is(Pipeliner.class)).andReturn(true).anyTimes();
593
594 expect(manager.deviceService.getDevice(DEV_1_ID)).andReturn(device).anyTimes();
595 expect(manager.deviceService.getDevice(DEV_2_ID)).andReturn(null).anyTimes();
596
597 ObjectMapper om = new ObjectMapper();
598 JsonNode json = om.readTree(Resources.getResource(CONFIG_FILE_PATH));
599 IgnoreDhcpConfig config = new IgnoreDhcpConfig();
600 json = json.path("apps").path(DHCP_RELAY_APP).path(IgnoreDhcpConfig.KEY);
601 config.init(APP_ID, IgnoreDhcpConfig.KEY, json, om, null);
602
603 Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
Yi Tseng525ff402017-10-23 19:39:39 -0700604 flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
Yi Tseng127ffe52017-09-12 15:55:17 -0700605 expectLastCall().times(DHCP_SELECTORS.size());
Yi Tseng525ff402017-10-23 19:39:39 -0700606 replay(flowObjectiveService, manager.deviceService, device);
Yi Tseng127ffe52017-09-12 15:55:17 -0700607
608 manager.updateConfig(config);
609 capturedFromDev1.getValues().forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));
610
Yi Tseng525ff402017-10-23 19:39:39 -0700611 assertEquals(1, v4Handler.ignoredVlans.size());
612 assertEquals(1, v6Handler.ignoredVlans.size());
Yi Tseng127ffe52017-09-12 15:55:17 -0700613 }
614
615 /**
616 * Should try install ignore rules when device comes up.
617 */
618 @Test
619 public void testInstallIgnoreRuleWhenDeviceComesUp() throws IOException {
620 ObjectMapper om = new ObjectMapper();
621 JsonNode json = om.readTree(Resources.getResource(CONFIG_FILE_PATH));
622 IgnoreDhcpConfig config = new IgnoreDhcpConfig();
623 json = json.path("apps").path(DHCP_RELAY_APP).path(IgnoreDhcpConfig.KEY);
624 config.init(APP_ID, IgnoreDhcpConfig.KEY, json, om, null);
625
Yi Tseng525ff402017-10-23 19:39:39 -0700626 reset(manager.cfgService, flowObjectiveService, manager.deviceService);
Yi Tseng127ffe52017-09-12 15:55:17 -0700627 expect(manager.cfgService.getConfig(APP_ID, IgnoreDhcpConfig.class))
628 .andReturn(config).anyTimes();
629
630 Device device = createNiceMock(Device.class);
631 expect(device.is(Pipeliner.class)).andReturn(true).anyTimes();
632 expect(device.id()).andReturn(DEV_1_ID).anyTimes();
633 expect(manager.deviceService.getDevice(DEV_1_ID)).andReturn(device).anyTimes();
634 DeviceEvent event = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, device);
635 Capture<Objective> capturedFromDev1 = newCapture(CaptureType.ALL);
Yi Tseng525ff402017-10-23 19:39:39 -0700636 flowObjectiveService.apply(eq(DEV_1_ID), capture(capturedFromDev1));
Yi Tseng127ffe52017-09-12 15:55:17 -0700637 expectLastCall().times(DHCP_SELECTORS.size());
Yi Tseng525ff402017-10-23 19:39:39 -0700638 replay(manager.cfgService, flowObjectiveService, manager.deviceService, device);
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000639
Yi Tseng127ffe52017-09-12 15:55:17 -0700640 manager.deviceListener.event(event);
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000641
642 // Wait until all flow objective events are captured before triggering onSuccess
643 int expectFlowObjCount = Dhcp4HandlerImpl.DHCP_SELECTORS.size() + Dhcp6HandlerImpl.DHCP_SELECTORS.size();
644 assertAfter(EVENT_PROCESSING_MS, () -> assertEquals(expectFlowObjCount, capturedFromDev1.getValues().size()));
Yi Tseng127ffe52017-09-12 15:55:17 -0700645 capturedFromDev1.getValues().forEach(obj -> obj.context().ifPresent(ctx -> ctx.onSuccess(obj)));
Ruchi Sahotae4934e12019-03-01 16:56:07 +0000646
647 assertAfter(EVENT_PROCESSING_MS, () -> assertEquals(1, v4Handler.ignoredVlans.size()));
648 assertAfter(EVENT_PROCESSING_MS, () -> assertEquals(1, v6Handler.ignoredVlans.size()));
Yi Tseng127ffe52017-09-12 15:55:17 -0700649 }
650
651 /**
Kalhee Kim45fede42017-09-05 19:05:06 +0000652 * Relay a DHCP6 packet without relay option
653 * Note: Should add new host to host store after dhcp ack.
654 */
655 @Test
656 public void relayDhcp6WithoutAgentInfo() {
Yi Tsengaa417a62017-09-08 17:22:51 -0700657 replay(mockHostProviderService);
Kalhee Kim45fede42017-09-05 19:05:06 +0000658 // send request
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +0000659 packetService.processPacket(new TestDhcp6RequestPacketContext(DHCP6.MsgType.REQUEST.value(),
660 CLIENT_MAC,
661 CLIENT_VLAN,
Kalhee Kim45fede42017-09-05 19:05:06 +0000662 CLIENT_CP,
663 INTERFACE_IP_V6.ipAddress().getIp6Address(),
664 0));
665
Yi Tsengaa417a62017-09-08 17:22:51 -0700666 verify(mockHostProviderService);
667 reset(mockHostProviderService);
Kalhee Kim45fede42017-09-05 19:05:06 +0000668 assertEquals(0, mockRouteStore.routes.size());
669
Yi Tsengaa417a62017-09-08 17:22:51 -0700670 Capture<HostDescription> capturedHostDesc = newCapture();
671 mockHostProviderService.hostDetected(eq(HostId.hostId(CLIENT_MAC, CLIENT_VLAN)),
672 capture(capturedHostDesc), eq(false));
673 replay(mockHostProviderService);
Kalhee Kim45fede42017-09-05 19:05:06 +0000674 // send reply
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +0000675 packetService.processPacket(new TestDhcp6ReplyPacketContext(DHCP6.MsgType.REPLY.value(),
676 CLIENT_CP, CLIENT_MAC,
Kalhee Kim45fede42017-09-05 19:05:06 +0000677 CLIENT_VLAN,
678 INTERFACE_IP_V6.ipAddress().getIp6Address(),
Kalhee Kim121ba922017-11-01 17:56:44 +0000679 0, false, CLIENT_VLAN));
Yi Tsengaa417a62017-09-08 17:22:51 -0700680 verify(mockHostProviderService);
Kalhee Kim45fede42017-09-05 19:05:06 +0000681 assertEquals(0, mockRouteStore.routes.size());
682
Yi Tsengaa417a62017-09-08 17:22:51 -0700683 HostDescription host = capturedHostDesc.getValue();
Kalhee Kim45fede42017-09-05 19:05:06 +0000684 assertEquals(CLIENT_VLAN, host.vlan());
685 assertEquals(CLIENT_CP.deviceId(), host.location().elementId());
686 assertEquals(CLIENT_CP.port(), host.location().port());
Yi Tsengaa417a62017-09-08 17:22:51 -0700687 assertEquals(1, host.ipAddress().size());
688 assertEquals(IP_FOR_CLIENT_V6, host.ipAddress().iterator().next());
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +0000689
690 // send release
691 packetService.processPacket(new TestDhcp6RequestPacketContext(DHCP6.MsgType.RELEASE.value(),
692 CLIENT_MAC,
693 CLIENT_VLAN,
694 CLIENT_CP,
695 INTERFACE_IP_V6.ipAddress().getIp6Address(),
696 0));
697
698 assertEquals(null, manager.hostService.getHost(HostId.hostId(CLIENT_MAC, CLIENT_VLAN)));
Kalhee Kim45fede42017-09-05 19:05:06 +0000699 }
700
701 /**
702 * Relay a DHCP6 packet with Relay Message opion (Indirectly connected host).
703 */
704 @Test
705 public void relayDhcp6WithAgentInfo() {
Yi Tsengaa417a62017-09-08 17:22:51 -0700706 replay(mockHostProviderService);
Kalhee Kim45fede42017-09-05 19:05:06 +0000707 // Assume outer dhcp6 relay agent exists in store already
708 // send request
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +0000709 packetService.processPacket(new TestDhcp6RequestPacketContext(DHCP6.MsgType.REQUEST.value(),
710 CLIENT2_MAC,
711 CLIENT2_VLAN,
712 CLIENT2_CP,
713 OUTER_RELAY_IP_V6,
714 1));
715
716 assertEquals(0, mockRouteStore.routes.size());
717
718 // send reply
719 packetService.processPacket(new TestDhcp6ReplyPacketContext(DHCP6.MsgType.REPLY.value(), CLIENT2_CP,
720 CLIENT2_MAC,
721 CLIENT2_VLAN,
722 OUTER_RELAY_IP_V6,
Kalhee Kim121ba922017-11-01 17:56:44 +0000723 1, false, CLIENT2_VLAN));
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +0000724
725 // won't trigger the host provider service
726 verify(mockHostProviderService);
727 reset(mockHostProviderService);
728 assertEquals(2, mockRouteStore.routes.size()); // ipAddress and prefix
729
730 Route aRoute = mockRouteStore.routes.stream()
731 .filter(rt -> rt.prefix().contains(IP_FOR_CLIENT_V6))
732 .findFirst()
733 .orElse(null);
734 assertNotEquals(null, aRoute);
735
736 aRoute = mockRouteStore.routes.stream()
737 .filter(rt -> rt.prefix().contains(PREFIX_FOR_CLIENT_V6))
738 .findFirst()
739 .orElse(null);
740 assertNotEquals(null, aRoute);
741
742 // send release msg
743 packetService.processPacket(new TestDhcp6RequestPacketContext(DHCP6.MsgType.RELEASE.value(),
744 CLIENT2_MAC,
745 CLIENT2_VLAN,
746 CLIENT2_CP,
747 OUTER_RELAY_IP_V6,
748 1));
749
750 aRoute = mockRouteStore.routes.stream()
751 .filter(rt -> rt.prefix().contains(IP_FOR_CLIENT_V6))
752 .findFirst()
753 .orElse(null);
754 assertEquals(null, aRoute);
755
756 aRoute = mockRouteStore.routes.stream()
757 .filter(rt -> rt.prefix().contains(PREFIX_FOR_CLIENT_V6))
758 .findFirst()
759 .orElse(null);
760 assertEquals(null, aRoute);
761
762 assertEquals(0, mockRouteStore.routes.size());
763
764 }
765
766 /**
767 * Relay a DHCP6 packet with Relay Message opion (Indirectly connected host) and server responded
768 * with vlan differnt from client interface vlan.
769 */
770 @Test
771 public void relayDhcp6WithAgentInfoWrongVlan() {
772 replay(mockHostProviderService);
773 // Assume outer dhcp6 relay agent exists in store already
774 // send request
775 packetService.processPacket(new TestDhcp6RequestPacketContext(DHCP6.MsgType.REQUEST.value(),
776 CLIENT2_MAC,
Kalhee Kim45fede42017-09-05 19:05:06 +0000777 CLIENT2_VLAN,
778 CLIENT2_CP,
779 INTERFACE_IP_V6.ipAddress().getIp6Address(),
780 1));
781
Kalhee Kim45fede42017-09-05 19:05:06 +0000782 assertEquals(0, mockRouteStore.routes.size());
783
784 // send reply
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +0000785 packetService.processPacket(new TestDhcp6ReplyPacketContext(DHCP6.MsgType.REPLY.value(),
786 CLIENT2_CP,
Kalhee Kim45fede42017-09-05 19:05:06 +0000787 CLIENT2_MAC,
Kalhee Kim121ba922017-11-01 17:56:44 +0000788 CLIENT2_VLAN,
Kalhee Kim45fede42017-09-05 19:05:06 +0000789 INTERFACE_IP_V6.ipAddress().getIp6Address(),
Kalhee Kim121ba922017-11-01 17:56:44 +0000790 1, true,
791 CLIENT_BOGUS_VLAN // mismatch
792 ));
Kalhee Kim45fede42017-09-05 19:05:06 +0000793
Yi Tsengaa417a62017-09-08 17:22:51 -0700794 // won't trigger the host provider service
795 verify(mockHostProviderService);
796 reset(mockHostProviderService);
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +0000797 assertEquals(0, mockRouteStore.routes.size()); // ipAddress and prefix
Kalhee Kim45fede42017-09-05 19:05:06 +0000798
Kalhee Kim45fede42017-09-05 19:05:06 +0000799 }
Yi Tsengaa417a62017-09-08 17:22:51 -0700800
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +0000801
Yi Tsengaa417a62017-09-08 17:22:51 -0700802 @Test
803 public void testDhcp4DualHome() {
804 PacketContext packetContext =
805 new TestDhcpAckPacketContext(CLIENT_DH_CP, CLIENT_MAC, CLIENT_VLAN,
806 INTERFACE_IP.ipAddress().getIp4Address(),
807 false);
808 reset(manager.hostService);
809 expect(manager.hostService.getHost(CLIENT_HOST_ID)).andReturn(EXISTS_HOST).anyTimes();
810 Capture<HostDescription> capturedHostDesc = newCapture();
811 mockHostProviderService.hostDetected(eq(CLIENT_HOST_ID), capture(capturedHostDesc), eq(false));
812 replay(mockHostProviderService, manager.hostService);
813 packetService.processPacket(packetContext);
814 verify(mockHostProviderService);
815
816 HostDescription hostDesc = capturedHostDesc.getValue();
817 Set<HostLocation> hostLocations = hostDesc.locations();
818 assertEquals(2, hostLocations.size());
819 assertTrue(hostLocations.contains(CLIENT_LOCATION));
820 assertTrue(hostLocations.contains(CLIENT_DH_LOCATION));
821 }
822
823 @Test
824 public void testDhcp6DualHome() {
825 PacketContext packetContext =
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +0000826 new TestDhcp6ReplyPacketContext(DHCP6.MsgType.REPLY.value(),
827 CLIENT_DH_CP, CLIENT_MAC, CLIENT_VLAN,
Yi Tsengaa417a62017-09-08 17:22:51 -0700828 INTERFACE_IP_V6.ipAddress().getIp6Address(),
Kalhee Kim121ba922017-11-01 17:56:44 +0000829 0, false, CLIENT_VLAN);
Yi Tsengaa417a62017-09-08 17:22:51 -0700830 reset(manager.hostService);
831 expect(manager.hostService.getHostsByIp(CLIENT_LL_IP_V6)).andReturn(ImmutableSet.of(EXISTS_HOST)).anyTimes();
832
833 // FIXME: currently DHCPv6 has a bug, we can't get correct vlan of client......
834 // XXX: The vlan relied from DHCP6 handler might be wrong, do hack here
835 HostId hostId = HostId.hostId(CLIENT_MAC, VlanId.NONE);
836 expect(manager.hostService.getHost(hostId)).andReturn(EXISTS_HOST).anyTimes();
837
838 // XXX: sometimes this will work, sometimes not
839 expect(manager.hostService.getHost(CLIENT_HOST_ID)).andReturn(EXISTS_HOST).anyTimes();
840
841 Capture<HostDescription> capturedHostDesc = newCapture();
842
843 // XXX: also a hack here
844 mockHostProviderService.hostDetected(eq(hostId), capture(capturedHostDesc), eq(false));
845 expectLastCall().anyTimes();
846
847 mockHostProviderService.hostDetected(eq(CLIENT_HOST_ID), capture(capturedHostDesc), eq(false));
848 expectLastCall().anyTimes();
849 replay(mockHostProviderService, manager.hostService);
850 packetService.processPacket(packetContext);
851 verify(mockHostProviderService);
852
853 HostDescription hostDesc = capturedHostDesc.getValue();
854 Set<HostLocation> hostLocations = hostDesc.locations();
855 assertEquals(2, hostLocations.size());
856 assertTrue(hostLocations.contains(CLIENT_LOCATION));
857 assertTrue(hostLocations.contains(CLIENT_DH_LOCATION));
858 }
859
Yi Tseng483ac6f2017-08-02 15:03:31 -0700860 private static class MockDefaultDhcpRelayConfig extends DefaultDhcpRelayConfig {
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700861 @Override
862 public boolean isValid() {
863 return true;
864 }
865
866 @Override
Yi Tseng483ac6f2017-08-02 15:03:31 -0700867 public List<DhcpServerConfig> dhcpServerConfigs() {
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700868 return ImmutableList.of(new MockDhcpServerConfig(null));
Yi Tseng483ac6f2017-08-02 15:03:31 -0700869 }
870 }
871
Kalhee Kim45fede42017-09-05 19:05:06 +0000872 private static class MockIndirectDhcpRelayConfig extends IndirectDhcpRelayConfig {
873 @Override
874 public boolean isValid() {
875 return true;
876 }
877
878 @Override
879 public List<DhcpServerConfig> dhcpServerConfigs() {
880 return ImmutableList.of(new MockDhcpServerConfig(null));
881 }
882 }
883
Yi Tseng483ac6f2017-08-02 15:03:31 -0700884 private static class MockDhcpServerConfig extends DhcpServerConfig {
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700885 Ip4Address relayAgentIp;
886
887 /**
888 * Create mocked version DHCP server config.
889 *
890 * @param relayAgentIp the relay agent Ip config; null if we don't need it
891 */
892 public MockDhcpServerConfig(Ip4Address relayAgentIp) {
893 this.relayAgentIp = relayAgentIp;
Yi Tseng25bfe372017-11-03 16:27:32 -0700894 this.relayAgentIps.put(DEV_1_ID, Pair.of(relayAgentIp, null));
895 this.relayAgentIps.put(DEV_2_ID, Pair.of(relayAgentIp, null));
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700896 }
897
898 @Override
Yi Tseng25bfe372017-11-03 16:27:32 -0700899 public Optional<Ip4Address> getRelayAgentIp4(DeviceId deviceId) {
900 return Optional.ofNullable(this.relayAgentIps.get(deviceId).getLeft());
Yi Tseng3df7f9d2017-08-17 13:08:31 -0700901 }
902
Yi Tseng483ac6f2017-08-02 15:03:31 -0700903 @Override
904 public Optional<ConnectPoint> getDhcpServerConnectPoint() {
905 return Optional.of(SERVER_CONNECT_POINT);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700906 }
907
Yi Tseng483ac6f2017-08-02 15:03:31 -0700908 @Override
909 public Optional<Ip4Address> getDhcpServerIp4() {
910 return Optional.of(SERVER_IP);
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700911 }
Kalhee Kim45fede42017-09-05 19:05:06 +0000912
913 @Override
914 public Optional<Ip4Address> getDhcpGatewayIp4() {
915 return Optional.of(GATEWAY_IP);
916 }
917
918 @Override
919 public Optional<Ip6Address> getDhcpServerIp6() {
920 return Optional.of(SERVER_IP_V6);
921 }
922
923 @Override
924 public Optional<Ip6Address> getDhcpGatewayIp6() {
925 return Optional.of(GATEWAY_IP_V6);
926 }
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700927 }
928
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700929 private class MockRouteStore extends RouteStoreAdapter {
930 private List<Route> routes = Lists.newArrayList();
931
932 @Override
933 public void updateRoute(Route route) {
934 routes.add(route);
935 }
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +0000936
937 @Override
938 public void removeRoute(Route route) {
939 routes.remove(route);
940 }
Daniel Ginsburg83b76452018-06-09 01:43:59 +0300941
942 public void replaceRoute(Route route) {
943 routes.remove(route);
944 routes.add(route);
945 }
Yi Tseng7a38f9a2017-06-09 14:36:40 -0700946 }
947
948 private class MockInterfaceService extends InterfaceServiceAdapter {
949
950 @Override
951 public Set<Interface> getInterfaces() {
952 return INTERFACES;
953 }
954
955 @Override
956 public Set<Interface> getInterfacesByIp(IpAddress ip) {
957 return INTERFACES.stream()
958 .filter(iface -> {
959 return iface.ipAddressesList().stream()
960 .anyMatch(ifaceIp -> ifaceIp.ipAddress().equals(ip));
961 })
962 .collect(Collectors.toSet());
963 }
964
965 @Override
966 public Set<Interface> getInterfacesByPort(ConnectPoint port) {
967 return INTERFACES.stream()
968 .filter(iface -> iface.connectPoint().equals(port))
969 .collect(Collectors.toSet());
970 }
971 }
972
973 private class MockDhcpRelayStore implements DhcpRelayStore {
974 StoreDelegate<DhcpRelayStoreEvent> delegate;
975 private Map<HostId, DhcpRecord> records = Maps.newHashMap();
976
977 @Override
978 public void updateDhcpRecord(HostId hostId, DhcpRecord dhcpRecord) {
979 records.put(hostId, dhcpRecord);
980 DhcpRelayStoreEvent event = new DhcpRelayStoreEvent(DhcpRelayStoreEvent.Type.UPDATED,
981 dhcpRecord);
982 if (delegate != null) {
983 delegate.notify(event);
984 }
985 }
986
987 @Override
988 public Optional<DhcpRecord> getDhcpRecord(HostId hostId) {
989 return Optional.ofNullable(records.get(hostId));
990 }
991
992 @Override
993 public Collection<DhcpRecord> getDhcpRecords() {
994 return records.values();
995 }
996
997 @Override
998 public Optional<DhcpRecord> removeDhcpRecord(HostId hostId) {
999 DhcpRecord dhcpRecord = records.remove(hostId);
1000 if (dhcpRecord != null) {
1001 DhcpRelayStoreEvent event = new DhcpRelayStoreEvent(DhcpRelayStoreEvent.Type.REMOVED,
1002 dhcpRecord);
1003 if (delegate != null) {
1004 delegate.notify(event);
1005 }
1006 }
1007 return Optional.ofNullable(dhcpRecord);
1008 }
1009
1010 @Override
1011 public void setDelegate(StoreDelegate<DhcpRelayStoreEvent> delegate) {
1012 this.delegate = delegate;
1013 }
1014
1015 @Override
1016 public void unsetDelegate(StoreDelegate<DhcpRelayStoreEvent> delegate) {
1017 this.delegate = null;
1018 }
1019
1020 @Override
1021 public boolean hasDelegate() {
1022 return this.delegate != null;
1023 }
1024 }
1025
Kalhee Kimd94ceea2017-11-29 19:03:02 +00001026 private class MockDhcpRelayCountersStore implements DhcpRelayCountersStore {
1027 private Map<String, DhcpRelayCounters> counters = Maps.newHashMap();
1028
1029 public void incrementCounter(String coutnerClass, String counterName) {
1030 DhcpRelayCounters countersRecord;
1031
1032 DhcpRelayCounters classCounters = counters.get(coutnerClass);
1033 if (classCounters == null) {
1034 classCounters = new DhcpRelayCounters();
1035 }
1036 classCounters.incrementCounter(counterName);
1037 counters.put(coutnerClass, classCounters);
1038 }
1039
1040 @Override
1041 public Set<Map.Entry<String, DhcpRelayCounters>> getAllCounters() {
1042 return counters.entrySet();
1043 }
1044
1045 @Override
1046 public Optional<DhcpRelayCounters> getCounters(String counterClass) {
1047 DhcpRelayCounters classCounters = counters.get(counterClass);
1048 if (classCounters == null) {
1049 return Optional.empty();
1050 }
1051 return Optional.of(classCounters);
1052 }
1053
1054 @Override
1055 public void resetAllCounters() {
1056 counters.clear();
1057 }
1058
1059 @Override
1060 public void resetCounters(String counterClass) {
1061 DhcpRelayCounters classCounters = counters.get(counterClass);
1062 classCounters.resetCounters();
1063 counters.put(counterClass, classCounters);
1064 }
1065 }
1066
1067
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001068 private class MockPacketService extends PacketServiceAdapter {
1069 Set<PacketProcessor> packetProcessors = Sets.newHashSet();
Ray Milkeyc108a6b2017-08-23 15:23:50 -07001070 OutboundPacket emittedPacket;
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001071
1072 @Override
1073 public void addProcessor(PacketProcessor processor, int priority) {
1074 packetProcessors.add(processor);
1075 }
1076
1077 public void processPacket(PacketContext packetContext) {
1078 packetProcessors.forEach(p -> p.process(packetContext));
1079 }
1080
1081 @Override
1082 public void emit(OutboundPacket packet) {
Ray Milkeyc108a6b2017-08-23 15:23:50 -07001083 this.emittedPacket = packet;
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001084 }
1085 }
1086
1087
1088
1089 /**
1090 * Generates DHCP REQUEST packet.
1091 */
1092 private class TestDhcpRequestPacketContext extends PacketContextAdapter {
1093
1094
1095 private InboundPacket inPacket;
1096
1097 public TestDhcpRequestPacketContext(MacAddress clientMac, VlanId vlanId,
1098 ConnectPoint clientCp,
1099 Ip4Address clientGwAddr,
1100 boolean withNonOnosRelayInfo) {
1101 super(0, null, null, false);
1102 byte[] dhcpMsgType = new byte[1];
1103 dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPREQUEST.getValue();
1104
1105 DhcpOption dhcpOption = new DhcpOption();
1106 dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
1107 dhcpOption.setData(dhcpMsgType);
1108 dhcpOption.setLength((byte) 1);
1109 DhcpOption endOption = new DhcpOption();
1110 endOption.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
1111
1112 DHCP dhcp = new DHCP();
1113 dhcp.setHardwareType(DHCP.HWTYPE_ETHERNET);
1114 dhcp.setHardwareAddressLength((byte) 6);
1115 dhcp.setClientHardwareAddress(clientMac.toBytes());
1116 if (withNonOnosRelayInfo) {
1117 DhcpRelayAgentOption relayOption = new DhcpRelayAgentOption();
1118 DhcpOption circuitIdOption = new DhcpOption();
1119 CircuitId circuitId = new CircuitId("Custom option", VlanId.NONE);
1120 byte[] cid = circuitId.serialize();
1121 circuitIdOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
1122 circuitIdOption.setLength((byte) cid.length);
1123 circuitIdOption.setData(cid);
1124 relayOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
1125 relayOption.addSubOption(circuitIdOption);
1126 dhcp.setOptions(ImmutableList.of(dhcpOption, relayOption, endOption));
1127 dhcp.setGatewayIPAddress(OUTER_RELAY_IP.getIp4Address().toInt());
1128 } else {
1129 dhcp.setOptions(ImmutableList.of(dhcpOption, endOption));
1130 }
1131
1132
1133 UDP udp = new UDP();
1134 udp.setPayload(dhcp);
1135 udp.setSourcePort(UDP.DHCP_CLIENT_PORT);
1136 udp.setDestinationPort(UDP.DHCP_SERVER_PORT);
1137
1138 IPv4 ipv4 = new IPv4();
1139 ipv4.setPayload(udp);
1140 ipv4.setDestinationAddress(SERVER_IP.toInt());
1141 ipv4.setSourceAddress(clientGwAddr.toInt());
1142
1143 Ethernet eth = new Ethernet();
1144 if (withNonOnosRelayInfo) {
1145 eth.setEtherType(Ethernet.TYPE_IPV4)
1146 .setVlanID(vlanId.toShort())
1147 .setSourceMACAddress(OUTER_RELAY_MAC)
1148 .setDestinationMACAddress(MacAddress.BROADCAST)
1149 .setPayload(ipv4);
1150 } else {
1151 eth.setEtherType(Ethernet.TYPE_IPV4)
1152 .setVlanID(vlanId.toShort())
1153 .setSourceMACAddress(clientMac)
1154 .setDestinationMACAddress(MacAddress.BROADCAST)
1155 .setPayload(ipv4);
1156 }
1157
1158 this.inPacket = new DefaultInboundPacket(clientCp, eth,
1159 ByteBuffer.wrap(eth.serialize()));
1160 }
1161
1162 @Override
1163 public InboundPacket inPacket() {
1164 return this.inPacket;
1165 }
1166 }
1167
1168 /**
1169 * Generates DHCP ACK packet.
1170 */
1171 private class TestDhcpAckPacketContext extends PacketContextAdapter {
1172 private InboundPacket inPacket;
1173
1174 public TestDhcpAckPacketContext(ConnectPoint clientCp, MacAddress clientMac,
1175 VlanId clientVlan, Ip4Address clientGwAddr,
1176 boolean withNonOnosRelayInfo) {
1177 super(0, null, null, false);
1178
1179 byte[] dhcpMsgType = new byte[1];
1180 dhcpMsgType[0] = (byte) DHCP.MsgType.DHCPACK.getValue();
1181
1182 DhcpOption dhcpOption = new DhcpOption();
1183 dhcpOption.setCode(DHCP.DHCPOptionCode.OptionCode_MessageType.getValue());
1184 dhcpOption.setData(dhcpMsgType);
1185 dhcpOption.setLength((byte) 1);
1186
1187 DhcpOption endOption = new DhcpOption();
1188 endOption.setCode(DHCP.DHCPOptionCode.OptionCode_END.getValue());
1189
1190 DHCP dhcp = new DHCP();
1191 if (withNonOnosRelayInfo) {
1192 DhcpRelayAgentOption relayOption = new DhcpRelayAgentOption();
1193 DhcpOption circuitIdOption = new DhcpOption();
Yi Tseng440e2b72017-08-24 14:47:34 -07001194 String circuitId = NON_ONOS_CID;
1195 byte[] cid = circuitId.getBytes(Charsets.US_ASCII);
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001196 circuitIdOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
1197 circuitIdOption.setLength((byte) cid.length);
1198 circuitIdOption.setData(cid);
1199 relayOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
1200 relayOption.addSubOption(circuitIdOption);
1201 dhcp.setOptions(ImmutableList.of(dhcpOption, relayOption, endOption));
1202 dhcp.setGatewayIPAddress(OUTER_RELAY_IP.getIp4Address().toInt());
1203 } else {
1204 CircuitId cid = new CircuitId(clientCp.toString(), clientVlan);
1205 byte[] circuitId = cid.serialize();
1206 DhcpOption circuitIdSubOption = new DhcpOption();
1207 circuitIdSubOption.setCode(DhcpRelayAgentOption.RelayAgentInfoOptions.CIRCUIT_ID.getValue());
1208 circuitIdSubOption.setData(circuitId);
1209 circuitIdSubOption.setLength((byte) circuitId.length);
1210
1211 DhcpRelayAgentOption relayInfoOption = new DhcpRelayAgentOption();
1212 relayInfoOption.setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue());
1213 relayInfoOption.addSubOption(circuitIdSubOption);
1214 dhcp.setOptions(ImmutableList.of(dhcpOption, relayInfoOption, endOption));
1215 dhcp.setGatewayIPAddress(clientGwAddr.toInt());
1216 }
1217 dhcp.setHardwareType(DHCP.HWTYPE_ETHERNET);
1218 dhcp.setHardwareAddressLength((byte) 6);
1219 dhcp.setClientHardwareAddress(clientMac.toBytes());
1220 dhcp.setYourIPAddress(IP_FOR_CLIENT.toInt());
1221
1222 UDP udp = new UDP();
1223 udp.setPayload(dhcp);
1224 udp.setSourcePort(UDP.DHCP_SERVER_PORT);
1225 udp.setDestinationPort(UDP.DHCP_CLIENT_PORT);
1226 IPv4 ipv4 = new IPv4();
1227 ipv4.setPayload(udp);
1228 ipv4.setDestinationAddress(IP_FOR_CLIENT.toString());
1229 ipv4.setSourceAddress(SERVER_IP.toString());
1230 Ethernet eth = new Ethernet();
1231 if (withNonOnosRelayInfo) {
1232 eth.setEtherType(Ethernet.TYPE_IPV4)
1233 .setVlanID(SERVER_VLAN.toShort())
1234 .setSourceMACAddress(SERVER_MAC)
1235 .setDestinationMACAddress(OUTER_RELAY_MAC)
1236 .setPayload(ipv4);
1237 } else {
1238 eth.setEtherType(Ethernet.TYPE_IPV4)
1239 .setVlanID(SERVER_VLAN.toShort())
1240 .setSourceMACAddress(SERVER_MAC)
1241 .setDestinationMACAddress(CLIENT_MAC)
1242 .setPayload(ipv4);
1243 }
1244
1245 this.inPacket = new DefaultInboundPacket(SERVER_CONNECT_POINT, eth,
1246 ByteBuffer.wrap(eth.serialize()));
1247
1248 }
1249
1250 @Override
1251 public InboundPacket inPacket() {
1252 return this.inPacket;
1253 }
1254 }
1255
1256 private class TestArpRequestPacketContext extends PacketContextAdapter {
1257 private InboundPacket inPacket;
1258
1259 public TestArpRequestPacketContext(Interface fromInterface) {
1260 super(0, null, null, false);
1261 ARP arp = new ARP();
1262 arp.setOpCode(ARP.OP_REQUEST);
1263
1264 IpAddress targetIp = fromInterface.ipAddressesList().get(0).ipAddress();
1265 arp.setTargetProtocolAddress(targetIp.toOctets());
1266 arp.setTargetHardwareAddress(MacAddress.BROADCAST.toBytes());
1267 arp.setSenderHardwareAddress(MacAddress.NONE.toBytes());
1268 arp.setSenderProtocolAddress(Ip4Address.valueOf(0).toOctets());
1269 arp.setHardwareAddressLength((byte) MacAddress.MAC_ADDRESS_LENGTH);
1270 Ethernet eth = new Ethernet();
1271 eth.setEtherType(Ethernet.TYPE_ARP);
1272 eth.setSourceMACAddress(MacAddress.NONE);
1273 eth.setDestinationMACAddress(MacAddress.BROADCAST);
1274 eth.setVlanID(fromInterface.vlan().toShort());
1275 eth.setPayload(arp);
1276
1277 this.inPacket = new DefaultInboundPacket(fromInterface.connectPoint(), eth,
1278 ByteBuffer.wrap(eth.serialize()));
1279 }
1280
1281 @Override
1282 public InboundPacket inPacket() {
1283 return this.inPacket;
1284 }
1285 }
Kalhee Kim45fede42017-09-05 19:05:06 +00001286
1287 /**
1288 * Generates DHCP6 REQUEST packet.
1289 */
1290 private void buildDhcp6Packet(DHCP6 dhcp6, byte msgType, Ip6Address ip6Addr, IpPrefix prefix) {
1291
1292 // build address option
1293 Dhcp6IaAddressOption iaAddressOption = new Dhcp6IaAddressOption();
1294 iaAddressOption.setCode(DHCP6.OptionCode.IAADDR.value());
1295 iaAddressOption.setIp6Address(ip6Addr);
1296 iaAddressOption.setPreferredLifetime(3600);
1297 iaAddressOption.setValidLifetime(1200);
1298 iaAddressOption.setLength((short) Dhcp6IaAddressOption.DEFAULT_LEN);
1299
Kalhee Kim495c9b22017-11-07 16:32:09 +00001300 Dhcp6ClientIdOption clientIdOption = new Dhcp6ClientIdOption();
1301 Dhcp6Duid dhcp6Duip = new Dhcp6Duid();
1302 dhcp6Duip.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
1303 dhcp6Duip.setHardwareType((short) 0x01); // Ethernet
1304 dhcp6Duip.setDuidTime(1234);
1305 dhcp6Duip.setLinkLayerAddress(CLIENT_MAC.toBytes());
1306 clientIdOption.setDuid(dhcp6Duip);
1307
Kalhee Kim45fede42017-09-05 19:05:06 +00001308 Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
1309 iaNaOption.setCode(DHCP6.OptionCode.IA_NA.value());
1310 iaNaOption.setIaId(0);
1311 iaNaOption.setT1(302400);
1312 iaNaOption.setT2(483840);
1313 List<Dhcp6Option> iaNaSubOptions = new ArrayList<Dhcp6Option>();
1314 iaNaSubOptions.add(iaAddressOption);
1315 iaNaOption.setOptions(iaNaSubOptions);
1316 iaNaOption.setLength((short) (Dhcp6IaNaOption.DEFAULT_LEN + iaAddressOption.getLength()));
1317
1318 // build prefix option
1319 Dhcp6IaPrefixOption iaPrefixOption = new Dhcp6IaPrefixOption();
1320 iaPrefixOption.setCode(DHCP6.OptionCode.IAPREFIX.value());
1321 iaPrefixOption.setIp6Prefix(prefix.address().getIp6Address());
1322 iaPrefixOption.setPrefixLength((byte) prefix.prefixLength());
1323 iaPrefixOption.setPreferredLifetime(3601);
1324 iaPrefixOption.setValidLifetime(1201);
1325 iaPrefixOption.setLength((short) Dhcp6IaPrefixOption.DEFAULT_LEN);
1326
1327 Dhcp6IaPdOption iaPdOption = new Dhcp6IaPdOption();
1328 iaPdOption.setCode(DHCP6.OptionCode.IA_PD.value());
1329 iaPdOption.setIaId(0);
1330 iaPdOption.setT1(302401);
1331 iaPdOption.setT2(483841);
1332 List<Dhcp6Option> iaPdSubOptions = new ArrayList<Dhcp6Option>();
1333 iaPdSubOptions.add(iaPrefixOption);
1334 iaPdOption.setOptions(iaPdSubOptions);
1335 iaPdOption.setLength((short) (Dhcp6IaPdOption.DEFAULT_LEN + iaPrefixOption.getLength()));
1336
1337 dhcp6.setMsgType(msgType);
1338 List<Dhcp6Option> dhcp6Options = new ArrayList<Dhcp6Option>();
1339 dhcp6Options.add(iaNaOption);
Kalhee Kim495c9b22017-11-07 16:32:09 +00001340 dhcp6Options.add(clientIdOption);
Kalhee Kim45fede42017-09-05 19:05:06 +00001341 dhcp6Options.add(iaPdOption);
1342 dhcp6.setOptions(dhcp6Options);
1343
1344 }
1345
1346 private void buildRelayMsg(DHCP6 dhcp6Relay, byte msgType, Ip6Address linkAddr,
1347 Ip6Address peerAddr, byte hop, byte[] interfaceIdBytes,
1348 DHCP6 dhcp6Payload) {
1349
1350 dhcp6Relay.setMsgType(msgType);
1351
1352 dhcp6Relay.setLinkAddress(linkAddr.toOctets());
1353 dhcp6Relay.setPeerAddress(peerAddr.toOctets());
1354 dhcp6Relay.setHopCount(hop);
1355 List<Dhcp6Option> options = new ArrayList<Dhcp6Option>();
1356
1357 // interfaceId option
1358 Dhcp6Option interfaceId = new Dhcp6Option();
1359 interfaceId.setCode(DHCP6.OptionCode.INTERFACE_ID.value());
1360
1361
1362 interfaceId.setData(interfaceIdBytes);
1363 interfaceId.setLength((short) interfaceIdBytes.length);
1364 Dhcp6InterfaceIdOption interfaceIdOption = new Dhcp6InterfaceIdOption(interfaceId);
Kalhee Kima0b8f652017-10-18 22:00:30 +00001365 byte[] optionData = interfaceIdOption.getData();
Kalhee Kim45fede42017-09-05 19:05:06 +00001366 ByteBuffer bb = ByteBuffer.wrap(interfaceIdBytes);
1367
1368 byte[] macAddr = new byte[MacAddress.MAC_ADDRESS_LENGTH];
Kalhee Kima0b8f652017-10-18 22:00:30 +00001369 byte[] port = new byte[optionData.length - MacAddress.MAC_ADDRESS_LENGTH -
Kalhee Kimba366062017-11-07 16:32:09 +00001370 VLAN_LEN - SEPARATOR_LEN * 2];
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +00001371 short vlan;
Kalhee Kim45fede42017-09-05 19:05:06 +00001372 bb.get(macAddr);
1373 bb.get(); // separator
1374 bb.get(port);
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +00001375 bb.get(); // separator
1376 vlan = bb.getShort();
Kalhee Kim45fede42017-09-05 19:05:06 +00001377 interfaceIdOption.setMacAddress(MacAddress.valueOf(macAddr));
1378 interfaceIdOption.setInPort(port);
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +00001379 interfaceIdOption.setVlanId(vlan);
Kalhee Kim45fede42017-09-05 19:05:06 +00001380
1381 options.add(interfaceIdOption);
1382
1383 // relay message option
1384 Dhcp6Option relayMsgOption = new Dhcp6Option();
1385 relayMsgOption.setCode(DHCP6.OptionCode.RELAY_MSG.value());
1386 byte[] dhcp6PayloadByte = dhcp6Payload.serialize();
1387 relayMsgOption.setLength((short) dhcp6PayloadByte.length);
1388 relayMsgOption.setPayload(dhcp6Payload);
1389 Dhcp6RelayOption relayOpt = new Dhcp6RelayOption(relayMsgOption);
1390
1391 options.add(relayOpt);
1392
1393 dhcp6Relay.setOptions(options);
1394 }
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +00001395 private byte[] buildInterfaceId(MacAddress clientMac, short vlanId, ConnectPoint clientCp) {
1396 String inPortString = "-" + clientCp.toString() + ":";
Kalhee Kim45fede42017-09-05 19:05:06 +00001397 byte[] clientSoureMacBytes = clientMac.toBytes();
1398 byte[] inPortStringBytes = inPortString.getBytes();
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +00001399 byte[] vlanIdBytes = new byte[2];
1400 vlanIdBytes[0] = (byte) ((vlanId >> 8) & 0xff); // high-order byte first
1401 vlanIdBytes[1] = (byte) (vlanId & 0xff);
1402 byte[] interfaceIdBytes = new byte[clientSoureMacBytes.length + inPortStringBytes.length + vlanIdBytes.length];
Kalhee Kim45fede42017-09-05 19:05:06 +00001403
1404 System.arraycopy(clientSoureMacBytes, 0, interfaceIdBytes, 0, clientSoureMacBytes.length);
1405 System.arraycopy(inPortStringBytes, 0, interfaceIdBytes, clientSoureMacBytes.length, inPortStringBytes.length);
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +00001406 System.arraycopy(vlanIdBytes, 0, interfaceIdBytes, clientSoureMacBytes.length + inPortStringBytes.length,
1407 vlanIdBytes.length);
Kalhee Kim45fede42017-09-05 19:05:06 +00001408
1409 return interfaceIdBytes;
1410 }
1411
Yi Tseng525ff402017-10-23 19:39:39 -07001412 private static List<TrafficSelector> buildClientDhcpSelectors() {
1413 return Streams.concat(Dhcp4HandlerImpl.DHCP_SELECTORS.stream(),
1414 Dhcp6HandlerImpl.DHCP_SELECTORS.stream())
1415 .collect(Collectors.toList());
1416 }
1417
Kalhee Kim45fede42017-09-05 19:05:06 +00001418 private class TestDhcp6RequestPacketContext extends PacketContextAdapter {
1419
1420
1421 private InboundPacket inPacket;
1422
1423
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +00001424 public TestDhcp6RequestPacketContext(byte msgType, MacAddress clientMac, VlanId vlanId,
Kalhee Kim45fede42017-09-05 19:05:06 +00001425 ConnectPoint clientCp,
1426 Ip6Address clientGwAddr,
1427 int relayLevel) {
1428 super(0, null, null, false);
1429
1430 DHCP6 dhcp6 = new DHCP6();
1431 if (relayLevel > 0) {
1432 DHCP6 dhcp6Payload = new DHCP6();
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +00001433 buildDhcp6Packet(dhcp6Payload, msgType,
Kalhee Kim45fede42017-09-05 19:05:06 +00001434 IP_FOR_CLIENT_V6,
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +00001435 msgType == DHCP6.MsgType.REQUEST.value() ? PREFIX_FOR_ZERO : PREFIX_FOR_CLIENT_V6);
Kalhee Kim45fede42017-09-05 19:05:06 +00001436 DHCP6 dhcp6Parent = null;
1437 DHCP6 dhcp6Child = dhcp6Payload;
1438 for (int i = 0; i < relayLevel; i++) {
1439 dhcp6Parent = new DHCP6();
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +00001440 byte[] interfaceId = buildInterfaceId(clientMac, vlanId.toShort(), clientCp);
Kalhee Kim45fede42017-09-05 19:05:06 +00001441 buildRelayMsg(dhcp6Parent, DHCP6.MsgType.RELAY_FORW.value(),
1442 INTERFACE_IP_V6.ipAddress().getIp6Address(),
1443 OUTER_RELAY_IP_V6,
1444 (byte) (relayLevel - 1), interfaceId,
1445 dhcp6Child);
1446 dhcp6Child = dhcp6Parent;
1447 }
1448 if (dhcp6Parent != null) {
1449 dhcp6 = dhcp6Parent;
1450 }
1451 } else {
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +00001452 buildDhcp6Packet(dhcp6, msgType,
Kalhee Kim45fede42017-09-05 19:05:06 +00001453 IP_FOR_CLIENT_V6,
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +00001454 msgType == DHCP6.MsgType.REQUEST.value() ? PREFIX_FOR_ZERO : PREFIX_FOR_CLIENT_V6);
Kalhee Kim45fede42017-09-05 19:05:06 +00001455 }
1456
1457 UDP udp = new UDP();
1458 udp.setPayload(dhcp6);
1459 if (relayLevel > 0) {
1460 udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
1461 } else {
1462 udp.setSourcePort(UDP.DHCP_V6_CLIENT_PORT);
1463 }
1464 udp.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
1465
1466 IPv6 ipv6 = new IPv6();
1467 ipv6.setPayload(udp);
1468 ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
1469 ipv6.setDestinationAddress(SERVER_IP_V6_MCAST.toOctets());
1470 ipv6.setSourceAddress(clientGwAddr.toOctets());
1471
1472 Ethernet eth = new Ethernet();
1473 if (relayLevel > 0) {
1474 eth.setEtherType(Ethernet.TYPE_IPV6)
Kalhee Kim121ba922017-11-01 17:56:44 +00001475 .setVlanID(OUTER_RELAY_VLAN.toShort())
Kalhee Kim45fede42017-09-05 19:05:06 +00001476 .setSourceMACAddress(OUTER_RELAY_MAC)
1477 .setDestinationMACAddress(MacAddress.valueOf("33:33:00:01:00:02"))
1478 .setPayload(ipv6);
1479 } else {
1480 eth.setEtherType(Ethernet.TYPE_IPV6)
1481 .setVlanID(vlanId.toShort())
1482 .setSourceMACAddress(clientMac)
1483 .setDestinationMACAddress(MacAddress.valueOf("33:33:00:01:00:02"))
1484 .setPayload(ipv6);
1485 }
1486 this.inPacket = new DefaultInboundPacket(clientCp, eth,
1487 ByteBuffer.wrap(eth.serialize()));
1488 }
1489
1490 @Override
1491 public InboundPacket inPacket() {
1492 return this.inPacket;
1493 }
1494 }
1495
1496 /**
1497 * Generates DHCP6 REPLY packet.
1498 */
1499
1500 private class TestDhcp6ReplyPacketContext extends PacketContextAdapter {
1501 private InboundPacket inPacket;
1502
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +00001503 public TestDhcp6ReplyPacketContext(byte msgType, ConnectPoint clientCp, MacAddress clientMac,
Kalhee Kim45fede42017-09-05 19:05:06 +00001504 VlanId clientVlan, Ip6Address clientGwAddr,
Kalhee Kim121ba922017-11-01 17:56:44 +00001505 int relayLevel, boolean overWriteFlag, VlanId overWriteVlan) {
Kalhee Kim45fede42017-09-05 19:05:06 +00001506 super(0, null, null, false);
1507
1508
1509 DHCP6 dhcp6Payload = new DHCP6();
Kalhee Kim0c0cb0b2017-09-15 17:43:27 +00001510 buildDhcp6Packet(dhcp6Payload, msgType,
Kalhee Kim45fede42017-09-05 19:05:06 +00001511 IP_FOR_CLIENT_V6,
1512 PREFIX_FOR_CLIENT_V6);
Kalhee Kim121ba922017-11-01 17:56:44 +00001513 byte[] interfaceId = null;
1514 if (relayLevel > 0) {
1515 interfaceId = buildInterfaceId(OUTER_RELAY_MAC,
1516 overWriteFlag ? overWriteVlan.toShort() : OUTER_RELAY_VLAN.toShort(),
1517 OUTER_RELAY_CP);
1518 } else {
1519 interfaceId = buildInterfaceId(clientMac, clientVlan.toShort(), clientCp);
1520 }
Kalhee Kim45fede42017-09-05 19:05:06 +00001521 DHCP6 dhcp6 = new DHCP6();
1522 buildRelayMsg(dhcp6, DHCP6.MsgType.RELAY_REPL.value(),
Yi Tsengaa417a62017-09-08 17:22:51 -07001523 INTERFACE_IP_V6.ipAddress().getIp6Address(),
1524 CLIENT_LL_IP_V6,
1525 (byte) 0, interfaceId,
1526 dhcp6Payload);
Kalhee Kim45fede42017-09-05 19:05:06 +00001527
1528 DHCP6 dhcp6Parent = null;
1529 DHCP6 dhcp6Child = dhcp6;
1530 for (int i = 0; i < relayLevel; i++) { // relayLevel 0 : no relay
1531 dhcp6Parent = new DHCP6();
1532
1533 buildRelayMsg(dhcp6Parent, DHCP6.MsgType.RELAY_REPL.value(),
1534 INTERFACE_IP_V6.ipAddress().getIp6Address(),
1535 OUTER_RELAY_IP_V6,
1536 (byte) relayLevel, interfaceId,
1537 dhcp6Child);
1538
1539 dhcp6Child = dhcp6Parent;
1540 }
1541 if (dhcp6Parent != null) {
1542 dhcp6 = dhcp6Parent;
1543 }
1544
1545
1546 UDP udp = new UDP();
1547 udp.setPayload(dhcp6);
1548 udp.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
1549 udp.setDestinationPort(UDP.DHCP_V6_CLIENT_PORT);
1550 IPv6 ipv6 = new IPv6();
1551 ipv6.setPayload(udp);
1552 ipv6.setNextHeader(IPv6.PROTOCOL_UDP);
1553 ipv6.setDestinationAddress(IP_FOR_CLIENT_V6.toOctets());
1554 ipv6.setSourceAddress(SERVER_IP_V6.toOctets());
1555 Ethernet eth = new Ethernet();
1556 if (relayLevel > 0) {
1557 eth.setEtherType(Ethernet.TYPE_IPV6)
1558 .setVlanID(SERVER_VLAN.toShort())
1559 .setSourceMACAddress(SERVER_MAC)
1560 .setDestinationMACAddress(OUTER_RELAY_MAC)
1561 .setPayload(ipv6);
1562 } else {
1563 eth.setEtherType(Ethernet.TYPE_IPV6)
1564 .setVlanID(SERVER_VLAN.toShort())
1565 .setSourceMACAddress(SERVER_MAC)
1566 .setDestinationMACAddress(CLIENT_MAC)
1567 .setPayload(ipv6);
1568 }
1569
1570 this.inPacket = new DefaultInboundPacket(SERVER_CONNECT_POINT, eth,
1571 ByteBuffer.wrap(eth.serialize()));
1572
1573 }
1574
1575 @Override
1576 public InboundPacket inPacket() {
1577 return this.inPacket;
1578 }
1579 }
1580
Yi Tseng7a38f9a2017-06-09 14:36:40 -07001581}