23 #define dhcp_proxy_error(n,s) s, 25 #undef dhcp_proxy_error 28 #define foreach_dhcp_proxy_to_server_input_next \ 29 _ (DROP, "error-drop") \ 30 _ (LOOKUP, "ip4-lookup") \ 31 _ (SEND_TO_CLIENT, "dhcp-proxy-to-client") 34 #define _(s,n) DHCP_PROXY_TO_SERVER_INPUT_NEXT_##s, 49 #define VPP_DHCP_OPTION82_SUB1_SIZE 6 50 #define VPP_DHCP_OPTION82_SUB5_SIZE 6 51 #define VPP_DHCP_OPTION82_VSS_SIZE 12 52 #define VPP_DHCP_OPTION82_SIZE (VPP_DHCP_OPTION82_SUB1_SIZE + \ 53 VPP_DHCP_OPTION82_SUB5_SIZE + \ 54 VPP_DHCP_OPTION82_VSS_SIZE +3) 66 s =
format (s,
"DHCP proxy: sent to server %U\n",
69 s =
format (s,
"DHCP proxy: broadcast to client from %U\n",
75 s =
format (s,
" original_sw_if_index: %d, sw_if_index: %d\n",
84 u32 max_header_bytes = va_arg (*args,
u32);
87 header_bytes =
sizeof (h[0]);
88 if (max_header_bytes != 0 && header_bytes > max_header_bytes)
89 return format (s,
"dhcp header truncated");
91 s =
format (s,
"DHCP Proxy");
101 u32 n_left_from, next_index, * from, * to_next;
105 u32 pkts_to_server=0, pkts_to_client=0, pkts_no_server=0;
106 u32 pkts_no_interface_address=0;
112 while (n_left_from > 0)
117 to_next, n_left_to_next);
119 while (n_left_from > 0 && n_left_to_next > 0)
131 u32 original_sw_if_index = 0;
133 u32 fib_index, server_index;
156 if (u0->
src_port == clib_net_to_host_u16(UDP_DST_PORT_dhcp_to_server))
159 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;
185 if (server->
valid == 0)
220 u32 fib_index, fib_id, opt82_fib_id=0, opt82_oui=0;
233 while (o->
option != 0xFF && (
u8 *)o < end)
240 next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP;
245 if ((o->option == 0xFF) && ((
u8 *)o <= end))
254 original_sw_if_index = 0;
256 original_sw_if_index = sw_if_index =
279 error0 = DHCP_PROXY_ERROR_NO_INTERFACE_ADDRESS;
280 next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_DROP;
281 pkts_no_interface_address++;
290 o->data[2] = (original_sw_if_index >> 24) & 0xFF;
291 o->data[3] = (original_sw_if_index >> 16) & 0xFF;
292 o->data[4] = (original_sw_if_index >> 8) & 0xFF;
293 o->data[5] = (original_sw_if_index >> 0) & 0xFF;
296 o->data[8] = ia0->
as_u8[0];
297 o->data[9] = ia0->
as_u8[1];
298 o->data[10] = ia0->
as_u8[2];
299 o->data[11] = ia0->
as_u8[3];
301 if (opt82_oui !=0 || opt82_fib_id != 0)
304 if (255 == opt82_fib_id) {
315 o->data[15] = (opt82_oui >> 16) & 0xff;
316 o->data[16] = (opt82_oui >> 8) & 0xff;
317 o->data[17] = (opt82_oui ) & 0xff;
318 o->data[18] = (opt82_fib_id >> 24) & 0xff;
319 o->data[19] = (opt82_fib_id >> 16) & 0xff;
320 o->data[20] = (opt82_fib_id >> 8) & 0xff;
321 o->data[21] = (opt82_fib_id) & 0xff;
335 new_l0 = clib_net_to_host_u16 (old_l0);
337 new_l0 = clib_host_to_net_u16 (new_l0);
345 new_l0 = clib_net_to_host_u16 (u0->
length);
347 u0->
length = clib_host_to_net_u16 (new_l0);
351 DHCP_PROXY_ERROR_OPTION_82_ERROR, 1);
355 next0 = DHCP_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP;
366 if (next0 == DHCP_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP)
372 to_next, n_left_to_next,
380 DHCP_PROXY_ERROR_RELAY_TO_CLIENT,
383 DHCP_PROXY_ERROR_RELAY_TO_SERVER,
386 DHCP_PROXY_ERROR_NO_SERVER,
389 DHCP_PROXY_ERROR_NO_INTERFACE_ADDRESS,
390 pkts_no_interface_address);
392 DHCP_PROXY_ERROR_PKT_TOO_BIG,
399 .name =
"dhcp-proxy-to-server",
401 .vector_size =
sizeof (
u32),
403 .n_errors = DHCP_PROXY_N_ERROR,
408 #define _(s,n) [DHCP_PROXY_TO_SERVER_INPUT_NEXT_##s] = n, 416 .unformat_buffer = unformat_dhcp_proxy_header,
425 u32 n_left_from, * from;
434 while (n_left_from > 0)
449 u32 sw_if_index = ~0;
456 u32 original_sw_if_index = (
u32) ~0;
488 while (o->
option != 0xFF &&
496 while (
sub->option != 0xFF &&
501 if (
sub->option == 1 &&
sub->length == 4)
503 sw_if_index = (o->
data[2] << 24)
507 }
else if (
sub->option == 151 &&
511 else if (
sub->option == 152 &&
sub->length == 0)
516 if (vss_ctrl && vss_exist)
519 DHCP_PROXY_ERROR_OPTION_82_VSS_NOT_PROCESSED, 1);
526 if (sw_if_index == (
u32)~0)
528 error0 = DHCP_PROXY_ERROR_NO_OPTION_82;
544 error0 = DHCP_PROXY_ERROR_BAD_OPTION_82;
558 error0 = DHCP_PROXY_ERROR_BAD_OPTION_82;
563 if (server->
valid == 0)
565 error0 = DHCP_PROXY_ERROR_NO_SERVER;
571 error0 = DHCP_PROXY_ERROR_BAD_SVR_FIB_OR_ADDRESS;
578 original_sw_if_index = sw_if_index;
585 error0 = DHCP_PROXY_ERROR_NO_INTERFACE_ADDRESS;
590 u0->
dst_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcp_to_client);
621 clib_net_to_host_u16(0x8100) : clib_net_to_host_u16 (0x0800);
625 u32 * vlan_tag = (
u32 *)(mac0+1);
627 tmp = (si0->
sub.
id << 16) | 0x0800;
628 *vlan_tag = clib_host_to_net_u32 (tmp);
655 .name =
"dhcp-proxy-to-client",
657 .vector_size =
sizeof (
u32),
659 .n_errors = DHCP_PROXY_N_ERROR,
664 .unformat_buffer = unformat_dhcp_proxy_header,
689 memset (server, 0,
sizeof (*server));
699 int insert_option_82,
int is_del)
705 u32 server_index = 0;
706 u32 rx_fib_index = 0;
709 return VNET_API_ERROR_INVALID_DST_ADDRESS;
711 if (src_address->
as_u32 == 0)
712 return VNET_API_ERROR_INVALID_SRC_ADDRESS;
718 return VNET_API_ERROR_NO_SUCH_INNER_FIB;
724 return VNET_API_ERROR_NO_SUCH_FIB;
732 memset (server, 0,
sizeof (*server));
738 rx_fib_index = rx_fib - im->
fibs;
743 return VNET_API_ERROR_NO_SUCH_ENTRY;
751 memset (server, 0,
sizeof (*server));
759 if (server_index != 0)
787 u32 fib_id,
int insert_option_82,
int is_del)
791 insert_option_82, is_del);
801 u32 server_fib_id = 0, rx_fib_id = 0;
803 int add_option_82 = 0;
804 int set_src = 0, set_server = 0;
811 else if (
unformat (input,
"server-fib-id %d", &server_fib_id))
813 else if (
unformat (input,
"rx-fib-id %d", &rx_fib_id))
815 else if (
unformat(input,
"src-address %U",
818 else if (
unformat (input,
"add-option-82")
819 ||
unformat (input,
"insert-option-82"))
821 else if (
unformat (input,
"delete") ||
828 if (is_del || (set_server && set_src))
833 server_fib_id, add_option_82, is_del);
839 case VNET_API_ERROR_INVALID_DST_ADDRESS:
842 case VNET_API_ERROR_INVALID_SRC_ADDRESS:
845 case VNET_API_ERROR_NO_SUCH_INNER_FIB:
848 case VNET_API_ERROR_NO_SUCH_FIB:
852 case VNET_API_ERROR_NO_SUCH_ENTRY:
854 (0,
"Fib id %d: no per-fib DHCP server configured", rx_fib_id);
866 .path =
"set dhcp proxy",
867 .short_help =
"set dhcp proxy [del] server <ip-addr> src-address <ip-addr> [add-option-82] [server-fib-id <n>] [rx-fib-id <n>]",
875 u32 rx_fib_index = va_arg (*args,
u32);
877 u32 server_fib_id = ~0, rx_fib_id = ~0;
881 s =
format (s,
"%=16s%=16s%=14s%=14s%=20s",
"Server",
"Src Address",
882 "Server FIB",
"RX FIB",
"Insert Option 82");
890 server_fib_id = server_fib->
table_id;
898 s =
format (s,
"%=16U%=16U%=14u%=14u%=20s",
901 server_fib_id, rx_fib_id,
936 .path =
"show dhcp proxy",
937 .short_help =
"Display dhcp proxy server info",
950 u32 old_oui=0, old_fib_id=0;
958 return VNET_API_ERROR_NO_SUCH_FIB;
964 if (old_oui == oui &&
965 old_fib_id == fib_id)
972 return VNET_API_ERROR_NO_SUCH_ENTRY;
977 return VNET_API_ERROR_NO_SUCH_ENTRY;
979 memset (a, ~0,
sizeof (a[0]));
992 int is_del = 0, got_new_vpn_id=0;
993 u32 oui=0, fib_id=0, tbl_id=~0;
1001 else if (
unformat (input,
"oui %d", &oui))
1003 else if (
unformat (input,
"vpn-id %d", &fib_id))
1005 else if (
unformat (input,
"table %d", &tbl_id))
1013 if (is_del || got_new_vpn_id)
1022 case VNET_API_ERROR_NO_SUCH_FIB:
1023 return clib_error_return (0,
"option 82 vss(oui:%d, vpn-id:%d) not found in table %d",
1024 oui, fib_id, tbl_id);
1026 case VNET_API_ERROR_NO_SUCH_ENTRY:
1027 return clib_error_return (0,
"option 82 vss for table %d not found in in pool.",
1039 .path =
"set dhcp option-82 vss",
1040 .short_help =
"set dhcp option-82 vss [del] table <table id> oui <oui> vpn-id <vpn-id>",
1061 v = pool_elt_at_index (dm->opt82vss, index);
1062 oui = v->vpn_id.oui;
1063 fib_id = v->vpn_id.fib_id;
1064 vlib_cli_output (vm,
"%=9d 0x%08x%=12d",
1065 tbl_id, oui, fib_id);
1072 .path =
"show dhcp vss",
1073 .short_help =
"show dhcp VSS",
1085 u32 sw_if_index0=0, sw_if_index;
1102 "source IP address");
1111 "No IPv4 address configured on",
1123 .path =
"show dhcp option-82-address interface",
1124 .short_help =
"show dhcp option-82-address interface <interface>",
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
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.
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED
ip4_fib_t * find_ip4_fib_by_table_index_or_id(ip4_main_t *im, u32 table_index_or_id, u32 flags)
Get or create an IPv4 fib.
#define hash_set(h, key, value)
sll srl srl sll sra u16x4 i
#define hash_unset(h, key)
static clib_error_t * dhcp_option_82_vss_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
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)
static clib_error_t * dhcp_proxy_set_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u32 free_list_index
Buffer free list that this buffer was allocated from and will be freed to.
ip4_address_t * ip4_interface_first_address(ip4_main_t *im, u32 sw_if_index, ip_interface_address_t **result_ia)
u8 * format_dhcp_proxy_header_with_length(u8 *s, va_list *args)
struct _vlib_node_registration vlib_node_registration_t
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
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
format_function_t format_vnet_sw_if_index_name
clib_error_t * dhcp_proxy_init(vlib_main_t *vm)
vnet_main_t * vnet_get_main(void)
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
static uword dhcp_proxy_to_client_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
#define VLIB_INIT_FUNCTION(x)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
#define VPP_DHCP_OPTION82_SIZE
uword * opt82vss_index_by_vrf_id
#define hash_foreach(key_var, value_var, h, body)
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define foreach_dhcp_proxy_to_server_input_next
u32 * dhcp_server_index_by_rx_fib_index
int dhcp_proxy_set_server(ip4_address_t *addr, ip4_address_t *src_address, u32 fib_id, int insert_option_82, int is_del)
#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.
ip4_address_t dhcp_src_address
#define pool_put(P, E)
Free an object E in pool P.
static uword dhcp_proxy_to_server_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
#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 vlib_cli_output(vlib_main_t *vm, char *fmt,...)
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 void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
dhcp_server_t * dhcp_servers
int dhcp_proxy_set_option82_vss(u32 vrf_id, u32 oui, u32 fib_id, int is_del)
u8 * format_dhcp_proxy_server(u8 *s, va_list *args)
#define clib_memcpy(a, b, c)
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
static char * dhcp_proxy_error_strings[]
u32 unnumbered_sw_if_index
vlib_node_registration_t dhcp_proxy_to_server_node
(constructor) VLIB_REGISTER_NODE (dhcp_proxy_to_server_node)
#define hash_create(elts, value_bytes)
ip4_address_t dhcp_server
ip4_fib_t * fibs
Vector of FIBs.
u8 * format_dhcp_proxy_trace(u8 *s, va_list *args)
#define VLIB_BUFFER_IS_TRACED
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)
dhcp_proxy_main_t dhcp_proxy_main
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
int dhcp_proxy_set_server_2(ip4_address_t *addr, ip4_address_t *src_address, u32 rx_fib_id, u32 server_fib_id, int insert_option_82, int is_del)
#define IP4_ROUTE_FLAG_FIB_INDEX
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)
#define VLIB_REGISTER_NODE(x,...)
vnet_sw_interface_type_t type
ip4_main_t ip4_main
Global ip4 main structure.
#define IP4_ROUTE_FLAG_TABLE_ID
static clib_error_t * dhcp_proxy_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
#define clib_error_return(e, args...)
int dhcp_client_for_us(u32 bi, vlib_buffer_t *b, ip4_header_t *ip, udp_header_t *udp, dhcp_header_t *dhcp)
static vlib_buffer_free_list_t * vlib_buffer_get_free_list(vlib_main_t *vm, u32 free_list_index)
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
ethernet_interface_t * interfaces
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
dhcp_proxy_to_server_input_next_t
static u16 ip_csum_fold(ip_csum_t c)
vlib_node_registration_t dhcp_proxy_to_client_node
(constructor) VLIB_REGISTER_NODE (dhcp_proxy_to_client_node)