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") 40 #define _(s,n) DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_##s, 71 s =
format (s,
"DHCPV6 proxy: sent to server %U",
74 s =
format (s,
"DHCPV6 proxy: sent to client from %U",
79 s =
format (s,
" original_sw_if_index: %d, sw_if_index: %d\n",
89 u32 max_header_bytes = va_arg (*args,
u32);
92 header_bytes =
sizeof (h[0]);
93 if (max_header_bytes != 0 && header_bytes > max_header_bytes)
94 return format (s,
"dhcpv6 header truncated");
96 s =
format (s,
"DHCPV6 Proxy");
114 if ((a->
as_u8[0] & 0xe0) == 0x20 ||
115 (a->
as_u8[0] & 0xfe) == 0xfc) {
136 u32 n_left_from, next_index, *from, *to_next;
140 u32 pkts_to_server = 0, pkts_to_client = 0, pkts_no_server = 0;
141 u32 pkts_no_interface_address = 0, pkts_no_exceeding_max_hop = 0;
142 u32 pkts_no_src_address = 0;
143 u32 pkts_wrong_msg_type = 0;
144 u32 pkts_too_big = 0;
150 u32 rx_fib_idx = 0, server_fib_idx = 0;
154 while (n_left_from > 0)
160 while (n_left_from > 0 && n_left_to_next > 0)
164 u32 rx_sw_if_index = 0;
174 dhcpv6_option_t *fwd_opt;
175 dhcpv6_relay_hdr_t *r1;
177 dhcpv6_int_id_t *id1;
179 dhcpv6_client_mac_t *cmac;
181 u8 client_src_mac[6];
197 u0 = (
void *) h0 - (
sizeof (*u0));
198 ip0 = (
void *) u0 - (
sizeof (*ip0));
218 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_SEND_TO_CLIENT;
224 pkts_wrong_msg_type++;
225 error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
226 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
232 rx_sw_if_index = sw_if_index =
239 error0 = DHCPV6_PROXY_ERROR_NO_SERVER;
240 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
268 fwd_opt->length = clib_host_to_net_u16 (len);
269 fwd_opt->option = clib_host_to_net_u16 (DHCPV6_OPTION_RELAY_MSG);
278 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
279 pkts_no_exceeding_max_hop++;
290 r1->link_addr.as_u64[0] = 0;
291 r1->link_addr.as_u64[1] = 0;
292 goto link_address_set;
309 error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
310 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
311 pkts_no_interface_address++;
325 error0 = DHCPV6_PROXY_ERROR_PKT_TOO_BIG;
326 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
334 id1->opt.option = clib_host_to_net_u16 (DHCPV6_OPTION_INTERFACE_ID);
335 id1->opt.length = clib_host_to_net_u16 (
sizeof (rx_sw_if_index));
336 id1->int_idx = clib_host_to_net_u32 (rx_sw_if_index);
344 cmac->opt.length = clib_host_to_net_u16 (
sizeof (*cmac) -
348 (DHCPV6_OPTION_CLIENT_LINK_LAYER_ADDRESS);
349 cmac->link_type = clib_host_to_net_u16 (1);
351 u1->
length +=
sizeof (*cmac);
359 u16 type_len =
sizeof (vss1->vss_type);
365 id_len =
sizeof (vss->
vpn_id);
366 memcpy (vss1->data, vss->
vpn_id, id_len);
376 vss1->opt.option = clib_host_to_net_u16 (DHCPV6_OPTION_VSS);
377 vss1->opt.length = clib_host_to_net_u16 (type_len + id_len);
378 u1->
length += type_len + id_len +
sizeof (vss1->opt);
384 u1->
src_port = clib_host_to_net_u16 (UDP_DST_PORT_dhcpv6_to_client);
385 u1->
dst_port = clib_host_to_net_u16 (UDP_DST_PORT_dhcpv6_to_server);
388 clib_host_to_net_u16 (clib_net_to_host_u16 (fwd_opt->length) +
389 sizeof (*r1) +
sizeof (*fwd_opt) +
390 sizeof (*u1) +
sizeof (*id1) + u1->
length);
393 ip1->ip_version_traffic_class_and_flow_label = 0x60;
394 ip1->payload_length = u1->
length;
399 &server->
dhcp_server.ip6 : &all_dhcpv6_server_address);
411 error0 = DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS;
412 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_DROP;
413 pkts_no_src_address++;
422 ASSERT (bogus_length == 0);
424 next0 = DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP;
453 &all_dhcpv6_server_address);
461 to_next, n_left_to_next,
473 if (next0 == DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP)
484 to_next, n_left_to_next);
498 if (DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_LOOKUP == next0)
509 to_next, n_left_to_next,
517 DHCPV6_PROXY_ERROR_RELAY_TO_CLIENT,
520 DHCPV6_PROXY_ERROR_RELAY_TO_SERVER,
523 DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS,
524 pkts_no_interface_address);
526 DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE,
527 pkts_wrong_msg_type);
529 DHCPV6_PROXY_ERROR_NO_SRC_ADDRESS,
530 pkts_no_src_address);
532 DHCPV6_PROXY_ERROR_PKT_TOO_BIG, pkts_too_big);
539 .name =
"dhcpv6-proxy-to-server",
541 .vector_size =
sizeof (
u32),
548 #define _(s,n) [DHCPV6_PROXY_TO_SERVER_INPUT_NEXT_##s] = n, 556 .unformat_buffer = unformat_dhcpv6_proxy_header,
567 u32 n_left_from, *from;
578 while (n_left_from > 0)
583 dhcpv6_relay_hdr_t *h0;
593 u32 original_sw_if_index = ~0;
597 dhcpv6_option_t *r0 = 0, *o;
599 u8 interface_opt_flag = 0;
600 u8 relay_msg_opt_flag = 0;
602 u32 server_fib_idx, client_fib_idx;
613 error0 = DHCPV6_PROXY_ERROR_WRONG_MESSAGE_TYPE;
627 if (HOP_COUNT_LIMIT < h0->hop_count)
632 u0 = (
void *) h0 - (
sizeof (*u0));
633 ip0 = (
void *) u0 - (
sizeof (*ip0));
646 if (DHCPV6_OPTION_INTERFACE_ID == clib_net_to_host_u16 (o->option))
648 interface_opt_flag = 1;
649 if (clib_net_to_host_u16 (o->length) == sizeof (sw_if_index))
651 clib_net_to_host_u32 (((dhcpv6_int_id_t *) o)->int_idx);
654 error0 = DHCPV6_PROXY_ERROR_WRONG_INTERFACE_ID_OPTION;
658 if (DHCPV6_OPTION_RELAY_MSG == clib_net_to_host_u16 (o->option))
660 relay_msg_opt_flag = 1;
663 if ((relay_msg_opt_flag == 1) && (interface_opt_flag == 1))
667 clib_net_to_host_u16 (o->length));
669 (dhcpv6_option_t *) (((
uword) o) +
670 clib_net_to_host_u16 (o->length) +
674 if ((relay_msg_opt_flag == 0) || (r0 == 0))
676 error0 = DHCPV6_PROXY_ERROR_NO_RELAY_MESSAGE_OPTION;
682 error0 = DHCPV6_PROXY_ERROR_NO_CIRCUIT_ID_OPTION;
694 error0 = DHCPV6_PROXY_ERROR_NO_SERVER;
704 ip0->src_address.as_u64[0] == server->
dhcp_server.ip6.as_u64[0] &&
705 ip0->src_address.as_u64[1] == server->
dhcp_server.ip6.as_u64[1])
712 error0 = DHCPV6_PROXY_ERROR_BAD_SVR_FIB_OR_ADDRESS;
739 error0 = DHCPV6_PROXY_ERROR_NO_INTERFACE_ADDRESS;
743 len = clib_net_to_host_u16 (r0->length);
747 u1->
src_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_server);
748 u1->
dst_port = clib_net_to_host_u16 (UDP_DST_PORT_dhcpv6_to_client);
752 ip0->ip_version_traffic_class_and_flow_label & 0x00000fff;
760 ASSERT (bogus_length == 0);
774 clib_net_to_host_u16 (0x8100) : clib_net_to_host_u16 (0x86dd);
778 u32 *vlan_tag = (
u32 *) (mac0 + 1);
780 tmp = (si0->
sub.
id << 16) | 0x0800;
781 *vlan_tag = clib_host_to_net_u32 (tmp);
811 .name =
"dhcpv6-proxy-to-client",
813 .vector_size =
sizeof (
u32),
820 .unformat_buffer = unformat_dhcpv6_proxy_header,
835 all_dhcpv6_server_address.
as_u64[0] =
836 clib_host_to_net_u64 (0xFF05000000000000);
837 all_dhcpv6_server_address.
as_u64[1] = clib_host_to_net_u64 (0x00010003);
840 all_dhcpv6_server_relay_agent_address.
as_u64[0] =
841 clib_host_to_net_u64 (0xFF02000000000000);
842 all_dhcpv6_server_relay_agent_address.
as_u64[1] =
843 clib_host_to_net_u64 (0x00010002);
852 ip46_address_t * src_addr,
853 u32 rx_table_id,
u32 server_table_id,
int is_del)
856 u32 rx_fib_index = 0;
868 return VNET_API_ERROR_INVALID_DST_ADDRESS;
871 return VNET_API_ERROR_INVALID_SRC_ADDRESS;
880 addr, server_table_id))
898 .frp_sw_if_index = 0xffffffff,
904 rx_fib_index, server_table_id))
944 ip46_address_t
addr, src_addr;
945 int set_server = 0, set_src_address = 0;
946 u32 rx_table_id = 0, server_table_id = 0;
953 else if (
unformat (input,
"src-address %U",
956 else if (
unformat (input,
"server-fib-id %d", &server_table_id))
958 else if (
unformat (input,
"rx-fib-id %d", &rx_table_id))
966 if (is_del || (set_server && set_src_address))
971 server_table_id, is_del);
979 case VNET_API_ERROR_INVALID_DST_ADDRESS:
982 case VNET_API_ERROR_INVALID_SRC_ADDRESS:
985 case VNET_API_ERROR_NO_SUCH_ENTRY:
987 (0,
"Fib id %d: no per-fib DHCP server configured", rx_table_id);
1000 .path =
"set dhcpv6 proxy",
1001 .short_help =
"set dhcpv6 proxy [del] server <ipv6-addr> src-address <ipv6-addr> " 1002 "[server-fib-id <fib-id>] [rx-fib-id <fib-id>] ",
1017 s =
format (s,
"%=14s%=16s%s",
"RX FIB",
"Src Address",
1018 "Servers FIB,Address");
1024 s =
format (s,
"%=14u%=16U",
1064 .path =
"show dhcpv6 proxy",
1065 .short_help =
"Display dhcpv6 proxy info",
1075 u8 *vpn_ascii_id = 0;
1076 u32 oui = 0, fib_id = 0, tbl_id = ~0;
1080 if (
unformat (input,
"table %d", &tbl_id))
1082 else if (
unformat (input,
"oui %d", &oui))
1084 else if (
unformat (input,
"vpn-id %d", &fib_id))
1086 else if (
unformat (input,
"vpn-ascii-id %s", &vpn_ascii_id))
1098 vpn_ascii_id, oui, fib_id, is_del);
1103 case VNET_API_ERROR_NO_SUCH_ENTRY:
1113 .path =
"set dhcpv6 vss",
1114 .short_help =
"set dhcpv6 vss table <table-id> [oui <n> vpn-id <n> | vpn-ascii-id <text>]",
1131 .path =
"show dhcpv6 vss",
1132 .short_help =
"show dhcpv6 VSS",
1167 "No IPv6 address configured on",
1179 .path =
"show dhcpv6 link-address interface",
1180 .short_help =
"show dhcpv6 link-address interface <interface>",
#define foreach_ip_interface_address(lm, a, sw_if_index, loop, body)
void mfib_table_entry_delete(u32 fib_index, const mfib_prefix_t *prefix, mfib_source_t source)
Delete a FIB entry.
static ip6_address_t all_dhcpv6_server_relay_agent_address
u32 mfib_table_find_or_create_and_lock(fib_protocol_t proto, u32 table_id, mfib_source_t src)
Get the index of the FIB for a Table-ID.
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)
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 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.
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
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.
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
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.
dpo_proto_t frp_proto
The protocol of the address below.
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)
u8 vss_type
VSS type as defined in RFC 6607: 0 for NVT ASCII VPN Identifier 1 for RFC 2685 VPN-ID of 7 octects - ...
u32 error_drop_node_index
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[]
#define clib_memcpy(d, s, n)
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)
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
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.
void mfib_table_unlock(u32 fib_index, fib_protocol_t proto, mfib_source_t source)
Take a reference counting lock on the table.
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.
vnet_sw_interface_flags_t flags
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)
Configure/set a new VSS info.
void mfib_table_lock(u32 fib_index, fib_protocol_t proto, mfib_source_t source)
Release a reference counting lock on the table.
#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)
#define VLIB_REGISTER_NODE(x,...)
static void vlib_buffer_copy_trace_flag(vlib_main_t *vm, vlib_buffer_t *b, u32 bi_target)
u8 * vpn_ascii_id
Type 0 ASCII VPN Identifier.
u32 ft_table_id
Table ID (hash key) for this FIB.
void udp_unregister_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u8 is_ip4)
static clib_error_t * dhcpv6_link_address_show_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
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)
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 vlib_buffer_free_list_index_t vlib_buffer_get_free_list_index(vlib_buffer_t *b)
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
static vlib_main_t * vlib_get_main(void)
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)
struct _vlib_node_registration vlib_node_registration_t
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)
u8 vpn_id[7]
Type 1 VPN-ID.
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
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 ethernet_main_t * vnet_get_ethernet_main(void)
static ip6_mfib_t * ip6_mfib_get(u32 index)
Get the FIB at the given index.
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)
static vlib_buffer_free_list_t * vlib_buffer_get_free_list(vlib_main_t *vm, vlib_buffer_free_list_index_t 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_FREE_LIST_INDEX_MASK: bits used to store free list index, 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)