summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c52
-rw-r--r--bgpd/bgp_attr.h2
-rw-r--r--bgpd/bgp_dump.c12
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);