blob: aaf594b4844b7ce9d1dc8f10f8e8234cf6bbb0e4 [file] [log] [blame]
Amit Ghosh8951f042017-08-10 13:48:10 +01001/*
Joey Armstrong7e08d2a2022-12-30 12:25:42 -05002 * Copyright 2017-2023 Open Networking Foundation (ONF) and the ONF Contributors
Amit Ghosh8951f042017-08-10 13:48:10 +01003 *
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 */
Matteo Scandolo57af5d12019-04-29 17:11:41 -070016package org.opencord.dhcpl2relay.impl;
Amit Ghosh8951f042017-08-10 13:48:10 +010017
Saurav Dasbd5ce9c2020-09-04 18:46:45 -070018import static org.easymock.EasyMock.createMock;
Saurav Das45861d42020-10-07 00:03:23 -070019import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.fail;
Saurav Dasbd5ce9c2020-09-04 18:46:45 -070021import static org.slf4j.LoggerFactory.getLogger;
22
23import java.nio.ByteBuffer;
24import java.util.List;
25import java.util.Map;
Saurav Das45861d42020-10-07 00:03:23 -070026import java.util.stream.Collectors;
Saurav Dasbd5ce9c2020-09-04 18:46:45 -070027
Amit Ghosh8951f042017-08-10 13:48:10 +010028import org.junit.After;
29import org.junit.Before;
30import org.junit.Test;
Jonathan Hartc36c9552018-07-31 15:07:53 -040031import org.onlab.junit.TestUtils;
Amit Ghosh8951f042017-08-10 13:48:10 +010032import org.onlab.packet.DHCP;
Saurav Das45861d42020-10-07 00:03:23 -070033import org.onlab.packet.DeserializationException;
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +053034import org.onlab.packet.Ethernet;
Amit Ghosh8951f042017-08-10 13:48:10 +010035import org.onlab.packet.IPv4;
Saurav Dasbd5ce9c2020-09-04 18:46:45 -070036import org.onlab.packet.MacAddress;
Amit Ghosh8951f042017-08-10 13:48:10 +010037import org.onlab.packet.UDP;
Saurav Dasbd5ce9c2020-09-04 18:46:45 -070038import org.onlab.packet.VlanId;
Jonathan Hartedbf6422018-05-02 17:30:05 -070039import org.onlab.packet.dhcp.DhcpOption;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030040import org.onosproject.cfg.ComponentConfigService;
Jonathan Hart77ca3152020-02-21 14:31:21 -080041import org.onosproject.cluster.ClusterServiceAdapter;
Jonathan Hart617bc3e2020-02-14 10:42:23 -080042import org.onosproject.cluster.LeadershipServiceAdapter;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030043import org.onosproject.net.ConnectPoint;
44import org.onosproject.net.flowobjective.FlowObjectiveServiceAdapter;
Jonathan Hart77ca3152020-02-21 14:31:21 -080045import org.onosproject.store.cluster.messaging.ClusterCommunicationServiceAdapter;
Jonathan Hart617bc3e2020-02-14 10:42:23 -080046import org.onosproject.store.service.TestStorageService;
Saurav Dasbd5ce9c2020-09-04 18:46:45 -070047import org.opencord.dhcpl2relay.DhcpAllocationInfo;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030048import org.opencord.dhcpl2relay.DhcpL2RelayEvent;
Jonathan Hart77ca3152020-02-21 14:31:21 -080049import org.opencord.dhcpl2relay.DhcpL2RelayStoreDelegate;
Saurav Das45861d42020-10-07 00:03:23 -070050import org.opencord.dhcpl2relay.impl.packet.DhcpOption82Data;
Saurav Dasbd5ce9c2020-09-04 18:46:45 -070051import org.slf4j.Logger;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030052
Saurav Dasbd5ce9c2020-09-04 18:46:45 -070053import com.google.common.collect.Lists;
Saurav Das45861d42020-10-07 00:03:23 -070054import com.google.common.util.concurrent.MoreExecutors;
Amit Ghosh8951f042017-08-10 13:48:10 +010055
56public class DhcpL2RelayTest extends DhcpL2RelayTestBase {
57
Amit Ghosh8951f042017-08-10 13:48:10 +010058 private DhcpL2Relay dhcpL2Relay;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030059 private SimpleDhcpL2RelayCountersStore store;
Saurav Dasbd5ce9c2020-09-04 18:46:45 -070060 private final Logger log = getLogger(getClass());
61 Map<String, DhcpAllocationInfo> allocs;
Amit Ghosh8951f042017-08-10 13:48:10 +010062
63 ComponentConfigService mockConfigService =
Jonathan Hart77ca3152020-02-21 14:31:21 -080064 createMock(ComponentConfigService.class);
Amit Ghosh8951f042017-08-10 13:48:10 +010065
66 /**
67 * Sets up the services required by the dhcpl2relay app.
68 */
69 @Before
70 public void setUp() {
71 dhcpL2Relay = new DhcpL2Relay();
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030072 dhcpL2Relay.cfgService = new DhcpL2RelayConfigTest.TestNetworkConfigRegistry();
Saurav Dasb4e3e102018-10-02 15:31:17 -070073 dhcpL2Relay.coreService = new MockCoreServiceAdapter();
74 dhcpL2Relay.flowObjectiveService = new FlowObjectiveServiceAdapter();
Amit Ghosh8951f042017-08-10 13:48:10 +010075 dhcpL2Relay.packetService = new MockPacketService();
76 dhcpL2Relay.componentConfigService = mockConfigService;
77 dhcpL2Relay.deviceService = new MockDeviceService();
Gamze Abakac806c6c2018-12-03 12:49:46 +000078 dhcpL2Relay.sadisService = new MockSadisService();
Amit Ghosh8951f042017-08-10 13:48:10 +010079 dhcpL2Relay.hostService = new MockHostService();
80 dhcpL2Relay.mastershipService = new MockMastershipService();
Gamze Abakaa64b3bc2020-01-31 06:51:43 +000081 dhcpL2Relay.dhcpL2RelayCounters = new MockDhcpL2RelayCountersStore();
Jonathan Hart617bc3e2020-02-14 10:42:23 -080082 dhcpL2Relay.storageService = new TestStorageService();
83 dhcpL2Relay.leadershipService = new LeadershipServiceAdapter();
Jonathan Hartc36c9552018-07-31 15:07:53 -040084 TestUtils.setField(dhcpL2Relay, "eventDispatcher", new TestEventDispatcher());
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030085 dhcpL2Relay.refreshService = new MockExecutor(dhcpL2Relay.refreshService);
86 dhcpL2Relay.activate(new DhcpL2RelayTestBase.MockComponentContext());
87 store = new SimpleDhcpL2RelayCountersStore();
Jonathan Hart77ca3152020-02-21 14:31:21 -080088 store.storageService = new TestStorageService();
89 store.leadershipService = new LeadershipServiceAdapter();
90 store.clusterService = new ClusterServiceAdapter();
91 store.clusterCommunicationService = new ClusterCommunicationServiceAdapter();
92 store.componentConfigService = mockConfigService;
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030093 TestUtils.setField(store, "eventDispatcher", new TestEventDispatcher());
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -080094 TestUtils.setField(dhcpL2Relay, "packetProcessorExecutor", MoreExecutors.newDirectExecutorService());
Jonathan Hart77ca3152020-02-21 14:31:21 -080095 store.activate(new MockComponentContext());
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -030096 dhcpL2Relay.dhcpL2RelayCounters = this.store;
Amit Ghosh8951f042017-08-10 13:48:10 +010097 }
98
99 /**
100 * Tears down the dhcpL2Relay application.
101 */
102 @After
103 public void tearDown() {
104 dhcpL2Relay.deactivate();
105 }
106
Saurav Das45861d42020-10-07 00:03:23 -0700107 private void checkAllocation(DHCP.MsgType messageType, String circuitId) {
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700108 ConnectPoint clientCp = ConnectPoint.deviceConnectPoint(OLT_DEV_ID + "/"
Saurav Das45861d42020-10-07 00:03:23 -0700109 + String.valueOf(CLIENT_PORT));
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700110 allocs = dhcpL2Relay.getAllocationInfo();
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800111 assertEquals(1, allocs.size());
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700112 allocs.forEach((k, v) -> {
113 log.info("Allocation {} : {}", k, v);
114 assertEquals(v.type(), messageType);
115 assertEquals(v.macAddress(), CLIENT_MAC);
116 assertEquals(v.location(), clientCp);
Saurav Das45861d42020-10-07 00:03:23 -0700117 assertEquals(v.circuitId(), circuitId);
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700118 });
119 }
120
121 @Test
122 public void testMultipleAllocations() throws Exception {
123 dhcpL2Relay.clearAllocations();
124 // Trigger a discover from one RG on port 32
125 MacAddress mac32 = MacAddress.valueOf("b4:96:91:0c:4f:e4");
126 VlanId vlan32a = VlanId.vlanId((short) 801);
127 Ethernet discover32a = constructDhcpDiscoverPacket(
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800128 mac32, vlan32a, (short) 0);
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700129 ConnectPoint client32 = ConnectPoint.deviceConnectPoint(
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800130 "of:0000b86a974385f7/32");
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700131 sendPacket(discover32a, client32);
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800132
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700133 allocs = dhcpL2Relay.getAllocationInfo();
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800134 assertEquals(1, allocs.size());
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700135
136 //Trigger a discover from another RG on port 4112
137 MacAddress mac4112 = MacAddress.valueOf("b4:96:91:0c:4f:c9");
138 VlanId vlan4112 = VlanId.vlanId((short) 101);
139 Ethernet discover4112 = constructDhcpDiscoverPacket(
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800140 mac4112, vlan4112,
141 (short) 0);
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700142 ConnectPoint client4112 = ConnectPoint.deviceConnectPoint(
143 "of:0000b86a974385f7/4112");
144 sendPacket(discover4112, client4112);
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800145
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700146 allocs = dhcpL2Relay.getAllocationInfo();
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800147 assertEquals(2, allocs.size());
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700148
149 // Trigger a discover for another service with a different vlan
150 // from the same UNI port 32
151 VlanId vlan32b = VlanId.vlanId((short) 802);
152 Ethernet discover32b = constructDhcpDiscoverPacket(
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800153 mac32, vlan32b, (short) 0);
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700154 sendPacket(discover32b, client32);
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800155
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700156 allocs = dhcpL2Relay.getAllocationInfo();
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800157 assertEquals(3, allocs.size());
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700158
159 allocs.forEach((k, v) -> {
160 log.info("Allocation {} : {}", k, v);
161 assertEquals(v.type(), DHCP.MsgType.DHCPDISCOVER);
162 if (v.subscriberId().equals("ALPHe3d1cea3-1")) {
163 assertEquals(v.macAddress(), mac32);
164 assertEquals(v.location(), client32);
165 if (!(v.vlanId().equals(vlan32a) || v.vlanId().equals(vlan32b))) {
166 assert false;
167 }
168 } else if (v.subscriberId().equals("ALPHe3d1ceb7-1")) {
169 assertEquals(v.macAddress(), mac4112);
170 assertEquals(v.location(), client4112);
171 assertEquals(v.vlanId(), vlan4112);
172 } else {
173 assert false;
174 }
175 });
176
177 dhcpL2Relay.clearAllocations();
178 assert dhcpL2Relay.getAllocationInfo().size() == 0;
179 }
180
Amit Ghosh8951f042017-08-10 13:48:10 +0100181 /**
Saurav Das45861d42020-10-07 00:03:23 -0700182 * Tests the DHCP relay app by sending DHCP discovery Packet. The circuitId
183 * and remote-Id for this client is operator defined in MockSadis.
Amit Ghosh8951f042017-08-10 13:48:10 +0100184 *
185 * @throws Exception when an unhandled error occurs
186 */
187 @Test
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800188 public void testDhcpDiscover() throws Exception {
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700189 // Sending DHCP Discover packet
190 dhcpL2Relay.clearAllocations();
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530191 Ethernet discoverPacket = constructDhcpDiscoverPacket(CLIENT_MAC);
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700192 ConnectPoint clientCp = ConnectPoint.deviceConnectPoint(OLT_DEV_ID + "/"
Saurav Das45861d42020-10-07 00:03:23 -0700193 + String.valueOf(CLIENT_PORT));
194 // send a copy of the packet as the app code modifies the sent packet
195 sendPacket(discoverPacket.duplicate(), clientCp);
Amit Ghosh8951f042017-08-10 13:48:10 +0100196
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530197 Ethernet discoverRelayed = (Ethernet) getPacket();
Amit Ghosh8951f042017-08-10 13:48:10 +0100198 compareClientPackets(discoverPacket, discoverRelayed);
Saurav Das45861d42020-10-07 00:03:23 -0700199 checkAllocation(DHCP.MsgType.DHCPDISCOVER, CLIENT_CIRCUIT_ID);
200 }
201
202 /**
203 * Tests the addition of app-defined circuit id, when this client's
204 * MockSadis config for circiutId is empty. The remoteId is configured.
205 *
206 * @throws Exception when an unhandled error occurs
207 */
208 @Test
209 public void testDhcpDiscoverEmptyCircuitId() throws Exception {
210 dhcpL2Relay.clearAllocations();
211 MacAddress mac32 = MacAddress.valueOf("b4:96:91:0c:4f:e4");
212 VlanId vlan32a = VlanId.vlanId((short) 801); // defined in mockSadis
213 VlanId qinq32a = VlanId.vlanId((short) 111);
214 Ethernet discover32a = constructDhcpDiscoverPacket(mac32, vlan32a,
215 (short) 0);
216 ConnectPoint client32 = ConnectPoint
217 .deviceConnectPoint("of:0000b86a974385f7/32");
218 sendPacket(discover32a.duplicate(), client32);
219 Ethernet discoverRelayed = (Ethernet) getPacket();
220 // empty circuitId in sadis for client32 should result in app defined
221 // circuitId
222 String expectedCircuitId = client32 + ":vlan" + vlan32a + ":pcp-1";
223 compareClientPackets(discover32a, discoverRelayed,
224 qinq32a, vlan32a, CLIENT_C_PBIT,
225 expectedCircuitId,
226 CLIENT_REMOTE_ID);
227 allocs = dhcpL2Relay.getAllocationInfo();
228 allocs.forEach((k, v) -> {
229 log.info("Allocation {} : {}", k, v);
230 assertEquals(v.circuitId(), expectedCircuitId);
231 });
232 }
233
234 /**
235 * Tests the addition of app-defined circuit id, when this client's
236 * MockSadis config for circuitId and remoteId are null. In addition, it
237 * tests that the configured downstream-pcp is included in the circuitId.
238 *
239 * @throws Exception when an unhandled error occurs
240 */
241 @Test
242 public void testDhcpDiscoverNullIds() throws Exception {
243 dhcpL2Relay.clearAllocations();
244 MacAddress mac4112 = MacAddress.valueOf("b4:96:91:0c:4f:c9");
245 VlanId vlan4112 = VlanId.vlanId((short) 101);
246 VlanId qinq4112 = VlanId.vlanId((short) 222);
247 Ethernet discover4112 = constructDhcpDiscoverPacket(mac4112, vlan4112,
248 (short) 0);
249 ConnectPoint client4112 = ConnectPoint
250 .deviceConnectPoint("of:0000b86a974385f7/4112");
251 sendPacket(discover4112.duplicate(), client4112);
252 Ethernet discoverRelayed = (Ethernet) getPacket();
253 // null circuitId in sadis for client32 should result in app defined
254 // circuitId. remoteId should not be there. Correct downstream pbit
255 // should be used
256 String expectedCircuitId = client4112 + ":vlan" + vlan4112 + ":pcp5";
257 compareClientPackets(discover4112, discoverRelayed,
258 qinq4112, vlan4112, CLIENT_C_PBIT,
259 expectedCircuitId,
260 null);
261 allocs = dhcpL2Relay.getAllocationInfo();
262 allocs.forEach((k, v) -> {
263 log.info("Allocation {} : {}", k, v);
264 assertEquals(v.circuitId(), expectedCircuitId);
265 });
Amit Ghosh8951f042017-08-10 13:48:10 +0100266 }
267
268 /**
269 * Tests the DHCP relay app by sending DHCP Request Packet.
270 *
271 * @throws Exception when an unhandled error occurs
272 */
273 @Test
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800274 public void testDhcpRequest() throws Exception {
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700275 // Sending DHCP Request packet
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530276 Ethernet requestPacket = constructDhcpRequestPacket(CLIENT_MAC);
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700277 ConnectPoint clientCp = ConnectPoint.deviceConnectPoint(OLT_DEV_ID + "/"
Saurav Das45861d42020-10-07 00:03:23 -0700278 + String.valueOf(CLIENT_PORT));
279 sendPacket(requestPacket.duplicate(), clientCp);
Amit Ghosh8951f042017-08-10 13:48:10 +0100280
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530281 Ethernet requestRelayed = (Ethernet) getPacket();
Amit Ghosh8951f042017-08-10 13:48:10 +0100282 compareClientPackets(requestPacket, requestRelayed);
Saurav Das45861d42020-10-07 00:03:23 -0700283 checkAllocation(DHCP.MsgType.DHCPREQUEST, CLIENT_CIRCUIT_ID);
Amit Ghosh8951f042017-08-10 13:48:10 +0100284 }
285
286 /**
Saurav Das45861d42020-10-07 00:03:23 -0700287 * Tests the DHCP relay app by sending DHCP Offer Packet with app-defined
288 * circuit id. App should use the circuit id for forwarding.
Amit Ghosh8951f042017-08-10 13:48:10 +0100289 *
290 * @throws Exception when an unhandled error occurs
291 */
292 @Test
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800293 public void testDhcpOffer() throws InterruptedException {
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700294 // Sending DHCP Offer packet
Saurav Das45861d42020-10-07 00:03:23 -0700295 Ethernet offerPacket = constructDhcpOfferPacket(SERVER_MAC, CLIENT_MAC,
296 DESTINATION_ADDRESS_IP,
297 DHCP_CLIENT_IP_ADDRESS);
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700298 sendPacket(offerPacket, ConnectPoint.deviceConnectPoint(OLT_DEV_ID + "/"
Saurav Das45861d42020-10-07 00:03:23 -0700299 + String.valueOf(UPLINK_PORT)));
Amit Ghosh8951f042017-08-10 13:48:10 +0100300
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530301 Ethernet offerRelayed = (Ethernet) getPacket();
Amit Ghosh8951f042017-08-10 13:48:10 +0100302 compareServerPackets(offerPacket, offerRelayed);
Saurav Das45861d42020-10-07 00:03:23 -0700303 String expectedCircuitId = OLT_DEV_ID + "/" + CLIENT_PORT + ":vlan"
304 + CLIENT_C_TAG + ":pcp" + CLIENT_C_PBIT;
305 checkAllocation(DHCP.MsgType.DHCPOFFER, expectedCircuitId);
Amit Ghosh8951f042017-08-10 13:48:10 +0100306 }
307
308 /**
Saurav Das45861d42020-10-07 00:03:23 -0700309 * Tests the DHCP relay app by sending DHCP Ack Packet with operator defined
310 * circuit id. App should ignore circuit Id and do a host lookup.
Amit Ghosh8951f042017-08-10 13:48:10 +0100311 *
312 * @throws Exception when an unhandled error occurs
313 */
314 @Test
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800315 public void testDhcpAck() throws InterruptedException {
Amit Ghosh8951f042017-08-10 13:48:10 +0100316
Saurav Das45861d42020-10-07 00:03:23 -0700317 Ethernet ackPacket = constructDhcpAckPacket(SERVER_MAC, CLIENT_MAC,
318 DESTINATION_ADDRESS_IP,
319 DHCP_CLIENT_IP_ADDRESS);
Amit Ghosh8951f042017-08-10 13:48:10 +0100320
Saurav Dasbd5ce9c2020-09-04 18:46:45 -0700321 sendPacket(ackPacket, ConnectPoint.deviceConnectPoint(OLT_DEV_ID + "/"
Saurav Das45861d42020-10-07 00:03:23 -0700322 + String.valueOf(UPLINK_PORT)));
Amit Ghosh8951f042017-08-10 13:48:10 +0100323
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530324 Ethernet ackRelayed = (Ethernet) getPacket();
Amit Ghosh8951f042017-08-10 13:48:10 +0100325 compareServerPackets(ackPacket, ackRelayed);
Saurav Das45861d42020-10-07 00:03:23 -0700326 checkAllocation(DHCP.MsgType.DHCPACK, CLIENT_CIRCUIT_ID);
Amit Ghosh8951f042017-08-10 13:48:10 +0100327 }
328
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300329 /**
Arjun E K05ad20b2020-03-13 13:25:17 +0000330 * Tests the DHCP relay app by sending DHCP Nak Packet.
Saurav Das45861d42020-10-07 00:03:23 -0700331 * Tests app-defined option82, but uses incorrect connectPoint - packet
332 * should still be forwarded to this connectPoint (ie without host lookup).
333 * Also pbit in circuitId is -1, which means original pbit should be retained
Arjun E K05ad20b2020-03-13 13:25:17 +0000334 *
335 * @throws Exception when an unhandled error occurs
336 */
337 @Test
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800338 public void testDhcpNak() throws InterruptedException {
Saurav Das45861d42020-10-07 00:03:23 -0700339 VlanId fakeVlan = VlanId.vlanId((short) 50);
340 short fakePcp = (short) 4; // should be retained
341 VlanId expectedVlan = VlanId.vlanId((short) 111);
342 // relayed packet should have vlan 111 and retain pcp4 and be sent out
343 // of port32
344 ConnectPoint fakeCp = ConnectPoint.fromString("of:0000b86a974385f7/32");
345 String fakeCircuitId = fakeCp + ":vlan"
346 + expectedVlan + ":pcp-1";
347 Ethernet nakPacket = constructDhcpNakPacket(SERVER_MAC, CLIENT_MAC,
348 DESTINATION_ADDRESS_IP,
349 DHCP_CLIENT_IP_ADDRESS,
350 fakeVlan,
351 fakePcp);
Arjun E K05ad20b2020-03-13 13:25:17 +0000352
Saurav Das45861d42020-10-07 00:03:23 -0700353 sendPacket(nakPacket, ConnectPoint.deviceConnectPoint(OLT_DEV_ID + "/"
354 + String.valueOf(UPLINK_PORT)));
Arjun E K05ad20b2020-03-13 13:25:17 +0000355
356 Ethernet nakRelayed = (Ethernet) getPacket();
Saurav Das45861d42020-10-07 00:03:23 -0700357 compareServerPackets(nakPacket, nakRelayed, expectedVlan, fakePcp);
358
359 allocs = dhcpL2Relay.getAllocationInfo();
360 assertEquals(1, allocs.size());
361 allocs.forEach((k, v) -> {
362 log.info("Allocation {} : {}", k, v);
363 assertEquals(v.type(), DHCP.MsgType.DHCPNAK);
364 assertEquals(v.macAddress(), CLIENT_MAC);
365 assertEquals(v.location(), fakeCp);
366 assertEquals(v.circuitId(), fakeCircuitId);
367 });
Arjun E K05ad20b2020-03-13 13:25:17 +0000368 }
369
370 /**
371 * Tests the DHCP relay app by sending DHCP Decline Packet.
372 *
373 * @throws Exception when an unhandled error occurs
374 */
375 @Test
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800376 public void testDhcpDecline() throws InterruptedException {
Arjun E K05ad20b2020-03-13 13:25:17 +0000377
378 Ethernet declinePacket = constructDhcpDeclinePacket(CLIENT_MAC);
379
Saurav Das45861d42020-10-07 00:03:23 -0700380 sendPacket(declinePacket.duplicate(),
381 ConnectPoint.deviceConnectPoint(OLT_DEV_ID + "/" + 1));
Arjun E K05ad20b2020-03-13 13:25:17 +0000382
383 Ethernet declineRelayed = (Ethernet) getPacket();
384 compareClientPackets(declinePacket, declineRelayed);
Saurav Das45861d42020-10-07 00:03:23 -0700385 checkAllocation(DHCP.MsgType.DHCPDECLINE, CLIENT_CIRCUIT_ID);
Arjun E K05ad20b2020-03-13 13:25:17 +0000386 }
387
388 /**
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300389 * Tests the DHCP global counters.
390 */
391 @Test
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800392 public void testDhcpGlobalCounters() throws InterruptedException {
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300393
394 Ethernet discoverPacket = constructDhcpDiscoverPacket(CLIENT_MAC);
395 Ethernet offerPacket = constructDhcpOfferPacket(SERVER_MAC,
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800396 CLIENT_MAC, DESTINATION_ADDRESS_IP, DHCP_CLIENT_IP_ADDRESS);
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300397 Ethernet requestPacket = constructDhcpRequestPacket(CLIENT_MAC);
398 Ethernet ackPacket = constructDhcpAckPacket(SERVER_MAC,
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800399 CLIENT_MAC, DESTINATION_ADDRESS_IP, DHCP_CLIENT_IP_ADDRESS);
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300400
401 sendPacket(discoverPacket, ConnectPoint.deviceConnectPoint(OLT_DEV_ID + "/" + 1));
402 sendPacket(offerPacket, ConnectPoint.deviceConnectPoint(OLT_DEV_ID + "/" + 1));
403 sendPacket(requestPacket, ConnectPoint.deviceConnectPoint(OLT_DEV_ID + "/" + 1));
404 sendPacket(ackPacket, ConnectPoint.deviceConnectPoint(OLT_DEV_ID + "/" + 1));
405
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300406
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800407 Map<DhcpL2RelayCountersIdentifier, Long> countersMap = store.getCountersMap();
408 long discoveryValue = countersMap.get(new DhcpL2RelayCountersIdentifier(DhcpL2RelayEvent.GLOBAL_COUNTER,
409 DhcpL2RelayCounterNames.valueOf("DHCPDISCOVER")));
410 long offerValue = countersMap.get(new DhcpL2RelayCountersIdentifier(DhcpL2RelayEvent.GLOBAL_COUNTER,
411 DhcpL2RelayCounterNames.valueOf("DHCPOFFER")));
412 long requestValue = countersMap.get(new DhcpL2RelayCountersIdentifier(DhcpL2RelayEvent.GLOBAL_COUNTER,
413 DhcpL2RelayCounterNames.valueOf("DHCPREQUEST")));
414 long ackValue = countersMap.get(new DhcpL2RelayCountersIdentifier(DhcpL2RelayEvent.GLOBAL_COUNTER,
415 DhcpL2RelayCounterNames.valueOf("DHCPACK")));
Jonathan Hart77ca3152020-02-21 14:31:21 -0800416 assertEquals(1, discoveryValue);
417 assertEquals(1, offerValue);
418 assertEquals(1, requestValue);
419 assertEquals(1, ackValue);
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300420 }
421
422 /**
423 * Tests the DHCP per subscriber counters.
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300424 */
425 @Test
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800426 public void testDhcpPerSubscriberCounters() throws Exception {
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300427
428 Ethernet discoverPacket = constructDhcpDiscoverPacket(CLIENT_MAC);
429 Ethernet offerPacket = constructDhcpOfferPacket(SERVER_MAC,
430 CLIENT_MAC, DESTINATION_ADDRESS_IP, DHCP_CLIENT_IP_ADDRESS);
431 Ethernet requestPacket = constructDhcpRequestPacket(CLIENT_MAC);
432 Ethernet ackPacket = constructDhcpAckPacket(SERVER_MAC,
433 CLIENT_MAC, DESTINATION_ADDRESS_IP, DHCP_CLIENT_IP_ADDRESS);
434
435 sendPacket(discoverPacket, ConnectPoint.deviceConnectPoint(OLT_DEV_ID + "/" + 1));
436 sendPacket(offerPacket, ConnectPoint.deviceConnectPoint(OLT_DEV_ID + "/" + 1));
437 sendPacket(requestPacket, ConnectPoint.deviceConnectPoint(OLT_DEV_ID + "/" + 1));
438 sendPacket(ackPacket, ConnectPoint.deviceConnectPoint(OLT_DEV_ID + "/" + 1));
439
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300440
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800441 Map<DhcpL2RelayCountersIdentifier, Long> countersMap = store.getCountersMap();
442 long discoveryValue = countersMap.get(new DhcpL2RelayCountersIdentifier(CLIENT_ID_1,
443 DhcpL2RelayCounterNames.valueOf("DHCPDISCOVER")));
444 long offerValue = countersMap.get(new DhcpL2RelayCountersIdentifier(CLIENT_ID_1,
445 DhcpL2RelayCounterNames.valueOf("DHCPOFFER")));
446 long requestValue = countersMap.get(new DhcpL2RelayCountersIdentifier(CLIENT_ID_1,
447 DhcpL2RelayCounterNames.valueOf("DHCPREQUEST")));
448 long ackValue = countersMap.get(new DhcpL2RelayCountersIdentifier(CLIENT_ID_1,
449 DhcpL2RelayCounterNames.valueOf("DHCPACK")));
Jonathan Hart77ca3152020-02-21 14:31:21 -0800450 assertEquals(1, discoveryValue);
451 assertEquals(1, offerValue);
452 assertEquals(1, requestValue);
453 assertEquals(1, ackValue);
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300454 }
455
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530456 public void compareClientPackets(Ethernet sent, Ethernet relayed) {
Saurav Das45861d42020-10-07 00:03:23 -0700457 compareClientPackets(sent, relayed, CLIENT_S_TAG, CLIENT_C_TAG,
458 CLIENT_C_PBIT, CLIENT_CIRCUIT_ID,
459 CLIENT_REMOTE_ID);
460 }
461
462 public void compareClientPackets(Ethernet sent, Ethernet relayed,
463 VlanId expectedQinQ,
464 VlanId expectedVlan, short expectedPcp,
465 String expectedCircuitId,
466 String expectedRemoteId) {
467 // convert the sent packet to the expected relayed packet
468 sent.setSourceMACAddress(OLT_MAC_ADDRESS); // due to netconfig test in setup
469 sent.setQinQVID(expectedQinQ.toShort());
470 sent.setQinQTPID((short) 0x8100);
471 sent.setVlanID(expectedVlan.toShort());
472 sent.setPriorityCode((byte) expectedPcp);
Amit Ghosh8951f042017-08-10 13:48:10 +0100473
474 IPv4 ipv4Packet = (IPv4) sent.getPayload();
475 UDP udpPacket = (UDP) ipv4Packet.getPayload();
476 DHCP dhcpPacket = (DHCP) udpPacket.getPayload();
Jonathan Hartedbf6422018-05-02 17:30:05 -0700477 List<DhcpOption> options = Lists.newArrayList(dhcpPacket.getOptions());
Saurav Das45861d42020-10-07 00:03:23 -0700478
479 DhcpOption82Data option82 = new DhcpOption82Data();
480 option82.setAgentCircuitId(expectedCircuitId);
481 option82.setAgentRemoteId(expectedRemoteId);
Amit Ghosh8951f042017-08-10 13:48:10 +0100482
Jonathan Hartedbf6422018-05-02 17:30:05 -0700483 DhcpOption option = new DhcpOption()
Amit Ghosh8951f042017-08-10 13:48:10 +0100484 .setCode(DHCP.DHCPOptionCode.OptionCode_CircuitID.getValue())
485 .setData(option82.toByteArray())
486 .setLength(option82.length());
487
488 options.add(options.size() - 1, option);
489 dhcpPacket.setOptions(options);
Amit Ghosh8951f042017-08-10 13:48:10 +0100490
Saurav Das45861d42020-10-07 00:03:23 -0700491 byte[] sb = sent.serialize();
492 Ethernet expectedPacket = null;
493 try {
494 expectedPacket = Ethernet.deserializer()
495 .deserialize(sb, 0, sb.length);
496 } catch (DeserializationException e) {
497 log.error("exeption: {}", e.getMessage());
498 fail();
499 }
500 verifyDhcpOptions(expectedPacket, relayed);
501 assertEquals(expectedPacket, relayed);
502 }
503
504 public void verifyDhcpOptions(Ethernet expected, Ethernet relayed) {
505 DHCP de = ((DHCP) ((UDP) ((IPv4) expected.getPayload()).getPayload())
506 .getPayload());
507 DHCP dr = ((DHCP) ((UDP) ((IPv4) relayed.getPayload()).getPayload())
508 .getPayload());
509 List<DhcpOption> del = de.getOptions();
510 List<DhcpOption> der = dr.getOptions();
511 assertEquals(del.size(), der.size());
512 for (int i = 0; i < del.size(); i++) {
513 assertEquals(del.get(i), der.get(i));
514 }
Amit Ghosh8951f042017-08-10 13:48:10 +0100515 }
516
Deepa Vaddireddy5f278d62017-08-30 05:59:39 +0530517 public void compareServerPackets(Ethernet sent, Ethernet relayed) {
Saurav Das45861d42020-10-07 00:03:23 -0700518 compareServerPackets(sent, relayed, CLIENT_C_TAG, CLIENT_C_PBIT);
519 }
Amit Ghosh8951f042017-08-10 13:48:10 +0100520
Saurav Das45861d42020-10-07 00:03:23 -0700521 public void compareServerPackets(Ethernet sent, Ethernet relayed,
522 VlanId expectedVlan, short expectedPcp) {
Amit Ghosh8951f042017-08-10 13:48:10 +0100523 try {
Saurav Das45861d42020-10-07 00:03:23 -0700524 // modify sent packet to create expected packet
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800525 sent.setDestinationMACAddress(CLIENT_MAC);
526 sent.setQinQVID(NOT_PROVIDED);
527 sent.setQinQPriorityCode((byte) NOT_PROVIDED);
Saurav Das45861d42020-10-07 00:03:23 -0700528 sent.setVlanID(expectedVlan.toShort());
529 sent.setPriorityCode((byte) expectedPcp);
530 DHCP d = ((DHCP) ((UDP) ((IPv4) sent.getPayload()).getPayload())
531 .getPayload());
532 List<DhcpOption> newOptions = d.getOptions().stream()
533 .filter(option -> option
534 .getCode() != DHCP.DHCPOptionCode.OptionCode_CircuitID
535 .getValue())
536 .collect(Collectors.toList());
537 d.setOptions(newOptions);
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800538
539 final ByteBuffer byteBuffer = ByteBuffer.wrap(sent.serialize());
540 Ethernet expectedPacket = Ethernet.deserializer().deserialize(byteBuffer.array(),
541 0, byteBuffer.array().length);
542 assertEquals(expectedPacket, relayed);
Amit Ghosh8951f042017-08-10 13:48:10 +0100543 } catch (Exception e) {
Matteo Scandoloa8b6eea2018-11-27 13:47:58 -0800544 log.error(e.getMessage());
545 fail();
Amit Ghosh8951f042017-08-10 13:48:10 +0100546 }
Amit Ghosh8951f042017-08-10 13:48:10 +0100547
548 }
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000549
550 private class MockDhcpL2RelayCountersStore implements DhcpL2RelayCountersStore {
Jonathan Hart77ca3152020-02-21 14:31:21 -0800551
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000552 @Override
Jonathan Hart77ca3152020-02-21 14:31:21 -0800553 public void incrementCounter(String counterClass, DhcpL2RelayCounterNames counterType) {
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000554
555 }
556
557 @Override
Jonathan Hart77ca3152020-02-21 14:31:21 -0800558 public void setCounter(String counterClass, DhcpL2RelayCounterNames counterType, Long value) {
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000559
560 }
561
562 @Override
Jonathan Hart77ca3152020-02-21 14:31:21 -0800563 public DhcpL2RelayStatistics getCounters() {
564 return new DhcpL2RelayStatistics();
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000565 }
566
567 @Override
568 public void resetCounters(String counterClass) {
569
570 }
Jonathan Hart77ca3152020-02-21 14:31:21 -0800571
572 @Override
573 public void setDelegate(DhcpL2RelayStoreDelegate delegate) {
574 }
575
576 @Override
577 public void unsetDelegate(DhcpL2RelayStoreDelegate delegate) {
578 }
579
580 @Override
581 public boolean hasDelegate() {
582 return false;
583 }
Gamze Abakaa64b3bc2020-01-31 06:51:43 +0000584 }
Marcos Aurelio Carreroeaf02b82019-11-25 13:34:25 -0300585}