From ff5279ba48f2ff388e2345e118732e5b27f5a791 Mon Sep 17 00:00:00 2001 From: lynne Date: Tue, 27 Apr 2021 12:21:54 -0400 Subject: [PATCH] ldpd: make allowing broken-lsps to be installed with pop operation configurable If LDP is miss configured in a setup and the router has LSPs with no remote label, this code installs the LSP with a pop instruction of the top-level label so the packet can be forwarded using IP. This is a best-effort attempt to deliver labeled IP packets to their final destination instead of dropping them. If this config is turned off the code will only install LSPs that have a valid remote label. Signed-off-by: Lynne Morrison --- ldpd/lde.c | 24 ++++++++++++++++++++++++ ldpd/lde.h | 1 + ldpd/ldp_vty.h | 1 + ldpd/ldp_vty_cmds.c | 11 +++++++++++ ldpd/ldp_vty_conf.c | 16 ++++++++++++++++ ldpd/ldp_zebra.c | 9 +++++++-- ldpd/ldpd.c | 10 ++++++++++ ldpd/ldpd.h | 2 +- 8 files changed, 71 insertions(+), 3 deletions(-) diff --git a/ldpd/lde.c b/ldpd/lde.c index 02dcec750b..724e83adb2 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -1630,6 +1630,30 @@ lde_nbr_addr_update(struct lde_nbr *ln, struct lde_addr *lde_addr, int removed) } } +void +lde_allow_broken_lsp_update(int new_config) +{ + struct fec_node *fn; + struct fec_nh *fnh; + struct fec *f; + + RB_FOREACH(f, fec_tree, &ft) { + fn = (struct fec_node *)f; + + LIST_FOREACH(fnh, &fn->nexthops, entry) { + /* allow-broken-lsp config is changing so + * we need to reprogram labeled routes to + * have proper top-level label + */ + if (!(new_config & F_LDPD_ALLOW_BROKEN_LSP)) + lde_send_delete_klabel(fn, fnh); + + if (fn->local_label != NO_LABEL) + lde_send_change_klabel(fn, fnh); + } + } +} + static __inline int lde_map_compare(const struct lde_map *a, const struct lde_map *b) { diff --git a/ldpd/lde.h b/ldpd/lde.h index e09be01ece..dee6f3fcb9 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -200,6 +200,7 @@ void lde_route_update_release(struct iface *, int); void lde_route_update_release_all(int); struct lde_addr *lde_address_find(struct lde_nbr *, int, union ldpd_addr *); +void lde_allow_broken_lsp_update(int new_config); /* lde_lib.c */ void fec_init(struct fec_tree *); diff --git a/ldpd/ldp_vty.h b/ldpd/ldp_vty.h index 882874f1be..d788fa0687 100644 --- a/ldpd/ldp_vty.h +++ b/ldpd/ldp_vty.h @@ -34,6 +34,7 @@ extern struct cmd_node ldp_debug_node; union ldpd_addr; int ldp_get_address(const char *, int *, union ldpd_addr *); int ldp_vty_mpls_ldp (struct vty *, const char *); +int ldp_vty_allow_broken_lsp(struct vty *, const char *); int ldp_vty_address_family (struct vty *, const char *, const char *); int ldp_vty_disc_holdtime(struct vty *, const char *, enum hello_type, long); int ldp_vty_disc_interval(struct vty *, const char *, enum hello_type, long); diff --git a/ldpd/ldp_vty_cmds.c b/ldpd/ldp_vty_cmds.c index 1f102f86fa..b65ebf6f55 100644 --- a/ldpd/ldp_vty_cmds.c +++ b/ldpd/ldp_vty_cmds.c @@ -241,6 +241,16 @@ DEFPY (ldp_wait_for_sync, } +DEFPY (ldp_allow_broken_lsps, + ldp_allow_broken_lsps_cmd, + "[no] install allow-broken-lsps", + NO_STR + "install lsps\n" + "if no remote-label install with imp-null") +{ + return (ldp_vty_allow_broken_lsp(vty, no)); +} + DEFPY (ldp_discovery_targeted_hello_accept, ldp_discovery_targeted_hello_accept_cmd, "[no] discovery targeted-hello accept [from <(1-199)|(1300-2699)|WORD>$from_acl]", @@ -844,6 +854,7 @@ ldp_vty_init (void) install_element(LDP_NODE, &ldp_router_id_cmd); install_element(LDP_NODE, &ldp_ordered_control_cmd); install_element(LDP_NODE, &ldp_wait_for_sync_cmd); + install_element(LDP_NODE, &ldp_allow_broken_lsps_cmd); install_element(LDP_IPV4_NODE, &ldp_discovery_link_holdtime_cmd); install_element(LDP_IPV4_NODE, &ldp_discovery_targeted_holdtime_cmd); diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index 6e925d1410..b35d3dfa00 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -290,6 +290,9 @@ ldp_config_write(struct vty *vty) vty_out (vty, " wait-for-sync %u\n", ldpd_conf->wait_for_sync_interval); + if (ldpd_conf->flags & F_LDPD_ALLOW_BROKEN_LSP) + vty_out(vty, " install allow-broken-lsp\n"); + RB_FOREACH(nbrp, nbrp_head, &ldpd_conf->nbrp_tree) { if (nbrp->flags & F_NBRP_KEEPALIVE) vty_out (vty, " neighbor %pI4 session holdtime %u\n", @@ -1039,6 +1042,19 @@ int ldp_vty_wait_for_sync_interval(struct vty *vty, const char *negate, return (CMD_SUCCESS); } +int +ldp_vty_allow_broken_lsp(struct vty *vty, const char *negate) +{ + if (negate) + vty_conf->flags &= ~F_LDPD_ALLOW_BROKEN_LSP; + else + vty_conf->flags |= F_LDPD_ALLOW_BROKEN_LSP; + + ldp_config_apply(vty, vty_conf); + + return (CMD_SUCCESS); +} + int ldp_vty_ds_cisco_interop(struct vty *vty, const char * negate) { diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c index fd51625bbd..2d90412d17 100644 --- a/ldpd/ldp_zebra.c +++ b/ldpd/ldp_zebra.c @@ -246,12 +246,17 @@ ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr) zl.route.instance = kr->route_instance; } - /* - * For broken LSPs, instruct the forwarding plane to pop the top-level + /* If allow-broken-lsps is enabled then if an lsp is received with + * no remote label, instruct the forwarding plane to pop the top-level * label and forward packets normally. This is a best-effort attempt * to deliver labeled IP packets to their final destination (instead of * dropping them). */ + if (kr->remote_label == NO_LABEL + && !(ldpd_conf->flags & F_LDPD_ALLOW_BROKEN_LSP) + && cmd == ZEBRA_MPLS_LABELS_ADD) + return 0; + if (kr->remote_label == NO_LABEL) kr->remote_label = MPLS_LABEL_IMPLICIT_NULL; diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index d69a4dcd3c..800b954d65 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -1365,6 +1365,16 @@ merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf) ldpe_reset_ds_nbrs(); } + /* + * Configuration of allow-broken-lsp requires reprograming all + * labeled routes + */ + if ((conf->flags & F_LDPD_ALLOW_BROKEN_LSP) != + (xconf->flags & F_LDPD_ALLOW_BROKEN_LSP)) { + if (ldpd_process == PROC_LDE_ENGINE) + lde_allow_broken_lsp_update(xconf->flags); + } + if (ldpd_process == PROC_LDP_ENGINE) ldpe_set_config_change_time(); diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index cb7ac85d96..616c390e50 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -590,7 +590,7 @@ DECLARE_QOBJ_TYPE(ldpd_conf); #define F_LDPD_DS_CISCO_INTEROP 0x0002 #define F_LDPD_ENABLED 0x0004 #define F_LDPD_ORDERED_CONTROL 0x0008 - +#define F_LDPD_ALLOW_BROKEN_LSP 0x0010 struct ldpd_af_global { struct thread *disc_ev;