diff options
Diffstat (limited to 'src/vnet/ip/ip4_forward.c')
-rw-r--r-- | src/vnet/ip/ip4_forward.c | 138 |
1 files changed, 49 insertions, 89 deletions
diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c index 919718035a1..5903ef892ca 100644 --- a/src/vnet/ip/ip4_forward.c +++ b/src/vnet/ip/ip4_forward.c @@ -380,28 +380,28 @@ ip4_add_interface_prefix_routes (ip4_main_t *im, mhash_set (&lm->prefix_to_if_prefix_index, &key, if_prefix - lm->if_prefix_pool, 0 /* old value */); + pfx_special.fp_len = a->address_length; + pfx_special.fp_addr.ip4.as_u32 = address->as_u32; + + /* set the glean route for the prefix */ + fib_table_entry_update_one_path (fib_index, &pfx_special, + FIB_SOURCE_INTERFACE, + (FIB_ENTRY_FLAG_CONNECTED | + FIB_ENTRY_FLAG_ATTACHED), + DPO_PROTO_IP4, + /* No next-hop address */ + NULL, + sw_if_index, + /* invalid FIB index */ + ~0, + 1, + /* no out-label stack */ + NULL, + FIB_ROUTE_PATH_FLAG_NONE); + /* length <= 30 - add glean, drop first address, maybe drop bcast address */ if (a->address_length <= 30) { - pfx_special.fp_len = a->address_length; - pfx_special.fp_addr.ip4.as_u32 = address->as_u32; - - /* set the glean route for the prefix */ - fib_table_entry_update_one_path (fib_index, &pfx_special, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_ATTACHED), - DPO_PROTO_IP4, - /* No next-hop address */ - NULL, - sw_if_index, - /* invalid FIB index */ - ~0, - 1, - /* no out-label stack */ - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - /* set a drop route for the base address of the prefix */ pfx_special.fp_len = 32; pfx_special.fp_addr.ip4.as_u32 = @@ -528,90 +528,52 @@ ip4_del_interface_prefix_routes (ip4_main_t * im, if_prefix->ref_count -= 1; /* - * Routes need to be adjusted if: - * - deleting last intf addr in prefix - * - deleting intf addr used as default source address in glean adjacency + * Routes need to be adjusted if deleting last intf addr in prefix * * We're done now otherwise */ - if ((if_prefix->ref_count > 0) && - !pool_is_free_index (lm->if_address_pool, if_prefix->src_ia_index)) + if (if_prefix->ref_count > 0) return; /* length <= 30, delete glean route, first address, last address */ if (address_length <= 30) { + /* Less work to do in FIB if we remove the covered /32s first */ - /* remove glean route for prefix */ - pfx_special.fp_addr.ip4 = *address; - pfx_special.fp_len = address_length; - fib_table_entry_delete (fib_index, &pfx_special, FIB_SOURCE_INTERFACE); - - /* if no more intf addresses in prefix, remove other special routes */ - if (!if_prefix->ref_count) - { - /* first address in prefix */ - pfx_special.fp_addr.ip4.as_u32 = - address->as_u32 & im->fib_masks[address_length]; - pfx_special.fp_len = 32; + /* first address in prefix */ + pfx_special.fp_addr.ip4.as_u32 = + address->as_u32 & im->fib_masks[address_length]; + pfx_special.fp_len = 32; - if (pfx_special.fp_addr.ip4.as_u32 != address->as_u32) - fib_table_entry_special_remove (fib_index, - &pfx_special, - FIB_SOURCE_INTERFACE); + if (pfx_special.fp_addr.ip4.as_u32 != address->as_u32) + fib_table_entry_special_remove (fib_index, + &pfx_special, + FIB_SOURCE_INTERFACE); - /* prefix broadcast address */ - pfx_special.fp_addr.ip4.as_u32 = - address->as_u32 | ~im->fib_masks[address_length]; - pfx_special.fp_len = 32; + /* prefix broadcast address */ + pfx_special.fp_addr.ip4.as_u32 = + address->as_u32 | ~im->fib_masks[address_length]; + pfx_special.fp_len = 32; - if (pfx_special.fp_addr.ip4.as_u32 != address->as_u32) - fib_table_entry_special_remove (fib_index, - &pfx_special, - FIB_SOURCE_INTERFACE); - } - else - /* default source addr just got deleted, find another */ - { - ip_interface_address_t *new_src_ia = NULL; - ip4_address_t *new_src_addr = NULL; - - new_src_addr = - ip4_interface_address_matching_destination - (im, address, sw_if_index, &new_src_ia); - - if_prefix->src_ia_index = new_src_ia - lm->if_address_pool; - - pfx_special.fp_len = address_length; - pfx_special.fp_addr.ip4 = *new_src_addr; - - /* set new glean route for the prefix */ - fib_table_entry_update_one_path (fib_index, &pfx_special, - FIB_SOURCE_INTERFACE, - (FIB_ENTRY_FLAG_CONNECTED | - FIB_ENTRY_FLAG_ATTACHED), - DPO_PROTO_IP4, - /* No next-hop address */ - NULL, - sw_if_index, - /* invalid FIB index */ - ~0, - 1, - /* no out-label stack */ - NULL, - FIB_ROUTE_PATH_FLAG_NONE); - return; - } + if (pfx_special.fp_addr.ip4.as_u32 != address->as_u32) + fib_table_entry_special_remove (fib_index, + &pfx_special, + FIB_SOURCE_INTERFACE); } - /* length == 31, delete attached route for the other address */ else if (address_length == 31) { + /* length == 31, delete attached route for the other address */ pfx_special.fp_addr.ip4.as_u32 = address->as_u32 ^ clib_host_to_net_u32(1); fib_table_entry_delete (fib_index, &pfx_special, FIB_SOURCE_INTERFACE); } + /* remove glean route for prefix */ + pfx_special.fp_addr.ip4 = *address; + pfx_special.fp_len = address_length; + fib_table_entry_delete (fib_index, &pfx_special, FIB_SOURCE_INTERFACE); + mhash_unset (&lm->prefix_to_if_prefix_index, &key, 0 /* old_value */); pool_put (lm->if_prefix_pool, if_prefix); } @@ -623,16 +585,15 @@ ip4_del_interface_routes (u32 sw_if_index, ip4_address_t * address, u32 address_length) { fib_prefix_t pfx = { - .fp_len = address_length, + .fp_len = 32, .fp_proto = FIB_PROTOCOL_IP4, .fp_addr.ip4 = *address, }; + fib_table_entry_delete (fib_index, &pfx, FIB_SOURCE_INTERFACE); + ip4_del_interface_prefix_routes (im, sw_if_index, fib_index, address, address_length); - - pfx.fp_len = 32; - fib_table_entry_delete (fib_index, &pfx, FIB_SOURCE_INTERFACE); } #ifndef CLIB_MARCH_VARIANT @@ -2540,9 +2501,8 @@ ip4_rewrite_inline_with_gso (vlib_main_t * vm, thread_index, adj_index0, 1, vlib_buffer_length_in_chain (vm, b[0]) + rw_len0); - if (is_midchain && adj0->sub_type.midchain.fixup_func) - adj0->sub_type.midchain.fixup_func - (vm, adj0, b[0], adj0->sub_type.midchain.fixup_data); + if (is_midchain) + adj_midchain_fixup (vm, adj0, b[0]); if (is_mcast) /* copy bytes from the IP address into the MAC rewrite */ |