Changeset View
Changeset View
Standalone View
Standalone View
sys/net/route/nhgrp_ctl.c
| Show First 20 Lines • Show All 245 Lines • ▼ Show 20 Lines | |||||
| */ | */ | ||||
| static void | static void | ||||
| compile_nhgrp(struct nhgrp_priv *dst_priv, const struct weightened_nhop *x, | compile_nhgrp(struct nhgrp_priv *dst_priv, const struct weightened_nhop *x, | ||||
| uint32_t num_slots, uint32_t metric) | uint32_t num_slots, uint32_t metric) | ||||
| { | { | ||||
| struct nhgrp_object *dst; | struct nhgrp_object *dst; | ||||
| int i, slot_idx, remaining_slots; | int i, slot_idx, remaining_slots; | ||||
| uint64_t remaining_sum, nh_weight, nh_slots; | uint64_t remaining_sum, nh_weight, nh_slots; | ||||
| bool one_reachable = true; | |||||
| slot_idx = 0; | slot_idx = 0; | ||||
| dst = dst_priv->nhg; | dst = dst_priv->nhg; | ||||
| /* Calculate sum of all weights with lowest metric */ | /* Calculate sum of all weights with lowest metric */ | ||||
| remaining_sum = 0; | remaining_sum = nh_weight = 0; | ||||
| for (i = 0; i < dst_priv->nhg_nh_count; i++) { | for (i = 0; i < dst_priv->nhg_nh_count; i++) { | ||||
| if (nhop_get_metric(x[i].nh) == metric) | if (nhop_get_metric(x[i].nh) == metric) { | ||||
| /* | |||||
| * Temporary store weight of unreachable nhops in nh_weight | |||||
| * to ensure we have at least one reachable nexthop. | |||||
| */ | |||||
| if (NH_IS_VALID(x[i].nh)) | |||||
| remaining_sum += x[i].weight; | remaining_sum += x[i].weight; | ||||
| else | |||||
| nh_weight += x[i].weight; | |||||
| } | } | ||||
| } | |||||
| /* If no reachable nhops exist, include all */ | |||||
| if (remaining_sum == 0) { | |||||
| remaining_sum = nh_weight; | |||||
| one_reachable = false; | |||||
| } | |||||
| remaining_slots = num_slots; | remaining_slots = num_slots; | ||||
| FIB_NH_LOG(LOG_DEBUG3, x[0].nh, "sum: %lu, slots: %d, lowest_metric: %u", | FIB_NH_LOG(LOG_DEBUG3, x[0].nh, "sum: %lu, slots: %d, lowest_metric: %u", | ||||
| remaining_sum, remaining_slots, metric); | remaining_sum, remaining_slots, metric); | ||||
| for (i = 0; i < dst_priv->nhg_nh_count; i++) { | for (i = 0; i < dst_priv->nhg_nh_count; i++) { | ||||
| if (nhop_get_metric(x[i].nh) != metric) | if (nhop_get_metric(x[i].nh) != metric) | ||||
| continue; | continue; | ||||
| /* Calculate number of slots for the current nexthop */ | /* | ||||
| if (remaining_sum > 0) { | * Calculate number of slots for the current nexthop. | ||||
| * Exclude unreachable nexthops if there is one reachable. | |||||
| */ | |||||
| if (remaining_sum > 0 && | |||||
| (NH_IS_VALID(x[i].nh) || !one_reachable)) { | |||||
| nh_weight = (uint64_t)x[i].weight; | nh_weight = (uint64_t)x[i].weight; | ||||
| nh_slots = (nh_weight * remaining_slots / remaining_sum); | nh_slots = (nh_weight * remaining_slots / remaining_sum); | ||||
| remaining_sum -= x[i].weight; | |||||
| } else | } else | ||||
| nh_slots = 0; | nh_slots = 0; | ||||
| remaining_sum -= x[i].weight; | |||||
| remaining_slots -= nh_slots; | remaining_slots -= nh_slots; | ||||
| FIB_NH_LOG(LOG_DEBUG3, x[0].nh, | FIB_NH_LOG(LOG_DEBUG3, x[0].nh, | ||||
| " rem_sum: %lu, rem_slots: %d nh_slots: %d, slot_idx: %d", | " rem_sum: %lu, rem_slots: %d nh_slots: %d, slot_idx: %d", | ||||
| remaining_sum, remaining_slots, (int)nh_slots, slot_idx); | remaining_sum, remaining_slots, (int)nh_slots, slot_idx); | ||||
| KASSERT((slot_idx + nh_slots <= num_slots), | KASSERT((slot_idx + nh_slots <= num_slots), | ||||
| ("index overflow during nhg compilation")); | ("index overflow during nhg compilation")); | ||||
| ▲ Show 20 Lines • Show All 772 Lines • ▼ Show 20 Lines | nhgrp_get_count(struct rib_head *rh) | ||||
| ctl = rh->nh_control; | ctl = rh->nh_control; | ||||
| NHOPS_RLOCK(ctl); | NHOPS_RLOCK(ctl); | ||||
| count = ctl->gr_head.items_count; | count = ctl->gr_head.items_count; | ||||
| NHOPS_RUNLOCK(ctl); | NHOPS_RUNLOCK(ctl); | ||||
| return (count); | return (count); | ||||
| } | |||||
| /* | |||||
| * Recompile nexthop group without changing the slots. | |||||
| * Since a nexthop might become reachable again soon, | |||||
| * this avoids unnecessary memory allocation. | |||||
| */ | |||||
| static void | |||||
| nhgrp_recompile_one(struct nhgrp_priv *nhg_priv) | |||||
| { | |||||
| struct nhgrp_object *nhg = nhg_priv->nhg; | |||||
| const struct weightened_nhop *wn; | |||||
| uint32_t num_nhops, min_metric; | |||||
| wn = nhgrp_get_nhops(nhg, &num_nhops); | |||||
| /* dataplane only has the lowest metric nhops, just pick one */ | |||||
| min_metric = nhop_get_metric(nhg->nhops[0]); | |||||
| compile_nhgrp(nhg_priv, wn, nhg->nhg_size, min_metric); | |||||
| } | |||||
| void | |||||
| nhgrp_recompile(struct rib_head *rh) | |||||
| { | |||||
| struct nh_control *ctl = rh->nh_control; | |||||
| struct nhgrp_priv *nhg_priv; | |||||
| NHOPS_WLOCK_ASSERT(ctl); | |||||
| if (ctl->gr_head.items_count == 0) | |||||
| return; | |||||
| CHT_SLIST_FOREACH(&ctl->gr_head, mpath, nhg_priv) { | |||||
glebius: Question: what does require us to be in the net epoch here, given that we already have the… | |||||
| nhgrp_recompile_one(nhg_priv); | |||||
| } CHT_SLIST_FOREACH_END; | |||||
| } | } | ||||
| int | int | ||||
| nhgrp_dump_sysctl(struct rib_head *rh, struct sysctl_req *w) | nhgrp_dump_sysctl(struct rib_head *rh, struct sysctl_req *w) | ||||
| { | { | ||||
| struct nh_control *ctl = rh->nh_control; | struct nh_control *ctl = rh->nh_control; | ||||
| struct epoch_tracker et; | struct epoch_tracker et; | ||||
| struct nhgrp_priv *nhg_priv; | struct nhgrp_priv *nhg_priv; | ||||
| Show All 29 Lines | |||||
Question: what does require us to be in the net epoch here, given that we already have the write lock?