From 93b73dfa1783276371d71e3520e6d2d19460f5d6 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Tue, 12 Jan 2016 13:41:59 -0500 Subject: [PATCH] bgpd: general MP/SAFI improvements This fixes some minor mixups particularly in MPLS-related SAFIs, as well as doing some stylistic changes & adding comments. Signed-off-by: Lou Berger Reviewed-by: David Lamparter (cherry picked from commit 050defe816e4bd4cac7b028f69e45cb1974ca96d) Conflicts: bgpd/bgp_attr.c bgpd/bgp_attr.h bgpd/bgp_packet.c bgpd/bgp_route.c bgpd/bgp_route.h --- bgpd/bgp_attr.c | 67 ++++++++++++++++++++++++++-------------- bgpd/bgp_attr.h | 2 ++ bgpd/bgp_mplsvpn.c | 19 +++--------- bgpd/bgp_mplsvpn.h | 1 - bgpd/bgp_routemap.c | 1 + bgpd/bgp_updgrp_packet.c | 17 +++++++--- 6 files changed, 64 insertions(+), 43 deletions(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index ad8c7641e4..2ffe464f0a 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -2208,8 +2208,9 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi, stream_putc (s, BGP_ATTR_MP_REACH_NLRI); sizep = stream_get_endp (s); stream_putw (s, 0); /* Marker: Attribute length. */ - stream_putw (s, afi); /* AFI */ - stream_putc (s, safi); /* SAFI */ + + stream_putw (s, afi); + stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi); /* Nexthop */ switch (nh_afi) @@ -2217,7 +2218,6 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi, case AFI_IP: switch (safi) { - case SAFI_UNICAST: case SAFI_MULTICAST: bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr); stream_putc (s, 4); @@ -2226,10 +2226,11 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi, case SAFI_MPLS_VPN: bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr); stream_putc (s, 12); - stream_putl (s, 0); + stream_putl (s, 0); /* RD = 0, per RFC */ stream_putl (s, 0); stream_put (s, &attr->extra->mp_nexthop_global_in, 4); break; + case SAFI_UNICAST: /* invalid for IPv4 */ default: break; } @@ -2250,6 +2251,28 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi, if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) stream_put (s, &attre->mp_nexthop_local, IPV6_MAX_BYTELEN); } + break; + case SAFI_MPLS_VPN: + { + struct attr_extra *attre = attr->extra; + + assert (attr->extra); + if (attre->mp_nexthop_len == 16) { + stream_putc (s, 24); + stream_putl (s, 0); /* RD = 0, per RFC */ + stream_putl (s, 0); + stream_put (s, &attre->mp_nexthop_global, 16); + } else if (attre->mp_nexthop_len == 32) { + stream_putc (s, 48); + stream_putl (s, 0); /* RD = 0, per RFC */ + stream_putl (s, 0); + stream_put (s, &attre->mp_nexthop_global, 16); + stream_putl (s, 0); /* RD = 0, per RFC */ + stream_putl (s, 0); + stream_put (s, &attre->mp_nexthop_local, 16); + } + } + break; default: break; } @@ -2270,24 +2293,27 @@ bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi, u_char *tag, int addpath_encode, u_int32_t addpath_tx_id) { - switch (safi) + if (safi == SAFI_MPLS_VPN) { - case SAFI_MPLS_VPN: - /* addpath TX ID */ if (addpath_encode) stream_putl(s, addpath_tx_id); - /* Tag, RD, Prefix write. */ stream_putc (s, p->prefixlen + 88); stream_put (s, tag, 3); stream_put (s, prd->val, 8); stream_put (s, &p->u.prefix, PSIZE (p->prefixlen)); - break; - default: - /* Prefix write. */ - stream_put_prefix_addpath (s, p, addpath_encode, addpath_tx_id); - break; } + else + stream_put_prefix_addpath (s, p, addpath_encode, addpath_tx_id); +} + +size_t +bgp_packet_mpattr_prefix_size (afi_t afi, safi_t safi, struct prefix *p) +{ + int size = PSIZE (p->prefixlen); + if (safi == SAFI_MPLS_VPN) + size += 88; + return size; } void @@ -2314,7 +2340,6 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, int send_as4_path = 0; int send_as4_aggregator = 0; int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0; - size_t mpattrlen_pos = 0; if (! bgp) bgp = peer->bgp; @@ -2325,6 +2350,8 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, if (p && !((afi == AFI_IP && safi == SAFI_UNICAST) && !peer_cap_enhe(peer))) { + size_t mpattrlen_pos = 0; + mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, (peer_cap_enhe(peer) ? AFI_IP6 : afi), vecarr, attr); @@ -2403,7 +2430,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, send_as4_path = 1; /* we'll do this later, at the correct place */ /* Nexthop attribute. */ - if (afi == AFI_IP && !peer_cap_enhe(peer)) + if (afi == AFI_IP && safi == SAFI_UNICAST && !peer_cap_enhe(peer)) { if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)) { @@ -2689,8 +2716,7 @@ bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi) stream_putw (s, 0); /* Length of this attribute. */ stream_putw (s, afi); - safi = (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi; - stream_putc (s, safi); + stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi); return attrlen_pnt; } @@ -2718,12 +2744,7 @@ bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p, void bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt) { - bgp_size_t size; - - /* Set MP attribute length. Don't count the (2) bytes used to encode - the attr length */ - size = stream_get_endp (s) - attrlen_pnt - 2; - stream_putw_at (s, attrlen_pnt, size); + bgp_packet_mpattr_end (s, attrlen_pnt); } /* Initialization of attribute. */ diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index da9bfec497..5cd6b8544a 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -239,6 +239,8 @@ extern void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi, struct prefix *p, struct prefix_rd *prd, u_char *tag, int addpath_encode, u_int32_t addpath_tx_id); +extern size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi, + struct prefix *p); extern void bgp_packet_mpattr_end(struct stream *s, size_t sizep); extern size_t bgp_packet_mpunreach_start (struct stream *s, afi_t afi, diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 9f27c9addb..00f8221bcb 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -206,13 +206,10 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr, decode_rd_ip (pnt + 5, &rd_ip); break; - case RD_TYPE_EOI: - break; - - default: - zlog_err ("Invalid RD type %d", type); - return -1; - } + default: + zlog_err ("Unknown RD type %d", type); + break; /* just report */ + } p.prefixlen = prefixlen - VPN_PREFIXLEN_MIN_BYTES*8; memcpy (&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES, @@ -348,14 +345,6 @@ prefix_rd2str (struct prefix_rd *prd, char *buf, size_t size) snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val); return buf; } - else if (type == RD_TYPE_EOI) - { - snprintf(buf, size, "LHI:%d, %02x:%02x:%02x:%02x:%02x:%02x", - pnt[1], /* LHI */ - pnt[2], pnt[3], pnt[4], pnt[5], pnt[6], pnt[7]); /* MAC */ - return buf; - } - return NULL; } diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 4e9b317b71..3299b9cb9a 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -24,7 +24,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #define RD_TYPE_AS 0 #define RD_TYPE_IP 1 #define RD_TYPE_AS4 2 -#define RD_TYPE_EOI 0xff00 #define RD_ADDRSTRLEN 28 diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 11b6919bf2..3018d074fc 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -2369,6 +2369,7 @@ route_set_vpnv4_nexthop (void *rule, struct prefix *prefix, /* Set next hop value. */ (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_global_in = *address; + (bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_len = 4; } return RMAP_OKAY; diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 9577d1b19e..63f88e932e 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -666,7 +666,8 @@ subgroup_update_packet (struct update_subgroup *subgrp) space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) - BGP_MAX_PACKET_SIZE_OVERFLOW; - space_needed = BGP_NLRI_LENGTH + PSIZE (rn->p.prefixlen); + space_needed = BGP_NLRI_LENGTH + + bgp_packet_mpattr_prefix_size (afi, safi, &rn->p); /* When remaining space can't include NLRI and it's length. */ if (space_remaining < space_needed) @@ -675,10 +676,18 @@ subgroup_update_packet (struct update_subgroup *subgrp) /* If packet is empty, set attribute. */ if (stream_empty (s)) { + struct prefix_rd *prd = NULL; + u_char *tag = NULL; struct peer *from = NULL; + if (rn->prn) + prd = (struct prefix_rd *) &rn->prn->p; if (binfo) - from = binfo->peer; + { + from = binfo->peer; + if (binfo->extra) + tag = binfo->extra->tag; + } /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length, * one byte message type. @@ -701,8 +710,8 @@ subgroup_update_packet (struct update_subgroup *subgrp) /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */ total_attr_len = bgp_packet_attribute (NULL, peer, s, adv->baa->attr, &vecarr, - NULL, afi, safi, - from, NULL, NULL, 0, 0); + &rn->p, afi, safi, + from, prd, tag, 0, 0); space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) - BGP_MAX_PACKET_SIZE_OVERFLOW; -- 2.39.5