From df089a8a13dcef08f10d6930c4959f129f784a4e Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Sun, 2 Oct 2016 16:39:06 +0100 Subject: [PATCH] (VPP-455) arp doesn't work when ip4 classifier configured with fib 2.0 Change-Id: I046de0c00db75d25ed90e33e9910c9dd0ff95580 Signed-off-by: Neale Ranns --- vnet/vnet/ethernet/arp.c | 7 +++-- vnet/vnet/fib/fib_entry.c | 2 +- vnet/vnet/fib/fib_entry.h | 6 +++++ vnet/vnet/fib/fib_entry_src.c | 44 ++++++++++++++++++++++++++++-- vnet/vnet/ip/ip4_forward.c | 41 ++++++++++++++++++++++++++++ vnet/vnet/ip/ip6_forward.c | 63 +++++++++++++++++++++++++++++++++++++++++++ vnet/vnet/ip/ip6_neighbor.c | 3 ++- 7 files changed, 160 insertions(+), 6 deletions(-) diff --git a/vnet/vnet/ethernet/arp.c b/vnet/vnet/ethernet/arp.c index 7d6184381c9..90d193e86c5 100644 --- a/vnet/vnet/ethernet/arp.c +++ b/vnet/vnet/ethernet/arp.c @@ -923,9 +923,12 @@ arp_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) dst_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0), &arp0->ip4_over_ethernet[1].ip4, 32); - dst_flags = fib_entry_get_flags (dst_fei); + dst_flags = fib_entry_get_flags_for_source (dst_fei, + FIB_SOURCE_INTERFACE); - conn_sw_if_index0 = fib_entry_get_resolving_interface (dst_fei); + conn_sw_if_index0 = + fib_entry_get_resolving_interface_for_source (dst_fei, + FIB_SOURCE_INTERFACE); if (!(FIB_ENTRY_FLAG_CONNECTED & dst_flags)) { diff --git a/vnet/vnet/fib/fib_entry.c b/vnet/vnet/fib/fib_entry.c index 8b63f0dc974..8b275c61912 100644 --- a/vnet/vnet/fib/fib_entry.c +++ b/vnet/vnet/fib/fib_entry.c @@ -1299,7 +1299,7 @@ fib_entry_recursive_loop_detect (fib_node_index_t entry_index, u32 fib_entry_get_resolving_interface (fib_node_index_t entry_index) { - fib_entry_t *fib_entry; + fib_entry_t *fib_entry; fib_entry = fib_entry_get(entry_index); diff --git a/vnet/vnet/fib/fib_entry.h b/vnet/vnet/fib/fib_entry.h index ac22c170d55..1ed9d619515 100644 --- a/vnet/vnet/fib/fib_entry.h +++ b/vnet/vnet/fib/fib_entry.h @@ -480,6 +480,9 @@ extern u32 fib_entry_child_add(fib_node_index_t fib_entry_index, extern void fib_entry_child_remove(fib_node_index_t fib_entry_index, u32 sibling_index); extern u32 fib_entry_get_resolving_interface(fib_node_index_t fib_entry_index); +extern u32 fib_entry_get_resolving_interface_for_source( + fib_node_index_t fib_entry_index, + fib_source_t source); extern void fib_entry_get_prefix(fib_node_index_t fib_entry_index, fib_prefix_t *pfx); @@ -491,6 +494,9 @@ extern const void* fib_entry_get_source_data(fib_node_index_t fib_entry_index, fib_source_t source); extern fib_entry_flag_t fib_entry_get_flags(fib_node_index_t fib_entry_index); +extern fib_entry_flag_t fib_entry_get_flags_for_source( + fib_node_index_t fib_entry_index, + fib_source_t source); extern fib_source_t fib_entry_get_best_source(fib_node_index_t fib_entry_index); extern int fib_entry_is_sourced(fib_node_index_t fib_entry_index, fib_source_t source); diff --git a/vnet/vnet/fib/fib_entry_src.c b/vnet/vnet/fib/fib_entry_src.c index f7d84e5ea34..70550069356 100644 --- a/vnet/vnet/fib/fib_entry_src.c +++ b/vnet/vnet/fib/fib_entry_src.c @@ -1038,8 +1038,8 @@ fib_entry_src_action_path_swap (fib_entry_t *fib_entry, ASSERT(NULL != fib_entry_src_vft[source].fesv_path_swap); - pl_flags = fib_entry_src_flags_2_path_list_flags( - fib_entry_get_flags_i(fib_entry)); + pl_flags = fib_entry_src_flags_2_path_list_flags(flags); + vec_foreach(rpath, rpaths) { fib_entry_flags_update(fib_entry, rpath, &pl_flags, esrc); @@ -1205,6 +1205,46 @@ fib_entry_get_dpo_for_source (fib_node_index_t fib_entry_index, return (0); } +u32 +fib_entry_get_resolving_interface_for_source (fib_node_index_t entry_index, + fib_source_t source) +{ + fib_entry_t *fib_entry; + fib_entry_src_t *esrc; + + fib_entry = fib_entry_get(entry_index); + + esrc = fib_entry_src_find(fib_entry, source, NULL); + + if (NULL != esrc) + { + if (FIB_NODE_INDEX_INVALID != esrc->fes_pl) + { + return (fib_path_list_get_resolving_interface(esrc->fes_pl)); + } + } + return (~0); +} + +fib_entry_flag_t +fib_entry_get_flags_for_source (fib_node_index_t entry_index, + fib_source_t source) +{ + fib_entry_t *fib_entry; + fib_entry_src_t *esrc; + + fib_entry = fib_entry_get(entry_index); + + esrc = fib_entry_src_find(fib_entry, source, NULL); + + if (NULL != esrc) + { + return (esrc->fes_entry_flags); + } + + return (FIB_ENTRY_FLAG_NONE); +} + fib_entry_flag_t fib_entry_get_flags_i (const fib_entry_t *fib_entry) { diff --git a/vnet/vnet/ip/ip4_forward.c b/vnet/vnet/ip/ip4_forward.c index 8105d74a8b6..08fe8162260 100644 --- a/vnet/vnet/ip/ip4_forward.c +++ b/vnet/vnet/ip/ip4_forward.c @@ -3058,6 +3058,7 @@ int vnet_set_ip4_classify_intfc (vlib_main_t * vm, u32 sw_if_index, ip4_main_t * ipm = &ip4_main; ip_lookup_main_t * lm = &ipm->lookup_main; vnet_classify_main_t * cm = &vnet_classify_main; + ip4_address_t *if_addr; if (pool_is_free_index (im->sw_interfaces, sw_if_index)) return VNET_API_ERROR_NO_MATCHING_INTERFACE; @@ -3068,6 +3069,46 @@ int vnet_set_ip4_classify_intfc (vlib_main_t * vm, u32 sw_if_index, vec_validate (lm->classify_table_index_by_sw_if_index, sw_if_index); lm->classify_table_index_by_sw_if_index [sw_if_index] = table_index; + if_addr = ip4_interface_first_address (ipm, sw_if_index, NULL); + + if (NULL != if_addr) + { + fib_prefix_t pfx = { + .fp_len = 32, + .fp_proto = FIB_PROTOCOL_IP4, + .fp_addr.ip4 = *if_addr, + }; + u32 fib_index; + + fib_index = fib_table_get_index_for_sw_if_index(FIB_PROTOCOL_IP4, + sw_if_index); + + + if (table_index != (u32) ~0) + { + dpo_id_t dpo = DPO_NULL; + + dpo_set(&dpo, + DPO_CLASSIFY, + DPO_PROTO_IP4, + classify_dpo_create(FIB_PROTOCOL_IP4, + table_index)); + + fib_table_entry_special_dpo_add(fib_index, + &pfx, + FIB_SOURCE_CLASSIFY, + FIB_ENTRY_FLAG_NONE, + &dpo); + dpo_reset(&dpo); + } + else + { + fib_table_entry_special_remove(fib_index, + &pfx, + FIB_SOURCE_CLASSIFY); + } + } + return 0; } diff --git a/vnet/vnet/ip/ip6_forward.c b/vnet/vnet/ip/ip6_forward.c index 56892d4132f..65e87595d06 100644 --- a/vnet/vnet/ip/ip6_forward.c +++ b/vnet/vnet/ip/ip6_forward.c @@ -457,6 +457,28 @@ ip6_sw_interface_enable_disable (u32 sw_if_index, } } +/* get first interface address */ +ip6_address_t * +ip6_interface_first_address (ip6_main_t * im, + u32 sw_if_index, + ip_interface_address_t ** result_ia) +{ + ip_lookup_main_t * lm = &im->lookup_main; + ip_interface_address_t * ia = 0; + ip6_address_t * result = 0; + + foreach_ip_interface_address (lm, ia, sw_if_index, + 1 /* honor unnumbered */, + ({ + ip6_address_t * a = ip_interface_address_get_address (lm, ia); + result = a; + break; + })); + if (result_ia) + *result_ia = result ? ia : 0; + return result; +} + clib_error_t * ip6_add_del_interface_address (vlib_main_t * vm, u32 sw_if_index, @@ -2866,6 +2888,7 @@ int vnet_set_ip6_classify_intfc (vlib_main_t * vm, u32 sw_if_index, ip6_main_t * ipm = &ip6_main; ip_lookup_main_t * lm = &ipm->lookup_main; vnet_classify_main_t * cm = &vnet_classify_main; + ip6_address_t *if_addr; if (pool_is_free_index (im->sw_interfaces, sw_if_index)) return VNET_API_ERROR_NO_MATCHING_INTERFACE; @@ -2876,6 +2899,46 @@ int vnet_set_ip6_classify_intfc (vlib_main_t * vm, u32 sw_if_index, vec_validate (lm->classify_table_index_by_sw_if_index, sw_if_index); lm->classify_table_index_by_sw_if_index [sw_if_index] = table_index; + if_addr = ip6_interface_first_address (ipm, sw_if_index, NULL); + + if (NULL != if_addr) + { + fib_prefix_t pfx = { + .fp_len = 128, + .fp_proto = FIB_PROTOCOL_IP6, + .fp_addr.ip6 = *if_addr, + }; + u32 fib_index; + + fib_index = fib_table_get_index_for_sw_if_index(FIB_PROTOCOL_IP4, + sw_if_index); + + + if (table_index != (u32) ~0) + { + dpo_id_t dpo = DPO_NULL; + + dpo_set(&dpo, + DPO_CLASSIFY, + DPO_PROTO_IP4, + classify_dpo_create(FIB_PROTOCOL_IP4, + table_index)); + + fib_table_entry_special_dpo_add(fib_index, + &pfx, + FIB_SOURCE_CLASSIFY, + FIB_ENTRY_FLAG_NONE, + &dpo); + dpo_reset(&dpo); + } + else + { + fib_table_entry_special_remove(fib_index, + &pfx, + FIB_SOURCE_CLASSIFY); + } + } + return 0; } diff --git a/vnet/vnet/ip/ip6_neighbor.c b/vnet/vnet/ip/ip6_neighbor.c index 5d059e9b9cf..a03701b8e80 100644 --- a/vnet/vnet/ip/ip6_neighbor.c +++ b/vnet/vnet/ip/ip6_neighbor.c @@ -812,7 +812,8 @@ icmp6_neighbor_solicitation_or_advertisement (vlib_main_t * vm, 128); if (FIB_NODE_INDEX_INVALID == fei || - !(FIB_ENTRY_FLAG_LOCAL & fib_entry_get_flags(fei))) + !(FIB_ENTRY_FLAG_LOCAL & + fib_entry_get_flags_for_source(fei, FIB_SOURCE_INTERFACE))) { error0 = ICMP6_ERROR_NEIGHBOR_SOLICITATION_SOURCE_UNKNOWN; } -- 2.16.6