From 7fd077aadd54598f8764003d9b96fde1e30c2701 Mon Sep 17 00:00:00 2001 From: vivek Date: Sun, 4 Mar 2018 03:28:50 +0000 Subject: [PATCH 1/5] bgpd: Parse PMSI Tunnel Attribute and display 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 --- bgpd/bgp_attr.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++- bgpd/bgp_attr.h | 17 ++++++++++++++++ bgpd/bgp_debug.c | 7 +++++++ bgpd/bgp_evpn.c | 14 ++++++++++++++ bgpd/bgp_route.c | 17 ++++++++++++++++ 5 files changed, 104 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 3f3acbe0e292..56303a3df5f4 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -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 } diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 1b1471a19897..c60fbd323d9a 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -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; diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index e89f399e418d..1c9c92044c82 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -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)); diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index a8ee14c72e6a..9e4a5172df34 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -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; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 20bf9635a3e0..93570f4a3c67 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -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 From 052ea98b431598466e939575df2992b483524587 Mon Sep 17 00:00:00 2001 From: vivek Date: Sun, 4 Mar 2018 06:56:19 +0000 Subject: [PATCH 2/5] bgpd: Fix warnings Signed-off-by: Vivek Venkatraman --- bgpd/bgp_attr.c | 8 ++++---- bgpd/bgp_debug.c | 4 ++-- bgpd/bgp_debug.h | 1 + bgpd/bgp_route.c | 1 - 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 56303a3df5f4..73256046f628 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -2143,10 +2143,10 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args) 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); + length); + return bgp_attr_malformed( + args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); } } diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index 1c9c92044c82..8b308c8f3eab 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -419,8 +419,8 @@ int bgp_dump_attr(struct attr *attr, char *buf, size_t size) } 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); + 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", diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h index 765e43f5b433..10a1e3159ffa 100644 --- a/bgpd/bgp_debug.h +++ b/bgpd/bgp_debug.h @@ -136,6 +136,7 @@ struct bgp_debug_filter { #define CONF_BGP_DEBUG(a, b) (conf_bgp_debug_ ## a & BGP_DEBUG_ ## b) extern const char *bgp_type_str[]; +extern const char *pmsi_tnltype_str[]; extern int bgp_dump_attr(struct attr *, char *, size_t); extern int bgp_debug_peer_updout_enabled(char *host); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 93570f4a3c67..d9d82800271f 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -81,7 +81,6 @@ /* 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, From d0be47e8e152e82270770bdb77aea620ea9b3ab2 Mon Sep 17 00:00:00 2001 From: vivek Date: Tue, 6 Mar 2018 21:29:09 +0000 Subject: [PATCH 3/5] bgpd: Fix warning Signed-off-by: Vivek Venkatraman --- bgpd/bgp_evpn.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 9e4a5172df34..7122f2a09528 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -2939,8 +2939,7 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi, 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", + zlog_warn("%u:%s - Rx EVPN Type-3 NLRI with unsupported PTA %d", peer->bgp->vrf_id, peer->host, attr->pmsi_tnl_type); } From b7d08f5ab50dffae02feb146dde3a5e752c6b3ff Mon Sep 17 00:00:00 2001 From: vivek Date: Tue, 13 Mar 2018 18:14:26 +0000 Subject: [PATCH 4/5] bgpd: Fix enum, use API for log string Suggested-by: Philippe Guibert Signed-off-by: Vivek Venkatraman --- bgpd/bgp_attr.h | 2 +- bgpd/bgp_debug.c | 4 ---- bgpd/bgp_route.c | 25 +++++++++++++++++++++---- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 5bf237755873..5403f325431e 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -99,7 +99,7 @@ struct overlay_index { }; enum pta_type { - PMSI_TNLTYPE_NO_INFO, + PMSI_TNLTYPE_NO_INFO = 0, PMSI_TNLTYPE_RSVP_TE_P2MP, PMSI_TNLTYPE_MLDP_P2MP, PMSI_TNLTYPE_PIM_SSM, diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index 8b308c8f3eab..2580d2e5a55a 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -159,10 +159,6 @@ 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 */ static struct peer *bgp_find_peer(struct vty *vty, const char *peer_str) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 88e93f5710e2..de693a219c3b 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -82,6 +82,20 @@ extern const char *bgp_origin_str[]; extern const char *bgp_origin_long_str[]; +/* PMSI strings. */ +#define PMSI_TNLTYPE_STR_NO_INFO "No info" +#define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO +static const struct message bgp_pmsi_tnltype_str[] = { + {PMSI_TNLTYPE_NO_INFO, PMSI_TNLTYPE_STR_NO_INFO}, + {PMSI_TNLTYPE_RSVP_TE_P2MP, "RSVP-TE P2MP"}, + {PMSI_TNLTYPE_MLDP_P2MP, "mLDP P2MP"}, + {PMSI_TNLTYPE_PIM_SSM, "PIM-SSM"}, + {PMSI_TNLTYPE_PIM_SM, "PIM-SM"}, + {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"}, + {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"}, + {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"}, + {0}}; + struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi, safi_t safi, struct prefix *p, struct prefix_rd *prd) @@ -7791,16 +7805,19 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, /* Line 10 display PMSI tunnel attribute, if present */ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) { + const char *str = lookup_msg(bgp_pmsi_tnltype_str, + attr->pmsi_tnl_type, + PMSI_TNLTYPE_STR_DEFAULT); + 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_string_add(json_pmsi, + "tunnelType", str); 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]); + str); } } From 88fbc36fcb74f5cc3d009802b6aac537916164d1 Mon Sep 17 00:00:00 2001 From: vivek Date: Tue, 13 Mar 2018 19:42:41 +0000 Subject: [PATCH 5/5] bgpd: Fix warning Signed-off-by: Vivek Venkatraman --- bgpd/bgp_route.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index de693a219c3b..fd0c87c8ca7f 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -94,7 +94,8 @@ static const struct message bgp_pmsi_tnltype_str[] = { {PMSI_TNLTYPE_PIM_BIDIR, "PIM-BIDIR"}, {PMSI_TNLTYPE_INGR_REPL, "Ingress Replication"}, {PMSI_TNLTYPE_MLDP_MP2MP, "mLDP MP2MP"}, - {0}}; + {0} +}; struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi, safi_t safi, struct prefix *p,