Normalize community sets when exporting.
Set PARTIAL bits correctly.
This commit is contained in:
parent
51a183af78
commit
e3558ab14e
1 changed files with 22 additions and 10 deletions
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#define LOCAL_DEBUG
|
#define LOCAL_DEBUG
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
#include "nest/iface.h"
|
#include "nest/iface.h"
|
||||||
#include "nest/protocol.h"
|
#include "nest/protocol.h"
|
||||||
|
@ -123,6 +125,7 @@ bgp_encode_attrs(byte *w, struct bgp_bucket *buck)
|
||||||
eattr *a = &buck->eattrs->attrs[i];
|
eattr *a = &buck->eattrs->attrs[i];
|
||||||
ASSERT(EA_PROTO(a->id) == EAP_BGP);
|
ASSERT(EA_PROTO(a->id) == EAP_BGP);
|
||||||
code = EA_ID(a->id);
|
code = EA_ID(a->id);
|
||||||
|
flags = a->flags & (BAF_OPTIONAL | BAF_TRANSITIVE | BAF_PARTIAL);
|
||||||
if (code && code < ARRAY_SIZE(bgp_attr_table))
|
if (code && code < ARRAY_SIZE(bgp_attr_table))
|
||||||
{
|
{
|
||||||
struct attr_desc *desc = &bgp_attr_table[code];
|
struct attr_desc *desc = &bgp_attr_table[code];
|
||||||
|
@ -138,14 +141,12 @@ bgp_encode_attrs(byte *w, struct bgp_bucket *buck)
|
||||||
ASSERT((a->type & EAF_TYPE_MASK) == EAF_TYPE_OPAQUE);
|
ASSERT((a->type & EAF_TYPE_MASK) == EAF_TYPE_OPAQUE);
|
||||||
len = a->u.ptr->length;
|
len = a->u.ptr->length;
|
||||||
}
|
}
|
||||||
DBG("\tAttribute %02x (type %02x, %d bytes)\n", code, a->type, len);
|
DBG("\tAttribute %02x (type %02x, %d bytes, flags %02x)\n", code, a->type, len, flags);
|
||||||
/* FIXME: Partial bit for locally added transitive attributes */
|
|
||||||
if (remains < len + 4)
|
if (remains < len + 4)
|
||||||
{
|
{
|
||||||
log(L_ERR "BGP: attribute list too long, ignoring the remaining attributes");
|
log(L_ERR "BGP: attribute list too long, ignoring the remaining attributes");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
flags = a->flags & (BAF_OPTIONAL | BAF_TRANSITIVE | BAF_PARTIAL);
|
|
||||||
if (len < 256)
|
if (len < 256)
|
||||||
{
|
{
|
||||||
*w++ = flags;
|
*w++ = flags;
|
||||||
|
@ -206,11 +207,17 @@ bgp_init_prefix(struct fib_node *N)
|
||||||
p->bucket_node.next = NULL;
|
p->bucket_node.next = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bgp_compare_u32(const u32 *x, const u32 *y)
|
||||||
|
{
|
||||||
|
return (*x < *y) ? -1 : (*x > *y) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
bgp_normalize_set(u32 *dest, u32 *src, unsigned cnt)
|
bgp_normalize_set(u32 *dest, u32 *src, unsigned cnt)
|
||||||
{
|
{
|
||||||
memcpy(dest, src, sizeof(u32) * cnt);
|
memcpy(dest, src, sizeof(u32) * cnt);
|
||||||
/* FIXME */
|
qsort(dest, cnt, sizeof(u32), (int(*)(const void *, const void *)) bgp_compare_u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -298,7 +305,7 @@ bgp_new_bucket(struct bgp_proto *p, ea_list *new, unsigned hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct bgp_bucket *
|
static struct bgp_bucket *
|
||||||
bgp_get_bucket(struct bgp_proto *p, ea_list *old, ea_list *tmp)
|
bgp_get_bucket(struct bgp_proto *p, ea_list *old, ea_list *tmp, int originate)
|
||||||
{
|
{
|
||||||
ea_list *t, *new;
|
ea_list *t, *new;
|
||||||
unsigned i, cnt;
|
unsigned i, cnt;
|
||||||
|
@ -335,9 +342,11 @@ bgp_get_bucket(struct bgp_proto *p, ea_list *old, ea_list *tmp)
|
||||||
if (EA_ID(a->id) < 32)
|
if (EA_ID(a->id) < 32)
|
||||||
seen |= 1 << EA_ID(a->id);
|
seen |= 1 << EA_ID(a->id);
|
||||||
*d = *a;
|
*d = *a;
|
||||||
|
if ((d->type & EAF_ORIGINATED) && !originate && (d->flags & BAF_TRANSITIVE) && (d->flags & BAF_OPTIONAL))
|
||||||
|
d->flags |= BAF_PARTIAL;
|
||||||
switch (d->type & EAF_TYPE_MASK)
|
switch (d->type & EAF_TYPE_MASK)
|
||||||
{
|
{
|
||||||
case EAF_TYPE_INT_SET: /* FIXME: Normalize the other attributes? */
|
case EAF_TYPE_INT_SET:
|
||||||
{
|
{
|
||||||
struct adata *z = alloca(sizeof(struct adata) + d->u.ptr->length);
|
struct adata *z = alloca(sizeof(struct adata) + d->u.ptr->length);
|
||||||
z->length = d->u.ptr->length;
|
z->length = d->u.ptr->length;
|
||||||
|
@ -402,7 +411,7 @@ bgp_rt_notify(struct proto *P, net *n, rte *new, rte *old, ea_list *tmpa)
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
buck = bgp_get_bucket(p, new->attrs->eattrs, tmpa);
|
buck = bgp_get_bucket(p, new->attrs->eattrs, tmpa, new->attrs->source != RTS_BGP);
|
||||||
if (!buck) /* Inconsistent attribute list */
|
if (!buck) /* Inconsistent attribute list */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -682,7 +691,7 @@ bgp_decode_attrs(struct bgp_conn *conn, byte *attr, unsigned int len, struct lin
|
||||||
type = desc->type;
|
type = desc->type;
|
||||||
}
|
}
|
||||||
else /* Unknown attribute */
|
else /* Unknown attribute */
|
||||||
{ /* FIXME: Send partial bit when forwarding */
|
{
|
||||||
if (!(flags & BAF_OPTIONAL))
|
if (!(flags & BAF_OPTIONAL))
|
||||||
{ errcode = 2; goto err; }
|
{ errcode = 2; goto err; }
|
||||||
type = EAF_TYPE_OPAQUE;
|
type = EAF_TYPE_OPAQUE;
|
||||||
|
@ -756,7 +765,10 @@ bgp_decode_attrs(struct bgp_conn *conn, byte *attr, unsigned int len, struct lin
|
||||||
e = ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
|
e = ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_AS_PATH));
|
||||||
ASSERT(e);
|
ASSERT(e);
|
||||||
if (bgp_path_loopy(bgp, e))
|
if (bgp_path_loopy(bgp, e))
|
||||||
|
{
|
||||||
|
DBG("BGP: Path loop!\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Fill in the remaining rta fields */
|
/* Fill in the remaining rta fields */
|
||||||
e = ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP));
|
e = ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP));
|
||||||
|
@ -764,7 +776,7 @@ bgp_decode_attrs(struct bgp_conn *conn, byte *attr, unsigned int len, struct lin
|
||||||
nexthop = *(ip_addr *) e->u.ptr->data;
|
nexthop = *(ip_addr *) e->u.ptr->data;
|
||||||
if (ipa_equal(nexthop, bgp->local_addr))
|
if (ipa_equal(nexthop, bgp->local_addr))
|
||||||
{
|
{
|
||||||
DBG("BGP: Loop!\n"); /* FIXME */
|
DBG("BGP: Loop!\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
neigh = neigh_find(&bgp->p, &nexthop, 0) ? : bgp->neigh;
|
neigh = neigh_find(&bgp->p, &nexthop, 0) ? : bgp->neigh;
|
||||||
|
|
Loading…
Reference in a new issue