bgpd: labeled unicast processing

Implement support for negotiating IPv4 or IPv6 labeled-unicast address
family, exchanging prefixes and installing them in the routing table, as
well as interactions with Zebra for FEC registration. This is the
implementation of RFC 3107.

Signed-off-by: Don Slice <dslice@cumulusnetworks.com>
This commit is contained in:
Don Slice 2017-03-09 09:54:20 -05:00 committed by Donald Sharp
parent f51bae9cf9
commit cd1964ff38
21 changed files with 819 additions and 60 deletions

View File

@ -81,7 +81,7 @@ libbgp_a_SOURCES = \
bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \ bgp_damp.c bgp_table.c bgp_advertise.c bgp_vty.c bgp_mpath.c \
bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \ bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \
bgp_encap.c bgp_encap_tlv.c $(BGP_VNC_RFAPI_SRC) bgp_attr_evpn.c \ bgp_encap.c bgp_encap_tlv.c $(BGP_VNC_RFAPI_SRC) bgp_attr_evpn.c \
bgp_evpn.c bgp_evpn_vty.c bgp_vpn.c bgp_evpn.c bgp_evpn_vty.c bgp_vpn.c bgp_label.c
noinst_HEADERS = \ noinst_HEADERS = \
bgp_memory.h \ bgp_memory.h \
@ -92,7 +92,8 @@ noinst_HEADERS = \
bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \ bgp_mplsvpn.h bgp_nexthop.h bgp_damp.h bgp_table.h \
bgp_advertise.h bgp_vty.h bgp_mpath.h bgp_nht.h \ bgp_advertise.h bgp_vty.h bgp_mpath.h bgp_nht.h \
bgp_updgrp.h bgp_bfd.h bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h \ bgp_updgrp.h bgp_bfd.h bgp_encap.h bgp_encap_tlv.h bgp_encap_types.h \
$(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h bgp_vpn.h $(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h \
bgp_vpn.h bgp_label.h
bgpd_SOURCES = bgp_main.c bgpd_SOURCES = bgp_main.c
bgpd_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@ bgpd_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@

View File

@ -2748,6 +2748,7 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
{ {
case SAFI_UNICAST: case SAFI_UNICAST:
case SAFI_MULTICAST: case SAFI_MULTICAST:
case SAFI_LABELED_UNICAST:
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, 4); stream_putc (s, 4);
stream_put_ipv4 (s, attr->nexthop.s_addr); stream_put_ipv4 (s, attr->nexthop.s_addr);
@ -2772,6 +2773,7 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
{ {
case SAFI_UNICAST: case SAFI_UNICAST:
case SAFI_MULTICAST: case SAFI_MULTICAST:
case SAFI_LABELED_UNICAST:
{ {
struct attr_extra *attre = attr->extra; struct attr_extra *attre = attr->extra;
@ -2875,6 +2877,11 @@ bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
{ {
bgp_packet_mpattr_route_type_5(s, p, prd, tag, attr); bgp_packet_mpattr_route_type_5(s, p, prd, tag, attr);
} }
else if (safi == SAFI_LABELED_UNICAST)
{
/* Prefix write with label. */
stream_put_labeled_prefix(s, p, tag);
}
else else
stream_put_prefix_addpath (s, p, addpath_encode, addpath_tx_id); stream_put_prefix_addpath (s, p, addpath_encode, addpath_tx_id);
} }
@ -3112,7 +3119,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 (safi == SAFI_UNICAST && peer_cap_enhe(from)) else if (peer_cap_enhe(from))
{ {
/* /*
* Likely this is the case when an IPv4 prefix was received with * Likely this is the case when an IPv4 prefix was received with
@ -3439,6 +3446,11 @@ bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
u_char *tag, int addpath_encode, u_char *tag, int addpath_encode,
u_int32_t addpath_tx_id, struct attr *attr) u_int32_t addpath_tx_id, struct attr *attr)
{ {
u_char wlabel[3] = {0x80, 0x00, 0x00};
if (safi == SAFI_LABELED_UNICAST)
tag = wlabel;
return bgp_packet_mpattr_prefix (s, afi, safi, p, prd, return bgp_packet_mpattr_prefix (s, afi, safi, p, prd,
tag, addpath_encode, addpath_tx_id, attr); tag, addpath_encode, addpath_tx_id, attr);
} }

View File

@ -1142,9 +1142,11 @@ bgp_stop (struct peer *peer)
/* Reset prefix count */ /* Reset prefix count */
peer->pcount[AFI_IP][SAFI_UNICAST] = 0; peer->pcount[AFI_IP][SAFI_UNICAST] = 0;
peer->pcount[AFI_IP][SAFI_MULTICAST] = 0; peer->pcount[AFI_IP][SAFI_MULTICAST] = 0;
peer->pcount[AFI_IP][SAFI_LABELED_UNICAST] = 0;
peer->pcount[AFI_IP][SAFI_MPLS_VPN] = 0; peer->pcount[AFI_IP][SAFI_MPLS_VPN] = 0;
peer->pcount[AFI_IP6][SAFI_UNICAST] = 0; peer->pcount[AFI_IP6][SAFI_UNICAST] = 0;
peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0; peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
peer->pcount[AFI_IP6][SAFI_LABELED_UNICAST] = 0;
#endif /* 0 */ #endif /* 0 */
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) && if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) &&

318
bgpd/bgp_label.c Normal file
View File

@ -0,0 +1,318 @@
/* BGP carrying label information
* Copyright (C) 2013 Cumulus Networks, Inc.
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <zebra.h>
#include "command.h"
#include "thread.h"
#include "prefix.h"
#include "zclient.h"
#include "stream.h"
#include "network.h"
#include "log.h"
#include "memory.h"
#include "nexthop.h"
#include "mpls.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_label.h"
#include "bgpd/bgp_packet.h"
#include "bgpd/bgp_debug.h"
extern struct zclient *zclient;
int
bgp_parse_fec_update (void)
{
struct stream *s;
struct bgp_node *rn;
struct bgp *bgp;
struct bgp_table *table;
struct prefix p;
u_int32_t label;
afi_t afi;
safi_t safi;
s = zclient->ibuf;
memset(&p, 0, sizeof(struct prefix));
p.family = stream_getw(s);
p.prefixlen = stream_getc(s);
stream_get(&p.u.prefix, s, PSIZE(p.prefixlen));
label = stream_getl(s);
/* hack for the bgp instance & SAFI = have to send/receive it */
afi = family2afi(p.family);
safi = SAFI_LABELED_UNICAST;
bgp = bgp_get_default();
if (!bgp)
{
zlog_debug("no default bgp instance");
return -1;
}
table = bgp->rib[afi][safi];
if (!table)
{
zlog_debug("no %u labeled-unicast table", p.family);
return -1;
}
rn = bgp_node_lookup(table, &p);
if (!rn)
{
zlog_debug("no node for the prefix");
return -1;
}
/* treat it as implicit withdraw - the label is invalid */
if (label == MPLS_INVALID_LABEL)
bgp_unset_valid_label(rn->local_label);
else
{
label_ntop(label, 1, rn->local_label);
bgp_set_valid_label(rn->local_label);
}
SET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED);
bgp_unlock_node (rn);
bgp_process (bgp, rn, afi, safi);
return 1;
}
u_char *
bgp_adv_label (struct bgp_node *rn, struct bgp_info *ri, struct peer *to,
afi_t afi, safi_t safi)
{
struct peer *from;
u_char *remote_label;
int reflect;
if (!rn || !ri || !to)
return NULL;
remote_label = ri->extra ? ri->extra->tag : NULL;
from = ri->peer;
reflect = ((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP));
if (reflect && !CHECK_FLAG(to->af_flags[afi][safi],
PEER_FLAG_FORCE_NEXTHOP_SELF))
return remote_label;
if (CHECK_FLAG(to->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED))
return remote_label;
return rn->local_label;
}
void
bgp_reg_dereg_for_label (struct bgp_node *rn, int reg)
{
struct stream *s;
struct prefix *p;
int command;
/* Check socket. */
if (!zclient || zclient->sock < 0)
return;
p = &(rn->p);
s = zclient->obuf;
stream_reset (s);
command = (reg) ? ZEBRA_FEC_REGISTER : ZEBRA_FEC_UNREGISTER;
zclient_create_header (s, command, VRF_DEFAULT);
stream_putw(s, PREFIX_FAMILY(p));
stream_put_prefix(s, p);
stream_putw_at (s, 0, stream_get_endp (s));
zclient_send_message(zclient);
return;
}
static int
bgp_nlri_get_labels (struct peer *peer, u_char *pnt, u_char plen,
u_char label[])
{
u_char *data = pnt;
u_char *lim = pnt + plen;
u_char llen = 0;
for (; data < lim; data += BGP_LABEL_BYTES)
{
memcpy(label, data, BGP_LABEL_BYTES);
llen += 3;
if (bgp_is_withdraw_label(label) || label_bos(label))
break;
}
if (!(bgp_is_withdraw_label(label) || label_bos(label)))
zlog_warn("%s: [Update:RCVD] invalid label - no bottom of stack",
peer->host);
return llen;
}
int
bgp_nlri_parse_label (struct peer *peer, struct attr *attr,
struct bgp_nlri *packet)
{
u_char *pnt;
u_char *lim;
struct prefix p;
int psize = 0;
int prefixlen;
afi_t afi;
safi_t safi;
int addpath_encoded;
u_int32_t addpath_id;
u_char label[3];
u_char llen;
/* Check peer status. */
if (peer->status != Established)
return 0;
pnt = packet->nlri;
lim = pnt + packet->length;
afi = packet->afi;
safi = packet->safi;
addpath_id = 0;
addpath_encoded = (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_ADV) &&
CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_RCV));
for (; pnt < lim; pnt += psize)
{
/* Clear prefix structure. */
memset (&p, 0, sizeof (struct prefix));
llen = 0;
if (addpath_encoded)
{
/* When packet overflow occurs return immediately. */
if (pnt + BGP_ADDPATH_ID_LEN > lim)
return -1;
addpath_id = ntohl(*((uint32_t*) pnt));
pnt += BGP_ADDPATH_ID_LEN;
}
/* Fetch prefix length. */
prefixlen = *pnt++;
p.family = afi2family (packet->afi);
psize = PSIZE (prefixlen);
/* sanity check against packet data */
if ((pnt + psize) > lim)
{
zlog_err ("%s [Error] Update packet error / L-U (prefix length %d exceeds packet size %u)",
peer->host,
prefixlen, (uint)(lim-pnt));
return -1;
}
/* Fill in the labels */
llen = bgp_nlri_get_labels(peer, pnt, psize, label);
// zlog_debug("rcvd label [%x/%x/%x], llen=%d\n", label[0], label[1], label[2], llen);
p.prefixlen -= BSIZE(llen);
/* There needs to be at least one label */
if (prefixlen < 24)
{
zlog_err ("%s [Error] Update packet error"
" (wrong label length %d)",
peer->host, prefixlen);
bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
BGP_NOTIFY_UPDATE_INVAL_NETWORK);
return -1;
}
if ((afi == AFI_IP && p.prefixlen > 32)
|| (afi == AFI_IP6 && p.prefixlen > 128))
return -1;
/* Fetch prefix from NLRI packet */
memcpy (&p.u.prefix, pnt + llen, psize - llen);
/* Check address. */
if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST)
{
if (IN_CLASSD (ntohl (p.u.prefix4.s_addr)))
{
/* From RFC4271 Section 6.3:
*
* If a prefix in the NLRI field is semantically incorrect
* (e.g., an unexpected multicast IP address), an error SHOULD
* be logged locally, and the prefix SHOULD be ignored.
*/
zlog_err ("%s: IPv4 labeled-unicast NLRI is multicast address %s, ignoring",
peer->host, inet_ntoa (p.u.prefix4));
continue;
}
}
/* Check address. */
if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST)
{
if (IN6_IS_ADDR_LINKLOCAL (&p.u.prefix6))
{
char buf[BUFSIZ];
zlog_err ("%s: IPv6 labeled-unicast NLRI is link-local address %s, ignoring",
peer->host, inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ));
continue;
}
if (IN6_IS_ADDR_MULTICAST (&p.u.prefix6))
{
char buf[BUFSIZ];
zlog_err ("%s: IPv6 unicast NLRI is multicast address %s, ignoring",
peer->host, inet_ntop (AF_INET6, &p.u.prefix6, buf, BUFSIZ));
continue;
}
}
if (attr)
{
bgp_update (peer, &p, addpath_id, attr, packet->afi, SAFI_LABELED_UNICAST,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, label, 0, NULL);
}
else
{
bgp_withdraw (peer, &p, addpath_id, attr, packet->afi, SAFI_LABELED_UNICAST,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, label, NULL);
}
}
/* Packet length consistency check. */
if (pnt != lim)
{
zlog_err ("%s [Error] Update packet error / L-U (%zu data remaining after parsing)",
peer->host, lim - pnt);
return -1;
}
return 0;
}

