forked from Mirror/frr
bgpd: wire up VPNv6 protocol processing
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 <lberger@labn.net> Signed-off-by: David Lamparter <equinox@opensourcerouting.org> [Editorial note: Signed-off-by may imply an authorship claim, but need not] Edited-by: Paul Jakma <paul.jakma@hpe.com> / <paul@jakma.org> (cherry picked from commit 9da04bca0e994ec92b9242159bf27d89c6743354) Conflicts: bgpd/bgp_attr.c bgpd/bgp_mplsvpn.c bgpd/bgpd.c
This commit is contained in:
parent
fe770c888a
commit
945c8fe985
|
@ -1601,10 +1601,27 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args,
|
||||||
break;
|
break;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
case BGP_ATTR_NHLEN_IPV6_GLOBAL:
|
case BGP_ATTR_NHLEN_IPV6_GLOBAL:
|
||||||
|
case BGP_ATTR_NHLEN_VPNV6_GLOBAL:
|
||||||
|
if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL)
|
||||||
|
{
|
||||||
|
stream_getl (s); /* RD high */
|
||||||
|
stream_getl (s); /* RD low */
|
||||||
|
}
|
||||||
stream_get (&attre->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
|
stream_get (&attre->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
|
||||||
break;
|
break;
|
||||||
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
|
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
|
||||||
|
case BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL:
|
||||||
|
if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
|
||||||
|
{
|
||||||
|
stream_getl (s); /* RD high */
|
||||||
|
stream_getl (s); /* RD low */
|
||||||
|
}
|
||||||
stream_get (&attre->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
|
stream_get (&attre->mp_nexthop_global, s, IPV6_MAX_BYTELEN);
|
||||||
|
if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
|
||||||
|
{
|
||||||
|
stream_getl (s); /* RD high */
|
||||||
|
stream_getl (s); /* RD low */
|
||||||
|
}
|
||||||
stream_get (&attre->mp_nexthop_local, s, IPV6_MAX_BYTELEN);
|
stream_get (&attre->mp_nexthop_local, s, IPV6_MAX_BYTELEN);
|
||||||
if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
|
if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local))
|
||||||
{
|
{
|
||||||
|
|
|
@ -49,9 +49,11 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
|
||||||
/* Valid lengths for mp_nexthop_len */
|
/* Valid lengths for mp_nexthop_len */
|
||||||
#define BGP_ATTR_NHLEN_IPV4 IPV4_MAX_BYTELEN
|
#define BGP_ATTR_NHLEN_IPV4 IPV4_MAX_BYTELEN
|
||||||
#define BGP_ATTR_NHLEN_VPNV4 12
|
#define BGP_ATTR_NHLEN_VPNV4 8+IPV4_MAX_BYTELEN
|
||||||
#define BGP_ATTR_NHLEN_IPV6_GLOBAL IPV6_MAX_BYTELEN
|
#define BGP_ATTR_NHLEN_IPV6_GLOBAL IPV6_MAX_BYTELEN
|
||||||
#define BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL (IPV6_MAX_BYTELEN * 2)
|
#define BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL (IPV6_MAX_BYTELEN * 2)
|
||||||
|
#define BGP_ATTR_NHLEN_VPNV6_GLOBAL 8+IPV6_MAX_BYTELEN
|
||||||
|
#define BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL ((8+IPV6_MAX_BYTELEN) * 2)
|
||||||
|
|
||||||
/* Additional/uncommon BGP attributes.
|
/* Additional/uncommon BGP attributes.
|
||||||
* lazily allocated as and when a struct attr
|
* lazily allocated as and when a struct attr
|
||||||
|
|
|
@ -93,13 +93,13 @@ decode_rd_ip (u_char *pnt, struct rd_ip *rd_ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr,
|
bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
|
||||||
struct bgp_nlri *packet)
|
struct bgp_nlri *packet)
|
||||||
{
|
{
|
||||||
u_char *pnt;
|
u_char *pnt;
|
||||||
u_char *lim;
|
u_char *lim;
|
||||||
struct prefix p;
|
struct prefix p;
|
||||||
int psize;
|
int psize = 0;
|
||||||
int prefixlen;
|
int prefixlen;
|
||||||
u_int16_t type;
|
u_int16_t type;
|
||||||
struct rd_as rd_as;
|
struct rd_as rd_as;
|
||||||
|
@ -219,10 +219,10 @@ bgp_nlri_parse_vpnv4 (struct peer *peer, struct attr *attr,
|
||||||
psize - VPN_PREFIXLEN_MIN_BYTES);
|
psize - VPN_PREFIXLEN_MIN_BYTES);
|
||||||
|
|
||||||
if (attr)
|
if (attr)
|
||||||
bgp_update (peer, &p, addpath_id, attr, AFI_IP, SAFI_MPLS_VPN,
|
bgp_update (peer, &p, addpath_id, attr, packet->afi, SAFI_MPLS_VPN,
|
||||||
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0);
|
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0);
|
||||||
else
|
else
|
||||||
bgp_withdraw (peer, &p, addpath_id, attr, AFI_IP, SAFI_MPLS_VPN,
|
bgp_withdraw (peer, &p, addpath_id, attr, packet->afi, SAFI_MPLS_VPN,
|
||||||
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
|
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt);
|
||||||
}
|
}
|
||||||
/* Packet length consistency check. */
|
/* Packet length consistency check. */
|
||||||
|
@ -572,6 +572,7 @@ static int
|
||||||
bgp_show_mpls_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type type,
|
bgp_show_mpls_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type type,
|
||||||
void *output_arg, int tags, u_char use_json)
|
void *output_arg, int tags, u_char use_json)
|
||||||
{
|
{
|
||||||
|
afi_t afi = AFI_IP;
|
||||||
struct bgp *bgp;
|
struct bgp *bgp;
|
||||||
struct bgp_table *table;
|
struct bgp_table *table;
|
||||||
struct bgp_node *rn;
|
struct bgp_node *rn;
|
||||||
|
@ -616,7 +617,13 @@ bgp_show_mpls_vpn (struct vty *vty, struct prefix_rd *prd, enum bgp_show_type ty
|
||||||
json_object_string_add(json_ocode, "incomplete", "?");
|
json_object_string_add(json_ocode, "incomplete", "?");
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
if (prd && memcmp (rn->p.u.val, prd->val, 8) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -43,7 +43,7 @@ struct rd_ip
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void bgp_mplsvpn_init (void);
|
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 (struct peer *, struct attr *, struct bgp_nlri *);
|
||||||
extern u_int32_t decode_label (u_char *);
|
extern u_int32_t decode_label (u_char *);
|
||||||
extern int str2prefix_rd (const char *, struct prefix_rd *);
|
extern int str2prefix_rd (const char *, struct prefix_rd *);
|
||||||
extern int str2tag (const char *, u_char *);
|
extern int str2tag (const char *, u_char *);
|
||||||
|
|
|
@ -1124,7 +1124,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_MULTICAST]
|
||||||
&& ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
|
&& ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
|
||||||
&& ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
|
&& ! 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])
|
||||||
{
|
{
|
||||||
zlog_err ("%s [Error] Configured AFI/SAFIs do not "
|
zlog_err ("%s [Error] Configured AFI/SAFIs do not "
|
||||||
"overlap with received MP capabilities",
|
"overlap with received MP capabilities",
|
||||||
|
@ -1316,6 +1317,18 @@ bgp_open_capability (struct stream *s, struct peer *peer)
|
||||||
stream_putc (s, 0);
|
stream_putc (s, 0);
|
||||||
stream_putc (s, SAFI_MULTICAST);
|
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 */
|
#endif /* HAVE_IPV6 */
|
||||||
|
|
||||||
/* Route refresh. */
|
/* Route refresh. */
|
||||||
|
|
|
@ -1631,12 +1631,12 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
|
||||||
if (mp_update.length
|
if (mp_update.length
|
||||||
&& mp_update.afi == AFI_IP
|
&& mp_update.afi == AFI_IP
|
||||||
&& mp_update.safi == SAFI_MPLS_LABELED_VPN)
|
&& mp_update.safi == SAFI_MPLS_LABELED_VPN)
|
||||||
bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
|
bgp_nlri_parse_vpn (peer, NLRI_ATTR_ARG, &mp_update);
|
||||||
|
|
||||||
if (mp_withdraw.length
|
if (mp_withdraw.length
|
||||||
&& mp_withdraw.afi == AFI_IP
|
&& mp_withdraw.afi == AFI_IP
|
||||||
&& mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
|
&& mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
|
||||||
bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
|
bgp_nlri_parse_vpn (peer, NULL, &mp_withdraw);
|
||||||
|
|
||||||
if (! withdraw_len
|
if (! withdraw_len
|
||||||
&& mp_withdraw.afi == AFI_IP
|
&& mp_withdraw.afi == AFI_IP
|
||||||
|
@ -1656,6 +1656,35 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
|
||||||
zlog_debug ("rcvd End-of-RIB for VPNv4 Unicast from %s", peer->host);
|
zlog_debug ("rcvd End-of-RIB for VPNv4 Unicast from %s", 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 (peer, NLRI_ATTR_ARG, &mp_update);
|
||||||
|
|
||||||
|
if (mp_withdraw.length
|
||||||
|
&& mp_withdraw.afi == AFI_IP6
|
||||||
|
&& mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
|
||||||
|
bgp_nlri_parse_vpn (peer, NULL, &mp_withdraw);
|
||||||
|
|
||||||
|
if (! withdraw_len
|
||||||
|
&& mp_withdraw.afi == AFI_IP6
|
||||||
|
&& mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
|
||||||
|
&& mp_withdraw.length == 0)
|
||||||
|
{
|
||||||
|
/* End-of-RIB received */
|
||||||
|
if (!CHECK_FLAG (peer->af_sflags[AFI_IP6][SAFI_MPLS_VPN],
|
||||||
|
PEER_STATUS_EOR_RECEIVED))
|
||||||
|
{
|
||||||
|
SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_MPLS_VPN], PEER_STATUS_EOR_RECEIVED);
|
||||||
|
bgp_update_explicit_eors(peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bgp_debug_neighbor_events(peer))
|
||||||
|
zlog_debug ("rcvd End-of-RIB for VPNv6 Unicast from %s", peer->host);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Everything is done. We unintern temporary structures which
|
/* Everything is done. We unintern temporary structures which
|
||||||
interned in bgp_attr_parse(). */
|
interned in bgp_attr_parse(). */
|
||||||
|
|
|
@ -10460,11 +10460,13 @@ afi_safi_print (afi_t afi, safi_t safi)
|
||||||
else if (afi == AFI_IP && safi == SAFI_MULTICAST)
|
else if (afi == AFI_IP && safi == SAFI_MULTICAST)
|
||||||
return "IPv4 Multicast";
|
return "IPv4 Multicast";
|
||||||
else if (afi == AFI_IP && safi == SAFI_MPLS_VPN)
|
else if (afi == AFI_IP && safi == SAFI_MPLS_VPN)
|
||||||
return "VPNv4 Unicast";
|
return "VPN-IPv4 Unicast";
|
||||||
else if (afi == AFI_IP6 && safi == SAFI_UNICAST)
|
else if (afi == AFI_IP6 && safi == SAFI_UNICAST)
|
||||||
return "IPv6 Unicast";
|
return "IPv6 Unicast";
|
||||||
else if (afi == AFI_IP6 && safi == SAFI_MULTICAST)
|
else if (afi == AFI_IP6 && safi == SAFI_MULTICAST)
|
||||||
return "IPv6 Multicast";
|
return "IPv6 Multicast";
|
||||||
|
else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN)
|
||||||
|
return "VPN-IPv6 Unicast";
|
||||||
else
|
else
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
@ -11248,6 +11250,8 @@ bgp_show_peer (struct vty *vty, struct peer *p, u_char use_json, json_object *js
|
||||||
|| p->afc_recv[AFI_IP6][SAFI_UNICAST]
|
|| p->afc_recv[AFI_IP6][SAFI_UNICAST]
|
||||||
|| p->afc_adv[AFI_IP6][SAFI_MULTICAST]
|
|| p->afc_adv[AFI_IP6][SAFI_MULTICAST]
|
||||||
|| p->afc_recv[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 */
|
#endif /* HAVE_IPV6 */
|
||||||
|| p->afc_adv[AFI_IP][SAFI_MPLS_VPN]
|
|| p->afc_adv[AFI_IP][SAFI_MPLS_VPN]
|
||||||
|| p->afc_recv[AFI_IP][SAFI_MPLS_VPN])
|
|| p->afc_recv[AFI_IP][SAFI_MPLS_VPN])
|
||||||
|
|
|
@ -1545,6 +1545,8 @@ peer_as_change (struct peer *peer, as_t as, int as_specified)
|
||||||
PEER_FLAG_REFLECTOR_CLIENT);
|
PEER_FLAG_REFLECTOR_CLIENT);
|
||||||
UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
|
UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
|
||||||
PEER_FLAG_REFLECTOR_CLIENT);
|
PEER_FLAG_REFLECTOR_CLIENT);
|
||||||
|
UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN],
|
||||||
|
PEER_FLAG_REFLECTOR_CLIENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* local-as reset */
|
/* local-as reset */
|
||||||
|
@ -3461,7 +3463,8 @@ peer_active (struct peer *peer)
|
||||||
|| peer->afc[AFI_IP][SAFI_MULTICAST]
|
|| peer->afc[AFI_IP][SAFI_MULTICAST]
|
||||||
|| peer->afc[AFI_IP][SAFI_MPLS_VPN]
|
|| peer->afc[AFI_IP][SAFI_MPLS_VPN]
|
||||||
|| peer->afc[AFI_IP6][SAFI_UNICAST]
|
|| 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 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3474,7 +3477,8 @@ peer_active_nego (struct peer *peer)
|
||||||
|| peer->afc_nego[AFI_IP][SAFI_MULTICAST]
|
|| peer->afc_nego[AFI_IP][SAFI_MULTICAST]
|
||||||
|| peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
|
|| peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
|
||||||
|| peer->afc_nego[AFI_IP6][SAFI_UNICAST]
|
|| 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 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue