37 #define foreach_dhcp6_pd_client_cp_msg \ 38 _(DHCP6_PD_CLIENT_ENABLE_DISABLE, dhcp6_pd_client_enable_disable) \ 39 _(IP6_ADD_DEL_ADDRESS_USING_PREFIX, ip6_add_del_address_using_prefix) 41 #define vl_api_dhcp6_pd_client_enable_disable_t_print vl_noop_handler 42 #define vl_api_ip6_add_del_address_using_prefix_t_print vl_noop_handler 123 if (prefix_group_index >=
135 static const u32 empty = ~0;
137 ASSERT (prefix_group_index != ~0);
139 if (prefix_index == ~0
140 && prefix_group_index >=
145 prefix_group_index, empty);
219 i32 diff_time = client_state->
T2 - current_time;
222 params.
mrd = diff_time;
232 params.
mrd = diff_time;
242 if (
vec_len (prefix_list) != 0)
244 for (i = 0; i <
vec_len (prefix_list); i++)
250 pref->prefix = prefix->
prefix;
282 return clib_net_to_host_u64 (prefix1->
as_u64[1]) >> (128 -
len) ==
283 clib_net_to_host_u64 (prefix2->
as_u64[1]) >> (128 -
len);
285 return clib_net_to_host_u64 (prefix1->
as_u64[0]) >> (64 -
len) ==
286 clib_net_to_host_u64 (prefix2->
as_u64[0]) >> (64 -
len);
300 u32 inner_status_code;
335 (
"Advertise message arrived with NoPrefixAvail status code");
341 for (i = 0; i < n_prefixes; i++)
347 prefix_info = &prefix_list[i];
348 prefix_info->
prefix = *prefix;
349 prefix_info->prefix_length = prefix_length;
350 prefix_info->preferred_lt = 0;
351 prefix_info->valid_lt = 0;
366 clib_warning (
"Reply message arrived with Server ID different " 367 "from that in Request or Renew message");
373 clib_warning (
"Reply message arrived with NoPrefixAvail status code");
377 (
"Invalid Reply message arrived: It contains NoPrefixAvail " 378 "status code but also contains prefixes");
385 clib_warning (
"Reply message arrived with UnspecFail status code");
392 for (i = 0; i < n_prefixes; i++)
411 if (preferred_time > valid_time)
414 u8 address_prefix_present = 0;
418 if (is_dhcpv6_pd_prefix (prefix_info) &&
419 prefix_info->opaque_data == sw_if_index &&
420 prefix_info->prefix_length == prefix_length &&
421 ip6_prefixes_equal (&prefix_info->prefix, prefix, prefix_length))
423 address_prefix_present = 1;
424 goto prefix_pool_foreach_out;
428 prefix_pool_foreach_out:
430 if (address_prefix_present)
432 prefix_info->preferred_lt = preferred_time;
433 prefix_info->valid_lt = valid_time;
434 prefix_info->due_time = current_time + valid_time;
447 prefix_info->prefix_length = prefix_length;
448 prefix_info->prefix = *
prefix;
449 prefix_info->preferred_lt = preferred_time;
450 prefix_info->valid_lt = valid_time;
451 prefix_info->due_time = current_time + valid_time;
460 client_state->server_index = server_index;
461 client_state->T1 = ntohl (mp->T1);
462 client_state->T2 = ntohl (mp->T2);
463 if (client_state->T1 != 0)
464 client_state->T1_due_time = current_time + client_state->T1;
465 if (client_state->T2 != 0)
466 client_state->T2_due_time = current_time + client_state->T2;
467 client_state->rebinding = 0;
483 if (is_dhcpv6_pd_prefix (prefix_info) &&
484 prefix_info->opaque_data == sw_if_index)
486 u32 pos = vec_len (prefix_list);
487 vec_validate (prefix_list, pos);
488 clib_memcpy (&prefix_list[pos], prefix_info, sizeof (*prefix_info));
506 f64 sleep_time = 1e9;
510 uword *event_data = 0;
529 due_time = current_time + 1e9;
533 if (is_dhcpv6_pd_prefix (prefix_info))
535 if (prefix_info->due_time > current_time)
537 if (prefix_info->due_time < due_time)
538 due_time = prefix_info->due_time;
542 u32 prefix_index = prefix_info - pm->prefix_pool;
543 notify_prefix_add_del (prefix_index, 0);
544 u32 sw_if_index = prefix_info->opaque_data;
545 set_is_dhcpv6_pd_prefix (prefix_info, 0);
546 pool_put (pm->prefix_pool, prefix_info);
547 client_state = &rm->client_state_by_sw_if_index[sw_if_index];
548 if (--client_state->prefix_count == 0)
550 client_state->rebinding = 0;
551 client_state->server_index = ~0;
552 send_client_message_start_stop (sw_if_index, ~0,
600 while (due_time < current_time);
602 sleep_time = due_time - current_time;
612 .name =
"dhcp6-pd-client-cp-process",
655 u64 mask, addr0, pref;
657 addr0 = clib_net_to_host_u64 (address_info->
address.
as_u64[0]);
669 r_addr->
as_u64[0] = clib_host_to_net_u64 (addr0);
692 if (prefix_index != ~0)
726 if (prefix_index == ~0)
742 "but active prefix index is not set");
763 u32 ignore_prefix_index)
771 if (prefix_info->prefix_group_index == prefix_group_index &&
772 prefix_info - pm->prefix_pool != ignore_prefix_index)
773 return prefix_info - pm->prefix_pool;
786 u32 new_prefix_index;
787 u32 prefix_group_index;
796 (prefix_group_index) == ~0)
799 (prefix_group_index, prefix_index);
811 (prefix_group_index) == prefix_index)
820 (prefix_group_index, ~0);
824 if (new_prefix_index != ~0)
827 (prefix_group_index, new_prefix_index);
853 (
const char *) name))
858 name_dup = (
u8 *) strdup ((
const char *)
name);
859 if (free_index != ~0)
879 u32 prefix_group_index;
885 return VNET_API_ERROR_INVALID_VALUE;
888 if (prefix_group != 0 && prefix_group[0] !=
'\0')
890 if (strnlen ((
const char *) prefix_group, 64) == 64)
891 return VNET_API_ERROR_INVALID_VALUE;
896 prefix_group_index = ~0;
905 0 == memcmp (&address_info->
address, &address, 16))
908 return VNET_API_ERROR_DUPLICATE_IF_ADDRESS;
917 return VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE;
934 vl_api_ip6_add_del_address_using_prefix_reply_t *rmp;
949 prefix_length, mp->
is_add);
964 u8 *prefix_group = 0;
978 else if (
unformat (line_input,
"prefix group %s", &prefix_group));
981 &address, &prefix_length))
983 else if (
unformat (line_input,
"del"))
996 if (sw_if_index == ~0)
998 else if (address_set == 0)
1003 (sw_if_index, prefix_group, address, prefix_length, add) != 0)
1027 .path =
"set ip6 address",
1028 .short_help =
"set ip6 address <interface> [prefix group <string>] " 1042 const u8 *prefix_group;
1050 prefix_group = (
const u8 *)
"NONE";
1055 "sw_if_index: %u, prefix_group: %s, address: %U/%d",
1066 .path =
"show ip6 addresses",
1067 .short_help =
"show ip6 addresses",
1080 const u8 *prefix_group;
1087 pm->prefix_group_name_by_index[prefix_info->prefix_group_index];
1088 vlib_cli_output (vm,
"opaque_data: %lu, prefix: %U/%d, prefix group: %s, " 1089 "preferred lifetime: %u, valid lifetime: %u " 1091 prefix_info->opaque_data, format_ip6_address,
1092 &prefix_info->prefix, prefix_info->prefix_length,
1094 prefix_info->preferred_lt, prefix_info->valid_lt,
1095 prefix_info->due_time - current_time);
1104 .path =
"show ip6 prefixes",
1105 .short_help =
"show ip6 prefixes",
1120 const u8 *prefix_group;
1123 const char *rebinding;
1133 sprintf (buf1,
"%u remaining",
1137 sprintf (buf1,
"timeout");
1139 sprintf (buf2,
"%u remaining",
1142 sprintf (buf2,
"timeout");
1144 rebinding =
", REBINDING";
1151 "sw_if_index: %u, prefix group: %s, T1: %u (%s), " 1152 "T2: %u (%s), server index: %d%s", i,
1153 prefix_group, cs->
T1, buf1, cs->
T2, buf2,
1157 prefix_group, rebinding);
1166 .path =
"show ip6 pd clients",
1167 .short_help =
"show ip6 pd clients",
1185 u32 prefix_group_index;
1190 return VNET_API_ERROR_INVALID_VALUE;
1201 if (strnlen ((
const char *) prefix_group, 64) == 64
1202 || prefix_group[0] ==
'\0')
1203 return VNET_API_ERROR_INVALID_VALUE;
1204 prefix_group_index =
1208 return VNET_API_ERROR_INVALID_VALUE;
1211 if (!old_enabled && enable)
1229 else if (old_enabled && !enable)
1245 if (is_dhcpv6_pd_prefix (prefix_info) &&
1246 prefix_info->opaque_data == sw_if_index)
1248 ASSERT (sw_if_index < vec_len (rm->client_state_by_sw_if_index) &&
1249 rm->client_state_by_sw_if_index[sw_if_index].enabled);
1250 client_state_t *client_state =
1251 &rm->client_state_by_sw_if_index[sw_if_index];
1252 prefix_list[0] = *prefix_info;
1253 send_client_message_start_stop (sw_if_index,
1254 client_state->server_index,
1255 DHCPV6_MSG_RELEASE, prefix_list,
1257 u32 prefix_index = prefix_info - pm->prefix_pool;
1258 notify_prefix_add_del (prefix_index, 0);
1259 set_is_dhcpv6_pd_prefix (prefix_info, 0);
1260 pool_put (pm->prefix_pool, prefix_info);
1267 clib_memset (client_state, 0,
sizeof (*client_state));
1282 u8 *prefix_group = 0;
1295 else if (
unformat (line_input,
"prefix group %s", &prefix_group));
1296 else if (
unformat (line_input,
"disable"))
1306 if (prefix_group == 0 && enable)
1308 else if (sw_if_index != ~0)
1338 .path =
"dhcp6 pd client",
1339 .short_help =
"dhcp6 pd client <interface> (prefix group <string> | disable)",
1348 vl_api_dhcp6_pd_client_enable_disable_reply_t *rmp;
1362 REPLY_MACRO (VL_API_SW_INTERFACE_SET_TABLE_REPLY);
1365 #define vl_msg_name_crc_list 1366 #include <vnet/dhcp/dhcp6_pd_client_cp.api.h> 1367 #undef vl_msg_name_crc_list 1372 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id); 1373 foreach_vl_msg_name_crc_dhcp6_pd_client_cp;
1389 vl_msg_api_set_handlers(VL_API_##N, #n, \ 1390 vl_api_##n##_t_handler, \ 1392 vl_api_##n##_t_endian, \ 1393 vl_api_##n##_t_print, \ 1394 sizeof(vl_api_##n##_t), 0); #define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
u8 * format_clib_error(u8 *s, va_list *va)
static void notify_prefix_add_del(u32 prefix_index, u8 is_add)
vlib_node_registration_t dhcp6_pd_client_cp_process_node
(constructor) VLIB_REGISTER_NODE (dhcp6_pd_client_cp_process_node)
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
vnet_main_t * vnet_get_main(void)
vl_api_dhcp6_pd_prefix_info_t prefixes[n_prefixes]
static void cp_ip6_address_prefix_add_del_handler(u32 prefix_index, u8 is_add)
Optimized string handling code, including c11-compliant "safe C library" variants.
static u32 cp_ip6_address_find_new_active_prefix(u32 prefix_group_index, u32 ignore_prefix_index)
static_always_inline u8 is_dhcpv6_pd_prefix(prefix_info_t *prefix_info)
static void send_client_message_start_stop(u32 sw_if_index, u32 server_index, u8 msg_type, prefix_info_t *prefix_list, u8 start)
static f64 vlib_time_now(vlib_main_t *vm)
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Enable/disable DHCPv6 PD client on interface.
dhcp6_pd_send_client_message_params_prefix_t * prefixes
static uword * clib_bitmap_set(uword *ai, uword i, uword value)
Sets the ith bit of a bitmap to new_value Removes trailing zeros from the bitmap. ...
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
void dhcp6_pd_send_client_message(vlib_main_t *vm, u32 sw_if_index, u8 stop, dhcp6_pd_send_client_message_params_t *params)
static void setup_message_id_table(api_main_t *am)
unformat_function_t unformat_vnet_sw_interface
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
static vlib_cli_command_t ip6_pd_clients_show_command
(constructor) VLIB_CLI_COMMAND (ip6_pd_clients_show_command)
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static ip6_address_with_prefix_main_t ip6_address_with_prefix_main
const u8 ** prefix_group_name_by_index
static void cp_ip6_address_add_del_now(ip6_address_info_t *address_info, u8 is_add)
#define static_always_inline
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
ip6_address_info_t * addresses
#define VLIB_INIT_FUNCTION(x)
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
#define clib_error_return(e, args...)
static clib_error_t * dhcp6_pd_client_enable_disable_command_fn(vlib_main_t *vm, unformat_input_t()*input, vlib_cli_command_t *cmd)
static_always_inline void active_prefix_index_by_prefix_group_index_set(u32 prefix_group_index, u32 prefix_index)
static u32 ip6_enable(u32 sw_if_index)
static vlib_cli_command_t ip6_address_add_del_command
(constructor) VLIB_CLI_COMMAND (ip6_address_add_del_command)
VNET_DHCP6_PD_REPLY_EVENT_FUNCTION(dhcp6_pd_reply_event_handler)
Struct representing DHCPv6 PD prefix.
static int cp_ip6_address_add_del(u32 sw_if_index, const u8 *prefix_group, ip6_address_t address, u8 prefix_length, u8 is_add)
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
u32 * active_prefix_index_by_prefix_group_index
static int dhcp6_pd_client_enable_disable(u32 sw_if_index, const u8 *prefix_group, u8 enable)
static void interrupt_process(void)
static void disable_process(void)
API main structure, used by both vpp and binary API clients.
#define BAD_SW_IF_INDEX_LABEL
#define VLIB_REGISTER_NODE(x,...)
static clib_error_t * cp_ip6_prefixes_show_command_function(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
static clib_error_t * ip6_pd_clients_show_command_function(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define vec_free(V)
Free vector's memory (no header).
static prefix_info_t * create_prefix_list(u32 sw_if_index)
#define clib_warning(format, args...)
static uword clib_bitmap_get(uword *ai, uword i)
Gets the ith bit value from a bitmap.
clib_error_t * enable_ip6_interface(vlib_main_t *vm, u32 sw_if_index)
#define VLIB_CLI_COMMAND(x,...)
static u32 cp_ip6_construct_address(ip6_address_info_t *address_info, u32 prefix_index, ip6_address_t *r_addr)
static_always_inline u32 active_prefix_index_by_prefix_group_index_get(u32 prefix_group_index)
static u8 ip6_prefixes_equal(ip6_address_t *prefix1, ip6_address_t *prefix2, u8 len)
Tell client about a DHCPv6 PD server reply event.
static void vlib_node_set_state(vlib_main_t *vm, u32 node_index, vlib_node_state_t new_state)
Set node dispatch state.
static uword ip6_address_is_link_local_unicast(const ip6_address_t *a)
static clib_error_t * dhcp6_pd_reply_event_handler(vl_api_dhcp6_pd_reply_event_t *mp)
static vlib_main_t * vlib_get_main(void)
#define vec_elt(v, i)
Get vector value at index i.
static dhcp6_pd_client_cp_main_t dhcp6_pd_client_cp_main
prefix_info_t * prefix_pool
static_always_inline void set_is_dhcpv6_pd_prefix(prefix_info_t *prefix_info, u8 value)
static uword vnet_sw_interface_is_api_valid(vnet_main_t *vnm, u32 sw_if_index)
u8 configured_in_data_plane
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static clib_error_t * cp_ip6_addresses_show_command_function(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
vlib_node_main_t node_main
static clib_error_t * dhcp_pd_client_cp_init(vlib_main_t *vm)
static uword dhcp6_pd_client_cp_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
static u32 prefix_group_find_or_create(const u8 *name, u8 create)
void dhcp6_clients_enable_disable(u8 enable)
static vlib_cli_command_t ip6_prefixes_show_command
(constructor) VLIB_CLI_COMMAND (ip6_prefixes_show_command)
Add/delete IPv6 address optionally using available prefix.
clib_bitmap_t * prefix_ownership_bitmap
static void vl_api_dhcp6_pd_client_enable_disable_t_handler(vl_api_dhcp6_pd_client_enable_disable_t *mp)
#define vec_foreach(var, vec)
Vector iterator.
clib_error_t * ip6_add_del_interface_address(vlib_main_t *vm, u32 sw_if_index, ip6_address_t *address, u32 address_length, u32 is_del)
static void vl_api_ip6_add_del_address_using_prefix_t_handler(vl_api_ip6_add_del_address_using_prefix_t *mp)
static vlib_cli_command_t dhcp6_pd_client_enable_disable_command
(constructor) VLIB_CLI_COMMAND (dhcp6_pd_client_enable_disable_command)
#define vec_validate_init_empty(V, I, INIT)
Make sure vector is long enough for given index and initialize empty space (no header, unspecified alignment)
void vlib_start_process(vlib_main_t *vm, uword process_index)
static void enable_process(void)
static ip6_prefix_main_t ip6_prefix_main
#define foreach_dhcp6_pd_client_cp_msg
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
static vlib_cli_command_t ip6_addresses_show_command
(constructor) VLIB_CLI_COMMAND (ip6_addresses_show_command)
static clib_error_t * cp_ip6_address_add_del_command_function(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define VALIDATE_SW_IF_INDEX(mp)
client_state_t * client_state_by_sw_if_index