From fe3ca08faf4e109ed9d0e5db0974847b39912fba Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Sat, 14 Jan 2017 08:34:22 -0500 Subject: [PATCH] bgpd: allow VPN next hop to be different AFI than NLRI next hop (Issue #71) Signed-off-by: Lou Berger --- bgpd/bgp_attr.c | 5 ++++- bgpd/bgp_route.c | 5 +++-- bgpd/bgp_route.h | 4 ++++ bgpd/bgp_updgrp_packet.c | 14 +++++++------- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 4cf1f0daed7a..87cff44293f6 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -2664,6 +2664,8 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi, stream_putw (s, pkt_afi); /* AFI */ stream_putc (s, pkt_safi); /* SAFI */ + if (nh_afi == AFI_MAX) + nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->extra->mp_nexthop_len); /* Nexthop */ switch (nh_afi) { @@ -2913,7 +2915,8 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, size_t mpattrlen_pos = 0; mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, - (peer_cap_enhe(peer) ? AFI_IP6 : afi), + (peer_cap_enhe(peer) ? AFI_IP6 : + AFI_MAX), /* get from NH */ vecarr, attr); bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag, addpath_encode, addpath_tx_id); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 26c500af1b4d..670ad84a3ab5 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1429,9 +1429,10 @@ subgroup_announce_check (struct bgp_info *ri, struct update_subgroup *subgrp, SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED); #define NEXTHOP_IS_V6 (\ - (safi != SAFI_ENCAP && \ + (safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN &&\ (p->family == AF_INET6 || peer_cap_enhe(peer))) || \ - (safi == SAFI_ENCAP && attr->extra->mp_nexthop_len == 16)) + ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) &&\ + attr->extra->mp_nexthop_len >= IPV6_MAX_BYTELEN)) /* IPv6/MP starts with 1 nexthop. The link-local address is passed only if * the peer (group) is configured to receive link-local nexthop unchanged diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 63b18aa2d8fb..3c7aa83a0e4d 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -179,6 +179,10 @@ struct bgp_static u_char tag[3]; }; +#define BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen) \ + ((nhlen) < IPV4_MAX_BYTELEN ? 0 : \ + ((nhlen) < IPV6_MAX_BYTELEN ? AFI_IP : AFI_IP6)) + #define BGP_ATTR_NEXTHOP_AFI_IP6(attr) \ (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)) && \ (attr)->extra && ((attr)->extra->mp_nexthop_len == 16 || \ diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 95c1ae4d5569..79c11358feab 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -423,12 +423,11 @@ bpacket_reformat_for_peer (struct bpacket *pkt, struct peer_af *paf) nhlen = stream_getc_from (s, vec->offset); if (paf->afi == AFI_IP || paf->afi == AFI_IP6) { - if (nhlen < IPV6_MAX_BYTELEN && !peer_cap_enhe(peer)) - nhafi = AFI_IP; - else + nhafi = BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen); + if (peer_cap_enhe(peer)) nhafi = AFI_IP6; - if (paf->safi == SAFI_MPLS_VPN && /* if VPN */ - nhlen != 48) /* and ! GLOBAL_AND_LL */ + if (paf->safi == SAFI_MPLS_VPN && /* if VPN && not global */ + nhlen != BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) nhafi = AFI_MAX; /* no change allowed */ } @@ -486,7 +485,7 @@ bpacket_reformat_for_peer (struct bpacket *pkt, struct peer_af *paf) if (bgp_debug_update(peer, NULL, NULL, 0)) zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s send UPDATE w/ nexthop %s%s", - PAF_SUBGRP(paf)->update_group->id, PAF_SUBGRP(paf)->id, + PAF_SUBGRP(paf)->update_group->id, PAF_SUBGRP(paf)->id, peer->host, inet_ntoa (*mod_v4nh), (nhlen == 12 ? " and RD" : "")); } @@ -762,7 +761,8 @@ subgroup_update_packet (struct update_subgroup *subgrp) if (stream_empty (snlri)) mpattrlen_pos = bgp_packet_mpattr_start (snlri, afi, safi, - (peer_cap_enhe(peer) ? AFI_IP6 : afi), + (peer_cap_enhe(peer) ? AFI_IP6 : + AFI_MAX), /* get from NH */ &vecarr, adv->baa->attr); bgp_packet_mpattr_prefix (snlri, afi, safi, &rn->p, prd, tag, addpath_encode, addpath_tx_id);