vcc_acl: change compare functions to differentiate cases

This is in preparation of a follow-up commit to merge acl entries and
detect supersedes from supernets, but these changes are backwards
compatible with the previous CMP() if being used as a comparison
function for which only negative, zero and positive result are
relevant.

The A in CMPA() stands for "adjacent". CMPA() returns -3/3 for left
of/right of.
parent 245c768f
...@@ -74,14 +74,29 @@ struct acl_e { ...@@ -74,14 +74,29 @@ struct acl_e {
struct token *t_mask; struct token *t_mask;
}; };
/* Compare two acl rules for ordering */ /*
* Compare two acl rules for ordering
* returns:
* 0 same
* -1/1 strictly less/greater
* -2/2 b contains a / a contains b
* -3/3 a left of b / b left of a
*/
#define CMP(a, b) \ #define CMP(n, a, b) \
do { \ do { \
if ((a) < (b)) \ if ((a) < (b)) \
return (-1); \ return (-n); \
else if ((b) < (a)) \ else if ((b) < (a)) \
return (1); \ return (n); \
} while (0)
#define CMPA(a, b) \
do { \
if (((a) | 1) == (b)) \
return (-3); \
else if (((b) | 1) == (a)) \
return (3); \
} while (0) } while (0)
static void static void
...@@ -99,6 +114,7 @@ vcl_acl_cmp(const struct acl_e *ae1, const struct acl_e *ae2) ...@@ -99,6 +114,7 @@ vcl_acl_cmp(const struct acl_e *ae1, const struct acl_e *ae2)
{ {
const unsigned char *p1, *p2; const unsigned char *p1, *p2;
unsigned m; unsigned m;
unsigned char a1, a2;
CHECK_OBJ_NOTNULL(ae1, VCC_ACL_E_MAGIC); CHECK_OBJ_NOTNULL(ae1, VCC_ACL_E_MAGIC);
CHECK_OBJ_NOTNULL(ae2, VCC_ACL_E_MAGIC); CHECK_OBJ_NOTNULL(ae2, VCC_ACL_E_MAGIC);
...@@ -107,17 +123,22 @@ vcl_acl_cmp(const struct acl_e *ae1, const struct acl_e *ae2) ...@@ -107,17 +123,22 @@ vcl_acl_cmp(const struct acl_e *ae1, const struct acl_e *ae2)
p2 = ae2->data; p2 = ae2->data;
m = vmin_t(unsigned, ae1->mask, ae2->mask); m = vmin_t(unsigned, ae1->mask, ae2->mask);
for (; m >= 8; m -= 8) { for (; m >= 8; m -= 8) {
CMP(*p1, *p2); CMP(1, *p1, *p2);
p1++; p1++;
p2++; p2++;
} }
if (m) { if (m) {
m = 0xff00 >> m; assert (m < 8);
m &= 0xff; a1 = *p1 >> (8 - m);
CMP(*p1 & m, *p2 & m); a2 = *p2 >> (8 - m);
if (ae1->mask == ae2->mask)
CMPA(a1, a2);
CMP(1, a1, a2);
} else if (ae1->mask == ae2->mask) {
CMPA(*p1, *p2);
} }
/* Long mask is less than short mask */ /* Long mask is less than short mask */
CMP(ae2->mask, ae1->mask); CMP(2, ae2->mask, ae1->mask);
return (0); return (0);
} }
...@@ -135,14 +156,14 @@ vcl_acl_disjoint(const struct acl_e *ae1, const struct acl_e *ae2) ...@@ -135,14 +156,14 @@ vcl_acl_disjoint(const struct acl_e *ae1, const struct acl_e *ae2)
p2 = ae2->data; p2 = ae2->data;
m = vmin_t(unsigned, ae1->mask, ae2->mask); m = vmin_t(unsigned, ae1->mask, ae2->mask);
for (; m >= 8; m -= 8) { for (; m >= 8; m -= 8) {
CMP(*p1, *p2); CMP(1, *p1, *p2);
p1++; p1++;
p2++; p2++;
} }
if (m) { if (m) {
m = 0xff00 >> m; m = 0xff00 >> m;
m &= 0xff; m &= 0xff;
CMP(*p1 & m, *p2 & m); CMP(1, *p1 & m, *p2 & m);
} }
return (0); return (0);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment