Add Support of DHCP VSS Type 0 where VPN-ID is ASCII
Enhence support of DHCP VSS (Virtual Subnet Selection) to include
VSS type 0 where VSS info is a NVT (Network Virtual Terminal)
ASCII VPN ID where the ASCII string MUST NOT be terminated with a
zero byte. Existing code already support VSS type 1, where VSS
information is a RFC 2685 VPN-ID of 7 bytes with 3 bytes OUI
and 4 bytes VPN index, and VSS type 255 indicating global VPN.
Change-Id: I54edbc447c89a2aacd1cc9fc72bd5ba386037608
Signed-off-by: John Lo <loj@cisco.com>
diff --git a/src/vat/api_format.c b/src/vat/api_format.c
index 612fba6..cfdce0b 100644
--- a/src/vat/api_format.c
+++ b/src/vat/api_format.c
@@ -50,6 +50,7 @@
#include <vnet/policer/policer.h>
#include <vnet/policer/police.h>
#include <vnet/mfib/mfib_types.h>
+#include <vnet/dhcp/dhcp_proxy.h>
#include "vat/json_format.h"
@@ -7060,7 +7061,7 @@
goto done;
}
- if ((bd_tag) && (strlen ((char *) bd_tag) > 63))
+ if ((bd_tag) && (vec_len (bd_tag) > 63))
{
errmsg ("bd-tag cannot be longer than 63");
ret = -99;
@@ -7078,8 +7079,10 @@
mp->is_add = is_add;
mp->mac_age = (u8) mac_age;
if (bd_tag)
- strcpy ((char *) mp->bd_tag, (char *) bd_tag);
-
+ {
+ clib_memcpy (mp->bd_tag, bd_tag, vec_len (bd_tag));
+ mp->bd_tag[vec_len (bd_tag)] = 0;
+ }
S (mp);
W (ret);
@@ -9337,15 +9340,19 @@
if (mp->is_ipv6)
print (vam->ofp,
- "RX Table-ID %d, Source Address %U, VSS FIB-ID %d, VSS OUI %d",
+ "RX Table-ID %d, Source Address %U, VSS Type %d, "
+ "VSS VPN-ID '%s', VSS FIB-ID %d, VSS OUI %d",
ntohl (mp->rx_vrf_id),
format_ip6_address, mp->dhcp_src_address,
+ mp->vss_type, mp->vss_vpn_ascii_id,
ntohl (mp->vss_oui), ntohl (mp->vss_fib_id));
else
print (vam->ofp,
- "RX Table-ID %d, Source Address %U, VSS FIB-ID %d, VSS OUI %d",
+ "RX Table-ID %d, Source Address %U, VSS Type %d, "
+ "VSS VPN-ID '%s', VSS FIB-ID %d, VSS OUI %d",
ntohl (mp->rx_vrf_id),
format_ip4_address, mp->dhcp_src_address,
+ mp->vss_type, mp->vss_vpn_ascii_id,
ntohl (mp->vss_oui), ntohl (mp->vss_fib_id));
for (i = 0; i < count; i++)
@@ -9382,6 +9389,10 @@
vat_json_init_object (node);
vat_json_object_add_uint (node, "rx-table-id", ntohl (mp->rx_vrf_id));
+ vat_json_object_add_bytes (node, "vss-type", &mp->vss_type,
+ sizeof (mp->vss_type));
+ vat_json_object_add_string_copy (node, "vss-vpn-ascii-id",
+ mp->vss_vpn_ascii_id);
vat_json_object_add_uint (node, "vss-fib-id", ntohl (mp->vss_fib_id));
vat_json_object_add_uint (node, "vss-oui", ntohl (mp->vss_oui));
@@ -9456,59 +9467,62 @@
vl_api_dhcp_proxy_set_vss_t *mp;
u8 is_ipv6 = 0;
u8 is_add = 1;
- u32 tbl_id;
- u8 tbl_id_set = 0;
- u32 oui;
- u8 oui_set = 0;
- u32 fib_id;
- u8 fib_id_set = 0;
+ u32 tbl_id = ~0;
+ u8 vss_type = VSS_TYPE_DEFAULT;
+ u8 *vpn_ascii_id = 0;
+ u32 oui = 0;
+ u32 fib_id = 0;
int ret;
while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
{
if (unformat (i, "tbl_id %d", &tbl_id))
- tbl_id_set = 1;
- if (unformat (i, "fib_id %d", &fib_id))
- fib_id_set = 1;
- if (unformat (i, "oui %d", &oui))
- oui_set = 1;
+ ;
+ else if (unformat (i, "vpn_ascii_id %s", &vpn_ascii_id))
+ vss_type = VSS_TYPE_ASCII;
+ else if (unformat (i, "fib_id %d", &fib_id))
+ vss_type = VSS_TYPE_VPN_ID;
+ else if (unformat (i, "oui %d", &oui))
+ vss_type = VSS_TYPE_VPN_ID;
else if (unformat (i, "ipv6"))
is_ipv6 = 1;
else if (unformat (i, "del"))
is_add = 0;
else
- {
- clib_warning ("parse error '%U'", format_unformat_error, i);
- return -99;
- }
+ break;
}
- if (tbl_id_set == 0)
+ if (tbl_id == ~0)
{
- errmsg ("missing tbl id");
+ errmsg ("missing tbl_id ");
+ vec_free (vpn_ascii_id);
return -99;
}
- if (fib_id_set == 0)
+ if ((vpn_ascii_id) && (vec_len (vpn_ascii_id) > 128))
{
- errmsg ("missing fib id");
- return -99;
- }
- if (oui_set == 0)
- {
- errmsg ("missing oui");
+ errmsg ("vpn_ascii_id cannot be longer than 128 ");
+ vec_free (vpn_ascii_id);
return -99;
}
M (DHCP_PROXY_SET_VSS, mp);
mp->tbl_id = ntohl (tbl_id);
- mp->fib_id = ntohl (fib_id);
+ mp->vss_type = vss_type;
+ if (vpn_ascii_id)
+ {
+ clib_memcpy (mp->vpn_ascii_id, vpn_ascii_id, vec_len (vpn_ascii_id));
+ mp->vpn_ascii_id[vec_len (vpn_ascii_id)] = 0;
+ }
+ mp->vpn_index = ntohl (fib_id);
mp->oui = ntohl (oui);
mp->is_ipv6 = is_ipv6;
mp->is_add = is_add;
S (mp);
W (ret);
+
+ vec_free (vpn_ascii_id);
return ret;
}
@@ -22344,7 +22358,7 @@
"enable | disable") \
_(bridge_domain_set_mac_age, "bd_id <bridge-domain-id> mac-age 0-255") \
_(bridge_domain_add_del, \
- "bd_id <bridge-domain-id> [flood 1|0] [uu-flood 1|0] [forward 1|0] [learn 1|0] [arp-term 1|0] [mac-age 0-255] [bd-tag <tag>] [del]\n") \
+ "bd_id <bridge-domain-id> [flood 1|0] [uu-flood 1|0] [forward 1|0] [learn 1|0] [arp-term 1|0] [mac-age 0-255] [bd-tag <text>] [del]\n") \
_(bridge_domain_dump, "[bd_id <bridge-domain-id>]\n") \
_(l2fib_add_del, \
"mac <mac-addr> bd_id <bridge-domain-id> [del] | sw_if <intfc> | sw_if_index <id> [static] [filter] [bvi] [count <nn>]\n") \
@@ -22409,7 +22423,7 @@
"svr <v46-address> src <v46-address>\n" \
"rx_vrf_id <nn> server_vrf_id <nn> [del]") \
_(dhcp_proxy_set_vss, \
- "tbl_id <n> fib_id <n> oui <n> [ipv6] [del]") \
+ "tbl_id <n> [fib_id <n> oui <n> | vpn_ascii_id <text>] [ipv6] [del]") \
_(dhcp_proxy_dump, "ip6") \
_(dhcp_client_config, \
"<intfc> | sw_if_index <id> [hostname <name>] [disable_event] [del]") \
diff --git a/src/vnet/dhcp/dhcp.api b/src/vnet/dhcp/dhcp.api
index 628b674..19650f5 100644
--- a/src/vnet/dhcp/dhcp.api
+++ b/src/vnet/dhcp/dhcp.api
@@ -13,7 +13,7 @@
* limitations under the License.
*/
-vl_api_version 1.0.0
+vl_api_version 1.0.1
/** \brief DHCP Proxy config add / del request
@param client_index - opaque cookie to identify the sender
@@ -42,8 +42,10 @@
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param tbl_id - table id
- @param oui - first part of vpn id
- @param fib_id - second part of vpn id
+ @vss_type - 0: use ASCI vpn_id; 1: use oui/vpn_index; 255: global vpn
+ @vpn_ascii - null terminated ASCII VPN ID up to 128 characters
+ @param oui - first part of rfc2685 vpn id, 3 bytes oui
+ @param vpn_index - second part of rfc2685 vpn id, 4 bytes vpn index
@param is_ipv6 - ip6 if non-zero, else ip4
@param is_add - set vss if non-zero, else delete
*/
@@ -52,8 +54,10 @@
u32 client_index;
u32 context;
u32 tbl_id;
+ u8 vss_type;
+ u8 vpn_ascii_id[129];
u32 oui;
- u32 fib_id;
+ u32 vpn_index;
u8 is_ipv6;
u8 is_add;
};
@@ -128,6 +132,8 @@
u32 rx_vrf_id;
u32 vss_oui;
u32 vss_fib_id;
+ u8 vss_type;
+ u8 vss_vpn_ascii_id[129];
u8 is_ipv6;
u8 dhcp_src_address[16];
u8 count;
diff --git a/src/vnet/dhcp/dhcp4_proxy_node.c b/src/vnet/dhcp/dhcp4_proxy_node.c
index 339a788..cd52be8 100644
--- a/src/vnet/dhcp/dhcp4_proxy_node.c
+++ b/src/vnet/dhcp/dhcp4_proxy_node.c
@@ -229,19 +229,19 @@
}
}
o = (dhcp_option_t *) (((uword) o) + (o->length + 2));
- }
+ }
fl = vlib_buffer_get_free_list (vm, vlib_buffer_get_free_list_index (b0));
// start write at (option*)o, some packets have padding
if (((u8 *)o - (u8 *)b0->data + VPP_DHCP_OPTION82_SIZE) > fl->n_data_bytes)
- {
+ {
next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP;
pkts_too_big++;
goto do_trace;
- }
+ }
if ((o->option == 0xFF) && ((u8 *)o <= end))
- {
+ {
vnet_main_t *vnm = vnet_get_main();
u16 old_l0, new_l0;
ip4_address_t _ia0, * ia0 = &_ia0;
@@ -264,65 +264,53 @@
ia0 = ip4_interface_first_address(&ip4_main, sw_if_index, 0);
if (ia0 == 0)
- {
+ {
error0 = DHCP_PROXY_ERROR_NO_INTERFACE_ADDRESS;
next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP;
pkts_no_interface_address++;
goto do_trace;
- }
+ }
/* Add option 82 */
o->option = 82; /* option 82 */
o->length = 12; /* 12 octets to follow */
o->data[0] = 1; /* suboption 1, circuit ID (=FIB id) */
o->data[1] = 4; /* length of suboption */
- o->data[2] = (original_sw_if_index >> 24) & 0xFF;
- o->data[3] = (original_sw_if_index >> 16) & 0xFF;
- o->data[4] = (original_sw_if_index >> 8) & 0xFF;
- o->data[5] = (original_sw_if_index >> 0) & 0xFF;
+ u32 *o_ifid = (u32 *) &o->data[2];
+ *o_ifid = clib_host_to_net_u32 (original_sw_if_index);
o->data[6] = 5; /* suboption 5 (client RX intfc address) */
o->data[7] = 4; /* length 4 */
- o->data[8] = ia0->as_u8[0];
- o->data[9] = ia0->as_u8[1];
- o->data[10] = ia0->as_u8[2];
- o->data[11] = ia0->as_u8[3];
+ u32 *o_addr = (u32 *) &o->data[8];
+ *o_addr = ia0->as_u32;
o->data[12] = 0xFF;
vss = dhcp_get_vss_info (dpm, fib_index, FIB_PROTOCOL_IP4);
- if (NULL != vss)
- {
- u32 opt82_fib_id=0, opt82_oui=0;
+ if (vss)
+ {
+ u32 id_len; /* length of VPN ID */
- opt82_oui = vss->oui;
- opt82_fib_id = vss->fib_id;
+ if (vss->vss_type == VSS_TYPE_VPN_ID)
+ {
+ id_len = sizeof (vss->vpn_id); /* vpn_id is 7 bytes */
+ memcpy (&o->data[15], vss->vpn_id, id_len);
+ }
+ else if (vss->vss_type == VSS_TYPE_ASCII)
+ {
+ id_len = vec_len (vss->vpn_ascii_id);
+ memcpy (&o->data[15], vss->vpn_ascii_id, id_len);
+ }
+ else /* must be VSS_TYPE_DEFAULT, no VPN ID */
+ id_len = 0;
- o->data[12] = 151; /* vss suboption */
- if (255 == opt82_fib_id) {
- o->data[13] = 1; /* length */
- o->data[14] = 255; /* vss option type */
- o->data[15] = 152; /* vss control suboption */
- o->data[16] = 0; /* length */
- /* and a new "end-of-options" option (0xff) */
- o->data[17] = 0xFF;
- o->length += 5;
- } else {
- o->data[13] = 8; /* length */
- o->data[14] = 1; /* vss option type */
- o->data[15] = (opt82_oui >> 16) & 0xff;
- o->data[16] = (opt82_oui >> 8) & 0xff;
- o->data[17] = (opt82_oui ) & 0xff;
- o->data[18] = (opt82_fib_id >> 24) & 0xff;
- o->data[19] = (opt82_fib_id >> 16) & 0xff;
- o->data[20] = (opt82_fib_id >> 8) & 0xff;
- o->data[21] = (opt82_fib_id) & 0xff;
- o->data[22] = 152; /* vss control suboption */
- o->data[23] = 0; /* length */
-
- /* and a new "end-of-options" option (0xff) */
- o->data[24] = 0xFF;
- o->length += 12;
- }
- }
+ o->data[12] = 151; /* vss suboption */
+ o->data[13] = id_len + 1; /* length: vss_type + id_len */
+ o->data[14] = vss->vss_type; /* vss option type */
+ o->data[15 + id_len] = 152; /* vss control suboption */
+ o->data[16 + id_len] = 0; /* length */
+ o->data[17 + id_len] = 0xFF; /* "end-of-options" (0xFF) */
+ /* 5 bytes for suboption headers 151+len, 152+len and 0xFF */
+ o->length += id_len + 5;
+ }
len = o->length + 3;
b0->current_length += len;
@@ -341,11 +329,13 @@
new_l0 = clib_net_to_host_u16 (u0->length);
new_l0 += len;
u0->length = clib_host_to_net_u16 (new_l0);
- } else {
+ }
+ else
+ {
vlib_node_increment_counter
(vm, dhcp_proxy_to_server_node.index,
DHCP_PROXY_ERROR_OPTION_82_ERROR, 1);
- }
+ }
next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP;
@@ -355,11 +345,11 @@
* those servers
*/
if (is_discover && vec_len(proxy->dhcp_servers) > 1)
- {
+ {
u32 ii;
for (ii = 1; ii < vec_len(proxy->dhcp_servers); ii++)
- {
+ {
vlib_buffer_t *c0;
u32 ci0;
@@ -387,7 +377,7 @@
ci0, next0);
if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
- {
+ {
dhcp_proxy_trace_t *tr;
tr = vlib_add_trace (vm, node, c0, sizeof (*tr));
@@ -397,15 +387,15 @@
tr->sw_if_index = sw_if_index;
if (next0 == DHCP_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP)
tr->trace_ip4_address.as_u32 = server->dhcp_server.ip4.as_u32;
- }
+ }
if (PREDICT_FALSE(0 == n_left_to_next))
- {
+ {
vlib_put_next_frame (vm, node, next_index,
n_left_to_next);
vlib_get_next_frame (vm, node, next_index,
to_next, n_left_to_next);
- }
+ }
}
}
do_trace:
@@ -949,54 +939,47 @@
unformat_input_t * input,
vlib_cli_command_t * cmd)
{
- int is_del = 0, got_new_vpn_id=0;
- u32 oui=0, fib_id=0, tbl_id=~0;
+ u8 is_del = 0, vss_type = VSS_TYPE_DEFAULT;
+ u32 oui = 0, fib_id = 0, tbl_id = ~0;
+ u8 *vpn_ascii_id = 0;
while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
{
-
- if (unformat(input, "delete") || unformat(input, "del"))
- is_del = 1;
+ if (unformat (input, "table %d", &tbl_id))
+ ;
else if (unformat (input, "oui %d", &oui))
- got_new_vpn_id = 1;
+ vss_type = VSS_TYPE_VPN_ID;
else if (unformat (input, "vpn-id %d", &fib_id))
- got_new_vpn_id = 1;
- else if (unformat (input, "table %d", &tbl_id))
- got_new_vpn_id = 1;
+ vss_type = VSS_TYPE_VPN_ID;
+ else if (unformat (input, "vpn-ascii-id %s", &vpn_ascii_id))
+ vss_type = VSS_TYPE_ASCII;
+ else if (unformat(input, "delete") || unformat(input, "del"))
+ is_del = 1;
else
- break;
- }
+ break;
+ }
+
if (tbl_id == ~0)
return clib_error_return (0, "no table ID specified.");
- if (is_del || got_new_vpn_id)
+ int rv = dhcp_proxy_set_vss (FIB_PROTOCOL_IP4, tbl_id, vss_type,
+ vpn_ascii_id, oui, fib_id, is_del);
+ switch (rv)
{
- int rv;
- rv = dhcp_proxy_set_vss(FIB_PROTOCOL_IP4, tbl_id, oui, fib_id, is_del);
- switch (rv)
- {
- case 0:
- return 0;
-
- case VNET_API_ERROR_NO_SUCH_FIB:
- return clib_error_return (0, "option 82 vss(oui:%d, vpn-id:%d) not found in table %d",
- oui, fib_id, tbl_id);
-
- case VNET_API_ERROR_NO_SUCH_ENTRY:
- return clib_error_return (0, "option 82 vss for table %d not found in in pool.",
- tbl_id);
- default:
- return clib_error_return (0, "BUG: rv %d", rv);
- }
+ case 0:
+ return 0;
+ case VNET_API_ERROR_NO_SUCH_ENTRY:
+ return clib_error_return (0, "option 82 vss for table %d not found in in pool.",
+ tbl_id);
+ default:
+ return clib_error_return (0, "BUG: rv %d", rv);
+
}
- else
- return clib_error_return (0, "parse error`%U'",
- format_unformat_error, input);
}
VLIB_CLI_COMMAND (dhcp_proxy_vss_command,static) = {
.path = "set dhcp option-82 vss",
- .short_help = "set dhcp option-82 vss [del] table <table id> oui <oui> vpn-id <vpn-id>",
+ .short_help = "set dhcp option-82 vss [del] table <table id> [oui <n> vpn-id <n> | vpn-ascii-id <text>]",
.function = dhcp_option_82_vss_fn,
};
diff --git a/src/vnet/dhcp/dhcp6_packet.h b/src/vnet/dhcp/dhcp6_packet.h
index ddcde7a..24a1814 100644
--- a/src/vnet/dhcp/dhcp6_packet.h
+++ b/src/vnet/dhcp/dhcp6_packet.h
@@ -164,7 +164,8 @@
typedef CLIB_PACKED (struct {
dhcpv6_option_t opt;
- u8 data[8]; // data[0]:type, data[1..7]: VPN ID
+ u8 vss_type;
+ u8 data[0];
}) dhcpv6_vss_t;
typedef CLIB_PACKED (struct {
diff --git a/src/vnet/dhcp/dhcp6_proxy_node.c b/src/vnet/dhcp/dhcp6_proxy_node.c
index ce7a8fc..3cac278 100644
--- a/src/vnet/dhcp/dhcp6_proxy_node.c
+++ b/src/vnet/dhcp/dhcp6_proxy_node.c
@@ -330,31 +330,40 @@
cmac = (dhcpv6_client_mac_t *) (((uword) ip1) + b0->current_length);
b0->current_length += (sizeof (*cmac));
cmac->opt.length =clib_host_to_net_u16(sizeof(*cmac) -
- sizeof(cmac->opt));
+ sizeof(cmac->opt));
cmac->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_CLIENT_LINK_LAYER_ADDRESS);
- cmac->link_type = clib_host_to_net_u16(1); // ethernet
+ cmac->link_type = clib_host_to_net_u16(1); /* ethernet */
clib_memcpy(cmac->data, client_src_mac, 6);
u1->length += sizeof(*cmac);
}
vss = dhcp_get_vss_info(dpm, rx_fib_idx, FIB_PROTOCOL_IP6);
- if (NULL != vss) {
+ if (vss)
+ {
+ u16 id_len; /* length of VPN ID */
+ u16 type_len = sizeof (vss1->vss_type);
+
vss1 = (dhcpv6_vss_t *) (((uword) ip1) + b0->current_length);
- b0->current_length += (sizeof (*vss1));
- vss1->opt.length =clib_host_to_net_u16(sizeof(*vss1) -
- sizeof(vss1->opt));
- vss1->opt.option = clib_host_to_net_u16(DHCPV6_OPTION_VSS);
- vss1->data[0] = 1; // type
- vss1->data[1] = vss->oui >>16 & 0xff;
- vss1->data[2] = vss->oui >>8 & 0xff;
- vss1->data[3] = vss->oui & 0xff;
- vss1->data[4] = vss->fib_id >> 24 & 0xff;
- vss1->data[5] = vss->fib_id >> 16 & 0xff;
- vss1->data[6] = vss->fib_id >> 8 & 0xff;
- vss1->data[7] = vss->fib_id & 0xff;
- u1->length += sizeof(*vss1);
- }
+ vss1->vss_type = vss->vss_type;
+ if (vss->vss_type == VSS_TYPE_VPN_ID)
+ {
+ id_len = sizeof (vss->vpn_id); /* vpn_id is 7 bytes */
+ memcpy (vss1->data, vss->vpn_id, id_len);
+ }
+ else if (vss->vss_type == VSS_TYPE_ASCII)
+ {
+ id_len = vec_len (vss->vpn_ascii_id);
+ memcpy (vss1->data, vss->vpn_ascii_id, id_len);
+ }
+ else /* must be VSS_TYPE_DEFAULT, no VPN ID */
+ id_len = 0;
+
+ vss1->opt.option = clib_host_to_net_u16 (DHCPV6_OPTION_VSS);
+ vss1->opt.length = clib_host_to_net_u16 (type_len + id_len);
+ u1->length += type_len + id_len + sizeof (vss1->opt);
+ b0->current_length += type_len + id_len + sizeof (vss1->opt);
+ }
pkts_to_server++;
u1->checksum = 0;
@@ -1030,18 +1039,20 @@
unformat_input_t * input,
vlib_cli_command_t * cmd)
{
- int is_del = 0, got_new_vss=0;
- u32 oui=0;
- u32 fib_id=0, tbl_id=~0;
+ u8 is_del = 0, vss_type = VSS_TYPE_DEFAULT;
+ u8 *vpn_ascii_id = 0;
+ u32 oui = 0, fib_id = 0, tbl_id = ~0;
while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT)
{
- if (unformat (input, "oui %d", &oui))
- got_new_vss = 1;
+ if (unformat (input, "table %d", &tbl_id))
+ ;
+ else if (unformat (input, "oui %d", &oui))
+ vss_type = VSS_TYPE_VPN_ID;
else if (unformat (input, "vpn-id %d", &fib_id))
- got_new_vss = 1;
- else if (unformat (input, "table %d", &tbl_id))
- got_new_vss = 1;
+ vss_type = VSS_TYPE_VPN_ID;
+ else if (unformat (input, "vpn-ascii-id %s", &vpn_ascii_id))
+ vss_type = VSS_TYPE_ASCII;
else if (unformat(input, "delete") || unformat(input, "del"))
is_del = 1;
else
@@ -1051,37 +1062,23 @@
if (tbl_id ==~0)
return clib_error_return (0, "no table ID specified.");
- if (is_del || got_new_vss)
+ int rv = dhcp_proxy_set_vss(FIB_PROTOCOL_IP6, tbl_id, vss_type,
+ vpn_ascii_id, oui, fib_id, is_del);
+ switch (rv)
{
- int rv;
-
- rv = dhcp_proxy_set_vss(FIB_PROTOCOL_IP6, tbl_id, oui, fib_id, is_del);
- switch (rv)
- {
- case 0:
- return 0;
-
- case VNET_API_ERROR_NO_SUCH_FIB:
- return clib_error_return (0, "vss info (oui:%d, vpn-id:%d) not found in table %d.",
- oui, fib_id, tbl_id);
-
- case VNET_API_ERROR_NO_SUCH_ENTRY:
- return clib_error_return (0, "vss for table %d not found in pool.",
- tbl_id);
-
- default:
- return clib_error_return (0, "BUG: rv %d", rv);
- }
+ case 0:
+ return 0;
+ case VNET_API_ERROR_NO_SUCH_ENTRY:
+ return clib_error_return (0, "vss for table %d not found in pool.",
+ tbl_id);
+ default:
+ return clib_error_return (0, "BUG: rv %d", rv);
}
- else
- return clib_error_return (0, "parse error`%U'",
- format_unformat_error, input);
-
}
VLIB_CLI_COMMAND (dhcpv6_proxy_vss_command, static) = {
.path = "set dhcpv6 vss",
- .short_help = "set dhcpv6 vss table <table-id> oui <oui> vpn-idx <vpn-idx>",
+ .short_help = "set dhcpv6 vss table <table-id> [oui <n> vpn-id <n> | vpn-ascii-id <text>]",
.function = dhcpv6_vss_command_fn,
};
diff --git a/src/vnet/dhcp/dhcp_api.c b/src/vnet/dhcp/dhcp_api.c
index d6984f2..ad96e02 100644
--- a/src/vnet/dhcp/dhcp_api.c
+++ b/src/vnet/dhcp/dhcp_api.c
@@ -55,14 +55,16 @@
vl_api_dhcp_proxy_set_vss_t_handler (vl_api_dhcp_proxy_set_vss_t * mp)
{
vl_api_dhcp_proxy_set_vss_reply_t *rmp;
+ u8 *vpn_ascii_id;
int rv;
- rv = dhcp_proxy_set_vss ((mp->is_ipv6 ?
- FIB_PROTOCOL_IP6 :
- FIB_PROTOCOL_IP4),
- ntohl (mp->tbl_id),
- ntohl (mp->oui),
- ntohl (mp->fib_id), (int) mp->is_add == 0);
+ mp->vpn_ascii_id[sizeof (mp->vpn_ascii_id) - 1] = 0;
+ vpn_ascii_id = format (0, "%s", mp->vpn_ascii_id);
+ rv =
+ dhcp_proxy_set_vss ((mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4),
+ ntohl (mp->tbl_id), mp->vss_type, vpn_ascii_id,
+ ntohl (mp->oui), ntohl (mp->vpn_index),
+ mp->is_add == 0);
REPLY_MACRO (VL_API_DHCP_PROXY_SET_VSS_REPLY);
}
@@ -147,11 +149,27 @@
vss = dhcp_get_vss_info (&dhcp_proxy_main, proxy->rx_fib_index, proto);
- if (NULL != vss)
+ if (vss)
{
- mp->vss_oui = htonl (vss->oui);
- mp->vss_fib_id = htonl (vss->fib_id);
+ mp->vss_type = vss->vss_type;
+ if (vss->vss_type == VSS_TYPE_ASCII)
+ {
+ u32 id_len = vec_len (vss->vpn_ascii_id);
+ clib_memcpy (mp->vss_vpn_ascii_id, vss->vpn_ascii_id, id_len);
+ }
+ else if (vss->vss_type == VSS_TYPE_VPN_ID)
+ {
+ u32 oui = ((u32) vss->vpn_id[0] << 16) + ((u32) vss->vpn_id[1] << 8)
+ + ((u32) vss->vpn_id[2]);
+ u32 fib_id = ((u32) vss->vpn_id[3] << 24) +
+ ((u32) vss->vpn_id[4] << 16) + ((u32) vss->vpn_id[5] << 8) +
+ ((u32) vss->vpn_id[6]);
+ mp->vss_oui = htonl (oui);
+ mp->vss_fib_id = htonl (fib_id);
+ }
}
+ else
+ mp->vss_type = VSS_TYPE_INVALID;
vec_foreach_index (count, proxy->dhcp_servers)
{
diff --git a/src/vnet/dhcp/dhcp_proxy.c b/src/vnet/dhcp/dhcp_proxy.c
index 1784906..dae6312 100644
--- a/src/vnet/dhcp/dhcp_proxy.c
+++ b/src/vnet/dhcp/dhcp_proxy.c
@@ -278,19 +278,60 @@
{
vlib_main_t * vm = ctx;
- vlib_cli_output (vm, "%=6d%=6d%=12d",
- rx_table_id,
- vss->oui,
- vss->fib_id);
+ if (vss->vss_type == VSS_TYPE_VPN_ID)
+ {
+ u32 oui = ((u32) vss->vpn_id[0] << 16) + ((u32) vss->vpn_id[1] << 8)
+ + ((u32) vss->vpn_id[2]);
+ u32 fib_id = ((u32) vss->vpn_id[3] << 24) + ((u32) vss->vpn_id[4] << 16)
+ + ((u32) vss->vpn_id[5] << 8) + ((u32) vss->vpn_id[6]);
+ vlib_cli_output (vm, " fib_table: %d oui: %d vpn_index: %d",
+ rx_table_id, oui, fib_id);
+ }
+ else if (vss->vss_type == VSS_TYPE_ASCII)
+ vlib_cli_output (vm, " fib_table: %d vpn_id: %s",
+ rx_table_id, vss->vpn_ascii_id);
+ else
+ vlib_cli_output (vm, " fib_table: %d default global vpn", rx_table_id);
return (1);
}
+void update_vss (dhcp_vss_t *v,
+ u8 vss_type,
+ u8 *vpn_ascii_id,
+ u32 oui,
+ u32 vpn_index)
+{
+ v->vss_type = vss_type;
+ if (v->vpn_ascii_id)
+ {
+ if (v->vpn_ascii_id == (u8 *) ~0)
+ v->vpn_ascii_id = 0;
+ else
+ vec_free (v->vpn_ascii_id);
+ }
+
+ if (vss_type == VSS_TYPE_ASCII)
+ v->vpn_ascii_id = vpn_ascii_id;
+ else if (vss_type == VSS_TYPE_VPN_ID)
+ {
+ v->vpn_id[0] = (oui >> 16) & 0xff;
+ v->vpn_id[1] = (oui >> 8) & 0xff;
+ v->vpn_id[2] = (oui >> 0) & 0xff;
+ v->vpn_id[3] = (vpn_index >> 24) & 0xff;
+ v->vpn_id[4] = (vpn_index >> 16) & 0xff;
+ v->vpn_id[5] = (vpn_index >> 8) & 0xff;
+ v->vpn_id[6] = (vpn_index >> 0) & 0xff;
+ }
+}
+
int dhcp_proxy_set_vss (fib_protocol_t proto,
u32 tbl_id,
+ u8 vss_type,
+ u8 *vpn_ascii_id,
u32 oui,
- u32 fib_id,
- int is_del)
+ u32 vpn_index,
+ u8 is_del)
{
dhcp_proxy_main_t *dm = &dhcp_proxy_main;
dhcp_vss_t *v = NULL;
@@ -306,43 +347,40 @@
v = dhcp_get_vss_info(dm, rx_fib_index, proto);
if (NULL != v)
- {
+ {
if (is_del)
- {
+ {
/* release the lock held on the table when the VSS
* info was created */
dhcp_proxy_rx_table_unlock (proto, rx_fib_index);
+ vec_free (v->vpn_ascii_id);
pool_put (dm->vss[proto], v);
dm->vss_index_by_rx_fib_index[proto][rx_fib_index] = ~0;
- }
+ }
else
- {
- /* this is a modify */
- v->fib_id = fib_id;
- v->oui = oui;
- }
- }
+ {
+ update_vss (v, vss_type, vpn_ascii_id, oui, vpn_index);
+ }
+ }
else
- {
+ {
if (is_del)
- rc = VNET_API_ERROR_NO_SUCH_ENTRY;
+ rc = VNET_API_ERROR_NO_SUCH_ENTRY;
else
- {
+ {
/* create a new entry */
vec_validate_init_empty(dm->vss_index_by_rx_fib_index[proto],
rx_fib_index, ~0);
/* hold a lock on the table whilst the VSS info exist */
pool_get (dm->vss[proto], v);
- v->fib_id = fib_id;
- v->oui = oui;
-
+ update_vss (v, vss_type, vpn_ascii_id, oui, vpn_index);
dm->vss_index_by_rx_fib_index[proto][rx_fib_index] =
v - dm->vss[proto];
dhcp_proxy_rx_table_lock (proto, rx_fib_index);
- }
- }
+ }
+ }
/* Release the lock taken during the create_or_lock at the start */
dhcp_proxy_rx_table_unlock (proto, rx_fib_index);
diff --git a/src/vnet/dhcp/dhcp_proxy.h b/src/vnet/dhcp/dhcp_proxy.h
index ef2bc0a..9b15ac8 100644
--- a/src/vnet/dhcp/dhcp_proxy.h
+++ b/src/vnet/dhcp/dhcp_proxy.h
@@ -48,13 +48,24 @@
*/
typedef struct dhcp_vss_t_ {
/**
- * @brief ?? RFC doesn't say
+ * @brief VSS type as defined in RFC 6607:
+ * 0 for NVT ASCII VPN Identifier
+ * 1 for RFC 2685 VPN-ID of 7 octects - 3 bytes OUI & 4 bytes VPN index
+ * 255 for global default VPN
*/
- u32 oui;
+ u8 vss_type;
+#define VSS_TYPE_ASCII 0
+#define VSS_TYPE_VPN_ID 1
+#define VSS_TYPE_INVALID 123
+#define VSS_TYPE_DEFAULT 255
/**
- * @brief VPN-ID
+ * @brief Type 1 VPN-ID
*/
- u32 fib_id;
+ u8 vpn_id[7];
+ /**
+ * @brief Type 0 ASCII VPN Identifier
+ */
+ u8 *vpn_ascii_id;
} dhcp_vss_t;
/**
@@ -152,11 +163,13 @@
/**
* @brief Configure/set a new VSS info
*/
-int dhcp_proxy_set_vss(fib_protocol_t proto,
- u32 vrf_id,
- u32 oui,
- u32 fib_id,
- int is_del);
+int dhcp_proxy_set_vss (fib_protocol_t proto,
+ u32 tbl_id,
+ u8 vss_type,
+ u8 *vpn_ascii_id,
+ u32 oui,
+ u32 vpn_index,
+ u8 is_del);
/**
* @brief Dump the proxy configs to the API
diff --git a/src/vpp/api/custom_dump.c b/src/vpp/api/custom_dump.c
index fd0e88a..f27acda 100644
--- a/src/vpp/api/custom_dump.c
+++ b/src/vpp/api/custom_dump.c
@@ -844,9 +844,13 @@
s = format (s, "tbl_id %d ", ntohl (mp->tbl_id));
- s = format (s, "fib_id %d ", ntohl (mp->fib_id));
-
- s = format (s, "oui %d ", ntohl (mp->oui));
+ if (mp->vss_type == VSS_TYPE_VPN_ID)
+ {
+ s = format (s, "fib_id %d ", ntohl (mp->vpn_index));
+ s = format (s, "oui %d ", ntohl (mp->oui));
+ }
+ else if (mp->vss_type == VSS_TYPE_ASCII)
+ s = format (s, "vpn_ascii_id %s", mp->vpn_ascii_id);
if (mp->is_ipv6 != 0)
s = format (s, "ipv6 ");
diff --git a/test/test_dhcp.py b/test/test_dhcp.py
index 42b80af..7ae98e8 100644
--- a/test/test_dhcp.py
+++ b/test/test_dhcp.py
@@ -4,7 +4,7 @@
import socket
import struct
-from framework import VppTestCase, VppTestRunner
+from framework import VppTestCase, VppTestRunner, running_extended_tests
from vpp_neighbor import VppNeighbor
from vpp_ip_route import find_route, VppIpTable
from util import mk_ll_addr
@@ -33,12 +33,12 @@
def setUp(self):
super(TestDHCP, self).setUp()
- # create 3 pg interfaces
- self.create_pg_interfaces(range(4))
+ # create 6 pg interfaces for pg0 to pg5
+ self.create_pg_interfaces(range(6))
self.tables = []
- # pg0 and 1 are IP configured in VRF 0 and 1.
- # pg2 and 3 are non IP-configured in VRF 0 and 1
+ # pg0 to 2 are IP configured in VRF 0, 1 and 2.
+ # pg3 to 5 are non IP-configured in VRF 0, 1 and 2.
table_id = 0
for table_id in range(1, 4):
tbl4 = VppIpTable(self, table_id)
@@ -49,7 +49,7 @@
self.tables.append(tbl6)
table_id = 0
- for i in self.pg_interfaces[:2]:
+ for i in self.pg_interfaces[:3]:
i.admin_up()
i.set_table_ip4(table_id)
i.set_table_ip6(table_id)
@@ -60,14 +60,14 @@
table_id += 1
table_id = 0
- for i in self.pg_interfaces[2:]:
+ for i in self.pg_interfaces[3:]:
i.admin_up()
i.set_table_ip4(table_id)
i.set_table_ip6(table_id)
table_id += 1
def tearDown(self):
- for i in self.pg_interfaces[:2]:
+ for i in self.pg_interfaces[:3]:
i.unconfig_ip4()
i.unconfig_ip6()
@@ -96,10 +96,11 @@
self.assertTrue(found)
- def validate_relay_options(self, pkt, intf, ip_addr, fib_id, oui):
+ def validate_relay_options(self, pkt, intf, ip_addr, vpn_id, fib_id, oui):
dhcp = pkt[DHCP]
found = 0
data = []
+ id_len = len(vpn_id)
for i in dhcp.options:
if type(i) is tuple:
@@ -110,6 +111,8 @@
data = i[1]
if oui != 0:
self.assertEqual(len(data), 24)
+ elif len(vpn_id) > 0:
+ self.assertEqual(len(data), len(vpn_id)+17)
else:
self.assertEqual(len(data), 12)
@@ -142,8 +145,9 @@
self.assertEqual(data[11], claddr[3])
if oui != 0:
- # sub-option 151 encodes the 3 byte oui
- # and the 4 byte fib_id
+ # sub-option 151 encodes vss_type 1,
+ # the 3 byte oui and the 4 byte fib_id
+ self.assertEqual(id_len, 0)
self.assertEqual(ord(data[12]), 151)
self.assertEqual(ord(data[13]), 8)
self.assertEqual(ord(data[14]), 1)
@@ -159,6 +163,19 @@
self.assertEqual(ord(data[22]), 152)
self.assertEqual(ord(data[23]), 0)
+ if id_len > 0:
+ # sub-option 151 encode vss_type of 0
+ # followerd by vpn_id in ascii
+ self.assertEqual(oui, 0)
+ self.assertEqual(ord(data[12]), 151)
+ self.assertEqual(ord(data[13]), id_len+1)
+ self.assertEqual(ord(data[14]), 0)
+ self.assertEqual(data[15:15+id_len], vpn_id)
+
+ # VSS control sub-option
+ self.assertEqual(ord(data[15+len(vpn_id)]), 152)
+ self.assertEqual(ord(data[16+len(vpn_id)]), 0)
+
found = 1
self.assertTrue(found)
@@ -174,7 +191,7 @@
found = True
self.assertTrue(found)
- def verify_dhcp_offer(self, pkt, intf, fib_id=0, oui=0):
+ def verify_dhcp_offer(self, pkt, intf, vpn_id="", fib_id=0, oui=0):
ether = pkt[Ether]
self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
self.assertEqual(ether.src, intf.local_mac)
@@ -189,7 +206,7 @@
self.verify_dhcp_msg_type(pkt, "offer")
data = self.validate_relay_options(pkt, intf, intf.local_ip4,
- fib_id, oui)
+ vpn_id, fib_id, oui)
def verify_orig_dhcp_pkt(self, pkt, intf):
ether = pkt[Ether]
@@ -229,6 +246,7 @@
def verify_relayed_dhcp_discover(self, pkt, intf, src_intf=None,
fib_id=0, oui=0,
+ vpn_id="",
dst_mac=None, dst_ip=None):
if not dst_mac:
dst_mac = intf.remote_mac
@@ -259,11 +277,13 @@
data = self.validate_relay_options(pkt, src_intf,
src_intf.local_ip4,
+ vpn_id,
fib_id, oui)
return data
def verify_dhcp6_solicit(self, pkt, intf,
peer_ip, peer_mac,
+ vpn_id="",
fib_id=0,
oui=0,
dst_mac=None,
@@ -293,7 +313,10 @@
self.assertEqual(cll.lltype, 1)
self.assertEqual(cll.clladdr, peer_mac)
+ id_len = len(vpn_id)
+
if fib_id != 0:
+ self.assertEqual(id_len, 0)
vss = pkt[DHCP6OptVSS]
self.assertEqual(vss.optlen, 8)
self.assertEqual(vss.type, 1)
@@ -307,6 +330,13 @@
self.assertEqual(ord(vss.data[5]), 0)
self.assertEqual(ord(vss.data[6]), fib_id)
+ if id_len > 0:
+ self.assertEqual(oui, 0)
+ vss = pkt[DHCP6OptVSS]
+ self.assertEqual(vss.optlen, id_len+1)
+ self.assertEqual(vss.type, 0)
+ self.assertEqual(vss.data[0:id_len], vpn_id)
+
# the relay message should be an encoded Solicit
msg = pkt[DHCP6OptRelayMsg]
sol = DHCP6_Solicit()
@@ -336,7 +366,7 @@
# Verify no response to DHCP request without DHCP config
#
p_disc_vrf0 = (Ether(dst="ff:ff:ff:ff:ff:ff",
- src=self.pg2.remote_mac) /
+ src=self.pg3.remote_mac) /
IP(src="0.0.0.0", dst="255.255.255.255") /
UDP(sport=DHCP4_CLIENT_PORT,
dport=DHCP4_SERVER_PORT) /
@@ -344,17 +374,27 @@
DHCP(options=[('message-type', 'discover'), ('end')]))
pkts_disc_vrf0 = [p_disc_vrf0]
p_disc_vrf1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
- src=self.pg3.remote_mac) /
+ src=self.pg4.remote_mac) /
IP(src="0.0.0.0", dst="255.255.255.255") /
UDP(sport=DHCP4_CLIENT_PORT,
dport=DHCP4_SERVER_PORT) /
BOOTP(op=1) /
DHCP(options=[('message-type', 'discover'), ('end')]))
- pkts_disc_vrf1 = [p_disc_vrf0]
+ pkts_disc_vrf1 = [p_disc_vrf1]
+ p_disc_vrf2 = (Ether(dst="ff:ff:ff:ff:ff:ff",
+ src=self.pg5.remote_mac) /
+ IP(src="0.0.0.0", dst="255.255.255.255") /
+ UDP(sport=DHCP4_CLIENT_PORT,
+ dport=DHCP4_SERVER_PORT) /
+ BOOTP(op=1) /
+ DHCP(options=[('message-type', 'discover'), ('end')]))
+ pkts_disc_vrf2 = [p_disc_vrf2]
- self.send_and_assert_no_replies(self.pg2, pkts_disc_vrf0,
+ self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf0,
"DHCP with no configuration")
- self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf1,
+ self.send_and_assert_no_replies(self.pg4, pkts_disc_vrf1,
+ "DHCP with no configuration")
+ self.send_and_assert_no_replies(self.pg5, pkts_disc_vrf2,
"DHCP with no configuration")
#
@@ -371,7 +411,7 @@
# Discover packets from the client are dropped because there is no
# IP address configured on the client facing interface
#
- self.send_and_assert_no_replies(self.pg2, pkts_disc_vrf0,
+ self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf0,
"Discover DHCP no relay address")
#
@@ -386,13 +426,13 @@
DHCP(options=[('message-type', 'offer'), ('end')]))
pkts = [p]
- self.send_and_assert_no_replies(self.pg2, pkts,
+ self.send_and_assert_no_replies(self.pg3, pkts,
"Offer DHCP no relay address")
#
# configure an IP address on the client facing interface
#
- self.pg2.config_ip4()
+ self.pg3.config_ip4()
#
# Try again with a discover packet
@@ -401,7 +441,7 @@
# UDP source ports are unchanged
# we've no option 82 config so that should be absent
#
- self.pg2.add_stream(pkts_disc_vrf0)
+ self.pg3.add_stream(pkts_disc_vrf0)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
@@ -409,7 +449,7 @@
rx = rx[0]
option_82 = self.verify_relayed_dhcp_discover(rx, self.pg0,
- src_intf=self.pg2)
+ src_intf=self.pg3)
#
# Create an DHCP offer reply from the server with a correctly formatted
@@ -429,10 +469,10 @@
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- rx = self.pg2.get_capture(1)
+ rx = self.pg3.get_capture(1)
rx = rx[0]
- self.verify_dhcp_offer(rx, self.pg2)
+ self.verify_dhcp_offer(rx, self.pg3)
#
# Bogus Option 82:
@@ -469,7 +509,7 @@
#
# Send a DHCP request in VRF 1. should be dropped.
#
- self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf1,
+ self.send_and_assert_no_replies(self.pg4, pkts_disc_vrf1,
"DHCP with no configuration VRF 1")
#
@@ -481,65 +521,91 @@
rx_table_id=0,
is_add=0)
- self.send_and_assert_no_replies(self.pg2, pkts_disc_vrf0,
+ self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf0,
"DHCP config removed VRF 0")
- self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf1,
+ self.send_and_assert_no_replies(self.pg4, pkts_disc_vrf1,
"DHCP config removed VRF 1")
#
- # Add DHCP config for VRF 1
+ # Add DHCP config for VRF 1 & 2
#
- server_addr = self.pg1.remote_ip4n
- src_addr = self.pg1.local_ip4n
- self.vapi.dhcp_proxy_config(server_addr,
- src_addr,
+ server_addr1 = self.pg1.remote_ip4n
+ src_addr1 = self.pg1.local_ip4n
+ self.vapi.dhcp_proxy_config(server_addr1,
+ src_addr1,
rx_table_id=1,
server_table_id=1)
+ server_addr2 = self.pg2.remote_ip4n
+ src_addr2 = self.pg2.local_ip4n
+ self.vapi.dhcp_proxy_config(server_addr2,
+ src_addr2,
+ rx_table_id=2,
+ server_table_id=2)
#
- # Confim DHCP requests ok in VRF 1.
+ # Confim DHCP requests ok in VRF 1 & 2.
# - dropped on IP config on client interface
#
- self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf1,
+ self.send_and_assert_no_replies(self.pg4, pkts_disc_vrf1,
"DHCP config removed VRF 1")
+ self.send_and_assert_no_replies(self.pg5, pkts_disc_vrf2,
+ "DHCP config removed VRF 2")
#
# configure an IP address on the client facing interface
#
- self.pg3.config_ip4()
-
- self.pg3.add_stream(pkts_disc_vrf1)
+ self.pg4.config_ip4()
+ self.pg4.add_stream(pkts_disc_vrf1)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
-
rx = self.pg1.get_capture(1)
rx = rx[0]
- self.verify_relayed_dhcp_discover(rx, self.pg1, src_intf=self.pg3)
+ self.verify_relayed_dhcp_discover(rx, self.pg1, src_intf=self.pg4)
+
+ self.pg5.config_ip4()
+ self.pg5.add_stream(pkts_disc_vrf2)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ rx = self.pg2.get_capture(1)
+ rx = rx[0]
+ self.verify_relayed_dhcp_discover(rx, self.pg2, src_intf=self.pg5)
#
# Add VSS config
- # table=1, fib=id=1, oui=4
- self.vapi.dhcp_proxy_set_vss(1, 1, 4)
+ # table=1, vss_type=1, vpn_index=1, oui=4
+ # table=2, vss_type=0, vpn_id = "ip4-table-2"
+ self.vapi.dhcp_proxy_set_vss(1, 1, vpn_index=1, oui=4, is_add=1)
+ self.vapi.dhcp_proxy_set_vss(2, 0, "ip4-table-2", is_add=1)
- self.pg3.add_stream(pkts_disc_vrf1)
+ self.pg4.add_stream(pkts_disc_vrf1)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
rx = self.pg1.get_capture(1)
rx = rx[0]
self.verify_relayed_dhcp_discover(rx, self.pg1,
- src_intf=self.pg3,
+ src_intf=self.pg4,
fib_id=1, oui=4)
+ self.pg5.add_stream(pkts_disc_vrf2)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ rx = self.pg2.get_capture(1)
+ rx = rx[0]
+ self.verify_relayed_dhcp_discover(rx, self.pg2,
+ src_intf=self.pg5,
+ vpn_id="ip4-table-2")
+
#
# 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_INET, self.pg1.remote_hosts[1].ip4)
+ server_addr12 = socket.inet_pton(AF_INET, self.pg1.remote_hosts[1].ip4)
- self.vapi.dhcp_proxy_config(server_addr2,
- src_addr,
+ self.vapi.dhcp_proxy_config(server_addr12,
+ src_addr1,
rx_table_id=1,
server_table_id=1,
is_add=1)
@@ -558,7 +624,7 @@
# 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(pkts_disc_vrf1)
+ self.pg4.add_stream(pkts_disc_vrf1)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
@@ -566,12 +632,12 @@
option_82 = self.verify_relayed_dhcp_discover(
rx[0], self.pg1,
- src_intf=self.pg3,
+ src_intf=self.pg4,
dst_mac=self.pg1.remote_hosts[1].mac,
dst_ip=self.pg1.remote_hosts[1].ip4,
fib_id=1, oui=4)
self.verify_relayed_dhcp_discover(rx[1], self.pg1,
- src_intf=self.pg3,
+ src_intf=self.pg4,
fib_id=1, oui=4)
#
@@ -597,10 +663,10 @@
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- rx = self.pg3.get_capture(2)
+ rx = self.pg4.get_capture(2)
- self.verify_dhcp_offer(rx[0], self.pg3, fib_id=1, oui=4)
- self.verify_dhcp_offer(rx[1], self.pg3, fib_id=1, oui=4)
+ self.verify_dhcp_offer(rx[0], self.pg4, fib_id=1, oui=4)
+ self.verify_dhcp_offer(rx[1], self.pg4, fib_id=1, oui=4)
#
# Ensure offers from non-servers are dropeed
@@ -619,7 +685,7 @@
# Ensure only the discover is sent to multiple servers
#
p_req_vrf1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
- src=self.pg3.remote_mac) /
+ src=self.pg4.remote_mac) /
IP(src="0.0.0.0", dst="255.255.255.255") /
UDP(sport=DHCP4_CLIENT_PORT,
dport=DHCP4_SERVER_PORT) /
@@ -627,7 +693,7 @@
DHCP(options=[('message-type', 'request'),
('end')]))
- self.pg3.add_stream(p_req_vrf1)
+ self.pg4.add_stream(p_req_vrf1)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
@@ -636,8 +702,8 @@
#
# Remove the second DHCP server
#
- self.vapi.dhcp_proxy_config(server_addr2,
- src_addr,
+ self.vapi.dhcp_proxy_config(server_addr12,
+ src_addr1,
rx_table_id=1,
server_table_id=1,
is_add=0)
@@ -645,45 +711,55 @@
#
# Test we can still relay with the first
#
- self.pg3.add_stream(pkts_disc_vrf1)
+ self.pg4.add_stream(pkts_disc_vrf1)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
rx = self.pg1.get_capture(1)
rx = rx[0]
self.verify_relayed_dhcp_discover(rx, self.pg1,
- src_intf=self.pg3,
+ src_intf=self.pg4,
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_add=0)
+ self.vapi.dhcp_proxy_set_vss(1, is_add=0)
+ self.vapi.dhcp_proxy_set_vss(2, is_add=0)
- self.pg3.add_stream(pkts_disc_vrf1)
+ self.pg4.add_stream(pkts_disc_vrf1)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
rx = self.pg1.get_capture(1)
rx = rx[0]
- self.verify_relayed_dhcp_discover(rx, self.pg1, src_intf=self.pg3)
+ self.verify_relayed_dhcp_discover(rx, self.pg1, src_intf=self.pg4)
#
# remove DHCP config to cleanup
#
- self.vapi.dhcp_proxy_config(server_addr,
- src_addr,
+ self.vapi.dhcp_proxy_config(server_addr1,
+ src_addr1,
rx_table_id=1,
server_table_id=1,
is_add=0)
+ self.vapi.dhcp_proxy_config(server_addr2,
+ src_addr2,
+ rx_table_id=2,
+ server_table_id=2,
+ is_add=0)
- self.send_and_assert_no_replies(self.pg2, pkts_disc_vrf0,
+ self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf0,
"DHCP cleanup VRF 0")
- self.send_and_assert_no_replies(self.pg3, pkts_disc_vrf1,
+ self.send_and_assert_no_replies(self.pg4, pkts_disc_vrf1,
"DHCP cleanup VRF 1")
- self.pg2.unconfig_ip4()
+ self.send_and_assert_no_replies(self.pg5, pkts_disc_vrf2,
+ "DHCP cleanup VRF 2")
+
self.pg3.unconfig_ip4()
+ self.pg4.unconfig_ip4()
+ self.pg5.unconfig_ip4()
def test_dhcp6_proxy(self):
""" DHCPv6 Proxy"""
@@ -691,30 +767,41 @@
# 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)
+ dhcp_solicit_src_vrf0 = mk_ll_addr(self.pg3.remote_mac)
+ dhcp_solicit_src_vrf1 = mk_ll_addr(self.pg4.remote_mac)
+ dhcp_solicit_src_vrf2 = mk_ll_addr(self.pg5.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
+ server_addr_vrf2 = self.pg2.remote_ip6n
+ src_addr_vrf2 = self.pg2.local_ip6n
dmac = in6_getnsmac(inet_pton(socket.AF_INET6, dhcp_solicit_dst))
- p_solicit_vrf0 = (Ether(dst=dmac, src=self.pg2.remote_mac) /
+ p_solicit_vrf0 = (Ether(dst=dmac, src=self.pg3.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) /
+ p_solicit_vrf1 = (Ether(dst=dmac, src=self.pg4.remote_mac) /
IPv6(src=dhcp_solicit_src_vrf1,
dst=dhcp_solicit_dst) /
UDP(sport=DHCP6_SERVER_PORT,
dport=DHCP6_CLIENT_PORT) /
DHCP6_Solicit())
+ p_solicit_vrf2 = (Ether(dst=dmac, src=self.pg5.remote_mac) /
+ IPv6(src=dhcp_solicit_src_vrf2,
+ 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,
+ self.send_and_assert_no_replies(self.pg3, p_solicit_vrf0,
"DHCP with no configuration")
- self.send_and_assert_no_replies(self.pg3, p_solicit_vrf1,
+ self.send_and_assert_no_replies(self.pg4, p_solicit_vrf1,
+ "DHCP with no configuration")
+ self.send_and_assert_no_replies(self.pg5, p_solicit_vrf2,
"DHCP with no configuration")
#
@@ -728,20 +815,20 @@
server_table_id=0,
is_ipv6=1)
- self.send_and_assert_no_replies(self.pg2, p_solicit_vrf0,
+ self.send_and_assert_no_replies(self.pg3, p_solicit_vrf0,
"DHCP with no configuration")
- self.send_and_assert_no_replies(self.pg3, p_solicit_vrf1,
+ self.send_and_assert_no_replies(self.pg4, p_solicit_vrf1,
"DHCP with no configuration")
#
# configure an IP address on the client facing interface
#
- self.pg2.config_ip6()
+ self.pg3.config_ip6()
#
# Now the DHCP requests are relayed to the server
#
- self.pg2.add_stream(p_solicit_vrf0)
+ self.pg3.add_stream(p_solicit_vrf0)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
@@ -749,7 +836,7 @@
self.verify_dhcp6_solicit(rx[0], self.pg0,
dhcp_solicit_src_vrf0,
- self.pg2.remote_mac)
+ self.pg3.remote_mac)
#
# Exception cases for rejected relay responses
@@ -760,7 +847,7 @@
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,
+ self.send_and_assert_no_replies(self.pg3, p_adv_vrf0,
"DHCP6 not a relay reply")
# 2 - no relay message option
@@ -769,7 +856,7 @@
UDP(sport=DHCP6_SERVER_PORT, dport=DHCP6_SERVER_PORT) /
DHCP6_RelayReply() /
DHCP6_Advertise())
- self.send_and_assert_no_replies(self.pg2, p_adv_vrf0,
+ self.send_and_assert_no_replies(self.pg3, p_adv_vrf0,
"DHCP not a relay message")
# 3 - no circuit ID
@@ -779,7 +866,7 @@
DHCP6_RelayReply() /
DHCP6OptRelayMsg(optlen=0) /
DHCP6_Advertise())
- self.send_and_assert_no_replies(self.pg2, p_adv_vrf0,
+ self.send_and_assert_no_replies(self.pg3, 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) /
@@ -789,7 +876,7 @@
DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x05') /
DHCP6OptRelayMsg(optlen=0) /
DHCP6_Advertise())
- self.send_and_assert_no_replies(self.pg2, p_adv_vrf0,
+ self.send_and_assert_no_replies(self.pg3, p_adv_vrf0,
"DHCP6 wrong circuit ID")
#
@@ -799,7 +886,7 @@
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') /
+ DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') /
DHCP6OptRelayMsg(optlen=0) /
DHCP6_Advertise(trid=1) /
DHCP6OptStatusCode(statuscode=0))
@@ -809,9 +896,9 @@
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- rx = self.pg2.get_capture(1)
+ rx = self.pg3.get_capture(1)
- self.verify_dhcp6_advert(rx[0], self.pg2, "::")
+ self.verify_dhcp6_advert(rx[0], self.pg3, "::")
#
# Send the relay response (the advertisement)
@@ -820,7 +907,7 @@
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') /
+ DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x04') /
DHCP6OptRelayMsg(optlen=0) /
DHCP6_Advertise(trid=1) /
DHCP6OptStatusCode(statuscode=0))
@@ -830,24 +917,31 @@
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- rx = self.pg2.get_capture(1)
+ rx = self.pg3.get_capture(1)
- self.verify_dhcp6_advert(rx[0], self.pg2, dhcp_solicit_src_vrf0)
+ self.verify_dhcp6_advert(rx[0], self.pg3, dhcp_solicit_src_vrf0)
#
- # Add all the config for VRF 1
+ # Add all the config for VRF 1 & 2
#
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()
+ self.pg4.config_ip6()
+
+ self.vapi.dhcp_proxy_config(server_addr_vrf2,
+ src_addr_vrf2,
+ rx_table_id=2,
+ server_table_id=2,
+ is_ipv6=1)
+ self.pg5.config_ip6()
#
# VRF 1 solicit
#
- self.pg3.add_stream(p_solicit_vrf1)
+ self.pg4.add_stream(p_solicit_vrf1)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
@@ -855,7 +949,20 @@
self.verify_dhcp6_solicit(rx[0], self.pg1,
dhcp_solicit_src_vrf1,
- self.pg3.remote_mac)
+ self.pg4.remote_mac)
+
+ #
+ # VRF 2 solicit
+ #
+ self.pg5.add_stream(p_solicit_vrf2)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ rx = self.pg2.get_capture(1)
+
+ self.verify_dhcp6_solicit(rx[0], self.pg2,
+ dhcp_solicit_src_vrf2,
+ self.pg5.remote_mac)
#
# VRF 1 Advert
@@ -864,7 +971,7 @@
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') /
+ DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x05') /
DHCP6OptRelayMsg(optlen=0) /
DHCP6_Advertise(trid=1) /
DHCP6OptStatusCode(statuscode=0))
@@ -874,16 +981,18 @@
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- rx = self.pg3.get_capture(1)
+ rx = self.pg4.get_capture(1)
- self.verify_dhcp6_advert(rx[0], self.pg3, dhcp_solicit_src_vrf1)
+ self.verify_dhcp6_advert(rx[0], self.pg4, 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)
+ # table=1, vss_type=1, vpn_index=1, oui=4
+ # table=2, vss_type=0, vpn_id = "ip6-table-2"
+ self.vapi.dhcp_proxy_set_vss(1, 1, oui=4, vpn_index=1, is_ip6=1)
+ self.vapi.dhcp_proxy_set_vss(2, 0, "IPv6-table-2", is_ip6=1)
- self.pg3.add_stream(p_solicit_vrf1)
+ self.pg4.add_stream(p_solicit_vrf1)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
@@ -891,17 +1000,28 @@
self.verify_dhcp6_solicit(rx[0], self.pg1,
dhcp_solicit_src_vrf1,
- self.pg3.remote_mac,
+ self.pg4.remote_mac,
fib_id=1,
oui=4)
+ self.pg5.add_stream(p_solicit_vrf2)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ rx = self.pg2.get_capture(1)
+
+ self.verify_dhcp6_solicit(rx[0], self.pg2,
+ dhcp_solicit_src_vrf2,
+ self.pg5.remote_mac,
+ vpn_id="IPv6-table-2")
+
#
# 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.vapi.dhcp_proxy_set_vss(1, is_ip6=1, is_add=0)
- self.pg3.add_stream(p_solicit_vrf1)
+ self.pg4.add_stream(p_solicit_vrf1)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
@@ -909,16 +1029,17 @@
self.verify_dhcp6_solicit(rx[0], self.pg1,
dhcp_solicit_src_vrf1,
- self.pg3.remote_mac)
+ self.pg4.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)
+ server_addr12 = socket.inet_pton(AF_INET6,
+ self.pg1.remote_hosts[1].ip6)
- self.vapi.dhcp_proxy_config(server_addr2,
+ self.vapi.dhcp_proxy_config(server_addr12,
src_addr_vrf1,
rx_table_id=1,
server_table_id=1,
@@ -939,7 +1060,7 @@
# 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.pg4.add_stream(p_solicit_vrf1)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
@@ -947,10 +1068,10 @@
self.verify_dhcp6_solicit(rx[0], self.pg1,
dhcp_solicit_src_vrf1,
- self.pg3.remote_mac)
+ self.pg4.remote_mac)
self.verify_dhcp6_solicit(rx[1], self.pg1,
dhcp_solicit_src_vrf1,
- self.pg3.remote_mac,
+ self.pg4.remote_mac,
dst_mac=self.pg1.remote_hosts[1].mac,
dst_ip=self.pg1.remote_hosts[1].ip6)
@@ -961,7 +1082,7 @@
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') /
+ DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x05') /
DHCP6OptRelayMsg(optlen=0) /
DHCP6_Advertise(trid=1) /
DHCP6OptStatusCode(statuscode=0))
@@ -969,7 +1090,7 @@
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') /
+ DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x05') /
DHCP6OptRelayMsg(optlen=0) /
DHCP6_Advertise(trid=1) /
DHCP6OptStatusCode(statuscode=0))
@@ -980,22 +1101,22 @@
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- rx = self.pg3.get_capture(2)
+ rx = self.pg4.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)
+ self.verify_dhcp6_advert(rx[0], self.pg4, dhcp_solicit_src_vrf1)
+ self.verify_dhcp6_advert(rx[1], self.pg4, dhcp_solicit_src_vrf1)
#
# Ensure only solicit messages are duplicated
#
- p_request_vrf1 = (Ether(dst=dmac, src=self.pg3.remote_mac) /
+ p_request_vrf1 = (Ether(dst=dmac, src=self.pg4.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.pg4.add_stream(p_request_vrf1)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
@@ -1009,7 +1130,7 @@
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') /
+ DHCP6OptIfaceId(optlen=4, ifaceid='\x00\x00\x00\x05') /
DHCP6OptRelayMsg(optlen=0) /
DHCP6_Advertise(trid=1) /
DHCP6OptStatusCode(statuscode=0))
@@ -1019,7 +1140,7 @@
#
# Remove the second DHCP server
#
- self.vapi.dhcp_proxy_config(server_addr2,
+ self.vapi.dhcp_proxy_config(server_addr12,
src_addr_vrf1,
rx_table_id=1,
server_table_id=1,
@@ -1029,7 +1150,7 @@
#
# Test we can still relay with the first
#
- self.pg3.add_stream(p_solicit_vrf1)
+ self.pg4.add_stream(p_solicit_vrf1)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
@@ -1037,11 +1158,17 @@
self.verify_dhcp6_solicit(rx[0], self.pg1,
dhcp_solicit_src_vrf1,
- self.pg3.remote_mac)
+ self.pg4.remote_mac)
#
# Cleanup
#
+ self.vapi.dhcp_proxy_config(server_addr_vrf2,
+ src_addr_vrf2,
+ rx_table_id=2,
+ server_table_id=2,
+ is_ipv6=1,
+ is_add=0)
self.vapi.dhcp_proxy_config(server_addr_vrf1,
src_addr_vrf1,
rx_table_id=1,
@@ -1062,8 +1189,9 @@
server_table_id=0,
is_ipv6=1,
is_add=0)
- self.pg2.unconfig_ip6()
self.pg3.unconfig_ip6()
+ self.pg4.unconfig_ip6()
+ self.pg5.unconfig_ip6()
def test_dhcp_client(self):
""" DHCP Client"""
@@ -1073,119 +1201,119 @@
self.pg_enable_capture(self.pg_interfaces)
#
- # Configure DHCP client on PG2 and capture the discover sent
+ # Configure DHCP client on PG3 and capture the discover sent
#
- self.vapi.dhcp_client(self.pg2.sw_if_index, hostname)
+ self.vapi.dhcp_client(self.pg3.sw_if_index, hostname)
- rx = self.pg2.get_capture(1)
+ rx = self.pg3.get_capture(1)
- self.verify_orig_dhcp_discover(rx[0], self.pg2, hostname)
+ self.verify_orig_dhcp_discover(rx[0], self.pg3, hostname)
#
- # Sned back on offer, expect the request
+ # Send back on offer, expect the request
#
- p_offer = (Ether(dst=self.pg2.local_mac, src=self.pg2.remote_mac) /
- IP(src=self.pg2.remote_ip4, dst="255.255.255.255") /
+ p_offer = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
+ IP(src=self.pg3.remote_ip4, dst="255.255.255.255") /
UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
- BOOTP(op=1, yiaddr=self.pg2.local_ip4) /
+ BOOTP(op=1, yiaddr=self.pg3.local_ip4) /
DHCP(options=[('message-type', 'offer'),
- ('server_id', self.pg2.remote_ip4),
+ ('server_id', self.pg3.remote_ip4),
('end')]))
- self.pg2.add_stream(p_offer)
+ self.pg3.add_stream(p_offer)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- rx = self.pg2.get_capture(1)
- self.verify_orig_dhcp_request(rx[0], self.pg2, hostname,
- self.pg2.local_ip4)
+ rx = self.pg3.get_capture(1)
+ self.verify_orig_dhcp_request(rx[0], self.pg3, hostname,
+ self.pg3.local_ip4)
#
# Send an acknowloedgement
#
- p_ack = (Ether(dst=self.pg2.local_mac, src=self.pg2.remote_mac) /
- IP(src=self.pg2.remote_ip4, dst="255.255.255.255") /
+ p_ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
+ IP(src=self.pg3.remote_ip4, dst="255.255.255.255") /
UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
- BOOTP(op=1, yiaddr=self.pg2.local_ip4) /
+ BOOTP(op=1, yiaddr=self.pg3.local_ip4) /
DHCP(options=[('message-type', 'ack'),
('subnet_mask', "255.255.255.0"),
- ('router', self.pg2.remote_ip4),
- ('server_id', self.pg2.remote_ip4),
+ ('router', self.pg3.remote_ip4),
+ ('server_id', self.pg3.remote_ip4),
('lease_time', 43200),
('end')]))
- self.pg2.add_stream(p_ack)
+ self.pg3.add_stream(p_ack)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
#
# We'll get an ARP request for the router address
#
- rx = self.pg2.get_capture(1)
+ rx = self.pg3.get_capture(1)
- self.assertEqual(rx[0][ARP].pdst, self.pg2.remote_ip4)
+ self.assertEqual(rx[0][ARP].pdst, self.pg3.remote_ip4)
self.pg_enable_capture(self.pg_interfaces)
#
# At the end of this procedure there should be a connected route
# in the FIB
#
- self.assertTrue(find_route(self, self.pg2.local_ip4, 24))
- self.assertTrue(find_route(self, self.pg2.local_ip4, 32))
+ self.assertTrue(find_route(self, self.pg3.local_ip4, 24))
+ self.assertTrue(find_route(self, self.pg3.local_ip4, 32))
# remove the left over ARP entry
- self.vapi.ip_neighbor_add_del(self.pg2.sw_if_index,
- mactobinary(self.pg2.remote_mac),
- self.pg2.remote_ip4,
+ self.vapi.ip_neighbor_add_del(self.pg3.sw_if_index,
+ mactobinary(self.pg3.remote_mac),
+ self.pg3.remote_ip4,
is_add=0)
#
# remove the DHCP config
#
- self.vapi.dhcp_client(self.pg2.sw_if_index, hostname, is_add=0)
+ self.vapi.dhcp_client(self.pg3.sw_if_index, hostname, is_add=0)
#
# and now the route should be gone
#
- self.assertFalse(find_route(self, self.pg2.local_ip4, 32))
- self.assertFalse(find_route(self, self.pg2.local_ip4, 24))
+ self.assertFalse(find_route(self, self.pg3.local_ip4, 32))
+ self.assertFalse(find_route(self, self.pg3.local_ip4, 24))
#
# Start the procedure again. this time have VPP send the client-ID
#
- self.pg2.admin_down()
+ self.pg3.admin_down()
self.sleep(1)
- self.pg2.admin_up()
- self.vapi.dhcp_client(self.pg2.sw_if_index, hostname,
- client_id=self.pg2.local_mac)
+ self.pg3.admin_up()
+ self.vapi.dhcp_client(self.pg3.sw_if_index, hostname,
+ client_id=self.pg3.local_mac)
- rx = self.pg2.get_capture(1)
+ rx = self.pg3.get_capture(1)
- self.verify_orig_dhcp_discover(rx[0], self.pg2, hostname,
- self.pg2.local_mac)
+ self.verify_orig_dhcp_discover(rx[0], self.pg3, hostname,
+ self.pg3.local_mac)
- self.pg2.add_stream(p_offer)
+ self.pg3.add_stream(p_offer)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- rx = self.pg2.get_capture(1)
- self.verify_orig_dhcp_request(rx[0], self.pg2, hostname,
- self.pg2.local_ip4)
+ rx = self.pg3.get_capture(1)
+ self.verify_orig_dhcp_request(rx[0], self.pg3, hostname,
+ self.pg3.local_ip4)
#
# unicast the ack to the offered address
#
- p_ack = (Ether(dst=self.pg2.local_mac, src=self.pg2.remote_mac) /
- IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) /
+ p_ack = (Ether(dst=self.pg3.local_mac, src=self.pg3.remote_mac) /
+ IP(src=self.pg3.remote_ip4, dst=self.pg3.local_ip4) /
UDP(sport=DHCP4_SERVER_PORT, dport=DHCP4_CLIENT_PORT) /
- BOOTP(op=1, yiaddr=self.pg2.local_ip4) /
+ BOOTP(op=1, yiaddr=self.pg3.local_ip4) /
DHCP(options=[('message-type', 'ack'),
('subnet_mask', "255.255.255.0"),
- ('router', self.pg2.remote_ip4),
- ('server_id', self.pg2.remote_ip4),
+ ('router', self.pg3.remote_ip4),
+ ('server_id', self.pg3.remote_ip4),
('lease_time', 43200),
('end')]))
- self.pg2.add_stream(p_ack)
+ self.pg3.add_stream(p_ack)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
@@ -1193,16 +1321,16 @@
# At the end of this procedure there should be a connected route
# in the FIB
#
- self.assertTrue(find_route(self, self.pg2.local_ip4, 32))
- self.assertTrue(find_route(self, self.pg2.local_ip4, 24))
+ self.assertTrue(find_route(self, self.pg3.local_ip4, 32))
+ self.assertTrue(find_route(self, self.pg3.local_ip4, 24))
#
# remove the DHCP config
#
- self.vapi.dhcp_client(self.pg2.sw_if_index, hostname, is_add=0)
+ self.vapi.dhcp_client(self.pg3.sw_if_index, hostname, is_add=0)
- self.assertFalse(find_route(self, self.pg2.local_ip4, 32))
- self.assertFalse(find_route(self, self.pg2.local_ip4, 24))
+ self.assertFalse(find_route(self, self.pg3.local_ip4, 32))
+ self.assertFalse(find_route(self, self.pg3.local_ip4, 24))
if __name__ == '__main__':
diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py
index 66126c5..3dd3482 100644
--- a/test/vpp_papi_provider.py
+++ b/test/vpp_papi_provider.py
@@ -2021,18 +2021,22 @@
def dhcp_proxy_set_vss(self,
table_id,
- fib_id,
- oui,
+ vss_type=255,
+ vpn_ascii_id="",
+ oui=0,
+ vpn_index=0,
is_add=1,
is_ip6=0):
return self.api(
self.papi.dhcp_proxy_set_vss,
{
'tbl_id': table_id,
- 'fib_id': fib_id,
- 'is_ipv6': is_ip6,
- 'is_add': is_add,
+ 'vss_type': vss_type,
+ 'vpn_ascii_id': vpn_ascii_id,
'oui': oui,
+ 'vpn_index': vpn_index,
+ 'is_add': is_add,
+ 'is_ipv6': is_ip6,
})
def dhcp_client(self,