summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJohn Lo <loj@cisco.com>2017-11-14 13:19:26 -0500
committerDave Barach <openvpp@barachs.net>2017-11-16 11:25:51 +0000
commit70bfcaf47779340951c1e6f169b1cedcabe708d1 (patch)
treeb6e1378942f278e914b7139d1210562d943cb680 /src
parent9d72120a6986e642c5b16c8650ad266188adf142 (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/vat/api_format.c78
-rw-r--r--src/vnet/dhcp/dhcp.api14
-rw-r--r--src/vnet/dhcp/dhcp4_proxy_node.c161
-rw-r--r--src/vnet/dhcp/dhcp6_packet.h3
-rw-r--r--src/vnet/dhcp/dhcp6_proxy_node.c97
-rw-r--r--src/vnet/dhcp/dhcp_api.c36
-rw-r--r--src/vnet/dhcp/dhcp_proxy.c84
-rw-r--r--src/vnet/dhcp/dhcp_proxy.h31
-rw-r--r--src/vpp/api/custom_dump.c10
9 files changed, 294 insertions, 220 deletions
diff --git a/src/vat/api_format.c b/src/vat/api_format.c
index 612fba66b0b..cfdce0bec2e 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 @@ 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)
- {
- errmsg ("missing fib id");
- return -99;
- }
- if (oui_set == 0)
+ if ((vpn_ascii_id) && (vec_len (vpn_ascii_id) > 128))
{
- 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]") \
diff --git a/src/vnet/dhcp/dhcp.api b/src/vnet/dhcp/dhcp.api
index 628b674e1c6..19650f5628b 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 @@ 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;
diff --git a/src/vnet/dhcp/dhcp4_proxy_node.c b/src/vnet/dhcp/dhcp4_proxy_node.c
index 339a78858a7..cd52be83f71 100644
--- a/src/vnet/dhcp/dhcp4_proxy_node.c
+++ b/src/vnet/dhcp/dhcp4_proxy_node.c
@@ -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;
-
- opt82_oui = vss->oui;
- opt82_fib_id = vss->fib_id;
-
- 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;
- }
- }
+ if (vss)
+ {
+ u32 id_len; /* length of VPN 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 */
+ 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,
};
diff --git a/src/vnet/dhcp/dhcp6_packet.h b/src/vnet/dhcp/dhcp6_packet.h
index ddcde7a0dd9..24a18144b16 100644
--- a/src/vnet/dhcp/dhcp6_packet.h
+++ b/src/vnet/dhcp/dhcp6_packet.h
@@ -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 {
diff --git a/src/vnet/dhcp/dhcp6_proxy_node.c b/src/vnet/dhcp/dhcp6_proxy_node.c
index ce7a8fca3bc..3cac278aa53 100644
--- a/src/vnet/dhcp/dhcp6_proxy_node.c
+++ b/src/vnet/dhcp/dhcp6_proxy_node.c
@@ -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,
};
diff --git a/src/vnet/dhcp/dhcp_api.c b/src/vnet/dhcp/dhcp_api.c
index d6984f2d083..ad96e027f57 100644
--- a/src/vnet/dhcp/dhcp_api.c
+++ b/src/vnet/dhcp/dhcp_api.c
@@ -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)
{
diff --git a/src/vnet/dhcp/dhcp_proxy.c b/src/vnet/dhcp/dhcp_proxy.c
index 1784906b7b3..dae631236de 100644
--- a/src/vnet/dhcp/dhcp_proxy.c
+++ b/src/vnet/dhcp/dhcp_proxy.c
@@ -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);
diff --git a/src/vnet/dhcp/dhcp_proxy.h b/src/vnet/dhcp/dhcp_proxy.h
index ef2bc0a1926..9b15ac82d1e 100644
--- a/src/vnet/dhcp/dhcp_proxy.h
+++ b/src/vnet/dhcp/dhcp_proxy.h
@@ -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
diff --git a/src/vpp/api/custom_dump.c b/src/vpp/api/custom_dump.c
index fd0e88a9bb1..f27acda24dd 100644
--- a/src/vpp/api/custom_dump.c
+++ b/src/vpp/api/custom_dump.c
@@ -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 ");