]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd: Install SAFI_LABELED_UNICAST routes in SAFI_UNICAST table
authorDaniel Walton <dwalton@cumulusnetworks.com>
Fri, 16 Jun 2017 19:12:57 +0000 (19:12 +0000)
committerDaniel Walton <dwalton@cumulusnetworks.com>
Fri, 16 Jun 2017 19:12:57 +0000 (19:12 +0000)
Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
- All ipv4 labeled-unicast routes are now installed in the ipv4 unicast
  table. This allows us to do things like take routes from an ipv4
  unicast peer, allocate a label for them and TX them to a ipv4
  labeled-unicast peer. We can do the opposite where we take routes from
  a labeled-unicast peer, remove the label and advertise them to an ipv4
  unicast peer.

- Multipath over a labeled route and non-labeled route is not allowed.

- You cannot activate a peer for both 'ipv4 unicast' and 'ipv4
  labeled-unicast'

- The 'tag' variable was overloaded for zebra's route tag feature as
  well as the mpls label. I added a 'mpls_label_t mpls' variable to
  avoid this.  This is much cleaner but resulted in touching a lot of
  code.

24 files changed:
bgpd/bgp_attr.c
bgpd/bgp_attr.h
bgpd/bgp_evpn.c
bgpd/bgp_evpn.h
bgpd/bgp_label.c
bgpd/bgp_label.h
bgpd/bgp_mplsvpn.c
bgpd/bgp_mplsvpn.h
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_vty.c
bgpd/bgp_vty.h
bgpd/bgp_zebra.c
bgpd/bgpd.c
bgpd/bgpd.h
lib/mpls.h
lib/stream.c
lib/stream.h
zebra/zebra_mpls.c
zebra/zserv.c

index cf2e4875905a0ff8ee23545a0ce9faf03354a8d5..1d038ba450708fc50a4b9c86a6b9ea3d1d1143d6 100644 (file)
@@ -39,6 +39,7 @@
 #include "bgpd/bgp_aspath.h"
 #include "bgpd/bgp_community.h"
 #include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_label.h"
 #include "bgpd/bgp_packet.h"
 #include "bgpd/bgp_ecommunity.h"
 #include "bgpd/bgp_lcommunity.h"
@@ -536,6 +537,7 @@ bgp_attr_extra_new (void)
   struct attr_extra *extra;
   extra = XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra));
   extra->label_index = BGP_INVALID_LABEL_INDEX;
+  extra->label = MPLS_INVALID_LABEL;
   return extra;
 }
 
@@ -579,6 +581,9 @@ bgp_attr_dup (struct attr *new, struct attr *orig)
     {
       new->extra = extra;
       memset(new->extra, 0, sizeof(struct attr_extra));
+      new->extra->label_index = BGP_INVALID_LABEL_INDEX;
+      new->extra->label = MPLS_INVALID_LABEL;
+
       if (orig->extra) {
         *new->extra = *orig->extra;
       }
@@ -962,6 +967,8 @@ bgp_attr_default_set (struct attr *attr, u_char origin)
   attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH);
   attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT;
   attr->extra->tag = 0;
+  attr->extra->label_index = BGP_INVALID_LABEL_INDEX;
+  attr->extra->label = MPLS_INVALID_LABEL;
   attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP);
   attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN;
 
@@ -1003,6 +1010,8 @@ bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin,
       attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES);
     }
 
+  attre.label_index = BGP_INVALID_LABEL_INDEX;
+  attre.label = MPLS_INVALID_LABEL;
   attre.weight = BGP_ATTR_DEFAULT_WEIGHT;
   attre.mp_nexthop_len = IPV6_MAX_BYTELEN;
   if (! as_set || atomic_aggregate)
@@ -2964,27 +2973,27 @@ bgp_packet_mpattr_start (struct stream *s, struct peer *peer,
 void
 bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi,
                          struct prefix *p, struct prefix_rd *prd,
-                          u_char *tag, int addpath_encode,
+                          mpls_label_t *label, int addpath_encode,
                           u_int32_t addpath_tx_id, struct attr *attr)
 {
   if (safi == SAFI_MPLS_VPN)
     {
       if (addpath_encode)
         stream_putl(s, addpath_tx_id);
-      /* Tag, RD, Prefix write. */
+      /* Label, RD, Prefix write. */
       stream_putc (s, p->prefixlen + 88);
-      stream_put (s, tag, 3);
+      stream_put (s, label, BGP_LABEL_BYTES);
       stream_put (s, prd->val, 8);
       stream_put (s, &p->u.prefix, PSIZE (p->prefixlen));
     }
   else if (safi == SAFI_EVPN)
     {
-      bgp_packet_mpattr_route_type_5(s, p, prd, tag, attr);
+      bgp_packet_mpattr_route_type_5(s, p, prd, label, attr);
     }
   else if (safi == SAFI_LABELED_UNICAST)
     {
       /* Prefix write with label. */
-      stream_put_labeled_prefix(s, p, tag);
+      stream_put_labeled_prefix(s, p, label);
     }
   else
     stream_put_prefix_addpath (s, p, addpath_encode, addpath_tx_id);
@@ -3115,7 +3124,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
                      struct stream *s, struct attr *attr,
                      struct bpacket_attr_vec_arr *vecarr,
                      struct prefix *p, afi_t afi, safi_t safi,
-                     struct peer *from, struct prefix_rd *prd, u_char *tag,
+                     struct peer *from, struct prefix_rd *prd, mpls_label_t *label,
                       int addpath_encode,
                       u_int32_t addpath_tx_id)
 {
@@ -3138,7 +3147,7 @@ bgp_packet_attribute (struct bgp *bgp, struct peer *peer,
       size_t mpattrlen_pos = 0;
 
       mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi, vecarr, attr);
-      bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag,
+      bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label,
                                addpath_encode, addpath_tx_id, attr);
       bgp_packet_mpattr_end(s, mpattrlen_pos);
     }
@@ -3571,16 +3580,17 @@ bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi)
 void
 bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
                             afi_t afi, safi_t safi, struct prefix_rd *prd,
-                            u_char *tag, int addpath_encode,
+                            mpls_label_t *label, 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;
+    label = (mpls_label_t *) wlabel;
 
   return bgp_packet_mpattr_prefix (s, afi, safi, p, prd,
-                                   tag, addpath_encode, addpath_tx_id, attr);
+                                   label,
+                                   addpath_encode, addpath_tx_id, attr);
 }
 
 void
index f25df3a8b9e5a0075107cf1890cd764d2aa250d5..f3c1b5e3c20c49ffc64ea18e80fcf95fc603840e 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef _QUAGGA_BGP_ATTR_H
 #define _QUAGGA_BGP_ATTR_H
 
+#include "mpls.h"
 #include "bgp_attr_evpn.h"
 
 /* Simple bit mapping. */
@@ -145,6 +146,9 @@ struct attr_extra
   /* Label index */
   u_int32_t label_index;
 
+  /* MPLS label */
+  mpls_label_t label;
+
   uint16_t                     encap_tunneltype;       /* grr */
   struct bgp_attr_encap_subtlv *encap_subtlvs;         /* rfc5512 */
 
@@ -254,7 +258,7 @@ extern bgp_size_t bgp_packet_attribute (struct bgp *bgp, struct peer *,
                                        struct bpacket_attr_vec_arr *vecarr,
                                        struct prefix *, afi_t, safi_t,
                                        struct peer *, struct prefix_rd *,
-                                       u_char *, int, u_int32_t);
+                                       mpls_label_t *, int, u_int32_t);
 extern void bgp_dump_routes_attr (struct stream *, struct attr *,
                                   struct prefix *);
 extern int attrhash_cmp (const void *, const void *);
@@ -303,7 +307,7 @@ extern size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer,
                                      struct attr *attr);
 extern void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
                                     struct prefix *p, struct prefix_rd *prd,
-                                    u_char *tag, int addpath_encode,
+                                    mpls_label_t *label, int addpath_encode,
                                      u_int32_t addpath_tx_id,
                                      struct attr *);
 extern size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
@@ -314,7 +318,7 @@ extern size_t bgp_packet_mpunreach_start (struct stream *s, afi_t afi,
                                          safi_t safi);
 extern void bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p,
                             afi_t afi, safi_t safi, struct prefix_rd *prd,
-                            u_char *tag, int, u_int32_t, struct attr *);
+                            mpls_label_t *, int, u_int32_t, struct attr *);
 extern void bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt);
 
 static inline int
index c5a0ef8893808a312bb3e3bac2dfcda881c4fdf4..d516f1718baf62edd65f5047611b6772c5977660 100644 (file)
@@ -33,6 +33,7 @@
 #include "bgpd/bgp_route.h"
 #include "bgpd/bgp_attr.h"
 #include "bgpd/bgp_mplsvpn.h"
