static clib_error_t * adj_mcast_interface_state_change (vnet_main_t * vnm, u32 sw_if_index, u32 flags) { /* * for each mcast on the interface trigger a walk back to the children */ fib_protocol_t proto; ip_adjacency_t *adj; for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++) { if (sw_if_index >= vec_len(adj_mcasts[proto]) || ADJ_INDEX_INVALID == adj_mcasts[proto][sw_if_index]) continue; adj = adj_get(adj_mcasts[proto][sw_if_index]); fib_node_back_walk_ctx_t bw_ctx = { .fnbw_reason = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP ? FIB_NODE_BW_REASON_FLAG_INTERFACE_UP : FIB_NODE_BW_REASON_FLAG_INTERFACE_DOWN), }; fib_walk_sync(FIB_NODE_TYPE_ADJ, adj_get_index(adj), &bw_ctx); } return (NULL); } VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(adj_mcast_interface_state_change); /** * @brief Invoked on each SW interface of a HW interface when the * HW interface state changes */ static walk_rc_t adj_mcast_hw_sw_interface_state_change (vnet_main_t * vnm, u32 sw_if_index, void *arg) { adj_mcast_interface_state_change(vnm, sw_if_index, (uword) arg); return (WALK_CONTINUE); }
static clib_error_t * adj_mcast_interface_delete (vnet_main_t * vnm, u32 sw_if_index, u32 is_add) { /* * for each mcast on the interface trigger a walk back to the children */ fib_protocol_t proto; ip_adjacency_t *adj; if (is_add) { /* * not interested in interface additions. we will not back walk * to resolve paths through newly added interfaces. Why? The control * plane should have the brains to add interfaces first, then routes. * So the case where there are paths with a interface that matches * one just created is the case where the path resolved through an * interface that was deleted, and still has not been removed. The * new interface added, is NO GUARANTEE that the interface being * added now, even though it may have the same sw_if_index, is the * same interface that the path needs. So tough! * If the control plane wants these routes to resolve it needs to * remove and add them again. */ return (NULL); } for (proto = FIB_PROTOCOL_IP4; proto <= FIB_PROTOCOL_IP6; proto++) { if (sw_if_index >= vec_len(adj_mcasts[proto]) || ADJ_INDEX_INVALID == adj_mcasts[proto][sw_if_index]) continue; adj = adj_get(adj_mcasts[proto][sw_if_index]); fib_node_back_walk_ctx_t bw_ctx = { .fnbw_reason = FIB_NODE_BW_REASON_FLAG_INTERFACE_DELETE, }; fib_walk_sync(FIB_NODE_TYPE_ADJ, adj_get_index(adj), &bw_ctx); } return (NULL); }
void abf_policy_update (u32 policy_id, u32 acl_index, const fib_route_path_t * rpaths) { abf_policy_t *ap; u32 api; api = abf_policy_find (policy_id); if (INDEX_INVALID == api) { /* * create a new policy */ pool_get (abf_policy_pool, ap); api = ap - abf_policy_pool; fib_node_init (&ap->ap_node, abf_policy_fib_node_type); ap->ap_acl = acl_index; ap->ap_id = policy_id; ap->ap_pl = fib_path_list_create ((FIB_PATH_LIST_FLAG_SHARED | FIB_PATH_LIST_FLAG_NO_URPF), rpaths); /* * become a child of the path list so we get poked when * the forwarding changes. */ ap->ap_sibling = fib_path_list_child_add (ap->ap_pl, abf_policy_fib_node_type, api); /* * add this new policy to the DB */ hash_set (abf_policy_db, policy_id, api); /* * take a lock on behalf of the CLI/API creation */ fib_node_lock (&ap->ap_node); } else { /* * update an existing policy. * - add the path to the path-list and swap our ancestry * - backwalk to poke all attachments to update */ fib_node_index_t old_pl; ap = abf_policy_get (api); old_pl = ap->ap_pl; if (FIB_NODE_INDEX_INVALID != old_pl) { ap->ap_pl = fib_path_list_copy_and_path_add (old_pl, (FIB_PATH_LIST_FLAG_SHARED | FIB_PATH_LIST_FLAG_NO_URPF), rpaths); fib_path_list_child_remove (old_pl, ap->ap_sibling); } else { ap->ap_pl = fib_path_list_create ((FIB_PATH_LIST_FLAG_SHARED | FIB_PATH_LIST_FLAG_NO_URPF), rpaths); } ap->ap_sibling = fib_path_list_child_add (ap->ap_pl, abf_policy_fib_node_type, api); fib_node_back_walk_ctx_t ctx = { .fnbw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE, }; fib_walk_sync (abf_policy_fib_node_type, api, &ctx); } }
int abf_policy_delete (u32 policy_id, const fib_route_path_t * rpaths) { abf_policy_t *ap; u32 api; api = abf_policy_find (policy_id); if (INDEX_INVALID == api) { /* * no such policy */ return (-1); } else { /* * update an existing policy. * - add the path to the path-list and swap our ancestry * - backwalk to poke all attachments to update */ fib_node_index_t old_pl; ap = abf_policy_get (api); old_pl = ap->ap_pl; fib_path_list_lock (old_pl); ap->ap_pl = fib_path_list_copy_and_path_remove (ap->ap_pl, (FIB_PATH_LIST_FLAG_SHARED | FIB_PATH_LIST_FLAG_NO_URPF), rpaths); fib_path_list_child_remove (old_pl, ap->ap_sibling); ap->ap_sibling = ~0; if (FIB_NODE_INDEX_INVALID == ap->ap_pl) { /* * no more paths on this policy. It's toast * remove the CLI/API's lock */ fib_node_unlock (&ap->ap_node); } else { ap->ap_sibling = fib_path_list_child_add (ap->ap_pl, abf_policy_fib_node_type, api); fib_node_back_walk_ctx_t ctx = { .fnbw_reason = FIB_NODE_BW_REASON_FLAG_EVALUATE, }; fib_walk_sync (abf_policy_fib_node_type, api, &ctx); } fib_path_list_unlock (old_pl); } return (0); }