diff options
-rw-r--r-- | bgpd/bgp_attr.c | 52 | ||||
-rw-r--r-- | bgpd/bgp_attr.h | 2 | ||||
-rw-r--r-- | bgpd/bgp_dump.c | 12 |
3 files changed, 55 insertions, 11 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 480bb912..91a0e07c 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1738,7 +1738,8 @@ bgp_attr_init () /* Make attribute packet. */ void -bgp_dump_routes_attr (struct stream *s, struct attr *attr) +bgp_dump_routes_attr (struct stream *s, struct attr *attr, + struct prefix *prefix) { unsigned long cp; unsigned long len; @@ -1773,10 +1774,18 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr) stream_put (s, aspath->data, aspath->length); /* Nexthop attribute. */ - stream_putc (s, BGP_ATTR_FLAG_TRANS); - stream_putc (s, BGP_ATTR_NEXT_HOP); - stream_putc (s, 4); - stream_put_ipv4 (s, attr->nexthop.s_addr); + /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */ + if(prefix != NULL +#ifdef HAVE_IPV6 + && prefix->family != AF_INET6 +#endif /* HAVE_IPV6 */ + ) + { + stream_putc (s, BGP_ATTR_FLAG_TRANS); + stream_putc (s, BGP_ATTR_NEXT_HOP); + stream_putc (s, 4); + stream_put_ipv4 (s, attr->nexthop.s_addr); + } /* MED attribute. */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) @@ -1832,6 +1841,39 @@ bgp_dump_routes_attr (struct stream *s, struct attr *attr) stream_put (s, attr->community->val, attr->community->size * 4); } +#ifdef HAVE_IPV6 + /* Add a MP_NLRI attribute to dump the IPv6 next hop */ + if(prefix != NULL && prefix->family == AF_INET6 && + (attr->mp_nexthop_len == 16 || attr->mp_nexthop_len == 32) ) + { + int sizep; + + stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); + stream_putc(s, BGP_ATTR_MP_REACH_NLRI); + sizep = stream_get_putp (s); + + /* MP header */ + stream_putc (s, 0); /* Length of this attribute. */ + stream_putw(s, AFI_IP6); /* AFI */ + stream_putc(s, SAFI_UNICAST); /* SAFI */ + + /* Next hop */ + stream_putc(s, attr->mp_nexthop_len); + stream_put(s, &attr->mp_nexthop_global, 16); + if(attr->mp_nexthop_len == 32) + stream_put(s, &attr->mp_nexthop_local, 16); + + /* SNPA */ + stream_putc(s, 0); + + /* Prefix */ + stream_put_prefix(s, prefix); + + /* Set MP attribute length. */ + stream_putc_at (s, sizep, (stream_get_putp (s) - sizep) - 1); + } +#endif /* HAVE_IPV6 */ + /* Return total size of attribute. */ len = stream_get_putp (s) - cp - 2; stream_putw_at (s, cp, len); diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index e44ff3a3..2bcbbf37 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -114,7 +114,7 @@ struct attr *bgp_attr_default_intern (u_char); struct attr *bgp_attr_aggregate_intern (struct bgp *, u_char, struct aspath *, struct community *, int as_set); bgp_size_t bgp_packet_attribute (struct bgp *bgp, struct peer *, struct stream *, struct attr *, struct prefix *, afi_t, safi_t, struct peer *, struct prefix_rd *, u_char *); bgp_size_t bgp_packet_withdraw (struct peer *peer, struct stream *s, struct prefix *p, afi_t, safi_t, struct prefix_rd *, u_char *); -void bgp_dump_routes_attr (struct stream *, struct attr *); +void bgp_dump_routes_attr (struct stream *, struct attr *, struct prefix *); unsigned int attrhash_key_make (struct attr *); int attrhash_cmp (struct attr *, struct attr *); void attr_show_all (struct vty *); diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c index 516e9b25..e3c62814 100644 --- a/bgpd/bgp_dump.c +++ b/bgpd/bgp_dump.c @@ -236,7 +236,7 @@ bgp_dump_routes_entry (struct prefix *p, struct bgp_info *info, int afi, stream_putw (obuf, peer->as); /* Dump attribute. */ - bgp_dump_routes_attr (obuf, attr); + bgp_dump_routes_attr (obuf, attr, NULL); } else { @@ -246,7 +246,7 @@ bgp_dump_routes_entry (struct prefix *p, struct bgp_info *info, int afi, stream_putc (obuf, p->prefixlen); plen = PSIZE (p->prefixlen); stream_put (obuf, &p->u.prefix4, plen); - bgp_dump_routes_attr (obuf, attr); + bgp_dump_routes_attr (obuf, attr, NULL); } } #ifdef HAVE_IPV6 @@ -272,7 +272,7 @@ bgp_dump_routes_entry (struct prefix *p, struct bgp_info *info, int afi, stream_putw (obuf, peer->as); /* Dump attribute. */ - bgp_dump_routes_attr (obuf, attr); + bgp_dump_routes_attr (obuf, attr, p); } else { @@ -330,7 +330,9 @@ bgp_dump_interval_func (struct thread *t) if (bgp_dump->type == BGP_DUMP_ROUTES) { bgp_dump_routes_func (AFI_IP); +#ifdef HAVE_IPV6 bgp_dump_routes_func (AFI_IP6); +#endif /* HAVE_IPV6 */ /* Close the file now. For a RIB dump there's no point in leaving * it open until the next scheduled dump starts. */ fclose(bgp_dump->fp); bgp_dump->fp = NULL; @@ -354,7 +356,7 @@ bgp_dump_common (struct stream *obuf, struct peer *peer) stream_putw (obuf, peer->as); stream_putw (obuf, peer->local_as); - if (peer->afc[AFI_IP][SAFI_UNICAST]) + if (peer->su.sa.sa_family == AF_INET) { stream_putw (obuf, peer->ifindex); stream_putw (obuf, AFI_IP); @@ -367,7 +369,7 @@ bgp_dump_common (struct stream *obuf, struct peer *peer) stream_put (obuf, empty, IPV4_MAX_BYTELEN); } #ifdef HAVE_IPV6 - else if (peer->afc[AFI_IP6][SAFI_UNICAST]) + else if (peer->su.sa.sa_family == AF_INET6) { /* Interface Index and Address family. */ stream_putw (obuf, peer->ifindex); |