X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Fdhcp%2Fdhcp6_pd_client_cp.c;h=f6d30fa0c7db6763c6b9daa7fcdb59f9191af44d;hb=18c17cb8afe8914ed754d3d196e0a969a9502222;hp=6f151430e5844c99bf5a9119c7d641ba9f79b0f2;hpb=02bfd641b69aab83397e217b9ca4e35a6aab05c8;p=vpp.git diff --git a/src/plugins/dhcp/dhcp6_pd_client_cp.c b/src/plugins/dhcp/dhcp6_pd_client_cp.c index 6f151430e58..f6d30fa0c7d 100644 --- a/src/plugins/dhcp/dhcp6_pd_client_cp.c +++ b/src/plugins/dhcp/dhcp6_pd_client_cp.c @@ -19,9 +19,12 @@ #include #include #include +#include +#include #include #include #include +#include typedef struct { @@ -67,6 +70,8 @@ typedef struct { prefix_info_t *prefix_pool; const u8 **prefix_group_name_by_index; + /* vector of active prefix pool indicies, prep-H for pool_foreach(..) */ + u32 *indices; } ip6_prefix_main_t; static ip6_prefix_main_t ip6_prefix_main; @@ -241,17 +246,6 @@ send_client_message_start_stop (u32 sw_if_index, u32 server_index, static void interrupt_process (void); -static u32 -ip6_enable (u32 sw_if_index) -{ - dhcp6_pd_client_cp_main_t *rm = &dhcp6_pd_client_cp_main; - clib_error_t *rv; - - rv = enable_ip6_interface (rm->vlib_main, sw_if_index); - - return rv != 0; -} - static u8 ip6_prefixes_equal (ip6_address_t * prefix1, ip6_address_t * prefix2, u8 len) { @@ -285,6 +279,7 @@ dhcp6_pd_reply_event_handler (vl_api_dhcp6_pd_reply_event_t * mp) f64 current_time; clib_error_t *error = 0; u32 i; + prefix_info_t *prefix_info; current_time = vlib_time_now (vm); @@ -371,13 +366,26 @@ dhcp6_pd_reply_event_handler (vl_api_dhcp6_pd_reply_event_t * mp) send_client_message_start_stop (sw_if_index, server_index, mp->msg_type, 0, 0); + vec_reset_length (pm->indices); + /* + * We're going to loop through the pool multiple times, + * so collect active indices. + */ + /* *INDENT-OFF* */ + pool_foreach (prefix_info, pm->prefix_pool) + { + vec_add1 (pm->indices, prefix_info - pm->prefix_pool); + } + /* *INDENT-ON* */ + for (i = 0; i < n_prefixes; i++) { - prefix_info_t *prefix_info = 0; u8 prefix_length; u32 valid_time; u32 preferred_time; + int j; + prefix_info = 0; api_prefix = &mp->prefixes[i]; prefix = (ip6_address_t *) api_prefix->prefix.address; @@ -394,28 +402,40 @@ dhcp6_pd_reply_event_handler (vl_api_dhcp6_pd_reply_event_t * mp) continue; u8 address_prefix_present = 0; - /* *INDENT-OFF* */ - pool_foreach (prefix_info, pm->prefix_pool, - ({ - if (is_dhcpv6_pd_prefix (prefix_info) && - prefix_info->opaque_data == sw_if_index && - prefix_info->prefix_length == prefix_length && - ip6_prefixes_equal (&prefix_info->prefix, prefix, prefix_length)) - { - address_prefix_present = 1; - goto prefix_pool_foreach_out; - } - })); - /* *INDENT-ON* */ - prefix_pool_foreach_out: + + /* Look for a matching prefix_info */ + for (j = 0; j < vec_len (pm->indices); j++) + { + prefix_info = pool_elt_at_index (pm->prefix_pool, pm->indices[j]); + + if (is_dhcpv6_pd_prefix (prefix_info) && + prefix_info->opaque_data == sw_if_index && + prefix_info->prefix_length == prefix_length && + ip6_prefixes_equal (&prefix_info->prefix, prefix, + prefix_length)) + { + address_prefix_present = 1; + break; + } + } if (address_prefix_present) { + /* Found the (primary) prefix, update prefix timers */ prefix_info->preferred_lt = preferred_time; prefix_info->valid_lt = valid_time; prefix_info->due_time = current_time + valid_time; if (prefix_info->due_time > rm->max_valid_due_time) rm->max_valid_due_time = prefix_info->due_time; + + /* + * Tell the RA code to update any secondary per-interface + * timers that it might be hoarding. + */ + ip6_ra_update_secondary_radv_info + (prefix, prefix_length, + prefix_info->opaque_data /* sw_if_index */ , + valid_time, preferred_time); continue; } @@ -423,6 +443,7 @@ dhcp6_pd_reply_event_handler (vl_api_dhcp6_pd_reply_event_t * mp) continue; pool_get (pm->prefix_pool, prefix_info); + vec_add1 (pm->indices, prefix_info - pm->prefix_pool); prefix_info->prefix_group_index = client_state->prefix_group_index; set_is_dhcpv6_pd_prefix (prefix_info, 1); prefix_info->opaque_data = sw_if_index; @@ -460,8 +481,8 @@ create_prefix_list (u32 sw_if_index) prefix_info_t *prefix_info, *prefix_list = 0;; /* *INDENT-OFF* */ - pool_foreach (prefix_info, pm->prefix_pool, - ({ + pool_foreach (prefix_info, pm->prefix_pool) + { if (is_dhcpv6_pd_prefix (prefix_info) && prefix_info->opaque_data == sw_if_index) { @@ -469,7 +490,7 @@ create_prefix_list (u32 sw_if_index) vec_validate (prefix_list, pos); clib_memcpy (&prefix_list[pos], prefix_info, sizeof (*prefix_info)); } - })); + } /* *INDENT-ON* */ return prefix_list; @@ -510,8 +531,8 @@ dhcp6_pd_client_cp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, { due_time = current_time + 1e9; /* *INDENT-OFF* */ - pool_foreach (prefix_info, pm->prefix_pool, - ({ + pool_foreach (prefix_info, pm->prefix_pool) + { if (is_dhcpv6_pd_prefix (prefix_info)) { if (prefix_info->due_time > current_time) @@ -537,7 +558,7 @@ dhcp6_pd_client_cp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, } } } - })); + } /* *INDENT-ON* */ for (i = 0; i < vec_len (rm->client_state_by_sw_if_index); i++) { @@ -684,7 +705,16 @@ cp_ip6_address_add_del_now (ip6_address_info_t * address_info, u8 is_add) clib_warning ("Failed adding IPv6 address: %U", format_clib_error, error); else - address_info->configured_in_data_plane = 1; + { + if (CLIB_DEBUG > 0) + clib_warning ("Add address %U on %U", + format_ip6_address_and_length, + &addr, address_info->prefix_length, + format_vnet_sw_if_index_name, + vnet_get_main (), address_info->sw_if_index); + + address_info->configured_in_data_plane = 1; + } } else { @@ -699,7 +729,17 @@ cp_ip6_address_add_del_now (ip6_address_info_t * address_info, u8 is_add) clib_warning ("Failed adding IPv6 address: %U", format_clib_error, error); else - address_info->configured_in_data_plane = 1; + { + if (CLIB_DEBUG > 0) + clib_warning ("Add address %U on %U", + format_ip6_address_and_length, + &addr, address_info->prefix_length, + format_vnet_sw_if_index_name, + vnet_get_main (), + address_info->sw_if_index); + + address_info->configured_in_data_plane = 1; + } } } } @@ -748,16 +788,63 @@ cp_ip6_address_find_new_active_prefix (u32 prefix_group_index, prefix_info_t *prefix_info; /* *INDENT-OFF* */ - pool_foreach (prefix_info, pm->prefix_pool, - ({ + pool_foreach (prefix_info, pm->prefix_pool) + { if (prefix_info->prefix_group_index == prefix_group_index && prefix_info - pm->prefix_pool != ignore_prefix_index) return prefix_info - pm->prefix_pool; - })); + } /* *INDENT-ON* */ return ~0; } +static void +cp_ip6_advertise_prefix (prefix_info_t * prefix_info, + ip6_address_info_t * address_info, int enable) +{ + vlib_main_t *vm = vlib_get_main (); + ip6_main_t *im = &ip6_main; + u32 prefix_index; + ip6_address_t addr; + int rv; + + prefix_index = + active_prefix_index_by_prefix_group_index_get + (address_info->prefix_group_index); + + if (cp_ip6_construct_address (address_info, prefix_index, &addr) != 0) + { + clib_warning ("address construction FAIL"); + return; + } + + /* The RA code assumes that host bits are zero, so clear them */ + addr.as_u64[0] &= im->fib_masks[address_info->prefix_length].as_u64[0]; + addr.as_u64[1] &= im->fib_masks[address_info->prefix_length].as_u64[1]; + + rv = ip6_ra_prefix (vm, address_info->sw_if_index, + &addr, address_info->prefix_length, + 0 /* use_default */ , + prefix_info->valid_lt, + prefix_info->preferred_lt, 0 /* no_advertise */ , + 0 /* off_link */ , + 0 /* no_autoconfig */ , + 0 /* no_onlink */ , + enable == 0 /* is_no */ ); + if (rv != 0) + { + clib_warning ("ip6_neighbor_ra_prefix returned %d", rv); + return; + } + + if (CLIB_DEBUG > 0) + clib_warning ("Advertise prefix %U valid lt %u preferred lt %u", + format_ip6_address_and_length, &addr, + address_info->prefix_length, prefix_info->valid_lt, + prefix_info->preferred_lt); +} + + static void cp_ip6_address_prefix_add_del_handler (u32 prefix_index, u8 is_add) { @@ -783,7 +870,13 @@ cp_ip6_address_prefix_add_del_handler (u32 prefix_index, u8 is_add) { address_info = &apm->addresses[i]; if (address_info->prefix_group_index == prefix_group_index) - cp_ip6_address_add_del_now (address_info, 1 /* add */ ); + { + /* Add the prefix to the interface */ + cp_ip6_address_add_del_now (address_info, 1 /* add */ ); + /* And advertise the prefix on the interface */ + cp_ip6_advertise_prefix (prefix, address_info, + 1 /* enable */ ); + } } } } @@ -796,7 +889,11 @@ cp_ip6_address_prefix_add_del_handler (u32 prefix_index, u8 is_add) { address_info = &apm->addresses[i]; if (address_info->prefix_group_index == prefix_group_index) - cp_ip6_address_add_del_now (address_info, 0 /* del */ ); + { + cp_ip6_advertise_prefix (prefix, address_info, + 0 /* enable */ ); + cp_ip6_address_add_del_now (address_info, 0 /* del */ ); + } } active_prefix_index_by_prefix_group_index_set (prefix_group_index, ~0); @@ -811,7 +908,11 @@ cp_ip6_address_prefix_add_del_handler (u32 prefix_index, u8 is_add) { address_info = &apm->addresses[i]; if (address_info->prefix_group_index == prefix_group_index) - cp_ip6_address_add_del_now (address_info, 1 /* add */ ); + { + cp_ip6_address_add_del_now (address_info, 1 /* add */ ); + cp_ip6_advertise_prefix (prefix, address_info, + 1 /* enable */ ); + } } } } @@ -1038,8 +1139,8 @@ cp_ip6_prefixes_show_command_function (vlib_main_t * vm, f64 current_time = vlib_time_now (vm); /* *INDENT-OFF* */ - pool_foreach (prefix_info, pm->prefix_pool, - ({ + pool_foreach (prefix_info, pm->prefix_pool) + { prefix_group = pm->prefix_group_name_by_index[prefix_info->prefix_group_index]; vlib_cli_output (vm, "opaque_data: %lu, prefix: %U/%d, prefix group: %s, " @@ -1050,7 +1151,7 @@ cp_ip6_prefixes_show_command_function (vlib_main_t * vm, prefix_group, prefix_info->preferred_lt, prefix_info->valid_lt, prefix_info->due_time - current_time); - })); + } /* *INDENT-ON* */ return error; @@ -1075,8 +1176,8 @@ ip6_pd_clients_show_command_function (vlib_main_t * vm, client_state_t *cs; f64 current_time = vlib_time_now (vm); const u8 *prefix_group; - char buf1[256]; - char buf2[256]; + u8 *buf1 = 0; + u8 *buf2 = 0; const char *rebinding; u32 i; @@ -1085,18 +1186,20 @@ ip6_pd_clients_show_command_function (vlib_main_t * vm, cs = &rm->client_state_by_sw_if_index[i]; if (cs->enabled) { + vec_reset_length (buf1); + vec_reset_length (buf2); if (cs->T1_due_time != DBL_MAX && cs->T1_due_time > current_time) { - sprintf (buf1, "%u remaining", - (u32) round (cs->T1_due_time - current_time)); + buf1 = format (buf1, "%u remaining", + (u32) round (cs->T1_due_time - current_time)); } else - sprintf (buf1, "timeout"); + buf1 = format (buf1, "timeout"); if (cs->T2_due_time != DBL_MAX && cs->T2_due_time > current_time) - sprintf (buf2, "%u remaining", - (u32) round (cs->T2_due_time - current_time)); + buf2 = format (buf2, "%u remaining", + (u32) round (cs->T2_due_time - current_time)); else - sprintf (buf2, "timeout"); + buf2 = format (buf2, "timeout"); if (cs->rebinding) rebinding = ", REBINDING"; else @@ -1105,8 +1208,8 @@ ip6_pd_clients_show_command_function (vlib_main_t * vm, pm->prefix_group_name_by_index[cs->prefix_group_index]; if (cs->T1) vlib_cli_output (vm, - "sw_if_index: %u, prefix group: %s, T1: %u (%s), " - "T2: %u (%s), server index: %d%s", i, + "sw_if_index: %u, prefix group: %s, T1: %u (%v), " + "T2: %u (%v), server index: %d%s", i, prefix_group, cs->T1, buf1, cs->T2, buf2, cs->server_index, rebinding); else @@ -1115,6 +1218,9 @@ ip6_pd_clients_show_command_function (vlib_main_t * vm, } } + vec_free (buf1); + vec_free (buf2); + return error; } @@ -1181,7 +1287,7 @@ dhcp6_pd_client_enable_disable (u32 sw_if_index, dhcp6_clients_enable_disable (1); } - ip6_enable (sw_if_index); + ip6_link_enable (sw_if_index, NULL); send_client_message_start_stop (sw_if_index, ~0, DHCPV6_MSG_SOLICIT, 0, 1); } @@ -1199,8 +1305,8 @@ dhcp6_pd_client_enable_disable (u32 sw_if_index, vec_validate (prefix_list, 0); /* *INDENT-OFF* */ - pool_foreach (prefix_info, pm->prefix_pool, - ({ + pool_foreach (prefix_info, pm->prefix_pool) + { if (is_dhcpv6_pd_prefix (prefix_info) && prefix_info->opaque_data == sw_if_index) { @@ -1218,7 +1324,7 @@ dhcp6_pd_client_enable_disable (u32 sw_if_index, set_is_dhcpv6_pd_prefix (prefix_info, 0); pool_put (pm->prefix_pool, prefix_info); } - })); + } /* *INDENT-ON* */ vec_free (prefix_list); @@ -1300,6 +1406,8 @@ VLIB_CLI_COMMAND (dhcp6_pd_client_enable_disable_command, static) = { }; /* *INDENT-ON* */ +#include + static clib_error_t * dhcp_pd_client_cp_init (vlib_main_t * vm) { @@ -1307,7 +1415,7 @@ dhcp_pd_client_cp_init (vlib_main_t * vm) rm->vlib_main = vm; rm->vnet_main = vnet_get_main (); - rm->api_main = &api_main; + rm->api_main = vlibapi_get_main (); rm->node_index = dhcp6_pd_client_cp_process_node.index; return (NULL);