]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Parse PMSI Tunnel Attribute and display
authorvivek <vivek@cumulusnetworks.com>
Sun, 4 Mar 2018 03:28:50 +0000 (03:28 +0000)
committervivek <vivek@cumulusnetworks.com>
Sun, 4 Mar 2018 03:28:50 +0000 (03:28 +0000)
Received PMSI tunnel attributes (in EVPN type-3 route) were not recognized.
Parse them and display the tunnel type when looking at routes. Note that
the only tunnel type currently supported is ingress replication (IR). A
warning message will be logged if the received tunnel type is something
else, but the attribute is otherwise ignored.

Updates: a21bd7a (bgpd: add PMSI_TUNNEL_ATTRIBUTE to EVPN IMET routes)
Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
bgpd/bgp_attr.c
bgpd/bgp_attr.h
bgpd/bgp_debug.c
bgpd/bgp_evpn.c
bgpd/bgp_route.c

index 3f3acbe0e2923db2638035a707dc494883508cb5..56303a3df5f4d8d2c1ed6596103af55b2c4526b0 100644 (file)
@@ -2114,6 +2114,51 @@ bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
        return BGP_ATTR_PARSE_PROCEED;
 }
 
+/* PMSI tunnel attribute (RFC 6514)
+ * Basic validation checks done here.
+ */
+static bgp_attr_parse_ret_t
+bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
+{
+       struct peer *const peer = args->peer;
+       struct attr *const attr = args->attr;
+       const bgp_size_t length = args->length;
+       u_int8_t tnl_type;
+
+       /* Verify that the receiver is expecting "ingress replication" as we
+        * can only support that.
+        */
+       if (length < 2) {
+               zlog_err("Bad PMSI tunnel attribute length %d", length);
+               return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                         args->total);
+       }
+       stream_getc(peer->curr); /* Flags */
+       tnl_type = stream_getc(peer->curr);
+       if (tnl_type > PMSI_TNLTYPE_MAX) {
+               zlog_err("Invalid PMSI tunnel attribute type %d", tnl_type);
+               return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+                                         args->total);
+       }
+       if (tnl_type == PMSI_TNLTYPE_INGR_REPL) {
+               if (length != 9) {
+                       zlog_err("Bad PMSI tunnel attribute length %d for IR",
+                                length);
+                       return bgp_attr_malformed(args,
+                                                 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                                 args->total);
+               }
+       }
+
+       attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
+       attr->pmsi_tnl_type = tnl_type;
+
+       /* Forward read pointer of input stream. */
+       stream_forward_getp(peer->curr, length - 2);
+
+       return BGP_ATTR_PARSE_PROCEED;
+}
+
 /* BGP unknown attribute treatment. */
 static bgp_attr_parse_ret_t bgp_attr_unknown(struct bgp_attr_parser_args *args)
 {
@@ -2447,6 +2492,9 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
                case BGP_ATTR_PREFIX_SID:
                        ret = bgp_attr_prefix_sid(&attr_args, mp_update);
                        break;
+               case BGP_ATTR_PMSI_TUNNEL:
+                       ret = bgp_attr_pmsi_tunnel(&attr_args);
+                       break;
                default:
                        ret = bgp_attr_unknown(&attr_args);
                        break;
@@ -3263,7 +3311,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
                stream_putc(s, BGP_ATTR_PMSI_TUNNEL);
                stream_putc(s, 9); // Length
                stream_putc(s, 0); // Flags
-               stream_putc(s, 6); // Tunnel type: Ingress Replication (6)
+               stream_putc(s, PMSI_TNLTYPE_INGR_REPL); // IR (6)
                stream_put(s, &(attr->label), BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI
                stream_put_ipv4(s, attr->nexthop.s_addr); // Unicast tunnel endpoint IP address
        }
index 1b1471a198974cdb7e4de38639225e1ba1a6bad4..c60fbd323d9ad420f3ed2b9a7076d385928b16ac 100644 (file)
@@ -66,6 +66,8 @@
 #define BGP_PREFIX_SID_IPV6_LENGTH            19
 #define BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH  6
 
+/* PMSI tunnel types (RFC 6514) */
+
 struct bgp_attr_encap_subtlv {
        struct bgp_attr_encap_subtlv *next; /* for chaining */
        /* Reference count of this attribute. */
@@ -96,6 +98,18 @@ struct overlay_index {
        union gw_addr gw_ip;
 };
 
+enum pta_type {
+       PMSI_TNLTYPE_NO_INFO,
+       PMSI_TNLTYPE_RSVP_TE_P2MP,
+       PMSI_TNLTYPE_MLDP_P2MP,
+       PMSI_TNLTYPE_PIM_SSM,
+       PMSI_TNLTYPE_PIM_SM,
+       PMSI_TNLTYPE_PIM_BIDIR,
+       PMSI_TNLTYPE_INGR_REPL,
+       PMSI_TNLTYPE_MLDP_MP2MP,
+       PMSI_TNLTYPE_MAX = PMSI_TNLTYPE_MLDP_MP2MP
+};
+
 /* BGP core attribute structure. */
 struct attr {
        /* AS Path structure */
@@ -119,6 +133,9 @@ struct attr {
        /* Path origin attribute */
        u_char origin;
 
+       /* PMSI tunnel type (RFC 6514). */
+       enum pta_type pmsi_tnl_type;
+
        /* has the route-map changed any attribute?
           Used on the peer outbound side. */
        u_int32_t rmap_change_flags;
index e89f399e418d0e424564f89c48fb6296ace4f428..1c9c92044c82a160598d66bd93b9f70817cf3449 100644 (file)
@@ -159,6 +159,9 @@ static const struct message bgp_notify_capability_msg[] = {
 /* Origin strings. */
 const char *bgp_origin_str[] = {"i", "e", "?"};
 const char *bgp_origin_long_str[] = {"IGP", "EGP", "incomplete"};
+const char *pmsi_tnltype_str[] = {"No info", "RSVP-TE P2MP", "mLDP P2MP",
+                                 "PIM-SSM", "PIM-SM", "PIM-BIDIR",
+                                 "Ingress Replication", "mLDP MP2MP"};
 
 
 /* Given a string return a pointer the corresponding peer structure */
@@ -415,6 +418,10 @@ int bgp_dump_attr(struct attr *attr, char *buf, size_t size)
                                 inet_ntoa(attr->cluster->list[i]));
        }
 
+       if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)))
+               snprintf(buf + strlen(buf), size - strlen(buf), ", pmsi tnltype %u",
+                        attr->pmsi_tnl_type);
+
        if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
                snprintf(buf + strlen(buf), size - strlen(buf), ", path %s",
                         aspath_print(attr->aspath));
