bgpd: add ENHE support for "address-family ipv4 labeled-unicast"

Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
This commit is contained in:
Daniel Walton 2017-05-10 09:40:29 -04:00 committed by Donald Sharp
parent 0896b75508
commit 343e90c328
5 changed files with 56 additions and 55 deletions

View file

@ -2890,10 +2890,15 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
assert (attr->extra); assert (attr->extra);
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, attre->mp_nexthop_len);
stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN); 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_putc (s, BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL);
stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
stream_put (s, &attre->mp_nexthop_local, IPV6_MAX_BYTELEN); stream_put (s, &attre->mp_nexthop_local, IPV6_MAX_BYTELEN);
} else {
stream_putc (s, IPV6_MAX_BYTELEN);
stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
}
} }
break; break;
case SAFI_MPLS_VPN: case SAFI_MPLS_VPN:
@ -3137,14 +3142,14 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
cp = stream_get_endp (s); cp = stream_get_endp (s);
if (p && !((afi == AFI_IP && safi == SAFI_UNICAST) && if (p && !((afi == AFI_IP && safi == SAFI_UNICAST) &&
!peer_cap_enhe(peer))) !peer_cap_enhe(peer, afi, safi)))
{ {
size_t mpattrlen_pos = 0; 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 : (peer_cap_enhe(peer, afi, safi) ? AFI_IP6 :
AFI_MAX), /* get from NH */ AFI_MAX), /* get from NH */
vecarr, attr); vecarr, attr);
bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag, bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag,
addpath_encode, addpath_tx_id, attr); addpath_encode, addpath_tx_id, attr);
bgp_packet_mpattr_end(s, mpattrlen_pos); bgp_packet_mpattr_end(s, mpattrlen_pos);
@ -3220,7 +3225,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 && safi == SAFI_UNICAST && !peer_cap_enhe(peer)) if (afi == AFI_IP && safi == SAFI_UNICAST && !peer_cap_enhe(peer, afi, safi))
{ {
if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)) if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
{ {
@ -3230,7 +3235,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
stream_putc (s, 4); stream_putc (s, 4);
stream_put_ipv4 (s, attr->nexthop.s_addr); stream_put_ipv4 (s, attr->nexthop.s_addr);
} }
else if (peer_cap_enhe(from)) else if (peer_cap_enhe(from, afi, safi))
{ {
/* /*
* Likely this is the case when an IPv4 prefix was received with * Likely this is the case when an IPv4 prefix was received with

View file

@ -594,11 +594,11 @@ bgp_capability_enhe (struct peer *peer, struct capability_header *hdr)
/* RFC 5549 specifies use of this capability only for IPv4 AFI, with /* RFC 5549 specifies use of this capability only for IPv4 AFI, with
* the Nexthop AFI being IPv6. A future spec may introduce other * the Nexthop AFI being IPv6. A future spec may introduce other
* possibilities, so we ignore other values with a log. Also, only * possibilities, so we ignore other values with a log. Also, only
* Unicast SAFI is currently supported (and expected). * SAFI_UNICAST and SAFI_LABELED_UNICAST are currently supported (and expected).
*/ */
nh_afi = afi_iana2int (pkt_nh_afi); nh_afi = afi_iana2int (pkt_nh_afi);
if (afi != AFI_IP || safi != SAFI_UNICAST || nh_afi != AFI_IP6) if (afi != AFI_IP || nh_afi != AFI_IP6 || !(safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
{ {
zlog_warn ("%s Unexpected afi/safi/next-hop afi: %u/%u/%u " zlog_warn ("%s Unexpected afi/safi/next-hop afi: %u/%u/%u "
"in Extended Next-hop capability, ignoring", "in Extended Next-hop capability, ignoring",
@ -1288,32 +1288,34 @@ bgp_open_capability (struct stream *s, struct peer *peer)
stream_putw (s, pkt_afi); stream_putw (s, pkt_afi);
stream_putc (s, 0); stream_putc (s, 0);
stream_putc (s, pkt_safi); stream_putc (s, pkt_safi);
/* Extended nexthop capability - currently supporting RFC-5549 for
* Link-Local peering only
*/
if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE) &&
peer->su.sa.sa_family == AF_INET6 &&
IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr) &&
afi == AFI_IP &&
(safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
{
/* RFC 5549 Extended Next Hop Encoding */
SET_FLAG (peer->cap, PEER_CAP_ENHE_ADV);
stream_putc (s, BGP_OPEN_OPT_CAP);
stream_putc (s, CAPABILITY_CODE_ENHE_LEN + 2);
stream_putc (s, CAPABILITY_CODE_ENHE);
stream_putc (s, CAPABILITY_CODE_ENHE_LEN);
SET_FLAG (peer->af_cap[AFI_IP][safi], PEER_CAP_ENHE_AF_ADV);
stream_putw (s, pkt_afi);
stream_putw (s, pkt_safi);
stream_putw (s, afi_int2iana(AFI_IP6));
if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_RCV))
SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_NEGO);
}
} }
} }
/* Extended nexthop capability - currently supporting RFC-5549 for
* Link-Local peering only
*/
if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE) &&
peer->su.sa.sa_family == AF_INET6 &&
IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr))
{
/* RFC 5549 Extended Next Hop Encoding */
SET_FLAG (peer->cap, PEER_CAP_ENHE_ADV);
stream_putc (s, BGP_OPEN_OPT_CAP);
stream_putc (s, CAPABILITY_CODE_ENHE_LEN + 2);
stream_putc (s, CAPABILITY_CODE_ENHE);
stream_putc (s, CAPABILITY_CODE_ENHE_LEN);
/* Currently supporting for SAFI_UNICAST only */
SET_FLAG (peer->af_cap[AFI_IP][SAFI_UNICAST], PEER_CAP_ENHE_AF_ADV);
stream_putw (s, AFI_IP);
stream_putw (s, SAFI_UNICAST);
stream_putw (s, AFI_IP6);
if (CHECK_FLAG (peer->af_cap[AFI_IP][SAFI_UNICAST], PEER_CAP_ENHE_AF_RCV))
SET_FLAG (peer->af_cap[AFI_IP][SAFI_UNICAST], PEER_CAP_ENHE_AF_NEGO);
}
/* Route refresh. */ /* Route refresh. */
SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV); SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, BGP_OPEN_OPT_CAP);