+#include "bgpd/bgp_label.h"
 #include "bgpd/bgp_evpn.h"
 
 int
@@ -46,7 +47,7 @@ bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
        struct evpn_addr *p_evpn_p;
        struct bgp_route_evpn evpn;
        uint8_t route_type, route_length;
-       u_char *pnt_label;
+       mpls_label_t label;
        u_int32_t addpath_id = 0;
 
        /* Check peer status. */
@@ -146,22 +147,23 @@ bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
                }
 
                /* Fetch Label */
-               if (pnt + 3 > lim) {
+               if (pnt + BGP_LABEL_BYTES > lim) {
                        zlog_err("not enough bytes for Label left in NLRI?");
                        return -1;
                }
-               pnt_label = pnt;
 
-               pnt += 3;
+                memcpy(&label, pnt, BGP_LABEL_BYTES);
+                bgp_set_valid_label(&label);
+               pnt += BGP_LABEL_BYTES;
 
                if (!withdraw) {
                        bgp_update(peer, &p, addpath_id, attr, AFI_L2VPN,
                                   SAFI_EVPN, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
-                                  &prd, pnt_label, 0, &evpn);
+                                  &prd, &label, 0, &evpn);
                } else {
                        bgp_withdraw(peer, &p, addpath_id, attr, AFI_L2VPN,
                                     SAFI_EVPN, ZEBRA_ROUTE_BGP,
-                                    BGP_ROUTE_NORMAL, &prd, pnt_label, &evpn);
+                                    BGP_ROUTE_NORMAL, &prd, &label, &evpn);
                }
        }
 
@@ -174,7 +176,7 @@ bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
 void
 bgp_packet_mpattr_route_type_5(struct stream *s,
                               struct prefix *p, struct prefix_rd *prd,
-                              u_char * label, struct attr *attr)
+                              mpls_label_t *label, struct attr *attr)
 {
        int len;
        char temp[16];
index 95d428015075d5bcf30cfafcc87ed6394544ca49..feabc9cd276319f974e003b26c4d53f3f81bcf57 100644 (file)
@@ -27,7 +27,7 @@ extern int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
 extern void
 bgp_packet_mpattr_route_type_5(struct stream *s,
                               struct prefix *p, struct prefix_rd *prd,
-                              u_char * label, struct attr *attr);
+                              mpls_label_t *label, struct attr *attr);
 /* EVPN route types as per RFC7432 and
  * as per draft-ietf-bess-evpn-prefix-advertisement-02
  */
index 0798515ebbe2a95ca90f6929e107f02b6b109a0b..adeaa7f3bdac44b4dcd2d991e67f97809cba0adc 100644 (file)
@@ -63,7 +63,7 @@ bgp_parse_fec_update (void)
 
   /* hack for the bgp instance & SAFI = have to send/receive it */
   afi = family2afi(p.family);
-  safi = SAFI_LABELED_UNICAST;
+  safi = SAFI_UNICAST;
   bgp = bgp_get_default();
   if (!bgp)
     {
@@ -74,7 +74,7 @@ bgp_parse_fec_update (void)
   table = bgp->rib[afi][safi];
   if (!table)
     {
-      zlog_debug("no %u labeled-unicast table", p.family);
+      zlog_debug("no %u unicast table", p.family);
       return -1;
     }
   rn = bgp_node_lookup(table, &p);
@@ -86,11 +86,11 @@ bgp_parse_fec_update (void)
 
   /* treat it as implicit withdraw - the label is invalid */
   if (label == MPLS_INVALID_LABEL)
-    bgp_unset_valid_label(rn->local_label);
+    bgp_unset_valid_label(&rn->local_label);
   else
     {
-      label_ntop(label, 1, rn->local_label);
-      bgp_set_valid_label(rn->local_label);
+      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);
@@ -98,18 +98,18 @@ bgp_parse_fec_update (void)
   return 1;
 }
 
-u_char *
+mpls_label_t
 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;
+  mpls_label_t remote_label;
   int reflect;
 
   if (!rn || !ri || !to)
-    return NULL;
+    return MPLS_INVALID_LABEL;
 
-  remote_label = ri->extra ? ri->extra->tag : NULL;
+  remote_label = ri->extra ? ri->extra->label : MPLS_INVALID_LABEL;
   from = ri->peer;
   reflect = ((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP));
 
@@ -172,22 +172,34 @@ bgp_reg_dereg_for_label (struct bgp_node *rn, struct bgp_info *ri,
 }
 
 static int