124
bgpd/bgp_label.h Normal file
View File

@ -0,0 +1,124 @@
/* BGP carrying Label information
* Copyright (C) 2013 Cumulus Networks, Inc.
*
* This file is part of GNU Zebra.
*
* GNU Zebra is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Zebra; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef _BGP_LABEL_H
#define _BGP_LABEL_H
#define BGP_LABEL_BYTES 3
#define BGP_LABEL_BITS 24
#define BGP_WITHDRAW_LABEL 0x800000
struct bgp_node;
struct bgp_info;
struct peer;
extern void bgp_reg_dereg_for_label (struct bgp_node *rn, int reg);
extern int bgp_parse_fec_update(void);
extern u_char * bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri,
struct peer *to, afi_t afi, safi_t safi);
extern int bgp_nlri_parse_label (struct peer *peer, struct attr *attr,
struct bgp_nlri *packet);
static inline int
bgp_labeled_safi (safi_t safi)
{
if ((safi == SAFI_LABELED_UNICAST) || (safi == SAFI_MPLS_VPN))
return 1;
return 0;
}
static inline int
bgp_is_withdraw_label (u_char *pkt)
{
if ((pkt[0] == 0x80) && (pkt[1] == 0x00) && (pkt[2] == 0x00))
return 1;
return 0;
}
static inline u_char *
bgp_encode_withdraw_label (u_char *pkt)
{
*pkt++ = 0x80; *pkt++ = 0x00; *pkt++ = 0x00;
return pkt;
}
static inline int
bgp_is_valid_label (u_char *t)
{
if (!t)
return 0;
return (t[2] & 0x02);
}
static inline void
bgp_set_valid_label (u_char *t)
{
if (t)
t[2] |= 0x02;
}
static inline void
bgp_unset_valid_label (u_char *t)
{
if (t)
t[2] &= ~0x02;
}
static inline void
bgp_register_for_label (struct bgp_node *rn)
{
bgp_reg_dereg_for_label (rn, 1);
}
static inline void
bgp_unregister_for_label (struct bgp_node *rn)
{
bgp_reg_dereg_for_label (rn, 0);
}
/* Label stream to value */
static inline u_int32_t
label_pton (u_char t[])
{
return ((((unsigned int) t[0]) << 12) | (((unsigned int) t[1]) << 4) |
((unsigned int) ((t[2] & 0xF0) >> 4)));
}
/* Encode label values */
static inline void
label_ntop (u_int32_t l, int bos, u_char t[])
{
t[0] = ((l & 0x000FF000) >> 12);
t[1] = ((l & 0x00000FF0) >> 4);
t[2] = ((l & 0x0000000F) << 4);
if (bos)
t[2] |= 0x01;
}
/* Return BOS value of label stream */
static inline u_char
label_bos (u_char t[])
{
return (t[2] & 0x01);
};
#endif /* _BGP_LABEL_H */

View File

@ -235,6 +235,8 @@ bgp_exit (int status)
stream_free (bgp_nexthop_buf); stream_free (bgp_nexthop_buf);
if (bgp_ifindices_buf) if (bgp_ifindices_buf)
stream_free (bgp_ifindices_buf); stream_free (bgp_ifindices_buf);
if (bgp_label_buf)
stream_free (bgp_label_buf);
/* reverse bgp_master_init */ /* reverse bgp_master_init */
if (bm->master) if (bm->master)

View File

