From 343e90c328b27ea9497cdcd286e541cb163ab69a Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Wed, 10 May 2017 09:40:29 -0400 Subject: [PATCH] bgpd: add ENHE support for "address-family ipv4 labeled-unicast" Signed-off-by: Daniel Walton --- bgpd/bgp_attr.c | 23 +++++++++++------- bgpd/bgp_open.c | 52 +++++++++++++++++++++------------------- bgpd/bgp_route.c | 8 +++---- bgpd/bgp_updgrp_packet.c | 18 +++++++------- bgpd/bgpd.h | 10 ++------ 5 files changed, 56 insertions(+), 55 deletions(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index b2789cd47d..9b9ad80d35 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -2890,10 +2890,15 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi, assert (attr->extra); 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); + } else { + stream_putc (s, IPV6_MAX_BYTELEN); + stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN); + } } break; case SAFI_MPLS_VPN: @@ -3137,14 +3142,14 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, cp = stream_get_endp (s); if (p && !((afi == AFI_IP && safi == SAFI_UNICAST) && - !peer_cap_enhe(peer))) + !peer_cap_enhe(peer, afi, safi))) { size_t mpattrlen_pos = 0; mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, - (peer_cap_enhe(peer) ? AFI_IP6 : - AFI_MAX), /* get from NH */ - vecarr, attr); + (peer_cap_enhe(peer, afi, safi) ? AFI_IP6 : + AFI_MAX), /* get from NH */ + vecarr, attr); bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag, addpath_encode, addpath_tx_id, attr); 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 */ /* 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)) { @@ -3230,7 +3235,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer, stream_putc (s, 4); 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 diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 83fc3fe977..3ad6be1a3f 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -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 * the Nexthop AFI being IPv6. A future spec may introduce other * 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); - 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 " "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_putc (s, 0); 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. */ SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV); stream_putc (s, BGP_OPEN_OPT_CAP); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f327e34f2a..ddb3679af9 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1456,7 +1456,7 @@ subgroup_announce_check (struct bgp_node *rn, struct bgp_info *ri, #define NEXTHOP_IS_V6 (\ (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) &&\ 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 || CHECK_FLAG (peer->af_flags[afi][safi], 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); } else if (peer->sort == BGP_PEER_EBGP) @@ -1573,14 +1573,14 @@ subgroup_announce_check (struct bgp_node *rn, struct bgp_info *ri, break; } 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 * 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 * 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)) subgroup_announce_reset_nhop (AF_INET6, attr); diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 9be1a50db7..459cf707d0 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -427,7 +427,7 @@ bpacket_reformat_for_peer (struct bpacket *pkt, struct peer_af *paf) if (paf->afi == AFI_IP || paf->afi == AFI_IP6) { nhafi = BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen); - if (peer_cap_enhe(peer)) + if (peer_cap_enhe(peer, paf->afi, paf->safi)) nhafi = AFI_IP6; if (paf->safi == SAFI_MPLS_VPN && /* if VPN && not global */ 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) && - !peer_cap_enhe(peer)) + !peer_cap_enhe(peer, afi, safi)) stream_put_prefix_addpath (s, &rn->p, addpath_encode, addpath_tx_id); else { @@ -769,9 +769,9 @@ 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_MAX), /* get from NH */ - &vecarr, adv->baa->attr); + (peer_cap_enhe(peer, afi, safi) ? 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, adv->baa->attr); @@ -923,7 +923,7 @@ subgroup_withdraw_packet (struct update_subgroup *subgrp) first_time = 0; 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); else { @@ -975,7 +975,7 @@ subgroup_withdraw_packet (struct update_subgroup *subgrp) if (!stream_empty (s)) { if (afi == AFI_IP && safi == SAFI_UNICAST && - !peer_cap_enhe(peer)) + !peer_cap_enhe(peer, afi, safi)) { 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. */ 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); /* Set size. */ @@ -1133,7 +1133,7 @@ subgroup_default_withdraw_packet (struct update_subgroup *subgrp) /* Withdrawn Routes. */ 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); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index ac09b97580..66ec8ccc84 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1514,16 +1514,10 @@ peer_dynamic_neighbor (struct peer *peer) 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 -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. */