-bgp_nlri_get_labels (struct peer *peer, u_char *pnt, u_char plen,
-                      u_char label[])
+bgp_nlri_get_labels (struct peer *peer, u_char *pnt, u_char plen, mpls_label_t *label)
 {
   u_char *data = pnt;
   u_char *lim = pnt + plen;
   u_char llen = 0;
+  u_char label_index = 0;
 
   for (; data < lim; data += BGP_LABEL_BYTES)
     {
       memcpy(label, data, BGP_LABEL_BYTES);
-      llen += 3;
+      llen += BGP_LABEL_BYTES;
+
+      bgp_set_valid_label(label);
+
       if (bgp_is_withdraw_label(label) || label_bos(label))
         break;
+
+      label_index += 1;
     }
+
+  /* If we RX multiple labels we will end up keeping only the last
+   * one. We do not yet support a label stack greater than 1. */
+  if (label_index > 1)
+      zlog_warn("%s rcvd UPDATE with label stack %d deep",
+                peer->host, label_index);
+
   if (!(bgp_is_withdraw_label(label) || label_bos(label)))
-      zlog_warn("%s: [Update:RCVD] invalid label - no bottom of stack",
+      zlog_warn("%s rcvd UPDATE with invalid label stack - no bottom of stack",
                 peer->host);
 
   return llen;
@@ -206,7 +218,7 @@ bgp_nlri_parse_label (struct peer *peer, struct attr *attr,
   safi_t safi;
   int addpath_encoded;
   u_int32_t addpath_id;
-  u_char label[3];
+  mpls_label_t label = MPLS_INVALID_LABEL;
   u_char llen;
 
   /* Check peer status. */
@@ -254,8 +266,7 @@ bgp_nlri_parse_label (struct peer *peer, struct attr *attr,
         }
 
       /* 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);
+      llen = bgp_nlri_get_labels(peer, pnt, psize, &label);
       p.prefixlen = prefixlen - BSIZE(llen);
 
       /* There needs to be at least one label */
@@ -319,13 +330,13 @@ bgp_nlri_parse_label (struct peer *peer, struct attr *attr,
 
       if (attr)
         {
-          bgp_update (peer, &p, addpath_id, attr, packet->afi, SAFI_LABELED_UNICAST,
-                      ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, label, 0, NULL);
+          bgp_update (peer, &p, addpath_id, attr, packet->afi, SAFI_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);
+          bgp_withdraw (peer, &p, addpath_id, attr, packet->afi, SAFI_UNICAST,
+                        ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, &label, NULL);
         }
     }
 
index dbc675dd43b782addfeaa4af062735bc3d280990..796df6652bd3b96049e3e8ac0fc3a9e6c0e5b543 100644 (file)
@@ -32,8 +32,8 @@ struct peer;
 extern void bgp_reg_dereg_for_label (struct bgp_node *rn, struct bgp_info *ri,
                                      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 mpls_label_t 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);
@@ -48,38 +48,35 @@ bgp_labeled_safi (safi_t safi)
 }
 
 static inline int
-bgp_is_withdraw_label (u_char *pkt)
+bgp_is_withdraw_label (mpls_label_t *label)
 {
+  u_char *pkt = (u_char *) label;
   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)
+bgp_is_valid_label (mpls_label_t *label)
 {
+  u_char *t= (u_char *) label;
   if (!t)
     return 0;
   return (t[2] & 0x02);
 }
 
 static inline void
-bgp_set_valid_label (u_char *t)
+bgp_set_valid_label (mpls_label_t *label)
 {
+  u_char *t= (u_char *) label;
   if (t)
     t[2] |= 0x02;
 }
 
 static inline void
-bgp_unset_valid_label (u_char *t)
+bgp_unset_valid_label (mpls_label_t *label)
 {
+  u_char *t= (u_char *) label;
   if (t)
     t[2] &= ~0x02;
 }
@@ -98,16 +95,18 @@ bgp_unregister_for_label (struct bgp_node *rn)
 
 /* Label stream to value */
 static inline u_int32_t
-label_pton (u_char t[])
+label_pton (mpls_label_t *label)
 {
+  u_char *t= (u_char *) label;
   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[])
+label_ntop (u_int32_t l, int bos, mpls_label_t *label)
 {
+  u_char *t= (u_char *) label;
   t[0] = ((l & 0x000FF000) >> 12);
   t[1] = ((l & 0x00000FF0) >> 4);
   t[2] = ((l & 0x0000000F) << 4);
@@ -117,8 +116,9 @@ label_ntop (u_int32_t l, int bos, u_char t[])
 
 /* Return BOS value of label stream */
 static inline u_char
-label_bos (u_char t[])
+label_bos (mpls_label_t *label)
 {
+  u_char *t= (u_char *) label;
   return (t[2] & 0x01);
 };
 
index 73c0389b1179c0b913942e22482bdcf648c87a15..551614aefbb86ace325b49eaf9df8f84a95aa501 100644 (file)
 #include "stream.h"
 #include "queue.h"
 #include "filter.h"
-
 #include "lib/json.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_mplsvpn.h"
 #include "bgpd/bgp_packet.h"
 #include "bgpd/bgp_vty.h"
@@ -87,9 +88,10 @@ encode_rd_type (u_int16_t v, u_char *pnt)
 }
 
 u_int32_t
-decode_label (u_char *pnt)
+decode_label (mpls_label_t *label_pnt)
 {
   u_int32_t l;
+  u_char *pnt = (u_char *) label_pnt;
 
   l = ((u_int32_t) *pnt++ << 12);
   l |= (u_int32_t) *pnt++ << 4;
@@ -98,9 +100,10 @@ decode_label (u_char *pnt)
 }
 
 void
-encode_label(u_int32_t label,
-             u_char *pnt)
+encode_label(mpls_label_t label,
+             mpls_label_t *label_pnt)
 {
+    u_char *pnt = (u_char *) label_pnt;
     if (pnt == NULL)
         return;
     *pnt++ = (label>>12) & 0xff;
@@ -169,7 +172,7 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
   struct rd_as rd_as;
   struct rd_ip rd_ip;
   struct prefix_rd prd;
-  u_char *tagpnt;
+  mpls_label_t label;
   afi_t afi;
   safi_t safi;
   int addpath_encoded;
@@ -249,14 +252,15 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
           return -1;
         }
       
-      /* Copyr label to prefix. */
-      tagpnt = pnt;
+      /* Copy label to prefix. */
+      memcpy(&label, pnt, BGP_LABEL_BYTES);
+      bgp_set_valid_label(&label);
 
       /* Copy routing distinguisher to rd. */
-      memcpy (&prd.val, pnt + 3, 8);
+      memcpy (&prd.val, pnt + BGP_LABEL_BYTES, 8);
 
       /* Decode RD type. */
-      type = decode_rd_type (pnt + 3);
+      type = decode_rd_type (pnt + BGP_LABEL_BYTES);
 
       switch (type)
         {
@@ -289,12 +293,12 @@ bgp_nlri_parse_vpn (struct peer *peer, struct attr *attr,
       if (attr)
         {
           bgp_update (peer, &p, addpath_id, attr, packet->afi, SAFI_MPLS_VPN,
-                      ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, 0, NULL);
+                      ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, &label, 0, NULL);
         }
       else
         {
           bgp_withdraw (peer, &p, addpath_id, attr, packet->afi, SAFI_MPLS_VPN,
-                        ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, tagpnt, NULL);
+                        ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, &label, NULL);
         }
     }
   /* Packet length consistency check. */
index faae041e07ba094026b013c6f11e333d4663f6c3..fba68b368a500e756ad8642fc40deb729b1c4f45 100644 (file)
@@ -94,8 +94,8 @@ extern u_int16_t decode_rd_type (u_char *);
 extern void encode_rd_type (u_int16_t, u_char *);
 extern void bgp_mplsvpn_init (void);
 extern int bgp_nlri_parse_vpn (struct peer *, struct attr *, struct bgp_nlri *);
-extern u_int32_t decode_label (u_char *);
-extern void encode_label(u_int32_t, u_char *);
+extern u_int32_t decode_label (mpls_label_t *);
+extern void encode_label(mpls_label_t, mpls_label_t *);
 extern void decode_rd_as (u_char *, struct rd_as *);
 extern void decode_rd_as4 (u_char *, struct rd_as *);
 extern void decode_rd_ip (u_char *, struct rd_ip *);
index da6bf5c3cb178f36cc6a67c59e7ca53d9de8a06d..d81f03c8b5a82e31a149775b777a195f7e211926 100644 (file)
@@ -1391,6 +1391,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size)
   memset (&attr, 0, sizeof (struct attr));
   memset (&extra, 0, sizeof (struct attr_extra));
   extra.label_index = BGP_INVALID_LABEL_INDEX;
+  extra.label = MPLS_INVALID_LABEL;
   memset (&nlris, 0, sizeof (nlris));
   attr.extra = &extra;
   memset (peer->rcvd_attr_str, 0, BUFSIZ);
index 31c1dd8c101d0fa82574bc2061d94eeac7e9e465..15367ec7c73a208ce23abbff90df6215aa9cef09 100644 (file)
@@ -35,7 +35,6 @@
 #include "thread.h"
 #include "workqueue.h"
 #include "queue.h"
-#include "mpls.h"
 #include "memory.h"
 #include "lib/json.h"
 
@@ -117,6 +116,7 @@ bgp_info_extra_new (void)
 {
   struct bgp_info_extra *new;
   new = XCALLOC (MTYPE_BGP_ROUTE_EXTRA, sizeof (struct bgp_info_extra));
+  new->label = MPLS_INVALID_LABEL;
   return new;
 }
 
@@ -694,7 +694,17 @@ bgp_info_cmp (struct bgp *bgp, struct bgp_info *new, struct bgp_info *exist,
   /* 11. Maximum path check. */
   if (newm == existm)
     {
-      if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX))
+      /* If one path has a label but the other does not, do not treat
+       * them as equals for multipath
+       */
+      if ((new->extra && bgp_is_valid_label(&new->extra->label)) !=
+          (exist->extra && bgp_is_valid_label(&exist->extra->label)))
+        {
+          if (debug)
+            zlog_debug("%s: %s and %s cannot be multipath, one has a label while the other does not",
+                       pfx_buf, new_buf, exist_buf);
+        }
+      else if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX))
         {
 
          /*
@@ -1271,14 +1281,14 @@ subgroup_announce_check (struct bgp_node *rn, struct bgp_info *ri,
   /* 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))
+      mpls_label_t label = bgp_adv_label(rn, ri, peer, afi, safi);
+      if (!bgp_is_valid_label(&label))
         {
           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);
+                 p->prefixlen, &label);
           return 0;
         }
     }
@@ -1940,7 +1950,7 @@ bgp_process_main (struct work_queue *wq, void *data)
    * 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)
+  if (safi == SAFI_UNICAST)
     {
       bgp_table_lock (bgp_node_table (rn));
       if (new_select)
@@ -1955,8 +1965,8 @@ bgp_process_main (struct work_queue *wq, void *data)
                 {
                   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);
+                  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);
@@ -1997,6 +2007,10 @@ bgp_process_main (struct work_queue *wq, void *data)
         {
           group_announce_route(bgp, afi, safi, rn, new_select);
 
+          /* unicast routes must also be annouced to labeled-unicast update-groups */
+          if (safi == SAFI_UNICAST)
+            group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn, new_select);
+
           UNSET_FLAG (old_select->flags, BGP_INFO_ATTR_CHANGED);
           UNSET_FLAG (rn->flags, BGP_NODE_LABEL_CHANGED);
          }
@@ -2049,6 +2063,10 @@ bgp_process_main (struct work_queue *wq, void *data)
 
   group_announce_route(bgp, afi, safi, rn, new_select);
 
+  /* unicast routes must also be annouced to labeled-unicast update-groups */
+  if (safi == SAFI_UNICAST)
+    group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, rn, new_select);
+
   /* FIB update. */
   if (bgp_fibupd_safi(safi) &&
       (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) &&
@@ -2464,7 +2482,7 @@ bgp_update_martian_nexthop (struct bgp *bgp, afi_t afi, safi_t safi, struct attr
 int
 bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
             struct attr *attr, afi_t afi, safi_t safi, int type,
-            int sub_type, struct prefix_rd *prd, u_char *tag,
+            int sub_type, struct prefix_rd *prd, mpls_label_t *label,
             int soft_reconfig, struct bgp_route_evpn* evpn)
 {
   int ret;
@@ -2481,18 +2499,24 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
   char label_buf[20];
   int connected = 0;
   int do_loop_check = 1;
+  int has_valid_label = 0;
 #if ENABLE_BGP_VNC
   int vnc_implicit_withdraw = 0;
 #endif
 
   memset (&new_attr, 0, sizeof(struct attr));
   memset (&new_extra, 0, sizeof(struct attr_extra));
+  new_extra.label_index = BGP_INVALID_LABEL_INDEX;
+  new_extra.label = MPLS_INVALID_LABEL;
 
   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));
