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 <lberger@labn.net>
Reviewed-by: David Lamparter <equinox@opensourcerouting.org>
(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
This commit is contained in:
Lou Berger 2016-01-12 13:41:59 -05:00 committed by vivek
parent 005b6bc0ab
commit 93b73dfa17
6 changed files with 64 additions and 43 deletions

View File

@ -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); stream_putc (s, BGP_ATTR_MP_REACH_NLRI);
sizep = stream_get_endp (s); sizep = stream_get_endp (s);
stream_putw (s, 0); /* Marker: Attribute length. */ 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 */ /* Nexthop */
switch (nh_afi) 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: case AFI_IP:
switch (safi) switch (safi)
{ {
case SAFI_UNICAST:
case SAFI_MULTICAST: case SAFI_MULTICAST:
bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr); bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr);
stream_putc (s, 4); 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: case SAFI_MPLS_VPN:
bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr); bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr);
stream_putc (s, 12); stream_putc (s, 12);
stream_putl (s, 0); stream_putl (s, 0); /* RD = 0, per RFC */
stream_putl (s, 0); stream_putl (s, 0);
stream_put (s, &attr->extra->mp_nexthop_global_in, 4); stream_put (s, &attr->extra->mp_nexthop_global_in, 4);
break; break;
case SAFI_UNICAST: /* invalid for IPv4 */
default: default:
break; 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) if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
stream_put (s, &attre->mp_nexthop_local, IPV6_MAX_BYTELEN); 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: default:
break; 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_char *tag, int addpath_encode,
u_int32_t addpath_tx_id) u_int32_t addpath_tx_id)
{ {
switch (safi) if (safi == SAFI_MPLS_VPN)
{ {
case SAFI_MPLS_VPN:
/* addpath TX ID */
if (addpath_encode) if (addpath_encode)
stream_putl(s, addpath_tx_id); stream_putl(s, addpath_tx_id);
/* Tag, RD, Prefix write. */ /* Tag, RD, Prefix write. */
stream_putc (s, p->prefixlen + 88); stream_putc (s, p->prefixlen + 88);
stream_put (s, tag, 3); stream_put (s, tag, 3);
stream_put (s, prd->val, 8); stream_put (s, prd->val, 8);
stream_put (s, &p->u.prefix, PSIZE (p->prefixlen)); 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 void
@ -2314,7 +2340,6 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
int send_as4_path = 0; int send_as4_path = 0;
int send_as4_aggregator = 0; int send_as4_aggregator = 0;
int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0; int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0;
size_t mpattrlen_pos = 0;
if (! bgp) if (! bgp)
bgp = peer->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) && if (p && !((afi == AFI_IP && safi == SAFI_UNICAST) &&
!peer_cap_enhe(peer))) !peer_cap_enhe(peer)))
{ {
size_t mpattrlen_pos = 0;
mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi,
(peer_cap_enhe(peer) ? AFI_IP6 : afi), (peer_cap_enhe(peer) ? AFI_IP6 : afi),
vecarr, attr); 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 */ send_as4_path = 1; /* we'll do this later, at the correct place */
/* Nexthop attribute. */ /* 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)) 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, 0); /* Length of this attribute. */
stream_putw (s, afi); stream_putw (s, afi);
safi = (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi; stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi);
stream_putc (s, safi);
return attrlen_pnt; return attrlen_pnt;
} }
@ -2718,12 +2744,7 @@ bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
void void
bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt) bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt)
{ {
bgp_size_t size; bgp_packet_mpattr_end (s, attrlen_pnt);
/* 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);
} }
/* Initialization of attribute. */ /* Initialization of attribute. */

View File

@ -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, struct prefix *p, struct prefix_rd *prd,
u_char *tag, int addpath_encode, u_char *tag, int addpath_encode,
u_int32_t addpath_tx_id); 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 void bgp_packet_mpattr_end(struct stream *s, size_t sizep);
extern size_t bgp_packet_mpunreach_start (struct stream *s, afi_t afi, extern size_t bgp_packet_mpunreach_start (struct stream *s, afi_t afi,

View File

@ -206,13 +206,10 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
decode_rd_ip (pnt + 5, &rd_ip); decode_rd_ip (pnt + 5, &rd_ip);
break; break;
case RD_TYPE_EOI: default:
break; zlog_err ("Unknown RD type %d", type);
break; /* just report */
default: }
zlog_err ("Invalid RD type %d", type);
return -1;
}
p.prefixlen = prefixlen - VPN_PREFIXLEN_MIN_BYTES*8; p.prefixlen = prefixlen - VPN_PREFIXLEN_MIN_BYTES*8;
memcpy (&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES, 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); snprintf (buf, size, "%s:%d", inet_ntoa (rd_ip.ip), rd_ip.val);
return buf; 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; return NULL;
} }

View File

@ -24,7 +24,6 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#define RD_TYPE_AS 0 #define RD_TYPE_AS 0
#define RD_TYPE_IP 1 #define RD_TYPE_IP 1
#define RD_TYPE_AS4 2 #define RD_TYPE_AS4 2
#define RD_TYPE_EOI 0xff00
#define RD_ADDRSTRLEN 28 #define RD_ADDRSTRLEN 28

View File

@ -2369,6 +2369,7 @@ route_set_vpnv4_nexthop (void *rule, struct prefix *prefix,
/* Set next hop value. */ /* 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_global_in = *address;
(bgp_attr_extra_get (bgp_info->attr))->mp_nexthop_len = 4;
} }
return RMAP_OKAY; return RMAP_OKAY;

View File

@ -666,7 +666,8 @@ subgroup_update_packet (struct update_subgroup *subgrp)
space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) - space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) -
BGP_MAX_PACKET_SIZE_OVERFLOW; 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. */ /* When remaining space can't include NLRI and it's length. */
if (space_remaining < space_needed) if (space_remaining < space_needed)
@ -675,10 +676,18 @@ subgroup_update_packet (struct update_subgroup *subgrp)
/* If packet is empty, set attribute. */ /* If packet is empty, set attribute. */
if (stream_empty (s)) if (stream_empty (s))
{ {
struct prefix_rd *prd = NULL;
u_char *tag = NULL;
struct peer *from = NULL; struct peer *from = NULL;
if (rn->prn)
prd = (struct prefix_rd *) &rn->prn->p;
if (binfo) 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, /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length,
* one byte message type. * 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. */ /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
total_attr_len = bgp_packet_attribute (NULL, peer, s, total_attr_len = bgp_packet_attribute (NULL, peer, s,
adv->baa->attr, &vecarr, adv->baa->attr, &vecarr,
NULL, afi, safi, &rn->p, afi, safi,
from, NULL, NULL, 0, 0); from, prd, tag, 0, 0);
space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) - space_remaining = STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) -
BGP_MAX_PACKET_SIZE_OVERFLOW; BGP_MAX_PACKET_SIZE_OVERFLOW;