mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 16:20:08 +00:00
ldpd: Fix issue when starting up LDP with no configuration.
LDP would mark all routes as learned on a non-ldp interface. Then when LDP was configured the labels were not updated correctly. This commit fixes issues 6841 and 6842. Signed-off-by: Lynne Morrison <lynne@voltanet.io>
This commit is contained in:
parent
ee7d41a437
commit
955357174f
158
ldpd/lde.c
158
ldpd/lde.c
@ -468,6 +468,10 @@ lde_dispatch_parent(struct thread *thread)
|
||||
iface = if_lookup_name(ldeconf, kif->ifname);
|
||||
if (iface) {
|
||||
if_update_info(iface, kif);
|
||||
|
||||
/* if up see if any labels need to be updated */
|
||||
if (kif->operative)
|
||||
lde_route_update(iface, AF_UNSPEC);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -786,7 +790,6 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh)
|
||||
kr.remote_label = fnh->remote_label;
|
||||
kr.route_type = fnh->route_type;
|
||||
kr.route_instance = fnh->route_instance;
|
||||
|
||||
lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr,
|
||||
sizeof(kr));
|
||||
break;
|
||||
@ -2271,3 +2274,156 @@ lde_check_filter_af(int af, struct ldpd_af_conf *af_conf,
|
||||
if (strcmp(af_conf->acl_label_expnull_for, filter_name) == 0)
|
||||
lde_change_expnull_for_filter(af);
|
||||
}
|
||||
|
||||
void lde_route_update(struct iface *iface, int af)
|
||||
{
|
||||
struct fec *f;
|
||||
struct fec_node *fn;
|
||||
struct fec_nh *fnh;
|
||||
struct lde_nbr *ln;
|
||||
|
||||
/* update label of non-connected routes */
|
||||
log_debug("update labels for interface %s", iface->name);
|
||||
RB_FOREACH(f, fec_tree, &ft) {
|
||||
fn = (struct fec_node *)f;
|
||||
if (IS_MPLS_UNRESERVED_LABEL(fn->local_label))
|
||||
continue;
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
if (fn->fec.type != FEC_TYPE_IPV4)
|
||||
continue;
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (fn->fec.type != FEC_TYPE_IPV6)
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
/* unspecified so process both address families */
|
||||
break;
|
||||
}
|
||||
|
||||
LIST_FOREACH(fnh, &fn->nexthops, entry) {
|
||||
/*
|
||||
* If connected leave existing label. If LDP
|
||||
* configured on interface or a static route
|
||||
* may need new label. If no LDP configured
|
||||
* treat fec as a connected route
|
||||
*/
|
||||
if (fnh->flags & F_FEC_NH_CONNECTED)
|
||||
break;
|
||||
|
||||
if (fnh->ifindex != iface->ifindex)
|
||||
continue;
|
||||
|
||||
fnh->flags &= ~F_FEC_NH_NO_LDP;
|
||||
if (IS_MPLS_RESERVED_LABEL(fn->local_label)) {
|
||||
fn->local_label = NO_LABEL;
|
||||
fn->local_label = lde_update_label(fn);
|
||||
if (fn->local_label != NO_LABEL)
|
||||
RB_FOREACH(ln, nbr_tree, &lde_nbrs)
|
||||
lde_send_labelmapping(
|
||||
ln, fn, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
RB_FOREACH(ln, nbr_tree, &lde_nbrs)
|
||||
lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid,
|
||||
0, NULL, 0);
|
||||
}
|
||||
|
||||
void lde_route_update_release(struct iface *iface, int af)
|
||||
{
|
||||
struct lde_nbr *ln;
|
||||
struct fec *f;
|
||||
struct fec_node *fn;
|
||||
struct fec_nh *fnh;
|
||||
|
||||
/* update label of interfaces no longer running LDP */
|
||||
log_debug("release all labels for interface %s af %s", iface->name,
|
||||
af == AF_INET ? "ipv4" : "ipv6");
|
||||
RB_FOREACH(f, fec_tree, &ft) {
|
||||
fn = (struct fec_node *)f;
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
if (fn->fec.type != FEC_TYPE_IPV4)
|
||||
continue;
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (fn->fec.type != FEC_TYPE_IPV6)
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
fatalx("lde_route_update_release: unknown af");
|
||||
}
|
||||
|
||||
if (fn->local_label == NO_LABEL)
|
||||
continue;
|
||||
|
||||
LIST_FOREACH(fnh, &fn->nexthops, entry) {
|
||||
/*
|
||||
* If connected leave existing label. If LDP
|
||||
* removed from interface may need new label
|
||||
* and would be treated as a connected route
|
||||
*/
|
||||
if (fnh->flags & F_FEC_NH_CONNECTED)
|
||||
break;
|
||||
|
||||
if (fnh->ifindex != iface->ifindex)
|
||||
continue;
|
||||
|
||||
fnh->flags |= F_FEC_NH_NO_LDP;
|
||||
RB_FOREACH(ln, nbr_tree, &lde_nbrs)
|
||||
lde_send_labelwithdraw(ln, fn, NULL, NULL);
|
||||
lde_free_label(fn->local_label);
|
||||
fn->local_label = NO_LABEL;
|
||||
fn->local_label = lde_update_label(fn);
|
||||
if (fn->local_label != NO_LABEL)
|
||||
RB_FOREACH(ln, nbr_tree, &lde_nbrs)
|
||||
lde_send_labelmapping(ln, fn, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
RB_FOREACH(ln, nbr_tree, &lde_nbrs)
|
||||
lde_imsg_compose_ldpe(IMSG_MAPPING_ADD_END, ln->peerid,
|
||||
0, NULL, 0);
|
||||
}
|
||||
|
||||
void lde_route_update_release_all(int af)
|
||||
{
|
||||
struct lde_nbr *ln;
|
||||
struct fec *f;
|
||||
struct fec_node *fn;
|
||||
struct fec_nh *fnh;
|
||||
|
||||
/* remove labels from all interfaces as LDP is no longer running for
|
||||
* this address family
|
||||
*/
|
||||
log_debug("release all labels for address family %s",
|
||||
af == AF_INET ? "ipv4" : "ipv6");
|
||||
RB_FOREACH(f, fec_tree, &ft) {
|
||||
fn = (struct fec_node *)f;
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
if (fn->fec.type != FEC_TYPE_IPV4)
|
||||
continue;
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (fn->fec.type != FEC_TYPE_IPV6)
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
fatalx("lde_route_update_release: unknown af");
|
||||
}
|
||||
|
||||
RB_FOREACH(ln, nbr_tree, &lde_nbrs)
|
||||
lde_send_labelwithdraw(ln, fn, NULL, NULL);
|
||||
|
||||
LIST_FOREACH(fnh, &fn->nexthops, entry) {
|
||||
fnh->flags |= F_FEC_NH_NO_LDP;
|
||||
lde_send_delete_klabel(fn, fnh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -193,6 +193,9 @@ void lde_change_allocate_filter(int);
|
||||
void lde_change_advertise_filter(int);
|
||||
void lde_change_accept_filter(int);
|
||||
void lde_change_expnull_for_filter(int);
|
||||
void lde_route_update(struct iface *, int);
|
||||
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 *);
|
||||
|
||||
|
@ -404,10 +404,15 @@ lde_kernel_update(struct fec *fec)
|
||||
* if LDP configured on interface or a static route
|
||||
* clear flag else treat fec as a connected route
|
||||
*/
|
||||
iface = if_lookup(ldeconf,fnh->ifindex);
|
||||
if (iface || fnh->route_type == ZEBRA_ROUTE_STATIC)
|
||||
fnh->flags &=~F_FEC_NH_NO_LDP;
|
||||
else
|
||||
if (ldeconf->flags & F_LDPD_ENABLED) {
|
||||
iface = if_lookup(ldeconf,fnh->ifindex);
|
||||
if (fnh->flags & F_FEC_NH_CONNECTED ||
|
||||
iface ||
|
||||
fnh->route_type == ZEBRA_ROUTE_STATIC)
|
||||
fnh->flags &=~F_FEC_NH_NO_LDP;
|
||||
else
|
||||
fnh->flags |= F_FEC_NH_NO_LDP;
|
||||
} else
|
||||
fnh->flags |= F_FEC_NH_NO_LDP;
|
||||
} else {
|
||||
lde_send_delete_klabel(fn, fnh);
|
||||
@ -437,6 +442,10 @@ lde_kernel_update(struct fec *fec)
|
||||
lde_send_labelmapping(ln, fn, 1);
|
||||
}
|
||||
|
||||
/* if no label created yet then don't try to program labeled route */
|
||||
if (fn->local_label == NO_LABEL)
|
||||
return;
|
||||
|
||||
LIST_FOREACH(fnh, &fn->nexthops, entry) {
|
||||
lde_send_change_klabel(fn, fnh);
|
||||
|
||||
@ -567,7 +576,8 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln, int rcvd_label_mapping)
|
||||
fnh->flags &= ~F_FEC_NH_DEFER;
|
||||
}
|
||||
fnh->remote_label = map->label;
|
||||
lde_send_change_klabel(fn, fnh);
|
||||
if (fn->local_label != NO_LABEL)
|
||||
lde_send_change_klabel(fn, fnh);
|
||||
break;
|
||||
case FEC_TYPE_PWID:
|
||||
pw = (struct l2vpn_pw *) fn->data;
|
||||
|
@ -616,6 +616,8 @@ DEFPY (ldp_show_mpls_ldp_binding,
|
||||
"Show detailed information\n"
|
||||
JSON_STR)
|
||||
{
|
||||
if (!(ldpd_conf->flags & F_LDPD_ENABLED))
|
||||
return CMD_SUCCESS;
|
||||
if (!local_label_str)
|
||||
local_label = NO_LABEL;
|
||||
if (!remote_label_str)
|
||||
|
43
ldpd/ldpd.c
43
ldpd/ldpd.c
@ -1329,6 +1329,7 @@ merge_af(int af, struct ldpd_af_conf *af_conf, struct ldpd_af_conf *xa)
|
||||
int reset_nbrs_ipv4 = 0;
|
||||
int reset_nbrs = 0;
|
||||
int update_sockets = 0;
|
||||
int change_ldp_disabled = 0;
|
||||
|
||||
/* update timers */
|
||||
if (af_conf->keepalive != xa->keepalive) {
|
||||
@ -1362,6 +1363,11 @@ merge_af(int af, struct ldpd_af_conf *af_conf, struct ldpd_af_conf *xa)
|
||||
!= (xa->flags & F_LDPD_AF_ALLOCHOSTONLY))
|
||||
change_host_label = 1;
|
||||
|
||||
/* disabling LDP for address family */
|
||||
if ((af_conf->flags & F_LDPD_AF_ENABLED) &&
|
||||
!(xa->flags & F_LDPD_AF_ENABLED))
|
||||
change_ldp_disabled = 1;
|
||||
|
||||
af_conf->flags = xa->flags;
|
||||
|
||||
/* update the transport address */
|
||||
@ -1409,6 +1415,9 @@ merge_af(int af, struct ldpd_af_conf *af_conf, struct ldpd_af_conf *xa)
|
||||
lde_change_egress_label(af);
|
||||
if (change_host_label)
|
||||
lde_change_allocate_filter(af);
|
||||
if (change_ldp_disabled)
|
||||
lde_route_update_release_all(af);
|
||||
|
||||
break;
|
||||
case PROC_LDP_ENGINE:
|
||||
if (stop_init_backoff)
|
||||
@ -1434,13 +1443,22 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
||||
struct iface *iface, *itmp, *xi;
|
||||
|
||||
RB_FOREACH_SAFE(iface, iface_head, &conf->iface_tree, itmp) {
|
||||
/* find deleted interfaces */
|
||||
/* find deleted interfaces, which occurs when LDP is removed
|
||||
* for all address families
|
||||
*/
|
||||
if (if_lookup_name(xconf, iface->name) == NULL) {
|
||||
switch (ldpd_process) {
|
||||
case PROC_LDP_ENGINE:
|
||||
ldpe_if_exit(iface);
|
||||
break;
|
||||
case PROC_LDE_ENGINE:
|
||||
if (iface->ipv4.enabled)
|
||||
lde_route_update_release(iface,
|
||||
AF_INET);
|
||||
if (iface->ipv6.enabled)
|
||||
lde_route_update_release(iface,
|
||||
AF_INET6);
|
||||
break;
|
||||
case PROC_MAIN:
|
||||
break;
|
||||
}
|
||||
@ -1468,6 +1486,29 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* update labels when adding or removing ldp on an
|
||||
* interface
|
||||
*/
|
||||
if (ldpd_process == PROC_LDE_ENGINE) {
|
||||
/* if we are removing lpd config for an address
|
||||
* family on an interface then advertise routes
|
||||
* learned over this interface as if they were
|
||||
* connected routes
|
||||
*/
|
||||
if (iface->ipv4.enabled && !xi->ipv4.enabled)
|
||||
lde_route_update_release(iface, AF_INET);
|
||||
if (iface->ipv6.enabled && !xi->ipv6.enabled)
|
||||
lde_route_update_release(iface, AF_INET6);
|
||||
|
||||
/* if we are adding lpd config for an address
|
||||
* family on an interface then add proper labels
|
||||
*/
|
||||
if (!iface->ipv4.enabled && xi->ipv4.enabled)
|
||||
lde_route_update(iface, AF_INET);
|
||||
if (!iface->ipv6.enabled && xi->ipv6.enabled)
|
||||
lde_route_update(iface, AF_INET6);
|
||||
}
|
||||
|
||||
/* update existing interfaces */
|
||||
merge_iface_af(&iface->ipv4, &xi->ipv4);
|
||||
merge_iface_af(&iface->ipv6, &xi->ipv6);
|
||||
|
@ -614,10 +614,8 @@ ldpe_dispatch_lde(struct thread *thread)
|
||||
map = imsg.data;
|
||||
|
||||
nbr = nbr_find_peerid(imsg.hdr.peerid);
|
||||
if (nbr == NULL) {
|
||||
log_debug("ldpe_dispatch_lde: cannot find neighbor");
|
||||
if (nbr == NULL)
|
||||
break;
|
||||
}
|
||||
if (nbr->state != NBR_STA_OPER)
|
||||
break;
|
||||
|
||||
@ -641,10 +639,8 @@ ldpe_dispatch_lde(struct thread *thread)
|
||||
case IMSG_REQUEST_ADD_END:
|
||||
case IMSG_WITHDRAW_ADD_END:
|
||||
nbr = nbr_find_peerid(imsg.hdr.peerid);
|
||||
if (nbr == NULL) {
|
||||
log_debug("ldpe_dispatch_lde: cannot find neighbor");
|
||||
if (nbr == NULL)
|
||||
break;
|
||||
}
|
||||
if (nbr->state != NBR_STA_OPER)
|
||||
break;
|
||||
|
||||
|
@ -72,8 +72,7 @@ extern "C" {
|
||||
/* Maximum # labels that can be pushed. */
|
||||
#define MPLS_MAX_LABELS 16
|
||||
|
||||
#define IS_MPLS_RESERVED_LABEL(label) \
|
||||
(label >= MPLS_LABEL_RESERVED_MIN && label <= MPLS_LABEL_RESERVED_MAX)
|
||||
#define IS_MPLS_RESERVED_LABEL(label) (label <= MPLS_LABEL_RESERVED_MAX)
|
||||
|
||||
#define IS_MPLS_UNRESERVED_LABEL(label) \
|
||||
(label >= MPLS_LABEL_UNRESERVED_MIN \
|
||||
|
Loading…
Reference in New Issue
Block a user