This is part of the core VPN and Encap SAFI changes. There wasn't much missing for VPNv6 to begin with; just a few bits of de- & encoding and a few lists to be updated.
Signed-off-by: Lou Berger <[email protected]> Signed-off-by: David Lamparter <[email protected]> --- bgpd/bgp_attr.c | 25 +++++++++++++++++++++++++ bgpd/bgp_mplsvpn.c | 37 +++++++++++++++++++++++++++---------- bgpd/bgp_mplsvpn.h | 3 ++- bgpd/bgp_open.c | 15 ++++++++++++++- bgpd/bgp_packet.c | 28 ++++++++++++++++++++++++++-- bgpd/bgp_vty.c | 6 +++++- bgpd/bgpd.c | 11 ++++++++--- 7 files changed, 107 insertions(+), 18 deletions(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index ef19bc4..7fde497 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1534,11 +1534,36 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args, stream_get (&attre->mp_nexthop_global_in, s, 4); break; #ifdef HAVE_IPV6 + case 24: + { + u_int32_t rd_high __attribute__((unused)); + u_int32_t rd_low __attribute__((unused)); + + rd_high = stream_getl (s); + rd_low = stream_getl (s); + } + /* fall through */ case 16: stream_get (&attre->mp_nexthop_global, s, 16); break; case 32: + case 48: + if (attre->mp_nexthop_len == 48) { + u_int32_t rd_high __attribute__((unused)); + u_int32_t rd_low __attribute__((unused)); + + rd_high = stream_getl (s); + rd_low = stream_getl (s); + } stream_get (&attre->mp_nexthop_global, s, 16); + + if (attre->mp_nexthop_len == 48) { + u_int32_t rd_high __attribute__((unused)); + u_int32_t rd_low __attribute__((unused)); + + rd_high = stream_getl (s); + rd_low = stream_getl (s); + } stream_get (&attre->mp_nexthop_local, s, 16); if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local)) { diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index d5211d6..719822f 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -92,13 +92,13 @@ decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip) } int -bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr, - struct bgp_nlri *packet) +bgp_nlri_parse_vpn (afi_t afi, struct peer *peer, struct attr *attr, + struct bgp_nlri *packet, int withdraw) { u_char *pnt; u_char *lim; struct prefix p; - int psize; + int psize = 0; int prefixlen; u_int16_t type; struct rd_as rd_as; @@ -124,7 +124,13 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr, /* Fetch prefix length. */ prefixlen = *pnt++; - p.family = AF_INET; + p.family = afi2family(afi); + if (p.family == 0) + { + /* bad afi, shouldn't happen */ + zlog_warn("%s: bad afi %d, dropping incoming route", __func__, afi); + continue; + } psize = PSIZE (prefixlen); if (prefixlen < 88) @@ -170,12 +176,16 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr, if (pnt + psize > lim) return -1; - if (attr) - bgp_update (peer, &p, attr, AFI_IP, SAFI_MPLS_VPN, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0); + if (!withdraw) + { + bgp_update (peer, &p, attr, afi, SAFI_MPLS_VPN, + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0); + } else - bgp_withdraw (peer, &p, attr, AFI_IP, SAFI_MPLS_VPN, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt); + { + bgp_withdraw (peer, &p, attr, afi, SAFI_MPLS_VPN, + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt); + } } /* Packet length consistency check. */ @@ -460,6 +470,7 @@ static int bgp_show_mpls_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type type, void *output_arg, int tags) { + afi_t afi = AFI_IP; struct bgp *bgp; struct bgp_table *table; struct bgp_node *rn; @@ -477,7 +488,13 @@ bgp_show_mpls_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type ty return CMD_WARNING; } - for (rn = bgp_table_top (bgp->rib[AFI_IP][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn)) + if ((afi != AFI_IP) && (afi != AFI_IP6)) + { + vty_out (vty, "Afi %d not supported%s", afi, VTY_NEWLINE); + return CMD_WARNING; + } + + for (rn = bgp_table_top (bgp->rib[afi][SAFI_MPLS_VPN]); rn; rn = bgp_route_next (rn)) { if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0) continue; diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 0cb9dec..6b1fafd 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -43,7 +43,8 @@ struct rd_ip }; extern void bgp_mplsvpn_init (void); -extern int bgp_nlri_parse_vpnv4 (struct peer *, struct attr *, struct bgp_nlri *); +extern int bgp_nlri_parse_vpn (afi_t, struct peer *, struct attr *, + struct bgp_nlri *, int withdraw); extern u_int32_t decode_label (u_char *); extern int str2prefix_rd (const char *, struct prefix_rd *); extern int str2tag (const char *, u_char *); diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index b9d6e93..129c11f 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -808,7 +808,8 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability) && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST] && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST] - && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST]) + && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST] + && ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]) { plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not " "overlap with received MP capabilities", @@ -978,6 +979,18 @@ bgp_open_capability (struct stream *s, struct peer *peer) stream_putc (s, 0); stream_putc (s, SAFI_MULTICAST); } + /* IPv6 VPN. */ + if (peer->afc[AFI_IP6][SAFI_MPLS_VPN]) + { + peer->afc_adv[AFI_IP6][SAFI_MPLS_VPN] = 1; + stream_putc (s, BGP_OPEN_OPT_CAP); + stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); + stream_putc (s, CAPABILITY_CODE_MP); + stream_putc (s, CAPABILITY_CODE_MP_LEN); + stream_putw (s, AFI_IP6); + stream_putc (s, 0); + stream_putc (s, SAFI_MPLS_LABELED_VPN); + } #endif /* HAVE_IPV6 */ /* Route refresh. */ diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index a90e56b..35c4719 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1885,12 +1885,12 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) if (mp_update.length && mp_update.afi == AFI_IP && mp_update.safi == SAFI_MPLS_LABELED_VPN) - bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update); + bgp_nlri_parse_vpn (mp_update.afi, peer, &attr, &mp_update, 0); if (mp_withdraw.length && mp_withdraw.afi == AFI_IP && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN) - bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw); + bgp_nlri_parse_vpn (mp_withdraw.afi, peer, &attr, &mp_withdraw, 1); if (! withdraw_len && mp_withdraw.afi == AFI_IP @@ -1904,6 +1904,30 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) peer->host); } } + if (peer->afc[AFI_IP6][SAFI_MPLS_VPN]) + { + if (mp_update.length + && mp_update.afi == AFI_IP6 + && mp_update.safi == SAFI_MPLS_LABELED_VPN) + bgp_nlri_parse_vpn (mp_update.afi, peer, &attr, &mp_update, 0); + + if (mp_withdraw.length + && mp_withdraw.afi == AFI_IP6 + && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN) + bgp_nlri_parse_vpn (mp_withdraw.afi, peer, &attr, &mp_withdraw, 1); + + if (! withdraw_len + && mp_withdraw.afi == AFI_IP6 + && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN + && mp_withdraw.length == 0) + { + /* End-of-RIB received */ + + if (BGP_DEBUG (update, UPDATE_IN)) + zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s", + peer->host); + } + } /* Everything is done. We unintern temporary structures which interned in bgp_attr_parse(). */ diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 36fd263..5330a22 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -7302,11 +7302,13 @@ afi_safi_print (afi_t afi, safi_t safi) else if (afi == AFI_IP && safi == SAFI_MULTICAST) return "IPv4 Multicast"; else if (afi == AFI_IP && safi == SAFI_MPLS_VPN) - return "VPNv4 Unicast"; + return "VPN-IPv4 Unicast"; else if (afi == AFI_IP6 && safi == SAFI_UNICAST) return "IPv6 Unicast"; else if (afi == AFI_IP6 && safi == SAFI_MULTICAST) return "IPv6 Multicast"; + else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN) + return "VPN-IPv6 Unicast"; else return "Unknown"; } @@ -7649,6 +7651,8 @@ bgp_show_peer (struct vty *vty, struct peer *p) || p->afc_recv[AFI_IP6][SAFI_UNICAST] || p->afc_adv[AFI_IP6][SAFI_MULTICAST] || p->afc_recv[AFI_IP6][SAFI_MULTICAST] + || p->afc_adv[AFI_IP6][SAFI_MPLS_VPN] + || p->afc_recv[AFI_IP6][SAFI_MPLS_VPN] #endif /* HAVE_IPV6 */ || p->afc_adv[AFI_IP][SAFI_MPLS_VPN] || p->afc_recv[AFI_IP][SAFI_MPLS_VPN]) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 2325f07..c3c0dba 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -978,6 +978,8 @@ peer_as_change (struct peer *peer, as_t as) PEER_FLAG_REFLECTOR_CLIENT); UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST], PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN], + PEER_FLAG_REFLECTOR_CLIENT); } /* local-as reset */ @@ -1394,7 +1396,8 @@ peer_group_active (struct peer *peer) || peer->af_group[AFI_IP][SAFI_MULTICAST] || peer->af_group[AFI_IP][SAFI_MPLS_VPN] || peer->af_group[AFI_IP6][SAFI_UNICAST] - || peer->af_group[AFI_IP6][SAFI_MULTICAST]) + || peer->af_group[AFI_IP6][SAFI_MULTICAST] + || peer->af_group[AFI_IP6][SAFI_MPLS_VPN]) return 1; return 0; } @@ -2335,7 +2338,8 @@ peer_active (struct peer *peer) || peer->afc[AFI_IP][SAFI_MULTICAST] || peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP6][SAFI_UNICAST] - || peer->afc[AFI_IP6][SAFI_MULTICAST]) + || peer->afc[AFI_IP6][SAFI_MULTICAST] + || peer->afc[AFI_IP6][SAFI_MPLS_VPN]) return 1; return 0; } @@ -2348,7 +2352,8 @@ peer_active_nego (struct peer *peer) || peer->afc_nego[AFI_IP][SAFI_MULTICAST] || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] || peer->afc_nego[AFI_IP6][SAFI_UNICAST] - || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]) + || peer->afc_nego[AFI_IP6][SAFI_MULTICAST] + || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]) return 1; return 0; } -- 2.1.3 _______________________________________________ Quagga-dev mailing list [email protected] https://lists.quagga.net/mailman/listinfo/quagga-dev