View file

@ -1456,7 +1456,7 @@ subgroup_announce_check (struct bgp_node *rn, struct bgp_info *ri,
#define NEXTHOP_IS_V6 (\ #define NEXTHOP_IS_V6 (\
(safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN &&\ (safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN &&\
(p->family == AF_INET6 || peer_cap_enhe(peer))) || \ (p->family == AF_INET6 || peer_cap_enhe(peer, AFI_IP6, safi))) || \
((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) &&\ ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) &&\
attr->extra->mp_nexthop_len >= IPV6_MAX_BYTELEN)) attr->extra->mp_nexthop_len >= IPV6_MAX_BYTELEN))
@ -1558,7 +1558,7 @@ subgroup_announce_check (struct bgp_node *rn, struct bgp_info *ri,
if (!reflect || if (!reflect ||
CHECK_FLAG (peer->af_flags[afi][safi], CHECK_FLAG (peer->af_flags[afi][safi],
PEER_FLAG_FORCE_NEXTHOP_SELF)) PEER_FLAG_FORCE_NEXTHOP_SELF))
subgroup_announce_reset_nhop ((peer_cap_enhe(peer) ? subgroup_announce_reset_nhop ((peer_cap_enhe(peer, afi, safi) ?
AF_INET6 : p->family), attr); AF_INET6 : p->family), attr);
} }
else if (peer->sort == BGP_PEER_EBGP) else if (peer->sort == BGP_PEER_EBGP)
@ -1573,14 +1573,14 @@ subgroup_announce_check (struct bgp_node *rn, struct bgp_info *ri,
break; break;
} }
if (!paf) if (!paf)
subgroup_announce_reset_nhop ((peer_cap_enhe(peer) ? AF_INET6 : p->family), attr); subgroup_announce_reset_nhop ((peer_cap_enhe(peer, afi, safi) ? AF_INET6 : p->family), attr);
} }
/* If IPv6/MP and nexthop does not have any override and happens to /* If IPv6/MP and nexthop does not have any override and happens to
* be a link-local address, reset it so that we don't pass along the * be a link-local address, reset it so that we don't pass along the
* source's link-local IPv6 address to recipients who may not be on * source's link-local IPv6 address to recipients who may not be on
* the same interface. * the same interface.
*/ */
if (p->family == AF_INET6 || peer_cap_enhe(peer)) if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))
{ {
if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global)) if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
subgroup_announce_reset_nhop (AF_INET6, attr); subgroup_announce_reset_nhop (AF_INET6, attr);

View file