@ -404,8 +404,9 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
{ {
char buf[PREFIX2STR_BUFFER]; char buf[PREFIX2STR_BUFFER];
prefix2str(&p, buf, sizeof (buf)); prefix2str(&p, buf, sizeof (buf));
zlog_debug("%d: NH update for %s - metric %d (cur %d) #nhops %d (cur %d)", zlog_debug("%d: Rcvd NH update %s - metric %d/%d #nhops %d/%d flags 0x%x",
vrf_id, buf, metric, bnc->metric, nexthop_num, bnc->nexthop_num); vrf_id, buf, metric, bnc->metric, nexthop_num, bnc->nexthop_num,
bnc->flags);
} }
if (metric != bnc->metric) if (metric != bnc->metric)
@ -678,6 +679,8 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
struct bgp *bgp = bnc->bgp; struct bgp *bgp = bnc->bgp;
int afi; int afi;
struct peer *peer = (struct peer *)bnc->nht_info; struct peer *peer = (struct peer *)bnc->nht_info;
struct bgp_table *table;
safi_t safi;
if (BGP_DEBUG(nht, NHT)) if (BGP_DEBUG(nht, NHT))
{ {
@ -695,7 +698,10 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
continue; continue;
rn = path->net; rn = path->net;
assert (rn && bgp_node_table (rn));
afi = family2afi(rn->p.family); afi = family2afi(rn->p.family);
table = bgp_node_table (rn);
safi = table->safi;
/* Path becomes valid/invalid depending on whether the nexthop /* Path becomes valid/invalid depending on whether the nexthop
* reachable/unreachable. * reachable/unreachable.
@ -705,15 +711,13 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
{ {
if (CHECK_FLAG (path->flags, BGP_INFO_VALID)) if (CHECK_FLAG (path->flags, BGP_INFO_VALID))
{ {
bgp_aggregate_decrement (bgp, &rn->p, path, bgp_aggregate_decrement (bgp, &rn->p, path, afi, safi);
afi, SAFI_UNICAST);
bgp_info_unset_flag (rn, path, BGP_INFO_VALID); bgp_info_unset_flag (rn, path, BGP_INFO_VALID);
} }
else else
{ {
bgp_info_set_flag (rn, path, BGP_INFO_VALID); bgp_info_set_flag (rn, path, BGP_INFO_VALID);
bgp_aggregate_increment (bgp, &rn->p, path, bgp_aggregate_increment (bgp, &rn->p, path, afi, safi);
afi, SAFI_UNICAST);
} }
} }
@ -727,7 +731,7 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)) CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED))
SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED); SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED);
bgp_process(bgp, rn, afi, SAFI_UNICAST); bgp_process(bgp, rn, afi, safi);
} }
if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED)) if (peer && !CHECK_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED))

View File

@ -108,6 +108,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
case SAFI_MULTICAST: case SAFI_MULTICAST:
json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "multicast"); json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "multicast");
break; break;
case SAFI_LABELED_UNICAST:
json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "labeled-unicast");
break;
case SAFI_MPLS_VPN: case SAFI_MPLS_VPN:
json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "MPLS-labeled VPN"); json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "MPLS-labeled VPN");
break; break;
@ -148,6 +151,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
case SAFI_MULTICAST: case SAFI_MULTICAST:
vty_out (vty, "SAFI Multicast"); vty_out (vty, "SAFI Multicast");
break; break;
case SAFI_LABELED_UNICAST:
vty_out (vty, "SAFI Labeled-unicast");
break;
case SAFI_MPLS_VPN: case SAFI_MPLS_VPN:
vty_out (vty, "SAFI MPLS-labeled VPN"); vty_out (vty, "SAFI MPLS-labeled VPN");
break; break;
@ -1143,10 +1149,12 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
{ {
if (! peer->afc_nego[AFI_IP][SAFI_UNICAST] if (! peer->afc_nego[AFI_IP][SAFI_UNICAST]
&& ! peer->afc_nego[AFI_IP][SAFI_MULTICAST] && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
&& ! peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST]
&& ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
&& ! peer->afc_nego[AFI_IP][SAFI_ENCAP] && ! peer->afc_nego[AFI_IP][SAFI_ENCAP]
&& ! 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_LABELED_UNICAST]
&& ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] && ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
&& ! peer->afc_nego[AFI_IP6][SAFI_ENCAP] && ! peer->afc_nego[AFI_IP6][SAFI_ENCAP]
&& ! peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) && ! peer->afc_nego[AFI_L2VPN][SAFI_EVPN])

View File

@ -55,6 +55,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_advertise.h" #include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_vty.h" #include "bgpd/bgp_vty.h"
#include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_updgrp.h"
#include "bgpd/bgp_label.h"
/* Set up BGP packet marker and packet type. */ /* Set up BGP packet marker and packet type. */
int int
@ -1153,8 +1154,10 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
{ {
peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST]; peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST]; peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST] = peer->afc[AFI_IP][SAFI_LABELED_UNICAST];
peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST]; peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST]; peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST] = peer->afc[AFI_IP6][SAFI_LABELED_UNICAST];
} }
/* When collision is detected and this peer is closed. Retrun /* When collision is detected and this peer is closed. Retrun
@ -1342,6 +1345,8 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet, i
case SAFI_UNICAST: case SAFI_UNICAST:
case SAFI_MULTICAST: case SAFI_MULTICAST:
return bgp_nlri_parse_ip (peer, mp_withdraw?NULL:attr, packet); return bgp_nlri_parse_ip (peer, mp_withdraw?NULL:attr, packet);
case SAFI_LABELED_UNICAST:
return bgp_nlri_parse_label (peer, attr, packet);
case SAFI_MPLS_VPN: case SAFI_MPLS_VPN:
return bgp_nlri_parse_vpn (peer, mp_withdraw?NULL:attr, packet); return bgp_nlri_parse_vpn (peer, mp_withdraw?NULL:attr, packet);
case SAFI_ENCAP: case SAFI_ENCAP:

View File

@ -35,6 +35,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "thread.h" #include "thread.h"
#include "workqueue.h" #include "workqueue.h"
#include "queue.h" #include "queue.h"
#include "mpls.h"
#include "memory.h" #include "memory.h"
#include "lib/json.h" #include "lib/json.h"
@ -62,6 +63,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "bgpd/bgp_mpath.h" #include "bgpd/bgp_mpath.h"
#include "bgpd/bgp_nht.h" #include "bgpd/bgp_nht.h"
#include "bgpd/bgp_updgrp.h" #include "bgpd/bgp_updgrp.h"
#include "bgpd/bgp_label.h"
#if ENABLE_BGP_VNC #if ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h" #include "bgpd/rfapi/rfapi_backend.h"
@ -1187,7 +1189,8 @@ subgroup_announce_reset_nhop (u_char family, struct attr *attr)
} }
int int
subgroup_announce_check (struct bgp_info *ri, struct update_subgroup *subgrp, subgroup_announce_check (struct bgp_node *rn, struct bgp_info *ri,
struct update_subgroup *subgrp,
struct prefix *p, struct attr *attr) struct prefix *p, struct attr *attr)
{ {
struct bgp_filter *filter; struct bgp_filter *filter;
@ -1261,6 +1264,21 @@ subgroup_announce_check (struct bgp_info *ri, struct update_subgroup *subgrp,
return 0; return 0;
} }
/* If it's labeled safi, make sure the route has a valid label. */
if (bgp_labeled_safi(safi))
{
u_char *tag = bgp_adv_label(rn, ri, peer, afi, safi);
if (!bgp_is_valid_label(tag))
{
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " %s/%d is filtered - no label (%p)",
subgrp->update_group->id, subgrp->id,
inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN),
p->prefixlen, tag);
return 0;
}
}
/* Do not send back route to sender. */ /* Do not send back route to sender. */
if (onlypeer && from == onlypeer) if (onlypeer && from == onlypeer)
{ {
@ -1804,7 +1822,7 @@ subgroup_process_announce_selected (struct update_subgroup *subgrp,
/* Announcement to the subgroup. If the route is filtered withdraw it. */ /* Announcement to the subgroup. If the route is filtered withdraw it. */
if (selected) if (selected)
{ {
if (subgroup_announce_check(selected, subgrp, p, &attr)) if (subgroup_announce_check(rn, selected, subgrp, p, &attr))
bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected); bgp_adj_out_set_subgroup(rn, subgrp, &attr, selected);
else else
bgp_adj_out_unset_subgroup(rn, subgrp, 1, selected->addpath_tx_id); bgp_adj_out_unset_subgroup(rn, subgrp, 1, selected->addpath_tx_id);
@ -1890,6 +1908,7 @@ bgp_process_main (struct work_queue *wq, void *data)
struct bgp_info *new_select; struct bgp_info *new_select;
struct bgp_info *old_select; struct bgp_info *old_select;
struct bgp_info_pair old_and_new; struct bgp_info_pair old_and_new;
int label_valid;
/* Is it end of initial update? (after startup) */ /* Is it end of initial update? (after startup) */
if (!rn) if (!rn)
@ -1914,7 +1933,24 @@ bgp_process_main (struct work_queue *wq, void *data)
old_select = old_and_new.old; old_select = old_and_new.old;
new_select = old_and_new.new; new_select = old_and_new.new;
/* Nothing to do. */ /* Do we need to allocate or free labels?
* Right now, since we only deal with per-prefix labels, it is not necessary
* to do this upon changes to best path.
*/
bgp_table_lock (bgp_node_table (rn));
if (bgp_labeled_safi (safi))
{
label_valid = bgp_is_valid_label (rn->local_label);
if (!old_select && new_select && !label_valid)
bgp_register_for_label (rn);
else if (old_select && !new_select)
bgp_unregister_for_label (rn);
}
/* If best route remains the same and this is not due to user-initiated
* clear, see exactly what needs to be done.
*/
if (old_select && old_select == new_select && if (old_select && old_select == new_select &&
!CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR) && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR) &&
!CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) && !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) &&
@ -1926,10 +1962,26 @@ bgp_process_main (struct work_queue *wq, void *data)
vnc_import_bgp_add_route(bgp, p, old_select); vnc_import_bgp_add_route(bgp, p, old_select);
vnc_import_bgp_exterior_add_route(bgp, p, old_select); vnc_import_bgp_exterior_add_route(bgp, p, old_select);
#endif #endif
bgp_zebra_announce (p, old_select, bgp, afi, safi); if (bgp_fibupd_safi(safi) &&
!bgp->name &&
!bgp_option_check (BGP_OPT_NO_FIB) &&
new_select->type == ZEBRA_ROUTE_BGP &&
new_select->sub_type == BGP_ROUTE_NORMAL)
bgp_zebra_announce (rn, p, old_select, bgp, afi, safi);
} }
UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG); UNSET_FLAG (old_select->flags, BGP_INFO_MULTIPATH_CHG);
bgp_zebra_clear_route_change_flags (rn); bgp_zebra_clear_route_change_flags (rn);
/* If there is a change of interest to peers, reannounce the route. */
if (CHECK_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED) ||
CHECK_FLAG (rn->flags, BGP_NODE_LABEL_CHANGED))
{
group_announce_route(bgp, afi, safi, rn, new_select);
UNSET_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED);
UNSET_FLAG (rn->flags, BGP_NODE_LABEL_CHANGED);
}
UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED); UNSET_FLAG (rn->flags, BGP_NODE_PROCESS_SCHEDULED);
return WQ_SUCCESS; return WQ_SUCCESS;
} }
@ -1978,7 +2030,7 @@ bgp_process_main (struct work_queue *wq, void *data)
group_announce_route(bgp, afi, safi, rn, new_select); group_announce_route(bgp, afi, safi, rn, new_select);
/* FIB update. */ /* FIB update. */
if ((safi == SAFI_UNICAST || safi == SAFI_MULTICAST) && if (bgp_fibupd_safi(safi) &&
(bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) &&
!bgp_option_check (BGP_OPT_NO_FIB)) !bgp_option_check (BGP_OPT_NO_FIB))
{ {
@ -1986,7 +2038,7 @@ bgp_process_main (struct work_queue *wq, void *data)
&& new_select->type == ZEBRA_ROUTE_BGP && new_select->type == ZEBRA_ROUTE_BGP
&& (new_select->sub_type == BGP_ROUTE_NORMAL || && (new_select->sub_type == BGP_ROUTE_NORMAL ||
new_select->sub_type == BGP_ROUTE_AGGREGATE)) new_select->sub_type == BGP_ROUTE_AGGREGATE))
bgp_zebra_announce (p, new_select, bgp, afi, safi); bgp_zebra_announce (rn, p, new_select, bgp, afi, safi);
else else
{ {
/* Withdraw the route from the kernel. */ /* Withdraw the route from the kernel. */
@ -2406,6 +2458,7 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
struct bgp_info *new; struct bgp_info *new;
const char *reason; const char *reason;
char pfx_buf[BGP_PRD_PATH_STRLEN]; char pfx_buf[BGP_PRD_PATH_STRLEN];
char label_buf[20];
int connected = 0; int connected = 0;
int do_loop_check = 1; int do_loop_check = 1;
#if ENABLE_BGP_VNC #if ENABLE_BGP_VNC
@ -2417,6 +2470,9 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
bgp = peer->bgp; bgp = peer->bgp;
rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd); rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd);
label_buf[0] = '\0';
if (bgp_labeled_safi(safi))
sprintf (label_buf, "label %u", label_pton(tag));
/* When peer's soft reconfiguration enabled. Record input packet in /* When peer's soft reconfiguration enabled. Record input packet in
Adj-RIBs-In. */ Adj-RIBs-In. */
@ -2516,6 +2572,8 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
/* Same attribute comes in. */ /* Same attribute comes in. */
if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED) if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED)
&& attrhash_cmp (ri->attr, attr_new) && attrhash_cmp (ri->attr, attr_new)
&& (!bgp_labeled_safi(safi) ||
memcmp ((bgp_info_extra_get (ri))->tag, tag, 3) == 0)
&& (overlay_index_equal(afi, ri, evpn==NULL?NULL:&evpn->eth_s_id, && (overlay_index_equal(afi, ri, evpn==NULL?NULL:&evpn->eth_s_id,
evpn==NULL?NULL:&evpn->gw_ip))) evpn==NULL?NULL:&evpn->gw_ip)))
{ {
@ -2524,9 +2582,9 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
&& CHECK_FLAG (ri->flags, BGP_INFO_HISTORY)) && CHECK_FLAG (ri->flags, BGP_INFO_HISTORY))
{ {
if (bgp_debug_update(peer, p, NULL, 1)) if (bgp_debug_update(peer, p, NULL, 1))
zlog_debug ("%s rcvd %s", peer->host, zlog_debug ("%s rcvd %s %s", peer->host,
bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0, bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0,
addpath_id, pfx_buf, sizeof (pfx_buf))); addpath_id, pfx_buf, sizeof (pfx_buf)), label_buf);
if (bgp_damp_update (ri, rn, afi, safi) != BGP_DAMP_SUPPRESSED) if (bgp_damp_update (ri, rn, afi, safi) != BGP_DAMP_SUPPRESSED)
{ {
@ -2544,10 +2602,10 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
peer->rcvd_attr_printed = 1; peer->rcvd_attr_printed = 1;
} }
zlog_debug ("%s rcvd %s...duplicate ignored", zlog_debug ("%s rcvd %s %s...duplicate ignored",
peer->host, peer->host,
bgp_debug_rdpfxpath2str (prd, p, addpath_id ? bgp_debug_rdpfxpath2str (prd, p, addpath_id ?
1 : 0, addpath_id, pfx_buf, sizeof (pfx_buf))); 1 : 0, addpath_id, pfx_buf, sizeof (pfx_buf)), label_buf);
} }
/* graceful restart STALE flag unset. */ /* graceful restart STALE flag unset. */
@ -2568,18 +2626,18 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
{ {
if (bgp_debug_update(peer, p, NULL, 1)) if (bgp_debug_update(peer, p, NULL, 1))
zlog_debug ("%s rcvd %s, flapped quicker than processing", zlog_debug ("%s rcvd %s %s, flapped quicker than processing",
peer->host, peer->host,
bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0, bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0,
addpath_id, pfx_buf, sizeof (pfx_buf))); addpath_id, pfx_buf, sizeof (pfx_buf)), label_buf);
bgp_info_restore (rn, ri); bgp_info_restore (rn, ri);
} }
/* Received Logging. */ /* Received Logging. */
if (bgp_debug_update(peer, p, NULL, 1)) if (bgp_debug_update(peer, p, NULL, 1))
zlog_debug ("%s rcvd %s", peer->host, zlog_debug ("%s rcvd %s %s", peer->host,
bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0, bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0,
addpath_id, pfx_buf, sizeof (pfx_buf))); addpath_id, pfx_buf, sizeof (pfx_buf)), label_buf);
/* graceful restart STALE flag unset. */ /* graceful restart STALE flag unset. */
if (CHECK_FLAG (ri->flags, BGP_INFO_STALE)) if (CHECK_FLAG (ri->flags, BGP_INFO_STALE))
@ -2637,7 +2695,7 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
ri->attr = attr_new; ri->attr = attr_new;
/* Update MPLS tag. */ /* Update MPLS tag. */
if (safi == SAFI_MPLS_VPN || safi == SAFI_EVPN) if (bgp_labeled_safi(safi))
memcpy ((bgp_info_extra_get (ri))->tag, tag, 3); memcpy ((bgp_info_extra_get (ri))->tag, tag, 3);
#if ENABLE_BGP_VNC #if ENABLE_BGP_VNC
@ -2678,8 +2736,9 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
} }
} }
/* Nexthop reachability check. */ /* Nexthop reachability check - for unicast and labeled-unicast.. */
if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST) if ((afi == AFI_IP || afi == AFI_IP6) &&
(safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
{ {
if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 && if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 &&
! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
@ -2759,16 +2818,16 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
peer->rcvd_attr_printed = 1; peer->rcvd_attr_printed = 1;
} }
zlog_debug ("%s rcvd %s", peer->host, zlog_debug ("%s rcvd %s%s ", peer->host,
bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0, bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0,
addpath_id, pfx_buf, sizeof (pfx_buf))); addpath_id, pfx_buf, sizeof (pfx_buf)), label_buf);
} }
/* Make new BGP info. */ /* Make new BGP info. */
new = info_make(type, sub_type, 0, peer, attr_new, rn); new = info_make(type, sub_type, 0, peer, attr_new, rn);
/* Update MPLS tag. */ /* Update MPLS tag. */
if (safi == SAFI_MPLS_VPN || safi == SAFI_EVPN) if (bgp_labeled_safi(safi) || safi == SAFI_EVPN)
memcpy ((bgp_info_extra_get (new))->tag, tag, 3); memcpy ((bgp_info_extra_get (new))->tag, tag, 3);
/* Update Overlay Index */ /* Update Overlay Index */
@ -2778,7 +2837,8 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
evpn==NULL?NULL:&evpn->gw_ip); evpn==NULL?NULL:&evpn->gw_ip);
} }
/* Nexthop reachability check. */ /* Nexthop reachability check. */
if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST) if ((afi == AFI_IP || afi == AFI_IP6) &&
(safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
{ {
if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 && if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 &&
! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) ! CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
@ -2873,10 +2933,10 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
peer->rcvd_attr_printed = 1; peer->rcvd_attr_printed = 1;
} }
zlog_debug ("%s rcvd UPDATE about %s -- DENIED due to: %s", zlog_debug ("%s rcvd UPDATE about %s %s -- DENIED due to: %s",
peer->host, peer->host,
bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0, bgp_debug_rdpfxpath2str (prd, p, addpath_id ? 1 : 0,
addpath_id, pfx_buf, sizeof (pfx_buf)), reason); addpath_id, pfx_buf, sizeof (pfx_buf)), label_buf, reason);
} }
if (ri) if (ri)
@ -3818,9 +3878,11 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
#endif #endif
/* Nexthop reachability check. */ /* Nexthop reachability check. */
if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK)) if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK) &&
safi == SAFI_UNICAST)
{ {
if (bgp_find_or_add_nexthop (bgp, afi, ri, NULL, 0)) if (bgp_find_or_add_nexthop (bgp, afi, ri, NULL, 0) &&
safi == SAFI_UNICAST)
bgp_info_set_flag (rn, ri, BGP_INFO_VALID); bgp_info_set_flag (rn, ri, BGP_INFO_VALID);
else else
{ {
@ -5557,6 +5619,8 @@ bgp_aggregate_unset (struct vty *vty, const char *prefix_str,
aggregate = rn->info; aggregate = rn->info;
if (aggregate->safi & SAFI_UNICAST) if (aggregate->safi & SAFI_UNICAST)
bgp_aggregate_delete (bgp, &p, afi, SAFI_UNICAST, aggregate); bgp_aggregate_delete (bgp, &p, afi, SAFI_UNICAST, aggregate);
if (aggregate->safi & SAFI_LABELED_UNICAST)
bgp_aggregate_delete (bgp, &p, afi, SAFI_LABELED_UNICAST, aggregate);
if (aggregate->safi & SAFI_MULTICAST) if (aggregate->safi & SAFI_MULTICAST)
bgp_aggregate_delete (bgp, &p, afi, SAFI_MULTICAST, aggregate); bgp_aggregate_delete (bgp, &p, afi, SAFI_MULTICAST, aggregate);
@ -5615,6 +5679,8 @@ bgp_aggregate_set (struct vty *vty, const char *prefix_str,
/* Aggregate address insert into BGP routing table. */ /* Aggregate address insert into BGP routing table. */
if (safi & SAFI_UNICAST) if (safi & SAFI_UNICAST)
bgp_aggregate_add (bgp, &p, afi, SAFI_UNICAST, aggregate); bgp_aggregate_add (bgp, &p, afi, SAFI_UNICAST, aggregate);
if (safi & SAFI_LABELED_UNICAST)
bgp_aggregate_add (bgp, &p, afi, SAFI_LABELED_UNICAST, aggregate);
if (safi & SAFI_MULTICAST) if (safi & SAFI_MULTICAST)
bgp_aggregate_add (bgp, &p, afi, SAFI_MULTICAST, aggregate); bgp_aggregate_add (bgp, &p, afi, SAFI_MULTICAST, aggregate);
@ -7439,6 +7505,15 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
if (binfo->extra && binfo->extra->damp_info) if (binfo->extra && binfo->extra->damp_info)
bgp_damp_info_vty (vty, binfo, json_path); bgp_damp_info_vty (vty, binfo, json_path);
if (bgp_labeled_safi(safi) && binfo->extra)
{
uint32_t label = label_pton(binfo->extra->tag);
if (json_paths)
json_object_int_add(json_path, "remote-label", label);
else
vty_out(vty, " Remote label: %d%s", label, VTY_NEWLINE);
}
/* Line 8 display Addpath IDs */ /* Line 8 display Addpath IDs */
if (binfo->addpath_rx_id || binfo->addpath_tx_id) if (binfo->addpath_rx_id || binfo->addpath_tx_id)
{ {
@ -7932,6 +8007,18 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) ? ":" : "", ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) ? ":" : "",
buf2, buf2,
p->prefixlen, VTY_NEWLINE); p->prefixlen, VTY_NEWLINE);
if (bgp_labeled_safi(safi))
{
vty_out(vty, "Local label: ");
if (!bgp_is_valid_label(rn->local_label))
vty_out(vty, "not allocated%s", VTY_NEWLINE);
else
{
uint32_t label = label_pton(rn->local_label);
vty_out(vty, "%d%s", label, VTY_NEWLINE);
}
}
} }
for (ri = rn->info; ri; ri = ri->next) for (ri = rn->info; ri; ri = ri->next)

View File

@ -150,6 +150,7 @@ struct bgp_info
#define BGP_INFO_COUNTED (1 << 10) #define BGP_INFO_COUNTED (1 << 10)
#define BGP_INFO_MULTIPATH (1 << 11) #define BGP_INFO_MULTIPATH (1 << 11)
#define BGP_INFO_MULTIPATH_CHG (1 << 12) #define BGP_INFO_MULTIPATH_CHG (1 << 12)
#define BGP_INFO_RIB_ATTR_CHG (1 << 13)
/* BGP route type. This can be static, RIP, OSPF, BGP etc. */ /* BGP route type. This can be static, RIP, OSPF, BGP etc. */
u_char type; u_char type;
@ -273,6 +274,16 @@ bgp_bump_version (struct bgp_node *node)
node->version = bgp_table_next_version(bgp_node_table(node)); node->version = bgp_table_next_version(bgp_node_table(node));
} }
static inline int
bgp_fibupd_safi (safi_t safi)
{
if (safi == SAFI_UNICAST ||
safi == SAFI_MULTICAST ||
safi == SAFI_LABELED_UNICAST)
return 1;
return 0;
}
/* Prototypes. */ /* Prototypes. */
extern void bgp_process_queue_init (void); extern void bgp_process_queue_init (void);
extern void bgp_route_init (void); extern void bgp_route_init (void);
@ -370,7 +381,7 @@ subgroup_process_announce_selected (struct update_subgroup *subgrp,
struct bgp_node *rn, struct bgp_node *rn,
u_int32_t addpath_tx_id); u_int32_t addpath_tx_id);
extern int subgroup_announce_check(struct bgp_info *ri, extern int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri,
struct update_subgroup *subgrp, struct update_subgroup *subgrp,
struct prefix *p, struct attr *attr); struct prefix *p, struct attr *attr);

