24 #define dhcpv6_proxy_error(n,s) s, 26 #undef dhcpv6_proxy_error 29 #define foreach_dhcpv6_proxy_to_server_input_next \ 30 _ (DROP, "error-drop") \ 31 _ (LOOKUP, "ip6-lookup") \ 32 _ (SEND_TO_CLIENT, "dhcpv6-proxy-to-client") 36 #define _(s,n) DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_##s, 62 s =
format (s,
"DHCPV6 proxy: sent to server %U",
65 s =
format (s,
"DHCPV6 proxy: sent to client from %U",
70 s =
format (s,
" original_sw_if_index: %d, sw_if_index: %d\n",
79 u32 max_header_bytes = va_arg (*args,
u32);
82 header_bytes =
sizeof (h[0]);
83 if (max_header_bytes != 0 && header_bytes > max_header_bytes)
84 return format (s,
"dhcpv6 header truncated");
86 s =
format (s,
"DHCPV6 Proxy");
102 if ((a->
as_u8[0] & 0xe0) == 0x20 ||
103 (a->
as_u8[0] & 0xfe) == 0xfc) {
141 u32 n_left_from, next_index, * from, * to_next;
145 u32 pkts_to_server=0, pkts_to_client=0, pkts_no_server=0;
146 u32 pkts_no_interface_address=0, pkts_no_exceeding_max_hop=0;
147 u32 pkts_no_src_address=0;
148 u32 pkts_wrong_msg_type=0;
155 u32 rx_fib_idx = 0, server_fib_idx = 0;
161 while (n_left_from > 0)
166 to_next, n_left_to_next);
168 while (n_left_from > 0 && n_left_to_next > 0)
172 u32 rx_sw_if_index = 0;
182 dhcpv6_option_t *fwd_opt;
183 dhcpv6_relay_hdr_t *r1;
185 dhcpv6_int_id_t *id1;
187 dhcpv6_client_mac_t *cmac;
189 u8 client_src_mac[6];
211 u0 = (
void *)h0 -(
sizeof(*u0));
212 ip0 = (
void *)u0 -(
sizeof(*ip0));
231 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_SEND_TO_CLIENT;
237 pkts_wrong_msg_type++;
238 error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
239 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
257 error0 = DHCPV6_PROXY_ERROR_NO_SERVER;
258 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
264 if (server->
valid == 0)
289 fwd_opt->length = clib_host_to_net_u16(len);
298 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
299 pkts_no_exceeding_max_hop++;
310 r1->link_addr.as_u64[0] = 0;
311 r1->link_addr.as_u64[1] = 0;
312 goto link_address_set;
327 error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
328 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
329 pkts_no_interface_address++;
341 error0 = DHCPV6_PROXY_ERROR_PKT_TOO_BIG;
342 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
364 id1->opt.length = clib_host_to_net_u16(
sizeof(rx_sw_if_index));
365 id1->int_idx = clib_host_to_net_u32(rx_sw_if_index);
372 cmac->opt.length =clib_host_to_net_u16(
sizeof(*cmac) -
375 cmac->link_type = clib_host_to_net_u16(1);
377 u1->
length +=
sizeof(*cmac);
382 vss1->opt.length =clib_host_to_net_u16(
sizeof(*vss1) -
386 vss1->data[1] = oui1>>16 & 0xff;
387 vss1->data[2] = oui1>>8 & 0xff;
388 vss1->data[3] = oui1 & 0xff;
389 vss1->data[4] = fib_id1>>24 & 0xff;
390 vss1->data[5] = fib_id1>>16 & 0xff;
391 vss1->data[6] = fib_id1>>8 & 0xff;
392 vss1->data[7] = fib_id1 & 0xff;
393 u1->
length +=
sizeof(*vss1);
398 u1->
src_port = clib_host_to_net_u16(UDP_DST_PORT_dhcpv6_to_client);
399 u1->
dst_port = clib_host_to_net_u16(UDP_DST_PORT_dhcpv6_to_server);
402 clib_host_to_net_u16( clib_net_to_host_u16(fwd_opt->length) +
403 sizeof(*r1) +
sizeof(*fwd_opt) +
404 sizeof(*u1) +
sizeof(*id1) + u1->
length);
406 memset(ip1, 0,
sizeof(*ip1));
407 ip1->ip_version_traffic_class_and_flow_label = 0x60;
408 ip1->payload_length = u1->
length;
423 error0 = DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS;
424 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
425 pkts_no_src_address++;
434 ASSERT(bogus_length == 0);
436 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP;
447 if (DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP == next0)
453 to_next, n_left_to_next,
461 DHCPV6_PROXY_ERROR_RELAY_TO_CLIENT,
464 DHCPV6_PROXY_ERROR_RELAY_TO_SERVER,
467 DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS,
468 pkts_no_interface_address);
470 DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE,
471 pkts_wrong_msg_type);
473 DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS,
474 pkts_no_src_address);
476 DHCPV6_PROXY_ERROR_PKT_TOO_BIG,
483 .name =
"dhcpv6-proxy-to-server",
485 .vector_size =
sizeof (
u32),
487 .n_errors = DHCPV6_PROXY_N_ERROR,
492 #define _(s,n) [DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_##s] = n, 500 .unformat_buffer = unformat_dhcpv6_proxy_header,
510 u32 n_left_from, * from;
520 while (n_left_from > 0)
525 dhcpv6_relay_hdr_t * h0;
534 u32 sw_if_index = ~0;
535 u32 original_sw_if_index = ~0;
539 dhcpv6_option_t *r0 = 0, *o;
541 u8 interface_opt_flag = 0;
542 u8 relay_msg_opt_flag = 0;
545 u32 server_fib_idx, svr_fib_id, client_fib_idx, server_idx;
556 error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
570 if (HOP_COUNT_LIMIT < h0->hop_count)
575 u0 = (
void *)h0 -(
sizeof(*u0));
576 ip0 = (
void *)u0 -(
sizeof(*ip0));
591 interface_opt_flag = 1;
592 if (clib_net_to_host_u16(o->length) ==
sizeof(sw_if_index))
593 sw_if_index = clib_net_to_host_u32(((dhcpv6_int_id_t*)o)->int_idx);
596 error0 = DHCPV6_PROXY_ERROR_WRONG_INTERFACE_ID_OPTION;
602 relay_msg_opt_flag = 1;
605 if ((relay_msg_opt_flag == 1) && (interface_opt_flag == 1))
608 o = (dhcpv6_option_t *) (((
uword) o) + clib_net_to_host_u16(o->length) +
sizeof(*o));
611 if ((relay_msg_opt_flag == 0) || (r0 == 0))
613 error0 = DHCPV6_PROXY_ERROR_NO_RELAY_MESSAGE_OPTION;
617 if ((
u32)~0 == sw_if_index)
619 error0 = DHCPV6_PROXY_ERROR_NO_CIRCUIT_ID_OPTION;
634 error0 = DHCPV6_PROXY_ERROR_WRONG_INTERFACE_ID_OPTION;
639 if (server->
valid == 0)
641 error0 = DHCPV6_PROXY_ERROR_NO_SERVER;
656 error0 = DHCPV6_PROXY_ERROR_BAD_SVR_FIB_OR_ADDRESS;
683 error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
687 len = clib_net_to_host_u16(r0->length);
688 memset(ip1, 0,
sizeof(*ip1));
691 u1->
src_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_server);
692 u1->
dst_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_client);
696 ip0->ip_version_traffic_class_and_flow_label &
705 ASSERT(bogus_length == 0);
719 clib_net_to_host_u16(0x8100) : clib_net_to_host_u16 (0x86dd);
723 u32 * vlan_tag = (
u32 *)(mac0+1);
725 tmp = (si0->
sub.
id << 16) | 0x0800;
726 *vlan_tag = clib_host_to_net_u32 (tmp);
755 .name =
"dhcpv6-proxy-to-client",
757 .vector_size =
sizeof (
u32),
759 .n_errors = DHCPV6_PROXY_N_ERROR,
764 .unformat_buffer = unformat_dhcpv6_proxy_header,
797 memset (server, 0,
sizeof (*server));
806 u32 fib_id,
int insert_vss,
int is_del)
814 u32 rx_fib_id,
u32 server_fib_id,
815 int insert_vss,
int is_del)
819 u32 server_fib_index = 0;
820 u32 rx_fib_index = 0;
829 return VNET_API_ERROR_NO_SUCH_ENTRY;
835 memset (server, 0,
sizeof (*server));
840 if (addr->
as_u64[0] == 0 &&
842 return VNET_API_ERROR_INVALID_DST_ADDRESS;
844 if (src_address->
as_u64[0] == 0 &&
845 src_address->
as_u64[1] == 0)
846 return VNET_API_ERROR_INVALID_SRC_ADDRESS;
858 if (server_fib_index != 0)
889 int set_server = 0, set_src_address = 0;
890 u32 rx_fib_id = 0, server_fib_id = 0;
891 int is_del = 0, add_vss = 0;
898 else if (
unformat(input,
"src-address %U",
901 else if (
unformat (input,
"server-fib-id %d", &server_fib_id))
903 else if (
unformat (input,
"rx-fib-id %d", &rx_fib_id))
905 else if (
unformat (input,
"add-vss-option")
906 ||
unformat (input,
"insert-option"))
908 else if (
unformat (input,
"delete") ||
915 if (is_del || (set_server && set_src_address))
920 server_fib_id, add_vss, is_del);
941 .path =
"set dhcpv6 proxy",
942 .short_help =
"set dhcpv6 proxy [del] server <ipv6-addr> src-address <ipv6-addr> " 943 "[add-vss-option] [server-fib-id <fib-id>] [rx-fib-id <fib-id>] ",
951 u32 rx_fib_index = va_arg (*args,
u32);
953 u32 server_fib_id = (
u32)~0, rx_fib_id = ~0;
957 s =
format (s,
"%=40s%=40s%=14s%=14s%=20s",
"Server Address",
"Source Address",
958 "Server FIB",
"RX FIB",
"Insert VSS Option");
964 server_fib_id= server_fib->
table_id;
971 s =
format (s,
"%=40U%=40U%=14u%=14u%=20s",
974 server_fib_id, rx_fib_id,
1007 .path =
"show dhcpv6 proxy",
1008 .short_help =
"Display dhcpv6 proxy info",
1018 u32 old_oui, old_fib_id;
1027 return VNET_API_ERROR_NO_SUCH_FIB;
1034 if (old_oui == oui &&
1035 old_fib_id == fib_id )
1042 return VNET_API_ERROR_NO_SUCH_ENTRY;
1048 return VNET_API_ERROR_NO_SUCH_ENTRY;
1051 memset (v, ~0,
sizeof (*v));
1065 int is_del = 0, got_new_vss=0;
1067 u32 fib_id=0, tbl_id=~0;
1071 if (
unformat (input,
"oui %d", &oui))
1073 else if (
unformat (input,
"vpn-id %d", &fib_id))
1075 else if (
unformat (input,
"table %d", &tbl_id))
1086 if (is_del || got_new_vss)
1096 case VNET_API_ERROR_NO_SUCH_FIB:
1097 return clib_error_return (0,
"vss info (oui:%d, vpn-id:%d) not found in table %d.",
1098 oui, fib_id, tbl_id);
1100 case VNET_API_ERROR_NO_SUCH_ENTRY:
1115 .path =
"set dhcpv6 vss",
1116 .short_help =
"set dhcpv6 vss table <table-id> oui <oui> vpn-idx <vpn-idx>",
1136 v = pool_elt_at_index (dm->vss, index);
1137 oui = v->vpn_id.oui;
1138 fib_id = v->vpn_id.fib_id;
1139 vlib_cli_output (vm,
"%=6d%=6d%=12d",
1140 tbl_id, oui, fib_id);
1147 .path =
"show dhcpv6 vss",
1148 .short_help =
"show dhcpv6 VSS",
1160 u32 sw_if_index0=0, sw_if_index;
1192 .path =
"show dhcpv6 link-address interface",
1193 .short_help =
"show dhcpv6 link-address interface <interface>",
static clib_error_t * dhcpv6_vss_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#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 foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED
#define hash_set(h, key, value)
int dhcpv6_proxy_set_server(ip6_address_t *addr, ip6_address_t *src_address, u32 fib_id, int insert_vss, int is_del)
sll srl srl sll sra u16x4 i
dhcpv6_proxy_main_t dhcpv6_proxy_main
#define hash_unset(h, key)
static ip6_fib_t * ip6_fib_get(fib_node_index_t index)
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)
u32 free_list_index
Buffer free list that this buffer was allocated from and will be freed to.
#define ethernet_buffer_header_size(b)
Determine the size of the Ethernet headers of the current frame in the buffer.
struct _vlib_node_registration vlib_node_registration_t
ip6_address_t all_dhcpv6_server_relay_agent_address
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
unformat_function_t unformat_vnet_sw_interface
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
format_function_t format_vnet_sw_if_index_name
vnet_main_t * vnet_get_main(void)
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
#define VLIB_INIT_FUNCTION(x)
static ip6_address_t * ip6_interface_first_address(ip6_main_t *im, u32 sw_if_index)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
#define hash_foreach(key_var, value_var, h, body)
ip6_address_t dhcp6_server
dhcpv6_server_t * dhcp6_servers
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
static clib_error_t * dhcpv6_link_address_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
u16 current_length
Nbytes between current data and the end of this buffer.
vlib_node_registration_t dhcpv6_proxy_to_server_node
(constructor) VLIB_REGISTER_NODE (dhcpv6_proxy_to_server_node)
#define pool_put(P, E)
Free an object E in pool P.
uword * vss_index_by_vrf_id
int dhcpv6_proxy_set_vss(u32 tbl_id, u32 oui, u32 fib_id, int is_del)
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).
u8 * format_dhcpv6_proxy_server(u8 *s, va_list *args)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
static uword dhcpv6_proxy_to_server_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
u8 * format_dhcpv6_proxy_header_with_length(u8 *s, va_list *args)
static clib_error_t * dhcpv6_proxy_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
clib_error_t * dhcpv6_proxy_init(vlib_main_t *vm)
#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.
u32 unnumbered_sw_if_index
#define VLIB_CLI_COMMAND(x,...)
u16 ip6_tcp_udp_icmp_compute_checksum(vlib_main_t *vm, vlib_buffer_t *p0, ip6_header_t *ip0, int *bogus_lengthp)
#define hash_create(elts, value_bytes)
dhcpv6_proxy_to_server_input_next_t
ip_lookup_main_t lookup_main
static clib_error_t * dhcpv6_proxy_set_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
vlib_node_registration_t dhcpv6_proxy_to_client_node
(constructor) VLIB_REGISTER_NODE (dhcpv6_proxy_to_client_node)
u8 * format_dhcpv6_proxy_trace(u8 *s, va_list *args)
#define VLIB_BUFFER_IS_TRACED
static void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
u32 ip6_fib_table_find_or_create_and_lock(u32 table_id)
Get or create an IPv6 fib.
#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.
static void copy_ip6_address(ip6_address_t *dst, ip6_address_t *src)
ip6_address_t all_dhcpv6_server_address
#define foreach_dhcpv6_proxy_to_server_input_next
union dhcpv6_hdr_::@119 u
static char * dhcpv6_proxy_error_strings[]
#define VLIB_REGISTER_NODE(x,...)
vnet_sw_interface_type_t type
static clib_error_t * dhcpv6_vss_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
ip6_address_t dhcp6_src_address
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...)
static vlib_buffer_free_list_t * vlib_buffer_get_free_list(vlib_main_t *vm, u32 free_list_index)
static void * ip_interface_address_get_address(ip_lookup_main_t *lm, ip_interface_address_t *a)
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
ethernet_interface_t * interfaces
int dhcpv6_proxy_set_server_2(ip6_address_t *addr, ip6_address_t *src_address, u32 rx_fib_id, u32 server_fib_id, int insert_vss, int is_del)
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
struct fib_table_t_ * fibs
u32 * fib_index_by_sw_if_index
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
u32 * dhcp6_server_index_by_rx_fib_index
static ip6_address_t * ip6_interface_first_global_or_site_address(ip6_main_t *im, u32 sw_if_index)
u32 error_drop_node_index
static uword dhcpv6_proxy_to_client_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)