Trie: Simplify network matching code
Introduce ipX_prefix_equal() and use it to simplify network matching code.
This commit is contained in:
parent
067f69a56d
commit
71c18d9f53
3 changed files with 90 additions and 16 deletions
|
@ -424,9 +424,6 @@ trie_add_prefix(struct f_trie *t, const net_addr *net, uint l, uint h)
|
||||||
static int
|
static int
|
||||||
trie_match_net4(const struct f_trie *t, ip4_addr px, uint plen)
|
trie_match_net4(const struct f_trie *t, ip4_addr px, uint plen)
|
||||||
{
|
{
|
||||||
ip4_addr pmask = ip4_mkmask(plen);
|
|
||||||
ip4_addr paddr = ip4_and(px, pmask);
|
|
||||||
|
|
||||||
if (plen == 0)
|
if (plen == 0)
|
||||||
return t->zero;
|
return t->zero;
|
||||||
|
|
||||||
|
@ -437,10 +434,8 @@ trie_match_net4(const struct f_trie *t, ip4_addr px, uint plen)
|
||||||
|
|
||||||
while (n)
|
while (n)
|
||||||
{
|
{
|
||||||
ip4_addr cmask = ip4_and(n->mask, pmask);
|
|
||||||
|
|
||||||
/* We are out of path */
|
/* We are out of path */
|
||||||
if (ip4_compare(ip4_and(paddr, cmask), ip4_and(n->addr, cmask)))
|
if (!ip4_prefix_equal(px, n->addr, MIN(plen, n->plen)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Check local mask */
|
/* Check local mask */
|
||||||
|
@ -452,11 +447,11 @@ trie_match_net4(const struct f_trie *t, ip4_addr px, uint plen)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* We finished trie walk and still no match */
|
/* We finished trie walk and still no match */
|
||||||
if (plen <= n->plen)
|
if (nlen <= n->plen)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Choose children */
|
/* Choose children */
|
||||||
n = n->c[ip4_getbits(paddr, n->plen, TRIE_STEP)];
|
n = n->c[ip4_getbits(px, n->plen, TRIE_STEP)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -465,9 +460,6 @@ trie_match_net4(const struct f_trie *t, ip4_addr px, uint plen)
|
||||||
static int
|
static int
|
||||||
trie_match_net6(const struct f_trie *t, ip6_addr px, uint plen)
|
trie_match_net6(const struct f_trie *t, ip6_addr px, uint plen)
|
||||||
{
|
{
|
||||||
ip6_addr pmask = ip6_mkmask(plen);
|
|
||||||
ip6_addr paddr = ip6_and(px, pmask);
|
|
||||||
|
|
||||||
if (plen == 0)
|
if (plen == 0)
|
||||||
return t->zero;
|
return t->zero;
|
||||||
|
|
||||||
|
@ -478,10 +470,8 @@ trie_match_net6(const struct f_trie *t, ip6_addr px, uint plen)
|
||||||
|
|
||||||
while (n)
|
while (n)
|
||||||
{
|
{
|
||||||
ip6_addr cmask = ip6_and(n->mask, pmask);
|
|
||||||
|
|
||||||
/* We are out of path */
|
/* We are out of path */
|
||||||
if (ip6_compare(ip6_and(paddr, cmask), ip6_and(n->addr, cmask)))
|
if (!ip6_prefix_equal(px, n->addr, MIN(plen, n->plen)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Check local mask */
|
/* Check local mask */
|
||||||
|
@ -493,11 +483,11 @@ trie_match_net6(const struct f_trie *t, ip6_addr px, uint plen)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* We finished trie walk and still no match */
|
/* We finished trie walk and still no match */
|
||||||
if (plen <= n->plen)
|
if (nlen <= n->plen)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Choose children */
|
/* Choose children */
|
||||||
n = n->c[ip6_getbits(paddr, n->plen, TRIE_STEP)];
|
n = n->c[ip6_getbits(px, n->plen, TRIE_STEP)];
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
18
lib/ip.h
18
lib/ip.h
|
@ -279,6 +279,24 @@ static inline uint ip6_pxlen(ip6_addr a, ip6_addr b)
|
||||||
return 32 * i + 31 - u32_log2(a.addr[i] ^ b.addr[i]);
|
return 32 * i + 31 - u32_log2(a.addr[i] ^ b.addr[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int ip4_prefix_equal(ip4_addr a, ip4_addr b, uint n)
|
||||||
|
{
|
||||||
|
return (_I(a) ^ _I(b)) < ((u64) 1 << (32 - n));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ip6_prefix_equal(ip6_addr a, ip6_addr b, uint n)
|
||||||
|
{
|
||||||
|
uint n0 = n / 32;
|
||||||
|
uint n1 = n % 32;
|
||||||
|
|
||||||
|
return
|
||||||
|
((n0 <= 0) || (_I0(a) == _I0(b))) &&
|
||||||
|
((n0 <= 1) || (_I1(a) == _I1(b))) &&
|
||||||
|
((n0 <= 2) || (_I2(a) == _I2(b))) &&
|
||||||
|
((n0 <= 3) || (_I3(a) == _I3(b))) &&
|
||||||
|
(!n1 || ((a.addr[n0] ^ b.addr[n0]) < (1u << (32 - n1))));
|
||||||
|
}
|
||||||
|
|
||||||
static inline u32 ip4_getbit(ip4_addr a, uint pos)
|
static inline u32 ip4_getbit(ip4_addr a, uint pos)
|
||||||
{ return (_I(a) >> (31 - pos)) & 1; }
|
{ return (_I(a) >> (31 - pos)) & 1; }
|
||||||
|
|
||||||
|
|
|
@ -167,6 +167,70 @@ t_ip6_ntop(void)
|
||||||
return bt_assert_batch(test_vectors, test_ipa_ntop, bt_fmt_ipa, bt_fmt_str);
|
return bt_assert_batch(test_vectors, test_ipa_ntop, bt_fmt_ipa, bt_fmt_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
t_ip4_prefix_equal(void)
|
||||||
|
{
|
||||||
|
bt_assert( ip4_prefix_equal(ip4_from_u32(0x12345678), ip4_from_u32(0x1234ffff), 16));
|
||||||
|
bt_assert(!ip4_prefix_equal(ip4_from_u32(0x12345678), ip4_from_u32(0x1234ffff), 17));
|
||||||
|
bt_assert( ip4_prefix_equal(ip4_from_u32(0x12345678), ip4_from_u32(0x12345000), 21));
|
||||||
|
bt_assert(!ip4_prefix_equal(ip4_from_u32(0x12345678), ip4_from_u32(0x12345000), 22));
|
||||||
|
|
||||||
|
bt_assert( ip4_prefix_equal(ip4_from_u32(0x00000000), ip4_from_u32(0xffffffff), 0));
|
||||||
|
bt_assert( ip4_prefix_equal(ip4_from_u32(0x12345678), ip4_from_u32(0x12345678), 0));
|
||||||
|
|
||||||
|
bt_assert( ip4_prefix_equal(ip4_from_u32(0x12345678), ip4_from_u32(0x12345678), 32));
|
||||||
|
bt_assert(!ip4_prefix_equal(ip4_from_u32(0x12345678), ip4_from_u32(0x12345679), 32));
|
||||||
|
bt_assert(!ip4_prefix_equal(ip4_from_u32(0x12345678), ip4_from_u32(0x92345678), 32));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
t_ip6_prefix_equal(void)
|
||||||
|
{
|
||||||
|
bt_assert( ip6_prefix_equal(ip6_build(0x20010db8, 0x12345678, 0x10101010, 0x20202020),
|
||||||
|
ip6_build(0x20010db8, 0x1234ffff, 0xfefefefe, 0xdcdcdcdc),
|
||||||
|
48));
|
||||||
|
|
||||||
|
bt_assert(!ip6_prefix_equal(ip6_build(0x20010db8, 0x12345678, 0x10101010, 0x20202020),
|
||||||
|
ip6_build(0x20010db8, 0x1234ffff, 0xfefefefe, 0xdcdcdcdc),
|
||||||
|
49));
|
||||||
|
|
||||||
|
bt_assert(!ip6_prefix_equal(ip6_build(0x20010db8, 0x12345678, 0x10101010, 0x20202020),
|
||||||
|
ip6_build(0x20020db8, 0x12345678, 0xfefefefe, 0xdcdcdcdc),
|
||||||
|
48));
|
||||||
|
|
||||||
|
bt_assert( ip6_prefix_equal(ip6_build(0x20010db8, 0x12345678, 0x10101010, 0x20202020),
|
||||||
|
ip6_build(0x20010db8, 0x12345678, 0xfefefefe, 0xdcdcdcdc),
|
||||||
|
64));
|
||||||
|
|
||||||
|
bt_assert(!ip6_prefix_equal(ip6_build(0x20010db8, 0x12345678, 0x10101010, 0x20202020),
|
||||||
|
ip6_build(0x20010db8, 0x1234567e, 0xfefefefe, 0xdcdcdcdc),
|
||||||
|
64));
|
||||||
|
|
||||||
|
bt_assert( ip6_prefix_equal(ip6_build(0x20010db8, 0x12345678, 0x10101010, 0x20002020),
|
||||||
|
ip6_build(0x20010db8, 0x12345678, 0x10101010, 0x20202020),
|
||||||
|
106));
|
||||||
|
|
||||||
|
bt_assert(!ip6_prefix_equal(ip6_build(0x20010db8, 0x12345678, 0x10101010, 0x20002020),
|
||||||
|
ip6_build(0x20010db8, 0x12345678, 0x10101010, 0x20202020),
|
||||||
|
107));
|
||||||
|
|
||||||
|
bt_assert( ip6_prefix_equal(ip6_build(0xfeef0db8, 0x87654321, 0x10101010, 0x20202020),
|
||||||
|
ip6_build(0x20010db8, 0x12345678, 0xfefefefe, 0xdcdcdcdc),
|
||||||
|
0));
|
||||||
|
|
||||||
|
bt_assert( ip6_prefix_equal(ip6_build(0x20010db8, 0x12345678, 0x10101010, 0x20202020),
|
||||||
|
ip6_build(0x20010db8, 0x12345678, 0x10101010, 0x20202020),
|
||||||
|
128));
|
||||||
|
|
||||||
|
bt_assert(!ip6_prefix_equal(ip6_build(0x20010db8, 0x12345678, 0x10101010, 0x20202020),
|
||||||
|
ip6_build(0x20010db8, 0x12345678, 0x10101010, 0x20202021),
|
||||||
|
128));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -176,6 +240,8 @@ main(int argc, char *argv[])
|
||||||
bt_test_suite(t_ip6_pton, "Converting IPv6 string to ip6_addr struct");
|
bt_test_suite(t_ip6_pton, "Converting IPv6 string to ip6_addr struct");
|
||||||
bt_test_suite(t_ip4_ntop, "Converting ip4_addr struct to IPv4 string");
|
bt_test_suite(t_ip4_ntop, "Converting ip4_addr struct to IPv4 string");
|
||||||
bt_test_suite(t_ip6_ntop, "Converting ip6_addr struct to IPv6 string");
|
bt_test_suite(t_ip6_ntop, "Converting ip6_addr struct to IPv6 string");
|
||||||
|
bt_test_suite(t_ip4_prefix_equal, "Testing ip4_prefix_equal()");
|
||||||
|
bt_test_suite(t_ip6_prefix_equal, "Testing ip6_prefix_equal()");
|
||||||
|
|
||||||
return bt_exit_value();
|
return bt_exit_value();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue