blob: e17b0049df718a3d0401b08eefab2df2040ef454 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Neale Rannsfca0c242017-01-13 07:57:46 -08002
3import unittest
4import socket
Neale Ranns3466c302017-02-16 07:45:03 -08005import struct
Ole Troan12966a72019-10-18 14:33:54 +02006import six
Neale Rannsfca0c242017-01-13 07:57:46 -08007
John Lo70bfcaf2017-11-14 13:19:26 -05008from framework import VppTestCase, VppTestRunner, running_extended_tests
Andrew Yourtchenko06f32812021-01-14 10:19:08 +00009from framework import tag_run_solo
Neale Ranns3466c302017-02-16 07:45:03 -080010from vpp_neighbor import VppNeighbor
Neale Ranns15002542017-09-10 04:39:11 -070011from vpp_ip_route import find_route, VppIpTable
Neale Ranns2a3ea492017-04-19 05:24:40 -070012from util import mk_ll_addr
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070013import scapy.compat
Neale Ranns038e1df2019-07-19 14:01:02 +000014from scapy.layers.l2 import Ether, getmacbyip, ARP, Dot1Q
Neale Rannsfca0c242017-01-13 07:57:46 -080015from scapy.layers.inet import IP, UDP, ICMP
Neale Ranns2bc94022018-02-25 12:27:18 -080016from scapy.layers.inet6 import IPv6, in6_getnsmac
17from scapy.utils6 import in6_mactoifaceid
Neale Rannsfca0c242017-01-13 07:57:46 -080018from scapy.layers.dhcp import DHCP, BOOTP, DHCPTypes
19from scapy.layers.dhcp6 import DHCP6, DHCP6_Solicit, DHCP6_RelayForward, \
20 DHCP6_RelayReply, DHCP6_Advertise, DHCP6OptRelayMsg, DHCP6OptIfaceId, \
Neale Ranns3466c302017-02-16 07:45:03 -080021 DHCP6OptStatusCode, DHCP6OptVSS, DHCP6OptClientLinkLayerAddr, DHCP6_Request
snaramre5d4b8912019-12-13 23:39:35 +000022from socket import AF_INET, AF_INET6, inet_pton, inet_ntop
Neale Rannsfca0c242017-01-13 07:57:46 -080023from scapy.utils6 import in6_ptop
Neale Ranns038e1df2019-07-19 14:01:02 +000024from vpp_papi import mac_pton, VppEnum
25from vpp_sub_interface import VppDot1QSubint
26from vpp_qos import VppQosEgressMap, VppQosMark
Jakub Grajciar103ba6b2019-10-01 11:30:56 +020027from vpp_dhcp import VppDHCPClient, VppDHCPProxy
Neale Ranns038e1df2019-07-19 14:01:02 +000028
Neale Rannsfca0c242017-01-13 07:57:46 -080029
30DHCP4_CLIENT_PORT = 68
31DHCP4_SERVER_PORT = 67
32DHCP6_CLIENT_PORT = 547
33DHCP6_SERVER_PORT = 546
34
35
Andrew Yourtchenko06f32812021-01-14 10:19:08 +000036@tag_run_solo
Neale Rannsfca0c242017-01-13 07:57:46 -080037class TestDHCP(VppTestCase):
38 """ DHCP Test Case """
39
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070040 @classmethod
41 def setUpClass(cls):
42 super(TestDHCP, cls).setUpClass()
43
44 @classmethod
45 def tearDownClass(cls):
46 super(TestDHCP, cls).tearDownClass()
47
Neale Rannsfca0c242017-01-13 07:57:46 -080048 def setUp(self):
49 super(TestDHCP, self).setUp()
50
John Lo70bfcaf2017-11-14 13:19:26 -050051 # create 6 pg interfaces for pg0 to pg5
52 self.create_pg_interfaces(range(6))
Neale Ranns15002542017-09-10 04:39:11 -070053 self.tables = []
Neale Rannsfca0c242017-01-13 07:57:46 -080054
John Lo70bfcaf2017-11-14 13:19:26 -050055 # pg0 to 2 are IP configured in VRF 0, 1 and 2.
56 # pg3 to 5 are non IP-configured in VRF 0, 1 and 2.
Neale Rannsfca0c242017-01-13 07:57:46 -080057 table_id = 0
Neale Ranns15002542017-09-10 04:39:11 -070058 for table_id in range(1, 4):
59 tbl4 = VppIpTable(self, table_id)
60 tbl4.add_vpp_config()
61 self.tables.append(tbl4)
62 tbl6 = VppIpTable(self, table_id, is_ip6=1)
63 tbl6.add_vpp_config()
64 self.tables.append(tbl6)
65
66 table_id = 0
John Lo70bfcaf2017-11-14 13:19:26 -050067 for i in self.pg_interfaces[:3]:
Neale Rannsfca0c242017-01-13 07:57:46 -080068 i.admin_up()
69 i.set_table_ip4(table_id)
70 i.set_table_ip6(table_id)
71 i.config_ip4()
72 i.resolve_arp()
73 i.config_ip6()
74 i.resolve_ndp()
75 table_id += 1
76
77 table_id = 0
John Lo70bfcaf2017-11-14 13:19:26 -050078 for i in self.pg_interfaces[3:]:
Neale Rannsfca0c242017-01-13 07:57:46 -080079 i.admin_up()
80 i.set_table_ip4(table_id)
81 i.set_table_ip6(table_id)
82 table_id += 1
83
Neale Ranns4008ac92017-02-13 23:20:04 -080084 def tearDown(self):
John Lo70bfcaf2017-11-14 13:19:26 -050085 for i in self.pg_interfaces[:3]:
Neale Ranns4008ac92017-02-13 23:20:04 -080086 i.unconfig_ip4()
87 i.unconfig_ip6()
Neale Ranns15002542017-09-10 04:39:11 -070088
89 for i in self.pg_interfaces:
90 i.set_table_ip4(0)
91 i.set_table_ip6(0)
Neale Ranns4008ac92017-02-13 23:20:04 -080092 i.admin_down()
Neale Ranns15002542017-09-10 04:39:11 -070093 super(TestDHCP, self).tearDown()
Neale Ranns4008ac92017-02-13 23:20:04 -080094
Neale Rannsa2fbf6b2017-07-18 08:23:32 -070095 def verify_dhcp_has_option(self, pkt, option, value):
96 dhcp = pkt[DHCP]
97 found = False
98
99 for i in dhcp.options:
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200100 if isinstance(i, tuple):
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700101 if i[0] == option:
102 self.assertEqual(i[1], value)
103 found = True
104
105 self.assertTrue(found)
106
John Lo70bfcaf2017-11-14 13:19:26 -0500107 def validate_relay_options(self, pkt, intf, ip_addr, vpn_id, fib_id, oui):
Neale Rannsfca0c242017-01-13 07:57:46 -0800108 dhcp = pkt[DHCP]
109 found = 0
110 data = []
John Lo70bfcaf2017-11-14 13:19:26 -0500111 id_len = len(vpn_id)
Neale Rannsfca0c242017-01-13 07:57:46 -0800112
113 for i in dhcp.options:
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200114 if isinstance(i, tuple):
Neale Rannsfca0c242017-01-13 07:57:46 -0800115 if i[0] == "relay_agent_Information":
116 #
117 # There are two sb-options present - each of length 6.
118 #
119 data = i[1]
Neale Ranns20a175a2017-02-14 07:28:41 -0800120 if oui != 0:
121 self.assertEqual(len(data), 24)
John Lo70bfcaf2017-11-14 13:19:26 -0500122 elif len(vpn_id) > 0:
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200123 self.assertEqual(len(data), len(vpn_id) + 17)
Neale Ranns20a175a2017-02-14 07:28:41 -0800124 else:
125 self.assertEqual(len(data), 12)
Neale Rannsfca0c242017-01-13 07:57:46 -0800126
127 #
128 # First sub-option is ID 1, len 4, then encoded
129 # sw_if_index. This test uses low valued indicies
130 # so [2:4] are 0.
131 # The ID space is VPP internal - so no matching value
132 # scapy
133 #
Ole Troan12966a72019-10-18 14:33:54 +0200134 self.assertEqual(six.byte2int(data[0:1]), 1)
135 self.assertEqual(six.byte2int(data[1:2]), 4)
136 self.assertEqual(six.byte2int(data[2:3]), 0)
137 self.assertEqual(six.byte2int(data[3:4]), 0)
138 self.assertEqual(six.byte2int(data[4:5]), 0)
139 self.assertEqual(six.byte2int(data[5:6]),
140 intf._sw_if_index)
Neale Rannsfca0c242017-01-13 07:57:46 -0800141
142 #
143 # next sub-option is the IP address of the client side
144 # interface.
145 # sub-option ID=5, length (of a v4 address)=4
146 #
147 claddr = socket.inet_pton(AF_INET, ip_addr)
148
Ole Troan12966a72019-10-18 14:33:54 +0200149 self.assertEqual(six.byte2int(data[6:7]), 5)
150 self.assertEqual(six.byte2int(data[7:8]), 4)
Neale Rannsfca0c242017-01-13 07:57:46 -0800151 self.assertEqual(data[8], claddr[0])
152 self.assertEqual(data[9], claddr[1])
153 self.assertEqual(data[10], claddr[2])
154 self.assertEqual(data[11], claddr[3])
155
Neale Ranns20a175a2017-02-14 07:28:41 -0800156 if oui != 0:
John Lo70bfcaf2017-11-14 13:19:26 -0500157 # sub-option 151 encodes vss_type 1,
158 # the 3 byte oui and the 4 byte fib_id
159 self.assertEqual(id_len, 0)
Ole Troan12966a72019-10-18 14:33:54 +0200160 self.assertEqual(six.byte2int(data[12:13]), 151)
161 self.assertEqual(six.byte2int(data[13:14]), 8)
162 self.assertEqual(six.byte2int(data[14:15]), 1)
163 self.assertEqual(six.byte2int(data[15:16]), 0)
164 self.assertEqual(six.byte2int(data[16:17]), 0)
165 self.assertEqual(six.byte2int(data[17:18]), oui)
166 self.assertEqual(six.byte2int(data[18:19]), 0)
167 self.assertEqual(six.byte2int(data[19:20]), 0)
168 self.assertEqual(six.byte2int(data[20:21]), 0)
169 self.assertEqual(six.byte2int(data[21:22]), fib_id)
Neale Ranns20a175a2017-02-14 07:28:41 -0800170
171 # VSS control sub-option
Ole Troan12966a72019-10-18 14:33:54 +0200172 self.assertEqual(six.byte2int(data[22:23]), 152)
173 self.assertEqual(six.byte2int(data[23:24]), 0)
Neale Ranns20a175a2017-02-14 07:28:41 -0800174
John Lo70bfcaf2017-11-14 13:19:26 -0500175 if id_len > 0:
176 # sub-option 151 encode vss_type of 0
177 # followerd by vpn_id in ascii
178 self.assertEqual(oui, 0)
Ole Troan12966a72019-10-18 14:33:54 +0200179 self.assertEqual(six.byte2int(data[12:13]), 151)
180 self.assertEqual(six.byte2int(data[13:14]), id_len + 1)
181 self.assertEqual(six.byte2int(data[14:15]), 0)
182 self.assertEqual(data[15:15 + id_len].decode('ascii'),
183 vpn_id)
John Lo70bfcaf2017-11-14 13:19:26 -0500184
185 # VSS control sub-option
Ole Troan12966a72019-10-18 14:33:54 +0200186 self.assertEqual(six.byte2int(data[15 + len(vpn_id):
187 16 + len(vpn_id)]),
188 152)
189 self.assertEqual(six.byte2int(data[16 + len(vpn_id):
190 17 + len(vpn_id)]),
191 0)
John Lo70bfcaf2017-11-14 13:19:26 -0500192
Neale Rannsfca0c242017-01-13 07:57:46 -0800193 found = 1
194 self.assertTrue(found)
195
196 return data
197
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700198 def verify_dhcp_msg_type(self, pkt, name):
199 dhcp = pkt[DHCP]
200 found = False
201 for o in dhcp.options:
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200202 if isinstance(o, tuple):
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700203 if o[0] == "message-type" \
204 and DHCPTypes[o[1]] == name:
205 found = True
206 self.assertTrue(found)
207
John Lo70bfcaf2017-11-14 13:19:26 -0500208 def verify_dhcp_offer(self, pkt, intf, vpn_id="", fib_id=0, oui=0):
Neale Rannsfca0c242017-01-13 07:57:46 -0800209 ether = pkt[Ether]
210 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
211 self.assertEqual(ether.src, intf.local_mac)
212
213 ip = pkt[IP]
214 self.assertEqual(ip.dst, "255.255.255.255")
215 self.assertEqual(ip.src, intf.local_ip4)
216
217 udp = pkt[UDP]
218 self.assertEqual(udp.dport, DHCP4_CLIENT_PORT)
219 self.assertEqual(udp.sport, DHCP4_SERVER_PORT)
220
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700221 self.verify_dhcp_msg_type(pkt, "offer")
Neale Ranns3466c302017-02-16 07:45:03 -0800222 data = self.validate_relay_options(pkt, intf, intf.local_ip4,
John Lo70bfcaf2017-11-14 13:19:26 -0500223 vpn_id, fib_id, oui)
Neale Rannsfca0c242017-01-13 07:57:46 -0800224
Neale Ranns038e1df2019-07-19 14:01:02 +0000225 def verify_orig_dhcp_pkt(self, pkt, intf, dscp, l2_bc=True):
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700226 ether = pkt[Ether]
Neale Ranns99536f42019-07-25 06:11:58 -0700227 if l2_bc:
228 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
229 else:
230 self.assertEqual(ether.dst, intf.remote_mac)
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700231 self.assertEqual(ether.src, intf.local_mac)
232
233 ip = pkt[IP]
Neale Ranns99536f42019-07-25 06:11:58 -0700234
235 if (l2_bc):
236 self.assertEqual(ip.dst, "255.255.255.255")
237 self.assertEqual(ip.src, "0.0.0.0")
238 else:
239 self.assertEqual(ip.dst, intf.remote_ip4)
240 self.assertEqual(ip.src, intf.local_ip4)
Neale Ranns038e1df2019-07-19 14:01:02 +0000241 self.assertEqual(ip.tos, dscp)
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700242
243 udp = pkt[UDP]
244 self.assertEqual(udp.dport, DHCP4_SERVER_PORT)
245 self.assertEqual(udp.sport, DHCP4_CLIENT_PORT)
246
Neale Ranns54c6dc42018-01-17 10:29:10 -0800247 def verify_orig_dhcp_discover(self, pkt, intf, hostname, client_id=None,
Neale Ranns038e1df2019-07-19 14:01:02 +0000248 broadcast=True, dscp=0):
249 self.verify_orig_dhcp_pkt(pkt, intf, dscp)
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700250
251 self.verify_dhcp_msg_type(pkt, "discover")
Ole Troan12966a72019-10-18 14:33:54 +0200252 self.verify_dhcp_has_option(pkt, "hostname",
253 hostname.encode('ascii'))
Neale Ranns51822bf2017-07-18 09:26:53 -0700254 if client_id:
Dave Barach211b9f62019-11-13 17:12:47 -0500255 client_id = '\x00' + client_id
Ole Troan12966a72019-10-18 14:33:54 +0200256 self.verify_dhcp_has_option(pkt, "client_id",
257 client_id.encode('ascii'))
Neale Ranns808c5b22017-08-02 05:15:07 -0700258 bootp = pkt[BOOTP]
259 self.assertEqual(bootp.ciaddr, "0.0.0.0")
260 self.assertEqual(bootp.giaddr, "0.0.0.0")
Neale Ranns54c6dc42018-01-17 10:29:10 -0800261 if broadcast:
262 self.assertEqual(bootp.flags, 0x8000)
263 else:
264 self.assertEqual(bootp.flags, 0x0000)
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700265
Neale Ranns54c6dc42018-01-17 10:29:10 -0800266 def verify_orig_dhcp_request(self, pkt, intf, hostname, ip,
Neale Ranns99536f42019-07-25 06:11:58 -0700267 broadcast=True,
Neale Ranns038e1df2019-07-19 14:01:02 +0000268 l2_bc=True,
269 dscp=0):
270 self.verify_orig_dhcp_pkt(pkt, intf, dscp, l2_bc=l2_bc)
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700271
272 self.verify_dhcp_msg_type(pkt, "request")
Ole Troan12966a72019-10-18 14:33:54 +0200273 self.verify_dhcp_has_option(pkt, "hostname",
274 hostname.encode('ascii'))
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700275 self.verify_dhcp_has_option(pkt, "requested_addr", ip)
Neale Ranns808c5b22017-08-02 05:15:07 -0700276 bootp = pkt[BOOTP]
Neale Ranns99536f42019-07-25 06:11:58 -0700277
278 if l2_bc:
279 self.assertEqual(bootp.ciaddr, "0.0.0.0")
280 else:
281 self.assertEqual(bootp.ciaddr, intf.local_ip4)
Neale Ranns808c5b22017-08-02 05:15:07 -0700282 self.assertEqual(bootp.giaddr, "0.0.0.0")
Neale Ranns99536f42019-07-25 06:11:58 -0700283
Neale Ranns54c6dc42018-01-17 10:29:10 -0800284 if broadcast:
285 self.assertEqual(bootp.flags, 0x8000)
286 else:
287 self.assertEqual(bootp.flags, 0x0000)
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700288
289 def verify_relayed_dhcp_discover(self, pkt, intf, src_intf=None,
290 fib_id=0, oui=0,
John Lo70bfcaf2017-11-14 13:19:26 -0500291 vpn_id="",
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700292 dst_mac=None, dst_ip=None):
Neale Ranns3466c302017-02-16 07:45:03 -0800293 if not dst_mac:
294 dst_mac = intf.remote_mac
295 if not dst_ip:
296 dst_ip = intf.remote_ip4
297
Neale Rannsfca0c242017-01-13 07:57:46 -0800298 ether = pkt[Ether]
Neale Ranns3466c302017-02-16 07:45:03 -0800299 self.assertEqual(ether.dst, dst_mac)
Neale Rannsfca0c242017-01-13 07:57:46 -0800300 self.assertEqual(ether.src, intf.local_mac)
301
302 ip = pkt[IP]
Neale Ranns3466c302017-02-16 07:45:03 -0800303 self.assertEqual(ip.dst, dst_ip)
Neale Rannsfca0c242017-01-13 07:57:46 -0800304 self.assertEqual(ip.src, intf.local_ip4)
305
306 udp = pkt[UDP]
307 self.assertEqual(udp.dport, DHCP4_SERVER_PORT)
308 self.assertEqual(udp.sport, DHCP4_CLIENT_PORT)
309
310 dhcp = pkt[DHCP]
311
312 is_discover = False
313 for o in dhcp.options:
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200314 if isinstance(o, tuple):
Neale Rannsfca0c242017-01-13 07:57:46 -0800315 if o[0] == "message-type" \
316 and DHCPTypes[o[1]] == "discover":
317 is_discover = True
318 self.assertTrue(is_discover)
319
Neale Ranns20a175a2017-02-14 07:28:41 -0800320 data = self.validate_relay_options(pkt, src_intf,
321 src_intf.local_ip4,
John Lo70bfcaf2017-11-14 13:19:26 -0500322 vpn_id,
Neale Ranns20a175a2017-02-14 07:28:41 -0800323 fib_id, oui)
324 return data
Neale Rannsfca0c242017-01-13 07:57:46 -0800325
326 def verify_dhcp6_solicit(self, pkt, intf,
327 peer_ip, peer_mac,
John Lo70bfcaf2017-11-14 13:19:26 -0500328 vpn_id="",
Neale Rannsfca0c242017-01-13 07:57:46 -0800329 fib_id=0,
Neale Ranns3466c302017-02-16 07:45:03 -0800330 oui=0,
331 dst_mac=None,
332 dst_ip=None):
333 if not dst_mac:
334 dst_mac = intf.remote_mac
335 if not dst_ip:
336 dst_ip = in6_ptop(intf.remote_ip6)
337
Neale Rannsfca0c242017-01-13 07:57:46 -0800338 ether = pkt[Ether]
Neale Ranns3466c302017-02-16 07:45:03 -0800339 self.assertEqual(ether.dst, dst_mac)
Neale Rannsfca0c242017-01-13 07:57:46 -0800340 self.assertEqual(ether.src, intf.local_mac)
341
342 ip = pkt[IPv6]
Neale Ranns3466c302017-02-16 07:45:03 -0800343 self.assertEqual(in6_ptop(ip.dst), dst_ip)
Neale Rannsfca0c242017-01-13 07:57:46 -0800344 self.assertEqual(in6_ptop(ip.src), in6_ptop(intf.local_ip6))
345
346 udp = pkt[UDP]
347 self.assertEqual(udp.dport, DHCP6_CLIENT_PORT)
348 self.assertEqual(udp.sport, DHCP6_SERVER_PORT)
349
350 relay = pkt[DHCP6_RelayForward]
351 self.assertEqual(in6_ptop(relay.peeraddr), in6_ptop(peer_ip))
352 oid = pkt[DHCP6OptIfaceId]
353 cll = pkt[DHCP6OptClientLinkLayerAddr]
354 self.assertEqual(cll.optlen, 8)
355 self.assertEqual(cll.lltype, 1)
356 self.assertEqual(cll.clladdr, peer_mac)
357
John Lo70bfcaf2017-11-14 13:19:26 -0500358 id_len = len(vpn_id)
359
Neale Ranns20a175a2017-02-14 07:28:41 -0800360 if fib_id != 0:
John Lo70bfcaf2017-11-14 13:19:26 -0500361 self.assertEqual(id_len, 0)
Neale Ranns20a175a2017-02-14 07:28:41 -0800362 vss = pkt[DHCP6OptVSS]
363 self.assertEqual(vss.optlen, 8)
364 self.assertEqual(vss.type, 1)
365 # the OUI and FIB-id are really 3 and 4 bytes resp.
366 # but the tested range is small
Ole Troan12966a72019-10-18 14:33:54 +0200367 self.assertEqual(six.byte2int(vss.data[0:1]), 0)
368 self.assertEqual(six.byte2int(vss.data[1:2]), 0)
369 self.assertEqual(six.byte2int(vss.data[2:3]), oui)
370 self.assertEqual(six.byte2int(vss.data[3:4]), 0)
371 self.assertEqual(six.byte2int(vss.data[4:5]), 0)
372 self.assertEqual(six.byte2int(vss.data[5:6]), 0)
373 self.assertEqual(six.byte2int(vss.data[6:7]), fib_id)
Neale Rannsfca0c242017-01-13 07:57:46 -0800374
John Lo70bfcaf2017-11-14 13:19:26 -0500375 if id_len > 0:
376 self.assertEqual(oui, 0)
377 vss = pkt[DHCP6OptVSS]
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200378 self.assertEqual(vss.optlen, id_len + 1)
John Lo70bfcaf2017-11-14 13:19:26 -0500379 self.assertEqual(vss.type, 0)
Ole Troan12966a72019-10-18 14:33:54 +0200380 self.assertEqual(vss.data[0:id_len].decode('ascii'),
381 vpn_id)
John Lo70bfcaf2017-11-14 13:19:26 -0500382
Neale Rannsfca0c242017-01-13 07:57:46 -0800383 # the relay message should be an encoded Solicit
384 msg = pkt[DHCP6OptRelayMsg]
385 sol = DHCP6_Solicit()
Ole Troan12966a72019-10-18 14:33:54 +0200386 self.assertEqual(msg.optlen, len(sol))
387 self.assertEqual(sol, msg[1])
Neale Rannsfca0c242017-01-13 07:57:46 -0800388
389 def verify_dhcp6_advert(self, pkt, intf, peer):
390 ether = pkt[Ether]
391 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
392 self.assertEqual(ether.src, intf.local_mac)
393
394 ip = pkt[IPv6]
395 self.assertEqual(in6_ptop(ip.dst), in6_ptop(peer))
396 self.assertEqual(in6_ptop(ip.src), in6_ptop(intf.local_ip6))
397
398 udp = pkt[UDP]
399 self.assertEqual(udp.dport, DHCP6_SERVER_PORT)
400 self.assertEqual(udp.sport, DHCP6_CLIENT_PORT)
401
402 # not sure why this is not decoding
403 # adv = pkt[DHCP6_Advertise]
404
Neale Rannsf6e9b012019-01-25 06:37:15 -0800405 def wait_for_no_route(self, address, length,
406 n_tries=50, s_time=1):
407 while (n_tries):
408 if not find_route(self, address, length):
409 return True
410 n_tries = n_tries - 1
411 self.sleep(s_time)
412
413 return False
414
Neale Rannsfca0c242017-01-13 07:57:46 -0800415 def test_dhcp_proxy(self):
416 """ DHCPv4 Proxy """
417
418 #
419 # Verify no response to DHCP request without DHCP config
420 #
421 p_disc_vrf0 = (Ether(dst="ff:ff:ff:ff:ff:ff",
John Lo70bfcaf2017-11-14 13:19:26 -0500422 src=self.pg3.remote_mac) /
Neale Rannsfca0c242017-01-13 07:57:46 -0800423 IP(src="0.0.0.0", dst="255.255.255.255") /
424 UDP(sport=DHCP4_CLIENT_PORT,
425 dport=DHCP4_SERVER_PORT) /
426 BOOTP(op=1) /
427 DHCP(options=[('message-type', 'discover'), ('end')]))
428 pkts_disc_vrf0 = [p_disc_vrf0]
429 p_disc_vrf1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
John Lo70bfcaf2017-11-14 13:19:26 -0500430 src=self.pg4.remote_mac) /
Neale Rannsfca0c242017-01-13 07:57:46 -0800431 IP(src="0.0.0.0", dst="255.255.255.255") /
432 UDP(sport=DHCP4_CLIENT_PORT,
433 dport=DHCP4_SERVER_PORT) /
434 BOOTP(op=1) /
435 DHCP(options=[('message-type', 'discover'), ('end')]))
John Lo70bfcaf2017-11-14 13:19:26 -0500436 pkts_disc_vrf1 = [p_disc_vrf1]
437 p_disc_vrf2 = (Ether(dst="ff:ff:ff:ff:ff:ff",
438 src=self.pg5.remote_mac) /
439 IP(src="0.0.0.0", dst="255.255.255.255") /
440 UDP(sport=DHCP4_CLIENT_PORT,
441 dport=DHCP4_SERVER_PORT) /
442 BOOTP(op=1) /
443 DHCP(options=[('message-type', 'discover'), ('end')]))
444 pkts_disc_vrf2 = [p_disc_vrf2]
Neale Rannsfca0c242017-01-13 07:57:46 -0800445
John Lo70bfcaf2017-11-14 13:19:26 -0500446 self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf0,
Neale Rannsfca0c242017-01-13 07:57:46 -0800447 "DHCP with no configuration")
John Lo70bfcaf2017-11-14 13:19:26 -0500448 self.send_and_assert_no_replies(self.pg4, pkts_disc_vrf1,
449 "DHCP with no configuration")
450 self.send_and_assert_no_replies(self.pg5, pkts_disc_vrf2,
Neale Rannsfca0c242017-01-13 07:57:46 -0800451 "DHCP with no configuration")
452
453 #
454 # Enable DHCP proxy in VRF 0
455 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200456 server_addr = self.pg0.remote_ip4
457 src_addr = self.pg0.local_ip4
Neale Rannsfca0c242017-01-13 07:57:46 -0800458
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200459 Proxy = VppDHCPProxy(self, server_addr, src_addr, rx_vrf_id=0)
460 Proxy.add_vpp_config()
Neale Rannsfca0c242017-01-13 07:57:46 -0800461
462 #
Neale Ranns20a175a2017-02-14 07:28:41 -0800463 # Discover packets from the client are dropped because there is no
464 # IP address configured on the client facing interface
Neale Rannsfca0c242017-01-13 07:57:46 -0800465 #
John Lo70bfcaf2017-11-14 13:19:26 -0500466 self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf0,
Neale Ranns20a175a2017-02-14 07:28:41 -0800467 "Discover DHCP no relay address")
Neale Rannsfca0c242017-01-13 07:57:46 -0800468
469 #
470 # Inject a response from the server
Neale Ranns20a175a2017-02-14 07:28:41 -0800471 # dropped, because there is no IP addrees on the
Neale Ranns2dd68522017-02-16 03:38:59 -0800472 # client interfce to fill in the option.
Neale Rannsfca0c242017-01-13 07:57:46 -0800473 #
474 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
475 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
476 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_SERVER_PORT) /
477 BOOTP(op=1) /
478 DHCP(options=[('message-type', 'offer'), ('end')]))
479 pkts = [p]
480
John Lo70bfcaf2017-11-14 13:19:26 -0500481 self.send_and_assert_no_replies(self.pg3, pkts,
Neale Ranns20a175a2017-02-14 07:28:41 -0800482 "Offer DHCP no relay address")
Neale Rannsfca0c242017-01-13 07:57:46 -0800483
484 #
485 # configure an IP address on the client facing interface
486 #
John Lo70bfcaf2017-11-14 13:19:26 -0500487 self.pg3.config_ip4()
Neale Rannsfca0c242017-01-13 07:57:46 -0800488
489 #
490 # Try again with a discover packet
491 # Rx'd packet should be to the server address and from the configured
492 # source address
493 # UDP source ports are unchanged
494 # we've no option 82 config so that should be absent
495 #
John Lo70bfcaf2017-11-14 13:19:26 -0500496 self.pg3.add_stream(pkts_disc_vrf0)
Neale Rannsfca0c242017-01-13 07:57:46 -0800497 self.pg_enable_capture(self.pg_interfaces)
498 self.pg_start()
499
500 rx = self.pg0.get_capture(1)
501 rx = rx[0]
502
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700503 option_82 = self.verify_relayed_dhcp_discover(rx, self.pg0,
John Lo70bfcaf2017-11-14 13:19:26 -0500504 src_intf=self.pg3)
Neale Rannsfca0c242017-01-13 07:57:46 -0800505
506 #
507 # Create an DHCP offer reply from the server with a correctly formatted
508 # option 82. i.e. send back what we just captured
509 # The offer, sent mcast to the client, still has option 82.
510 #
511 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
512 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
513 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_SERVER_PORT) /
514 BOOTP(op=1) /
515 DHCP(options=[('message-type', 'offer'),
516 ('relay_agent_Information', option_82),
517 ('end')]))
518 pkts = [p]
519
520 self.pg0.add_stream(pkts)
521 self.pg_enable_capture(self.pg_interfaces)
522 self.pg_start()
523
John Lo70bfcaf2017-11-14 13:19:26 -0500524 rx = self.pg3.get_capture(1)
Neale Rannsfca0c242017-01-13 07:57:46 -0800525 rx = rx[0]
526
John Lo70bfcaf2017-11-14 13:19:26 -0500527 self.verify_dhcp_offer(rx, self.pg3)
Neale Rannsfca0c242017-01-13 07:57:46 -0800528
529 #
530 # Bogus Option 82:
531 #
532 # 1. not our IP address = not checked by VPP? so offer is replayed
533 # to client
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700534 bad_ip = option_82[0:8] + scapy.compat.chb(33) + option_82[9:]
Neale Rannsfca0c242017-01-13 07:57:46 -0800535
536 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
537 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
538 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_SERVER_PORT) /
539 BOOTP(op=1) /
540 DHCP(options=[('message-type', 'offer'),
541 ('relay_agent_Information', bad_ip),
542 ('end')]))
543 pkts = [p]
Neale Ranns20a175a2017-02-14 07:28:41 -0800544 self.send_and_assert_no_replies(self.pg0, pkts,
545 "DHCP offer option 82 bad address")
Neale Rannsfca0c242017-01-13 07:57:46 -0800546
547 # 2. Not a sw_if_index VPP knows
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -0700548 bad_if_index = option_82[0:2] + scapy.compat.chb(33) + option_82[3:]
Neale Rannsfca0c242017-01-13 07:57:46 -0800549
550 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
551 IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
552 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_SERVER_PORT) /
553 BOOTP(op=1) /
554 DHCP(options=[('message-type', 'offer'),
555 ('relay_agent_Information', bad_if_index),
556 ('end')]))
557 pkts = [p]
558 self.send_and_assert_no_replies(self.pg0, pkts,
559 "DHCP offer option 82 bad if index")
560
561 #
562 # Send a DHCP request in VRF 1. should be dropped.
563 #
John Lo70bfcaf2017-11-14 13:19:26 -0500564 self.send_and_assert_no_replies(self.pg4, pkts_disc_vrf1,
Neale Rannsfca0c242017-01-13 07:57:46 -0800565 "DHCP with no configuration VRF 1")
566
567 #
568 # Delete the DHCP config in VRF 0
569 # Should now drop requests.
570 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200571 Proxy.remove_vpp_config()
Neale Rannsfca0c242017-01-13 07:57:46 -0800572
John Lo70bfcaf2017-11-14 13:19:26 -0500573 self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf0,
Neale Rannsfca0c242017-01-13 07:57:46 -0800574 "DHCP config removed VRF 0")
John Lo70bfcaf2017-11-14 13:19:26 -0500575 self.send_and_assert_no_replies(self.pg4, pkts_disc_vrf1,
Neale Rannsfca0c242017-01-13 07:57:46 -0800576 "DHCP config removed VRF 1")
577
578 #
John Lo70bfcaf2017-11-14 13:19:26 -0500579 # Add DHCP config for VRF 1 & 2
Neale Rannsfca0c242017-01-13 07:57:46 -0800580 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200581 server_addr1 = self.pg1.remote_ip4
582 src_addr1 = self.pg1.local_ip4
583 Proxy1 = VppDHCPProxy(
584 self,
585 server_addr1,
586 src_addr1,
587 rx_vrf_id=1,
588 server_vrf_id=1)
589 Proxy1.add_vpp_config()
590
591 server_addr2 = self.pg2.remote_ip4
592 src_addr2 = self.pg2.local_ip4
593 Proxy2 = VppDHCPProxy(
594 self,
595 server_addr2,
596 src_addr2,
597 rx_vrf_id=2,
598 server_vrf_id=2)
599 Proxy2.add_vpp_config()
Neale Rannsfca0c242017-01-13 07:57:46 -0800600
601 #
John Lo70bfcaf2017-11-14 13:19:26 -0500602 # Confim DHCP requests ok in VRF 1 & 2.
Neale Rannsfca0c242017-01-13 07:57:46 -0800603 # - dropped on IP config on client interface
604 #
John Lo70bfcaf2017-11-14 13:19:26 -0500605 self.send_and_assert_no_replies(self.pg4, pkts_disc_vrf1,
Neale Rannsfca0c242017-01-13 07:57:46 -0800606 "DHCP config removed VRF 1")
John Lo70bfcaf2017-11-14 13:19:26 -0500607 self.send_and_assert_no_replies(self.pg5, pkts_disc_vrf2,
608 "DHCP config removed VRF 2")
Neale Rannsfca0c242017-01-13 07:57:46 -0800609
610 #
611 # configure an IP address on the client facing interface
612 #
John Lo70bfcaf2017-11-14 13:19:26 -0500613 self.pg4.config_ip4()
614 self.pg4.add_stream(pkts_disc_vrf1)
Neale Rannsfca0c242017-01-13 07:57:46 -0800615 self.pg_enable_capture(self.pg_interfaces)
616 self.pg_start()
Neale Rannsfca0c242017-01-13 07:57:46 -0800617 rx = self.pg1.get_capture(1)
618 rx = rx[0]
John Lo70bfcaf2017-11-14 13:19:26 -0500619 self.verify_relayed_dhcp_discover(rx, self.pg1, src_intf=self.pg4)
620
621 self.pg5.config_ip4()
622 self.pg5.add_stream(pkts_disc_vrf2)
623 self.pg_enable_capture(self.pg_interfaces)
624 self.pg_start()
625 rx = self.pg2.get_capture(1)
626 rx = rx[0]
627 self.verify_relayed_dhcp_discover(rx, self.pg2, src_intf=self.pg5)
Neale Rannsfca0c242017-01-13 07:57:46 -0800628
629 #
Neale Ranns20a175a2017-02-14 07:28:41 -0800630 # Add VSS config
John Lo70bfcaf2017-11-14 13:19:26 -0500631 # table=1, vss_type=1, vpn_index=1, oui=4
632 # table=2, vss_type=0, vpn_id = "ip4-table-2"
Neale Ranns02bfd642019-10-07 00:39:28 -0700633 self.vapi.dhcp_proxy_set_vss(tbl_id=1, vss_type=1,
634 vpn_index=1, oui=4, is_add=1)
635 self.vapi.dhcp_proxy_set_vss(tbl_id=2, vss_type=0,
636 vpn_ascii_id="ip4-table-2", is_add=1)
Neale Ranns20a175a2017-02-14 07:28:41 -0800637
John Lo70bfcaf2017-11-14 13:19:26 -0500638 self.pg4.add_stream(pkts_disc_vrf1)
Neale Ranns20a175a2017-02-14 07:28:41 -0800639 self.pg_enable_capture(self.pg_interfaces)
640 self.pg_start()
641
642 rx = self.pg1.get_capture(1)
643 rx = rx[0]
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700644 self.verify_relayed_dhcp_discover(rx, self.pg1,
John Lo70bfcaf2017-11-14 13:19:26 -0500645 src_intf=self.pg4,
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700646 fib_id=1, oui=4)
Neale Ranns20a175a2017-02-14 07:28:41 -0800647
John Lo70bfcaf2017-11-14 13:19:26 -0500648 self.pg5.add_stream(pkts_disc_vrf2)
649 self.pg_enable_capture(self.pg_interfaces)
650 self.pg_start()
651
652 rx = self.pg2.get_capture(1)
653 rx = rx[0]
654 self.verify_relayed_dhcp_discover(rx, self.pg2,
655 src_intf=self.pg5,
656 vpn_id="ip4-table-2")
657
Neale Ranns20a175a2017-02-14 07:28:41 -0800658 #
Neale Ranns3466c302017-02-16 07:45:03 -0800659 # Add a second DHCP server in VRF 1
660 # expect clients messages to be relay to both configured servers
661 #
662 self.pg1.generate_remote_hosts(2)
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200663 server_addr12 = self.pg1.remote_hosts[1].ip4
Neale Ranns3466c302017-02-16 07:45:03 -0800664
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200665 Proxy12 = VppDHCPProxy(
666 self,
667 server_addr12,
668 src_addr,
669 rx_vrf_id=1,
670 server_vrf_id=1)
671 Proxy12.add_vpp_config()
Neale Ranns3466c302017-02-16 07:45:03 -0800672
673 #
674 # We'll need an ARP entry for the server to send it packets
675 #
676 arp_entry = VppNeighbor(self,
677 self.pg1.sw_if_index,
678 self.pg1.remote_hosts[1].mac,
679 self.pg1.remote_hosts[1].ip4)
680 arp_entry.add_vpp_config()
681
682 #
683 # Send a discover from the client. expect two relayed messages
684 # The frist packet is sent to the second server
685 # We're not enforcing that here, it's just the way it is.
686 #
John Lo70bfcaf2017-11-14 13:19:26 -0500687 self.pg4.add_stream(pkts_disc_vrf1)
Neale Ranns3466c302017-02-16 07:45:03 -0800688 self.pg_enable_capture(self.pg_interfaces)
689 self.pg_start()
690
691 rx = self.pg1.get_capture(2)
692
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700693 option_82 = self.verify_relayed_dhcp_discover(
Neale Ranns3466c302017-02-16 07:45:03 -0800694 rx[0], self.pg1,
John Lo70bfcaf2017-11-14 13:19:26 -0500695 src_intf=self.pg4,
Neale Ranns3466c302017-02-16 07:45:03 -0800696 dst_mac=self.pg1.remote_hosts[1].mac,
697 dst_ip=self.pg1.remote_hosts[1].ip4,
698 fib_id=1, oui=4)
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700699 self.verify_relayed_dhcp_discover(rx[1], self.pg1,
John Lo70bfcaf2017-11-14 13:19:26 -0500700 src_intf=self.pg4,
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700701 fib_id=1, oui=4)
Neale Ranns3466c302017-02-16 07:45:03 -0800702
703 #
704 # Send both packets back. Client gets both.
705 #
706 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
707 IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) /
708 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_SERVER_PORT) /
709 BOOTP(op=1) /
710 DHCP(options=[('message-type', 'offer'),
711 ('relay_agent_Information', option_82),
712 ('end')]))
713 p2 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
714 IP(src=self.pg1.remote_hosts[1].ip4, dst=self.pg1.local_ip4) /
715 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_SERVER_PORT) /
716 BOOTP(op=1) /
717 DHCP(options=[('message-type', 'offer'),
718 ('relay_agent_Information', option_82),
719 ('end')]))
720 pkts = [p1, p2]
721
722 self.pg1.add_stream(pkts)
723 self.pg_enable_capture(self.pg_interfaces)
724 self.pg_start()
725
John Lo70bfcaf2017-11-14 13:19:26 -0500726 rx = self.pg4.get_capture(2)
Neale Ranns3466c302017-02-16 07:45:03 -0800727
John Lo70bfcaf2017-11-14 13:19:26 -0500728 self.verify_dhcp_offer(rx[0], self.pg4, fib_id=1, oui=4)
729 self.verify_dhcp_offer(rx[1], self.pg4, fib_id=1, oui=4)
Neale Ranns3466c302017-02-16 07:45:03 -0800730
731 #
732 # Ensure offers from non-servers are dropeed
733 #
734 p2 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
735 IP(src="8.8.8.8", dst=self.pg1.local_ip4) /
736 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_SERVER_PORT) /
737 BOOTP(op=1) /
738 DHCP(options=[('message-type', 'offer'),
739 ('relay_agent_Information', option_82),
740 ('end')]))
741 self.send_and_assert_no_replies(self.pg1, p2,
742 "DHCP offer from non-server")
743
744 #
745 # Ensure only the discover is sent to multiple servers
746 #
747 p_req_vrf1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
John Lo70bfcaf2017-11-14 13:19:26 -0500748 src=self.pg4.remote_mac) /
Neale Ranns3466c302017-02-16 07:45:03 -0800749 IP(src="0.0.0.0", dst="255.255.255.255") /
750 UDP(sport=DHCP4_CLIENT_PORT,
751 dport=DHCP4_SERVER_PORT) /
752 BOOTP(op=1) /
753 DHCP(options=[('message-type', 'request'),
754 ('end')]))
755
John Lo70bfcaf2017-11-14 13:19:26 -0500756 self.pg4.add_stream(p_req_vrf1)
Neale Ranns3466c302017-02-16 07:45:03 -0800757 self.pg_enable_capture(self.pg_interfaces)
758 self.pg_start()
759
760 rx = self.pg1.get_capture(1)
761
762 #
763 # Remove the second DHCP server
764 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200765 Proxy12.remove_vpp_config()
Neale Ranns3466c302017-02-16 07:45:03 -0800766
767 #
768 # Test we can still relay with the first
769 #
John Lo70bfcaf2017-11-14 13:19:26 -0500770 self.pg4.add_stream(pkts_disc_vrf1)
Neale Ranns3466c302017-02-16 07:45:03 -0800771 self.pg_enable_capture(self.pg_interfaces)
772 self.pg_start()
773
774 rx = self.pg1.get_capture(1)
775 rx = rx[0]
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700776 self.verify_relayed_dhcp_discover(rx, self.pg1,
John Lo70bfcaf2017-11-14 13:19:26 -0500777 src_intf=self.pg4,
Neale Rannsa2fbf6b2017-07-18 08:23:32 -0700778 fib_id=1, oui=4)
Neale Ranns3466c302017-02-16 07:45:03 -0800779
780 #
Neale Ranns20a175a2017-02-14 07:28:41 -0800781 # Remove the VSS config
782 # relayed DHCP has default vlaues in the option.
783 #
Neale Ranns02bfd642019-10-07 00:39:28 -0700784 self.vapi.dhcp_proxy_set_vss(tbl_id=1, is_add=0)
785 self.vapi.dhcp_proxy_set_vss(tbl_id=2, is_add=0)
Neale Ranns20a175a2017-02-14 07:28:41 -0800786
John Lo70bfcaf2017-11-14 13:19:26 -0500787 self.pg4.add_stream(pkts_disc_vrf1)
Neale Ranns20a175a2017-02-14 07:28:41 -0800788 self.pg_enable_capture(self.pg_interfaces)
789 self.pg_start()
790
791 rx = self.pg1.get_capture(1)
792 rx = rx[0]
John Lo70bfcaf2017-11-14 13:19:26 -0500793 self.verify_relayed_dhcp_discover(rx, self.pg1, src_intf=self.pg4)
Neale Ranns20a175a2017-02-14 07:28:41 -0800794
795 #
Neale Rannsfca0c242017-01-13 07:57:46 -0800796 # remove DHCP config to cleanup
797 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200798 Proxy1.remove_vpp_config()
799 Proxy2.remove_vpp_config()
Neale Rannsfca0c242017-01-13 07:57:46 -0800800
John Lo70bfcaf2017-11-14 13:19:26 -0500801 self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf0,
Neale Rannsfca0c242017-01-13 07:57:46 -0800802 "DHCP cleanup VRF 0")
John Lo70bfcaf2017-11-14 13:19:26 -0500803 self.send_and_assert_no_replies(self.pg4, pkts_disc_vrf1,
Neale Rannsfca0c242017-01-13 07:57:46 -0800804 "DHCP cleanup VRF 1")
John Lo70bfcaf2017-11-14 13:19:26 -0500805 self.send_and_assert_no_replies(self.pg5, pkts_disc_vrf2,
806 "DHCP cleanup VRF 2")
807
Neale Ranns15002542017-09-10 04:39:11 -0700808 self.pg3.unconfig_ip4()
John Lo70bfcaf2017-11-14 13:19:26 -0500809 self.pg4.unconfig_ip4()
810 self.pg5.unconfig_ip4()
Neale Rannsfca0c242017-01-13 07:57:46 -0800811
812 def test_dhcp6_proxy(self):
813 """ DHCPv6 Proxy"""
814 #
815 # Verify no response to DHCP request without DHCP config
816 #
817 dhcp_solicit_dst = "ff02::1:2"
John Lo70bfcaf2017-11-14 13:19:26 -0500818 dhcp_solicit_src_vrf0 = mk_ll_addr(self.pg3.remote_mac)
819 dhcp_solicit_src_vrf1 = mk_ll_addr(self.pg4.remote_mac)
820 dhcp_solicit_src_vrf2 = mk_ll_addr(self.pg5.remote_mac)
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200821 server_addr_vrf0 = self.pg0.remote_ip6
822 src_addr_vrf0 = self.pg0.local_ip6
823 server_addr_vrf1 = self.pg1.remote_ip6
824 src_addr_vrf1 = self.pg1.local_ip6
825 server_addr_vrf2 = self.pg2.remote_ip6
826 src_addr_vrf2 = self.pg2.local_ip6
Neale Rannsfca0c242017-01-13 07:57:46 -0800827
Neale Rannsfca0c242017-01-13 07:57:46 -0800828 dmac = in6_getnsmac(inet_pton(socket.AF_INET6, dhcp_solicit_dst))
John Lo70bfcaf2017-11-14 13:19:26 -0500829 p_solicit_vrf0 = (Ether(dst=dmac, src=self.pg3.remote_mac) /
Neale Rannsfca0c242017-01-13 07:57:46 -0800830 IPv6(src=dhcp_solicit_src_vrf0,
831 dst=dhcp_solicit_dst) /
832 UDP(sport=DHCP6_SERVER_PORT,
833 dport=DHCP6_CLIENT_PORT) /
834 DHCP6_Solicit())
John Lo70bfcaf2017-11-14 13:19:26 -0500835 p_solicit_vrf1 = (Ether(dst=dmac, src=self.pg4.remote_mac) /
Neale Rannsfca0c242017-01-13 07:57:46 -0800836 IPv6(src=dhcp_solicit_src_vrf1,
837 dst=dhcp_solicit_dst) /
838 UDP(sport=DHCP6_SERVER_PORT,
839 dport=DHCP6_CLIENT_PORT) /
840 DHCP6_Solicit())
John Lo70bfcaf2017-11-14 13:19:26 -0500841 p_solicit_vrf2 = (Ether(dst=dmac, src=self.pg5.remote_mac) /
842 IPv6(src=dhcp_solicit_src_vrf2,
843 dst=dhcp_solicit_dst) /
844 UDP(sport=DHCP6_SERVER_PORT,
845 dport=DHCP6_CLIENT_PORT) /
846 DHCP6_Solicit())
Neale Rannsfca0c242017-01-13 07:57:46 -0800847
John Lo70bfcaf2017-11-14 13:19:26 -0500848 self.send_and_assert_no_replies(self.pg3, p_solicit_vrf0,
Neale Rannsfca0c242017-01-13 07:57:46 -0800849 "DHCP with no configuration")
John Lo70bfcaf2017-11-14 13:19:26 -0500850 self.send_and_assert_no_replies(self.pg4, p_solicit_vrf1,
851 "DHCP with no configuration")
852 self.send_and_assert_no_replies(self.pg5, p_solicit_vrf2,
Neale Rannsfca0c242017-01-13 07:57:46 -0800853 "DHCP with no configuration")
854
855 #
856 # DHCPv6 config in VRF 0.
857 # Packets still dropped because the client facing interface has no
858 # IPv6 config
859 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200860 Proxy = VppDHCPProxy(
861 self,
862 server_addr_vrf0,
863 src_addr_vrf0,
864 rx_vrf_id=0,
865 server_vrf_id=0)
866 Proxy.add_vpp_config()
Neale Rannsfca0c242017-01-13 07:57:46 -0800867
John Lo70bfcaf2017-11-14 13:19:26 -0500868 self.send_and_assert_no_replies(self.pg3, p_solicit_vrf0,
Neale Rannsfca0c242017-01-13 07:57:46 -0800869 "DHCP with no configuration")
John Lo70bfcaf2017-11-14 13:19:26 -0500870 self.send_and_assert_no_replies(self.pg4, p_solicit_vrf1,
Neale Rannsfca0c242017-01-13 07:57:46 -0800871 "DHCP with no configuration")
872
873 #
874 # configure an IP address on the client facing interface
875 #
John Lo70bfcaf2017-11-14 13:19:26 -0500876 self.pg3.config_ip6()
Neale Rannsfca0c242017-01-13 07:57:46 -0800877
878 #
879 # Now the DHCP requests are relayed to the server
880 #
John Lo70bfcaf2017-11-14 13:19:26 -0500881 self.pg3.add_stream(p_solicit_vrf0)
Neale Rannsfca0c242017-01-13 07:57:46 -0800882 self.pg_enable_capture(self.pg_interfaces)
883 self.pg_start()
884
885 rx = self.pg0.get_capture(1)
Neale Ranns3466c302017-02-16 07:45:03 -0800886
887 self.verify_dhcp6_solicit(rx[0], self.pg0,
Neale Rannsfca0c242017-01-13 07:57:46 -0800888 dhcp_solicit_src_vrf0,
John Lo70bfcaf2017-11-14 13:19:26 -0500889 self.pg3.remote_mac)
Neale Rannsfca0c242017-01-13 07:57:46 -0800890
891 #
892 # Exception cases for rejected relay responses
893 #
894
895 # 1 - not a relay reply
896 p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
897 IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
898 UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
899 DHCP6_Advertise())
John Lo70bfcaf2017-11-14 13:19:26 -0500900 self.send_and_assert_no_replies(self.pg3, p_adv_vrf0,
Neale Rannsfca0c242017-01-13 07:57:46 -0800901 "DHCP6 not a relay reply")
902
903 # 2 - no relay message option
904 p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
905 IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
906 UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
907 DHCP6_RelayReply() /
908 DHCP6_Advertise())
John Lo70bfcaf2017-11-14 13:19:26 -0500909 self.send_and_assert_no_replies(self.pg3, p_adv_vrf0,
Neale Rannsfca0c242017-01-13 07:57:46 -0800910 "DHCP not a relay message")
911
912 # 3 - no circuit ID
913 p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
914 IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
915 UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
916 DHCP6_RelayReply() /
917 DHCP6OptRelayMsg(optlen=0) /
918 DHCP6_Advertise())
John Lo70bfcaf2017-11-14 13:19:26 -0500919 self.send_and_assert_no_replies(self.pg3, p_adv_vrf0,
Neale Rannsfca0c242017-01-13 07:57:46 -0800920 "DHCP6 no circuit ID")
921 # 4 - wrong circuit ID
922 p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
923 IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
924 UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
925 DHCP6_RelayReply() /
926 DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x05') /
927 DHCP6OptRelayMsg(optlen=0) /
928 DHCP6_Advertise())
John Lo70bfcaf2017-11-14 13:19:26 -0500929 self.send_and_assert_no_replies(self.pg3, p_adv_vrf0,
Neale Rannsfca0c242017-01-13 07:57:46 -0800930 "DHCP6 wrong circuit ID")
931
932 #
933 # Send the relay response (the advertisement)
934 # - no peer address
935 p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
936 IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
937 UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
938 DHCP6_RelayReply() /
John Lo70bfcaf2017-11-14 13:19:26 -0500939 DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') /
Neale Rannsfca0c242017-01-13 07:57:46 -0800940 DHCP6OptRelayMsg(optlen=0) /
941 DHCP6_Advertise(trid=1) /
942 DHCP6OptStatusCode(statuscode=0))
943 pkts_adv_vrf0 = [p_adv_vrf0]
944
945 self.pg0.add_stream(pkts_adv_vrf0)
946 self.pg_enable_capture(self.pg_interfaces)
947 self.pg_start()
948
John Lo70bfcaf2017-11-14 13:19:26 -0500949 rx = self.pg3.get_capture(1)
Neale Ranns3466c302017-02-16 07:45:03 -0800950
John Lo70bfcaf2017-11-14 13:19:26 -0500951 self.verify_dhcp6_advert(rx[0], self.pg3, "::")
Neale Rannsfca0c242017-01-13 07:57:46 -0800952
953 #
954 # Send the relay response (the advertisement)
955 # - with peer address
956 p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
957 IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
958 UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
959 DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf0) /
John Lo70bfcaf2017-11-14 13:19:26 -0500960 DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') /
Neale Rannsfca0c242017-01-13 07:57:46 -0800961 DHCP6OptRelayMsg(optlen=0) /
962 DHCP6_Advertise(trid=1) /
963 DHCP6OptStatusCode(statuscode=0))
964 pkts_adv_vrf0 = [p_adv_vrf0]
965
966 self.pg0.add_stream(pkts_adv_vrf0)
967 self.pg_enable_capture(self.pg_interfaces)
968 self.pg_start()
969
John Lo70bfcaf2017-11-14 13:19:26 -0500970 rx = self.pg3.get_capture(1)
Neale Ranns3466c302017-02-16 07:45:03 -0800971
John Lo70bfcaf2017-11-14 13:19:26 -0500972 self.verify_dhcp6_advert(rx[0], self.pg3, dhcp_solicit_src_vrf0)
Neale Rannsfca0c242017-01-13 07:57:46 -0800973
974 #
John Lo70bfcaf2017-11-14 13:19:26 -0500975 # Add all the config for VRF 1 & 2
Neale Rannsfca0c242017-01-13 07:57:46 -0800976 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200977 Proxy1 = VppDHCPProxy(
978 self,
979 server_addr_vrf1,
980 src_addr_vrf1,
981 rx_vrf_id=1,
982 server_vrf_id=1)
983 Proxy1.add_vpp_config()
John Lo70bfcaf2017-11-14 13:19:26 -0500984 self.pg4.config_ip6()
985
Jakub Grajciar103ba6b2019-10-01 11:30:56 +0200986 Proxy2 = VppDHCPProxy(
987 self,
988 server_addr_vrf2,
989 src_addr_vrf2,
990 rx_vrf_id=2,
991 server_vrf_id=2)
992 Proxy2.add_vpp_config()
John Lo70bfcaf2017-11-14 13:19:26 -0500993 self.pg5.config_ip6()
Neale Rannsfca0c242017-01-13 07:57:46 -0800994
995 #
996 # VRF 1 solicit
997 #
John Lo70bfcaf2017-11-14 13:19:26 -0500998 self.pg4.add_stream(p_solicit_vrf1)
Neale Rannsfca0c242017-01-13 07:57:46 -0800999 self.pg_enable_capture(self.pg_interfaces)
1000 self.pg_start()
1001
1002 rx = self.pg1.get_capture(1)
Neale Ranns3466c302017-02-16 07:45:03 -08001003
1004 self.verify_dhcp6_solicit(rx[0], self.pg1,
Neale Rannsfca0c242017-01-13 07:57:46 -08001005 dhcp_solicit_src_vrf1,
John Lo70bfcaf2017-11-14 13:19:26 -05001006 self.pg4.remote_mac)
1007
1008 #
1009 # VRF 2 solicit
1010 #
1011 self.pg5.add_stream(p_solicit_vrf2)
1012 self.pg_enable_capture(self.pg_interfaces)
1013 self.pg_start()
1014
1015 rx = self.pg2.get_capture(1)
1016
1017 self.verify_dhcp6_solicit(rx[0], self.pg2,
1018 dhcp_solicit_src_vrf2,
1019 self.pg5.remote_mac)
Neale Rannsfca0c242017-01-13 07:57:46 -08001020
1021 #
1022 # VRF 1 Advert
1023 #
1024 p_adv_vrf1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1025 IPv6(dst=self.pg1.local_ip6, src=self.pg1.remote_ip6) /
1026 UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
1027 DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) /
John Lo70bfcaf2017-11-14 13:19:26 -05001028 DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x05') /
Neale Rannsfca0c242017-01-13 07:57:46 -08001029 DHCP6OptRelayMsg(optlen=0) /
1030 DHCP6_Advertise(trid=1) /
1031 DHCP6OptStatusCode(statuscode=0))
1032 pkts_adv_vrf1 = [p_adv_vrf1]
1033
1034 self.pg1.add_stream(pkts_adv_vrf1)
1035 self.pg_enable_capture(self.pg_interfaces)
1036 self.pg_start()
1037
John Lo70bfcaf2017-11-14 13:19:26 -05001038 rx = self.pg4.get_capture(1)
Neale Ranns3466c302017-02-16 07:45:03 -08001039
John Lo70bfcaf2017-11-14 13:19:26 -05001040 self.verify_dhcp6_advert(rx[0], self.pg4, dhcp_solicit_src_vrf1)
Neale Rannsfca0c242017-01-13 07:57:46 -08001041
1042 #
1043 # Add VSS config
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001044 #
1045 self.vapi.dhcp_proxy_set_vss(
Neale Ranns02bfd642019-10-07 00:39:28 -07001046 tbl_id=1, vss_type=1, oui=4, vpn_index=1, is_ipv6=1, is_add=1)
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001047 self.vapi.dhcp_proxy_set_vss(
1048 tbl_id=2,
1049 vss_type=0,
1050 vpn_ascii_id="IPv6-table-2",
Neale Ranns02bfd642019-10-07 00:39:28 -07001051 is_ipv6=1,
1052 is_add=1)
Neale Rannsfca0c242017-01-13 07:57:46 -08001053
John Lo70bfcaf2017-11-14 13:19:26 -05001054 self.pg4.add_stream(p_solicit_vrf1)
Neale Rannsfca0c242017-01-13 07:57:46 -08001055 self.pg_enable_capture(self.pg_interfaces)
1056 self.pg_start()
1057
1058 rx = self.pg1.get_capture(1)
Neale Ranns3466c302017-02-16 07:45:03 -08001059
1060 self.verify_dhcp6_solicit(rx[0], self.pg1,
Neale Rannsfca0c242017-01-13 07:57:46 -08001061 dhcp_solicit_src_vrf1,
John Lo70bfcaf2017-11-14 13:19:26 -05001062 self.pg4.remote_mac,
Neale Rannsfca0c242017-01-13 07:57:46 -08001063 fib_id=1,
1064 oui=4)
1065
John Lo70bfcaf2017-11-14 13:19:26 -05001066 self.pg5.add_stream(p_solicit_vrf2)
1067 self.pg_enable_capture(self.pg_interfaces)
1068 self.pg_start()
1069
1070 rx = self.pg2.get_capture(1)
1071
1072 self.verify_dhcp6_solicit(rx[0], self.pg2,
1073 dhcp_solicit_src_vrf2,
1074 self.pg5.remote_mac,
1075 vpn_id="IPv6-table-2")
1076
Neale Rannsfca0c242017-01-13 07:57:46 -08001077 #
1078 # Remove the VSS config
1079 # relayed DHCP has default vlaues in the option.
1080 #
Neale Ranns02bfd642019-10-07 00:39:28 -07001081 self.vapi.dhcp_proxy_set_vss(tbl_id=1, is_ipv6=1, is_add=0)
Neale Rannsfca0c242017-01-13 07:57:46 -08001082
John Lo70bfcaf2017-11-14 13:19:26 -05001083 self.pg4.add_stream(p_solicit_vrf1)
Neale Rannsfca0c242017-01-13 07:57:46 -08001084 self.pg_enable_capture(self.pg_interfaces)
1085 self.pg_start()
1086
1087 rx = self.pg1.get_capture(1)
Neale Ranns3466c302017-02-16 07:45:03 -08001088
1089 self.verify_dhcp6_solicit(rx[0], self.pg1,
1090 dhcp_solicit_src_vrf1,
John Lo70bfcaf2017-11-14 13:19:26 -05001091 self.pg4.remote_mac)
Neale Ranns3466c302017-02-16 07:45:03 -08001092
1093 #
1094 # Add a second DHCP server in VRF 1
1095 # expect clients messages to be relay to both configured servers
1096 #
1097 self.pg1.generate_remote_hosts(2)
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001098 server_addr12 = self.pg1.remote_hosts[1].ip6
Neale Ranns3466c302017-02-16 07:45:03 -08001099
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001100 Proxy12 = VppDHCPProxy(
1101 self,
1102 server_addr12,
1103 src_addr_vrf1,
1104 rx_vrf_id=1,
1105 server_vrf_id=1)
1106 Proxy12.add_vpp_config()
Neale Ranns3466c302017-02-16 07:45:03 -08001107
1108 #
1109 # We'll need an ND entry for the server to send it packets
1110 #
1111 nd_entry = VppNeighbor(self,
1112 self.pg1.sw_if_index,
1113 self.pg1.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001114 self.pg1.remote_hosts[1].ip6)
Neale Ranns3466c302017-02-16 07:45:03 -08001115 nd_entry.add_vpp_config()
1116
1117 #
1118 # Send a discover from the client. expect two relayed messages
1119 # The frist packet is sent to the second server
1120 # We're not enforcing that here, it's just the way it is.
1121 #
John Lo70bfcaf2017-11-14 13:19:26 -05001122 self.pg4.add_stream(p_solicit_vrf1)
Neale Ranns3466c302017-02-16 07:45:03 -08001123 self.pg_enable_capture(self.pg_interfaces)
1124 self.pg_start()
1125
1126 rx = self.pg1.get_capture(2)
1127
1128 self.verify_dhcp6_solicit(rx[0], self.pg1,
1129 dhcp_solicit_src_vrf1,
John Lo70bfcaf2017-11-14 13:19:26 -05001130 self.pg4.remote_mac)
Neale Ranns3466c302017-02-16 07:45:03 -08001131 self.verify_dhcp6_solicit(rx[1], self.pg1,
1132 dhcp_solicit_src_vrf1,
John Lo70bfcaf2017-11-14 13:19:26 -05001133 self.pg4.remote_mac,
Neale Ranns3466c302017-02-16 07:45:03 -08001134 dst_mac=self.pg1.remote_hosts[1].mac,
1135 dst_ip=self.pg1.remote_hosts[1].ip6)
1136
1137 #
1138 # Send both packets back. Client gets both.
1139 #
1140 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1141 IPv6(dst=self.pg1.local_ip6, src=self.pg1.remote_ip6) /
1142 UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
1143 DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) /
John Lo70bfcaf2017-11-14 13:19:26 -05001144 DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x05') /
Neale Ranns3466c302017-02-16 07:45:03 -08001145 DHCP6OptRelayMsg(optlen=0) /
1146 DHCP6_Advertise(trid=1) /
1147 DHCP6OptStatusCode(statuscode=0))
1148 p2 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_hosts[1].mac) /
1149 IPv6(dst=self.pg1.local_ip6, src=self.pg1._remote_hosts[1].ip6) /
1150 UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
1151 DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) /
John Lo70bfcaf2017-11-14 13:19:26 -05001152 DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x05') /
Neale Ranns3466c302017-02-16 07:45:03 -08001153 DHCP6OptRelayMsg(optlen=0) /
1154 DHCP6_Advertise(trid=1) /
1155 DHCP6OptStatusCode(statuscode=0))
1156
1157 pkts = [p1, p2]
1158
1159 self.pg1.add_stream(pkts)
1160 self.pg_enable_capture(self.pg_interfaces)
1161 self.pg_start()
1162
John Lo70bfcaf2017-11-14 13:19:26 -05001163 rx = self.pg4.get_capture(2)
Neale Ranns3466c302017-02-16 07:45:03 -08001164
John Lo70bfcaf2017-11-14 13:19:26 -05001165 self.verify_dhcp6_advert(rx[0], self.pg4, dhcp_solicit_src_vrf1)
1166 self.verify_dhcp6_advert(rx[1], self.pg4, dhcp_solicit_src_vrf1)
Neale Ranns3466c302017-02-16 07:45:03 -08001167
1168 #
1169 # Ensure only solicit messages are duplicated
1170 #
John Lo70bfcaf2017-11-14 13:19:26 -05001171 p_request_vrf1 = (Ether(dst=dmac, src=self.pg4.remote_mac) /
Neale Ranns3466c302017-02-16 07:45:03 -08001172 IPv6(src=dhcp_solicit_src_vrf1,
1173 dst=dhcp_solicit_dst) /
1174 UDP(sport=DHCP6_SERVER_PORT,
1175 dport=DHCP6_CLIENT_PORT) /
1176 DHCP6_Request())
1177
John Lo70bfcaf2017-11-14 13:19:26 -05001178 self.pg4.add_stream(p_request_vrf1)
Neale Ranns3466c302017-02-16 07:45:03 -08001179 self.pg_enable_capture(self.pg_interfaces)
1180 self.pg_start()
1181
1182 rx = self.pg1.get_capture(1)
1183
1184 #
1185 # Test we drop DHCP packets from addresses that are not configured as
1186 # DHCP servers
1187 #
1188 p2 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_hosts[1].mac) /
1189 IPv6(dst=self.pg1.local_ip6, src="3001::1") /
1190 UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
1191 DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) /
John Lo70bfcaf2017-11-14 13:19:26 -05001192 DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x05') /
Neale Ranns3466c302017-02-16 07:45:03 -08001193 DHCP6OptRelayMsg(optlen=0) /
1194 DHCP6_Advertise(trid=1) /
1195 DHCP6OptStatusCode(statuscode=0))
1196 self.send_and_assert_no_replies(self.pg1, p2,
1197 "DHCP6 not from server")
1198
1199 #
1200 # Remove the second DHCP server
1201 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001202 Proxy12.remove_vpp_config()
Neale Ranns3466c302017-02-16 07:45:03 -08001203
1204 #
1205 # Test we can still relay with the first
1206 #
John Lo70bfcaf2017-11-14 13:19:26 -05001207 self.pg4.add_stream(p_solicit_vrf1)
Neale Ranns3466c302017-02-16 07:45:03 -08001208 self.pg_enable_capture(self.pg_interfaces)
1209 self.pg_start()
1210
1211 rx = self.pg1.get_capture(1)
1212
1213 self.verify_dhcp6_solicit(rx[0], self.pg1,
Neale Rannsfca0c242017-01-13 07:57:46 -08001214 dhcp_solicit_src_vrf1,
John Lo70bfcaf2017-11-14 13:19:26 -05001215 self.pg4.remote_mac)
Neale Rannsfca0c242017-01-13 07:57:46 -08001216
1217 #
1218 # Cleanup
1219 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001220 Proxy.remove_vpp_config()
1221 Proxy1.remove_vpp_config()
1222 Proxy2.remove_vpp_config()
Neale Ranns3466c302017-02-16 07:45:03 -08001223
Neale Ranns15002542017-09-10 04:39:11 -07001224 self.pg3.unconfig_ip6()
John Lo70bfcaf2017-11-14 13:19:26 -05001225 self.pg4.unconfig_ip6()
1226 self.pg5.unconfig_ip6()
Neale Rannsfca0c242017-01-13 07:57:46 -08001227
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001228 def test_dhcp_client(self):
1229 """ DHCP Client"""
1230
Neale Ranns038e1df2019-07-19 14:01:02 +00001231 vdscp = VppEnum.vl_api_ip_dscp_t
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001232 hostname = 'universal-dp'
1233
1234 self.pg_enable_capture(self.pg_interfaces)
1235
1236 #
John Lo70bfcaf2017-11-14 13:19:26 -05001237 # Configure DHCP client on PG3 and capture the discover sent
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001238 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001239 Client = VppDHCPClient(self, self.pg3.sw_if_index, hostname)
1240 Client.add_vpp_config()
1241 self.assertTrue(Client.query_vpp_config())
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001242
John Lo70bfcaf2017-11-14 13:19:26 -05001243 rx = self.pg3.get_capture(1)
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001244
John Lo70bfcaf2017-11-14 13:19:26 -05001245 self.verify_orig_dhcp_discover(rx[0], self.pg3, hostname)
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001246
1247 #
John Lo70bfcaf2017-11-14 13:19:26 -05001248 # Send back on offer, expect the request
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001249 #
John Lo70bfcaf2017-11-14 13:19:26 -05001250 p_offer = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
1251 IP(src=self.pg3.remote_ip4, dst="255.255.255.255") /
Neale Ranns808c5b22017-08-02 05:15:07 -07001252 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
Neale Ranns1f2f4b72018-03-23 11:53:12 -07001253 BOOTP(op=1,
1254 yiaddr=self.pg3.local_ip4,
Ole Troan8006c6a2018-12-17 12:02:26 +01001255 chaddr=mac_pton(self.pg3.local_mac)) /
Neale Ranns808c5b22017-08-02 05:15:07 -07001256 DHCP(options=[('message-type', 'offer'),
John Lo70bfcaf2017-11-14 13:19:26 -05001257 ('server_id', self.pg3.remote_ip4),
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001258 'end']))
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001259
John Lo70bfcaf2017-11-14 13:19:26 -05001260 self.pg3.add_stream(p_offer)
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001261 self.pg_enable_capture(self.pg_interfaces)
1262 self.pg_start()
1263
John Lo70bfcaf2017-11-14 13:19:26 -05001264 rx = self.pg3.get_capture(1)
1265 self.verify_orig_dhcp_request(rx[0], self.pg3, hostname,
1266 self.pg3.local_ip4)
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001267
1268 #
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001269 # Send an acknowledgment
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001270 #
John Lo70bfcaf2017-11-14 13:19:26 -05001271 p_ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
1272 IP(src=self.pg3.remote_ip4, dst="255.255.255.255") /
Neale Ranns808c5b22017-08-02 05:15:07 -07001273 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
Neale Ranns1f2f4b72018-03-23 11:53:12 -07001274 BOOTP(op=1, yiaddr=self.pg3.local_ip4,
Ole Troan8006c6a2018-12-17 12:02:26 +01001275 chaddr=mac_pton(self.pg3.local_mac)) /
Neale Ranns808c5b22017-08-02 05:15:07 -07001276 DHCP(options=[('message-type', 'ack'),
1277 ('subnet_mask', "255.255.255.0"),
John Lo70bfcaf2017-11-14 13:19:26 -05001278 ('router', self.pg3.remote_ip4),
1279 ('server_id', self.pg3.remote_ip4),
Neale Ranns808c5b22017-08-02 05:15:07 -07001280 ('lease_time', 43200),
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001281 'end']))
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001282
John Lo70bfcaf2017-11-14 13:19:26 -05001283 self.pg3.add_stream(p_ack)
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001284 self.pg_enable_capture(self.pg_interfaces)
1285 self.pg_start()
1286
1287 #
Neale Ranns51822bf2017-07-18 09:26:53 -07001288 # We'll get an ARP request for the router address
1289 #
John Lo70bfcaf2017-11-14 13:19:26 -05001290 rx = self.pg3.get_capture(1)
Neale Ranns51822bf2017-07-18 09:26:53 -07001291
John Lo70bfcaf2017-11-14 13:19:26 -05001292 self.assertEqual(rx[0][ARP].pdst, self.pg3.remote_ip4)
Neale Ranns51822bf2017-07-18 09:26:53 -07001293 self.pg_enable_capture(self.pg_interfaces)
1294
1295 #
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001296 # At the end of this procedure there should be a connected route
1297 # in the FIB
1298 #
John Lo70bfcaf2017-11-14 13:19:26 -05001299 self.assertTrue(find_route(self, self.pg3.local_ip4, 24))
1300 self.assertTrue(find_route(self, self.pg3.local_ip4, 32))
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001301
1302 #
1303 # remove the DHCP config
1304 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001305 Client.remove_vpp_config()
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001306
1307 #
1308 # and now the route should be gone
1309 #
John Lo70bfcaf2017-11-14 13:19:26 -05001310 self.assertFalse(find_route(self, self.pg3.local_ip4, 32))
1311 self.assertFalse(find_route(self, self.pg3.local_ip4, 24))
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001312
Neale Ranns51822bf2017-07-18 09:26:53 -07001313 #
Neale Ranns808c5b22017-08-02 05:15:07 -07001314 # Start the procedure again. this time have VPP send the client-ID
Neale Ranns038e1df2019-07-19 14:01:02 +00001315 # and set the DSCP value
Neale Ranns51822bf2017-07-18 09:26:53 -07001316 #
John Lo70bfcaf2017-11-14 13:19:26 -05001317 self.pg3.admin_down()
Neale Ranns808c5b22017-08-02 05:15:07 -07001318 self.sleep(1)
John Lo70bfcaf2017-11-14 13:19:26 -05001319 self.pg3.admin_up()
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001320 Client.set_client(self.pg3.sw_if_index, hostname,
1321 id=self.pg3.local_mac,
1322 dscp=vdscp.IP_API_DSCP_EF)
1323 Client.add_vpp_config()
Neale Ranns51822bf2017-07-18 09:26:53 -07001324
John Lo70bfcaf2017-11-14 13:19:26 -05001325 rx = self.pg3.get_capture(1)
Neale Ranns51822bf2017-07-18 09:26:53 -07001326
John Lo70bfcaf2017-11-14 13:19:26 -05001327 self.verify_orig_dhcp_discover(rx[0], self.pg3, hostname,
Neale Ranns038e1df2019-07-19 14:01:02 +00001328 self.pg3.local_mac,
1329 dscp=vdscp.IP_API_DSCP_EF)
Neale Ranns51822bf2017-07-18 09:26:53 -07001330
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001331 # TODO: VPP DHCP client should not accept DHCP OFFER message with
1332 # the XID (Transaction ID) not matching the XID of the most recent
1333 # DHCP DISCOVERY message.
1334 # Such DHCP OFFER message must be silently discarded - RFC2131.
1335 # Reported in Jira ticket: VPP-99
John Lo70bfcaf2017-11-14 13:19:26 -05001336 self.pg3.add_stream(p_offer)
Neale Ranns808c5b22017-08-02 05:15:07 -07001337 self.pg_enable_capture(self.pg_interfaces)
1338 self.pg_start()
1339
John Lo70bfcaf2017-11-14 13:19:26 -05001340 rx = self.pg3.get_capture(1)
1341 self.verify_orig_dhcp_request(rx[0], self.pg3, hostname,
Neale Ranns038e1df2019-07-19 14:01:02 +00001342 self.pg3.local_ip4,
1343 dscp=vdscp.IP_API_DSCP_EF)
Neale Ranns808c5b22017-08-02 05:15:07 -07001344
1345 #
1346 # unicast the ack to the offered address
1347 #
John Lo70bfcaf2017-11-14 13:19:26 -05001348 p_ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
1349 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
Neale Ranns808c5b22017-08-02 05:15:07 -07001350 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
Neale Ranns1f2f4b72018-03-23 11:53:12 -07001351 BOOTP(op=1, yiaddr=self.pg3.local_ip4,
Ole Troan8006c6a2018-12-17 12:02:26 +01001352 chaddr=mac_pton(self.pg3.local_mac)) /
Neale Ranns808c5b22017-08-02 05:15:07 -07001353 DHCP(options=[('message-type', 'ack'),
1354 ('subnet_mask', "255.255.255.0"),
John Lo70bfcaf2017-11-14 13:19:26 -05001355 ('router', self.pg3.remote_ip4),
1356 ('server_id', self.pg3.remote_ip4),
Neale Ranns808c5b22017-08-02 05:15:07 -07001357 ('lease_time', 43200),
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001358 'end']))
Neale Ranns808c5b22017-08-02 05:15:07 -07001359
John Lo70bfcaf2017-11-14 13:19:26 -05001360 self.pg3.add_stream(p_ack)
Neale Ranns808c5b22017-08-02 05:15:07 -07001361 self.pg_enable_capture(self.pg_interfaces)
1362 self.pg_start()
1363
1364 #
Neale Ranns54c6dc42018-01-17 10:29:10 -08001365 # We'll get an ARP request for the router address
1366 #
1367 rx = self.pg3.get_capture(1)
1368
1369 self.assertEqual(rx[0][ARP].pdst, self.pg3.remote_ip4)
1370 self.pg_enable_capture(self.pg_interfaces)
1371
1372 #
Neale Ranns808c5b22017-08-02 05:15:07 -07001373 # At the end of this procedure there should be a connected route
1374 # in the FIB
1375 #
John Lo70bfcaf2017-11-14 13:19:26 -05001376 self.assertTrue(find_route(self, self.pg3.local_ip4, 32))
1377 self.assertTrue(find_route(self, self.pg3.local_ip4, 24))
Neale Ranns808c5b22017-08-02 05:15:07 -07001378
Neale Ranns51822bf2017-07-18 09:26:53 -07001379 #
1380 # remove the DHCP config
1381 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001382 Client.remove_vpp_config()
Neale Rannsa2fbf6b2017-07-18 08:23:32 -07001383
John Lo70bfcaf2017-11-14 13:19:26 -05001384 self.assertFalse(find_route(self, self.pg3.local_ip4, 32))
1385 self.assertFalse(find_route(self, self.pg3.local_ip4, 24))
Neale Ranns808c5b22017-08-02 05:15:07 -07001386
Neale Ranns54c6dc42018-01-17 10:29:10 -08001387 #
1388 # Rince and repeat, this time with VPP configured not to set
1389 # the braodcast flag in the discover and request messages,
1390 # and for the server to unicast the responses.
1391 #
1392 # Configure DHCP client on PG3 and capture the discover sent
1393 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001394 Client.set_client(
1395 self.pg3.sw_if_index,
1396 hostname,
1397 set_broadcast_flag=False)
1398 Client.add_vpp_config()
Neale Ranns54c6dc42018-01-17 10:29:10 -08001399
1400 rx = self.pg3.get_capture(1)
1401
1402 self.verify_orig_dhcp_discover(rx[0], self.pg3, hostname,
Neale Ranns99536f42019-07-25 06:11:58 -07001403 broadcast=False)
Neale Ranns54c6dc42018-01-17 10:29:10 -08001404
1405 #
1406 # Send back on offer, unicasted to the offered address.
1407 # Expect the request.
1408 #
1409 p_offer = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
1410 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
1411 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
Neale Ranns1f2f4b72018-03-23 11:53:12 -07001412 BOOTP(op=1, yiaddr=self.pg3.local_ip4,
Ole Troan8006c6a2018-12-17 12:02:26 +01001413 chaddr=mac_pton(self.pg3.local_mac)) /
Neale Ranns54c6dc42018-01-17 10:29:10 -08001414 DHCP(options=[('message-type', 'offer'),
1415 ('server_id', self.pg3.remote_ip4),
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001416 'end']))
Neale Ranns54c6dc42018-01-17 10:29:10 -08001417
1418 self.pg3.add_stream(p_offer)
1419 self.pg_enable_capture(self.pg_interfaces)
1420 self.pg_start()
1421
1422 rx = self.pg3.get_capture(1)
1423 self.verify_orig_dhcp_request(rx[0], self.pg3, hostname,
1424 self.pg3.local_ip4,
Neale Ranns99536f42019-07-25 06:11:58 -07001425 broadcast=False)
Neale Ranns54c6dc42018-01-17 10:29:10 -08001426
1427 #
Neale Ranns99536f42019-07-25 06:11:58 -07001428 # Send an acknowledgment, the lease renewal time is 2 seconds
1429 # so we should expect the renew straight after
Neale Ranns54c6dc42018-01-17 10:29:10 -08001430 #
1431 p_ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
1432 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
1433 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
Neale Ranns1f2f4b72018-03-23 11:53:12 -07001434 BOOTP(op=1, yiaddr=self.pg3.local_ip4,
Ole Troan8006c6a2018-12-17 12:02:26 +01001435 chaddr=mac_pton(self.pg3.local_mac)) /
Neale Ranns54c6dc42018-01-17 10:29:10 -08001436 DHCP(options=[('message-type', 'ack'),
1437 ('subnet_mask', "255.255.255.0"),
1438 ('router', self.pg3.remote_ip4),
1439 ('server_id', self.pg3.remote_ip4),
1440 ('lease_time', 43200),
Neale Ranns99536f42019-07-25 06:11:58 -07001441 ('renewal_time', 2),
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001442 'end']))
Neale Ranns54c6dc42018-01-17 10:29:10 -08001443
1444 self.pg3.add_stream(p_ack)
1445 self.pg_enable_capture(self.pg_interfaces)
1446 self.pg_start()
1447
1448 #
1449 # We'll get an ARP request for the router address
1450 #
1451 rx = self.pg3.get_capture(1)
1452
1453 self.assertEqual(rx[0][ARP].pdst, self.pg3.remote_ip4)
1454 self.pg_enable_capture(self.pg_interfaces)
1455
1456 #
1457 # At the end of this procedure there should be a connected route
1458 # in the FIB
1459 #
1460 self.assertTrue(find_route(self, self.pg3.local_ip4, 24))
1461 self.assertTrue(find_route(self, self.pg3.local_ip4, 32))
1462
Neale Ranns99536f42019-07-25 06:11:58 -07001463 #
Neale Ranns6bcc6a42019-10-15 15:47:55 +00001464 # read the DHCP client details from a dump
1465 #
1466 clients = self.vapi.dhcp_client_dump()
1467
1468 self.assertEqual(clients[0].client.sw_if_index,
1469 self.pg3.sw_if_index)
1470 self.assertEqual(clients[0].lease.sw_if_index,
1471 self.pg3.sw_if_index)
1472 self.assertEqual(clients[0].client.hostname, hostname)
1473 self.assertEqual(clients[0].lease.hostname, hostname)
1474 # 0 = DISCOVER, 1 = REQUEST, 2 = BOUND
1475 self.assertEqual(clients[0].lease.state, 2)
1476 self.assertEqual(clients[0].lease.mask_width, 24)
1477 self.assertEqual(str(clients[0].lease.router_address),
1478 self.pg3.remote_ip4)
1479 self.assertEqual(str(clients[0].lease.host_address),
1480 self.pg3.local_ip4)
1481
1482 #
Neale Ranns99536f42019-07-25 06:11:58 -07001483 # wait for the unicasted renewal
1484 # the first attempt will be an ARP packet, since we have not yet
1485 # responded to VPP's request
1486 #
1487 self.logger.info(self.vapi.cli("sh dhcp client intfc pg3 verbose"))
1488 rx = self.pg3.get_capture(1, timeout=10)
1489
1490 self.assertEqual(rx[0][ARP].pdst, self.pg3.remote_ip4)
1491
1492 # respond to the arp
1493 p_arp = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
1494 ARP(op="is-at",
1495 hwdst=self.pg3.local_mac,
1496 hwsrc=self.pg3.remote_mac,
1497 pdst=self.pg3.local_ip4,
1498 psrc=self.pg3.remote_ip4))
1499 self.pg3.add_stream(p_arp)
1500 self.pg_enable_capture(self.pg_interfaces)
1501 self.pg_start()
1502
1503 # the next packet is the unicasted renewal
1504 rx = self.pg3.get_capture(1, timeout=10)
1505 self.verify_orig_dhcp_request(rx[0], self.pg3, hostname,
1506 self.pg3.local_ip4,
1507 l2_bc=False,
1508 broadcast=False)
Neale Rannsdaff1782018-05-16 04:12:18 -07001509
Neale Ranns6bcc6a42019-10-15 15:47:55 +00001510 # send an ACK with different data from the original offer *
1511 self.pg3.generate_remote_hosts(4)
1512 p_ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
1513 IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
1514 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
1515 BOOTP(op=1, yiaddr=self.pg3.remote_hosts[3].ip4,
1516 chaddr=mac_pton(self.pg3.local_mac)) /
1517 DHCP(options=[('message-type', 'ack'),
1518 ('subnet_mask', "255.255.255.0"),
1519 ('router', self.pg3.remote_hosts[1].ip4),
1520 ('server_id', self.pg3.remote_hosts[2].ip4),
1521 ('lease_time', 43200),
1522 ('renewal_time', 2),
1523 'end']))
1524
1525 self.pg3.add_stream(p_ack)
1526 self.pg_enable_capture(self.pg_interfaces)
1527 self.pg_start()
1528
Neale Rannsdaff1782018-05-16 04:12:18 -07001529 #
1530 # read the DHCP client details from a dump
1531 #
1532 clients = self.vapi.dhcp_client_dump()
1533
1534 self.assertEqual(clients[0].client.sw_if_index,
1535 self.pg3.sw_if_index)
1536 self.assertEqual(clients[0].lease.sw_if_index,
1537 self.pg3.sw_if_index)
Neale Ranns6bcc6a42019-10-15 15:47:55 +00001538 self.assertEqual(clients[0].client.hostname, hostname)
1539 self.assertEqual(clients[0].lease.hostname, hostname)
Neale Rannsdaff1782018-05-16 04:12:18 -07001540 # 0 = DISCOVER, 1 = REQUEST, 2 = BOUND
1541 self.assertEqual(clients[0].lease.state, 2)
1542 self.assertEqual(clients[0].lease.mask_width, 24)
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001543 self.assertEqual(str(clients[0].lease.router_address),
Neale Ranns6bcc6a42019-10-15 15:47:55 +00001544 self.pg3.remote_hosts[1].ip4)
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001545 self.assertEqual(str(clients[0].lease.host_address),
Neale Ranns6bcc6a42019-10-15 15:47:55 +00001546 self.pg3.remote_hosts[3].ip4)
Neale Ranns99536f42019-07-25 06:11:58 -07001547
Neale Ranns54c6dc42018-01-17 10:29:10 -08001548 #
1549 # remove the DHCP config
1550 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001551 Client.remove_vpp_config()
Neale Ranns54c6dc42018-01-17 10:29:10 -08001552
1553 #
1554 # and now the route should be gone
1555 #
1556 self.assertFalse(find_route(self, self.pg3.local_ip4, 32))
1557 self.assertFalse(find_route(self, self.pg3.local_ip4, 24))
1558
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001559 #
1560 # Start the procedure again. Use requested lease time option.
Neale Ranns6bcc6a42019-10-15 15:47:55 +00001561 # this time wait for the lease to expire and the client to
1562 # self-destruct
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001563 #
Neale Ranns99536f42019-07-25 06:11:58 -07001564 hostname += "-2"
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001565 self.pg3.admin_down()
1566 self.sleep(1)
1567 self.pg3.admin_up()
Neale Ranns99536f42019-07-25 06:11:58 -07001568 self.pg_enable_capture(self.pg_interfaces)
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001569 Client.set_client(self.pg3.sw_if_index, hostname)
1570 Client.add_vpp_config()
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001571
1572 rx = self.pg3.get_capture(1)
1573
1574 self.verify_orig_dhcp_discover(rx[0], self.pg3, hostname)
1575
1576 #
1577 # Send back on offer with requested lease time, expect the request
1578 #
1579 lease_time = 1
1580 p_offer = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
1581 IP(src=self.pg3.remote_ip4, dst='255.255.255.255') /
1582 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
1583 BOOTP(op=1,
1584 yiaddr=self.pg3.local_ip4,
Ole Troan8006c6a2018-12-17 12:02:26 +01001585 chaddr=mac_pton(self.pg3.local_mac)) /
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001586 DHCP(options=[('message-type', 'offer'),
1587 ('server_id', self.pg3.remote_ip4),
1588 ('lease_time', lease_time),
1589 'end']))
1590
1591 self.pg3.add_stream(p_offer)
1592 self.pg_enable_capture(self.pg_interfaces)
1593 self.pg_start()
1594
1595 rx = self.pg3.get_capture(1)
1596 self.verify_orig_dhcp_request(rx[0], self.pg3, hostname,
1597 self.pg3.local_ip4)
1598
1599 #
1600 # Send an acknowledgment
1601 #
1602 p_ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
1603 IP(src=self.pg3.remote_ip4, dst='255.255.255.255') /
1604 UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
1605 BOOTP(op=1, yiaddr=self.pg3.local_ip4,
Ole Troan8006c6a2018-12-17 12:02:26 +01001606 chaddr=mac_pton(self.pg3.local_mac)) /
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001607 DHCP(options=[('message-type', 'ack'),
1608 ('subnet_mask', '255.255.255.0'),
1609 ('router', self.pg3.remote_ip4),
1610 ('server_id', self.pg3.remote_ip4),
1611 ('lease_time', lease_time),
1612 'end']))
1613
1614 self.pg3.add_stream(p_ack)
1615 self.pg_enable_capture(self.pg_interfaces)
1616 self.pg_start()
1617
1618 #
1619 # We'll get an ARP request for the router address
1620 #
1621 rx = self.pg3.get_capture(1)
1622
1623 self.assertEqual(rx[0][ARP].pdst, self.pg3.remote_ip4)
1624
1625 #
1626 # At the end of this procedure there should be a connected route
1627 # in the FIB
1628 #
1629 self.assertTrue(find_route(self, self.pg3.local_ip4, 32))
1630 self.assertTrue(find_route(self, self.pg3.local_ip4, 24))
1631
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001632 #
Neale Rannsf6e9b012019-01-25 06:37:15 -08001633 # the route should be gone after the lease expires
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001634 #
Neale Rannsf6e9b012019-01-25 06:37:15 -08001635 self.assertTrue(self.wait_for_no_route(self.pg3.local_ip4, 32))
1636 self.assertTrue(self.wait_for_no_route(self.pg3.local_ip4, 24))
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001637
1638 #
1639 # remove the DHCP config
1640 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001641 Client.remove_vpp_config()
Jan Gelety2a3fb1a2018-06-27 10:56:17 +02001642
Neale Ranns038e1df2019-07-19 14:01:02 +00001643 def test_dhcp_client_vlan(self):
1644 """ DHCP Client w/ VLAN"""
1645
1646 vdscp = VppEnum.vl_api_ip_dscp_t
1647 vqos = VppEnum.vl_api_qos_source_t
1648 hostname = 'universal-dp'
1649
1650 self.pg_enable_capture(self.pg_interfaces)
1651
1652 vlan_100 = VppDot1QSubint(self, self.pg3, 100)
1653 vlan_100.admin_up()
1654
1655 output = [scapy.compat.chb(4)] * 256
1656 os = b''.join(output)
1657 rows = [{'outputs': os},
1658 {'outputs': os},
1659 {'outputs': os},
1660 {'outputs': os}]
1661
1662 qem1 = VppQosEgressMap(self, 1, rows).add_vpp_config()
1663 qm1 = VppQosMark(self, vlan_100, qem1,
1664 vqos.QOS_API_SOURCE_VLAN).add_vpp_config()
1665
1666 #
1667 # Configure DHCP client on PG3 and capture the discover sent
1668 #
Jakub Grajciar103ba6b2019-10-01 11:30:56 +02001669 Client = VppDHCPClient(
1670 self,
1671 vlan_100.sw_if_index,
1672 hostname,
1673 dscp=vdscp.IP_API_DSCP_EF)
1674 Client.add_vpp_config()
Neale Ranns038e1df2019-07-19 14:01:02 +00001675
1676 rx = self.pg3.get_capture(1)
1677
1678 self.assertEqual(rx[0][Dot1Q].vlan, 100)
Prashant Maheshwari3bcf1a92019-07-31 21:37:33 +05301679 self.assertEqual(rx[0][Dot1Q].prio, 2)
Neale Ranns038e1df2019-07-19 14:01:02 +00001680
1681 self.verify_orig_dhcp_discover(rx[0], self.pg3, hostname,
1682 dscp=vdscp.IP_API_DSCP_EF)
1683
Neale Ranns808c5b22017-08-02 05:15:07 -07001684
Neale Rannsfca0c242017-01-13 07:57:46 -08001685if __name__ == '__main__':
1686 unittest.main(testRunner=VppTestRunner)