diff options
author | John Lo <loj@cisco.com> | 2017-11-14 13:19:26 -0500 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2017-11-16 11:25:51 +0000 |
commit | 70bfcaf47779340951c1e6f169b1cedcabe708d1 (patch) | |
tree | b6e1378942f278e914b7139d1210562d943cb680 /src | |
parent | 9d72120a6986e642c5b16c8650ad266188adf142 (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.c | 78 | ||||
-rw-r--r-- | src/vnet/dhcp/dhcp.api | 14 | ||||
-rw-r--r-- | src/vnet/dhcp/dhcp4_proxy_node.c | 161 | ||||
-rw-r--r-- | src/vnet/dhcp/dhcp6_packet.h | 3 | ||||
-rw-r--r-- | src/vnet/dhcp/dhcp6_proxy_node.c | 97 | ||||
-rw-r--r-- | src/vnet/dhcp/dhcp_api.c | 36 | ||||
-rw-r--r-- | src/vnet/dhcp/dhcp_proxy.c | 84 | ||||
-rw-r--r-- | src/vnet/dhcp/dhcp_proxy.h | 31 | ||||
-rw-r--r-- | src/vpp/api/custom_dump.c | 10 |
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 "); |