]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: labeled unicast processing
authorDon Slice <dslice@cumulusnetworks.com>
Thu, 9 Mar 2017 14:54:20 +0000 (09:54 -0500)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 6 Apr 2017 14:32:07 +0000 (10:32 -0400)
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>
21 files changed:
bgpd/Makefile.am
bgpd/bgp_attr.c
bgpd/bgp_fsm.c
bgpd/bgp_label.c [new file with mode: 0644]
bgpd/bgp_label.h [new file with mode: 0644]
bgpd/bgp_main.c
bgpd/bgp_nht.c
bgpd/bgp_open.c
bgpd/bgp_packet.c
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_table.h
bgpd/bgp_updgrp_adv.c
bgpd/bgp_updgrp_packet.c
bgpd/bgp_zebra.c
bgpd/bgp_zebra.h
bgpd/bgpd.c
bgpd/bgpd.h
lib/prefix.h
lib/stream.c
lib/stream.h

index b6ed9a4d6db726e6d18ce453e901ce57ef2eef81..4ea045552510da7f7e3105c179562df75122be8a 100644 (file)
@@ -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@
index 1fccd25c8af40faf91f64b708823a1d21304248b..2c6bb5de0e9d5f3cee35398b0311e0fe7c4a7c57 100644 (file)
@@ -2748,6 +2748,7 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
        {
        case SAFI_UNICAST:
        case SAFI_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);
 }
index 2bbdca595c512cd22909bfc938f7217871d5ff0a..b17888482489aacd11944cf0b532099ece4126dd 100644 (file)
@@ -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 (file)
index 0000000..283afbc
--- /dev/null
@@ -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 (file)
index 0000000..a7e7d5c
--- /dev/null
@@ -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 */
index 423c9453ebbff8b1f0d9003d051f078e0c9e97da..152d4a7acde0ef50e2d5116e4547209fca912181 100644 (file)
@@ -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)
index b0362b5537dfb280c2e1a284d3f5bd4012e98475..1e8dc5d9744c95cb24aa4326082fc8c373778e17 100644 (file)
@@ -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))
index 51079f31e03b77be43d733e250f41177cf1226b2..83fc3fe97765b9949cf6c76c55eb9d8ed0b5c2bb 100644 (file)
@@ -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])
index 853fcc8697f6378a1d16ff8261b656dc07d2b4bc..f7a78caf91ff333aab683f2e40d6b8cc9cbc341d 100644 (file)
@@ -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:
index 432a566c15701b09a5a6e3fb4be2e3561b542cf7..77154b0f334b9ea5c1754701f59c7d38f69b89e0 100644 (file)
@@ -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)
index e75978d003fd8ee03d3786e510db762142bf1462..69b8ea8a553b42f2bf1af785986c07249871ab9a 100644 (file)
@@ -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);
 
index 3c96dac617a656c0b105041c9abbc48075fd0b8b..2b874f66a667b7bc6e39175dad35813950b4729a 100644 (file)
@@ -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)
 };
 
 /*
index efb2046e1256a7b8e2e6655e0544cc809c1e7ffe..ac5f77474c79b55c6946b9ac954d6f399e146e8f 100644 (file)
@@ -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);
index 57e5c07029df279d8356c2f4a2beda66e94b7619..135cdadb2463d3f2a453c1db2465a9808913aa82 100644 (file)
@@ -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.  */
index 72bd081a7e75c4480dbd92d037538c7fbf4f15bd..1ded613f65d296b7da05191e86d3242931e201a8 100644 (file)
@@ -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);
index d22a00e8fbed3df2871828b248b7f809a1de6738..bc4e36352d077339e0a26c7b8bd0999396a80282 100644 (file)
@@ -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);
 
index 0ed277b16464c9773999fe4d59b4735b8a111f84..1c73fb9407d9d78857076419ea3f9cc23d162c6b 100644 (file)
@@ -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;
index a72974bc1d6e9c866df009c02a8313df3d34062b..e95d059227f8544938513e3974b6be49c1c471be 100644 (file)
@@ -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;
index eb3ae3dafb618713b8f9e327ad4fb0c3e81e22bf..786c2bf7ea0b60b2f36a410079e57ecb5db002f8 100644 (file)
@@ -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)
 
index 301ebc627527611977326b0005de950f94514d89..32dde1ca0c0d4bb42faffa371b04c7d98073cabc 100644 (file)
@@ -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
index 1e2bc89b32d63a26f74217d0dce4d325265e5928..b7bf31bf7f45af225741ae16d854535a1ffd6d34 100644 (file)
@@ -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 *);