View File

@ -56,10 +56,13 @@ struct bgp_node
struct bgp_node *prn; struct bgp_node *prn;
u_char local_label[3];
uint64_t version; uint64_t version;
u_char flags; u_char flags;
#define BGP_NODE_PROCESS_SCHEDULED (1 << 0) #define BGP_NODE_PROCESS_SCHEDULED (1 << 0)
#define BGP_NODE_USER_CLEAR (1 << 1) #define BGP_NODE_USER_CLEAR (1 << 1)
#define BGP_NODE_LABEL_CHANGED (1 << 2)
}; };
/* /*

View File

@ -618,7 +618,7 @@ subgroup_announce_table (struct update_subgroup *subgrp,
if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) || if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) ||
(addpath_capable && bgp_addpath_tx_path(peer, afi, safi, ri))) (addpath_capable && bgp_addpath_tx_path(peer, afi, safi, ri)))
{ {
if (subgroup_announce_check (ri, subgrp, &rn->p, &attr)) if (subgroup_announce_check (rn, ri, subgrp, &rn->p, &attr))
bgp_adj_out_set_subgroup (rn, subgrp, &attr, ri); bgp_adj_out_set_subgroup (rn, subgrp, &attr, ri);
else else
bgp_adj_out_unset_subgroup (rn, subgrp, 1, ri->addpath_tx_id); bgp_adj_out_unset_subgroup (rn, subgrp, 1, ri->addpath_tx_id);

View File

@ -43,6 +43,7 @@
#include "workqueue.h" #include "workqueue.h"
#include "hash.h" #include "hash.h"
#include "queue.h" #include "queue.h"
#include "mpls.h"
#include "bgpd/bgpd.h" #include "bgpd/bgpd.h"
#include "bgpd/bgp_debug.h" #include "bgpd/bgp_debug.h"
@ -54,6 +55,7 @@
#include "bgpd/bgp_nexthop.h" #include "bgpd/bgp_nexthop.h"
#include "bgpd/bgp_nht.h" #include "bgpd/bgp_nht.h"
#include "bgpd/bgp_mplsvpn.h" #include "bgpd/bgp_mplsvpn.h"
#include "bgpd/bgp_label.h"
/******************** /********************
* PRIVATE FUNCTIONS * PRIVATE FUNCTIONS
@ -653,6 +655,7 @@ subgroup_update_packet (struct update_subgroup *subgrp)
int addpath_encode = 0; int addpath_encode = 0;
u_int32_t addpath_tx_id = 0; u_int32_t addpath_tx_id = 0;
struct prefix_rd *prd = NULL; struct prefix_rd *prd = NULL;
char label_buf[20];
if (!subgrp) if (!subgrp)
return NULL; return NULL;
@ -660,7 +663,6 @@ subgroup_update_packet (struct update_subgroup *subgrp)
if (bpacket_queue_is_full (SUBGRP_INST (subgrp), SUBGRP_PKTQ (subgrp))) if (bpacket_queue_is_full (SUBGRP_INST (subgrp), SUBGRP_PKTQ (subgrp)))
return NULL; return NULL;
peer = SUBGRP_PEER (subgrp); peer = SUBGRP_PEER (subgrp);
afi = SUBGRP_AFI (subgrp); afi = SUBGRP_AFI (subgrp);
safi = SUBGRP_SAFI (subgrp); safi = SUBGRP_SAFI (subgrp);
@ -668,6 +670,7 @@ subgroup_update_packet (struct update_subgroup *subgrp)
stream_reset (s); stream_reset (s);
snlri = subgrp->scratch; snlri = subgrp->scratch;
stream_reset (snlri); stream_reset (snlri);
label_buf[0] = '\0';
bpacket_attr_vec_arr_reset (&vecarr); bpacket_attr_vec_arr_reset (&vecarr);
@ -760,8 +763,9 @@ subgroup_update_packet (struct update_subgroup *subgrp)
if (rn->prn) if (rn->prn)
prd = (struct prefix_rd *) &rn->prn->p; prd = (struct prefix_rd *) &rn->prn->p;
if (binfo && binfo->extra) tag = bgp_adv_label(rn, binfo, peer, afi, safi);
tag = binfo->extra->tag; if (bgp_labeled_safi(safi))
sprintf (label_buf, "label %u", label_pton(tag));
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,
@ -797,11 +801,12 @@ subgroup_update_packet (struct update_subgroup *subgrp)
send_attr_printed = 1; send_attr_printed = 1;
} }
zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s", zlog_debug ("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s %s",
subgrp->update_group->id, subgrp->id, subgrp->update_group->id, subgrp->id,
bgp_debug_rdpfxpath2str (prd, &rn->p, addpath_encode, bgp_debug_rdpfxpath2str (prd, &rn->p, addpath_encode,
addpath_tx_id, addpath_tx_id,
pfx_buf, sizeof (pfx_buf))); pfx_buf, sizeof (pfx_buf)),
label_buf);
} }
/* Synchnorize attribute. */ /* Synchnorize attribute. */

