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>
This commit is contained in:
+46
-32
@@ -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 @@ api_bridge_domain_add_del (vat_main_t * vam)
|
||||
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 @@ api_bridge_domain_add_del (vat_main_t * vam)
|
||||
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 @@ vl_api_dhcp_proxy_details_t_handler (vl_api_dhcp_proxy_details_t * mp)
|
||||
|
||||
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 @@ static void vl_api_dhcp_proxy_details_t_handler_json
|
||||
|
||||
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 @@ api_dhcp_proxy_set_vss (vat_main_t * vam)
|
||||
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 @@ _(sw_interface_set_l2_bridge, \
|
||||
"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 @@ _(dhcp_proxy_config, \
|
||||
"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]") \
|
||||
|
||||
+10
-4
@@ -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 @@ autoreply define dhcp_proxy_config
|
||||
@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 @@ autoreply define dhcp_proxy_set_vss
|
||||
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 @@ manual_endian manual_print define dhcp_proxy_details
|
||||
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;
|
||||
|
||||
@@ -229,19 +229,19 @@ dhcp_proxy_to_server_input (vlib_main_t * vm,
|
||||
}
|
||||
}
|
||||
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 @@ dhcp_proxy_to_server_input (vlib_main_t * vm,
|
||||
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 @@ dhcp_proxy_to_server_input (vlib_main_t * vm,
|
||||
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 @@ dhcp_proxy_to_server_input (vlib_main_t * vm,
|
||||
* 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 @@ dhcp_proxy_to_server_input (vlib_main_t * vm,
|
||||
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 @@ dhcp_proxy_to_server_input (vlib_main_t * vm,
|
||||
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 @@ dhcp_option_82_vss_fn (vlib_main_t * vm,
|
||||
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,
|
||||
};
|
||||
|
||||
|
||||
@@ -164,7 +164,8 @@ typedef CLIB_PACKED (struct {
|
||||
|
||||
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 {
|
||||
|
||||
@@ -330,31 +330,40 @@ dhcpv6_proxy_to_server_input (vlib_main_t * vm,
|
||||
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 @@ dhcpv6_vss_command_fn (vlib_main_t * vm,
|
||||
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 @@ dhcpv6_vss_command_fn (vlib_main_t * vm,
|
||||
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,
|
||||
};
|
||||
|
||||
|
||||
@@ -55,14 +55,16 @@ static void
|
||||
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 @@ dhcp_send_details (fib_protocol_t proto,
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
+61
-23
@@ -278,19 +278,60 @@ dhcp_vss_show_walk (dhcp_vss_t *vss,
|
||||
{
|
||||
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 @@ int dhcp_proxy_set_vss (fib_protocol_t proto,
|
||||
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);
|
||||
|
||||
@@ -48,13 +48,24 @@ typedef enum {
|
||||
*/
|
||||
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 @@ int dhcp_vss_show_walk (dhcp_vss_t *vss,
|
||||
/**
|
||||
* @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
|
||||
|
||||
@@ -844,9 +844,13 @@ static void *vl_api_dhcp_proxy_set_vss_t_print
|
||||
|
||||
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 ");
|
||||
|
||||
+298
-170
File diff suppressed because it is too large
Load Diff
@@ -2021,18 +2021,22 @@ class VppPapiProvider(object):
|
||||
|
||||
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,
|
||||
|
||||
Reference in New Issue
Block a user