+
+  has_valid_label = bgp_is_valid_label(label);
+
+  if (has_valid_label)
+    sprintf (label_buf, "label %u", label_pton(label));
   
   /* When peer's soft reconfiguration enabled.  Record input packet in
      Adj-RIBs-In.  */
@@ -2592,8 +2616,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)
+          && (!has_valid_label ||
+              memcmp (&(bgp_info_extra_get (ri))->label, label, BGP_LABEL_BYTES) == 0)
           && (overlay_index_equal(afi, ri, evpn==NULL?NULL:&evpn->eth_s_id,
                                   evpn==NULL?NULL:&evpn->gw_ip)))
        {
@@ -2714,9 +2738,12 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
       bgp_attr_unintern (&ri->attr);
       ri->attr = attr_new;
 
-      /* Update MPLS tag.  */
-      if (bgp_labeled_safi(safi))
-        memcpy ((bgp_info_extra_get (ri))->tag, tag, 3);
+      /* Update MPLS label */
+      if (has_valid_label)
+        {
+          memcpy (&(bgp_info_extra_get (ri))->label, label, BGP_LABEL_BYTES);
+          bgp_set_valid_label(&(bgp_info_extra_get (ri))->label);
+        }
 
 #if ENABLE_BGP_VNC
       if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) 
@@ -2814,10 +2841,10 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
 #if ENABLE_BGP_VNC
   if (SAFI_MPLS_VPN == safi)
     {
-      uint32_t    label = decode_label(tag);
+      mpls_label_t label_decoded = decode_label(label);
 
       rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type, sub_type,
-        &label);
+        &label_decoded);
     }
   if (SAFI_ENCAP == safi)
     {
@@ -2846,9 +2873,12 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
   /* Make new BGP info. */
   new = info_make(type, sub_type, 0, peer, attr_new, rn);
 
-  /* Update MPLS tag. */
-  if (bgp_labeled_safi(safi))
-    memcpy ((bgp_info_extra_get (new))->tag, tag, 3);
+  /* Update MPLS label */
+  if (has_valid_label)
+    {
+      memcpy (&(bgp_info_extra_get (new))->label, label, BGP_LABEL_BYTES);
+      bgp_set_valid_label(&(bgp_info_extra_get (new))->label);
+    }
 
   /* Update Overlay Index */
   if(afi == AFI_L2VPN)
@@ -2928,10 +2958,10 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
 #if ENABLE_BGP_VNC
   if (SAFI_MPLS_VPN == safi)
     {
-      uint32_t    label = decode_label(tag);
+      mpls_label_t label_decoded = decode_label(label);
 
       rfapiProcessUpdate(peer, NULL, p, prd, attr, afi, safi, type, sub_type,
-        &label);
+        &label_decoded);
     }
   if (SAFI_ENCAP == safi)
     {
@@ -2981,7 +3011,7 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
 int
 bgp_withdraw (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
               struct attr *attr, afi_t afi, safi_t safi, int type, int sub_type,
-             struct prefix_rd *prd, u_char *tag, struct bgp_route_evpn *evpn)
+             struct prefix_rd *prd, mpls_label_t *label, struct bgp_route_evpn *evpn)
 {
   struct bgp *bgp;
   char pfx_buf[BGP_PRD_PATH_STRLEN];
@@ -3169,11 +3199,11 @@ bgp_soft_reconfig_table (struct peer *peer, afi_t afi, safi_t safi,
        if (ain->peer == peer)
          {
            struct bgp_info *ri = rn->info;
-           u_char *tag = (ri && ri->extra) ? ri->extra->tag : NULL;
+           mpls_label_t label = (ri && ri->extra) ? ri->extra->label : MPLS_INVALID_LABEL;
 
            ret = bgp_update (peer, &rn->p, ain->addpath_rx_id, ain->attr,
                               afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
-                             prd, tag, 1, NULL);
+                             prd, &label, 1, NULL);
 
            if (ret < 0)
              {
@@ -4021,7 +4051,7 @@ bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi,
  */
 static void
 bgp_static_withdraw_safi (struct bgp *bgp, struct prefix *p, afi_t afi,
-                          safi_t safi, struct prefix_rd *prd, u_char *tag)
+                          safi_t safi, struct prefix_rd *prd)
 {
   struct bgp_node *rn;
   struct bgp_info *ri;
@@ -4134,8 +4164,7 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix *p,
           /* Unintern original. */
           aspath_unintern (&attr.aspath);
           bgp_attr_extra_free (&attr);
-          bgp_static_withdraw_safi (bgp, p, afi, safi, &bgp_static->prd,
-                                    bgp_static->tag);
+          bgp_static_withdraw_safi (bgp, p, afi, safi, &bgp_static->prd);
           return;
         }
 
@@ -4204,9 +4233,9 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix *p,
                  rn);
   SET_FLAG (new->flags, BGP_INFO_VALID);
   new->extra = bgp_info_extra_new();
-  memcpy (new->extra->tag, bgp_static->tag, 3);
+  new->extra->label = bgp_static->label;
 #if ENABLE_BGP_VNC
-  label = decode_label (bgp_static->tag);
+  label = decode_label (bgp_static->label);
 #endif
 
   /* Aggregate address increment. */
@@ -4437,8 +4466,7 @@ bgp_static_delete (struct bgp *bgp)
                    bgp_static = rm->info;
                    bgp_static_withdraw_safi (bgp, &rm->p,
                                               AFI_IP, safi,
-                                              (struct prefix_rd *)&rn->p,
-                                              bgp_static->tag);
+                                              (struct prefix_rd *)&rn->p);
                    bgp_static_free (bgp_static);
                    rn->info = NULL;
                    bgp_unlock_node (rn);
