| 132 | } |
| 133 | |
| 134 | void |
| 135 | nhops_destroy_rib(struct rib_head *rh) |
| 136 | { |
| 137 | struct nh_control *ctl; |
| 138 | struct nhop_priv *nh_priv; |
| 139 | |
| 140 | ctl = rh->nh_control; |
| 141 | |
| 142 | /* |
| 143 | * All routes should have been deleted in rt_table_destroy(). |
| 144 | * However, TCP stack or other consumers may store referenced |
| 145 | * nexthop pointers. When these references go to zero, |
| 146 | * nhop_free() will try to unlink these records from the |
| 147 | * datastructures, most likely leading to panic. |
| 148 | * |
| 149 | * Avoid that by explicitly marking all of the remaining |
| 150 | * nexthops as unlinked by removing a reference from a special |
| 151 | * counter. Please see nhop_free() comments for more |
| 152 | * details. |
| 153 | */ |
| 154 | |
| 155 | NHOPS_WLOCK(ctl); |
| 156 | CHT_SLIST_FOREACH(&ctl->nh_head, nhops, nh_priv) { |
| 157 | DPRINTF("Marking nhop %u unlinked", nh_priv->nh_idx); |
| 158 | refcount_release(&nh_priv->nh_linked); |
| 159 | } CHT_SLIST_FOREACH_END; |
| 160 | #ifdef ROUTE_MPATH |
| 161 | nhgrp_ctl_unlink_all(ctl); |
| 162 | #endif |
| 163 | NHOPS_WUNLOCK(ctl); |
| 164 | |
| 165 | /* |
| 166 | * Postpone destruction till the end of current epoch |
| 167 | * so nhop_free() can safely use nh_control pointer. |
| 168 | */ |
| 169 | epoch_call(net_epoch_preempt, destroy_ctl_epoch, |
| 170 | &ctl->ctl_epoch_ctx); |
| 171 | } |
| 172 | |
| 173 | /* |
| 174 | * Nexhop hash calculation: |
no test coverage detected