mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-28 21:20:48 +00:00
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 <karen@voltanet.io>
This commit is contained in:
parent
6b2210021c
commit
fd563cc7f3
@ -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));
|
||||
|
@ -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_ */
|
||||
|
@ -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");
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
10
lib/pw.h
10
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.
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user