]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge remote-tracking branch 'origin/stable/3.0'
authorDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 19 May 2017 13:41:15 +0000 (09:41 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 19 May 2017 13:41:15 +0000 (09:41 -0400)
1  2 
bgpd/bgp_attr.c
bgpd/bgp_encap.c
bgpd/bgp_mplsvpn.c
bgpd/bgp_route.c

diff --combined bgpd/bgp_attr.c
index 9c06c74aac1b803e089676286e36c56de6037de1,5fe8ebb67fbb9c22ec26afe4c2b94431191599c3..ec4f34ff47dc1d55d90b186abe67fb3c8933dac3
@@@ -1,22 -1,22 +1,22 @@@
  /* BGP attributes management routines.
 -   Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
 -
 -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.  */
 + * Copyright (C) 1996, 97, 98, 1999 Kunihiro Ishiguro
 + *
 + * 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 this program; see the file COPYING; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 + */
  
  #include <zebra.h>
  
@@@ -78,8 -78,7 +78,8 @@@ static const struct message attr_str [
  #if ENABLE_BGP_VNC
    { BGP_ATTR_VNC,              "VNC" },
  #endif
 -  { BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY" }
 +  { BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY" },
 +  { BGP_ATTR_PREFIX_SID,        "PREFIX_SID" }
  };
  static const int attr_str_max = array_size(attr_str);
  
@@@ -533,10 -532,7 +533,10 @@@ static struct hash *attrhash
  static struct attr_extra *
  bgp_attr_extra_new (void)
  {
 -  return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
 +  struct attr_extra *extra;
 +  extra = XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
 +  extra->label_index = BGP_INVALID_LABEL_INDEX;
 +  return extra;
  }
  
  void
@@@ -680,7 -676,6 +680,7 @@@ attrhash_key_make (void *p
        MIX(extra->mp_nexthop_global_in.s_addr);
        MIX(extra->originator_id.s_addr);
        MIX(extra->tag);
 +      MIX(extra->label_index);
      }
    
    if (attr->aspath)
@@@ -735,7 -730,6 +735,7 @@@ attrhash_cmp (const void *p1, const voi
            && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr
            && ae1->weight == ae2->weight
            && ae1->tag == ae2->tag
 +          && ae1->label_index == ae2->label_index
            && ae1->mp_nexthop_len == ae2->mp_nexthop_len
            && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global)
            && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local)
@@@ -968,6 -962,26 +968,6 @@@ bgp_attr_default_set (struct attr *attr
    return attr;
  }
  
 -
 -/* Make network statement's attribute. */
 -struct attr *
 -bgp_attr_default_intern (u_char origin)
 -{
 -  struct attr attr;
 -  struct attr *new;
 -
 -  memset (&attr, 0, sizeof (struct attr));
 -  bgp_attr_extra_get (&attr);
 -
 -  bgp_attr_default_set(&attr, origin);
 -
 -  new = bgp_attr_intern (&attr);
 -  bgp_attr_extra_free (&attr);
 -  
 -  aspath_unintern (&new->aspath);
 -  return new;
 -}
 -
  /* Create the attributes for an aggregate */
  struct attr *
  bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
@@@ -1273,7 -1287,6 +1273,7 @@@ const u_int8_t attr_flags_values [] = 
    [BGP_ATTR_AS4_PATH] =         BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
    [BGP_ATTR_AS4_AGGREGATOR] =   BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
    [BGP_ATTR_LARGE_COMMUNITIES]= BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
 +  [BGP_ATTR_PREFIX_SID] =       BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS,
  };
  static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1;
  
@@@ -1480,7 -1493,8 +1480,7 @@@ bgp_attr_as4_path (struct bgp_attr_pars
      }
  
    /* Set aspath attribute flag. */
 -  if (as4_path)
 -    attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
 +  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
  
    return BGP_ATTR_PARSE_PROCEED;
  }
@@@ -2260,106 -2274,6 +2260,106 @@@ bgp_attr_encap
    return 0;
  }
  
 +/* Prefix SID attribute
 + * draft-ietf-idr-bgp-prefix-sid-05
 + */
 +static bgp_attr_parse_ret_t
 +bgp_attr_prefix_sid (struct bgp_attr_parser_args *args, struct bgp_nlri *mp_update)
 +{
 +  struct peer *const peer = args->peer;
 +  struct attr *const attr = args->attr;
 +  int type;
 +  int length;
 +  u_int32_t label_index;
 +  struct in6_addr ipv6_sid;
 +  u_int32_t srgb_base;
 +  u_int32_t srgb_range;
 +  int srgb_count;
 +
 +  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID);
 +
 +  type = stream_getc (peer->ibuf);
 +  length = stream_getw (peer->ibuf);
 +
 +  if (type == BGP_PREFIX_SID_LABEL_INDEX)
 +    {
 +      if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH)
 +        {
 +          zlog_err ("Prefix SID label index length is %d instead of %d", length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
 +          return bgp_attr_malformed (args,
 +                                     BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
 +                                     args->total);
 +        }
 +
 +        /* Ignore flags and reserved */
 +        stream_getc (peer->ibuf);
 +        stream_getw (peer->ibuf);
 +
 +        /* Fetch the label index and see if it is valid. */
 +        label_index = stream_getl (peer->ibuf);
 +        if (label_index == BGP_INVALID_LABEL_INDEX)
 +          return bgp_attr_malformed (args,
 +                                     BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
 +                                    args->total);
 +
 +        /* Store label index; subsequently, we'll check on address-family */
 +        (bgp_attr_extra_get (attr))->label_index = label_index;
 +
 +        /*
 +         * Ignore the Label index attribute unless received for labeled-unicast
 +         * SAFI.
 +         */
 +        if (!mp_update->length || mp_update->safi != SAFI_LABELED_UNICAST)
 +          attr->extra->label_index = BGP_INVALID_LABEL_INDEX;
 +    }
 +
 +  /* Placeholder code for the IPv6 SID type */
 +  else if (type == BGP_PREFIX_SID_IPV6)
 +    {
 +      if (length != BGP_PREFIX_SID_IPV6_LENGTH)
 +        {
 +          zlog_err ("Prefix SID IPv6 length is %d instead of %d", length, BGP_PREFIX_SID_IPV6_LENGTH);
 +          return bgp_attr_malformed (args,
 +                                     BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
 +                                     args->total);
 +        }
 +
 +        /* Ignore reserved */
 +        stream_getc (peer->ibuf);
 +        stream_getw (peer->ibuf);
 +
 +        stream_get (&ipv6_sid, peer->ibuf, 16);
 +    }
 +
 +  /* Placeholder code for the Originator SRGB type */
 +  else if (type == BGP_PREFIX_SID_ORIGINATOR_SRGB)
 +    {
 +      /* Ignore flags */
 +      stream_getw (peer->ibuf);
 +
 +      length -= 2;
 +
 +      if (length % BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH)
 +        {
 +          zlog_err ("Prefix SID Originator SRGB length is %d, it must be a multiple of %d ",
 +                    length, BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH);
 +          return bgp_attr_malformed (args,
 +                                     BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
 +                                     args->total);
 +        }
 +
 +      srgb_count = length / BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH;
 +
 +      for (int i = 0; i < srgb_count; i++)
 +        {
 +          stream_get (&srgb_base, peer->ibuf, 3);
 +          stream_get (&srgb_range, peer->ibuf, 3);
 +        }
 +    }
 +
 +  return BGP_ATTR_PARSE_PROCEED;
 +}
 +
  /* BGP unknown attribute treatment. */
  static bgp_attr_parse_ret_t
  bgp_attr_unknown (struct bgp_attr_parser_args *args)
