From fd563cc7f35e598decdbfd6a58bae2f050143b3f Mon Sep 17 00:00:00 2001 From: Karen Schoener Date: Thu, 28 May 2020 16:36:35 -0400 Subject: [PATCH] ldpd: Relay data plane pseudowire status in LDP notification Provide a way for the data plane to indicate pseudowire status (such as: not forwarding, AC failure). On a data plane pseudowire install failure, data plane sets the pseudowire status. Zebra relays the pseudowire status to LDP. LDP includes the pseudowire status in the LDP notification to the LDP peer. Signed-off-by: Karen Schoener --- ldpd/l2vpn.c | 7 ++++--- ldpd/ldp.h | 7 ------- ldpd/ldp_vty_exec.c | 4 ++-- ldpd/ldp_zebra.c | 5 +++-- ldpd/notification.c | 2 +- lib/pw.h | 10 +++++++--- lib/zclient.h | 1 + zebra/zebra_dplane.c | 18 ++++++++++++++++++ zebra/zebra_dplane.h | 3 ++- zebra/zebra_pw.c | 27 ++++++++++++++------------- zebra/zebra_pw.h | 2 +- zebra/zebra_rib.c | 3 ++- 12 files changed, 55 insertions(+), 34 deletions(-) diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c index 4a944fa019..0d479e77ba 100644 --- a/ldpd/l2vpn.c +++ b/ldpd/l2vpn.c @@ -521,11 +521,11 @@ l2vpn_pw_status_update(struct zapi_pw_status *zpw) return (1); } - if (zpw->status == PW_STATUS_UP) { + if (zpw->status == PW_FORWARDING) { local_status = PW_FORWARDING; pw->reason = F_PW_NO_ERR; } else { - local_status = PW_NOT_FORWARDING; + local_status = zpw->status; pw->reason = F_PW_LOCAL_NOT_FWD; } @@ -571,10 +571,11 @@ l2vpn_pw_ctl(pid_t pid) sizeof(pwctl.ifname)); pwctl.pwid = pw->pwid; pwctl.lsr_id = pw->lsr_id; + pwctl.status = PW_NOT_FORWARDING; if (pw->enabled && pw->local_status == PW_FORWARDING && pw->remote_status == PW_FORWARDING) - pwctl.status = 1; + pwctl.status = PW_FORWARDING; lde_imsg_compose_ldpe(IMSG_CTL_SHOW_L2VPN_PW, 0, pid, &pwctl, sizeof(pwctl)); diff --git a/ldpd/ldp.h b/ldpd/ldp.h index cac3da7c55..5d1bf81ec7 100644 --- a/ldpd/ldp.h +++ b/ldpd/ldp.h @@ -326,13 +326,6 @@ struct pw_status_tlv { #define PW_STATUS_TLV_SIZE 8 #define PW_STATUS_TLV_LEN 4 -#define PW_FORWARDING 0 -#define PW_NOT_FORWARDING (1 << 0) -#define PW_LOCAL_RX_FAULT (1 << 1) -#define PW_LOCAL_TX_FAULT (1 << 2) -#define PW_PSN_RX_FAULT (1 << 3) -#define PW_PSN_TX_FAULT (1 << 4) - #define NO_LABEL UINT32_MAX #endif /* !_LDP_H_ */ diff --git a/ldpd/ldp_vty_exec.c b/ldpd/ldp_vty_exec.c index d74017c7e2..7bc2623eb3 100644 --- a/ldpd/ldp_vty_exec.c +++ b/ldpd/ldp_vty_exec.c @@ -1357,7 +1357,7 @@ show_l2vpn_pw_msg(struct vty *vty, struct imsg *imsg, struct show_params *params vty_out (vty, "%-9s %-15s %-10u %-16s %-10s\n", pw->ifname, inet_ntoa(pw->lsr_id), pw->pwid, pw->l2vpn_name, - (pw->status ? "UP" : "DOWN")); + (pw->status == PW_FORWARDING ? "UP" : "DOWN")); break; case IMSG_CTL_END: vty_out (vty, "\n"); @@ -1384,7 +1384,7 @@ show_l2vpn_pw_msg_json(struct imsg *imsg, struct show_params *params, json_object_string_add(json_pw, "peerId", inet_ntoa(pw->lsr_id)); json_object_int_add(json_pw, "vcId", pw->pwid); json_object_string_add(json_pw, "VpnName", pw->l2vpn_name); - if (pw->status) + if (pw->status == PW_FORWARDING) json_object_string_add(json_pw, "status", "up"); else json_object_string_add(json_pw, "status", "down"); diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index 8638be83db..d828fbe977 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -508,8 +508,9 @@ ldp_zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS) zebra_read_pw_status_update(cmd, zclient, length, vrf_id, &zpw); - debug_zebra_in("pseudowire %s status %s", zpw.ifname, - (zpw.status == PW_STATUS_UP) ? "up" : "down"); + debug_zebra_in("pseudowire %s status %s 0x%x", zpw.ifname, + (zpw.status == PW_FORWARDING) ? "up" : "down", + zpw.status); main_imsg_compose_lde(IMSG_PW_UPDATE, 0, &zpw, sizeof(zpw)); diff --git a/ldpd/notification.c b/ldpd/notification.c index 4a5f3c8fa4..6de26107e6 100644 --- a/ldpd/notification.c +++ b/ldpd/notification.c @@ -321,5 +321,5 @@ log_msg_notification(int out, struct nbr *nbr, struct notify_msg *nm) debug_msg(out, "notification: fec %s", log_map(&nm->fec)); if (nm->flags & F_NOTIF_PW_STATUS) debug_msg(out, "notification: pw-status %s", - (nm->pw_status) ? "not forwarding" : "forwarding"); + (nm->pw_status == PW_FORWARDING) ? "forwarding" : "not forwarding"); } diff --git a/lib/pw.h b/lib/pw.h index 42b3ee2155..2fc4a61f96 100644 --- a/lib/pw.h +++ b/lib/pw.h @@ -35,9 +35,13 @@ extern "C" { /* Pseudowire flags. */ #define F_PSEUDOWIRE_CWORD 0x01 -/* Pseudowire status. */ -#define PW_STATUS_DOWN 0 -#define PW_STATUS_UP 1 +/* Pseudowire status TLV */ +#define PW_FORWARDING 0 +#define PW_NOT_FORWARDING (1 << 0) +#define PW_LOCAL_RX_FAULT (1 << 1) +#define PW_LOCAL_TX_FAULT (1 << 2) +#define PW_PSN_RX_FAULT (1 << 3) +#define PW_PSN_TX_FAULT (1 << 4) /* * Protocol-specific information about the pseudowire. diff --git a/lib/zclient.h b/lib/zclient.h index 4ada064623..e3e929c8d6 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -514,6 +514,7 @@ struct zapi_pw_status { char ifname[IF_NAMESIZE]; ifindex_t ifindex; uint32_t status; + uint32_t pwstatus; }; enum zapi_route_notify_owner { diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 278e894d06..4bd95ba963 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -896,6 +896,7 @@ void dplane_ctx_set_notif_provider(struct zebra_dplane_ctx *ctx, ctx->zd_notif_provider = id; } + const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); @@ -903,6 +904,16 @@ const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx) return ctx->zd_ifname; } +void dplane_ctx_set_ifname(struct zebra_dplane_ctx *ctx, const char *ifname) +{ + DPLANE_CTX_VALID(ctx); + + if (!ifname) + return; + + strlcpy(ctx->zd_ifname, ifname, sizeof(ctx->zd_ifname)); +} + ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); @@ -1310,6 +1321,13 @@ int dplane_ctx_get_pw_status(const struct zebra_dplane_ctx *ctx) return ctx->u.pw.status; } +void dplane_ctx_set_pw_status(struct zebra_dplane_ctx *ctx, int status) +{ + DPLANE_CTX_VALID(ctx); + + ctx->u.pw.status = status; +} + const union g_addr *dplane_ctx_get_pw_dest( const struct zebra_dplane_ctx *ctx) { diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 9ce542944d..e16e69c03d 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -223,6 +223,7 @@ const struct prefix *dplane_ctx_get_dest(const struct zebra_dplane_ctx *ctx); void dplane_ctx_set_dest(struct zebra_dplane_ctx *ctx, const struct prefix *dest); const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx); +void dplane_ctx_set_ifname(struct zebra_dplane_ctx *ctx, const char *ifname); ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx); /* Retrieve last/current provider id */ @@ -332,6 +333,7 @@ int dplane_ctx_get_pw_type(const struct zebra_dplane_ctx *ctx); int dplane_ctx_get_pw_af(const struct zebra_dplane_ctx *ctx); uint32_t dplane_ctx_get_pw_flags(const struct zebra_dplane_ctx *ctx); int dplane_ctx_get_pw_status(const struct zebra_dplane_ctx *ctx); +void dplane_ctx_set_pw_status(struct zebra_dplane_ctx *ctx, int status); const union g_addr *dplane_ctx_get_pw_dest( const struct zebra_dplane_ctx *ctx); const union pw_protocol_fields *dplane_ctx_get_pw_proto( @@ -550,7 +552,6 @@ enum dplane_provider_prio { /* Provider will be spawning its own worker thread */ #define DPLANE_PROV_FLAG_THREADED 0x1 - /* Provider registration: ordering or priority value, callbacks, and optional * opaque data value. If 'prov_p', return the newly-allocated provider object * on success. diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c index 273843baa2..8f255ecfb0 100644 --- a/zebra/zebra_pw.c +++ b/zebra/zebra_pw.c @@ -74,7 +74,7 @@ struct zebra_pw *zebra_pw_add(struct zebra_vrf *zvrf, const char *ifname, pw->protocol = protocol; pw->vrf_id = zvrf_id(zvrf); pw->client = client; - pw->status = PW_STATUS_DOWN; + pw->status = PW_NOT_FORWARDING; pw->local_label = MPLS_NO_LABEL; pw->remote_label = MPLS_NO_LABEL; pw->flags = F_PSEUDOWIRE_CWORD; @@ -98,7 +98,7 @@ void zebra_pw_del(struct zebra_vrf *zvrf, struct zebra_pw *pw) zebra_deregister_rnh_pseudowire(pw->vrf_id, pw); /* uninstall */ - if (pw->status == PW_STATUS_UP) { + if (pw->status == PW_FORWARDING) { hook_call(pw_uninstall, pw); dplane_pw_uninstall(pw); } else if (pw->install_retry_timer) @@ -156,6 +156,7 @@ void zebra_pw_update(struct zebra_pw *pw) { if (zebra_pw_check_reachability(pw) < 0) { zebra_pw_uninstall(pw); + zebra_pw_install_failure(pw, PW_NOT_FORWARDING); /* wait for NHT and try again later */ } else { /* @@ -175,17 +176,17 @@ static void zebra_pw_install(struct zebra_pw *pw) hook_call(pw_install, pw); if (dplane_pw_install(pw) == ZEBRA_DPLANE_REQUEST_FAILURE) { - zebra_pw_install_failure(pw); + zebra_pw_install_failure(pw, PW_NOT_FORWARDING); return; } - if (pw->status == PW_STATUS_DOWN) - zebra_pw_update_status(pw, PW_STATUS_UP); + if (pw->status != PW_FORWARDING) + zebra_pw_update_status(pw, PW_FORWARDING); } static void zebra_pw_uninstall(struct zebra_pw *pw) { - if (pw->status == PW_STATUS_DOWN) + if (pw->status != PW_FORWARDING) return; if (IS_ZEBRA_DEBUG_PW) @@ -198,7 +199,7 @@ static void zebra_pw_uninstall(struct zebra_pw *pw) dplane_pw_uninstall(pw); if (zebra_pw_enabled(pw)) - zebra_pw_update_status(pw, PW_STATUS_DOWN); + zebra_pw_update_status(pw, PW_NOT_FORWARDING); } /* @@ -207,7 +208,7 @@ static void zebra_pw_uninstall(struct zebra_pw *pw) * to retry the installation later. This function can be called by an external * agent that performs the pseudowire installation in an asynchronous way. */ -void zebra_pw_install_failure(struct zebra_pw *pw) +void zebra_pw_install_failure(struct zebra_pw *pw, int pwstatus) { if (IS_ZEBRA_DEBUG_PW) zlog_debug( @@ -220,7 +221,7 @@ void zebra_pw_install_failure(struct zebra_pw *pw) thread_add_timer(zrouter.master, zebra_pw_install_retry, pw, PW_INSTALL_RETRY_INTERVAL, &pw->install_retry_timer); - zebra_pw_update_status(pw, PW_STATUS_DOWN); + zebra_pw_update_status(pw, pwstatus); } static int zebra_pw_install_retry(struct thread *thread) @@ -500,7 +501,7 @@ DEFUN (show_pseudowires, vty_out(vty, "%-16s %-24s %-12s %-8s %-10s\n", pw->ifname, (pw->af != AF_UNSPEC) ? buf_nbr : "-", buf_labels, zebra_route_string(pw->protocol), - (zebra_pw_enabled(pw) && pw->status == PW_STATUS_UP) + (zebra_pw_enabled(pw) && pw->status == PW_FORWARDING) ? "UP" : "DOWN"); } @@ -540,7 +541,7 @@ static void vty_show_mpls_pseudowire_detail(struct vty *vty) if (pw->protocol == ZEBRA_ROUTE_LDP) vty_out(vty, " VC-ID: %u\n", pw->data.ldp.pwid); vty_out(vty, " Status: %s \n", - (zebra_pw_enabled(pw) && pw->status == PW_STATUS_UP) + (zebra_pw_enabled(pw) && pw->status == PW_FORWARDING) ? "Up" : "Down"); re = rib_match(family2afi(pw->af), SAFI_UNICAST, pw->vrf_id, @@ -595,8 +596,8 @@ static void vty_show_mpls_pseudowire(struct zebra_pw *pw, json_object *json_pws) json_object_int_add(json_pw, "vcId", pw->data.ldp.pwid); json_object_string_add( json_pw, "Status", - (zebra_pw_enabled(pw) && pw->status == PW_STATUS_UP) ? "Up" - : "Down"); + (zebra_pw_enabled(pw) && pw->status == PW_FORWARDING) ? "Up" + : "Down"); re = rib_match(family2afi(pw->af), SAFI_UNICAST, pw->vrf_id, &pw->nexthop, NULL); if (re) { diff --git a/zebra/zebra_pw.h b/zebra/zebra_pw.h index bbb3776725..7b13c7e16b 100644 --- a/zebra/zebra_pw.h +++ b/zebra/zebra_pw.h @@ -73,7 +73,7 @@ void zebra_pw_change(struct zebra_pw *, ifindex_t, int, int, union g_addr *, uint32_t, uint32_t, uint8_t, union pw_protocol_fields *); struct zebra_pw *zebra_pw_find(struct zebra_vrf *, const char *); void zebra_pw_update(struct zebra_pw *); -void zebra_pw_install_failure(struct zebra_pw *); +void zebra_pw_install_failure(struct zebra_pw *pw, int pwstatus); void zebra_pw_init(struct zebra_vrf *); void zebra_pw_exit(struct zebra_vrf *); void zebra_pw_vty_init(void); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index d491982d62..f52ed471f0 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -3466,7 +3466,8 @@ static int handle_pw_result(struct zebra_dplane_ctx *ctx) vrf = zebra_vrf_lookup_by_id(dplane_ctx_get_vrf(ctx)); pw = zebra_pw_find(vrf, dplane_ctx_get_ifname(ctx)); if (pw) - zebra_pw_install_failure(pw); + zebra_pw_install_failure(pw, + dplane_ctx_get_pw_status(ctx)); } done: