25 #define dhcp_proxy_error(n,s) s, 27 #undef dhcp_proxy_error 30 #define foreach_dhcp_proxy_to_server_input_next \ 31 _ (DROP, "error-drop") \ 32 _ (LOOKUP, "ip4-lookup") \ 33 _ (SEND_TO_CLIENT, "dhcp-proxy-to-client") 36 #define _(s,n) DHCP_PROXY_TO_SERVER_INPUT_NEXT_##s, 51 #define VPP_DHCP_OPTION82_SUB1_SIZE 6 52 #define VPP_DHCP_OPTION82_SUB5_SIZE 6 53 #define VPP_DHCP_OPTION82_VSS_SIZE 12 54 #define VPP_DHCP_OPTION82_SIZE (VPP_DHCP_OPTION82_SUB1_SIZE + \ 55 VPP_DHCP_OPTION82_SUB5_SIZE + \ 56 VPP_DHCP_OPTION82_VSS_SIZE +3) 69 s =
format (s,
"DHCP proxy: sent to server %U\n",
72 s =
format (s,
"DHCP proxy: broadcast to client from %U\n",
78 s =
format (s,
" original_sw_if_index: %d, sw_if_index: %d\n",
88 u32 max_header_bytes = va_arg (*args,
u32);
91 header_bytes =
sizeof (h[0]);
92 if (max_header_bytes != 0 && header_bytes > max_header_bytes)
93 return format (s,
"dhcp header truncated");
95 s =
format (s,
"DHCP Proxy");
105 u32 n_left_from, next_index, * from, * to_next;
109 u32 pkts_to_server=0, pkts_to_client=0, pkts_no_server=0;
110 u32 pkts_no_interface_address=0;
116 while (n_left_from > 0)
121 to_next, n_left_to_next);
123 while (n_left_from > 0 && n_left_to_next > 0)
135 u32 original_sw_if_index = 0;
162 if (u0->
src_port == clib_net_to_host_u16(UDP_DST_PORT_dhcp_to_server))
165 next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_SEND_TO_CLIENT;
178 error0 = DHCP_PROXY_ERROR_NO_SERVER;
179 next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP;
222 while (o->
option != 0xFF && (
u8 *)o < end)
238 next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP;
243 if ((o->
option == 0xFF) && ((
u8 *)o <= end))
251 original_sw_if_index = 0;
253 original_sw_if_index = sw_if_index =
268 error0 = DHCP_PROXY_ERROR_NO_INTERFACE_ADDRESS;
269 next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP;
270 pkts_no_interface_address++;
279 o->
data[2] = (original_sw_if_index >> 24) & 0xFF;
280 o->
data[3] = (original_sw_if_index >> 16) & 0xFF;
281 o->
data[4] = (original_sw_if_index >> 8) & 0xFF;
282 o->
data[5] = (original_sw_if_index >> 0) & 0xFF;
294 u32 opt82_fib_id=0, opt82_oui=0;
296 opt82_oui = vss->
oui;
297 opt82_fib_id = vss->
fib_id;
300 if (255 == opt82_fib_id) {
311 o->
data[15] = (opt82_oui >> 16) & 0xff;
312 o->
data[16] = (opt82_oui >> 8) & 0xff;
313 o->
data[17] = (opt82_oui ) & 0xff;
314 o->
data[18] = (opt82_fib_id >> 24) & 0xff;
315 o->
data[19] = (opt82_fib_id >> 16) & 0xff;
316 o->
data[20] = (opt82_fib_id >> 8) & 0xff;
317 o->
data[21] = (opt82_fib_id) & 0xff;
331 new_l0 = clib_net_to_host_u16 (old_l0);
333 new_l0 = clib_host_to_net_u16 (new_l0);
341 new_l0 = clib_net_to_host_u16 (u0->
length);
343 u0->
length = clib_host_to_net_u16 (new_l0);
347 DHCP_PROXY_ERROR_OPTION_82_ERROR, 1);
350 next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP;
386 to_next, n_left_to_next,
398 if (next0 == DHCP_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP)
407 to_next, n_left_to_next);
420 if (next0 == DHCP_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP)
431 to_next, n_left_to_next,
439 DHCP_PROXY_ERROR_RELAY_TO_CLIENT,
442 DHCP_PROXY_ERROR_RELAY_TO_SERVER,
445 DHCP_PROXY_ERROR_NO_SERVER,
448 DHCP_PROXY_ERROR_NO_INTERFACE_ADDRESS,
449 pkts_no_interface_address);
451 DHCP_PROXY_ERROR_PKT_TOO_BIG,
458 .name =
"dhcp-proxy-to-server",
460 .vector_size =
sizeof (
u32),
467 #define _(s,n) [DHCP_PROXY_TO_SERVER_INPUT_NEXT_##s] = n, 475 .unformat_buffer = unformat_dhcp_proxy_header,
484 u32 n_left_from, * from;
493 while (n_left_from > 0)
508 u32 sw_if_index = ~0;
515 u32 original_sw_if_index = (
u32) ~0;
550 while (o->
option != 0xFF &&
558 while (
sub->option != 0xFF &&
563 if (
sub->option == 1 &&
sub->length == 4)
565 sw_if_index = ((
sub->data[0] << 24) |
566 (
sub->data[1] << 16) |
567 (
sub->data[2] << 8) |
570 else if (
sub->option == 5 &&
sub->length == 4)
577 else if (
sub->option == 151 &&
581 else if (
sub->option == 152 &&
sub->length == 0)
586 if (vss_ctrl && vss_exist)
589 DHCP_PROXY_ERROR_OPTION_82_VSS_NOT_PROCESSED, 1);
596 if (sw_if_index == (
u32)~0)
598 error0 = DHCP_PROXY_ERROR_NO_OPTION_82;
611 if (relay_addr.
as_u32 == 0)
613 error0 = DHCP_PROXY_ERROR_BAD_OPTION_82_ADDR;
619 error0 = DHCP_PROXY_ERROR_BAD_OPTION_82_ITF;
628 error0 = DHCP_PROXY_ERROR_NO_SERVER;
640 error0 = DHCP_PROXY_ERROR_BAD_SVR_FIB_OR_ADDRESS;
647 original_sw_if_index = sw_if_index;
654 error0 = DHCP_PROXY_ERROR_NO_INTERFACE_ADDRESS;
660 error0 = DHCP_PROXY_ERROR_BAD_YIADDR;
665 u0->
dst_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcp_to_client);
696 clib_net_to_host_u16(0x8100) : clib_net_to_host_u16 (0x0800);
700 u32 * vlan_tag = (
u32 *)(mac0+1);
702 tmp = (si0->
sub.
id << 16) | 0x0800;
703 *vlan_tag = clib_host_to_net_u32 (tmp);
730 .name =
"dhcp-proxy-to-client",
732 .vector_size =
sizeof (
u32),
739 .unformat_buffer = unformat_dhcp_proxy_header,
766 ip46_address_t *src_addr,
771 u32 rx_fib_index = 0;
777 .fp_addr.ip4.as_u32 = 0xffffffff,
782 return VNET_API_ERROR_INVALID_DST_ADDRESS;
785 return VNET_API_ERROR_INVALID_SRC_ADDRESS;
794 addr, server_table_id))
806 rx_fib_index, server_table_id))
825 ip46_address_t server_addr, src_addr;
826 u32 server_table_id = 0, rx_table_id = 0;
828 int set_src = 0, set_server = 0;
830 memset(&server_addr, 0,
sizeof(server_addr));
831 memset(&src_addr, 0,
sizeof(src_addr));
838 else if (
unformat (input,
"server-fib-id %d", &server_table_id))
840 else if (
unformat (input,
"rx-fib-id %d", &rx_table_id))
842 else if (
unformat(input,
"src-address %U",
845 else if (
unformat (input,
"delete") ||
852 if (is_del || (set_server && set_src))
857 server_table_id, is_del);
863 case VNET_API_ERROR_INVALID_DST_ADDRESS:
866 case VNET_API_ERROR_INVALID_SRC_ADDRESS:
869 case VNET_API_ERROR_NO_SUCH_ENTRY:
871 (0,
"Fib id %d: no per-fib DHCP server configured", rx_table_id);
883 .path =
"set dhcp proxy",
884 .short_help =
"set dhcp proxy [del] server <ip-addr> src-address <ip-addr> [server-fib-id <n>] [rx-fib-id <n>]",
897 s =
format (s,
"%=14s%=16s%s",
"RX FIB",
"Src Address",
898 "Servers FIB,Address");
904 s =
format (s,
"%=14u%=16U",
942 .path =
"show dhcp proxy",
943 .short_help =
"Display dhcp proxy server info",
952 int is_del = 0, got_new_vpn_id=0;
953 u32 oui=0, fib_id=0, tbl_id=~0;
960 else if (
unformat (input,
"oui %d", &oui))
962 else if (
unformat (input,
"vpn-id %d", &fib_id))
964 else if (
unformat (input,
"table %d", &tbl_id))
972 if (is_del || got_new_vpn_id)
981 case VNET_API_ERROR_NO_SUCH_FIB:
982 return clib_error_return (0,
"option 82 vss(oui:%d, vpn-id:%d) not found in table %d",
983 oui, fib_id, tbl_id);
985 case VNET_API_ERROR_NO_SUCH_ENTRY:
998 .path =
"set dhcp option-82 vss",
999 .short_help =
"set dhcp option-82 vss [del] table <table id> oui <oui> vpn-id <vpn-id>",
1015 .path =
"show dhcp vss",
1016 .short_help =
"show dhcp VSS",
1027 u32 sw_if_index0=0, sw_if_index;
1044 "source IP address");
1053 "No IPv4 address configured on",
1065 .path =
"show dhcp option-82-address interface",
1066 .short_help =
"show dhcp option-82-address interface <interface>",
static vlib_node_registration_t dhcp_proxy_to_client_node
(constructor) VLIB_REGISTER_NODE (dhcp_proxy_to_client_node)
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED
static dhcp_vss_t * dhcp_get_vss_info(dhcp_proxy_main_t *dm, u32 rx_fib_index, fib_protocol_t proto)
Get the VSS data for the FIB index.
vnet_main_t * vnet_get_main(void)
static vnet_hw_interface_t * vnet_get_sup_hw_interface(vnet_main_t *vnm, u32 sw_if_index)
ethernet_main_t * ethernet_get_main(vlib_main_t *vm)
void dhcp_vss_walk(fib_protocol_t proto, dhcp_vss_walk_fn_t fn, void *ctx)
Walk/Visit each DHCP proxy VSS.
dhcp_server_t * dhcp_servers
The set of DHCP servers to which messages are relayed.
static uword dhcp_proxy_to_client_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
void dhcp_proxy_walk(fib_protocol_t proto, dhcp_proxy_walk_fn_t fn, void *ctx)
Walk/Visit each DHCP proxy server.
static clib_error_t * dhcp4_proxy_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define VPP_DHCP_OPTION82_SIZE
ip4_address_t * ip4_interface_first_address(ip4_main_t *im, u32 sw_if_index, ip_interface_address_t **result_ia)
dhcp_proxy_main_t dhcp_proxy_main
Shard 4/6 instance of DHCP main.
int dhcp_vss_show_walk(dhcp_vss_t *vss, u32 rx_table_id, void *ctx)
Show (on CLI) a VSS config during a show walk.
static uword dhcp_proxy_to_server_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
ip46_address_t dhcp_src_address
The source address to use in relayed messaes.
The Virtual Sub-net Selection information for a given RX FIB.
int dhcp_client_for_us(u32 bi, vlib_buffer_t *b, ip4_header_t *ip, udp_header_t *udp, dhcp_header_t *dhcp)
struct _vlib_node_registration vlib_node_registration_t
u32 rx_fib_index
The FIB index (not the external Table-ID) in which the client is resides.
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u32 * fib_index_by_sw_if_index
Table index indexed by software interface.
unformat_function_t unformat_vnet_sw_interface
u32 error_drop_node_index
u32 oui
?? RFC doesn't say
format_function_t format_vnet_sw_if_index_name
static vlib_buffer_t * vlib_buffer_copy(vlib_main_t *vm, vlib_buffer_t *b)
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
#define VLIB_INIT_FUNCTION(x)
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a 'special' entry from the FIB.
static vlib_node_registration_t dhcp_proxy_to_server_node
(constructor) VLIB_REGISTER_NODE (dhcp_proxy_to_server_node)
Aggregrate type for a prefix.
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
static clib_error_t * dhcp4_proxy_set_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static dhcp_proxy_t * dhcp_get_proxy(dhcp_proxy_main_t *dm, u32 rx_fib_index, fib_protocol_t proto)
Get the DHCP proxy server data for the FIB index.
#define clib_error_return(e, args...)
int dhcp_proxy_server_add(fib_protocol_t proto, ip46_address_t *addr, ip46_address_t *src_address, u32 rx_fib_index, u32 server_table_id)
Add a new DHCP proxy server configuration.
u16 fp_len
The mask length.
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
u32 server_fib_index
The FIB index (not the external Table-ID) in which the server is reachable.
static u8 * format_dhcp4_proxy_server(u8 *s, va_list *args)
Collection of global DHCP proxy data.
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
u16 current_length
Nbytes between current data and the end of this buffer.
dhcp_proxy_to_server_input_next_t
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
static char * dhcp_proxy_error_strings[]
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
void fib_table_unlock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Take a reference counting lock on the table.
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
static clib_error_t * dhcp4_proxy_init(vlib_main_t *vm)
fib_node_index_t fib_table_entry_special_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags)
Add a 'special' entry to the FIB.
static u32 vlib_buffer_get_free_list_index(vlib_buffer_t *b)
static clib_error_t * dhcp_option_82_address_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static ip4_fib_t * ip4_fib_get(u32 index)
Get the FIB at the given index.
#define VLIB_BUFFER_IS_TRACED
#define clib_memcpy(a, b, c)
A representation of a single DHCP Server within a given VRF config.
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
void fib_table_lock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Release a reference counting lock on the table.
u32 unnumbered_sw_if_index
#define VLIB_CLI_COMMAND(x,...)
int dhcp4_proxy_set_server(ip46_address_t *addr, ip46_address_t *src_addr, u32 rx_table_id, u32 server_table_id, int is_del)
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
ip46_address_t dhcp_server
The address of the DHCP server to which to relay the client's messages.
static u8 * format_dhcp_proxy_trace(u8 *s, va_list *args)
#define foreach_dhcp_proxy_to_server_input_next
static clib_error_t * dhcp_option_82_vss_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u32 fib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id, fib_source_t src)
Get the index of the FIB for a Table-ID.
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
static clib_error_t * dhcp_vss_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
ip4_address_t trace_ip4_address
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
int dhcp_proxy_set_vss(fib_protocol_t proto, u32 tbl_id, u32 oui, u32 fib_id, int is_del)
Configure/set a new VSS info.
A DHCP proxy represenation fpr per-client VRF config.
int dhcp_proxy_server_del(fib_protocol_t proto, u32 rx_fib_index, ip46_address_t *addr, u32 server_table_id)
Delete a DHCP proxy config.
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
#define ip_csum_update(sum, old, new, type, field)
static u8 * format_dhcp_proxy_header_with_length(u8 *s, va_list *args)
#define VLIB_REGISTER_NODE(x,...)
vnet_sw_interface_type_t type
ip4_main_t ip4_main
Global ip4 main structure.
#define vec_foreach(var, vec)
Vector iterator.
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
static vlib_buffer_free_list_t * vlib_buffer_get_free_list(vlib_main_t *vm, u32 free_list_index)
ethernet_interface_t * interfaces
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
#define ip46_address_is_zero(ip46)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
static int dhcp4_proxy_show_walk(dhcp_proxy_t *server, void *ctx)
static u16 ip_csum_fold(ip_csum_t c)