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 <lynne@voltanet.io>
This commit is contained in:
lynne 2021-04-27 12:21:54 -04:00
parent adf1bb9f0c
commit ff5279ba48
8 changed files with 71 additions and 3 deletions

View File

@ -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)
{

View File

@ -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 *);

View File

@ -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);

View File

@ -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);

View File

@ -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)
{

View File

@ -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;

View File

@ -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();

View File

@ -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;