@@@ -2658,9 -2572,6 +2658,9 @@@ bgp_attr_parse (struct peer *peer, stru
          case BGP_ATTR_ENCAP:
            ret = bgp_attr_encap (type, peer, length, attr, flag, startp);
            break;
 +        case BGP_ATTR_PREFIX_SID:
 +          ret = bgp_attr_prefix_sid (&attr_args, mp_update);
 +          break;
        default:
          ret = bgp_attr_unknown (&attr_args);
          break;
  }
  
  size_t
 -bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi,
 +bgp_packet_mpattr_start (struct stream *s, struct peer *peer,
 +                         afi_t afi, safi_t safi,
                         struct bpacket_attr_vec_arr *vecarr,
                         struct attr *attr)
  {
    size_t sizep;
    iana_afi_t pkt_afi;
    safi_t pkt_safi;
 +  afi_t nh_afi;
  
    /* Set extended bit always to encode the attribute length as 2 bytes */
    stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN);
  
    stream_putw (s, pkt_afi);    /* AFI */
    stream_putc (s, pkt_safi);   /* SAFI */
 -  if (afi == AFI_L2VPN)
 -    nh_afi = AFI_L2VPN;
 -  else if (nh_afi == AFI_MAX)
 -    nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->extra->mp_nexthop_len);
 +
 +  /* Nexthop AFI */
 +  if (peer_cap_enhe(peer, afi, safi)) {
 +    nh_afi = AFI_IP6;
 +  } else {
 +    if (afi == AFI_L2VPN)
 +      nh_afi = AFI_L2VPN;
 +    else if (safi == SAFI_LABELED_UNICAST)
 +      nh_afi = afi;
 +    else
 +      nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->extra->mp_nexthop_len);
 +  }
 +
    /* Nexthop */
    switch (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);
        {
        case SAFI_UNICAST:
        case SAFI_MULTICAST:
 +      case SAFI_LABELED_UNICAST:
        {
          struct attr_extra *attre = attr->extra;
  
          assert (attr->extra);
          bpacket_attr_vec_arr_set_vec (vecarr, BGP_ATTR_VEC_NH, s, attr);
 -        stream_putc (s, attre->mp_nexthop_len);
 -        stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
 -        if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
 +
 +        if (attre->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
 +          stream_putc (s, BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL);
 +          stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
            stream_put (s, &attre->mp_nexthop_local, IPV6_MAX_BYTELEN);
 +          } else {
 +          stream_putc (s, IPV6_MAX_BYTELEN);
 +          stream_put (s, &attre->mp_nexthop_global, IPV6_MAX_BYTELEN);
 +          }
        }
        break;
        case SAFI_MPLS_VPN:
@@@ -2983,11 -2876,6 +2983,11 @@@ bgp_packet_mpattr_prefix (struct strea
      {
        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);
  }
@@@ -3030,7 -2918,8 +3030,8 @@@ bgp_packet_mpattr_tea
        case BGP_ATTR_ENCAP:
            attrname = "Tunnel Encap";
            subtlvs = attr->extra->encap_subtlvs;
+             if (subtlvs == NULL) /* nothing to do */
+               return;
            /*
             * The tunnel encap attr has an "outer" tlv.
             * T = tunneltype,
        case BGP_ATTR_VNC:
            attrname = "VNC";
            subtlvs = attr->extra->vnc_subtlvs;
+             if (subtlvs == NULL) /* nothing to do */
+               return;
            attrlenfield = 0;     /* no outer T + L */
              attrhdrlen   = 2 + 2; /* subTLV T + L */
            break;
@@@ -3132,11 -3023,14 +3135,11 @@@ bgp_packet_attribute (struct bgp *bgp, 
    cp = stream_get_endp (s);
  
    if (p && !((afi == AFI_IP && safi == SAFI_UNICAST) &&
 -              !peer_cap_enhe(peer)))
 +             !peer_cap_enhe(peer, afi, safi)))
      {
        size_t mpattrlen_pos = 0;
  
 -      mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi,
 -                                    (peer_cap_enhe(peer) ? AFI_IP6 :
 -                                     AFI_MAX), /* get from NH */
 -                                    vecarr, attr);
 +      mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi, vecarr, attr);
        bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag,
                                 addpath_encode, addpath_tx_id, attr);
        bgp_packet_mpattr_end(s, mpattrlen_pos);
        send_as4_path = 1; /* we'll do this later, at the correct place */
    
    /* Nexthop attribute. */
 -  if (afi == AFI_IP && safi == SAFI_UNICAST && !peer_cap_enhe(peer))
 +  if (afi == AFI_IP && safi == SAFI_UNICAST && !peer_cap_enhe(peer, afi, safi))
      {
        if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP))
          {
            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, afi, safi))
          {
            /*
             * Likely this is the case when an IPv4 prefix was received with
        }
      }
  
 +  /* Label index attribute. */
 +  if (safi == SAFI_LABELED_UNICAST)
 +    {
 +      if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID))
 +        {
 +          u_int32_t label_index;
 +
 +          assert (attr->extra);
 +          label_index = attr->extra->label_index;
 +
 +          if (label_index != BGP_INVALID_LABEL_INDEX)
 +            {
 +              stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
 +              stream_putc (s, BGP_ATTR_PREFIX_SID);
 +              stream_putc (s, 10);
 +              stream_putc (s, BGP_PREFIX_SID_LABEL_INDEX);
 +              stream_putw (s, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
 +              stream_putc (s, 0); // reserved
 +              stream_putw (s, 0); // flags
 +              stream_putl (s, label_index);
 +            }
 +        }
 +    }
 +
    if ( send_as4_path )
      {
        /* If the peer is NOT As4 capable, AND */
@@@ -3573,11 -3443,6 +3576,11 @@@ bgp_packet_mpunreach_prefix (struct str
                             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);
  }
@@@ -3765,24 -3630,6 +3768,24 @@@ bgp_dump_routes_attr (struct stream *s
        stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1);
      }
  
 +  /* Prefix SID */
 +  if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID))
 +    {
 +      assert (attr->extra);
 +
 +      if (attr->extra->label_index != BGP_INVALID_LABEL_INDEX)
 +        {
 +          stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS);
 +          stream_putc (s, BGP_ATTR_PREFIX_SID);
 +          stream_putc (s, 10);
 +          stream_putc (s, BGP_PREFIX_SID_LABEL_INDEX);
 +          stream_putc (s, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
 +          stream_putc (s, 0); // reserved
 +          stream_putw (s, 0); // flags
 +          stream_putl (s, attr->extra->label_index);
 +        }
 +    }
 +
    /* Return total size of attribute. */
    len = stream_get_endp (s) - cp - 2;
    stream_putw_at (s, cp, len);
