mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 15:33:56 +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);
|
iface = if_lookup_name(ldeconf, kif->ifname);
|
||||||
if (iface) {
|
if (iface) {
|
||||||
if_update_info(iface, kif);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -786,7 +790,6 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh)
|
|||||||
kr.remote_label = fnh->remote_label;
|
kr.remote_label = fnh->remote_label;
|
||||||
kr.route_type = fnh->route_type;
|
kr.route_type = fnh->route_type;
|
||||||
kr.route_instance = fnh->route_instance;
|
kr.route_instance = fnh->route_instance;
|
||||||
|
|
||||||
lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr,
|
lde_imsg_compose_parent(IMSG_KLABEL_CHANGE, 0, &kr,
|
||||||
sizeof(kr));
|
sizeof(kr));
|
||||||
break;
|
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)
|
if (strcmp(af_conf->acl_label_expnull_for, filter_name) == 0)
|
||||||
lde_change_expnull_for_filter(af);
|
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_advertise_filter(int);
|
||||||
void lde_change_accept_filter(int);
|
void lde_change_accept_filter(int);
|
||||||
void lde_change_expnull_for_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,
|
struct lde_addr *lde_address_find(struct lde_nbr *, int,
|
||||||
union ldpd_addr *);
|
union ldpd_addr *);
|
||||||
|
|
||||||
|
@ -404,10 +404,15 @@ lde_kernel_update(struct fec *fec)
|
|||||||
* if LDP configured on interface or a static route
|
* if LDP configured on interface or a static route
|
||||||
* clear flag else treat fec as a connected route
|
* clear flag else treat fec as a connected route
|
||||||
*/
|
*/
|
||||||
iface = if_lookup(ldeconf,fnh->ifindex);
|
if (ldeconf->flags & F_LDPD_ENABLED) {
|
||||||
if (iface || fnh->route_type == ZEBRA_ROUTE_STATIC)
|
iface = if_lookup(ldeconf,fnh->ifindex);
|
||||||
fnh->flags &=~F_FEC_NH_NO_LDP;
|
if (fnh->flags & F_FEC_NH_CONNECTED ||
|
||||||
else
|
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;
|
fnh->flags |= F_FEC_NH_NO_LDP;
|
||||||
} else {
|
} else {
|
||||||
lde_send_delete_klabel(fn, fnh);
|
lde_send_delete_klabel(fn, fnh);
|
||||||
@ -437,6 +442,10 @@ lde_kernel_update(struct fec *fec)
|
|||||||
lde_send_labelmapping(ln, fn, 1);
|
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) {
|
LIST_FOREACH(fnh, &fn->nexthops, entry) {
|
||||||
lde_send_change_klabel(fn, fnh);
|
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->flags &= ~F_FEC_NH_DEFER;
|
||||||
}
|
}
|
||||||
fnh->remote_label = map->label;
|
fnh->remote_label = map->label;
|
||||||
lde_send_change_klabel(fn, fnh);
|
if (fn->local_label != NO_LABEL)
|
||||||
|
lde_send_change_klabel(fn, fnh);
|
||||||
break;
|
break;
|
||||||
case FEC_TYPE_PWID:
|
case FEC_TYPE_PWID:
|
||||||
pw = (struct l2vpn_pw *) fn->data;
|
pw = (struct l2vpn_pw *) fn->data;
|
||||||
|
@ -616,6 +616,8 @@ DEFPY (ldp_show_mpls_ldp_binding,
|
|||||||
"Show detailed information\n"
|
"Show detailed information\n"
|
||||||
JSON_STR)
|
JSON_STR)
|
||||||
{
|
{
|
||||||
|
if (!(ldpd_conf->flags & F_LDPD_ENABLED))
|
||||||
|
return CMD_SUCCESS;
|
||||||
if (!local_label_str)
|
if (!local_label_str)
|
||||||
local_label = NO_LABEL;
|
local_label = NO_LABEL;
|
||||||
if (!remote_label_str)
|
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_ipv4 = 0;
|
||||||
int reset_nbrs = 0;
|
int reset_nbrs = 0;
|
||||||
int update_sockets = 0;
|
int update_sockets = 0;
|
||||||
|
int change_ldp_disabled = 0;
|
||||||
|
|
||||||
/* update timers */
|
/* update timers */
|
||||||
if (af_conf->keepalive != xa->keepalive) {
|
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))
|
!= (xa->flags & F_LDPD_AF_ALLOCHOSTONLY))
|
||||||
change_host_label = 1;
|
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;
|
af_conf->flags = xa->flags;
|
||||||
|
|
||||||
/* update the transport address */
|
/* 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);
|
lde_change_egress_label(af);
|
||||||
if (change_host_label)
|
if (change_host_label)
|
||||||
lde_change_allocate_filter(af);
|
lde_change_allocate_filter(af);
|
||||||
|
if (change_ldp_disabled)
|
||||||
|
lde_route_update_release_all(af);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case PROC_LDP_ENGINE:
|
case PROC_LDP_ENGINE:
|
||||||
if (stop_init_backoff)
|
if (stop_init_backoff)
|
||||||
@ -1434,13 +1443,22 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
|||||||
struct iface *iface, *itmp, *xi;
|
struct iface *iface, *itmp, *xi;
|
||||||
|
|
||||||
RB_FOREACH_SAFE(iface, iface_head, &conf->iface_tree, itmp) {
|
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) {
|
if (if_lookup_name(xconf, iface->name) == NULL) {
|
||||||
switch (ldpd_process) {
|
switch (ldpd_process) {
|
||||||
case PROC_LDP_ENGINE:
|
case PROC_LDP_ENGINE:
|
||||||
ldpe_if_exit(iface);
|
ldpe_if_exit(iface);
|
||||||
break;
|
break;
|
||||||
case PROC_LDE_ENGINE:
|
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:
|
case PROC_MAIN:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1468,6 +1486,29 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
|||||||
continue;
|
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 */
|
/* update existing interfaces */
|
||||||
merge_iface_af(&iface->ipv4, &xi->ipv4);
|
merge_iface_af(&iface->ipv4, &xi->ipv4);
|
||||||
merge_iface_af(&iface->ipv6, &xi->ipv6);
|
merge_iface_af(&iface->ipv6, &xi->ipv6);
|
||||||
|
@ -614,10 +614,8 @@ ldpe_dispatch_lde(struct thread *thread)
|
|||||||
map = imsg.data;
|
map = imsg.data;
|
||||||
|
|
||||||
nbr = nbr_find_peerid(imsg.hdr.peerid);
|
nbr = nbr_find_peerid(imsg.hdr.peerid);
|
||||||
if (nbr == NULL) {
|
if (nbr == NULL)
|
||||||
log_debug("ldpe_dispatch_lde: cannot find neighbor");
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
if (nbr->state != NBR_STA_OPER)
|
if (nbr->state != NBR_STA_OPER)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -641,10 +639,8 @@ ldpe_dispatch_lde(struct thread *thread)
|
|||||||
case IMSG_REQUEST_ADD_END:
|
case IMSG_REQUEST_ADD_END:
|
||||||
case IMSG_WITHDRAW_ADD_END:
|
case IMSG_WITHDRAW_ADD_END:
|
||||||
nbr = nbr_find_peerid(imsg.hdr.peerid);
|
nbr = nbr_find_peerid(imsg.hdr.peerid);
|
||||||
if (nbr == NULL) {
|
if (nbr == NULL)
|
||||||
log_debug("ldpe_dispatch_lde: cannot find neighbor");
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
if (nbr->state != NBR_STA_OPER)
|
if (nbr->state != NBR_STA_OPER)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -72,8 +72,7 @@ extern "C" {
|
|||||||
/* Maximum # labels that can be pushed. */
|
/* Maximum # labels that can be pushed. */
|
||||||
#define MPLS_MAX_LABELS 16
|
#define MPLS_MAX_LABELS 16
|
||||||
|
|
||||||
#define IS_MPLS_RESERVED_LABEL(label) \
|
#define IS_MPLS_RESERVED_LABEL(label) (label <= MPLS_LABEL_RESERVED_MAX)
|
||||||
(label >= MPLS_LABEL_RESERVED_MIN && label <= MPLS_LABEL_RESERVED_MAX)
|
|
||||||
|
|
||||||
#define IS_MPLS_UNRESERVED_LABEL(label) \
|
#define IS_MPLS_UNRESERVED_LABEL(label) \
|
||||||
(label >= MPLS_LABEL_UNRESERVED_MIN \
|
(label >= MPLS_LABEL_UNRESERVED_MIN \
|
||||||
|
Loading…
Reference in New Issue
Block a user