@@ -4552,7 +4580,7 @@ bgp_static_set_safi (afi_t afi, safi_t safi, struct vty *vty, const char *ip_str
   struct bgp_node *rn;
   struct bgp_table *table;
   struct bgp_static *bgp_static;
-  u_char tag[3];
+  mpls_label_t label = MPLS_INVALID_LABEL;
   struct prefix gw_ip;
 
   /* validate ip prefix */
@@ -4580,13 +4608,10 @@ bgp_static_set_safi (afi_t afi, safi_t safi, struct vty *vty, const char *ip_str
   if (label_str)
     {
       unsigned long label_val;
-      VTY_GET_INTEGER_RANGE("Label/tag", label_val, label_str, 0, 16777215);
-      encode_label (label_val, tag);
-    }
-  else
-    {
-      memset (tag, 0, sizeof(tag)); /* empty, not even BoS */
+      VTY_GET_INTEGER_RANGE("Label", label_val, label_str, 0, 16777215);
+      encode_label (label_val, &label);
     }
+
   if (safi == SAFI_EVPN)
     {
       if( esi && str2esi (esi, NULL) == 0)
@@ -4639,7 +4664,7 @@ bgp_static_set_safi (afi_t afi, safi_t safi, struct vty *vty, const char *ip_str
       bgp_static->valid = 0;
       bgp_static->igpmetric = 0;
       bgp_static->igpnexthop.s_addr = 0;
-      memcpy(bgp_static->tag, tag, 3);
+      bgp_static->label = label;
       bgp_static->prd = prd;
 
       if (rmap_str)
@@ -4688,7 +4713,7 @@ bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty, const char *ip_st
   struct bgp_node *rn;
   struct bgp_table *table;
   struct bgp_static *bgp_static;
-  u_char tag[3];
+  mpls_label_t label = MPLS_INVALID_LABEL;
 
   /* Convert IP prefix string to struct prefix. */
   ret = str2prefix (ip_str, &p);
@@ -4714,12 +4739,8 @@ bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty, const char *ip_st
   if (label_str)
     {
       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 */
+      VTY_GET_INTEGER_RANGE("Label", label_val, label_str, 0, MPLS_LABEL_MAX);
+      encode_label (label_val, &label);
     }
 
   prn = bgp_node_get (bgp->route[afi][safi],
@@ -4734,7 +4755,7 @@ bgp_static_unset_safi(afi_t afi, safi_t safi, struct vty *vty, const char *ip_st
 
   if (rn)
     {
-      bgp_static_withdraw_safi (bgp, &p, afi, safi, &prd, tag);
+      bgp_static_withdraw_safi (bgp, &p, afi, safi, &prd);
 
       bgp_static = rn->info;
       bgp_static_free (bgp_static);
@@ -6658,7 +6679,7 @@ route_vty_out_tag (struct vty *vty, struct prefix *p,
 {
   json_object *json_out = NULL;
   struct attr *attr;
-  u_int32_t label = 0;
+  mpls_label_t label = MPLS_INVALID_LABEL;
 
   if (!binfo->extra)
     return;
@@ -6741,19 +6762,20 @@ route_vty_out_tag (struct vty *vty, struct prefix *p,
        }
     }
 
-  label = decode_label (binfo->extra->tag);
+  label = decode_label (&binfo->extra->label);
 
-  if (json)
+  // dwalton why is this called 'notag'?
+  if (bgp_is_valid_label(&label))
     {
-      if (label)
-        json_object_int_add(json_out, "notag", label);
-      json_object_array_add(json, json_out);
-    }
-  else
-    {
-      vty_out (vty, "notag/%d", label);
-
-      vty_out (vty, "%s", VTY_NEWLINE);
+      if (json)
+        {
+          json_object_int_add(json_out, "notag", label);
+          json_object_array_add(json, json_out);
+        }
+      else
+        {
+          vty_out (vty, "notag/%d%s", label, VTY_NEWLINE);
+        }
     }
 }  
 
@@ -7642,10 +7664,10 @@ 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);
 
-      /* Remove Label */
-      if (bgp_labeled_safi(safi) && binfo->extra)
+      /* Remote Label */
+      if (binfo->extra && bgp_is_valid_label(&binfo->extra->label))
         {
-          uint32_t label = label_pton(binfo->extra->tag);
+          mpls_label_t label = label_pton(&binfo->extra->label);
           if (json_paths)
             json_object_int_add(json_path, "remoteLabel", label);
           else
@@ -8124,12 +8146,21 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
   int no_advertise = 0;
   int local_as = 0;
   int first = 1;
+  int has_valid_label = 0;
+  uint32_t label = 0;
   json_object *json_adv_to = NULL;
 
   p = &rn->p;
+  has_valid_label = bgp_is_valid_label(&rn->local_label);
+
+  if (has_valid_label)
+    label = label_pton(&rn->local_label);
 
   if (json)
     {
+      if (has_valid_label)
+        json_object_int_add(json, "localLabel", label);
+
       json_object_string_add(json, "prefix", inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN));
       json_object_int_add(json, "prefixlen", p->prefixlen);
     }
@@ -8146,17 +8177,10 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
               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);
-            }
-        }
+      if (has_valid_label)
+        vty_out(vty, "Local label: %d%s", label, VTY_NEWLINE);
+      else if (bgp_labeled_safi(safi))
+        vty_out(vty, "Local label: not allocated%s", VTY_NEWLINE);
     }
 
   for (ri = rn->info; ri; ri = ri->next)
@@ -8438,17 +8462,13 @@ bgp_show_lcommunity_list (struct vty *vty, struct bgp *bgp, const char *lcom,
 
 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|labeled-unicast>]] large-community-list <(1-500)|WORD> [json]",
+       "show [ip] bgp [<view|vrf> WORD] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] large-community-list <(1-500)|WORD> [json]",
        SHOW_STR
        IP_STR
        BGP_STR
        BGP_INSTANCE_HELP_STR
-       "Address Family\n"
-       "Address Family\n"
-       "Address Family modifier\n"
-       "Address Family modifier\n"
-       "Address Family modifier\n"
-       "Address Family modifier\n"
+       BGP_AFI_HELP_STR
+       BGP_SAFI_HELP_STR
        "Display routes matching the large-community-list\n"
        "large-community-list number\n"
        "large-community-list name\n"
@@ -8484,17 +8504,13 @@ DEFUN (show_ip_bgp_large_community_list,
 }
 DEFUN (show_ip_bgp_large_community,
        show_ip_bgp_large_community_cmd,
-       "show [ip] bgp [<view|vrf> WORD] [<ipv4|ipv6> [<unicast|multicast|vpn|labeled-unicast>]] large-community [AA:BB:CC] [json]",
+       "show [ip] bgp [<view|vrf> WORD] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] large-community [AA:BB:CC] [json]",
        SHOW_STR
        IP_STR
        BGP_STR
        BGP_INSTANCE_HELP_STR
-       "Address Family\n"
-       "Address Family\n"
-       "Address Family modifier\n"
-       "Address Family modifier\n"
-       "Address Family modifier\n"
-       "Address Family modifier\n"
+       BGP_AFI_HELP_STR
+       BGP_SAFI_HELP_STR
        "Display routes matching the large-communities\n"
        "List of large-community numbers\n"
        JSON_STR)
@@ -9437,18 +9453,14 @@ bgp_peer_counts (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, u_c
 
 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|labeled-unicast>]] "
+       "show [ip] bgp [<view|vrf> WORD] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] "
        "neighbors <A.B.C.D|X:X::X:X|WORD> prefix-counts [json]",
        SHOW_STR
        IP_STR
        BGP_STR
        BGP_INSTANCE_HELP_STR
-       "Address Family\n"
-       "Address Family\n"
-       "Address Family modifier\n"
-       "Address Family modifier\n"
-       "Address Family modifier\n"
-       "Address Family modifier\n"
+       BGP_AFI_HELP_STR
+       BGP_SAFI_HELP_STR
        "Address Family modifier\n"
        "Detailed information on TCP and BGP neighbor connections\n"
        "Neighbor to display information about\n"