diff --combined bgpd/bgp_encap.c
index a1a0c1710b831ea9ccd7b4f7ac7972ce351d4ec7,060f5afb4cd80328009ed8b30befdcdfe7842e42..bc86a541e923664d90d0173a584eb3738c46df34
@@@ -1,26 -1,32 +1,26 @@@
 -
  /*
   * This file created by LabN Consulting, L.L.C.
   *
 - *
   * This file is based on bgp_mplsvpn.c which is Copyright (C) 2000
   * Kunihiro Ishiguro <kunihiro@zebra.org>
   *
 + * 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 this program; see the file COPYING; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
 -/* 
 -
 -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"
@@@ -202,25 -208,22 +202,22 @@@ bgp_nlri_parse_encap
  /* For testing purpose, static route of ENCAP. */
  DEFUN (encap_network,
         encap_network_cmd,
-        "network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
+        "network A.B.C.D/M rd ASN:nn_or_IP-address:nn",
         "Specify a network to announce via BGP\n"
         "IPv4 prefix\n"
         "Specify Route Distinguisher\n"
-        "ENCAP Route Distinguisher\n"
-        "BGP tag\n"
-        "tag value\n")
+        "ENCAP Route Distinguisher\n")
  {
    int idx_ipv4 = 1;
    int idx_rd = 3;
-   int idx_word = 5;
-   return bgp_static_set_safi (AFI_IP, SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, argv[idx_word]->arg,
+   return bgp_static_set_safi (AFI_IP, SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, NULL,
                                NULL, 0, NULL, NULL, NULL, NULL);
  }
  
  /* For testing purpose, static route of ENCAP. */
  DEFUN (no_encap_network,
         no_encap_network_cmd,
-        "no network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
+        "no network A.B.C.D/M rd ASN:nn_or_IP-address:nn",
         NO_STR
         "Specify a network to announce via BGP\n"
         "IPv4 prefix\n"
  {
    int idx_ipv4 = 2;
    int idx_rd = 4;
-   int idx_word = 6;
-   return bgp_static_unset_safi (AFI_IP, SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, argv[idx_word]->arg,
+   return bgp_static_unset_safi (AFI_IP, SAFI_ENCAP, vty, argv[idx_ipv4]->arg, argv[idx_rd]->arg, NULL,
                                  0, NULL, NULL, NULL);
  }
  
diff --combined bgpd/bgp_mplsvpn.c
index 2d13d05c007910680af273d69bcdfd5a3786a2b8,4a8bfed8bbacbfa0bb8b2967de5fb83cf59ba981..60e0a212ed1c87d2475eb176566f39065315d654
@@@ -1,22 -1,22 +1,22 @@@
  /* MPLS-VPN
 -   Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
 -
 -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.  */
 + * Copyright (C) 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
 + *
 + * 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 this program; see the file COPYING; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 + */
  
  #include <zebra.h>
  
@@@ -460,99 -460,104 +460,104 @@@ prefix_rd2str (struct prefix_rd *prd, c
  /* For testing purpose, static route of MPLS-VPN. */
  DEFUN (vpnv4_network,
         vpnv4_network_cmd,
-        "network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
+        "network A.B.C.D/M rd ASN:nn_or_IP-address:nn <tag|label> (0-1048575)",
         "Specify a network to announce via BGP\n"
         "IPv4 prefix\n"
         "Specify Route Distinguisher\n"
         "VPN Route Distinguisher\n"
-        "BGP tag\n"
-        "tag value\n")
+        "VPN NLRI label (tag)\n"
+        "VPN NLRI label (tag)\n"
+        "Label value\n")
  {
    int idx_ipv4_prefixlen = 1;
    int idx_ext_community = 3;
-   int idx_word = 5;
+   int idx_label = 5;
    return bgp_static_set_safi (AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg,
-                               argv[idx_word]->arg, NULL, 0, NULL, NULL, NULL, NULL);
+                               argv[idx_label]->arg, NULL, 0, NULL, NULL, NULL, NULL);
  }
  
  DEFUN (vpnv4_network_route_map,
         vpnv4_network_route_map_cmd,
-        "network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD route-map WORD",
+        "network A.B.C.D/M rd ASN:nn_or_IP-address:nn <tag|label> (0-1048575) route-map WORD",
         "Specify a network to announce via BGP\n"
         "IPv4 prefix\n"
         "Specify Route Distinguisher\n"
         "VPN Route Distinguisher\n"
-        "BGP tag\n"
-        "tag value\n"
+        "VPN NLRI label (tag)\n"
+        "VPN NLRI label (tag)\n"
+        "Label value\n"
         "route map\n"
         "route map name\n")
  {
    int idx_ipv4_prefixlen = 1;
    int idx_ext_community = 3;
-   int idx_word = 5;
+   int idx_label = 5;
    int idx_word_2 = 7;
-   return bgp_static_set_safi (AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg,
+   return bgp_static_set_safi (AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg, argv[idx_ext_community]->arg, argv[idx_label]->arg,
                                argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
  }
  
  /* For testing purpose, static route of MPLS-VPN. */
  DEFUN (no_vpnv4_network,
         no_vpnv4_network_cmd,
-        "no network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD",
+        "no network A.B.C.D/M rd ASN:nn_or_IP-address:nn <tag|label> (0-1048575)",
         NO_STR
         "Specify a network to announce via BGP\n"
         "IPv4 prefix\n"
         "Specify Route Distinguisher\n"
         "VPN Route Distinguisher\n"
-        "BGP tag\n"
-        "tag value\n")
+        "VPN NLRI label (tag)\n"
+        "VPN NLRI label (tag)\n"
+        "Label value\n")
  {
    int idx_ipv4_prefixlen = 2;
    int idx_ext_community = 4;
-   int idx_word = 6;
+   int idx_label = 6;
    return bgp_static_unset_safi (AFI_IP, SAFI_MPLS_VPN, vty, argv[idx_ipv4_prefixlen]->arg,
-                                 argv[idx_ext_community]->arg, argv[idx_word]->arg,
+                                 argv[idx_ext_community]->arg, argv[idx_label]->arg,
                                  0, NULL, NULL, NULL);
  }
  
  DEFUN (vpnv6_network,
         vpnv6_network_cmd,
-        "network X:X::X:X/M rd ASN:nn_or_IP-address:nn tag WORD [route-map WORD]",
+        "network X:X::X:X/M rd ASN:nn_or_IP-address:nn <tag|label> (0-1048575) [route-map WORD]",
         "Specify a network to announce via BGP\n"
         "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
         "Specify Route Distinguisher\n"
         "VPN Route Distinguisher\n"
-        "BGP tag\n"
-        "tag value\n"
+        "VPN NLRI label (tag)\n"
+        "VPN NLRI label (tag)\n"
+        "Label value\n"
         "route map\n"
         "route map name\n")
  {
    int idx_ipv6_prefix = 1;
    int idx_ext_community = 3;
-   int idx_word = 5;
+   int idx_label = 5;
    int idx_word_2 = 7;
    if (argc == 8)
-     return bgp_static_set_safi (AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
+     return bgp_static_set_safi (AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_label]->arg, argv[idx_word_2]->arg, 0, NULL, NULL, NULL, NULL);
    else
-     return bgp_static_set_safi (AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, NULL, 0, NULL, NULL, NULL, NULL);
+     return bgp_static_set_safi (AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_label]->arg, NULL, 0, NULL, NULL, NULL, NULL);
  }
  
  /* For testing purpose, static route of MPLS-VPN. */
  DEFUN (no_vpnv6_network,
         no_vpnv6_network_cmd,
-        "no network X:X::X:X/M rd ASN:nn_or_IP-address:nn tag WORD",
+        "no network X:X::X:X/M rd ASN:nn_or_IP-address:nn <tag|label> (0-1048575)",
         NO_STR
         "Specify a network to announce via BGP\n"
         "IPv6 prefix <network>/<length>, e.g., 3ffe::/16\n"
         "Specify Route Distinguisher\n"
         "VPN Route Distinguisher\n"
-        "BGP tag\n"
-        "tag value\n")
+        "VPN NLRI label (tag)\n"
+        "VPN NLRI label (tag)\n"
+        "Label value\n")
  {
    int idx_ipv6_prefix = 2;
    int idx_ext_community = 4;
-   int idx_word = 6;
-   return bgp_static_unset_safi (AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_word]->arg, 0, NULL, NULL, NULL);
+   int idx_label = 6;
+   return bgp_static_unset_safi (AFI_IP6, SAFI_MPLS_VPN, vty, argv[idx_ipv6_prefix]->arg, argv[idx_ext_community]->arg, argv[idx_label]->arg, 0, NULL, NULL, NULL);
  }
  
  int