View File

@ -34,6 +34,7 @@ Boston, MA 02111-1307, USA. */
#include "lib/json.h" #include "lib/json.h"
#include "lib/bfd.h" #include "lib/bfd.h"
#include "filter.h" #include "filter.h"
#include "mpls.h"
#include "bgpd/bgpd.h" #include "bgpd/bgpd.h"
#include "bgpd/bgp_route.h" #include "bgpd/bgp_route.h"
@ -46,6 +47,7 @@ Boston, MA 02111-1307, USA. */
#include "bgpd/bgp_nexthop.h" #include "bgpd/bgp_nexthop.h"
#include "bgpd/bgp_nht.h" #include "bgpd/bgp_nht.h"
#include "bgpd/bgp_bfd.h" #include "bgpd/bgp_bfd.h"
#include "bgpd/bgp_label.h"
#if ENABLE_BGP_VNC #if ENABLE_BGP_VNC
# include "bgpd/rfapi/rfapi_backend.h" # include "bgpd/rfapi/rfapi_backend.h"
# include "bgpd/rfapi/vnc_export_bgp.h" # include "bgpd/rfapi/vnc_export_bgp.h"
@ -57,6 +59,7 @@ struct zclient *zclient = NULL;
/* Growable buffer for nexthops sent to zebra */ /* Growable buffer for nexthops sent to zebra */
struct stream *bgp_nexthop_buf = NULL; struct stream *bgp_nexthop_buf = NULL;
struct stream *bgp_ifindices_buf = NULL; struct stream *bgp_ifindices_buf = NULL;
struct stream *bgp_label_buf = NULL;
/* These array buffers are used in making a copy of the attributes for /* These array buffers are used in making a copy of the attributes for
route-map apply. Arrays are being used here to minimize mallocs and route-map apply. Arrays are being used here to minimize mallocs and
@ -178,6 +181,14 @@ bgp_update_interface_nbrs (struct bgp *bgp, struct interface *ifp,
} }
} }
static int
bgp_read_fec_update (int command, struct zclient *zclient,
zebra_size_t length)
{
bgp_parse_fec_update();
return 0;
}
static void static void
bgp_start_interface_nbrs (struct bgp *bgp, struct interface *ifp) bgp_start_interface_nbrs (struct bgp *bgp, struct interface *ifp)
{ {
@ -1204,8 +1215,8 @@ bgp_table_map_apply (struct route_map *map, struct prefix *p,
} }
void void
bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info,
afi_t afi, safi_t safi) struct bgp *bgp, afi_t afi, safi_t safi)
{ {
u_int32_t flags; u_int32_t flags;
u_char distance; u_char distance;
@ -1216,6 +1227,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
struct bgp_info local_info; struct bgp_info local_info;
struct bgp_info *info_cp = &local_info; struct bgp_info *info_cp = &local_info;
route_tag_t tag; route_tag_t tag;
u_int32_t label;
/* Don't try to install if we're not connected to Zebra or Zebra doesn't /* Don't try to install if we're not connected to Zebra or Zebra doesn't
* know of this instance. * know of this instance.
@ -1271,7 +1283,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
if ((oldsize = stream_get_size (bgp_nexthop_buf)) < if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
(sizeof (struct in_addr *) * nhcount)) (sizeof (struct in_addr *) * nhcount))
{ {
newsize = (sizeof (struct in_addr *) * nhcount); newsize = sizeof (struct in_addr *) * nhcount;
newsize = stream_resize (bgp_nexthop_buf, newsize); newsize = stream_resize (bgp_nexthop_buf, newsize);
if (newsize == oldsize) if (newsize == oldsize)
{ {
@ -1282,6 +1294,25 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
stream_reset (bgp_nexthop_buf); stream_reset (bgp_nexthop_buf);
nexthop = NULL; nexthop = NULL;
/* For labeled unicast, each nexthop has a label too. Resize label
* buffer, if required.
*/
if (safi == SAFI_LABELED_UNICAST)
{
if ((oldsize = stream_get_size (bgp_label_buf)) <
(sizeof (unsigned int) * nhcount))
{
newsize = (sizeof (unsigned int) * nhcount);
newsize = stream_resize (bgp_label_buf, newsize);
if (newsize == oldsize)
{
zlog_err ("can't resize label buffer");
return;
}
}
stream_reset (bgp_label_buf);
}
/* Metric is currently based on the best-path only. */ /* Metric is currently based on the best-path only. */
metric = info->attr->med; metric = info->attr->med;
@ -1311,6 +1342,11 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
{ {
stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *)); stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
valid_nh_count++; valid_nh_count++;
if (safi == SAFI_LABELED_UNICAST)
{
label = label_pton(info->extra->tag);
stream_put (bgp_label_buf, &label, sizeof (u_int32_t));
}
} }
for (mpinfo = bgp_info_mpath_first (info); mpinfo; for (mpinfo = bgp_info_mpath_first (info); mpinfo;
@ -1336,6 +1372,11 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
continue; continue;
stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *)); stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
if (safi == SAFI_LABELED_UNICAST)
{
label = label_pton(mpinfo->extra->tag);
stream_put (bgp_label_buf, &label, sizeof (u_int32_t));
}
valid_nh_count++; valid_nh_count++;
} }
@ -1344,8 +1385,10 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
api.type = ZEBRA_ROUTE_BGP; api.type = ZEBRA_ROUTE_BGP;
api.instance = 0; api.instance = 0;
api.message = 0; api.message = 0;
api.safi = safi; api.safi = (safi == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
if (safi == SAFI_LABELED_UNICAST)
SET_FLAG (api.message, ZAPI_MESSAGE_LABEL);
/* Note that this currently only applies to Null0 routes for aggregates. /* Note that this currently only applies to Null0 routes for aggregates.
* ZEBRA_FLAG_BLACKHOLE signals zapi_ipv4_route to encode a special * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv4_route to encode a special
@ -1358,6 +1401,16 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
api.nexthop_num = valid_nh_count; api.nexthop_num = valid_nh_count;
api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf); api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf);
if (safi == SAFI_LABELED_UNICAST)
{
api.label_num = valid_nh_count;
api.label = (unsigned int *)STREAM_DATA (bgp_label_buf);
}
else
{
api.label_num = 0;
api.label = NULL;
}
api.ifindex_num = 0; api.ifindex_num = 0;
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
api.metric = metric; api.metric = metric;
@ -1379,14 +1432,22 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
if (bgp_debug_zebra(p)) if (bgp_debug_zebra(p))
{ {
int i; int i;
char label_buf[20];
zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI
" count %d", (valid_nh_count ? "add":"delete"), " count %d", (valid_nh_count ? "add":"delete"),
bgp->vrf_id, bgp->vrf_id,
inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
p->prefixlen, api.metric, api.tag, api.nexthop_num); p->prefixlen, api.metric, api.tag, api.nexthop_num);
for (i = 0; i < api.nexthop_num; i++) for (i = 0; i < api.nexthop_num; i++)
zlog_debug(" IPv4 [nexthop %d] %s", i+1, {
inet_ntop(AF_INET, api.nexthop[i], buf[1], sizeof(buf[1]))); label_buf[0] = '\0';
if (safi == SAFI_LABELED_UNICAST)
sprintf(label_buf, "label %u", api.label[i]);
zlog_debug(" nhop [%d]: %s %s",
i+1,
inet_ntop(AF_INET, api.nexthop[i], buf[1], sizeof(buf[1])),
label_buf);
}
} }
zapi_ipv4_route (valid_nh_count ? ZEBRA_IPV4_ROUTE_ADD: ZEBRA_IPV4_ROUTE_DELETE, zapi_ipv4_route (valid_nh_count ? ZEBRA_IPV4_ROUTE_ADD: ZEBRA_IPV4_ROUTE_DELETE,
@ -1431,6 +1492,25 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
} }
stream_reset (bgp_ifindices_buf); stream_reset (bgp_ifindices_buf);
/* For labeled unicast, each nexthop has a label too. Resize label
* buffer, if required.
*/
if (safi == SAFI_LABELED_UNICAST)
{
if ((oldsize = stream_get_size (bgp_label_buf)) <
(sizeof (unsigned int) * nhcount))
{
newsize = (sizeof (unsigned int) * nhcount);
newsize = stream_resize (bgp_label_buf, newsize);
if (newsize == oldsize)
{
zlog_err ("can't resize label buffer");
return;
}
}
stream_reset (bgp_label_buf);
}
ifindex = 0; ifindex = 0;
nexthop = NULL; nexthop = NULL;
@ -1476,6 +1556,11 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
} }
stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *)); stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int)); stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
if (safi == SAFI_LABELED_UNICAST)
{
label = label_pton(info->extra->tag);
stream_put (bgp_label_buf, &label, sizeof (u_int32_t));
}
valid_nh_count++; valid_nh_count++;
} }
@ -1518,6 +1603,11 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *)); stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int)); stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
if (safi == SAFI_LABELED_UNICAST)
{
label = label_pton(mpinfo->extra->tag);
stream_put (bgp_label_buf, &label, sizeof (u_int32_t));
}
valid_nh_count++; valid_nh_count++;
} }
@ -1527,8 +1617,10 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
api.type = ZEBRA_ROUTE_BGP; api.type = ZEBRA_ROUTE_BGP;
api.instance = 0; api.instance = 0;
api.message = 0; api.message = 0;
api.safi = safi; api.safi = (safi == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
if (safi == SAFI_LABELED_UNICAST)
SET_FLAG (api.message, ZAPI_MESSAGE_LABEL);
/* Note that this currently only applies to Null0 routes for aggregates. /* Note that this currently only applies to Null0 routes for aggregates.
* ZEBRA_FLAG_BLACKHOLE signals zapi_ipv6_route to encode a special * ZEBRA_FLAG_BLACKHOLE signals zapi_ipv6_route to encode a special
@ -1544,6 +1636,16 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
api.ifindex_num = valid_nh_count; api.ifindex_num = valid_nh_count;
api.ifindex = (ifindex_t *)STREAM_DATA (bgp_ifindices_buf); api.ifindex = (ifindex_t *)STREAM_DATA (bgp_ifindices_buf);
if (safi == SAFI_LABELED_UNICAST)
{
api.label_num = valid_nh_count;
api.label = (unsigned int *)STREAM_DATA (bgp_label_buf);
}
else
{
api.label_num = 0;
api.label = NULL;
}
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
api.metric = metric; api.metric = metric;
api.tag = 0; api.tag = 0;
@ -1566,13 +1668,22 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
if (bgp_debug_zebra(p)) if (bgp_debug_zebra(p))
{ {
int i; int i;
char label_buf[20];
zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI, zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI,
valid_nh_count ? "add" : "delete", bgp->vrf_id, valid_nh_count ? "add" : "delete", bgp->vrf_id,
inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
p->prefixlen, api.metric, api.tag); p->prefixlen, api.metric, api.tag);
for (i = 0; i < api.nexthop_num; i++) for (i = 0; i < api.nexthop_num; i++)
zlog_debug(" IPv6 [nexthop %d] %s", i+1, {
inet_ntop(AF_INET6, api.nexthop[i], buf[1], sizeof(buf[1]))); label_buf[0] = '\0';
if (safi == SAFI_LABELED_UNICAST)
sprintf(label_buf, "label %u", api.label[i]);
zlog_debug(" nhop [%d]: %s if %s %s",
i+1,
inet_ntop(AF_INET6, api.nexthop[i], buf[1], sizeof(buf[1])),
ifindex2ifname (api.ifindex[i], bgp->vrf_id),
label_buf);
}
} }
if (valid_nh_count) if (valid_nh_count)
@ -1588,13 +1699,22 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
if (bgp_debug_zebra(p)) if (bgp_debug_zebra(p))
{ {
int i; int i;
char label_buf[20];
zlog_debug("Tx IPv6 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI, zlog_debug("Tx IPv6 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI,
valid_nh_count ? "add" : "delete", bgp->vrf_id, valid_nh_count ? "add" : "delete", bgp->vrf_id,
inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
p->prefixlen, api.metric, api.tag); p->prefixlen, api.metric, api.tag);
for (i = 0; i < api.nexthop_num; i++) for (i = 0; i < api.nexthop_num; i++)
zlog_debug(" IPv6 [nexthop %d] %s", i+1, {
inet_ntop(AF_INET6, api.nexthop[i], buf[1], sizeof(buf[1]))); label_buf[0] = '\0';
if (safi == SAFI_LABELED_UNICAST)
sprintf(label_buf, "label %u", api.label[i]);
zlog_debug(" nhop [%d]: %s if %s %s",
i+1,
inet_ntop(AF_INET6, api.nexthop[i], buf[1], sizeof(buf[1])),
ifindex2ifname (api.ifindex[i], bgp->vrf_id),
label_buf);
}
} }
zapi_ipv6_route (valid_nh_count ? zapi_ipv6_route (valid_nh_count ?
@ -1626,7 +1746,7 @@ bgp_zebra_announce_table (struct bgp *bgp, afi_t afi, safi_t safi)
if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)
&& ri->type == ZEBRA_ROUTE_BGP && ri->type == ZEBRA_ROUTE_BGP
&& ri->sub_type == BGP_ROUTE_NORMAL) && ri->sub_type == BGP_ROUTE_NORMAL)
bgp_zebra_announce (&rn->p, ri, bgp, afi, safi); bgp_zebra_announce (rn, &rn->p, ri, bgp, afi, safi);
} }
void void
@ -1673,10 +1793,14 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
api.type = ZEBRA_ROUTE_BGP; api.type = ZEBRA_ROUTE_BGP;
api.instance = 0; api.instance = 0;
api.message = 0; api.message = 0;
api.safi = safi; api.safi = (safi == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
if (safi == SAFI_LABELED_UNICAST)
SET_FLAG (api.message, ZAPI_MESSAGE_LABEL);
api.nexthop_num = 0; api.nexthop_num = 0;
api.nexthop = NULL; api.nexthop = NULL;
api.label_num = 0;
api.label = NULL;
api.ifindex_num = 0; api.ifindex_num = 0;
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
api.metric = info->attr->med; api.metric = info->attr->med;
@ -1712,11 +1836,14 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
api.type = ZEBRA_ROUTE_BGP; api.type = ZEBRA_ROUTE_BGP;
api.instance = 0; api.instance = 0;
api.message = 0; api.message = 0;
api.safi = safi; api.safi = (safi == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
if (safi == SAFI_LABELED_UNICAST)
SET_FLAG (api.message, ZAPI_MESSAGE_LABEL);
api.nexthop_num = 0; api.nexthop_num = 0;
api.nexthop = NULL; api.nexthop = NULL;
api.ifindex_num = 0; api.ifindex_num = 0;
api.label_num = 0;
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
api.metric = info->attr->med; api.metric = info->attr->med;
api.tag = 0; api.tag = 0;
@ -2141,6 +2268,7 @@ bgp_zebra_init (struct thread_master *master)
zclient->redistribute_route_ipv6_del = zebra_read_ipv6; zclient->redistribute_route_ipv6_del = zebra_read_ipv6;
zclient->nexthop_update = bgp_read_nexthop_update; zclient->nexthop_update = bgp_read_nexthop_update;
zclient->import_check_update = bgp_read_import_check_update; zclient->import_check_update = bgp_read_import_check_update;
zclient->fec_update = bgp_read_fec_update;
bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE); bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE); bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE);

View File

@ -23,9 +23,11 @@ Boston, MA 02111-1307, USA. */
#define BGP_NEXTHOP_BUF_SIZE (8 * sizeof (struct in_addr *)) #define BGP_NEXTHOP_BUF_SIZE (8 * sizeof (struct in_addr *))
#define BGP_IFINDICES_BUF_SIZE (8 * sizeof (unsigned int)) #define BGP_IFINDICES_BUF_SIZE (8 * sizeof (unsigned int))
#define BGP_LABEL_BUF_SIZE (8 * sizeof (unsigned int))
extern struct stream *bgp_nexthop_buf; extern struct stream *bgp_nexthop_buf;
extern struct stream *bgp_ifindices_buf; extern struct stream *bgp_ifindices_buf;
extern struct stream *bgp_label_buf;
extern void bgp_zebra_init (struct thread_master *master); extern void bgp_zebra_init (struct thread_master *master);
extern void bgp_zebra_destroy (void); extern void bgp_zebra_destroy (void);
@ -34,8 +36,8 @@ extern int bgp_config_write_maxpaths (struct vty *, struct bgp *, afi_t,
safi_t, int *); safi_t, int *);
extern int bgp_config_write_redistribute (struct vty *, struct bgp *, afi_t, safi_t, extern int bgp_config_write_redistribute (struct vty *, struct bgp *, afi_t, safi_t,
int *); int *);
extern void bgp_zebra_announce (struct prefix *, struct bgp_info *, struct bgp *, extern void bgp_zebra_announce (struct bgp_node *, struct prefix *,
afi_t, safi_t); struct bgp_info *, struct bgp *, afi_t, safi_t);
extern void bgp_zebra_announce_table (struct bgp *, afi_t, safi_t); extern void bgp_zebra_announce_table (struct bgp *, afi_t, safi_t);
extern void bgp_zebra_withdraw (struct prefix *, struct bgp_info *, safi_t); extern void bgp_zebra_withdraw (struct prefix *, struct bgp_info *, safi_t);