@@ -10638,7 +10650,7 @@ bgp_config_write_network_vpn (struct vty *vty, struct bgp *bgp,
   struct prefix *p;
   struct prefix_rd *prd;
   struct bgp_static *bgp_static;
-  u_int32_t label;
+  mpls_label_t label;
   char buf[SU_ADDRSTRLEN];
   char rdbuf[RD_ADDRSTRLEN];
   
@@ -10656,7 +10668,7 @@ bgp_config_write_network_vpn (struct vty *vty, struct bgp *bgp,
 
            /* "network" configuration display.  */
            prefix_rd2str (prd, rdbuf, RD_ADDRSTRLEN);
-           label = decode_label (bgp_static->tag);
+           label = decode_label (&bgp_static->label);
 
            vty_out (vty, "  network %s/%d rd %s",
                     inet_ntop (p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), 
@@ -10717,7 +10729,7 @@ bgp_config_write_network_evpn (struct vty *vty, struct bgp *bgp,
             prefix2str (p, buf, sizeof (buf)),
            vty_out (vty, " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s",
                     buf, rdbuf, p->u.prefix_evpn.eth_tag,
-                     decode_label (bgp_static->tag), esi, buf2 , macrouter);
+                     decode_label (&bgp_static->label), esi, buf2 , macrouter);
            vty_out (vty, "%s", VTY_NEWLINE);
             if (macrouter)
               XFREE (MTYPE_TMP, macrouter);
@@ -10911,8 +10923,10 @@ 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, &bgp_network_label_index_cmd);
+  install_element (BGP_IPV4_NODE, &bgp_network_label_index_route_map_cmd);
+  install_element (BGP_IPV4_NODE, &no_bgp_network_label_index_cmd);
+  install_element (BGP_IPV4_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);
@@ -10941,20 +10955,6 @@ bgp_route_init (void)
   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);
index 3d179e07bef17058db01ec7c567b7f2b411d687a..763553b5545fd3cc3c8935bec9ba09b801f9edeb 100644 (file)
@@ -74,7 +74,7 @@ struct bgp_info_extra
   u_int32_t igpmetric;
 
   /* MPLS label.  */
-  u_char tag[3];  
+  mpls_label_t label;
 
 #if ENABLE_BGP_VNC
   union {
@@ -207,7 +207,7 @@ struct bgp_static
   struct prefix_rd     prd;
 
   /* MPLS label.  */
-  u_char tag[3];
+  mpls_label_t label;
 
   /* EVPN */
   struct eth_segment_id *eth_s_id;
@@ -344,9 +344,9 @@ extern int bgp_static_unset_safi (afi_t afi, safi_t safi, struct vty *, const ch
 /* this is primarily for MPLS-VPN */
 extern int bgp_update (struct peer *, struct prefix *, u_int32_t, struct attr *,
                       afi_t, safi_t, int, int, struct prefix_rd *,
-                      u_char *, int, struct bgp_route_evpn *);
+                      mpls_label_t *, int, struct bgp_route_evpn *);
 extern int bgp_withdraw (struct peer *, struct prefix *, u_int32_t, struct attr *,
-                        afi_t, safi_t, int, int, struct prefix_rd *, u_char *, 
+                        afi_t, safi_t, int, int, struct prefix_rd *, mpls_label_t *,
                          struct bgp_route_evpn *);
 
 /* for bgp_nexthop and bgp_damp */
index cff270ebb95ed74997e4412679818bf3f3e68f54..3aa519d562af1ca156a57b0ee8be86d15d74a460 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef _QUAGGA_BGP_TABLE_H
 #define _QUAGGA_BGP_TABLE_H
 
+#include "mpls.h"
 #include "table.h"
 
 struct bgp_table
@@ -56,7 +57,7 @@ struct bgp_node
 
   struct bgp_node *prn;
 
-  u_char local_label[3];
+  mpls_label_t local_label;
 
   uint64_t version;
   u_char flags;
index c6a160632349dbc2d51b635e787473ac0974c0f0..80620a9084205655a61de528afd56d021202c3dd 100644 (file)
@@ -599,6 +599,9 @@ subgroup_announce_table (struct update_subgroup *subgrp,
   safi = SUBGRP_SAFI (subgrp);
   addpath_capable = bgp_addpath_encode_tx (peer, afi, safi);
 
+  if (safi == SAFI_LABELED_UNICAST)
+    safi = SAFI_UNICAST;
+
   if (!table)
     table = peer->bgp->rib[afi][safi];
 
index 51abc19bea973e8e8f75d98fa329f9d65b6782cb..1857d96833ecb642802f01678165cab4ea8c117d 100644 (file)
@@ -785,26 +785,26 @@ subgroup_update_packet (struct update_subgroup *subgrp)
       else
        {
          /* Encode the prefix in MP_REACH_NLRI attribute */
-         u_char *tag = NULL;
+         mpls_label_t label = MPLS_INVALID_LABEL;
 
          if (rn->prn)
            prd = (struct prefix_rd *) &rn->prn->p;
 
           if (safi == SAFI_LABELED_UNICAST)
-            tag = bgp_adv_label(rn, binfo, peer, afi, safi);
+            label = bgp_adv_label(rn, binfo, peer, afi, safi);
           else
             if (binfo && binfo->extra)
-              tag = binfo->extra->tag;
+              label = binfo->extra->label;
 
           if (bgp_labeled_safi(safi))
-            sprintf (label_buf, "label %u", label_pton(tag));
+            sprintf (label_buf, "label %u", label_pton(&label));
 
          if (stream_empty (snlri))
             mpattrlen_pos = bgp_packet_mpattr_start (snlri, peer, afi, safi,
                                                      &vecarr, adv->baa->attr);
 
           bgp_packet_mpattr_prefix (snlri, afi, safi, &rn->p, prd,
-                                    tag, addpath_encode, addpath_tx_id, adv->baa->attr);
+                                    &label, addpath_encode, addpath_tx_id, adv->baa->attr);
        }
 
       num_pfx++;
index f5f538de95ae7d9346dfcfb18de6d841f0fdbd1e..3c510f3779e4bc63a11144c023376fd659bd067a 100644 (file)
@@ -531,6 +531,9 @@ bgp_vty_return (struct vty *vty, int ret)
     case BGP_ERR_INVALID_FOR_DIRECT_PEER:
       str = "Operation not allowed on a directly connected neighbor";
       break;
+    case BGP_ERR_PEER_SAFI_CONFLICT:
+      str = "Cannot activate peer for both 'ipv4 unicast' and 'ipv4 labeled-unicast'";
+      break;
     }
   if (str)
     {
@@ -3317,10 +3320,7 @@ DEFUN (neighbor_activate,
     return CMD_WARNING;
 
   ret = peer_activate (peer, bgp_node_afi (vty), bgp_node_safi (vty));
-
-  if (ret)
-    return CMD_WARNING;
-  return CMD_SUCCESS;
+  return bgp_vty_return (vty, ret);
 }
 
 ALIAS_HIDDEN (neighbor_activate,
@@ -3348,10 +3348,7 @@ DEFUN (no_neighbor_activate,
     return CMD_WARNING;
 
   ret = peer_deactivate (peer, bgp_node_afi (vty), bgp_node_safi (vty));
-
-  if (ret)
-    return CMD_WARNING;
-  return CMD_SUCCESS;
+  return bgp_vty_return (vty, ret);
 }
 
 ALIAS_HIDDEN (no_neighbor_activate,
@@ -6499,7 +6496,7 @@ bgp_clear_prefix (struct vty *vty, const char *view_name, const char *ip_str,
 /* one clear bgp command to rule them all */
 DEFUN (clear_ip_bgp_all,
        clear_ip_bgp_all_cmd,
-       "clear [ip] bgp [<view|vrf> WORD] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> [<soft [<in|out>]|in [prefix-filter]|out>]",
+       "clear [ip] bgp [<view|vrf> WORD] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> [<soft [<in|out>]|in [prefix-filter]|out>]",
        CLEAR_STR
        IP_STR
        BGP_STR
@@ -6513,7 +6510,7 @@ DEFUN (clear_ip_bgp_all,
        "Clear all members of peer-group\n"
        "BGP peer-group name\n"
        BGP_AFI_HELP_STR
-       BGP_SAFI_HELP_STR
+       BGP_SAFI_WITH_LABEL_HELP_STR
        BGP_SOFT_STR
        BGP_SOFT_IN_STR
        BGP_SOFT_OUT_STR
@@ -6534,12 +6531,18 @@ DEFUN (clear_ip_bgp_all,
   /* clear [ip] bgp */
   if (argv_find (argv, argc, "ip", &idx))
     afi = AFI_IP;
+
   /* [<view|vrf> WORD] */
   if (argv_find (argv, argc, "view", &idx) || argv_find (argv, argc, "vrf", &idx))
     {
       vrf = argv[idx + 1]->arg;
       idx += 2;
     }
+
+  /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */
+  if (argv_find_and_parse_afi (argv, argc, &idx, &afi))
+    argv_find_and_parse_safi (argv, argc, &idx, &safi);
+
   /* <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> */
   if (argv_find (argv, argc, "*", &idx))
     {
@@ -6575,11 +6578,7 @@ DEFUN (clear_ip_bgp_all,
     {
       clr_sort = clear_external;
     }
-  /* ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] */
-  if (argv_find_and_parse_afi (argv, argc, &idx, &afi))
-    {
-      argv_find_and_parse_safi (argv, argc, &idx, &safi);
-    }
+
   /* [<soft [<in|out>]|in [prefix-filter]|out>] */
   if (argv_find (argv, argc, "soft", &idx))
     {
@@ -6952,6 +6951,22 @@ DEFUN (show_bgp_memory,
   return CMD_SUCCESS;
 }
 
+static int
+bgp_show_summary_afi_safi_peer (struct peer *peer, int afi, int safi)
+{
+  if (peer->afc[afi][safi])
+    return 1;
+
+  /* The peer is doing 'ipv4 labeled-unicast' but we put those routes in
+   * the 'ipv4 unicast' table so return True for SAFI_UNICAST if they are
+   * doing SAFI_LABELED_UNICAST
+   */
+  if (safi == SAFI_UNICAST && peer->afc[afi][SAFI_LABELED_UNICAST])
+    return 1;
+
+  return 0;
+}
+
 /* Show BGP peer's summary information. */
 static int
 bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi,
@@ -6985,7 +7000,7 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi,
           if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
             continue;
 
-          if (peer->afc[afi][safi])
+          if (bgp_show_summary_afi_safi_peer (peer, afi, safi))
            {
              memset(dn_flag, '\0', sizeof(dn_flag));
              if (peer_dynamic_neighbor(peer))
@@ -7015,7 +7030,7 @@ bgp_show_summary (struct vty *vty, struct bgp *bgp, int afi, int safi,
       if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
        continue;
 
-      if (peer->afc[afi][safi])
+      if (bgp_show_summary_afi_safi_peer (peer, afi, safi))
        {
           if (!count)
             {
@@ -7319,6 +7334,13 @@ bgp_show_summary_afi_safi_peer_exists (struct bgp *bgp, int afi, int safi)
 
       if (peer->afc[afi][safi])
         return 1;
+
+      /* The peer is doing 'ipv4 labeled-unicast' but we put those routes in
+       * the 'ipv4 unicast' table so return True for SAFI_UNICAST if they are
+       * doing SAFI_LABELED_UNICAST
+       */
+      if (safi == SAFI_UNICAST && peer->afc[afi][SAFI_LABELED_UNICAST])
+        return 1;
     }
 
   return 0;
@@ -7344,6 +7366,16 @@ bgp_show_summary_afi_safi (struct vty *vty, struct bgp *bgp, int afi, int safi,
         safi = 1;                 /* SAFI_UNICAST */
       while (safi < SAFI_MAX)
         {
+
+          /* SAFI_LABELED_UNICAST routes are treated as SAFI_UNICAST
+           * so do not display a summary
+           */
+          if (safi == SAFI_LABELED_UNICAST)
+            {
+              safi++;
+              continue;
+            }
+
           if (bgp_show_summary_afi_safi_peer_exists (bgp, afi, safi))
             {
               json_output = true;
@@ -9610,13 +9642,13 @@ bgp_show_update_groups(struct vty *vty, const char *name,
 
 DEFUN (show_ip_bgp_updgrps,
        show_ip_bgp_updgrps_cmd,
-       "show [ip] bgp [<view|vrf> WORD] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] update-groups [SUBGROUP-ID]",
+       "show [ip] bgp [<view|vrf> WORD] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] update-groups [SUBGROUP-ID]",
        SHOW_STR
        IP_STR
        BGP_STR
        BGP_INSTANCE_HELP_STR
        BGP_AFI_HELP_STR
-       BGP_SAFI_HELP_STR
+       BGP_SAFI_WITH_LABEL_HELP_STR
        "Detailed info about dynamic update groups\n"
        "Specific subgroup to display detailed info for\n")
 {
@@ -11027,14 +11059,8 @@ bgp_vty_init (void)
   install_element (BGP_IPV6_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
   install_element (BGP_IPV6_NODE, &no_bgp_maxpaths_ibgp_cmd);
 
-  install_element (BGP_IPV4L_NODE, &bgp_maxpaths_cmd);
-  install_element (BGP_IPV4L_NODE, &no_bgp_maxpaths_cmd);
   install_element (BGP_IPV6L_NODE, &bgp_maxpaths_cmd);
   install_element (BGP_IPV6L_NODE, &no_bgp_maxpaths_cmd);
-
-  install_element (BGP_IPV4L_NODE, &bgp_maxpaths_ibgp_cmd);
-  install_element (BGP_IPV4L_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
-  install_element (BGP_IPV4L_NODE, &no_bgp_maxpaths_ibgp_cmd);
   install_element (BGP_IPV6L_NODE, &bgp_maxpaths_ibgp_cmd);
   install_element (BGP_IPV6L_NODE, &bgp_maxpaths_ibgp_cluster_cmd);
   install_element (BGP_IPV6L_NODE, &no_bgp_maxpaths_ibgp_cmd);
@@ -11191,7 +11217,6 @@ bgp_vty_init (void)
   install_element (BGP_NODE, &neighbor_set_peer_group_cmd);
   install_element (BGP_IPV4_NODE, &neighbor_set_peer_group_hidden_cmd);
   install_element (BGP_IPV4M_NODE, &neighbor_set_peer_group_hidden_cmd);
-  install_element (BGP_IPV4L_NODE, &neighbor_set_peer_group_hidden_cmd);
   install_element (BGP_IPV6_NODE, &neighbor_set_peer_group_hidden_cmd);
   install_element (BGP_IPV6M_NODE, &neighbor_set_peer_group_hidden_cmd);
   install_element (BGP_IPV6L_NODE, &neighbor_set_peer_group_hidden_cmd);
@@ -11202,7 +11227,6 @@ bgp_vty_init (void)
   install_element (BGP_NODE, &no_neighbor_set_peer_group_cmd);
   install_element (BGP_IPV4_NODE, &no_neighbor_set_peer_group_hidden_cmd);
   install_element (BGP_IPV4M_NODE, &no_neighbor_set_peer_group_hidden_cmd);
-  install_element (BGP_IPV4L_NODE, &no_neighbor_set_peer_group_hidden_cmd);
   install_element (BGP_IPV6_NODE, &no_neighbor_set_peer_group_hidden_cmd);
   install_element (BGP_IPV6M_NODE, &no_neighbor_set_peer_group_hidden_cmd);
   install_element (BGP_IPV6L_NODE, &no_neighbor_set_peer_group_hidden_cmd);
index 1bb9cfb7120c8391fd84b98162cd7bd0ddcec163..b3e6f73a6c048e0d909322f59cfdcc2d03b9c8da 100644 (file)
@@ -28,15 +28,21 @@ struct bgp;
 
 #define BGP_AFI_CMD_STR         "<ipv4|ipv6>"
 #define BGP_AFI_HELP_STR        "Address Family\nAddress Family\n"
-#define BGP_SAFI_CMD_STR        "<unicast|multicast|vpn|labeled-unicast>"
+#define BGP_SAFI_CMD_STR        "<unicast|multicast|vpn>"
 #define BGP_SAFI_HELP_STR       \
-  "Address Family modifier\n"   \
   "Address Family modifier\n"   \
   "Address Family modifier\n"   \
   "Address Family modifier\n"
 #define BGP_AFI_SAFI_CMD_STR    BGP_AFI_CMD_STR" "BGP_SAFI_CMD_STR
 #define BGP_AFI_SAFI_HELP_STR   BGP_AFI_HELP_STR BGP_SAFI_HELP_STR
 
+#define BGP_SAFI_WITH_LABEL_CMD_STR  "<unicast|multicast|vpn|labeled-unicast>"
+#define BGP_SAFI_WITH_LABEL_HELP_STR       \
+  "Address Family modifier\n"   \
+  "Address Family modifier\n"   \
+  "Address Family modifier\n"   \
+  "Address Family modifier\n"
+
 extern void bgp_vty_init (void);
 extern const char *afi_safi_print (afi_t, safi_t);
 extern const char *afi_safi_json (afi_t, safi_t);
index 4fff339b85a08e07ed197bd180b7c7077980a952..970318327938d064f003a6d68f4ef3b626f7750d 100644 (file)
@@ -1227,7 +1227,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
   struct bgp_info local_info;
   struct bgp_info *info_cp = &local_info;
   route_tag_t tag;
-  u_int32_t label;
+  mpls_label_t label;
 
   /* Don't try to install if we're not connected to Zebra or Zebra doesn't
    * know of this instance.
@@ -1278,6 +1278,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
       struct in_addr *nexthop;
       char buf[2][INET_ADDRSTRLEN];
       int valid_nh_count = 0;
+      int has_valid_label = 0;
 
       /* resize nexthop buffer size if necessary */
       if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
@@ -1297,7 +1298,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
       /* For labeled unicast, each nexthop has a label too. Resize label
        * buffer, if required.
        */
-      if (safi == SAFI_LABELED_UNICAST)
+      if (safi == SAFI_UNICAST)
         {
           if ((oldsize = stream_get_size (bgp_label_buf)) <
               (sizeof (unsigned int) * nhcount))
@@ -1342,9 +1343,10 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
         {
           stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
           valid_nh_count++;
-          if (safi == SAFI_LABELED_UNICAST)
+          if (info->extra && bgp_is_valid_label(&info->extra->label))
             {
-              label = label_pton(info->extra->tag);
+              has_valid_label = 1;
+              label = label_pton(&info->extra->label);
               stream_put (bgp_label_buf, &label, sizeof (u_int32_t));
             }
         }
@@ -1372,9 +1374,10 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
             continue;
 
           stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *));
-          if (safi == SAFI_LABELED_UNICAST)
+          if (mpinfo->extra && bgp_is_valid_label(&mpinfo->extra->label))
             {
-              label = label_pton(mpinfo->extra->tag);
+              has_valid_label = 1;
+              label = label_pton(&mpinfo->extra->label);
               stream_put (bgp_label_buf, &label, sizeof (u_int32_t));
             }
           valid_nh_count++;
@@ -1385,9 +1388,11 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
       api.type = ZEBRA_ROUTE_BGP;
       api.instance = 0;
       api.message = 0;
-      api.safi = (safi == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
+      assert (safi != SAFI_LABELED_UNICAST); // remove this assert after testing
+      api.safi = safi;
       SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
-      if (safi == SAFI_LABELED_UNICAST)
+
+      if (has_valid_label)
         SET_FLAG (api.message, ZAPI_MESSAGE_LABEL);
 
       /* Note that this currently only applies to Null0 routes for aggregates.
@@ -1401,7 +1406,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
         api.nexthop_num = valid_nh_count;
 
       api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf);
-      if (safi == SAFI_LABELED_UNICAST)
+      if (has_valid_label)
         {
           api.label_num = valid_nh_count;
           api.label = (unsigned int *)STREAM_DATA (bgp_label_buf);
@@ -1441,7 +1446,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
           for (i = 0; i < api.nexthop_num; i++)
             {
               label_buf[0] = '\0';
-              if (safi == SAFI_LABELED_UNICAST)
+              if (has_valid_label)
                 sprintf(label_buf, "label %u", api.label[i]);
               zlog_debug("  nhop [%d]: %s %s",
                          i+1,
@@ -1463,6 +1468,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
       struct zapi_ipv6 api;
       int valid_nh_count = 0;
            char buf[2][INET6_ADDRSTRLEN];
+      int has_valid_label = 0;
 
       /* resize nexthop buffer size if necessary */
       if ((oldsize = stream_get_size (bgp_nexthop_buf)) <
@@ -1495,7 +1501,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
       /* For labeled unicast, each nexthop has a label too. Resize label
        * buffer, if required.
        */
-      if (safi == SAFI_LABELED_UNICAST)
+      if (safi == SAFI_UNICAST)
         {
           if ((oldsize = stream_get_size (bgp_label_buf)) <
               (sizeof (unsigned int) * nhcount))
@@ -1556,9 +1562,11 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
            }
           stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
           stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
-          if (safi == SAFI_LABELED_UNICAST)
+
+          if (info->extra && bgp_is_valid_label(&info->extra->label))
             {
-              label = label_pton(info->extra->tag);
+              has_valid_label = 1;
+              label = label_pton(&info->extra->label);
               stream_put (bgp_label_buf, &label, sizeof (u_int32_t));
             }
           valid_nh_count++;
@@ -1603,9 +1611,11 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
 
           stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in6_addr *));
           stream_put (bgp_ifindices_buf, &ifindex, sizeof (unsigned int));
-          if (safi == SAFI_LABELED_UNICAST)
+
+          if (mpinfo->extra && bgp_is_valid_label(&mpinfo->extra->label))
             {
-              label = label_pton(mpinfo->extra->tag);
+              has_valid_label = 1;
+              label = label_pton(&mpinfo->extra->label);
               stream_put (bgp_label_buf, &label, sizeof (u_int32_t));
             }
           valid_nh_count++;
@@ -1617,9 +1627,11 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
       api.type = ZEBRA_ROUTE_BGP;
       api.instance = 0;
       api.message = 0;
-      api.safi = (safi == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
+      assert (safi != SAFI_LABELED_UNICAST); // remove this assert after testing
+      api.safi = safi;
       SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
-      if (safi == SAFI_LABELED_UNICAST)
+
+      if (has_valid_label)
         SET_FLAG (api.message, ZAPI_MESSAGE_LABEL);
 
       /* Note that this currently only applies to Null0 routes for aggregates.
@@ -1636,7 +1648,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
       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)
+      if (has_valid_label)
         {
           api.label_num = valid_nh_count;
           api.label = (unsigned int *)STREAM_DATA (bgp_label_buf);
@@ -1676,7 +1688,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
               for (i = 0; i < api.nexthop_num; i++)
                 {
                   label_buf[0] = '\0';
-                  if (safi == SAFI_LABELED_UNICAST)
+                  if (has_valid_label)
                     sprintf(label_buf, "label %u", api.label[i]);
                   zlog_debug("  nhop [%d]: %s if %s %s",
                              i+1,
@@ -1707,7 +1719,7 @@ bgp_zebra_announce (struct bgp_node *rn, struct prefix *p, struct bgp_info *info
               for (i = 0; i < api.nexthop_num; i++)
                 {
                   label_buf[0] = '\0';
-                  if (safi == SAFI_LABELED_UNICAST)
+                  if (has_valid_label)
                     sprintf(label_buf, "label %u", api.label[i]);
                   zlog_debug("  nhop [%d]: %s if %s %s",
                              i+1,
@@ -1793,10 +1805,9 @@ 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 == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
+      assert (safi != SAFI_LABELED_UNICAST); // remove this assert after testing
+      api.safi = 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;
@@ -1836,10 +1847,9 @@ 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 == SAFI_LABELED_UNICAST) ? SAFI_UNICAST : safi;
+      assert (safi != SAFI_LABELED_UNICAST); // remove this assert after testing
+      api.safi = 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;
index cf6c00ae52b3e9f7d038e804183a87ab2fc7647a..1160066e8940dbd2c04bc39c12806f2e21e3cd39 100644 (file)
@@ -1756,6 +1756,11 @@ non_peergroup_activate_af (struct peer *peer, afi_t afi, safi_t safi)
       return 1;
     }
 
+  /* Do not activate a peer for both SAFI_UNICAST and SAFI_LABELED_UNICAST */
+  if ((safi == SAFI_UNICAST && peer->afc[afi][SAFI_LABELED_UNICAST]) ||
+      (safi == SAFI_LABELED_UNICAST && peer->afc[afi][SAFI_UNICAST]))
+    return BGP_ERR_PEER_SAFI_CONFLICT;
+
   /* Nothing to do if we've already activated this peer */
   if (peer->afc[afi][safi])
     return 0;
@@ -1815,6 +1820,12 @@ peer_activate (struct peer *peer, afi_t afi, safi_t safi)
    * peer-group as well */
   if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     {
+
+      /* Do not activate a peer for both SAFI_UNICAST and SAFI_LABELED_UNICAST */
+      if ((safi == SAFI_UNICAST && peer->afc[afi][SAFI_LABELED_UNICAST]) ||
+          (safi == SAFI_LABELED_UNICAST && peer->afc[afi][SAFI_UNICAST]))
+        return BGP_ERR_PEER_SAFI_CONFLICT;
+
       peer->afc[afi][safi] = 1;
       group = peer->group;
 
index 84dcb7e1d966a651d4a28eac9a7916f4d6ad11f9..2e96f6cb9067f06bcc19c60b58d4325c4b6f47db 100644 (file)
@@ -1157,6 +1157,7 @@ enum bgp_clear_type
 #define BGP_ERR_INVALID_FOR_DYNAMIC_PEER        -32
 #define BGP_ERR_MAX                             -33
 #define BGP_ERR_INVALID_FOR_DIRECT_PEER         -34
+#define BGP_ERR_PEER_SAFI_CONFLICT              -35
 
 /*
  * Enumeration of different policy kinds a peer can be configured with.
index 6cf014275502ce34156a64e82b1fcac936915984..d78fcb1f577ea594cf369ffcaf1fe9d31a7c29b2 100644 (file)
@@ -76,8 +76,13 @@ typedef unsigned int mpls_lse_t;
 /* MPLS label value as a 32-bit (mostly we only care about the label value). */
 typedef unsigned int mpls_label_t;
 
-#define MPLS_NO_LABEL                      0xFFFFFFFF
-#define MPLS_INVALID_LABEL                 0xFFFFFFFF
+/* The MPLS explicit-null label is 0 which means when you memset a mpls_label_t
+ * to zero you have set that variable to explicit-null which was probably not
+ * your intent. The work-around is to use one bit to indicate if the
+ * mpls_label_t has been set by the user. MPLS_INVALID_LABEL has this bit clear
+ * so that we can use MPLS_INVALID_LABEL to initialize mpls_label_t variables.
+ */
+#define MPLS_INVALID_LABEL                 0xFFFDFFFF
 
 /* LSP types. */
 enum lsp_types_t
index e8320a8fa132875b287c0d87a5bbe73dce3e9319..6163a5b3ec195ac2071055fee65edfa8cfa59848 100644 (file)
@@ -920,9 +920,10 @@ stream_put_prefix (struct stream *s, struct prefix *p)
 
 /* Put NLRI with label */
 int
-stream_put_labeled_prefix (struct stream *s, struct prefix *p, u_char *label)
+stream_put_labeled_prefix (struct stream *s, struct prefix *p, mpls_label_t *label)
 {
   size_t psize;
+  u_char *label_pnt = (u_char *) label;
 
   STREAM_VERIFY_SANE(s);
 
@@ -935,9 +936,9 @@ stream_put_labeled_prefix (struct stream *s, struct prefix *p, u_char *label)
     }
 
   stream_putc (s, (p->prefixlen + 24));
-  stream_putc(s, label[0]);
-  stream_putc(s, label[1]);
-  stream_putc(s, label[2]);
+  stream_putc(s, label_pnt[0]);
+  stream_putc(s, label_pnt[1]);
+  stream_putc(s, label_pnt[2]);
   memcpy (s->data + s->endp, &p->u.prefix, psize);
   s->endp += psize;
 
index dd6aae677d85b50d0144611e128aa1fb6e2b55fd..c012cc4593d12e58b8af6512273f2212772c255e 100644 (file)
@@ -22,6 +22,7 @@
 #ifndef _ZEBRA_STREAM_H
 #define _ZEBRA_STREAM_H
 
+#include "mpls.h"
 #include "prefix.h"
 
 /*
@@ -181,7 +182,7 @@ extern int stream_put_prefix_addpath (struct stream *, struct prefix *,
                                       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 *);
+                                      mpls_label_t *);
 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 *);
index fb46184b6274ea4d30776b24e114fdbe9f32c3b8..fcf1a02ebda828a00bc2757a5aff3af205fde092 100644 (file)
@@ -1876,7 +1876,7 @@ zebra_mpls_lsp_uninstall (struct zebra_vrf *zvrf, struct route_node *rn, struct
  * Registration from a client for the label binding for a FEC. If a binding
  * already exists, it is informed to the client.
  * NOTE: If there is a manually configured label binding, that is used.
- * Otherwise, if aa label index is specified, it means we have to allocate the
+ * Otherwise, if a label index is specified, it means we have to allocate the
  * label from a locally configured label block (SRGB), if one exists and index
  * is acceptable.
  */
index ba42c67be39e7617640bc3090230d8626b231e5e..07d0d2f2c1cfb41b04e50fc30fb6a622a5780ad7 100644 (file)
@@ -989,6 +989,8 @@ zserv_fec_register (struct zserv *client, int sock, u_short length)
           label_index = stream_getl(s);
           l += 4;
         }
+      else
+        label_index = MPLS_INVALID_LABEL_INDEX;
       zebra_mpls_fec_register (zvrf, &p, label_index, client);
     }