mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-02 18:52:04 +00:00
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>
This commit is contained in:
parent
46f1e1ee96
commit
9a14899b0a
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
86
lib/prefix.c
86
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(©, 0, sizeof(copy));
|
||||
prefix_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. */
|
||||
|
19
lib/prefix.h
19
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
|
||||
|
12
lib/table.c
12
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])
|
||||
|
Loading…
Reference in New Issue
Block a user