summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDon Slice <dslice@cumulusnetworks.com>2017-03-09 15:54:20 +0100
committerDonald Sharp <sharpd@cumulusnetworks.com>2017-04-06 16:32:07 +0200
commitcd1964ff38bdbd2b5d36d0a0d89890e9d1bb2a50 (patch)
tree204d8be9bf9c213e4a895b1d335fafc8cc4c7d3f
parentbgpd: labeled unicast config (diff)
downloadfrr-cd1964ff38bdbd2b5d36d0a0d89890e9d1bb2a50.tar.xz
frr-cd1964ff38bdbd2b5d36d0a0d89890e9d1bb2a50.zip
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>
-rw-r--r--bgpd/Makefile.am5
-rw-r--r--bgpd/bgp_attr.c14
-rw-r--r--bgpd/bgp_fsm.c2
-rw-r--r--bgpd/bgp_label.c318
-rw-r--r--bgpd/bgp_label.h124
-rw-r--r--bgpd/bgp_main.c2
-rw-r--r--bgpd/bgp_nht.c18
-rw-r--r--bgpd/bgp_open.c8
-rw-r--r--bgpd/bgp_packet.c5
-rw-r--r--bgpd/bgp_route.c137
-rw-r--r--bgpd/bgp_route.h13
-rw-r--r--bgpd/bgp_table.h3
-rw-r--r--bgpd/bgp_updgrp_adv.c2
-rw-r--r--bgpd/bgp_updgrp_packet.c15
-rw-r--r--bgpd/bgp_zebra.c156
-rw-r--r--bgpd/bgp_zebra.h6
-rw-r--r--bgpd/bgpd.c8
-rw-r--r--bgpd/bgpd.h13
-rw-r--r--lib/prefix.h2
-rw-r--r--lib/stream.c25
-rw-r--r--lib/stream.h3
21 files changed, 819 insertions, 60 deletions
diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am
index b6ed9a4d6..4ea045552 100644
--- a/bgpd/Makefile.am
+++ b/bgpd/Makefile.am
@@ -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@
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 1fccd25c8..2c6bb5de0 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -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);
}
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 2bbdca595..b17888482 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -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) &&
diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c
new file mode 100644
index 000000000..283afbc92
--- /dev/null
+++ b/bgpd/bgp_label.c
@@ -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;
+}
diff --git a/bgpd/bgp_label.h b/bgpd/bgp_label.h
new file mode 100644
index 000000000..a7e7d5c47
--- /dev/null
+++ b/bgpd/bgp_label.h
@@ -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 */
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 423c9453e..152d4a7ac 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -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)
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index b0362b553..1e8dc5d97 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -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))
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 51079f31e..83fc3fe97 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -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])
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 853fcc869..f7a78caf9 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -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:
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 432a566c1..77154b0f3 100644
--- a/bgpd/bgp_route.c
+++ b/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)
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index e75978d00..69b8ea8a5 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -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);
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
index 3c96dac61..2b874f66a 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -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)
};
/*
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index efb2046e1..ac5f77474 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -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);
diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c
index 57e5c0702..135cdadb2 100644
--- a/bgpd/bgp_updgrp_packet.c
+++ b/bgpd/bgp_updgrp_packet.c
@@ -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. */
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 72bd081a7..1ded613f6 100644
--- a/bgpd/bgp_zebra.c
+++ b/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);
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index d22a00e8f..bc4e36352 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -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);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 0ed277b16..1c73fb940 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -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;
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index a72974bc1..e95d05922 100644
--- a/bgpd/bgpd.h
+++ b/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;
diff --git a/lib/prefix.h b/lib/prefix.h
index eb3ae3daf..786c2bf7e 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -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)
diff --git a/lib/stream.c b/lib/stream.c
index 301ebc627..32dde1ca0 100644
--- a/lib/stream.c
+++ b/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
diff --git a/lib/stream.h b/lib/stream.h
index 1e2bc89b3..b7bf31bf7 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -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 *);