View File

@ -1636,6 +1636,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_IP][SAFI_MULTICAST], UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
PEER_FLAG_REFLECTOR_CLIENT); PEER_FLAG_REFLECTOR_CLIENT);
UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_LABELED_UNICAST],
PEER_FLAG_REFLECTOR_CLIENT);
UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN], UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
PEER_FLAG_REFLECTOR_CLIENT); PEER_FLAG_REFLECTOR_CLIENT);
UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_ENCAP], UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_ENCAP],
@ -1644,6 +1646,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_LABELED_UNICAST],
PEER_FLAG_REFLECTOR_CLIENT);
UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN], UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN],
PEER_FLAG_REFLECTOR_CLIENT); PEER_FLAG_REFLECTOR_CLIENT);
UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP], UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP],
@ -3608,10 +3612,12 @@ peer_active (struct peer *peer)
return 0; return 0;
if (peer->afc[AFI_IP][SAFI_UNICAST] if (peer->afc[AFI_IP][SAFI_UNICAST]
|| peer->afc[AFI_IP][SAFI_MULTICAST] || peer->afc[AFI_IP][SAFI_MULTICAST]
|| peer->afc[AFI_IP][SAFI_LABELED_UNICAST]
|| peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_MPLS_VPN]
|| peer->afc[AFI_IP][SAFI_ENCAP] || peer->afc[AFI_IP][SAFI_ENCAP]
|| 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_LABELED_UNICAST]
|| peer->afc[AFI_IP6][SAFI_MPLS_VPN] || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
|| peer->afc[AFI_IP6][SAFI_ENCAP]) || peer->afc[AFI_IP6][SAFI_ENCAP])
return 1; return 1;
@ -3624,10 +3630,12 @@ peer_active_nego (struct peer *peer)
{ {
if (peer->afc_nego[AFI_IP][SAFI_UNICAST] if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
|| peer->afc_nego[AFI_IP][SAFI_MULTICAST] || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
|| peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST]
|| peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
|| peer->afc_nego[AFI_IP][SAFI_ENCAP] || peer->afc_nego[AFI_IP][SAFI_ENCAP]
|| 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_LABELED_UNICAST]
|| peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
|| peer->afc_nego[AFI_IP6][SAFI_ENCAP]) || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
return 1; return 1;