@ -427,7 +427,7 @@ bpacket_reformat_for_peer (struct bpacket *pkt, struct peer_af *paf)
if (paf->afi == AFI_IP || paf->afi == AFI_IP6) if (paf->afi == AFI_IP || paf->afi == AFI_IP6)
{ {
nhafi = BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen); nhafi = BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen);
if (peer_cap_enhe(peer)) if (peer_cap_enhe(peer, paf->afi, paf->safi))
nhafi = AFI_IP6; nhafi = AFI_IP6;
if (paf->safi == SAFI_MPLS_VPN && /* if VPN && not global */ if (paf->safi == SAFI_MPLS_VPN && /* if VPN && not global */
nhlen != BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) nhlen != BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
@ -754,7 +754,7 @@ subgroup_update_packet (struct update_subgroup *subgrp)
} }
if ((afi == AFI_IP && safi == SAFI_UNICAST) && if ((afi == AFI_IP && safi == SAFI_UNICAST) &&
!peer_cap_enhe(peer)) !peer_cap_enhe(peer, afi, safi))
stream_put_prefix_addpath (s, &rn->p, addpath_encode, addpath_tx_id); stream_put_prefix_addpath (s, &rn->p, addpath_encode, addpath_tx_id);
else else
{ {
@ -769,9 +769,9 @@ subgroup_update_packet (struct update_subgroup *subgrp)
if (stream_empty (snlri)) if (stream_empty (snlri))
mpattrlen_pos = bgp_packet_mpattr_start (snlri, afi, safi, mpattrlen_pos = bgp_packet_mpattr_start (snlri, afi, safi,
(peer_cap_enhe(peer) ? AFI_IP6 : (peer_cap_enhe(peer, afi, safi) ? AFI_IP6 :
AFI_MAX), /* get from NH */ AFI_MAX), /* get from NH */
&vecarr, adv->baa->attr); &vecarr, adv->baa->attr);
bgp_packet_mpattr_prefix (snlri, afi, safi, &rn->p, prd, bgp_packet_mpattr_prefix (snlri, afi, safi, &rn->p, prd,
tag, addpath_encode, addpath_tx_id, adv->baa->attr); tag, addpath_encode, addpath_tx_id, adv->baa->attr);
@ -923,7 +923,7 @@ subgroup_withdraw_packet (struct update_subgroup *subgrp)
first_time = 0; first_time = 0;
if (afi == AFI_IP && safi == SAFI_UNICAST && if (afi == AFI_IP && safi == SAFI_UNICAST &&
!peer_cap_enhe(peer)) !peer_cap_enhe(peer, afi, safi))
stream_put_prefix_addpath (s, &rn->p, addpath_encode, addpath_tx_id); stream_put_prefix_addpath (s, &rn->p, addpath_encode, addpath_tx_id);
else else
{ {
@ -975,7 +975,7 @@ subgroup_withdraw_packet (struct update_subgroup *subgrp)
if (!stream_empty (s)) if (!stream_empty (s))
{ {
if (afi == AFI_IP && safi == SAFI_UNICAST && if (afi == AFI_IP && safi == SAFI_UNICAST &&
!peer_cap_enhe(peer)) !peer_cap_enhe(peer, afi, safi))
{ {
unfeasible_len unfeasible_len
= stream_get_endp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN; = stream_get_endp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN;
@ -1072,7 +1072,7 @@ subgroup_default_update_packet (struct update_subgroup *subgrp,
/* NLRI set. */ /* NLRI set. */
if (p.family == AF_INET && safi == SAFI_UNICAST && if (p.family == AF_INET && safi == SAFI_UNICAST &&
!peer_cap_enhe(peer)) !peer_cap_enhe(peer, afi, safi))
stream_put_prefix_addpath (s, &p, addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); stream_put_prefix_addpath (s, &p, addpath_encode, BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
/* Set size. */ /* Set size. */
@ -1133,7 +1133,7 @@ subgroup_default_withdraw_packet (struct update_subgroup *subgrp)
/* Withdrawn Routes. */ /* Withdrawn Routes. */
if (p.family == AF_INET && safi == SAFI_UNICAST && if (p.family == AF_INET && safi == SAFI_UNICAST &&
!peer_cap_enhe(peer)) !peer_cap_enhe(peer, afi, safi))
{ {
stream_put_prefix_addpath (s, &p, addpath_encode, stream_put_prefix_addpath (s, &p, addpath_encode,
BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);

View file

@ -1514,16 +1514,10 @@ peer_dynamic_neighbor (struct peer *peer)
return (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR)) ? 1 : 0; return (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR)) ? 1 : 0;
} }
/*
* Currently supporting RFC 5549 for AFI_IP/SAFI_UNICAST only.
*
* Note: When other RFC-5549 applicable SAFIs to be supported, that should
* come as an argument to this routine.
*/
static inline int static inline int
peer_cap_enhe (struct peer *peer) peer_cap_enhe (struct peer *peer, afi_t afi, safi_t safi)
{ {
return (CHECK_FLAG(peer->af_cap[AFI_IP][SAFI_UNICAST], PEER_CAP_ENHE_AF_NEGO)); return (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_NEGO));
} }
/* Lookup VRF for BGP instance based on its type. */ /* Lookup VRF for BGP instance based on its type. */