diff --combined bgpd/bgp_route.c
index 0f719d55364501c55ee2de517b63d03152b8188b,5c157b95393377340aea310cc1dd1aca46ba28e0..172ef2e913e2c46e36226c9fbd3ffbad28f53325
@@@ -1,23 -1,23 +1,23 @@@
  /* BGP routing information
 -   Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
 -   Copyright (C) 2016 Job Snijders <job@instituut.net>
 -
 -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.  */
 + * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
 + * Copyright (C) 2016 Job Snijders <job@instituut.net>
 + *
 + * 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 this program; see the file COPYING; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 + */
  
  #include <zebra.h>
  
@@@ -35,7 -35,6 +35,7 @@@
  #include "thread.h"
  #include "workqueue.h"
  #include "queue.h"
 +#include "mpls.h"
  #include "memory.h"
  #include "lib/json.h"
  
@@@ -63,7 -62,6 +63,7 @@@
  #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"
@@@ -298,11 -296,6 +298,11 @@@ bgp_pcount_adjust (struct bgp_node *rn
      }
  }
  
 +static int
 +bgp_label_index_differs (struct bgp_info *ri1, struct bgp_info *ri2)
 +{
 +  return (!(ri1->attr->extra->label_index == ri2->attr->extra->label_index));
 +}
  
  /* Set/unset bgp_info flags, adjusting any other state as needed.
   * This is here primarily to keep prefix-count in check.
@@@ -1194,8 -1187,7 +1194,8 @@@ subgroup_announce_reset_nhop (u_char fa
  }
  
  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;
        return 0;
        }
  
 +  /* If it's labeled safi, make sure the route has a valid label. */
 +  if (safi == SAFI_LABELED_UNICAST)
 +    {
 +      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)
      {
  
  #define NEXTHOP_IS_V6 (\
      (safi != SAFI_ENCAP && safi != SAFI_MPLS_VPN &&\
 -     (p->family == AF_INET6 || peer_cap_enhe(peer))) || \
 +     (p->family == AF_INET6 || peer_cap_enhe(peer, AFI_IP6, safi))) || \
      ((safi == SAFI_ENCAP || safi == SAFI_MPLS_VPN) &&\
       attr->extra->mp_nexthop_len >= IPV6_MAX_BYTELEN))
  
            if (!reflect ||
                CHECK_FLAG (peer->af_flags[afi][safi],
                            PEER_FLAG_FORCE_NEXTHOP_SELF))
 -            subgroup_announce_reset_nhop ((peer_cap_enhe(peer) ?
 +            subgroup_announce_reset_nhop ((peer_cap_enhe(peer, afi, safi) ?
                            AF_INET6 : p->family), attr);
          }
        else if (peer->sort == BGP_PEER_EBGP)
                  break;
              }
            if (!paf)
 -            subgroup_announce_reset_nhop ((peer_cap_enhe(peer) ? AF_INET6 : p->family), attr);
 +            subgroup_announce_reset_nhop ((peer_cap_enhe(peer, afi, safi) ? AF_INET6 : p->family), attr);
          }
        /* If IPv6/MP and nexthop does not have any override and happens to
         * be a link-local address, reset it so that we don't pass along the
         * source's link-local IPv6 address to recipients who may not be on
         * the same interface.
         */
 -      if (p->family == AF_INET6 || peer_cap_enhe(peer))
 +      if (p->family == AF_INET6 || peer_cap_enhe(peer, afi, safi))
          {
            if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
              subgroup_announce_reset_nhop (AF_INET6, attr);
@@@ -1827,7 -1804,7 +1827,7 @@@ subgroup_process_announce_selected (str
    /* 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);
@@@ -1937,40 -1914,7 +1937,40 @@@ bgp_process_main (struct work_queue *wq
    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 except of the label index changes.
 +   */
 +  if (safi == SAFI_LABELED_UNICAST)
 +    {
 +      bgp_table_lock (bgp_node_table (rn));
 +      if (new_select)
 +        {
 +          if (!old_select ||
 +              bgp_label_index_differs (new_select, old_select) ||
 +              new_select->sub_type != old_select->sub_type)
 +            {
 +              if (new_select->sub_type == BGP_ROUTE_STATIC &&
 +                  new_select->attr->flag & ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID) &&
 +                  new_select->attr->extra->label_index != BGP_INVALID_LABEL_INDEX)
 +                {
 +                  if (CHECK_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
 +                    bgp_unregister_for_label (rn);
 +                  label_ntop (MPLS_IMP_NULL_LABEL, 1, rn->local_label);
 +                  bgp_set_valid_label(rn->local_label);
 +                }
 +              else
 +                bgp_register_for_label (rn, new_select);
 +            }
 +        }
 +      else if (CHECK_FLAG (rn->flags, BGP_NODE_REGISTERED_FOR_LABEL))
 +        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) &&
                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;
      }
        if (!bgp->t_rmap_def_originate_eval)
          {
            bgp_lock (bgp);
 -          THREAD_TIMER_ON(bm->master, bgp->t_rmap_def_originate_eval,
 -                          update_group_refresh_default_originate_route_map,
 -                          bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER);
 +          thread_add_timer(bm->master,
 +                           update_group_refresh_default_originate_route_map,
 +                           bgp, RMAP_DEFAULT_ORIGINATE_EVAL_TIMER,
 +                           &bgp->t_rmap_def_originate_eval);
          }
      }
  
    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))
      {
          && 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. */
@@@ -2479,7 -2406,6 +2479,7 @@@ bgp_update (struct peer *peer, struct p
    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
  
    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.  */
        /* 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)))
        {
              && 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)
                {
                      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. */
        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))
        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
            }
        }
  
 -      /* 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)
            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))
      memcpy ((bgp_info_extra_get (new))->tag, tag, 3);
  
    /* Update Overlay Index */
                             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)
            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)
