27 #define dhcpv6_proxy_error(n,s) s, 29 #undef dhcpv6_proxy_error 32 #define foreach_dhcpv6_proxy_to_server_input_next \ 33 _ (DROP, "error-drop") \ 34 _ (LOOKUP, "ip6-lookup") \ 35 _ (SEND_TO_CLIENT, "dhcpv6-proxy-to-client") 39 #define _(s,n) DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_##s, 69 s =
format (s,
"DHCPV6 proxy: sent to server %U",
72 s =
format (s,
"DHCPV6 proxy: sent to client from %U",
77 s =
format (s,
" original_sw_if_index: %d, sw_if_index: %d\n",
87 u32 max_header_bytes = va_arg (*args,
u32);
90 header_bytes =
sizeof (h[0]);
91 if (max_header_bytes != 0 && header_bytes > max_header_bytes)
92 return format (s,
"dhcpv6 header truncated");
94 s =
format (s,
"DHCPV6 Proxy");
110 if ((a->
as_u8[0] & 0xe0) == 0x20 ||
111 (a->
as_u8[0] & 0xfe) == 0xfc) {
131 u32 n_left_from, next_index, * from, * to_next;
135 u32 pkts_to_server=0, pkts_to_client=0, pkts_no_server=0;
136 u32 pkts_no_interface_address=0, pkts_no_exceeding_max_hop=0;
137 u32 pkts_no_src_address=0;
138 u32 pkts_wrong_msg_type=0;
145 u32 rx_fib_idx = 0, server_fib_idx = 0;
149 while (n_left_from > 0)
154 to_next, n_left_to_next);
156 while (n_left_from > 0 && n_left_to_next > 0)
160 u32 rx_sw_if_index = 0;
170 dhcpv6_option_t *fwd_opt;
171 dhcpv6_relay_hdr_t *r1;
173 dhcpv6_int_id_t *id1;
175 dhcpv6_client_mac_t *cmac;
177 u8 client_src_mac[6];
193 u0 = (
void *)h0 -(
sizeof(*u0));
194 ip0 = (
void *)u0 -(
sizeof(*ip0));
213 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_SEND_TO_CLIENT;
219 pkts_wrong_msg_type++;
220 error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
221 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
233 error0 = DHCPV6_PROXY_ERROR_NO_SERVER;
234 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
262 fwd_opt->length = clib_host_to_net_u16(len);
271 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
272 pkts_no_exceeding_max_hop++;
283 r1->link_addr.as_u64[0] = 0;
284 r1->link_addr.as_u64[1] = 0;
285 goto link_address_set;
300 error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
301 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
302 pkts_no_interface_address++;
314 error0 = DHCPV6_PROXY_ERROR_PKT_TOO_BIG;
315 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
324 id1->opt.length = clib_host_to_net_u16(
sizeof(rx_sw_if_index));
325 id1->int_idx = clib_host_to_net_u32(rx_sw_if_index);
332 cmac->opt.length =clib_host_to_net_u16(
sizeof(*cmac) -
335 cmac->link_type = clib_host_to_net_u16(1);
337 u1->
length +=
sizeof(*cmac);
345 vss1->opt.length =clib_host_to_net_u16(
sizeof(*vss1) -
349 vss1->data[1] = vss->
oui >>16 & 0xff;
350 vss1->data[2] = vss->
oui >>8 & 0xff;
351 vss1->data[3] = vss->
oui & 0xff;
352 vss1->data[4] = vss->
fib_id >> 24 & 0xff;
353 vss1->data[5] = vss->
fib_id >> 16 & 0xff;
354 vss1->data[6] = vss->
fib_id >> 8 & 0xff;
355 vss1->data[7] = vss->
fib_id & 0xff;
356 u1->
length +=
sizeof(*vss1);
361 u1->
src_port = clib_host_to_net_u16(UDP_DST_PORT_dhcpv6_to_client);
362 u1->
dst_port = clib_host_to_net_u16(UDP_DST_PORT_dhcpv6_to_server);
365 clib_host_to_net_u16( clib_net_to_host_u16(fwd_opt->length) +
366 sizeof(*r1) +
sizeof(*fwd_opt) +
367 sizeof(*u1) +
sizeof(*id1) + u1->
length);
369 memset(ip1, 0,
sizeof(*ip1));
370 ip1->ip_version_traffic_class_and_flow_label = 0x60;
371 ip1->payload_length = u1->
length;
377 &all_dhcpv6_server_address);
389 error0 = DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS;
390 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
391 pkts_no_src_address++;
400 ASSERT(bogus_length == 0);
402 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP;
429 &all_dhcpv6_server_address);
437 to_next, n_left_to_next,
449 if (next0 == DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP)
459 to_next, n_left_to_next);
473 if (DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP == next0)
483 to_next, n_left_to_next,
491 DHCPV6_PROXY_ERROR_RELAY_TO_CLIENT,
494 DHCPV6_PROXY_ERROR_RELAY_TO_SERVER,
497 DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS,
498 pkts_no_interface_address);
500 DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE,
501 pkts_wrong_msg_type);
503 DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS,
504 pkts_no_src_address);
506 DHCPV6_PROXY_ERROR_PKT_TOO_BIG,
513 .name =
"dhcpv6-proxy-to-server",
515 .vector_size =
sizeof (
u32),
522 #define _(s,n) [DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_##s] = n, 530 .unformat_buffer = unformat_dhcpv6_proxy_header,
540 u32 n_left_from, * from;
551 while (n_left_from > 0)
556 dhcpv6_relay_hdr_t * h0;
565 u32 sw_if_index = ~0;
566 u32 original_sw_if_index = ~0;
570 dhcpv6_option_t *r0 = 0, *o;
572 u8 interface_opt_flag = 0;
573 u8 relay_msg_opt_flag = 0;
575 u32 server_fib_idx, client_fib_idx;
586 error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
600 if (HOP_COUNT_LIMIT < h0->hop_count)
605 u0 = (
void *)h0 -(
sizeof(*u0));
606 ip0 = (
void *)u0 -(
sizeof(*ip0));
621 interface_opt_flag = 1;
622 if (clib_net_to_host_u16(o->length) ==
sizeof(sw_if_index))
623 sw_if_index = clib_net_to_host_u32(((dhcpv6_int_id_t*)o)->int_idx);
626 error0 = DHCPV6_PROXY_ERROR_WRONG_INTERFACE_ID_OPTION;
632 relay_msg_opt_flag = 1;
635 if ((relay_msg_opt_flag == 1) && (interface_opt_flag == 1))
638 o = (dhcpv6_option_t *) (((
uword) o) + clib_net_to_host_u16(o->length) +
sizeof(*o));
641 if ((relay_msg_opt_flag == 0) || (r0 == 0))
643 error0 = DHCPV6_PROXY_ERROR_NO_RELAY_MESSAGE_OPTION;
647 if ((
u32)~0 == sw_if_index)
649 error0 = DHCPV6_PROXY_ERROR_NO_CIRCUIT_ID_OPTION;
661 error0 = DHCPV6_PROXY_ERROR_NO_SERVER;
671 ip0->src_address.as_u64[0] == server->
dhcp_server.ip6.as_u64[0] &&
672 ip0->src_address.as_u64[1] == server->
dhcp_server.ip6.as_u64[1])
679 error0 = DHCPV6_PROXY_ERROR_BAD_SVR_FIB_OR_ADDRESS;
706 error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
710 len = clib_net_to_host_u16(r0->length);
711 memset(ip1, 0,
sizeof(*ip1));
714 u1->
src_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_server);
715 u1->
dst_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_client);
719 ip0->ip_version_traffic_class_and_flow_label &
728 ASSERT(bogus_length == 0);
742 clib_net_to_host_u16(0x8100) : clib_net_to_host_u16 (0x86dd);
746 u32 * vlan_tag = (
u32 *)(mac0+1);
748 tmp = (si0->
sub.
id << 16) | 0x0800;
749 *vlan_tag = clib_host_to_net_u32 (tmp);
778 .name =
"dhcpv6-proxy-to-client",
780 .vector_size =
sizeof (
u32),
787 .unformat_buffer = unformat_dhcpv6_proxy_header,
801 all_dhcpv6_server_address.
as_u64[0] = clib_host_to_net_u64 (0xFF05000000000000);
802 all_dhcpv6_server_address.
as_u64[1] = clib_host_to_net_u64 (0x00010003);
805 all_dhcpv6_server_relay_agent_address.
as_u64[0] = clib_host_to_net_u64 (0xFF02000000000000);
806 all_dhcpv6_server_relay_agent_address.
as_u64[1] = clib_host_to_net_u64 (0x00010002);
821 ip46_address_t *src_addr,
826 u32 rx_fib_index = 0;
838 return VNET_API_ERROR_INVALID_DST_ADDRESS;
841 return VNET_API_ERROR_INVALID_SRC_ADDRESS;
849 addr, server_table_id))
862 .frp_sw_if_index = 0xffffffff,
868 rx_fib_index, server_table_id))
902 ip46_address_t
addr, src_addr;
903 int set_server = 0, set_src_address = 0;
904 u32 rx_table_id = 0, server_table_id = 0;
912 else if (
unformat(input,
"src-address %U",
915 else if (
unformat (input,
"server-fib-id %d", &server_table_id))
917 else if (
unformat (input,
"rx-fib-id %d", &rx_table_id))
919 else if (
unformat (input,
"delete") ||
926 if (is_del || (set_server && set_src_address))
931 server_table_id, is_del);
939 case VNET_API_ERROR_INVALID_DST_ADDRESS:
942 case VNET_API_ERROR_INVALID_SRC_ADDRESS:
945 case VNET_API_ERROR_NO_SUCH_ENTRY:
947 (0,
"Fib id %d: no per-fib DHCP server configured", rx_table_id);
959 .path =
"set dhcpv6 proxy",
960 .short_help =
"set dhcpv6 proxy [del] server <ipv6-addr> src-address <ipv6-addr> " 961 "[server-fib-id <fib-id>] [rx-fib-id <fib-id>] ",
975 s =
format (s,
"%=14s%=16s%s",
"RX FIB",
"Src Address",
976 "Servers FIB,Address");
982 s =
format (s,
"%=14u%=16U",
1022 .path =
"show dhcpv6 proxy",
1023 .short_help =
"Display dhcpv6 proxy info",
1032 int is_del = 0, got_new_vss=0;
1034 u32 fib_id=0, tbl_id=~0;
1038 if (
unformat (input,
"oui %d", &oui))
1040 else if (
unformat (input,
"vpn-id %d", &fib_id))
1042 else if (
unformat (input,
"table %d", &tbl_id))
1053 if (is_del || got_new_vss)
1063 case VNET_API_ERROR_NO_SUCH_FIB:
1064 return clib_error_return (0,
"vss info (oui:%d, vpn-id:%d) not found in table %d.",
1065 oui, fib_id, tbl_id);
1067 case VNET_API_ERROR_NO_SUCH_ENTRY:
1082 .path =
"set dhcpv6 vss",
1083 .short_help =
"set dhcpv6 vss table <table-id> oui <oui> vpn-idx <vpn-idx>",
1099 .path =
"show dhcpv6 vss",
1100 .short_help =
"show dhcpv6 VSS",
1111 u32 sw_if_index0=0, sw_if_index;
1143 .path =
"show dhcpv6 link-address interface",
1144 .short_help =
"show dhcpv6 link-address interface <interface>",
#define foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED
void mfib_table_entry_delete(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source)
Delete a FIB entry.
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
static ip6_address_t all_dhcpv6_server_relay_agent_address
fib_protocol_t frp_proto
The protocol of the address below.
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.
static u8 * format_dhcpv6_proxy_trace(u8 *s, va_list *args)
u32 * mfib_index_by_sw_if_index
Table index indexed by software interface.
A representation of a path as described by a route producer.
static clib_error_t * dhcpv6_proxy_set_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
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.
u32 free_list_index
Buffer free list that this buffer was allocated from and will be freed to.
static u8 * format_dhcpv6_proxy_header_with_length(u8 *s, va_list *args)
void dhcp_proxy_walk(fib_protocol_t proto, dhcp_proxy_walk_fn_t fn, void *ctx)
Walk/Visit each DHCP proxy server.
void mfib_table_unlock(u32 fib_index, fib_protocol_t proto)
Take a reference counting lock on the table.
dhcp_proxy_main_t dhcp_proxy_main
Shard 4/6 instance of DHCP main.
static ip6_address_t all_dhcpv6_server_address
int dhcp6_proxy_set_server(ip46_address_t *addr, ip46_address_t *src_addr, u32 rx_table_id, u32 server_table_id, int is_del)
#define ethernet_buffer_header_size(b)
Determine the size of the Ethernet headers of the current frame in the buffer.
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.
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.
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.
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 * ip6_interface_first_address(ip6_main_t *im, u32 sw_if_index)
get first IPv6 interface address
struct _vlib_node_registration vlib_node_registration_t
static vlib_node_registration_t dhcpv6_proxy_to_server_node
(constructor) VLIB_REGISTER_NODE (dhcpv6_proxy_to_server_node)
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)
fib_node_index_t mfib_table_entry_update(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, fib_rpf_id_t rpf_id, mfib_entry_flags_t entry_flags)
Add a new (with no replication) or lock an existing entry.
unformat_function_t unformat_vnet_sw_interface
static ip6_address_t * ip6_interface_first_global_or_site_address(ip6_main_t *im, u32 sw_if_index)
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)
static clib_error_t * dhcp6_proxy_init(vlib_main_t *vm)
static char * dhcpv6_proxy_error_strings[]
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
dhcpv6_proxy_to_server_input_next_t
#define VLIB_INIT_FUNCTION(x)
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...)
fib_node_index_t mfib_table_entry_path_update(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source, const fib_route_path_t *rpath, mfib_itf_flags_t itf_flags)
Add n paths to an entry (aka route) in the FIB.
static clib_error_t * dhcpv6_vss_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
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.
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
static vlib_node_registration_t dhcpv6_proxy_to_client_node
(constructor) VLIB_REGISTER_NODE (dhcpv6_proxy_to_client_node)
#define foreach_dhcpv6_proxy_to_server_input_next
u32 server_fib_index
The FIB index (not the external Table-ID) in which the server is reachable.
Collection of global DHCP proxy data.
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
static clib_error_t * dhcpv6_proxy_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.
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
#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).
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
u32 ft_table_id
Table ID (hash key) for this FIB.
static clib_error_t * dhcpv6_link_address_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define VLIB_BUFFER_IS_TRACED
#define clib_memcpy(a, b, c)
A representation of a single DHCP Server within a given VRF config.
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Aggregrate type for a prefix.
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)
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.
ip_lookup_main_t lookup_main
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
static void copy_ip6_address(ip6_address_t *dst, ip6_address_t *src)
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.
u32 mfib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
void mfib_table_lock(u32 fib_index, fib_protocol_t proto)
Release a reference counting lock on the table.
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
fib_table_t * fib_table_get(fib_node_index_t index, fib_protocol_t proto)
Get a pointer to a FIB table.
static ip6_mfib_t * ip6_mfib_get(u32 index)
Get the FIB at the given index.
#define VLIB_REGISTER_NODE(x,...)
vnet_sw_interface_type_t type
#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)
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
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)
u16 fp_len
The mask length.
ethernet_interface_t * interfaces
u32 flags
buffer flags: VLIB_BUFFER_IS_TRACED: trace this buffer.
static int dhcp6_proxy_show_walk(dhcp_proxy_t *proxy, void *ctx)
#define ip46_address_is_zero(ip46)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
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.
static u8 * format_dhcp6_proxy_server(u8 *s, va_list *args)
const ip46_address_t zero_addr
A protocol Independent FIB table.
static uword dhcpv6_proxy_to_server_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
static uword dhcpv6_proxy_to_client_input(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)