mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 05:18:47 +00:00
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:
parent
f51bae9cf9
commit
cd1964ff38
@ -81,7 +81,7 @@ libbgp_a_SOURCES = \
|
||||
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_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 = \
|
||||
bgp_memory.h \
|
||||
@ -92,7 +92,8 @@ noinst_HEADERS = \
|
||||
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_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_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@
|
||||
|
@ -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_MULTICAST:
|
||||
case SAFI_LABELED_UNICAST:
|
||||
bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr);
|
||||
stream_putc (s, 4);
|
||||
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_MULTICAST:
|
||||
case SAFI_LABELED_UNICAST:
|
||||
{
|
||||
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);
|
||||
}
|
||||
else if (safi == SAFI_LABELED_UNICAST)
|
||||
{
|
||||
/* Prefix write with label. */
|
||||
stream_put_labeled_prefix(s, p, tag);
|
||||
}
|
||||
else
|
||||
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_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
|
||||
@ -3439,6 +3446,11 @@ bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
|
||||
u_char *tag, int addpath_encode,
|
||||
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,
|
||||
tag, addpath_encode, addpath_tx_id, attr);
|
||||
}
|
||||
|
@ -1142,9 +1142,11 @@ bgp_stop (struct peer *peer)
|
||||
/* Reset prefix count */
|
||||
peer->pcount[AFI_IP][SAFI_UNICAST] = 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_IP6][SAFI_UNICAST] = 0;
|
||||
peer->pcount[AFI_IP6][SAFI_MULTICAST] = 0;
|
||||
peer->pcount[AFI_IP6][SAFI_LABELED_UNICAST] = 0;
|
||||
#endif /* 0 */
|
||||
|
||||
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) &&
|
||||
|
318
bgpd/bgp_label.c
Normal file
318
bgpd/bgp_label.c
Normal 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
124
bgpd/bgp_label.h
Normal 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 */
|
@ -235,6 +235,8 @@ bgp_exit (int status)
|
||||
stream_free (bgp_nexthop_buf);
|
||||
if (bgp_ifindices_buf)
|
||||
stream_free (bgp_ifindices_buf);
|
||||
if (bgp_label_buf)
|
||||
stream_free (bgp_label_buf);
|
||||
|
||||
/* reverse bgp_master_init */
|
||||
if (bm->master)
|
||||
|
@ -404,8 +404,9 @@ bgp_parse_nexthop_update (int command, vrf_id_t vrf_id)
|
||||
{
|
||||
char buf[PREFIX2STR_BUFFER];
|
||||
prefix2str(&p, buf, sizeof (buf));
|
||||
zlog_debug("%d: NH update for %s - metric %d (cur %d) #nhops %d (cur %d)",
|
||||
vrf_id, buf, metric, bnc->metric, nexthop_num, bnc->nexthop_num);
|
||||
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,
|
||||
bnc->flags);
|
||||
}
|
||||
|
||||
if (metric != bnc->metric)
|
||||
@ -678,6 +679,8 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
|
||||
struct bgp *bgp = bnc->bgp;
|
||||
int afi;
|
||||
struct peer *peer = (struct peer *)bnc->nht_info;
|
||||
struct bgp_table *table;
|
||||
safi_t safi;
|
||||
|
||||
if (BGP_DEBUG(nht, NHT))
|
||||
{
|
||||
@ -695,7 +698,10 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
|
||||
continue;
|
||||
|
||||
rn = path->net;
|
||||
assert (rn && bgp_node_table (rn));
|
||||
afi = family2afi(rn->p.family);
|
||||
table = bgp_node_table (rn);
|
||||
safi = table->safi;
|
||||
|
||||
/* Path becomes valid/invalid depending on whether the nexthop
|
||||
* reachable/unreachable.
|
||||
@ -705,15 +711,13 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
|
||||
{
|
||||
if (CHECK_FLAG (path->flags, BGP_INFO_VALID))
|
||||
{
|
||||
bgp_aggregate_decrement (bgp, &rn->p, path,
|
||||
afi, SAFI_UNICAST);
|
||||
bgp_aggregate_decrement (bgp, &rn->p, path, afi, safi);
|
||||
bgp_info_unset_flag (rn, path, BGP_INFO_VALID);
|
||||
}
|
||||
else
|
||||
{
|
||||
bgp_info_set_flag (rn, path, BGP_INFO_VALID);
|
||||
bgp_aggregate_increment (bgp, &rn->p, path,
|
||||
afi, SAFI_UNICAST);
|
||||
bgp_aggregate_increment (bgp, &rn->p, path, afi, safi);
|
||||
}
|
||||
}
|
||||
|
||||
@ -727,7 +731,7 @@ evaluate_paths (struct bgp_nexthop_cache *bnc)
|
||||
CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_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))
|
||||
|
@ -108,6 +108,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
|
||||
case SAFI_MULTICAST:
|
||||
json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "multicast");
|
||||
break;
|
||||
case SAFI_LABELED_UNICAST:
|
||||
json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "labeled-unicast");
|
||||
break;
|
||||
case SAFI_MPLS_VPN:
|
||||
json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "MPLS-labeled VPN");
|
||||
break;
|
||||
@ -148,6 +151,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso
|
||||
case SAFI_MULTICAST:
|
||||
vty_out (vty, "SAFI Multicast");
|
||||
break;
|
||||
case SAFI_LABELED_UNICAST:
|
||||
vty_out (vty, "SAFI Labeled-unicast");
|
||||
break;
|
||||
case SAFI_MPLS_VPN:
|
||||
vty_out (vty, "SAFI MPLS-labeled VPN");
|
||||
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]
|
||||
&& ! 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_ENCAP]
|
||||
&& ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
|
||||
&& ! 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_ENCAP]
|
||||
&& ! peer->afc_nego[AFI_L2VPN][SAFI_EVPN])
|
||||
|
@ -55,6 +55,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "bgpd/bgp_advertise.h"
|
||||
#include "bgpd/bgp_vty.h"
|
||||
#include "bgpd/bgp_updgrp.h"
|
||||
#include "bgpd/bgp_label.h"
|
||||
|
||||
/* Set up BGP packet marker and packet type. */
|
||||
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_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_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
|
||||
@ -1342,6 +1345,8 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet, i
|
||||
case SAFI_UNICAST:
|
||||
case SAFI_MULTICAST:
|
||||
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:
|
||||
return bgp_nlri_parse_vpn (peer, mp_withdraw?NULL:attr, packet);
|
||||
case SAFI_ENCAP:
|
||||
|
137
bgpd/bgp_route.c
137
bgpd/bgp_route.c
@ -35,6 +35,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "thread.h"
|
||||
#include "workqueue.h"
|
||||
#include "queue.h"
|
||||
#include "mpls.h"
|
||||
#include "memory.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_nht.h"
|
||||
#include "bgpd/bgp_updgrp.h"
|
||||
#include "bgpd/bgp_label.h"
|
||||
|
||||
#if ENABLE_BGP_VNC
|
||||
#include "bgpd/rfapi/rfapi_backend.h"
|
||||
@ -1187,7 +1189,8 @@ subgroup_announce_reset_nhop (u_char family, struct attr *attr)
|
||||
}
|
||||
|
||||
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 bgp_filter *filter;
|
||||
@ -1261,6 +1264,21 @@ subgroup_announce_check (struct bgp_info *ri, struct update_subgroup *subgrp,
|
||||
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. */
|
||||
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. */
|
||||
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);
|
||||
else
|
||||
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 *old_select;
|
||||
struct bgp_info_pair old_and_new;
|
||||
int label_valid;
|
||||
|
||||
/* Is it end of initial update? (after startup) */
|
||||
if (!rn)
|
||||
@ -1914,7 +1933,24 @@ bgp_process_main (struct work_queue *wq, void *data)
|
||||
old_select = old_and_new.old;
|
||||
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 &&
|
||||
!CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR) &&
|
||||
!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_exterior_add_route(bgp, p, old_select);
|
||||
#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);
|
||||
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);
|
||||
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);
|
||||
|
||||
/* FIB update. */
|
||||
if ((safi == SAFI_UNICAST || safi == SAFI_MULTICAST) &&
|
||||
if (bgp_fibupd_safi(safi) &&
|
||||
(bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) &&
|
||||
!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->sub_type == BGP_ROUTE_NORMAL ||
|
||||
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
|
||||
{
|
||||
/* 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;
|
||||
const char *reason;
|
||||
char pfx_buf[BGP_PRD_PATH_STRLEN];
|
||||
char label_buf[20];
|
||||
int connected = 0;
|
||||
int do_loop_check = 1;
|
||||
#if ENABLE_BGP_VNC
|
||||
@ -2417,6 +2470,9 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
|
||||
|
||||
bgp = peer->bgp;
|
||||
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
|
||||
Adj-RIBs-In. */
|
||||
@ -2516,6 +2572,8 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
|
||||
/* Same attribute comes in. */
|
||||
if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED)
|
||||
&& 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,
|
||||
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))
|
||||
{
|
||||
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,
|
||||
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)
|
||||
{
|
||||
@ -2544,10 +2602,10 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
|
||||
peer->rcvd_attr_printed = 1;
|
||||
}
|
||||
|
||||
zlog_debug ("%s rcvd %s...duplicate ignored",
|
||||
zlog_debug ("%s rcvd %s %s...duplicate ignored",
|
||||
peer->host,
|
||||
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. */
|
||||
@ -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 (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,
|
||||
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);
|
||||
}
|
||||
|
||||
/* Received Logging. */
|
||||
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,
|
||||
addpath_id, pfx_buf, sizeof (pfx_buf)));
|
||||
addpath_id, pfx_buf, sizeof (pfx_buf)), label_buf);
|
||||
|
||||
/* graceful restart STALE flag unset. */
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
|
||||
#if ENABLE_BGP_VNC
|
||||
@ -2678,8 +2736,9 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
|
||||
}
|
||||
}
|
||||
|
||||
/* Nexthop reachability check. */
|
||||
if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST)
|
||||
/* Nexthop reachability check - for unicast and labeled-unicast.. */
|
||||
if ((afi == AFI_IP || afi == AFI_IP6) &&
|
||||
(safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST))
|
||||
{
|
||||
if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 &&
|
||||
! 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;
|
||||
}
|
||||
|
||||
zlog_debug ("%s rcvd %s", peer->host,
|
||||
zlog_debug ("%s rcvd %s%s ", peer->host,
|
||||
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. */
|
||||
new = info_make(type, sub_type, 0, peer, attr_new, rn);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
/* 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 &&
|
||||
! 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;
|
||||
}
|
||||
|
||||
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,
|
||||
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)
|
||||
@ -3818,9 +3878,11 @@ bgp_static_update_main (struct bgp *bgp, struct prefix *p,
|
||||
#endif
|
||||
|
||||
/* 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);
|
||||
else
|
||||
{
|
||||
@ -5557,6 +5619,8 @@ bgp_aggregate_unset (struct vty *vty, const char *prefix_str,
|
||||
aggregate = rn->info;
|
||||
if (aggregate->safi & SAFI_UNICAST)
|
||||
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)
|
||||
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. */
|
||||
if (safi & SAFI_UNICAST)
|
||||
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)
|
||||
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)
|
||||
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 */
|
||||
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)) ? ":" : "",
|
||||
buf2,
|
||||
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)
|
||||
|
@ -150,6 +150,7 @@ struct bgp_info
|
||||
#define BGP_INFO_COUNTED (1 << 10)
|
||||
#define BGP_INFO_MULTIPATH (1 << 11)
|
||||
#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. */
|
||||
u_char type;
|
||||
@ -273,6 +274,16 @@ bgp_bump_version (struct bgp_node *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. */
|
||||
extern void bgp_process_queue_init (void);
|
||||
extern void bgp_route_init (void);
|
||||
@ -370,7 +381,7 @@ subgroup_process_announce_selected (struct update_subgroup *subgrp,
|
||||
struct bgp_node *rn,
|
||||
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 prefix *p, struct attr *attr);
|
||||
|
||||
|
@ -56,10 +56,13 @@ struct bgp_node
|
||||
|
||||
struct bgp_node *prn;
|
||||
|
||||
u_char local_label[3];
|
||||
|
||||
uint64_t version;
|
||||
u_char flags;
|
||||
#define BGP_NODE_PROCESS_SCHEDULED (1 << 0)
|
||||
#define BGP_NODE_USER_CLEAR (1 << 1)
|
||||
#define BGP_NODE_LABEL_CHANGED (1 << 2)
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -618,7 +618,7 @@ subgroup_announce_table (struct update_subgroup *subgrp,
|
||||
if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) ||
|
||||
(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);
|
||||
else
|
||||
bgp_adj_out_unset_subgroup (rn, subgrp, 1, ri->addpath_tx_id);
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "workqueue.h"
|
||||
#include "hash.h"
|
||||
#include "queue.h"
|
||||
#include "mpls.h"
|
||||
|
||||
#include "bgpd/bgpd.h"
|
||||
#include "bgpd/bgp_debug.h"
|
||||
@ -54,6 +55,7 @@
|
||||
#include "bgpd/bgp_nexthop.h"
|
||||
#include "bgpd/bgp_nht.h"
|
||||
#include "bgpd/bgp_mplsvpn.h"
|
||||
#include "bgpd/bgp_label.h"
|
||||
|
||||
/********************
|
||||
* PRIVATE FUNCTIONS
|
||||
@ -653,6 +655,7 @@ subgroup_update_packet (struct update_subgroup *subgrp)
|
||||
int addpath_encode = 0;
|
||||
u_int32_t addpath_tx_id = 0;
|
||||
struct prefix_rd *prd = NULL;
|
||||
char label_buf[20];
|
||||
|
||||
if (!subgrp)
|
||||
return NULL;
|
||||
@ -660,7 +663,6 @@ subgroup_update_packet (struct update_subgroup *subgrp)
|
||||
if (bpacket_queue_is_full (SUBGRP_INST (subgrp), SUBGRP_PKTQ (subgrp)))
|
||||
return NULL;
|
||||
|
||||
|
||||
peer = SUBGRP_PEER (subgrp);
|
||||
afi = SUBGRP_AFI (subgrp);
|
||||
safi = SUBGRP_SAFI (subgrp);
|
||||
@ -668,6 +670,7 @@ subgroup_update_packet (struct update_subgroup *subgrp)
|
||||
stream_reset (s);
|
||||
snlri = subgrp->scratch;
|
||||
stream_reset (snlri);
|
||||
label_buf[0] = '\0';
|
||||
|
||||
bpacket_attr_vec_arr_reset (&vecarr);
|
||||
|
||||
@ -760,8 +763,9 @@ subgroup_update_packet (struct update_subgroup *subgrp)
|
||||
|
||||
if (rn->prn)
|
||||
prd = (struct prefix_rd *) &rn->prn->p;
|
||||
if (binfo && binfo->extra)
|
||||
tag = binfo->extra->tag;
|
||||
tag = bgp_adv_label(rn, binfo, peer, afi, safi);
|
||||
if (bgp_labeled_safi(safi))
|
||||
sprintf (label_buf, "label %u", label_pton(tag));
|
||||
|
||||
if (stream_empty (snlri))
|
||||
mpattrlen_pos = bgp_packet_mpattr_start (snlri, afi, safi,
|
||||
@ -797,11 +801,12 @@ subgroup_update_packet (struct update_subgroup *subgrp)
|
||||
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,
|
||||
bgp_debug_rdpfxpath2str (prd, &rn->p, addpath_encode,
|
||||
addpath_tx_id,
|
||||
pfx_buf, sizeof (pfx_buf)));
|
||||
pfx_buf, sizeof (pfx_buf)),
|
||||
label_buf);
|
||||
}
|
||||
|
||||
/* Synchnorize attribute. */
|
||||
|
156
bgpd/bgp_zebra.c
156
bgpd/bgp_zebra.c
@ -34,6 +34,7 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "lib/json.h"
|
||||
#include "lib/bfd.h"
|
||||
#include "filter.h"
|
||||
#include "mpls.h"
|
||||
|
||||
#include "bgpd/bgpd.h"
|
||||
#include "bgpd/bgp_route.h"
|
||||
@ -46,6 +47,7 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "bgpd/bgp_nexthop.h"
|
||||
#include "bgpd/bgp_nht.h"
|
||||
#include "bgpd/bgp_bfd.h"
|
||||
#include "bgpd/bgp_label.h"
|
||||
#if ENABLE_BGP_VNC
|
||||
# include "bgpd/rfapi/rfapi_backend.h"
|
||||
# include "bgpd/rfapi/vnc_export_bgp.h"
|
||||
@ -57,6 +59,7 @@ struct zclient *zclient = NULL;
|
||||
/* Growable buffer for nexthops sent to zebra */
|
||||
struct stream *bgp_nexthop_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
|
||||
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
|
||||
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
|
||||
bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
|
||||
afi_t afi, safi_t safi)
|
||||
bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info,
|
||||
struct bgp *bgp, afi_t afi, safi_t safi)
|
||||
{
|
||||
u_int32_t flags;
|
||||
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 *info_cp = &local_info;
|
||||
route_tag_t tag;
|
||||
u_int32_t label;
|
||||
|
||||
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
|
||||
* 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)) <
|
||||
(sizeof (struct in_addr *) * nhcount))
|
||||
{
|
||||
newsize = (sizeof (struct in_addr *) * nhcount);
|
||||
newsize = sizeof (struct in_addr *) * nhcount;
|
||||
newsize = stream_resize (bgp_nexthop_buf, newsize);
|
||||
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);
|
||||
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 = 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 *));
|
||||
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;
|
||||
@ -1336,6 +1372,11 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
|
||||
continue;
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
@ -1344,8 +1385,10 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
|
||||
api.type = ZEBRA_ROUTE_BGP;
|
||||
api.instance = 0;
|
||||
api.message = 0;
|
||||
api.safi = safi;
|
||||
api.safi = (safi == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
|
||||
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.
|
||||
* 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 = (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;
|
||||
SET_FLAG (api.message, ZAPI_MESSAGE_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))
|
||||
{
|
||||
int i;
|
||||
char label_buf[20];
|
||||
zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI
|
||||
" count %d", (valid_nh_count ? "add":"delete"),
|
||||
bgp->vrf_id,
|
||||
inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
|
||||
p->prefixlen, api.metric, api.tag, api.nexthop_num);
|
||||
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,
|
||||
@ -1431,6 +1492,25 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
|
||||
}
|
||||
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;
|
||||
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_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++;
|
||||
}
|
||||
|
||||
@ -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_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++;
|
||||
}
|
||||
|
||||
@ -1527,8 +1617,10 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
|
||||
api.type = ZEBRA_ROUTE_BGP;
|
||||
api.instance = 0;
|
||||
api.message = 0;
|
||||
api.safi = safi;
|
||||
api.safi = (safi == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
|
||||
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.
|
||||
* 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);
|
||||
api.ifindex_num = valid_nh_count;
|
||||
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);
|
||||
api.metric = metric;
|
||||
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))
|
||||
{
|
||||
int i;
|
||||
char label_buf[20];
|
||||
zlog_debug("Tx IPv4 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI,
|
||||
valid_nh_count ? "add" : "delete", bgp->vrf_id,
|
||||
inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])),
|
||||
p->prefixlen, api.metric, api.tag);
|
||||
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)
|
||||
@ -1588,13 +1699,22 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
|
||||
if (bgp_debug_zebra(p))
|
||||
{
|
||||
int i;
|
||||
char label_buf[20];
|
||||
zlog_debug("Tx IPv6 route %s VRF %u %s/%d metric %u tag %"ROUTE_TAG_PRI,
|
||||
valid_nh_count ? "add" : "delete", bgp->vrf_id,
|
||||
inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])),
|
||||
p->prefixlen, api.metric, api.tag);
|
||||
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 ?
|
||||
@ -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)
|
||||
&& ri->type == ZEBRA_ROUTE_BGP
|
||||
&& 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
|
||||
@ -1673,10 +1793,14 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
|
||||
api.type = ZEBRA_ROUTE_BGP;
|
||||
api.instance = 0;
|
||||
api.message = 0;
|
||||
api.safi = safi;
|
||||
api.safi = (safi == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
|
||||
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 = NULL;
|
||||
api.label_num = 0;
|
||||
api.label = NULL;
|
||||
api.ifindex_num = 0;
|
||||
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
|
||||
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.instance = 0;
|
||||
api.message = 0;
|
||||
api.safi = safi;
|
||||
api.safi = (safi == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
|
||||
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 = NULL;
|
||||
api.ifindex_num = 0;
|
||||
api.label_num = 0;
|
||||
SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
|
||||
api.metric = info->attr->med;
|
||||
api.tag = 0;
|
||||
@ -2141,6 +2268,7 @@ bgp_zebra_init (struct thread_master *master)
|
||||
zclient->redistribute_route_ipv6_del = zebra_read_ipv6;
|
||||
zclient->nexthop_update = bgp_read_nexthop_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_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE);
|
||||
|
@ -23,9 +23,11 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#define BGP_NEXTHOP_BUF_SIZE (8 * sizeof (struct in_addr *))
|
||||
#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_ifindices_buf;
|
||||
extern struct stream *bgp_label_buf;
|
||||
|
||||
extern void bgp_zebra_init (struct thread_master *master);
|
||||
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 *);
|
||||
extern int bgp_config_write_redistribute (struct vty *, struct bgp *, afi_t, safi_t,
|
||||
int *);
|
||||
extern void bgp_zebra_announce (struct prefix *, struct bgp_info *, struct bgp *,
|
||||
afi_t, safi_t);
|
||||
extern void bgp_zebra_announce (struct bgp_node *, struct prefix *,
|
||||
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_withdraw (struct prefix *, struct bgp_info *, safi_t);
|
||||
|
||||
|
@ -1636,6 +1636,8 @@ peer_as_change (struct peer *peer, as_t as, int as_specified)
|
||||
PEER_FLAG_REFLECTOR_CLIENT);
|
||||
UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
|
||||
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],
|
||||
PEER_FLAG_REFLECTOR_CLIENT);
|
||||
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);
|
||||
UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
|
||||
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],
|
||||
PEER_FLAG_REFLECTOR_CLIENT);
|
||||
UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP],
|
||||
@ -3608,10 +3612,12 @@ peer_active (struct peer *peer)
|
||||
return 0;
|
||||
if (peer->afc[AFI_IP][SAFI_UNICAST]
|
||||
|| 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_ENCAP]
|
||||
|| peer->afc[AFI_IP6][SAFI_UNICAST]
|
||||
|| 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_ENCAP])
|
||||
return 1;
|
||||
@ -3624,10 +3630,12 @@ peer_active_nego (struct peer *peer)
|
||||
{
|
||||
if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
|
||||
|| 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_ENCAP]
|
||||
|| peer->afc_nego[AFI_IP6][SAFI_UNICAST]
|
||||
|| 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_ENCAP])
|
||||
return 1;
|
||||
|
13
bgpd/bgpd.h
13
bgpd/bgpd.h
@ -76,6 +76,8 @@ enum bgp_af_index
|
||||
BGP_AF_IPV4_ENCAP,
|
||||
BGP_AF_IPV6_ENCAP,
|
||||
BGP_AF_L2VPN_EVPN,
|
||||
BGP_AF_IPV4_LBL_UNICAST,
|
||||
BGP_AF_IPV6_LBL_UNICAST,
|
||||
BGP_AF_MAX
|
||||
};
|
||||
|
||||
@ -1394,6 +1396,9 @@ afindex (afi_t afi, safi_t safi)
|
||||
case SAFI_MULTICAST:
|
||||
return BGP_AF_IPV4_MULTICAST;
|
||||
break;
|
||||
case SAFI_LABELED_UNICAST:
|
||||
return BGP_AF_IPV4_LBL_UNICAST;
|
||||
break;
|
||||
case SAFI_MPLS_VPN:
|
||||
return BGP_AF_IPV4_VPN;
|
||||
break;
|
||||
@ -1414,7 +1419,10 @@ afindex (afi_t afi, safi_t safi)
|
||||
case SAFI_MULTICAST:
|
||||
return BGP_AF_IPV6_MULTICAST;
|
||||
break;
|
||||
case SAFI_MPLS_VPN:
|
||||
case SAFI_LABELED_UNICAST:
|
||||
return BGP_AF_IPV6_LBL_UNICAST;
|
||||
break;
|
||||
case SAFI_MPLS_VPN:
|
||||
return BGP_AF_IPV6_VPN;
|
||||
break;
|
||||
case SAFI_ENCAP:
|
||||
@ -1456,6 +1464,7 @@ peer_afi_active_nego (const struct peer *peer, afi_t afi)
|
||||
{
|
||||
if (peer->afc_nego[afi][SAFI_UNICAST]
|
||||
|| 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_ENCAP])
|
||||
return 1;
|
||||
@ -1470,10 +1479,12 @@ peer_group_af_configured (struct peer_group *group)
|
||||
|
||||
if (peer->afc[AFI_IP][SAFI_UNICAST]
|
||||
|| 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_ENCAP]
|
||||
|| peer->afc[AFI_IP6][SAFI_UNICAST]
|
||||
|| 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_ENCAP])
|
||||
return 1;
|
||||
|
@ -244,6 +244,8 @@ union prefixconstptr
|
||||
/* Count prefix size from mask length */
|
||||
#define PSIZE(a) (((a) + 7) / (8))
|
||||
|
||||
#define BSIZE(a) ((a) * (8))
|
||||
|
||||
/* Prefix's family member. */
|
||||
#define PREFIX_FAMILY(p) ((p)->family)
|
||||
|
||||
|
25
lib/stream.c
25
lib/stream.c
@ -919,6 +919,31 @@ stream_put_prefix (struct stream *s, struct prefix *p)
|
||||
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. */
|
||||
int
|
||||
|
@ -181,7 +181,8 @@ extern int stream_put_prefix_addpath (struct stream *, struct prefix *,
|
||||
int addpath_encode,
|
||||
u_int32_t addpath_tx_id);
|
||||
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_from (void *, struct stream *, size_t, size_t);
|
||||
extern u_char stream_getc (struct stream *);
|
||||
|
Loading…
Reference in New Issue
Block a user