From: Alexander Chernavin Date: Wed, 26 May 2021 13:55:42 +0000 (-0400) Subject: nat: test all intf addrs in is_interface_addr() X-Git-Tag: v22.02-rc0~313 X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commitdiff_plain;h=d52a8921b85057682f2cf5bae7d6353142ba279a nat: test all intf addrs in is_interface_addr() Type: fix Currently, is_interface_addr() tests if a given IPv4 address belongs to an interface by a given sw_if_index. However, there are several issues: * only the first found address on the interface is actually tested, * sw_if_index is always cached even if the interface hasn't been assigned any addresses yet. With this change, is_interface_addr() tests all IPv4 addresses on an interface by a given sw_if_index and caches sw_if_index only if there are addresses present. Signed-off-by: Alexander Chernavin Change-Id: If1acc4a534647a5f0ce8e9b565b867c92a016dc3 --- diff --git a/src/plugins/nat/nat44-ed/nat44_ed.h b/src/plugins/nat/nat44-ed/nat44_ed.h index bbd5a148ed2..2710d29cb9d 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed.h +++ b/src/plugins/nat/nat44-ed/nat44_ed.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -683,7 +684,7 @@ typedef struct typedef struct { u32 cached_sw_if_index; - u32 cached_ip4_address; + uword *cached_presence_by_ip4_address; } snat_runtime_t; extern snat_main_t snat_main; diff --git a/src/plugins/nat/nat44-ed/nat44_ed_inlines.h b/src/plugins/nat/nat44-ed/nat44_ed_inlines.h index b2b578a5a8b..680bdef1f9f 100644 --- a/src/plugins/nat/nat44-ed/nat44_ed_inlines.h +++ b/src/plugins/nat/nat44-ed/nat44_ed_inlines.h @@ -724,20 +724,30 @@ is_interface_addr (snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0, u32 ip4_addr) { snat_runtime_t *rt = (snat_runtime_t *) node->runtime_data; - ip4_address_t *first_int_addr; + u8 ip4_addr_exists; if (PREDICT_FALSE (rt->cached_sw_if_index != sw_if_index0)) { - first_int_addr = ip4_interface_first_address ( - sm->ip4_main, sw_if_index0, 0 /* just want the address */); - rt->cached_sw_if_index = sw_if_index0; - if (first_int_addr) - rt->cached_ip4_address = first_int_addr->as_u32; - else - rt->cached_ip4_address = 0; + ip_lookup_main_t *lm = &sm->ip4_main->lookup_main; + ip_interface_address_t *ia; + ip4_address_t *a; + + rt->cached_sw_if_index = ~0; + hash_free (rt->cached_presence_by_ip4_address); + + foreach_ip_interface_address ( + lm, ia, sw_if_index0, 1 /* honor unnumbered */, ({ + a = ip_interface_address_get_address (lm, ia); + hash_set (rt->cached_presence_by_ip4_address, a->as_u32, 1); + rt->cached_sw_if_index = sw_if_index0; + })); + + if (rt->cached_sw_if_index == ~0) + return 0; } - if (PREDICT_FALSE (ip4_addr == rt->cached_ip4_address)) + ip4_addr_exists = !!hash_get (rt->cached_presence_by_ip4_address, ip4_addr); + if (PREDICT_FALSE (ip4_addr_exists)) return 1; else return 0; diff --git a/src/plugins/nat/nat44-ei/nat44_ei.h b/src/plugins/nat/nat44-ei/nat44_ei.h index ae63d9de050..055f81c069b 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei.h +++ b/src/plugins/nat/nat44-ei/nat44_ei.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -304,7 +305,7 @@ typedef struct typedef struct { u32 cached_sw_if_index; - u32 cached_ip4_address; + uword *cached_presence_by_ip4_address; } nat44_ei_runtime_t; typedef struct diff --git a/src/plugins/nat/nat44-ei/nat44_ei_inlines.h b/src/plugins/nat/nat44-ei/nat44_ei_inlines.h index 30935884ce7..672927256d1 100644 --- a/src/plugins/nat/nat44-ei/nat44_ei_inlines.h +++ b/src/plugins/nat/nat44-ei/nat44_ei_inlines.h @@ -118,20 +118,30 @@ nat44_ei_is_interface_addr (ip4_main_t *im, vlib_node_runtime_t *node, u32 sw_if_index0, u32 ip4_addr) { nat44_ei_runtime_t *rt = (nat44_ei_runtime_t *) node->runtime_data; - ip4_address_t *first_int_addr; + u8 ip4_addr_exists; if (PREDICT_FALSE (rt->cached_sw_if_index != sw_if_index0)) { - first_int_addr = ip4_interface_first_address ( - im, sw_if_index0, 0 /* just want the address */); - rt->cached_sw_if_index = sw_if_index0; - if (first_int_addr) - rt->cached_ip4_address = first_int_addr->as_u32; - else - rt->cached_ip4_address = 0; + ip_lookup_main_t *lm = &im->lookup_main; + ip_interface_address_t *ia; + ip4_address_t *a; + + rt->cached_sw_if_index = ~0; + hash_free (rt->cached_presence_by_ip4_address); + + foreach_ip_interface_address ( + lm, ia, sw_if_index0, 1 /* honor unnumbered */, ({ + a = ip_interface_address_get_address (lm, ia); + hash_set (rt->cached_presence_by_ip4_address, a->as_u32, 1); + rt->cached_sw_if_index = sw_if_index0; + })); + + if (rt->cached_sw_if_index == ~0) + return 0; } - if (PREDICT_FALSE (ip4_addr == rt->cached_ip4_address)) + ip4_addr_exists = !!hash_get (rt->cached_presence_by_ip4_address, ip4_addr); + if (PREDICT_FALSE (ip4_addr_exists)) return 1; else return 0;