MRT: Fix IPv6 table dumps
Add fake MP_REACH_NLRI attribute with BGP next hop when encoding MRT table dumps for IPv6 routes. That is necessary to encode next hop as NEXT_HOP attribute is not used for MP-BGP. Thanks to Santiago Aggio for the bugreport.
This commit is contained in:
parent
910adaa08b
commit
d774f6d721
3 changed files with 77 additions and 19 deletions
|
@ -683,6 +683,37 @@ bgp_format_cluster_list(const eattr *a, byte *buf, uint size)
|
|||
}
|
||||
|
||||
|
||||
int
|
||||
bgp_encode_mp_reach_mrt(struct bgp_write_state *s UNUSED, eattr *a, byte *buf, uint size)
|
||||
{
|
||||
/*
|
||||
* Limited version of MP_REACH_NLRI used for MRT table dumps (IPv6 only):
|
||||
*
|
||||
* 3 B MP_REACH_NLRI header
|
||||
* 1 B MP_REACH_NLRI data - Length of Next Hop Network Address
|
||||
* var MP_REACH_NLRI data - Network Address of Next Hop
|
||||
*/
|
||||
|
||||
ip_addr *nh = (void *) a->u.ptr->data;
|
||||
uint len = a->u.ptr->length;
|
||||
|
||||
ASSERT((len == 16) || (len == 32));
|
||||
|
||||
if (size < (3+1+len))
|
||||
return -1;
|
||||
|
||||
bgp_put_attr_hdr3(buf, BA_MP_REACH_NLRI, BAF_OPTIONAL, 1+len);
|
||||
buf[3] = len;
|
||||
buf += 4;
|
||||
|
||||
put_ip6(buf, ipa_to_ip6(nh[0]));
|
||||
|
||||
if (len == 32)
|
||||
put_ip6(buf+16, ipa_to_ip6(nh[1]));
|
||||
|
||||
return 3+1+len;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
get_af3(byte *buf)
|
||||
{
|
||||
|
|
|
@ -559,6 +559,7 @@ static inline void
|
|||
bgp_unset_attr(ea_list **to, struct linpool *pool, uint code)
|
||||
{ eattr *e = bgp_set_attr(to, pool, code, 0, 0); e->type = EAF_TYPE_UNDEF; }
|
||||
|
||||
int bgp_encode_mp_reach_mrt(struct bgp_write_state *s, eattr *a, byte *buf, uint size);
|
||||
|
||||
int bgp_encode_attrs(struct bgp_write_state *s, ea_list *attrs, byte *buf, byte *end);
|
||||
ea_list * bgp_decode_attrs(struct bgp_parse_state *s, byte *data, uint len);
|
||||
|
|
|
@ -417,6 +417,50 @@ mrt_rib_table_header(struct mrt_table_dump_state *s, net_addr *n)
|
|||
mrt_put_u16(b, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BGP
|
||||
static void
|
||||
mrt_rib_table_entry_bgp_attrs(struct mrt_table_dump_state *s, rte *r)
|
||||
{
|
||||
struct ea_list *eattrs = r->attrs->eattrs;
|
||||
buffer *b = &s->buf;
|
||||
|
||||
if (!eattrs)
|
||||
return;
|
||||
|
||||
/* Attribute list must be normalized for bgp_encode_attrs() */
|
||||
if (!rta_is_cached(r->attrs))
|
||||
ea_normalize(eattrs);
|
||||
|
||||
mrt_buffer_need(b, MRT_ATTR_BUFFER_SIZE);
|
||||
byte *pos = b->pos;
|
||||
|
||||
s->bws->mp_next_hop = NULL;
|
||||
|
||||
/* Encode BGP attributes */
|
||||
int len = bgp_encode_attrs(s->bws, eattrs, pos, b->end);
|
||||
if (len < 0)
|
||||
goto fail;
|
||||
pos += len;
|
||||
|
||||
/* Encode IPv6 next hop separately as fake MP_REACH_NLRI attribute */
|
||||
if (s->bws->mp_next_hop)
|
||||
{
|
||||
len = bgp_encode_mp_reach_mrt(s->bws, s->bws->mp_next_hop, pos, b->end - pos);
|
||||
if (len < 0)
|
||||
goto fail;
|
||||
pos += len;
|
||||
}
|
||||
|
||||
/* Update attribute length and advance buffer pos */
|
||||
put_u16(b->pos - 2, pos - b->pos);
|
||||
b->pos = pos;
|
||||
return;
|
||||
|
||||
fail:
|
||||
mrt_log(s, "Attribute list too long for %N", r->net->n.addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
mrt_rib_table_entry(struct mrt_table_dump_state *s, rte *r)
|
||||
{
|
||||
|
@ -447,25 +491,7 @@ mrt_rib_table_entry(struct mrt_table_dump_state *s, rte *r)
|
|||
mrt_put_u16(b, 0);
|
||||
|
||||
#ifdef CONFIG_BGP
|
||||
if (r->attrs->eattrs)
|
||||
{
|
||||
struct ea_list *eattrs = r->attrs->eattrs;
|
||||
|
||||
if (!rta_is_cached(r->attrs))
|
||||
ea_normalize(eattrs);
|
||||
|
||||
mrt_buffer_need(b, MRT_ATTR_BUFFER_SIZE);
|
||||
int alen = bgp_encode_attrs(s->bws, eattrs, b->pos, b->end);
|
||||
|
||||
if (alen < 0)
|
||||
{
|
||||
mrt_log(s, "Attribute list too long for %N", r->net->n.addr);
|
||||
alen = 0;
|
||||
}
|
||||
|
||||
put_u16(b->pos - 2, alen);
|
||||
b->pos += alen;
|
||||
}
|
||||
mrt_rib_table_entry_bgp_attrs(s, r);
|
||||
#endif
|
||||
|
||||
s->entry_count++;
|
||||
|
|
Loading…
Reference in a new issue