diff options
Diffstat (limited to 'src/plugins/cnat/cnat_snat.c')
-rw-r--r-- | src/plugins/cnat/cnat_snat.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/src/plugins/cnat/cnat_snat.c b/src/plugins/cnat/cnat_snat.c index 86fac126226..21ac8257a23 100644 --- a/src/plugins/cnat/cnat_snat.c +++ b/src/plugins/cnat/cnat_snat.c @@ -101,6 +101,48 @@ cnat_del_snat_prefix (ip_prefix_t * pfx) return 0; } +int +cnat_search_snat_prefix (ip46_address_t * addr, ip_address_family_t af) +{ + /* Returns 0 if addr matches any of the listed prefixes */ + cnat_snat_pfx_table_t *table = &cnat_main.snat_pfx_table; + clib_bihash_kv_24_8_t kv, val; + int i, n_p, rv; + n_p = vec_len (table->meta[af].prefix_lengths_in_search_order); + if (AF_IP4 == af) + { + kv.key[0] = addr->ip4.as_u32; + kv.key[1] = 0; + } + else + { + kv.key[0] = addr->as_u64[0]; + kv.key[1] = addr->as_u64[1]; + } + + /* + * start search from a mask length same length or shorter. + * we don't want matches longer than the mask passed + */ + i = 0; + for (; i < n_p; i++) + { + int dst_address_length = + table->meta[af].prefix_lengths_in_search_order[i]; + ip6_address_t *mask = &table->ip_masks[dst_address_length]; + + ASSERT (dst_address_length >= 0 && dst_address_length <= 128); + /* As lengths are decreasing, masks are increasingly specific. */ + kv.key[0] &= mask->as_u64[0]; + kv.key[1] &= mask->as_u64[1]; + kv.key[2] = ((u64) af << 32) | dst_address_length; + rv = clib_bihash_search_inline_2_24_8 (&table->ip_hash, &kv, &val); + if (rv == 0) + return 0; + } + return -1; +} + u8 * format_cnat_snat_prefix (u8 * s, va_list * args) { |