View File

@ -76,6 +76,8 @@ enum bgp_af_index
BGP_AF_IPV4_ENCAP, BGP_AF_IPV4_ENCAP,
BGP_AF_IPV6_ENCAP, BGP_AF_IPV6_ENCAP,
BGP_AF_L2VPN_EVPN, BGP_AF_L2VPN_EVPN,
BGP_AF_IPV4_LBL_UNICAST,
BGP_AF_IPV6_LBL_UNICAST,
BGP_AF_MAX BGP_AF_MAX
}; };
@ -1394,6 +1396,9 @@ afindex (afi_t afi, safi_t safi)
case SAFI_MULTICAST: case SAFI_MULTICAST:
return BGP_AF_IPV4_MULTICAST; return BGP_AF_IPV4_MULTICAST;
break; break;
case SAFI_LABELED_UNICAST:
return BGP_AF_IPV4_LBL_UNICAST;
break;
case SAFI_MPLS_VPN: case SAFI_MPLS_VPN:
return BGP_AF_IPV4_VPN; return BGP_AF_IPV4_VPN;
break; break;
@ -1414,6 +1419,9 @@ afindex (afi_t afi, safi_t safi)
case SAFI_MULTICAST: case SAFI_MULTICAST:
return BGP_AF_IPV6_MULTICAST; return BGP_AF_IPV6_MULTICAST;
break; break;
case SAFI_LABELED_UNICAST:
return BGP_AF_IPV6_LBL_UNICAST;
break;
case SAFI_MPLS_VPN: case SAFI_MPLS_VPN:
return BGP_AF_IPV6_VPN; return BGP_AF_IPV6_VPN;
break; break;
@ -1456,6 +1464,7 @@ peer_afi_active_nego (const struct peer *peer, afi_t afi)
{ {
if (peer->afc_nego[afi][SAFI_UNICAST] if (peer->afc_nego[afi][SAFI_UNICAST]
|| peer->afc_nego[afi][SAFI_MULTICAST] || peer->afc_nego[afi][SAFI_MULTICAST]
|| peer->afc_nego[afi][SAFI_LABELED_UNICAST]
|| peer->afc_nego[afi][SAFI_MPLS_VPN] || peer->afc_nego[afi][SAFI_MPLS_VPN]
|| peer->afc_nego[afi][SAFI_ENCAP]) || peer->afc_nego[afi][SAFI_ENCAP])
return 1; return 1;
@ -1470,10 +1479,12 @@ peer_group_af_configured (struct peer_group *group)
if (peer->afc[AFI_IP][SAFI_UNICAST] if (peer->afc[AFI_IP][SAFI_UNICAST]
|| peer->afc[AFI_IP][SAFI_MULTICAST] || peer->afc[AFI_IP][SAFI_MULTICAST]
|| peer->afc[AFI_IP][SAFI_LABELED_UNICAST]
|| peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_MPLS_VPN]
|| peer->afc[AFI_IP][SAFI_ENCAP] || peer->afc[AFI_IP][SAFI_ENCAP]
|| 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_LABELED_UNICAST]
|| peer->afc[AFI_IP6][SAFI_MPLS_VPN] || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
|| peer->afc[AFI_IP6][SAFI_ENCAP]) || peer->afc[AFI_IP6][SAFI_ENCAP])
return 1; return 1;

