summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/memory.c1
-rw-r--r--lib/memory.h1
-rw-r--r--lib/prefix.c86
-rw-r--r--lib/prefix.h19
-rw-r--r--lib/table.c12
5 files changed, 112 insertions, 7 deletions
diff --git a/lib/memory.c b/lib/memory.c
index 90d7d420a..be8b100ba 100644
--- a/lib/memory.c
+++ b/lib/memory.c
@@ -26,6 +26,7 @@ struct memgroup **mg_insert = &mg_first;
DEFINE_MGROUP(LIB, "libfrr")
DEFINE_MTYPE(LIB, TMP, "Temporary memory")
+DEFINE_MTYPE(LIB, PREFIX_FLOWSPEC, "Prefix Flowspec")
static inline void mt_count_alloc(struct memtype *mt, size_t size)
{
diff --git a/lib/memory.h b/lib/memory.h
index 6de370514..1fbbbe423 100644
--- a/lib/memory.h
+++ b/lib/memory.h
@@ -127,6 +127,7 @@ struct memgroup {
DECLARE_MGROUP(LIB)
DECLARE_MTYPE(TMP)
+DECLARE_MTYPE(PREFIX_FLOWSPEC)
extern void *qmalloc(struct memtype *mt, size_t size)
diff --git a/lib/prefix.c b/lib/prefix.c
index 003ce992b..515b4dcb5 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. */
diff --git a/lib/prefix.h b/lib/prefix.h
index 133264f99..4efbc5a95 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -106,6 +106,15 @@ struct evpn_addr {
#define AF_EVPN (AF_MAX + 1)
#endif
+#if !defined(AF_FLOWSPEC)
+#define AF_FLOWSPEC (AF_MAX + 2)
+#endif
+
+struct flowspec_prefix {
+ uint16_t prefixlen; /* length in bytes */
+ uintptr_t ptr;
+};
+
/* FRR generic prefix structure. */
struct prefix {
uint8_t family;
@@ -122,6 +131,7 @@ struct prefix {
uint8_t val[16];
uintptr_t ptr;
struct evpn_addr prefix_evpn; /* AF_EVPN */
+ struct flowspec_prefix prefix_flowspec; /* AF_FLOWSPEC */
} u __attribute__((aligned(8)));
};
@@ -174,6 +184,13 @@ struct prefix_ptr {
uintptr_t prefix __attribute__((aligned(8)));
};
+/* Prefix for a Flowspec entry */
+struct prefix_fs {
+ uint8_t family;
+ uint8_t prefixlen; /* unused */
+ struct flowspec_prefix prefix __attribute__((aligned(8)));
+};
+
struct prefix_sg {
uint8_t family;
uint8_t prefixlen;
@@ -191,6 +208,7 @@ union prefixptr {
struct prefix_ipv4 *p4;
struct prefix_ipv6 *p6;
struct prefix_evpn *evp;
+ const struct prefix_fs *fs;
} __attribute__((transparent_union));
union prefixconstptr {
@@ -198,6 +216,7 @@ union prefixconstptr {
const struct prefix_ipv4 *p4;
const struct prefix_ipv6 *p6;
const struct prefix_evpn *evp;
+ const struct prefix_fs *fs;
} __attribute__((transparent_union));
#ifndef INET_ADDRSTRLEN
diff --git a/lib/table.c b/lib/table.c
index bf63609bc..3adb79389 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -152,10 +152,16 @@ static void route_common(const struct prefix *n, const struct prefix *p,
int i;
uint8_t diff;
uint8_t mask;
+ const uint8_t *np;
+ const uint8_t *pp;
+ uint8_t *newp;
- const uint8_t *np = (const uint8_t *)&n->u.prefix;
- const uint8_t *pp = (const uint8_t *)&p->u.prefix;
- uint8_t *newp = (uint8_t *)&new->u.prefix;
+ if (n->family == AF_FLOWSPEC)
+ return prefix_copy(new, p);
+ np = (const uint8_t *)&n->u.prefix;
+ pp = (const uint8_t *)&p->u.prefix;
+
+ newp = (uint8_t *)&new->u.prefix;
for (i = 0; i < p->prefixlen / 8; i++) {
if (np[i] == pp[i])