@@@ -3089,6 -3008,9 +3089,6 @@@ bgp_announce_route_timer_expired (struc
    paf = THREAD_ARG (t);
    peer = paf->peer;
  
 -  assert (paf->t_announce_route);
 -  paf->t_announce_route = NULL;
 -
    if (peer->status != Established)
      return 0;
  
@@@ -3128,9 -3050,11 +3128,9 @@@ bgp_announce_route (struct peer *peer, 
     * multiple peers and the announcement doesn't happen in the
     * vty context.
     */
 -  THREAD_TIMER_MSEC_ON (bm->master, paf->t_announce_route,
 -                      bgp_announce_route_timer_expired, paf,
 -                        (subgrp->peer_count == 1) ?
 -                      BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS :
 -                      BGP_ANNOUNCE_ROUTE_DELAY_MS);
 +  thread_add_timer_msec(bm->master, bgp_announce_route_timer_expired, paf,
 +                        (subgrp->peer_count == 1) ? BGP_ANNOUNCE_ROUTE_SHORT_DELAY_MS : BGP_ANNOUNCE_ROUTE_DELAY_MS,
 +                        &paf->t_announce_route);
  }
  
  /*
@@@ -3778,9 -3702,9 +3778,9 @@@ bgp_static_free (struct bgp_static *bgp
    XFREE (MTYPE_BGP_STATIC, bgp_static);
  }
  
 -static void
 -bgp_static_update_main (struct bgp *bgp, struct prefix *p,
 -                      struct bgp_static *bgp_static, afi_t afi, safi_t safi)
 +void
 +bgp_static_update (struct bgp *bgp, struct prefix *p,
 +                   struct bgp_static *bgp_static, afi_t afi, safi_t safi)
  {
    struct bgp_node *rn;
    struct bgp_info *ri;
    if (bgp_static->atomic)
      attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE);
  
 +  /* Store label index, if required. */
 +  if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
 +    {
 +      (bgp_attr_extra_get (&attr))->label_index = bgp_static->label_index;
 +      attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_PREFIX_SID);
 +    }
 +
    /* Apply route-map. */
    if (bgp_static->rmap.name)
      {
  #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
                {
    bgp_attr_extra_free (&attr);
  }
  
 -void
 -bgp_static_update (struct bgp *bgp, struct prefix *p,
 -                  struct bgp_static *bgp_static, afi_t afi, safi_t safi)
 -{
 -  bgp_static_update_main (bgp, p, bgp_static, afi, safi);
 -}
 -
  void
  bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi,
                     safi_t safi)