index a8ee14c72e6a045ab82944c30d2e20d0eb1291f3..9e4a5172df341aa71cedd1f0d783f48c81504ee1 100644 (file)
@@ -2932,6 +2932,20 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi,
                return -1;
        }
 
+       /* If PMSI is present, log if it is anything other than IR.
+        * Note: We just simply ignore the values as it is not clear if
+        * doing anything else is better.
+        */
+       if (attr &&
+           (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL))) {
+               if (attr->pmsi_tnl_type != PMSI_TNLTYPE_INGR_REPL) {
+                       zlog_warn("%u:%s - Rx EVPN Type-3 NLRI with "
+                                 "unsupported PTA %d",
+                                 peer->bgp->vrf_id, peer->host,
+                                 attr->pmsi_tnl_type);
+               }
+       }
+
        /* Make prefix_rd */
        prd.family = AF_UNSPEC;
        prd.prefixlen = 64;
index 20bf9635a3e040c410038fdc2fd35917d3d54784..93570f4a3c67882eae8f66f5a9e658dfd754e906 100644 (file)
@@ -81,6 +81,7 @@
 /* Extern from bgp_dump.c */
 extern const char *bgp_origin_str[];
 extern const char *bgp_origin_long_str[];
+extern const char *pmsi_tnltype_str[];
 
 struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi,
                                  safi_t safi, struct prefix *p,
@@ -7035,6 +7036,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
        json_object *json_ext_community = NULL;
        json_object *json_lcommunity = NULL;
        json_object *json_last_update = NULL;
+       json_object *json_pmsi = NULL;
        json_object *json_nexthop_global = NULL;
        json_object *json_nexthop_ll = NULL;
        json_object *json_nexthops = NULL;
@@ -7787,6 +7789,21 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
                                               json_last_update);
                } else
                        vty_out(vty, "      Last update: %s", ctime(&tbuf));
+
+               /* Line 10 display PMSI tunnel attribute, if present */
+               if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
+                       if (json_paths) {
+                               json_pmsi = json_object_new_object();
+                               json_object_string_add(
+                                       json_pmsi, "tunnelType",
+                                       pmsi_tnltype_str[attr->pmsi_tnl_type]);
+                               json_object_object_add(json_path, "pmsi",
+                                                      json_pmsi);
+                       } else
+                               vty_out(vty, "      PMSI Tunnel Type: %s\n",
+                                       pmsi_tnltype_str[attr->pmsi_tnl_type]);
+               }
+
        }
 
        /* We've constructed the json object for this path, add it to the json