summaryrefslogtreecommitdiff
path: root/lib/prefix.c
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2018-01-10 19:13:27 +0100
committerPhilippe Guibert <philippe.guibert@6wind.com>2018-03-30 14:00:47 +0200
commit9a14899b0ac8f3d9d0ce077127568f215c301f6a (patch)
tree177eadb198e40a532c4ae6d9a2f72ab2825df5cd /lib/prefix.c
parent46f1e1ee964e6408fbae477b824e8ed18cb357d6 (diff)
lib: prefix support for flowspec
prefix structure is used to handle flowspec prefixes. A new AFI is introduced: AF_FLOWSPEC. A sub structure named flowspec_prefix is used in prefix to host the flowspec entry. Reason to introduce that new kind is that prefixlen from prefix structure is too short to all the flowspec needs, since NLRI can go over 0xff bytes. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Diffstat (limited to 'lib/prefix.c')
-rw-r--r--lib/prefix.c86
1 files changed, 82 insertions, 4 deletions
diff --git a/lib/prefix.c b/lib/prefix.c
index 003ce992b4..515b4dcb5e 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -539,6 +539,24 @@ int prefix_match(const struct prefix *n, const struct prefix *p)
if (n->prefixlen > p->prefixlen)
return 0;
+ if (n->family == AF_FLOWSPEC) {
+ /* prefixlen is unused. look at fs prefix len */
+ if (n->u.prefix_flowspec.prefixlen >
+ p->u.prefix_flowspec.prefixlen)
+ return 0;
+
+ /* Set both prefix's head pointer. */
+ np = (const uint8_t *)&n->u.prefix_flowspec.ptr;
+ pp = (const uint8_t *)&p->u.prefix_flowspec.ptr;
+
+ offset = n->u.prefix_flowspec.prefixlen;
+
+ while (offset--)
+ if (np[offset] != pp[offset])
+ return 0;
+ return 1;
+ }
+
/* Set both prefix's head pointer. */
np = (const uint8_t *)&n->u.prefix;
pp = (const uint8_t *)&p->u.prefix;
@@ -581,7 +599,6 @@ int prefix_match_network_statement(const struct prefix *n,
return 1;
}
-/* Copy prefix from src to dest. */
void prefix_copy(struct prefix *dest, const struct prefix *src)
{
dest->family = src->family;
@@ -600,6 +617,18 @@ void prefix_copy(struct prefix *dest, const struct prefix *src)
} else if (src->family == AF_UNSPEC) {
dest->u.lp.id = src->u.lp.id;
dest->u.lp.adv_router = src->u.lp.adv_router;
+ } else if (src->family == AF_FLOWSPEC) {
+ void *temp;
+ int len;
+
+ len = src->u.prefix_flowspec.prefixlen;
+ dest->u.prefix_flowspec.prefixlen =
+ src->u.prefix_flowspec.prefixlen;
+ dest->family = src->family;
+ temp = XCALLOC(MTYPE_PREFIX_FLOWSPEC, len);
+ dest->u.prefix_flowspec.ptr = (uintptr_t)temp;
+ memcpy((void *)dest->u.prefix_flowspec.ptr,
+ (void *)src->u.prefix_flowspec.ptr, len);
} else {
zlog_err("prefix_copy(): Unknown address family %d",
src->family);
@@ -639,6 +668,15 @@ int prefix_same(const struct prefix *p1, const struct prefix *p2)
if (!memcmp(&p1->u.prefix_evpn, &p2->u.prefix_evpn,
sizeof(struct evpn_addr)))
return 1;
+ if (p1->family == AF_FLOWSPEC) {
+ if (p1->u.prefix_flowspec.prefixlen !=
+ p2->u.prefix_flowspec.prefixlen)
+ return 0;
+ if (!memcmp(&p1->u.prefix_flowspec.ptr,
+ &p2->u.prefix_flowspec.ptr,
+ p2->u.prefix_flowspec.prefixlen))
+ return 1;
+ }
}
return 0;
}
@@ -659,12 +697,30 @@ int prefix_cmp(const struct prefix *p1, const struct prefix *p2)
int shift;
/* Set both prefix's head pointer. */
- const uint8_t *pp1 = (const uint8_t *)&p1->u.prefix;
- const uint8_t *pp2 = (const uint8_t *)&p2->u.prefix;
+ const uint8_t *pp1;
+ const uint8_t *pp2;
- if (p1->family != p2->family || p1->prefixlen != p2->prefixlen)
+ if (p1->family != p2->family)
return 1;
+ if (p1->family == AF_FLOWSPEC) {
+ pp1 = (const uint8_t *)p1->u.prefix_flowspec.ptr;
+ pp2 = (const uint8_t *)p2->u.prefix_flowspec.ptr;
+ if (p1->u.prefix_flowspec.prefixlen !=
+ p2->u.prefix_flowspec.prefixlen)
+ return 1;
+
+ offset = p1->u.prefix_flowspec.prefixlen;
+ while (offset--)
+ if (pp1[offset] != pp2[offset])
+ return 1;
+ return 0;
+ }
+ pp1 = (const uint8_t *)&p1->u.prefix;
+ pp2 = (const uint8_t *)&p2->u.prefix;
+
+ if (p1->prefixlen != p2->prefixlen)
+ return 1;
offset = p1->prefixlen / PNBBY;
shift = p1->prefixlen % PNBBY;
@@ -1207,6 +1263,10 @@ const char *prefix2str(union prefixconstptr pu, char *str, int size)
prefixevpn2str(p, str, size);
break;
+ case AF_FLOWSPEC:
+ sprintf(str, "FS prefix");
+ break;
+
default:
sprintf(str, "UNK prefix");
break;
@@ -1386,6 +1446,24 @@ unsigned prefix_hash_key(void *pp)
{
struct prefix copy;
+ if (((struct prefix *)pp)->family == AF_FLOWSPEC) {
+ uint32_t len;
+ void *temp;
+
+ /* make sure *all* unused bits are zero,
+ * particularly including alignment /
+ * padding and unused prefix bytes.
+ */
+ memset(&copy, 0, sizeof(copy));
+ prefix_copy(&copy, (struct prefix *)pp);
+ len = jhash((void *)copy.u.prefix_flowspec.ptr,
+ copy.u.prefix_flowspec.prefixlen,
+ 0x55aa5a5a);
+ temp = (void *)copy.u.prefix_flowspec.ptr;
+ XFREE(MTYPE_PREFIX_FLOWSPEC, temp);
+ copy.u.prefix_flowspec.ptr = (uintptr_t)NULL;
+ return len;
+ }
/* make sure *all* unused bits are zero, particularly including
* alignment /
* padding and unused prefix bytes. */