View File

@ -244,6 +244,8 @@ union prefixconstptr
/* Count prefix size from mask length */ /* Count prefix size from mask length */
#define PSIZE(a) (((a) + 7) / (8)) #define PSIZE(a) (((a) + 7) / (8))
#define BSIZE(a) ((a) * (8))
/* Prefix's family member. */ /* Prefix's family member. */
#define PREFIX_FAMILY(p) ((p)->family) #define PREFIX_FAMILY(p) ((p)->family)

View File

@ -919,6 +919,31 @@ stream_put_prefix (struct stream *s, struct prefix *p)
return stream_put_prefix_addpath (s, p, 0, 0); return stream_put_prefix_addpath (s, p, 0, 0);
} }
/* Put NLRI with label */
int
stream_put_labeled_prefix (struct stream *s, struct prefix *p, u_char *label)
{
size_t psize;
STREAM_VERIFY_SANE(s);
psize = PSIZE (p->prefixlen);
if (STREAM_WRITEABLE (s) < (psize + 3))
{
STREAM_BOUND_WARN (s, "put");
return 0;
}
stream_putc (s, (p->prefixlen + 24));
stream_putc(s, label[0]);
stream_putc(s, label[1]);
stream_putc(s, label[2]);
memcpy (s->data + s->endp, &p->u.prefix, psize);
s->endp += psize;
return (psize + 3);
}
/* Read size from fd. */ /* Read size from fd. */
int int

View File

@ -181,7 +181,8 @@ extern int stream_put_prefix_addpath (struct stream *, struct prefix *,
int addpath_encode, int addpath_encode,
u_int32_t addpath_tx_id); u_int32_t addpath_tx_id);
extern int stream_put_prefix (struct stream *, struct prefix *); extern int stream_put_prefix (struct stream *, struct prefix *);
extern int stream_put_labeled_prefix (struct stream *, struct prefix *,
u_char *);
extern void stream_get (void *, struct stream *, size_t); extern void stream_get (void *, struct stream *, size_t);
extern void stream_get_from (void *, struct stream *, size_t, size_t); extern void stream_get_from (void *, struct stream *, size_t, size_t);
extern u_char stream_getc (struct stream *); extern u_char stream_getc (struct stream *);