Changeset View
Changeset View
Standalone View
Standalone View
sys/net/route/fib_algo.c
Show First 20 Lines • Show All 1,532 Lines • ▼ Show 20 Lines | set_algo_inet6_sysctl_handler(SYSCTL_HANDLER_ARGS) | ||||
return (set_fib_algo(curthread->td_proc->p_fibnum, AF_INET6, oidp, req)); | return (set_fib_algo(curthread->td_proc->p_fibnum, AF_INET6, oidp, req)); | ||||
} | } | ||||
SYSCTL_PROC(_net_route_algo_inet6, OID_AUTO, algo, | SYSCTL_PROC(_net_route_algo_inet6, OID_AUTO, algo, | ||||
CTLFLAG_VNET | CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, 0, | CTLFLAG_VNET | CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, 0, | ||||
set_algo_inet6_sysctl_handler, "A", "Set IPv6 lookup algo"); | set_algo_inet6_sysctl_handler, "A", "Set IPv6 lookup algo"); | ||||
#endif | #endif | ||||
static struct nhop_object * | |||||
dummy_lookup(void *algo_data, const struct flm_lookup_key key, uint32_t scopeid) | |||||
{ | |||||
return (NULL); | |||||
} | |||||
static void | static void | ||||
destroy_fdh_epoch(epoch_context_t ctx) | destroy_fdh_epoch(epoch_context_t ctx) | ||||
{ | { | ||||
struct fib_dp_header *fdh; | struct fib_dp_header *fdh; | ||||
fdh = __containerof(ctx, struct fib_dp_header, fdh_epoch_ctx); | fdh = __containerof(ctx, struct fib_dp_header, fdh_epoch_ctx); | ||||
free(fdh, M_RTABLE); | free(fdh, M_RTABLE); | ||||
} | } | ||||
static struct fib_dp_header * | static struct fib_dp_header * | ||||
alloc_fib_dp_array(uint32_t num_tables, bool waitok) | alloc_fib_dp_array(uint32_t num_tables, bool waitok) | ||||
{ | { | ||||
size_t sz; | size_t sz; | ||||
struct fib_dp_header *fdh; | struct fib_dp_header *fdh; | ||||
sz = sizeof(struct fib_dp_header); | sz = sizeof(struct fib_dp_header); | ||||
sz += sizeof(struct fib_dp) * num_tables; | sz += sizeof(struct fib_dp) * num_tables; | ||||
fdh = malloc(sz, M_RTABLE, (waitok ? M_WAITOK : M_NOWAIT) | M_ZERO); | fdh = malloc(sz, M_RTABLE, (waitok ? M_WAITOK : M_NOWAIT) | M_ZERO); | ||||
if (fdh != NULL) | if (fdh != NULL) { | ||||
fdh->fdh_num_tables = num_tables; | fdh->fdh_num_tables = num_tables; | ||||
/* | |||||
* Set dummy lookup function ptr always returning NULL, so | |||||
* we can delay algo init. | |||||
*/ | |||||
for (uint32_t i = 0; i < num_tables; i++) | |||||
fdh->fdh_idx[i].f = dummy_lookup; | |||||
} | |||||
return (fdh); | return (fdh); | ||||
} | } | ||||
static struct fib_dp_header * | static struct fib_dp_header * | ||||
get_fib_dp_header(struct fib_dp *dp) | get_fib_dp_header(struct fib_dp *dp) | ||||
{ | { | ||||
return (__containerof((void *)dp, struct fib_dp_header, fdh_idx)); | return (__containerof((void *)dp, struct fib_dp_header, fdh_idx)); | ||||
▲ Show 20 Lines • Show All 359 Lines • ▼ Show 20 Lines | fib_check_best_algo(struct rib_head *rh, struct fib_lookup_module *orig_flm) | ||||
return (best_flm); | return (best_flm); | ||||
} | } | ||||
/* | /* | ||||
* Called when new route table is created. | * Called when new route table is created. | ||||
* Selects, allocates and attaches fib algo for the table. | * Selects, allocates and attaches fib algo for the table. | ||||
*/ | */ | ||||
int | static bool | ||||
fib_select_algo_initial(struct rib_head *rh) | fib_select_algo_initial(struct rib_head *rh, struct fib_dp *dp) | ||||
{ | { | ||||
struct fib_lookup_module *flm; | struct fib_lookup_module *flm; | ||||
struct fib_data *fd = NULL; | struct fib_data *fd = NULL; | ||||
enum flm_op_result result; | enum flm_op_result result; | ||||
struct epoch_tracker et; | struct epoch_tracker et; | ||||
int error = 0; | |||||
flm = fib_check_best_algo(rh, NULL); | flm = fib_check_best_algo(rh, NULL); | ||||
if (flm == NULL) { | if (flm == NULL) { | ||||
RH_PRINTF(LOG_CRIT, rh, "no algo selected"); | RH_PRINTF(LOG_CRIT, rh, "no algo selected"); | ||||
return (ENOENT); | return (false); | ||||
} | } | ||||
RH_PRINTF(LOG_INFO, rh, "selected algo %s", flm->flm_name); | RH_PRINTF(LOG_INFO, rh, "selected algo %s", flm->flm_name); | ||||
NET_EPOCH_ENTER(et); | NET_EPOCH_ENTER(et); | ||||
RIB_WLOCK(rh); | RIB_WLOCK(rh); | ||||
result = setup_fd_instance(flm, rh, NULL, &fd, false); | result = setup_fd_instance(flm, rh, NULL, &fd, false); | ||||
RIB_WUNLOCK(rh); | RIB_WUNLOCK(rh); | ||||
NET_EPOCH_EXIT(et); | NET_EPOCH_EXIT(et); | ||||
RH_PRINTF(LOG_DEBUG, rh, "result=%d fd=%p", result, fd); | RH_PRINTF(LOG_DEBUG, rh, "result=%d fd=%p", result, fd); | ||||
if (result == FLM_SUCCESS) { | if (result == FLM_SUCCESS) | ||||
*dp = fd->fd_dp; | |||||
else | |||||
RH_PRINTF(LOG_CRIT, rh, "unable to setup algo %s", flm->flm_name); | |||||
fib_unref_algo(flm); | |||||
return (result == FLM_SUCCESS); | |||||
} | |||||
/* | /* | ||||
* Attach datapath directly to avoid multiple reallocations | * Sets up fib algo instances for the non-initialized RIBs in the @family. | ||||
* during fib growth | * Allocates temporary datapath index to amortize datapaint index updates | ||||
* with large @num_tables. | |||||
*/ | */ | ||||
struct fib_dp_header *fdp; | void | ||||
struct fib_dp **pdp; | fib_setup_family(int family, uint32_t num_tables) | ||||
{ | |||||
struct fib_dp_header *new_fdh = alloc_fib_dp_array(num_tables, false); | |||||
if (new_fdh == NULL) { | |||||
ALGO_PRINTF(LOG_CRIT, "Unable to setup framework for %s", print_family(family)); | |||||
return; | |||||
} | |||||
pdp = get_family_dp_ptr(rh->rib_family); | for (int i = 0; i < num_tables; i++) { | ||||
if (pdp != NULL) { | struct rib_head *rh = rt_tables_get_rnh(i, family); | ||||
fdp = get_fib_dp_header(*pdp); | if (rh->rib_algo_init) | ||||
fdp->fdh_idx[fd->fd_fibnum] = fd->fd_dp; | continue; | ||||
FD_PRINTF(LOG_INFO, fd, "datapath attached"); | if (!fib_select_algo_initial(rh, &new_fdh->fdh_idx[i])) | ||||
continue; | |||||
rh->rib_algo_init = true; | |||||
} | } | ||||
} else { | |||||
error = EINVAL; | FIB_MOD_LOCK(); | ||||
RH_PRINTF(LOG_CRIT, rh, "unable to setup algo %s", flm->flm_name); | struct fib_dp **pdp = get_family_dp_ptr(family); | ||||
struct fib_dp_header *old_fdh = get_fib_dp_header(*pdp); | |||||
/* Update the items not touched by the new init, from the old data pointer */ | |||||
for (int i = 0; i < num_tables; i++) { | |||||
if (new_fdh->fdh_idx[i].f == dummy_lookup) | |||||
new_fdh->fdh_idx[i] = old_fdh->fdh_idx[i]; | |||||
} | } | ||||
fib_unref_algo(flm); | /* Ensure all index writes have completed */ | ||||
atomic_thread_fence_rel(); | |||||
/* Set new datapath pointer */ | |||||
*pdp = &new_fdh->fdh_idx[0]; | |||||
return (error); | FIB_MOD_UNLOCK(); | ||||
fib_epoch_call(destroy_fdh_epoch, &old_fdh->fdh_epoch_ctx); | |||||
} | } | ||||
/* | /* | ||||
* Registers fib lookup module within the subsystem. | * Registers fib lookup module within the subsystem. | ||||
*/ | */ | ||||
int | int | ||||
fib_module_register(struct fib_lookup_module *flm) | fib_module_register(struct fib_lookup_module *flm) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 49 Lines • Show Last 20 Lines |