@@@ -4086,7 -4008,7 +4086,7 @@@ bgp_static_update_safi (struct bgp *bgp
  
    if ((safi == SAFI_EVPN) || (safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP))
      {
-       if (bgp_static->igpnexthop.s_addr)
+       if (afi == AFI_IP)
          {
            bgp_attr_extra_get (&attr)->mp_nexthop_global_in = bgp_static->igpnexthop;
            bgp_attr_extra_get (&attr)->mp_nexthop_len = IPV4_MAX_BYTELEN;
     route should be installed as valid.  */
  static int
  bgp_static_set (struct vty *vty, const char *ip_str, 
 -                afi_t afi, safi_t safi, const char *rmap, int backdoor)
 +                afi_t afi, safi_t safi, const char *rmap, int backdoor,
 +                u_int32_t label_index)
  {
    VTY_DECLVAR_CONTEXT(bgp, bgp);
    int ret;
        /* Configuration change. */
        bgp_static = rn->info;
  
 +      /* Label index cannot be changed. */
 +      if (bgp_static->label_index != label_index)
 +        {
 +          vty_out (vty, "%% Label index cannot be changed%s", VTY_NEWLINE);
 +          return CMD_WARNING;
 +        }
 +
        /* Check previous routes are installed into BGP.  */
        if (bgp_static->valid && bgp_static->backdoor != backdoor)
          need_update = 1;
        bgp_static->valid = 0;
        bgp_static->igpmetric = 0;
        bgp_static->igpnexthop.s_addr = 0;
 +      bgp_static->label_index = label_index;
        
        if (rmap)
        {
@@@ -4541,7 -4454,7 +4541,7 @@@ bgp_purge_static_redist_routes (struct 
   */
  int
  bgp_static_set_safi (afi_t afi, safi_t safi, struct vty *vty, const char *ip_str,
-                      const char *rd_str, const char *tag_str,
+                      const char *rd_str, const char *label_str,
                       const char *rmap_str, int evpn_type, const char *esi, const char *gwip,
                       const char *ethtag, const char *routermac)
  {
        return CMD_WARNING;
      }
  
-   if (tag_str)
+   if (label_str)
      {
-       ret = str2tag (tag_str, tag);
-       if (! ret)
-         {
-           vty_out (vty, "%% Malformed tag%s", VTY_NEWLINE);
-           return CMD_WARNING;
-         }
+       unsigned long label_val;
+       VTY_GET_INTEGER_RANGE("Label/tag", label_val, label_str, 0, 16777215);
+       encode_label (label_val, tag);
      }
    else
      {
-       encode_label (0, tag);
+       memset (tag, 0, sizeof(tag)); /* empty, not even BoS */
      }
    if (safi == SAFI_EVPN)
      {
        if (rmap_str)
        {
          if (bgp_static->rmap.name)
-           free (bgp_static->rmap.name);
-         bgp_static->rmap.name = strdup (rmap_str);
+           XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
+         bgp_static->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
          bgp_static->rmap.map = route_map_lookup_by_name (rmap_str);
        }
  
  /* Configure static BGP network. */
  int
  bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty, const char *ip_str,
-                       const char *rd_str, const char *tag_str,
+                       const char *rd_str, const char *label_str,
                        int evpn_type, const char *esi, const char *gwip, const char *ethtag)
  {
    VTY_DECLVAR_CONTEXT(bgp, bgp);
        return CMD_WARNING;
      }
  
-   ret = str2tag (tag_str, tag);
-   if (! ret)
+   if (label_str)
      {
-       vty_out (vty, "%% Malformed tag%s", VTY_NEWLINE);
-       return CMD_WARNING;
+       unsigned long label_val;
+       VTY_GET_INTEGER_RANGE("Label/tag", label_val, label_str, 0, MPLS_LABEL_MAX);
+       encode_label (label_val, tag);
+     }
+   else
+     {
+       memset (tag, 0, sizeof(tag)); /* empty, not even BoS */
      }
  
    prn = bgp_node_get (bgp->route[afi][safi],
@@@ -4838,8 -4752,7 +4839,8 @@@ DEFUN (bgp_network
  {
    int idx_ipv4_prefixlen = 1;
    return bgp_static_set (vty, argv[idx_ipv4_prefixlen]->arg,
 -                       AFI_IP, bgp_node_safi (vty), NULL, 0);
 +                       AFI_IP, bgp_node_safi (vty), NULL, 0,
 +                         BGP_INVALID_LABEL_INDEX);
  }
  
  DEFUN (bgp_network_route_map,
    int idx_ipv4_prefixlen = 1;
    int idx_word = 3;
    return bgp_static_set (vty, argv[idx_ipv4_prefixlen]->arg,
 -                       AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0);
 +                       AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0,
 +                         BGP_INVALID_LABEL_INDEX);
  }
  
  DEFUN (bgp_network_backdoor,
  {
    int idx_ipv4_prefixlen = 1;
    return bgp_static_set (vty, argv[idx_ipv4_prefixlen]->arg, AFI_IP, SAFI_UNICAST,
 -                         NULL, 1);
 +                         NULL, 1, BGP_INVALID_LABEL_INDEX);
  }
  
  DEFUN (bgp_network_mask,
      }
  
    return bgp_static_set (vty, prefix_str,
 -                       AFI_IP, bgp_node_safi (vty), NULL, 0);
 +                       AFI_IP, bgp_node_safi (vty), NULL, 0, BGP_INVALID_LABEL_INDEX);
  }
  
  DEFUN (bgp_network_mask_route_map,
      }
  
    return bgp_static_set (vty, prefix_str,
 -                       AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0);
 +                       AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0, BGP_INVALID_LABEL_INDEX);
  }
  
  DEFUN (bgp_network_mask_backdoor,
      }
  
    return bgp_static_set (vty, prefix_str, AFI_IP, SAFI_UNICAST,
 -                         NULL, 1);
 +                         NULL, 1,
 +                         BGP_INVALID_LABEL_INDEX);
  }
  
  DEFUN (bgp_network_mask_natural,
      }
  
    return bgp_static_set (vty, prefix_str,
 -                       AFI_IP, bgp_node_safi (vty), NULL, 0);
 +                       AFI_IP, bgp_node_safi (vty), NULL, 0,
 +                         BGP_INVALID_LABEL_INDEX);
  }
  
  DEFUN (bgp_network_mask_natural_route_map,
      }
  
    return bgp_static_set (vty, prefix_str,
 -                       AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0);
 +                       AFI_IP, bgp_node_safi (vty), argv[idx_word]->arg, 0,
 +                         BGP_INVALID_LABEL_INDEX);
  }
  
  DEFUN (bgp_network_mask_natural_backdoor,
      }
  
    return bgp_static_set (vty, prefix_str, AFI_IP, SAFI_UNICAST,
 -                         NULL, 1);
 +                         NULL, 1, BGP_INVALID_LABEL_INDEX);
 +}
 +
 +DEFUN (bgp_network_label_index,
 +       bgp_network_label_index_cmd,
 +       "network A.B.C.D/M label-index (0-4294967294)",
 +       "Specify a network to announce via BGP\n"
 +       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
 +       "Label index to associate with the prefix\n"
 +       "Label index value\n")
 +{
 +  u_int32_t label_index;
 +
 +  VTY_GET_INTEGER ("label-index", label_index, argv[3]->arg);
 +  return bgp_static_set (vty, argv[1]->arg,
 +                         AFI_IP, bgp_node_safi (vty), NULL, 0, label_index);
 +}
 +
 +DEFUN (bgp_network_label_index_route_map,
 +       bgp_network_label_index_route_map_cmd,
 +       "network A.B.C.D/M label-index (0-4294967294) route-map WORD",
 +       "Specify a network to announce via BGP\n"
 +       "IP prefix\n"
 +       "Label index to associate with the prefix\n"
 +       "Label index value\n"
 +       "Route-map to modify the attributes\n"
 +       "Name of the route map\n")
 +{
 +  u_int32_t label_index;
 +
 +  VTY_GET_INTEGER ("label-index", label_index, argv[3]->arg);
 +  return bgp_static_set (vty, argv[1]->arg,
 +                         AFI_IP, bgp_node_safi (vty), argv[5]->arg, 0, label_index);
  }
  
  DEFUN (no_bgp_network,
@@@ -5115,26 -4992,6 +5116,26 @@@ DEFUN (no_bgp_network_mask_natural
                           bgp_node_safi (vty));
  }
  
 +ALIAS (no_bgp_network,
 +       no_bgp_network_label_index_cmd,
 +       "no network A.B.C.D/M label-index (0-4294967294)",
 +       NO_STR
 +       "Specify a network to announce via BGP\n"
 +       "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
 +       "Label index to associate with the prefix\n"
 +       "Label index value\n")
 +
 +ALIAS (no_bgp_network,
 +       no_bgp_network_label_index_route_map_cmd,
 +       "no network A.B.C.D/M label-index (0-4294967294) route-map WORD",
 +       NO_STR
 +       "Specify a network to announce via BGP\n"
 +       "IP prefix\n"
 +       "Label index to associate with the prefix\n"
 +       "Label index value\n"
 +       "Route-map to modify the attributes\n"
 +       "Name of the route map\n")
 +
  DEFUN (ipv6_bgp_network,
         ipv6_bgp_network_cmd,
         "network X:X::X:X/M",
  {
    int idx_ipv6_prefixlen = 1;
    return bgp_static_set (vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, bgp_node_safi(vty),
 -                         NULL, 0);
 +                         NULL, 0,
 +                         BGP_INVALID_LABEL_INDEX);
  }
  
  DEFUN (ipv6_bgp_network_route_map,
    int idx_ipv6_prefixlen = 1;
    int idx_word = 3;
    return bgp_static_set (vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6,
 -                       bgp_node_safi (vty), argv[idx_word]->arg, 0);
 +                       bgp_node_safi (vty), argv[idx_word]->arg, 0,
 +                         BGP_INVALID_LABEL_INDEX);
 +}
 +
 +DEFUN (ipv6_bgp_network_label_index,
 +       ipv6_bgp_network_label_index_cmd,
 +       "network X:X::X:X/M label-index (0-4294967294)",
 +       "Specify a network to announce via BGP\n"
 +       "IPv6 prefix <network>/<length>\n"
 +       "Label index to associate with the prefix\n"
 +       "Label index value\n")
 +{
 +  u_int32_t label_index;
 +
 +  VTY_GET_INTEGER ("label-index", label_index, argv[3]->arg);
 +  return bgp_static_set (vty, argv[1]->arg,
 +                         AFI_IP6, bgp_node_safi (vty), NULL, 0, label_index);
 +}
 +
 +DEFUN (ipv6_bgp_network_label_index_route_map,
 +       ipv6_bgp_network_label_index_route_map_cmd,
 +       "network X:X::X:X/M label-index (0-4294967294) route-map WORD",
 +       "Specify a network to announce via BGP\n"
 +       "IPv6 prefix\n"
 +       "Label index to associate with the prefix\n"
 +       "Label index value\n"
 +       "Route-map to modify the attributes\n"
 +       "Name of the route map\n")
 +{
 +  u_int32_t label_index;
 +
 +  VTY_GET_INTEGER ("label-index", label_index, argv[3]->arg);
 +  return bgp_static_set (vty, argv[1]->arg,
 +                         AFI_IP6, bgp_node_safi (vty), argv[5]->arg, 0, label_index);
  }
  
  DEFUN (no_ipv6_bgp_network,
    return bgp_static_unset (vty, argv[idx_ipv6_prefixlen]->arg, AFI_IP6, bgp_node_safi(vty));
  }
  
 +ALIAS (no_ipv6_bgp_network,
 +       no_ipv6_bgp_network_label_index_cmd,
 +       "no network X:X::X:X/M label-index (0-4294967294)",
 +       NO_STR
 +       "Specify a network to announce via BGP\n"
 +       "IPv6 prefix <network>/<length>\n"
 +       "Label index to associate with the prefix\n"
 +       "Label index value\n")
 +
 +ALIAS (no_ipv6_bgp_network,
 +       no_ipv6_bgp_network_label_index_route_map_cmd,
 +       "no network X:X::X:X/M label-index (0-4294967294) route-map WORD",
 +       NO_STR
 +       "Specify a network to announce via BGP\n"
 +       "IPv6 prefix\n"
 +       "Label index to associate with the prefix\n"
 +       "Label index value\n"
 +       "Route-map to modify the attributes\n"
 +       "Name of the route map\n")
 +
  /* Aggreagete address:
  
    advertise-map  Set condition to advertise attribute
@@@ -5756,11 -5559,9 +5757,11 @@@ bgp_aggregate_unset (struct vty *vty, c
      }
  
    aggregate = rn->info;
 -  if (aggregate->safi & SAFI_UNICAST)
 +  if (aggregate->safi == SAFI_UNICAST)
      bgp_aggregate_delete (bgp, &p, afi, SAFI_UNICAST, aggregate);
 -  if (aggregate->safi & SAFI_MULTICAST)
 +  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);
  
    /* Unlock aggregate address configuration. */
