def test_dhcp_ia_na_send_solicit_receive_advertise(self): """Verify DHCPv6 IA NA Solicit packet and Advertise event""" self.vapi.dhcp6_clients_enable_disable(enable=1) self.pg_enable_capture(self.pg_interfaces) self.pg_start() address = {"address": "1:2:3::5", "preferred_time": 60, "valid_time": 120} self.vapi.dhcp6_send_client_message( server_index=0xFFFFFFFF, mrc=1, msg_type=VppEnum.vl_api_dhcpv6_msg_type_t.DHCPV6_MSG_API_SOLICIT, sw_if_index=self.pg0.sw_if_index, T1=20, T2=40, addresses=[address], n_addresses=len([address]), ) rx_list = self.pg0.get_capture(1) self.assertEqual(len(rx_list), 1) packet = rx_list[0] self.assertEqual(packet.haslayer(IPv6), 1) self.assertEqual(packet[IPv6].haslayer(DHCP6_Solicit), 1) client_duid = packet[DHCP6OptClientId].duid trid = packet[DHCP6_Solicit].trid dst = ip6_normalize(packet[IPv6].dst) dst2 = ip6_normalize("ff02::1:2") self.assert_equal(dst, dst2) src = ip6_normalize(packet[IPv6].src) src2 = ip6_normalize(self.pg0.local_ip6_ll) self.assert_equal(src, src2) ia_na = packet[DHCP6OptIA_NA] self.assert_equal(ia_na.T1, 20) self.assert_equal(ia_na.T2, 40) self.assert_equal(len(ia_na.ianaopts), 1) address = ia_na.ianaopts[0] self.assert_equal(address.addr, "1:2:3::5") self.assert_equal(address.preflft, 60) self.assert_equal(address.validlft, 120) self.vapi.want_dhcp6_reply_events(enable_disable=1, pid=os.getpid()) try: ia_na_opts = DHCP6OptIAAddress(addr="7:8::2", preflft=60, validlft=120) p = ( Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IPv6( src=util.mk_ll_addr(self.pg0.remote_mac), dst=self.pg0.local_ip6_ll ) / UDP(sport=547, dport=546) / DHCP6_Advertise(trid=trid) / DHCP6OptServerId(duid=self.server_duid) / DHCP6OptClientId(duid=client_duid) / DHCP6OptPref(prefval=7) / DHCP6OptStatusCode(statuscode=1) / DHCP6OptIA_NA(iaid=1, T1=20, T2=40, ianaopts=ia_na_opts) ) self.pg0.add_stream([p]) self.pg_start() ev = self.vapi.wait_for_event(1, "dhcp6_reply_event") self.assert_equal(ev.preference, 7) self.assert_equal(ev.status_code, 1) self.assert_equal(ev.T1, 20) self.assert_equal(ev.T2, 40) reported_address = ev.addresses[0] address = ia_na_opts.getfieldval("addr") self.assert_equal(str(reported_address.address), address) self.assert_equal( reported_address.preferred_time, ia_na_opts.getfieldval("preflft") ) self.assert_equal( reported_address.valid_time, ia_na_opts.getfieldval("validlft") ) finally: self.vapi.want_dhcp6_reply_events(enable_disable=0) self.vapi.dhcp6_clients_enable_disable(enable=0)
def test_dhcp_pd_send_solicit_receive_advertise(self): """Verify DHCPv6 PD Solicit packet and Advertise event""" self.vapi.dhcp6_clients_enable_disable(enable=1) self.pg_enable_capture(self.pg_interfaces) self.pg_start() prefix = { "prefix": {"address": "1:2:3::", "len": 50}, "preferred_time": 60, "valid_time": 120, } prefixes = [prefix] self.vapi.dhcp6_pd_send_client_message( server_index=0xFFFFFFFF, mrc=1, msg_type=VppEnum.vl_api_dhcpv6_msg_type_t.DHCPV6_MSG_API_SOLICIT, sw_if_index=self.pg0.sw_if_index, T1=20, T2=40, prefixes=prefixes, n_prefixes=len(prefixes), ) rx_list = self.pg0.get_capture(1) self.assertEqual(len(rx_list), 1) packet = rx_list[0] self.assertEqual(packet.haslayer(IPv6), 1) self.assertEqual(packet[IPv6].haslayer(DHCP6_Solicit), 1) client_duid = packet[DHCP6OptClientId].duid trid = packet[DHCP6_Solicit].trid dst = ip6_normalize(packet[IPv6].dst) dst2 = ip6_normalize("ff02::1:2") self.assert_equal(dst, dst2) src = ip6_normalize(packet[IPv6].src) src2 = ip6_normalize(self.pg0.local_ip6_ll) self.assert_equal(src, src2) ia_pd = packet[DHCP6OptIA_PD] self.assert_equal(ia_pd.T1, 20) self.assert_equal(ia_pd.T2, 40) self.assert_equal(len(ia_pd.iapdopt), 1) prefix = ia_pd.iapdopt[0] self.assert_equal(prefix.prefix, "1:2:3::") self.assert_equal(prefix.plen, 50) self.assert_equal(prefix.preflft, 60) self.assert_equal(prefix.validlft, 120) self.vapi.want_dhcp6_pd_reply_events(enable_disable=1, pid=os.getpid()) try: ia_pd_opts = DHCP6OptIAPrefix( prefix="7:8::", plen=56, preflft=60, validlft=120 ) p = ( Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IPv6( src=util.mk_ll_addr(self.pg0.remote_mac), dst=self.pg0.local_ip6_ll ) / UDP(sport=547, dport=546) / DHCP6_Advertise(trid=trid) / DHCP6OptServerId(duid=self.server_duid) / DHCP6OptClientId(duid=client_duid) / DHCP6OptPref(prefval=7) / DHCP6OptStatusCode(statuscode=1) / DHCP6OptIA_PD(iaid=1, T1=20, T2=40, iapdopt=ia_pd_opts) ) self.pg0.add_stream([p]) self.pg_start() ev = self.vapi.wait_for_event(1, "dhcp6_pd_reply_event") self.assert_equal(ev.preference, 7) self.assert_equal(ev.status_code, 1) self.assert_equal(ev.T1, 20) self.assert_equal(ev.T2, 40) reported_prefix = ev.prefixes[0] prefix = ia_pd_opts.getfieldval("prefix") self.assert_equal(str(reported_prefix.prefix).split("/")[0], prefix) self.assert_equal( int(str(reported_prefix.prefix).split("/")[1]), ia_pd_opts.getfieldval("plen"), ) self.assert_equal( reported_prefix.preferred_time, ia_pd_opts.getfieldval("preflft") ) self.assert_equal( reported_prefix.valid_time, ia_pd_opts.getfieldval("validlft") ) finally: self.vapi.want_dhcp6_pd_reply_events(enable_disable=0) self.vapi.dhcp6_clients_enable_disable(enable=0)
def test_dhcp6_proxy(self): """ DHCPv6 Proxy""" # # Verify no response to DHCP request without DHCP config # dhcp_solicit_dst = "ff02::1:2" dhcp_solicit_src_vrf0 = mk_ll_addr(self.pg2.remote_mac) dhcp_solicit_src_vrf1 = mk_ll_addr(self.pg3.remote_mac) server_addr_vrf0 = self.pg0.remote_ip6n src_addr_vrf0 = self.pg0.local_ip6n server_addr_vrf1 = self.pg1.remote_ip6n src_addr_vrf1 = self.pg1.local_ip6n dmac = in6_getnsmac(inet_pton(socket.AF_INET6, dhcp_solicit_dst)) p_solicit_vrf0 = ( Ether(dst=dmac, src=self.pg2.remote_mac) / IPv6(src=dhcp_solicit_src_vrf0, dst=dhcp_solicit_dst) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_CLIENT_PORT) / DHCP6_Solicit()) p_solicit_vrf1 = ( Ether(dst=dmac, src=self.pg3.remote_mac) / IPv6(src=dhcp_solicit_src_vrf1, dst=dhcp_solicit_dst) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_CLIENT_PORT) / DHCP6_Solicit()) self.send_and_assert_no_replies(self.pg2, p_solicit_vrf0, "DHCP with no configuration") self.send_and_assert_no_replies(self.pg3, p_solicit_vrf1, "DHCP with no configuration") # # DHCPv6 config in VRF 0. # Packets still dropped because the client facing interface has no # IPv6 config # self.vapi.dhcp_proxy_config(server_addr_vrf0, src_addr_vrf0, rx_table_id=0, server_table_id=0, is_ipv6=1) self.send_and_assert_no_replies(self.pg2, p_solicit_vrf0, "DHCP with no configuration") self.send_and_assert_no_replies(self.pg3, p_solicit_vrf1, "DHCP with no configuration") # # configure an IP address on the client facing interface # self.pg2.config_ip6() # # Now the DHCP requests are relayed to the server # self.pg2.add_stream(p_solicit_vrf0) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg0.get_capture(1) self.verify_dhcp6_solicit(rx[0], self.pg0, dhcp_solicit_src_vrf0, self.pg2.remote_mac) # # Exception cases for rejected relay responses # # 1 - not a relay reply p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_Advertise()) self.send_and_assert_no_replies(self.pg2, p_adv_vrf0, "DHCP6 not a relay reply") # 2 - no relay message option p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_RelayReply() / DHCP6_Advertise()) self.send_and_assert_no_replies(self.pg2, p_adv_vrf0, "DHCP not a relay message") # 3 - no circuit ID p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_RelayReply() / DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise()) self.send_and_assert_no_replies(self.pg2, p_adv_vrf0, "DHCP6 no circuit ID") # 4 - wrong circuit ID p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_RelayReply() / DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x05') / DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise()) self.send_and_assert_no_replies(self.pg2, p_adv_vrf0, "DHCP6 wrong circuit ID") # # Send the relay response (the advertisement) # - no peer address p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_RelayReply() / DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x03') / DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) / DHCP6OptStatusCode(statuscode=0)) pkts_adv_vrf0 = [p_adv_vrf0] self.pg0.add_stream(pkts_adv_vrf0) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg2.get_capture(1) self.verify_dhcp6_advert(rx[0], self.pg2, "::") # # Send the relay response (the advertisement) # - with peer address p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf0) / DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x03') / DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) / DHCP6OptStatusCode(statuscode=0)) pkts_adv_vrf0 = [p_adv_vrf0] self.pg0.add_stream(pkts_adv_vrf0) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg2.get_capture(1) self.verify_dhcp6_advert(rx[0], self.pg2, dhcp_solicit_src_vrf0) # # Add all the config for VRF 1 # self.vapi.dhcp_proxy_config(server_addr_vrf1, src_addr_vrf1, rx_table_id=1, server_table_id=1, is_ipv6=1) self.pg3.config_ip6() # # VRF 1 solicit # self.pg3.add_stream(p_solicit_vrf1) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) self.verify_dhcp6_solicit(rx[0], self.pg1, dhcp_solicit_src_vrf1, self.pg3.remote_mac) # # VRF 1 Advert # p_adv_vrf1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / IPv6(dst=self.pg1.local_ip6, src=self.pg1.remote_ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) / DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') / DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) / DHCP6OptStatusCode(statuscode=0)) pkts_adv_vrf1 = [p_adv_vrf1] self.pg1.add_stream(pkts_adv_vrf1) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg3.get_capture(1) self.verify_dhcp6_advert(rx[0], self.pg3, dhcp_solicit_src_vrf1) # # Add VSS config # table=1, fib=id=1, oui=4 self.vapi.dhcp_proxy_set_vss(1, 1, 4, is_ip6=1) self.pg3.add_stream(p_solicit_vrf1) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) self.verify_dhcp6_solicit(rx[0], self.pg1, dhcp_solicit_src_vrf1, self.pg3.remote_mac, fib_id=1, oui=4) # # Remove the VSS config # relayed DHCP has default vlaues in the option. # self.vapi.dhcp_proxy_set_vss(1, 1, 4, is_ip6=1, is_add=0) self.pg3.add_stream(p_solicit_vrf1) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) self.verify_dhcp6_solicit(rx[0], self.pg1, dhcp_solicit_src_vrf1, self.pg3.remote_mac) # # Add a second DHCP server in VRF 1 # expect clients messages to be relay to both configured servers # self.pg1.generate_remote_hosts(2) server_addr2 = socket.inet_pton(AF_INET6, self.pg1.remote_hosts[1].ip6) self.vapi.dhcp_proxy_config(server_addr2, src_addr_vrf1, rx_table_id=1, server_table_id=1, is_ipv6=1) # # We'll need an ND entry for the server to send it packets # nd_entry = VppNeighbor(self, self.pg1.sw_if_index, self.pg1.remote_hosts[1].mac, self.pg1.remote_hosts[1].ip6, af=AF_INET6) nd_entry.add_vpp_config() # # Send a discover from the client. expect two relayed messages # The frist packet is sent to the second server # We're not enforcing that here, it's just the way it is. # self.pg3.add_stream(p_solicit_vrf1) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(2) self.verify_dhcp6_solicit(rx[0], self.pg1, dhcp_solicit_src_vrf1, self.pg3.remote_mac) self.verify_dhcp6_solicit(rx[1], self.pg1, dhcp_solicit_src_vrf1, self.pg3.remote_mac, dst_mac=self.pg1.remote_hosts[1].mac, dst_ip=self.pg1.remote_hosts[1].ip6) # # Send both packets back. Client gets both. # p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / IPv6(dst=self.pg1.local_ip6, src=self.pg1.remote_ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) / DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') / DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) / DHCP6OptStatusCode(statuscode=0)) p2 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_hosts[1].mac) / IPv6(dst=self.pg1.local_ip6, src=self.pg1._remote_hosts[1].ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) / DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') / DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) / DHCP6OptStatusCode(statuscode=0)) pkts = [p1, p2] self.pg1.add_stream(pkts) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg3.get_capture(2) self.verify_dhcp6_advert(rx[0], self.pg3, dhcp_solicit_src_vrf1) self.verify_dhcp6_advert(rx[1], self.pg3, dhcp_solicit_src_vrf1) # # Ensure only solicit messages are duplicated # p_request_vrf1 = ( Ether(dst=dmac, src=self.pg3.remote_mac) / IPv6(src=dhcp_solicit_src_vrf1, dst=dhcp_solicit_dst) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_CLIENT_PORT) / DHCP6_Request()) self.pg3.add_stream(p_request_vrf1) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) # # Test we drop DHCP packets from addresses that are not configured as # DHCP servers # p2 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_hosts[1].mac) / IPv6(dst=self.pg1.local_ip6, src="3001::1") / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) / DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') / DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) / DHCP6OptStatusCode(statuscode=0)) self.send_and_assert_no_replies(self.pg1, p2, "DHCP6 not from server") # # Remove the second DHCP server # self.vapi.dhcp_proxy_config(server_addr2, src_addr_vrf1, rx_table_id=1, server_table_id=1, is_ipv6=1, is_add=0) # # Test we can still relay with the first # self.pg3.add_stream(p_solicit_vrf1) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) self.verify_dhcp6_solicit(rx[0], self.pg1, dhcp_solicit_src_vrf1, self.pg3.remote_mac) # # Cleanup # self.vapi.dhcp_proxy_config(server_addr_vrf1, src_addr_vrf1, rx_table_id=1, server_table_id=1, is_ipv6=1, is_add=0) self.vapi.dhcp_proxy_config(server_addr_vrf0, src_addr_vrf0, rx_table_id=0, server_table_id=0, is_ipv6=1, is_add=0) # duplicate delete self.vapi.dhcp_proxy_config(server_addr_vrf0, src_addr_vrf0, rx_table_id=0, server_table_id=0, is_ipv6=1, is_add=0) self.pg2.unconfig_ip6() self.pg3.unconfig_ip6()
def test_dhcp_ia_na_send_solicit_receive_advertise(self): """ Verify DHCPv6 IA NA Solicit packet and Advertise envent """ self.vapi.dhcp6_clients_enable_disable() self.pg_enable_capture(self.pg_interfaces) self.pg_start() address_bin = '\00\01\00\02\00\03' + '\00' * 8 + '\00\05' address = {'address': address_bin, 'preferred_time': 60, 'valid_time': 120} self.vapi.dhcp6_send_client_message(1, self.pg0.sw_if_index, T1=20, T2=40, addresses=[address]) rx_list = self.pg0.get_capture(1) self.assertEqual(len(rx_list), 1) packet = rx_list[0] self.assertTrue(packet.haslayer(IPv6)) self.assertTrue(packet[IPv6].haslayer(DHCP6_Solicit)) client_duid = packet[DHCP6OptClientId].duid trid = packet[DHCP6_Solicit].trid dst = ip6_normalize(packet[IPv6].dst) dst2 = ip6_normalize("ff02::1:2") self.assert_equal(dst, dst2) src = ip6_normalize(packet[IPv6].src) src2 = ip6_normalize(self.pg0.local_ip6_ll) self.assert_equal(src, src2) ia_na = packet[DHCP6OptIA_NA] self.assert_equal(ia_na.T1, 20) self.assert_equal(ia_na.T2, 40) self.assert_equal(len(ia_na.ianaopts), 1) address = ia_na.ianaopts[0] self.assert_equal(address.addr, '1:2:3::5') self.assert_equal(address.preflft, 60) self.assert_equal(address.validlft, 120) self.vapi.want_dhcp6_reply_events() try: ia_na_opts = DHCP6OptIAAddress(addr='7:8::2', preflft=60, validlft=120) p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IPv6(src=mk_ll_addr(self.pg0.remote_mac), dst=self.pg0.local_ip6_ll) / UDP(sport=547, dport=546) / DHCP6_Advertise(trid=trid) / DHCP6OptServerId(duid=self.server_duid) / DHCP6OptClientId(duid=client_duid) / DHCP6OptPref(prefval=7) / DHCP6OptStatusCode(statuscode=1) / DHCP6OptIA_NA(iaid=1, T1=20, T2=40, ianaopts=ia_na_opts) ) self.pg0.add_stream([p]) self.pg_start() ev = self.vapi.wait_for_event(1, "dhcp6_reply_event") self.assert_equal(ev.preference, 7) self.assert_equal(ev.status_code, 1) self.assert_equal(ev.T1, 20) self.assert_equal(ev.T2, 40) reported_address = ev.addresses[0] address = inet_pton(AF_INET6, ia_na_opts.getfieldval("addr")) self.assert_equal(reported_address.address, address) self.assert_equal(reported_address.preferred_time, ia_na_opts.getfieldval("preflft")) self.assert_equal(reported_address.valid_time, ia_na_opts.getfieldval("validlft")) finally: self.vapi.want_dhcp6_reply_events(enable_disable=0)
def test_dhcp_pd_send_solicit_receive_advertise(self): """ Verify DHCPv6 PD Solicit packet and Advertise envent """ self.vapi.dhcp6_clients_enable_disable() self.pg_enable_capture(self.pg_interfaces) self.pg_start() prefix_bin = '\00\01\00\02\00\03' + '\00' * 10 prefix = {'prefix': prefix_bin, 'prefix_length': 50, 'preferred_time': 60, 'valid_time': 120} self.vapi.dhcp6_pd_send_client_message(1, self.pg0.sw_if_index, T1=20, T2=40, prefixes=[prefix]) rx_list = self.pg0.get_capture(1) self.assertEqual(len(rx_list), 1) packet = rx_list[0] self.assertTrue(packet.haslayer(IPv6)) self.assertTrue(packet[IPv6].haslayer(DHCP6_Solicit)) client_duid = packet[DHCP6OptClientId].duid trid = packet[DHCP6_Solicit].trid dst = ip6_normalize(packet[IPv6].dst) dst2 = ip6_normalize("ff02::1:2") self.assert_equal(dst, dst2) src = ip6_normalize(packet[IPv6].src) src2 = ip6_normalize(self.pg0.local_ip6_ll) self.assert_equal(src, src2) ia_pd = packet[DHCP6OptIA_PD] self.assert_equal(ia_pd.T1, 20) self.assert_equal(ia_pd.T2, 40) self.assert_equal(len(ia_pd.iapdopt), 1) prefix = ia_pd.iapdopt[0] self.assert_equal(prefix.prefix, '1:2:3::') self.assert_equal(prefix.plen, 50) self.assert_equal(prefix.preflft, 60) self.assert_equal(prefix.validlft, 120) self.vapi.want_dhcp6_pd_reply_events() try: ia_pd_opts = DHCP6OptIAPrefix(prefix='7:8::', plen=56, preflft=60, validlft=120) p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IPv6(src=mk_ll_addr(self.pg0.remote_mac), dst=self.pg0.local_ip6_ll) / UDP(sport=547, dport=546) / DHCP6_Advertise(trid=trid) / DHCP6OptServerId(duid=self.server_duid) / DHCP6OptClientId(duid=client_duid) / DHCP6OptPref(prefval=7) / DHCP6OptStatusCode(statuscode=1) / DHCP6OptIA_PD(iaid=1, T1=20, T2=40, iapdopt=ia_pd_opts) ) self.pg0.add_stream([p]) self.pg_start() ev = self.vapi.wait_for_event(1, "dhcp6_pd_reply_event") self.assert_equal(ev.preference, 7) self.assert_equal(ev.status_code, 1) self.assert_equal(ev.T1, 20) self.assert_equal(ev.T2, 40) reported_prefix = ev.prefixes[0] prefix = inet_pton(AF_INET6, ia_pd_opts.getfieldval("prefix")) self.assert_equal(reported_prefix.prefix, prefix) self.assert_equal(reported_prefix.prefix_length, ia_pd_opts.getfieldval("plen")) self.assert_equal(reported_prefix.preferred_time, ia_pd_opts.getfieldval("preflft")) self.assert_equal(reported_prefix.valid_time, ia_pd_opts.getfieldval("validlft")) finally: self.vapi.want_dhcp6_pd_reply_events(enable_disable=0)
def test_dhcp6_proxy(self): """ DHCPv6 Proxy""" # # Verify no response to DHCP request without DHCP config # dhcp_solicit_dst = "ff02::1:2" dhcp_solicit_src_vrf0 = mk_ll_addr(self.pg2.remote_mac) dhcp_solicit_src_vrf1 = mk_ll_addr(self.pg3.remote_mac) server_addr_vrf0 = self.pg0.remote_ip6n src_addr_vrf0 = self.pg0.local_ip6n server_addr_vrf1 = self.pg1.remote_ip6n src_addr_vrf1 = self.pg1.local_ip6n dmac = in6_getnsmac(inet_pton(socket.AF_INET6, dhcp_solicit_dst)) p_solicit_vrf0 = ( Ether(dst=dmac, src=self.pg2.remote_mac) / IPv6(src=dhcp_solicit_src_vrf0, dst=dhcp_solicit_dst) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_CLIENT_PORT) / DHCP6_Solicit()) pkts_solicit_vrf0 = [p_solicit_vrf0] p_solicit_vrf1 = ( Ether(dst=dmac, src=self.pg3.remote_mac) / IPv6(src=dhcp_solicit_src_vrf1, dst=dhcp_solicit_dst) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_CLIENT_PORT) / DHCP6_Solicit()) pkts_solicit_vrf1 = [p_solicit_vrf1] self.send_and_assert_no_replies(self.pg2, pkts_solicit_vrf0, "DHCP with no configuration") self.send_and_assert_no_replies(self.pg3, pkts_solicit_vrf1, "DHCP with no configuration") # # DHCPv6 config in VRF 0. # Packets still dropped because the client facing interface has no # IPv6 config # self.vapi.dhcp_proxy_config(server_addr_vrf0, src_addr_vrf0, rx_table_id=0, server_table_id=0, is_ipv6=1) self.send_and_assert_no_replies(self.pg2, pkts_solicit_vrf0, "DHCP with no configuration") self.send_and_assert_no_replies(self.pg3, pkts_solicit_vrf1, "DHCP with no configuration") # # configure an IP address on the client facing interface # self.pg2.config_ip6() # # Now the DHCP requests are relayed to the server # self.pg2.add_stream(pkts_solicit_vrf0) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg0.get_capture(1) rx = rx[0] self.verify_dhcp6_solicit(rx, self.pg0, dhcp_solicit_src_vrf0, self.pg2.remote_mac) # # Exception cases for rejected relay responses # # 1 - not a relay reply p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_Advertise()) pkts_adv_vrf0 = [p_adv_vrf0] self.send_and_assert_no_replies(self.pg2, pkts_adv_vrf0, "DHCP6 not a relay reply") # 2 - no relay message option p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_RelayReply() / DHCP6_Advertise()) pkts_adv_vrf0 = [p_adv_vrf0] self.send_and_assert_no_replies(self.pg2, pkts_adv_vrf0, "DHCP not a relay message") # 3 - no circuit ID p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_RelayReply() / DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise()) pkts_adv_vrf0 = [p_adv_vrf0] self.send_and_assert_no_replies(self.pg2, pkts_adv_vrf0, "DHCP6 no circuit ID") # 4 - wrong circuit ID p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_RelayReply() / DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x05') / DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise()) pkts_adv_vrf0 = [p_adv_vrf0] self.send_and_assert_no_replies(self.pg2, pkts_adv_vrf0, "DHCP6 wrong circuit ID") # # Send the relay response (the advertisement) # - no peer address p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_RelayReply() / DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x03') / DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) / DHCP6OptStatusCode(statuscode=0)) pkts_adv_vrf0 = [p_adv_vrf0] self.pg0.add_stream(pkts_adv_vrf0) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg2.get_capture(1) rx = rx[0] self.verify_dhcp6_advert(rx, self.pg2, "::") # # Send the relay response (the advertisement) # - with peer address p_adv_vrf0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf0) / DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x03') / DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) / DHCP6OptStatusCode(statuscode=0)) pkts_adv_vrf0 = [p_adv_vrf0] self.pg0.add_stream(pkts_adv_vrf0) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg2.get_capture(1) rx = rx[0] self.verify_dhcp6_advert(rx, self.pg2, dhcp_solicit_src_vrf0) # # Add all the config for VRF 1 # self.vapi.dhcp_proxy_config(server_addr_vrf1, src_addr_vrf1, rx_table_id=1, server_table_id=1, is_ipv6=1) self.pg3.config_ip6() # # VRF 1 solicit # self.pg3.add_stream(pkts_solicit_vrf1) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) rx = rx[0] self.verify_dhcp6_solicit(rx, self.pg1, dhcp_solicit_src_vrf1, self.pg3.remote_mac) # # VRF 1 Advert # p_adv_vrf1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / IPv6(dst=self.pg1.local_ip6, src=self.pg1.remote_ip6) / UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) / DHCP6_RelayReply(peeraddr=dhcp_solicit_src_vrf1) / DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') / DHCP6OptRelayMsg(optlen=0) / DHCP6_Advertise(trid=1) / DHCP6OptStatusCode(statuscode=0)) pkts_adv_vrf1 = [p_adv_vrf1] self.pg1.add_stream(pkts_adv_vrf1) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg3.get_capture(1) rx = rx[0] self.verify_dhcp6_advert(rx, self.pg3, dhcp_solicit_src_vrf1) # # Add VSS config # table=1, fib=id=1, oui=4 self.vapi.dhcp_proxy_set_vss(1, 1, 4, is_ip6=1) self.pg3.add_stream(pkts_solicit_vrf1) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) rx = rx[0] self.verify_dhcp6_solicit(rx, self.pg1, dhcp_solicit_src_vrf1, self.pg3.remote_mac, fib_id=1, oui=4) # # Remove the VSS config # relayed DHCP has default vlaues in the option. # self.vapi.dhcp_proxy_set_vss(1, 1, 4, is_ip6=1, is_add=0) self.pg3.add_stream(pkts_solicit_vrf1) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) rx = rx[0] self.verify_dhcp6_solicit(rx, self.pg1, dhcp_solicit_src_vrf1, self.pg3.remote_mac) # # Cleanup # self.vapi.dhcp_proxy_config(server_addr_vrf1, src_addr_vrf1, rx_table_id=1, server_table_id=1, is_ipv6=1, is_add=0) self.vapi.dhcp_proxy_config(server_addr_vrf1, src_addr_vrf1, rx_table_id=0, server_table_id=0, is_ipv6=1, is_add=0)