@@@ -5816,11 -5617,9 +5817,11 @@@ bgp_aggregate_set (struct vty *vty, con
    rn->info = aggregate;
  
    /* Aggregate address insert into BGP routing table. */
 -  if (safi & SAFI_UNICAST)
 +  if (safi == SAFI_UNICAST)
      bgp_aggregate_add (bgp, &p, afi, SAFI_UNICAST, aggregate);
 -  if (safi & SAFI_MULTICAST)
 +  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);
  
    return CMD_SUCCESS;
@@@ -5859,8 -5658,9 +5860,8 @@@ DEFUN (aggregate_address_mask
  {
    int idx = 0;
    argv_find (argv, argc, "A.B.C.D", &idx);
 -  char *prefix = argv[idx++]->arg;
 -  argv_find (argv, argc, "A.B.C.D", &idx);
 -  char *mask = argv[idx]->arg;
 +  char *prefix = argv[idx]->arg;
 +  char *mask = argv[idx+1]->arg;
    int as_set = argv_find (argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
    idx = 0;
    int summary_only = argv_find (argv, argc, "summary-only", &idx) ? AGGREGATE_SUMMARY_ONLY : 0;
@@@ -5908,8 -5708,9 +5909,8 @@@ DEFUN (no_aggregate_address_mask
  {
    int idx = 0;
    argv_find (argv, argc, "A.B.C.D", &idx);
 -  char *prefix = argv[idx++]->arg;
 -  argv_find (argv, argc, "A.B.C.D", &idx);
 -  char *mask = argv[idx]->arg;
 +  char *prefix = argv[idx]->arg;
 +  char *mask = argv[idx+1]->arg;
  
    char prefix_str[BUFSIZ];
    int ret = netmask_str2prefix_str (prefix, mask, prefix_str);
@@@ -7642,25 -7443,6 +7643,25 @@@ route_vty_out_detail (struct vty *vty, 
        if (binfo->extra && binfo->extra->damp_info)
        bgp_damp_info_vty (vty, binfo, json_path);
  
 +      /* Remove Label */
 +      if (bgp_labeled_safi(safi) && binfo->extra)
 +        {
 +          uint32_t label = label_pton(binfo->extra->tag);
 +          if (json_paths)
 +            json_object_int_add(json_path, "remoteLabel", label);
 +          else
 +            vty_out(vty, "      Remote label: %d%s", label, VTY_NEWLINE);
 +        }
 +
 +      /* Label Index */
 +      if (attr->extra->label_index != BGP_INVALID_LABEL_INDEX)
 +        {
 +          if (json_paths)
 +            json_object_int_add(json_path, "labelIndex", attr->extra->label_index);
 +          else
 +            vty_out(vty, "      Label Index: %d%s", attr->extra->label_index, VTY_NEWLINE);
 +        }
 +
        /* Line 8 display Addpath IDs */
        if (binfo->addpath_rx_id || binfo->addpath_tx_id)
          {
@@@ -8154,18 -7936,6 +8155,18 @@@ route_vty_out_detail_header (struct vt
               ((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)
@@@ -8447,7 -8217,7 +8448,7 @@@ bgp_show_lcommunity_list (struct vty *v
  
  DEFUN (show_ip_bgp_large_community_list,
         show_ip_bgp_large_community_list_cmd,
 -       "show [ip] bgp [<view|vrf> WORD] [<ipv4|ipv6> [<unicast|multicast|vpn|encap>]] large-community-list <(1-500)|WORD> [json]",
 +       "show [ip] bgp [<view|vrf> WORD] [<ipv4|ipv6> [<unicast|multicast|vpn|encap|labeled-unicast>]] large-community-list <(1-500)|WORD> [json]",
         SHOW_STR
         IP_STR
         BGP_STR
         "Address Family modifier\n"
         "Address Family modifier\n"
         "Address Family modifier\n"
 +       "Address Family modifier\n"
         "Display routes matching the large-community-list\n"
         "large-community-list number\n"
         "large-community-list name\n"
  }
  DEFUN (show_ip_bgp_large_community,
         show_ip_bgp_large_community_cmd,
 -       "show [ip] bgp [<view|vrf> WORD] [<ipv4|ipv6> [<unicast|multicast|vpn|encap>]] large-community [AA:BB:CC] [json]",
 +       "show [ip] bgp [<view|vrf> WORD] [<ipv4|ipv6> [<unicast|multicast|vpn|encap|labeled-unicast>]] large-community [AA:BB:CC] [json]",
         SHOW_STR
         IP_STR
         BGP_STR
         "Address Family modifier\n"
         "Address Family modifier\n"
         "Address Family modifier\n"
 +       "Address Family modifier\n"
         "Display routes matching the large-communities\n"
         "List of large-community numbers\n"
         JSON_STR)
@@@ -8875,7 -8643,6 +8876,7 @@@ bgp_show_community (struct vty *vty, st
    int i;
    char *str;
    int first = 0;
 +  int ret = 0;
  
    b = buffer_new (1024);
    for (i = 0; i < argc; i++)
        return CMD_WARNING;
      }
  
 -  return bgp_show (vty, bgp, afi, safi,
 -                   (exact ? bgp_show_type_community_exact :
 -                  bgp_show_type_community), com, 0);
 +  ret = bgp_show (vty, bgp, afi, safi,
 +                  (exact ? bgp_show_type_community_exact :
 +                bgp_show_type_community), com, 0);
 +  community_free (com);
 +
 +  return ret;
  }
  
  static int
@@@ -9450,7 -9214,7 +9451,7 @@@ bgp_peer_counts (struct vty *vty, struc
  
  DEFUN (show_ip_bgp_instance_neighbor_prefix_counts,
         show_ip_bgp_instance_neighbor_prefix_counts_cmd,
 -       "show [ip] bgp [<view|vrf> WORD] [<ipv4|ipv6> [<unicast|multicast|vpn|encap>]] "
 +       "show [ip] bgp [<view|vrf> WORD] [<ipv4|ipv6> [<unicast|multicast|vpn|encap|labeled-unicast>]] "
         "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
         SHOW_STR
         IP_STR
         "Address Family modifier\n"
         "Address Family modifier\n"
         "Address Family modifier\n"
 +       "Address Family modifier\n"
         "Detailed information on TCP and BGP neighbor connections\n"
         "Neighbor to display information about\n"
         "Neighbor to display information about\n"
@@@ -10671,10 -10434,17 +10672,17 @@@ bgp_config_write_network_vpn (struct vt
            prefix_rd2str (prd, rdbuf, RD_ADDRSTRLEN);
            label = decode_label (bgp_static->tag);
  
-           vty_out (vty, "  network %s/%d rd %s tag %d",
+           vty_out (vty, "  network %s/%d rd %s label %d",
                     inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), 
                     p->prefixlen,
                     rdbuf, label);
+             if (bgp_static->rmap.name)
+               vty_out (vty, " route-map %s", bgp_static->rmap.name);
+             else
+               {
+                 if (bgp_static->backdoor)
+                   vty_out (vty, " backdoor");
+               }
            vty_out (vty, "%s", VTY_NEWLINE);
          }
    return 0;
@@@ -10786,9 -10556,6 +10794,9 @@@ bgp_config_write_network (struct vty *v
                     p->prefixlen);
          }
  
 +        if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX)
 +        vty_out (vty, " label-index %u", bgp_static->label_index);
 +
        if (bgp_static->rmap.name)
          vty_out (vty, " route-map %s", bgp_static->rmap.name);
        else 
@@@ -10915,8 -10682,6 +10923,8 @@@ bgp_route_init (void
    install_element (BGP_IPV4_NODE, &bgp_network_route_map_cmd);
    install_element (BGP_IPV4_NODE, &bgp_network_mask_route_map_cmd);
    install_element (BGP_IPV4_NODE, &bgp_network_mask_natural_route_map_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_bgp_network_label_index_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_bgp_network_label_index_route_map_cmd);
    install_element (BGP_IPV4_NODE, &no_bgp_table_map_cmd);
    install_element (BGP_IPV4_NODE, &no_bgp_network_cmd);
    install_element (BGP_IPV4_NODE, &no_bgp_network_mask_cmd);
    install_element (BGP_IPV4M_NODE, &no_aggregate_address_cmd);
    install_element (BGP_IPV4M_NODE, &no_aggregate_address_mask_cmd);
  
 +  /* IPv4 labeled-unicast configuration.  */
 +  install_element (BGP_IPV4L_NODE, &bgp_table_map_cmd);
 +  install_element (BGP_IPV4L_NODE, &bgp_network_cmd);
 +  install_element (BGP_IPV4L_NODE, &bgp_network_mask_cmd);
 +  install_element (BGP_IPV4L_NODE, &bgp_network_mask_natural_cmd);
 +  install_element (BGP_IPV4L_NODE, &bgp_network_route_map_cmd);
 +  install_element (BGP_IPV4L_NODE, &bgp_network_mask_route_map_cmd);
 +  install_element (BGP_IPV4L_NODE, &bgp_network_mask_natural_route_map_cmd);
 +  install_element (BGP_IPV4L_NODE, &bgp_network_label_index_cmd);
 +  install_element (BGP_IPV4L_NODE, &bgp_network_label_index_route_map_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_bgp_table_map_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_bgp_network_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_bgp_network_mask_cmd);
 +  install_element (BGP_IPV4L_NODE, &no_bgp_network_mask_natural_cmd);
 +
    install_element (VIEW_NODE, &show_ip_bgp_instance_all_cmd);
    install_element (VIEW_NODE, &show_ip_bgp_cmd);
    install_element (VIEW_NODE, &show_ip_bgp_route_cmd);
    install_element (BGP_IPV6_NODE, &ipv6_bgp_network_route_map_cmd);
    install_element (BGP_IPV6_NODE, &no_bgp_table_map_cmd);
    install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_cmd);
 +  install_element (BGP_IPV6_NODE, &ipv6_bgp_network_label_index_cmd);
 +  install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_label_index_cmd);
 +  install_element (BGP_IPV6_NODE, &ipv6_bgp_network_label_index_route_map_cmd);
 +  install_element (BGP_IPV6_NODE, &no_ipv6_bgp_network_label_index_route_map_cmd);
  
    install_element (BGP_IPV6_NODE, &ipv6_aggregate_address_cmd);
    install_element (BGP_IPV6_NODE, &no_ipv6_aggregate_address_cmd);
    install_element (BGP_IPV6M_NODE, &ipv6_bgp_network_cmd);
    install_element (BGP_IPV6M_NODE, &no_ipv6_bgp_network_cmd);
  
 +  install_element (BGP_IPV6L_NODE, &bgp_table_map_cmd);
 +  install_element (BGP_IPV6L_NODE, &ipv6_bgp_network_cmd);
 +  install_element (BGP_IPV6L_NODE, &ipv6_bgp_network_route_map_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_bgp_table_map_cmd);
 +  install_element (BGP_IPV6L_NODE, &no_ipv6_bgp_network_cmd);
 +
    install_element (BGP_NODE, &bgp_distance_cmd);
    install_element (BGP_NODE, &no_bgp_distance_cmd);
    install_element (BGP_NODE, &bgp_distance_source_cmd);