From 83139e57e96493d00cf46c403845c45b6ef2a37c Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Wed, 22 Mar 2017 16:23:46 -0300 Subject: ldpd: drop privileges earlier in the parent process This solves a bug where log files created with "log file" were being created root-owned. So, inserting the "log file" command multiple times with the same path would fail giving a permission denied error. Also, rearrange the main() function to call start_child() as soon as possible to avoid a bunch of unnecessary initializations in the forked processes. Signed-off-by: Renato Westphal --- ldpd/ldpd.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) (limited to 'ldpd') diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 559a2474b..f8218ec4d 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -264,31 +264,13 @@ main(int argc, char *argv[]) exit(1); } - openzlog(ldpd_di.progname, "LDP", 0, - LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); - if (lflag) lde(user, group, instance); else if (eflag) ldpe(user, group, ctl_sock_path); - master = thread_master_create(); - - cmd_init(1); - vty_config_lockless (); - vty_init(master); - vrf_init(); - access_list_init (); - ldp_vty_init(); - ldp_vty_if_init(); - - /* Get configuration file. */ - ldpd_conf = config_new_empty(); - ldp_config_reset_main(ldpd_conf, NULL); - - frr_config_fork(); - - QOBJ_REG (ldpd_conf, ldpd_conf); + openzlog(ldpd_di.progname, "LDP", 0, + LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2ldpe) == -1) fatal("socketpair"); @@ -329,9 +311,25 @@ main(int argc, char *argv[]) /* setup signal handler */ signal_init(master, array_size(ldp_signals), ldp_signals); + /* thread master */ + master = thread_master_create(); + /* library inits */ + cmd_init(1); + vty_config_lockless(); + vty_init(master); + vrf_init(); + access_list_init(); + ldp_vty_init(); + ldp_vty_if_init(); ldp_zebra_init(master); + /* Get configuration file. */ + ldpd_conf = config_new_empty(); + ldp_config_reset_main(ldpd_conf, NULL); + QOBJ_REG(ldpd_conf, ldpd_conf); + frr_config_fork(); + /* setup pipes to children */ if ((iev_ldpe = calloc(1, sizeof(struct imsgev))) == NULL || (iev_ldpe_sync = calloc(1, sizeof(struct imsgev))) == NULL || @@ -392,6 +390,7 @@ ldpd_shutdown(void) close(iev_lde->ibuf.fd); config_clear(ldpd_conf); + QOBJ_UNREG(ldpd_conf); log_debug("waiting for children to terminate"); do { @@ -1895,7 +1894,5 @@ config_clear(struct ldpd_conf *conf) xconf->trans_pref = conf->trans_pref; xconf->flags = conf->flags; merge_config(conf, xconf); - if (ldpd_process == PROC_MAIN) - QOBJ_UNREG (conf); free(conf); } -- cgit v1.2.3 From 56b8a8d231bf36a7011eb97eb115a148b3395635 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 23 Mar 2017 14:49:28 -0300 Subject: ldpd: simplify handling of configuration commands The logic to make configuration changes in ldpd is as follows: 1 - duplicate the current configuration; 2 - modify the duplicated configuration (delta); 3 - merge the duplicated configuration into the current configuration. We can however change things a little bit in order to simplify the code. If we provide a global vty_conf variable and make sure that it's always an up-to-date duplicate of ldpd_conf, then we don't need to call ldp_dup_config() in the callback of each configuration command. Instead of that, we just need to duplicate ldpd_conf in the startup of the daemon and in the end of the ldp_reload() function. Doing this is safe because, due to the single-threaded nature of the parent process, it's impossible to have multiple requests to change the configuration at the same time. Also, we can remove the *_ref() functions and do something much simpler instead. The problem we have to deal with here is that VTY_GET_CONTEXT() returns a pointer to an element of ldpd_conf, and what we want is a pointer to an element of vty_conf (e.g. an l2vpn). To solve this, we just need to look for the equivalent element inside vty_conf using standard functions from ldpd like l2vpn_find() and others. Signed-off-by: Renato Westphal --- ldpd/ldp_vty_conf.c | 214 +++++++++++++++------------------------------------- ldpd/ldpd.c | 123 +++++++++++------------------- ldpd/ldpd.h | 4 +- 3 files changed, 109 insertions(+), 232 deletions(-) (limited to 'ldpd') diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index f313bc147..68e3a3601 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -449,11 +449,8 @@ ldp_iface_is_configured(struct ldpd_conf *xconf, const char *ifname) int ldp_vty_mpls_ldp(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; int disable; - vty_conf = ldp_dup_config(ldpd_conf); - disable = (vty_get_arg_value(args, "no")) ? 1 : 0; if (disable) @@ -471,7 +468,6 @@ ldp_vty_mpls_ldp(struct vty *vty, struct vty_arg *args[]) int ldp_vty_address_family(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct ldpd_af_conf *af_conf; int af; const char *af_str; @@ -480,17 +476,14 @@ ldp_vty_address_family(struct vty *vty, struct vty_arg *args[]) disable = (vty_get_arg_value(args, "no")) ? 1 : 0; af_str = vty_get_arg_value(args, "address-family"); - vty_conf = ldp_dup_config(ldpd_conf); if (strcmp(af_str, "ipv4") == 0) { af = AF_INET; af_conf = &vty_conf->ipv4; } else if (strcmp(af_str, "ipv6") == 0) { af = AF_INET6; af_conf = &vty_conf->ipv6; - } else { - ldp_clear_config(vty_conf); + } else return (CMD_WARNING); - } if (disable) { af_conf->flags &= ~F_LDPD_AF_ENABLED; @@ -518,7 +511,6 @@ ldp_vty_address_family(struct vty *vty, struct vty_arg *args[]) int ldp_vty_disc_holdtime(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct ldpd_af_conf *af_conf; struct iface *iface; struct iface_af *ia; @@ -547,7 +539,6 @@ ldp_vty_disc_holdtime(struct vty *vty, struct vty_arg *args[]) switch (vty->node) { case LDP_NODE: - vty_conf = ldp_dup_config(ldpd_conf); if (disable) { switch (hello_type) { case HELLO_LINK: @@ -572,7 +563,6 @@ ldp_vty_disc_holdtime(struct vty *vty, struct vty_arg *args[]) break; case LDP_IPV4_NODE: case LDP_IPV6_NODE: - vty_conf = ldp_dup_config(ldpd_conf); af = ldp_vty_get_af(vty); af_conf = ldp_af_conf_get(vty_conf, af); @@ -601,14 +591,13 @@ ldp_vty_disc_holdtime(struct vty *vty, struct vty_arg *args[]) case LDP_IPV6_IFACE_NODE: af = ldp_vty_get_af(vty); iface = VTY_GET_CONTEXT(iface); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&iface); ia = iface_af_get(iface, af); if (disable) ia->hello_holdtime = 0; else ia->hello_holdtime = secs; - ldp_reload_ref(vty_conf, (void **)&iface); + ldp_reload(vty_conf); break; default: fatalx("ldp_vty_disc_holdtime: unexpected node"); @@ -620,7 +609,6 @@ ldp_vty_disc_holdtime(struct vty *vty, struct vty_arg *args[]) int ldp_vty_disc_interval(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct ldpd_af_conf *af_conf; struct iface *iface; struct iface_af *ia; @@ -650,7 +638,6 @@ ldp_vty_disc_interval(struct vty *vty, struct vty_arg *args[]) switch (vty->node) { case LDP_NODE: - vty_conf = ldp_dup_config(ldpd_conf); if (disable) { switch (hello_type) { case HELLO_LINK: @@ -675,7 +662,6 @@ ldp_vty_disc_interval(struct vty *vty, struct vty_arg *args[]) break; case LDP_IPV4_NODE: case LDP_IPV6_NODE: - vty_conf = ldp_dup_config(ldpd_conf); af = ldp_vty_get_af(vty); af_conf = ldp_af_conf_get(vty_conf, af); @@ -704,14 +690,13 @@ ldp_vty_disc_interval(struct vty *vty, struct vty_arg *args[]) case LDP_IPV6_IFACE_NODE: af = ldp_vty_get_af(vty); iface = VTY_GET_CONTEXT(iface); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&iface); ia = iface_af_get(iface, af); if (disable) ia->hello_interval = 0; else ia->hello_interval = secs; - ldp_reload_ref(vty_conf, (void **)&iface); + ldp_reload(vty_conf); break; default: fatalx("ldp_vty_disc_interval: unexpected node"); @@ -723,14 +708,11 @@ ldp_vty_disc_interval(struct vty *vty, struct vty_arg *args[]) int ldp_vty_targeted_hello_accept(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct ldpd_af_conf *af_conf; int af; const char *acl_from_str; int disable; - vty_conf = ldp_dup_config(ldpd_conf); - disable = (vty_get_arg_value(args, "no")) ? 1 : 0; acl_from_str = vty_get_arg_value(args, "from_acl"); @@ -757,7 +739,6 @@ ldp_vty_targeted_hello_accept(struct vty *vty, struct vty_arg *args[]) static int ldp_vty_nbr_session_holdtime(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; char *ep; long int secs; struct in_addr lsr_id; @@ -776,18 +757,17 @@ ldp_vty_nbr_session_holdtime(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - vty_conf = ldp_dup_config(ldpd_conf); nbrp = nbr_params_find(vty_conf, lsr_id); secs = strtol(seconds_str, &ep, 10); if (*ep != '\0' || secs < MIN_KEEPALIVE || secs > MAX_KEEPALIVE) { vty_out(vty, "%% Invalid holdtime%s", VTY_NEWLINE); - goto cancel; + return (CMD_SUCCESS); } if (disable) { if (nbrp == NULL) - goto cancel; + return (CMD_SUCCESS); nbrp->keepalive = 0; nbrp->flags &= ~F_NBRP_KEEPALIVE; @@ -796,7 +776,7 @@ ldp_vty_nbr_session_holdtime(struct vty *vty, struct vty_arg *args[]) nbrp = nbr_params_new(lsr_id); RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp); } else if (nbrp->keepalive == secs) - goto cancel; + return (CMD_SUCCESS); nbrp->keepalive = secs; nbrp->flags |= F_NBRP_KEEPALIVE; @@ -805,16 +785,11 @@ ldp_vty_nbr_session_holdtime(struct vty *vty, struct vty_arg *args[]) ldp_reload(vty_conf); return (CMD_SUCCESS); - -cancel: - ldp_clear_config(vty_conf); - return (CMD_SUCCESS); } static int ldp_vty_af_session_holdtime(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct ldpd_af_conf *af_conf; int af; char *ep; @@ -831,7 +806,6 @@ ldp_vty_af_session_holdtime(struct vty *vty, struct vty_arg *args[]) return (CMD_SUCCESS); } - vty_conf = ldp_dup_config(ldpd_conf); af = ldp_vty_get_af(vty); af_conf = ldp_af_conf_get(vty_conf, af); @@ -862,7 +836,6 @@ ldp_vty_session_holdtime(struct vty *vty, struct vty_arg *args[]) int ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; int af; struct iface *iface; struct iface_af *ia; @@ -874,17 +847,16 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) disable = (vty_get_arg_value(args, "no")) ? 1 : 0; ifname = vty_get_arg_value(args, "ifname"); - vty_conf = ldp_dup_config(ldpd_conf); af = ldp_vty_get_af(vty); iface = if_lookup_name(vty_conf, ifname); if (disable) { if (iface == NULL) - goto cancel; + return (CMD_SUCCESS); ia = iface_af_get(iface, af); if (ia->enabled == 0) - goto cancel; + return (CMD_SUCCESS); ia->enabled = 0; ia->hello_holdtime = 0; @@ -897,7 +869,7 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) if (ldp_iface_is_configured(vty_conf, ifname)) { vty_out(vty, "%% Interface is already in use%s", VTY_NEWLINE); - goto cancel; + return (CMD_SUCCESS); } ifp = if_lookup_by_name(ifname, VRF_DEFAULT); @@ -912,7 +884,7 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) ia = iface_af_get(iface, af); ia->enabled = 1; RB_INSERT(iface_head, &vty_conf->iface_tree, iface); - ldp_reload_ref(vty_conf, (void **)&iface); + ldp_reload(vty_conf); } else { memset(&kif, 0, sizeof(kif)); strlcpy(kif.ifname, ifname, sizeof(kif.ifname)); @@ -920,9 +892,8 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) ia = iface_af_get(iface, af); if (!ia->enabled) { ia->enabled = 1; - ldp_reload_ref(vty_conf, (void **)&iface); - } else - ldp_clear_config(vty_conf); + ldp_reload(vty_conf); + } } switch (af) { @@ -937,16 +908,11 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) } return (CMD_SUCCESS); - -cancel: - ldp_clear_config(vty_conf); - return (CMD_SUCCESS); } int ldp_vty_trans_addr(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct ldpd_af_conf *af_conf; int af; const char *addr_str; @@ -955,7 +921,6 @@ ldp_vty_trans_addr(struct vty *vty, struct vty_arg *args[]) disable = (vty_get_arg_value(args, "no")) ? 1 : 0; addr_str = vty_get_arg_value(args, "addr"); - vty_conf = ldp_dup_config(ldpd_conf); af = ldp_vty_get_af(vty); af_conf = ldp_af_conf_get(vty_conf, af); @@ -965,23 +930,18 @@ ldp_vty_trans_addr(struct vty *vty, struct vty_arg *args[]) if (inet_pton(af, addr_str, &af_conf->trans_addr) != 1 || bad_addr(af, &af_conf->trans_addr)) { vty_out(vty, "%% Malformed address%s", VTY_NEWLINE); - goto cancel; + return (CMD_SUCCESS); } } ldp_reload(vty_conf); return (CMD_SUCCESS); - -cancel: - ldp_clear_config(vty_conf); - return (CMD_SUCCESS); } int ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; int af; union ldpd_addr addr; struct tnbr *tnbr; @@ -1003,12 +963,11 @@ ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - vty_conf = ldp_dup_config(ldpd_conf); tnbr = tnbr_find(vty_conf, af, &addr); if (disable) { if (tnbr == NULL) - goto cancel; + return (CMD_SUCCESS); RB_REMOVE(tnbr_head, &vty_conf->tnbr_tree, tnbr); free(tnbr); @@ -1017,7 +976,7 @@ ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[]) } if (tnbr) - goto cancel; + return (CMD_SUCCESS); tnbr = tnbr_new(af, &addr); tnbr->flags |= F_TNBR_CONFIGURED; @@ -1026,16 +985,11 @@ ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[]) ldp_reload(vty_conf); return (CMD_SUCCESS); - -cancel: - ldp_clear_config(vty_conf); - return (CMD_SUCCESS); } int ldp_vty_label_advertise(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct ldpd_af_conf *af_conf; int af; const char *acl_to_str; @@ -1046,7 +1000,6 @@ ldp_vty_label_advertise(struct vty *vty, struct vty_arg *args[]) acl_to_str = vty_get_arg_value(args, "to_acl"); acl_for_str = vty_get_arg_value(args, "for_acl"); - vty_conf = ldp_dup_config(ldpd_conf); af = ldp_vty_get_af(vty); af_conf = ldp_af_conf_get(vty_conf, af); @@ -1074,7 +1027,6 @@ ldp_vty_label_advertise(struct vty *vty, struct vty_arg *args[]) int ldp_vty_label_allocate(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct ldpd_af_conf *af_conf; int af; const char *acl_for_str; @@ -1085,7 +1037,6 @@ ldp_vty_label_allocate(struct vty *vty, struct vty_arg *args[]) acl_for_str = vty_get_arg_value(args, "for_acl"); host_routes_str = vty_get_arg_value(args, "host-routes"); - vty_conf = ldp_dup_config(ldpd_conf); af = ldp_vty_get_af(vty); af_conf = ldp_af_conf_get(vty_conf, af); @@ -1107,7 +1058,6 @@ ldp_vty_label_allocate(struct vty *vty, struct vty_arg *args[]) int ldp_vty_label_expnull(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct ldpd_af_conf *af_conf; int af; const char *acl_for_str; @@ -1116,7 +1066,6 @@ ldp_vty_label_expnull(struct vty *vty, struct vty_arg *args[]) disable = (vty_get_arg_value(args, "no")) ? 1 : 0; acl_for_str = vty_get_arg_value(args, "for_acl"); - vty_conf = ldp_dup_config(ldpd_conf); af = ldp_vty_get_af(vty); af_conf = ldp_af_conf_get(vty_conf, af); @@ -1140,7 +1089,6 @@ ldp_vty_label_expnull(struct vty *vty, struct vty_arg *args[]) int ldp_vty_label_accept(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct ldpd_af_conf *af_conf; int af; const char *acl_from_str; @@ -1151,7 +1099,6 @@ ldp_vty_label_accept(struct vty *vty, struct vty_arg *args[]) acl_from_str = vty_get_arg_value(args, "from_acl"); acl_for_str = vty_get_arg_value(args, "for_acl"); - vty_conf = ldp_dup_config(ldpd_conf); af = ldp_vty_get_af(vty); af_conf = ldp_af_conf_get(vty_conf, af); @@ -1179,14 +1126,12 @@ ldp_vty_label_accept(struct vty *vty, struct vty_arg *args[]) int ldp_vty_ttl_security(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct ldpd_af_conf *af_conf; int af; int disable; disable = (vty_get_arg_value(args, "no")) ? 1 : 0; - vty_conf = ldp_dup_config(ldpd_conf); af = ldp_vty_get_af(vty); af_conf = ldp_af_conf_get(vty_conf, af); @@ -1203,44 +1148,34 @@ ldp_vty_ttl_security(struct vty *vty, struct vty_arg *args[]) int ldp_vty_router_id(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; const char *addr_str; int disable; disable = (vty_get_arg_value(args, "no")) ? 1 : 0; addr_str = vty_get_arg_value(args, "addr"); - vty_conf = ldp_dup_config(ldpd_conf); - if (disable) vty_conf->rtr_id.s_addr = INADDR_ANY; else { if (inet_pton(AF_INET, addr_str, &vty_conf->rtr_id) != 1 || bad_addr_v4(vty_conf->rtr_id)) { vty_out(vty, "%% Malformed address%s", VTY_NEWLINE); - goto cancel; + return (CMD_SUCCESS); } } ldp_reload(vty_conf); return (CMD_SUCCESS); - -cancel: - ldp_clear_config(vty_conf); - return (CMD_SUCCESS); } int ldp_vty_ds_cisco_interop(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; int disable; disable = (vty_get_arg_value(args, "no")) ? 1 : 0; - vty_conf = ldp_dup_config(ldpd_conf); - if (disable) vty_conf->flags &= ~F_LDPD_DS_CISCO_INTEROP; else @@ -1254,13 +1189,10 @@ ldp_vty_ds_cisco_interop(struct vty *vty, struct vty_arg *args[]) int ldp_vty_trans_pref_ipv4(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; int disable; disable = (vty_get_arg_value(args, "no")) ? 1 : 0; - vty_conf = ldp_dup_config(ldpd_conf); - if (disable) vty_conf->trans_pref = DUAL_STACK_LDPOV6; else @@ -1274,7 +1206,6 @@ ldp_vty_trans_pref_ipv4(struct vty *vty, struct vty_arg *args[]) int ldp_vty_neighbor_password(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct in_addr lsr_id; size_t password_len; struct nbr_params *nbrp; @@ -1292,12 +1223,11 @@ ldp_vty_neighbor_password(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - vty_conf = ldp_dup_config(ldpd_conf); nbrp = nbr_params_find(vty_conf, lsr_id); if (disable) { if (nbrp == NULL) - goto cancel; + return (CMD_SUCCESS); memset(&nbrp->auth, 0, sizeof(nbrp->auth)); nbrp->auth.method = AUTH_NONE; @@ -1307,7 +1237,7 @@ ldp_vty_neighbor_password(struct vty *vty, struct vty_arg *args[]) RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp); } else if (nbrp->auth.method == AUTH_MD5SIG && strcmp(nbrp->auth.md5key, password_str) == 0) - goto cancel; + return (CMD_SUCCESS); password_len = strlcpy(nbrp->auth.md5key, password_str, sizeof(nbrp->auth.md5key)); @@ -1321,16 +1251,11 @@ ldp_vty_neighbor_password(struct vty *vty, struct vty_arg *args[]) ldp_reload(vty_conf); return (CMD_SUCCESS); - -cancel: - ldp_clear_config(vty_conf); - return (CMD_SUCCESS); } int ldp_vty_neighbor_ttl_security(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct in_addr lsr_id; struct nbr_params *nbrp; long int hops = 0; @@ -1357,12 +1282,11 @@ ldp_vty_neighbor_ttl_security(struct vty *vty, struct vty_arg *args[]) } } - vty_conf = ldp_dup_config(ldpd_conf); nbrp = nbr_params_find(vty_conf, lsr_id); if (disable) { if (nbrp == NULL) - goto cancel; + return (CMD_SUCCESS); nbrp->flags &= ~(F_NBRP_GTSM|F_NBRP_GTSM_HOPS); nbrp->gtsm_enabled = 0; @@ -1386,16 +1310,11 @@ ldp_vty_neighbor_ttl_security(struct vty *vty, struct vty_arg *args[]) ldp_reload(vty_conf); return (CMD_SUCCESS); - -cancel: - ldp_clear_config(vty_conf); - return (CMD_SUCCESS); } int ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct l2vpn *l2vpn; const char *name_str; int disable; @@ -1403,12 +1322,11 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[]) disable = (vty_get_arg_value(args, "no")) ? 1 : 0; name_str = vty_get_arg_value(args, "name"); - vty_conf = ldp_dup_config(ldpd_conf); l2vpn = l2vpn_find(vty_conf, name_str); if (disable) { if (l2vpn == NULL) - goto cancel; + return (CMD_SUCCESS); RB_REMOVE(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn); l2vpn_del(l2vpn); @@ -1418,27 +1336,22 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[]) if (l2vpn) { VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn); - goto cancel; + return (CMD_SUCCESS); } l2vpn = l2vpn_new(name_str); l2vpn->type = L2VPN_TYPE_VPLS; RB_INSERT(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn); - ldp_reload_ref(vty_conf, (void **)&l2vpn); + ldp_reload(vty_conf); VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn); return (CMD_SUCCESS); - -cancel: - ldp_clear_config(vty_conf); - return (CMD_SUCCESS); } int ldp_vty_l2vpn_bridge(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct l2vpn *l2vpn; const char *ifname; int disable; @@ -1447,14 +1360,14 @@ ldp_vty_l2vpn_bridge(struct vty *vty, struct vty_arg *args[]) ifname = vty_get_arg_value(args, "ifname"); l2vpn = VTY_GET_CONTEXT(l2vpn); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&l2vpn); + l2vpn = l2vpn_find(vty_conf, l2vpn->name); if (disable) memset(l2vpn->br_ifname, 0, sizeof(l2vpn->br_ifname)); else strlcpy(l2vpn->br_ifname, ifname, sizeof(l2vpn->br_ifname)); - ldp_reload_ref(vty_conf, (void **)&l2vpn); + ldp_reload(vty_conf); return (CMD_SUCCESS); } @@ -1462,7 +1375,6 @@ ldp_vty_l2vpn_bridge(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_mtu(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct l2vpn *l2vpn; char *ep; int mtu; @@ -1479,14 +1391,14 @@ ldp_vty_l2vpn_mtu(struct vty *vty, struct vty_arg *args[]) } l2vpn = VTY_GET_CONTEXT(l2vpn); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&l2vpn); + l2vpn = l2vpn_find(vty_conf, l2vpn->name); if (disable) l2vpn->mtu = DEFAULT_L2VPN_MTU; else l2vpn->mtu = mtu; - ldp_reload_ref(vty_conf, (void **)&l2vpn); + ldp_reload(vty_conf); return (CMD_SUCCESS); } @@ -1494,7 +1406,6 @@ ldp_vty_l2vpn_mtu(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pwtype(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct l2vpn *l2vpn; int pw_type; const char *type_str; @@ -1509,14 +1420,14 @@ ldp_vty_l2vpn_pwtype(struct vty *vty, struct vty_arg *args[]) pw_type = PW_TYPE_ETHERNET_TAGGED; l2vpn = VTY_GET_CONTEXT(l2vpn); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&l2vpn); + l2vpn = l2vpn_find(vty_conf, l2vpn->name); if (disable) l2vpn->pw_type = DEFAULT_PW_TYPE; else l2vpn->pw_type = pw_type; - ldp_reload_ref(vty_conf, (void **)&l2vpn); + ldp_reload(vty_conf); return (CMD_SUCCESS); } @@ -1524,7 +1435,6 @@ ldp_vty_l2vpn_pwtype(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct l2vpn *l2vpn; struct l2vpn_if *lif; struct interface *ifp; @@ -1536,13 +1446,12 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) ifname = vty_get_arg_value(args, "ifname"); l2vpn = VTY_GET_CONTEXT(l2vpn); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&l2vpn); l2vpn = l2vpn_find(vty_conf, l2vpn->name); lif = l2vpn_if_find_name(l2vpn, ifname); if (disable) { if (lif == NULL) - goto cancel; + return (CMD_SUCCESS); RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); free(lif); @@ -1551,11 +1460,11 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) } if (lif) - goto cancel; + return (CMD_SUCCESS); if (ldp_iface_is_configured(vty_conf, ifname)) { vty_out(vty, "%% Interface is already in use%s", VTY_NEWLINE); - goto cancel; + return (CMD_SUCCESS); } ifp = if_lookup_by_name(ifname, VRF_DEFAULT); @@ -1569,19 +1478,14 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) lif = l2vpn_if_new(l2vpn, &kif); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); - ldp_reload_ref(vty_conf, (void **)&l2vpn); - - return (CMD_SUCCESS); + ldp_reload(vty_conf); -cancel: - ldp_clear_config(vty_conf); return (CMD_SUCCESS); } int ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; struct l2vpn *l2vpn; struct l2vpn_pw *pw; struct interface *ifp; @@ -1593,12 +1497,12 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) ifname = vty_get_arg_value(args, "ifname"); l2vpn = VTY_GET_CONTEXT(l2vpn); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&l2vpn); + l2vpn = l2vpn_find(vty_conf, l2vpn->name); pw = l2vpn_pw_find_name(l2vpn, ifname); if (disable) { if (pw == NULL) - goto cancel; + return (CMD_SUCCESS); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); free(pw); @@ -1608,12 +1512,12 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) if (pw) { VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw); - goto cancel; + return (CMD_SUCCESS); } if (ldp_iface_is_configured(vty_conf, ifname)) { vty_out(vty, "%% Interface is already in use%s", VTY_NEWLINE); - goto cancel; + return (CMD_SUCCESS); } ifp = if_lookup_by_name(ifname, VRF_DEFAULT); @@ -1628,20 +1532,16 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF; RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); - ldp_reload_ref(vty_conf, (void **)&pw); + ldp_reload(vty_conf); VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw); return (CMD_SUCCESS); - -cancel: - ldp_clear_config(vty_conf); - return (CMD_SUCCESS); } int ldp_vty_l2vpn_pw_cword(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; + struct l2vpn *l2vpn; struct l2vpn_pw *pw; const char *preference_str; int disable; @@ -1649,8 +1549,10 @@ ldp_vty_l2vpn_pw_cword(struct vty *vty, struct vty_arg *args[]) disable = (vty_get_arg_value(args, "no")) ? 1 : 0; preference_str = vty_get_arg_value(args, "preference"); + l2vpn = VTY_GET_CONTEXT(l2vpn); + l2vpn = l2vpn_find(vty_conf, l2vpn->name); pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); + pw = l2vpn_pw_find_name(l2vpn, pw->ifname); if (disable) pw->flags |= F_PW_CWORD_CONF; @@ -1661,7 +1563,7 @@ ldp_vty_l2vpn_pw_cword(struct vty *vty, struct vty_arg *args[]) pw->flags |= F_PW_CWORD_CONF; } - ldp_reload_ref(vty_conf, (void **)&pw); + ldp_reload(vty_conf); return (CMD_SUCCESS); } @@ -1669,7 +1571,7 @@ ldp_vty_l2vpn_pw_cword(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; + struct l2vpn *l2vpn; struct l2vpn_pw *pw; int af; union ldpd_addr addr; @@ -1685,8 +1587,10 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } + l2vpn = VTY_GET_CONTEXT(l2vpn); + l2vpn = l2vpn_find(vty_conf, l2vpn->name); pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); + pw = l2vpn_pw_find_name(l2vpn, pw->ifname); if (disable) { pw->af = AF_UNSPEC; @@ -1698,7 +1602,7 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[]) pw->flags |= F_PW_STATIC_NBR_ADDR; } - ldp_reload_ref(vty_conf, (void **)&pw); + ldp_reload(vty_conf); return (CMD_SUCCESS); } @@ -1706,7 +1610,7 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; + struct l2vpn *l2vpn; struct l2vpn_pw *pw; struct in_addr lsr_id; const char *lsr_id_str; @@ -1721,15 +1625,17 @@ ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } + l2vpn = VTY_GET_CONTEXT(l2vpn); + l2vpn = l2vpn_find(vty_conf, l2vpn->name); pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); + pw = l2vpn_pw_find_name(l2vpn, pw->ifname); if (disable) pw->lsr_id.s_addr = INADDR_ANY; else pw->lsr_id = lsr_id; - ldp_reload_ref(vty_conf, (void **)&pw); + ldp_reload(vty_conf); return (CMD_SUCCESS); } @@ -1737,7 +1643,7 @@ ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; + struct l2vpn *l2vpn; struct l2vpn_pw *pw; char *ep; uint32_t pwid; @@ -1753,15 +1659,17 @@ ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } + l2vpn = VTY_GET_CONTEXT(l2vpn); + l2vpn = l2vpn_find(vty_conf, l2vpn->name); pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); + pw = l2vpn_pw_find_name(l2vpn, pw->ifname); if (disable) pw->pwid = 0; else pw->pwid = pwid; - ldp_reload_ref(vty_conf, (void **)&pw); + ldp_reload(vty_conf); return (CMD_SUCCESS); } @@ -1769,21 +1677,23 @@ ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[]) int ldp_vty_l2vpn_pw_pwstatus(struct vty *vty, struct vty_arg *args[]) { - struct ldpd_conf *vty_conf; + struct l2vpn *l2vpn; struct l2vpn_pw *pw; int disable; disable = (vty_get_arg_value(args, "no")) ? 1 : 0; + l2vpn = VTY_GET_CONTEXT(l2vpn); + l2vpn = l2vpn_find(vty_conf, l2vpn->name); pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); + pw = l2vpn_pw_find_name(l2vpn, pw->ifname); if (disable) pw->flags |= F_PW_STATUSTLV_CONF; else pw->flags &= ~F_PW_STATUSTLV_CONF; - ldp_reload_ref(vty_conf, (void **)&pw); + ldp_reload(vty_conf); return (CMD_SUCCESS); } diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index f8218ec4d..c3d72d022 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -53,20 +53,19 @@ static int main_imsg_send_ipc_sockets(struct imsgbuf *, static void main_imsg_send_net_sockets(int); static void main_imsg_send_net_socket(int, enum socket_type); static int main_imsg_send_config(struct ldpd_conf *); -static void ldp_config_normalize(struct ldpd_conf *, void **); -static void ldp_config_reset_main(struct ldpd_conf *, void **); -static void ldp_config_reset_af(struct ldpd_conf *, int, void **); -static void merge_config_ref(struct ldpd_conf *, struct ldpd_conf *, void **); +static void ldp_config_normalize(struct ldpd_conf *); +static void ldp_config_reset_main(struct ldpd_conf *); +static void ldp_config_reset_af(struct ldpd_conf *, int); static void merge_global(struct ldpd_conf *, struct ldpd_conf *); static void merge_af(int, struct ldpd_af_conf *, struct ldpd_af_conf *); -static void merge_ifaces(struct ldpd_conf *, struct ldpd_conf *, void **); +static void merge_ifaces(struct ldpd_conf *, struct ldpd_conf *); static void merge_iface_af(struct iface_af *, struct iface_af *); -static void merge_tnbrs(struct ldpd_conf *, struct ldpd_conf *, void **); -static void merge_nbrps(struct ldpd_conf *, struct ldpd_conf *, void **); -static void merge_l2vpns(struct ldpd_conf *, struct ldpd_conf *, void **); +static void merge_tnbrs(struct ldpd_conf *, struct ldpd_conf *); +static void merge_nbrps(struct ldpd_conf *, struct ldpd_conf *); +static void merge_l2vpns(struct ldpd_conf *, struct ldpd_conf *); static void merge_l2vpn(struct ldpd_conf *, struct l2vpn *, - struct l2vpn *, void **); + struct l2vpn *); DEFINE_QOBJ_TYPE(iface) DEFINE_QOBJ_TYPE(tnbr) @@ -77,7 +76,7 @@ DEFINE_QOBJ_TYPE(l2vpn) DEFINE_QOBJ_TYPE(ldpd_conf) struct ldpd_global global; -struct ldpd_conf *ldpd_conf; +struct ldpd_conf *ldpd_conf, *vty_conf; static struct imsgev *iev_ldpe, *iev_ldpe_sync; static struct imsgev *iev_lde, *iev_lde_sync; @@ -324,10 +323,19 @@ main(int argc, char *argv[]) ldp_vty_if_init(); ldp_zebra_init(master); - /* Get configuration file. */ + /* create base configuration with sane defaults */ ldpd_conf = config_new_empty(); - ldp_config_reset_main(ldpd_conf, NULL); + ldp_config_reset_main(ldpd_conf); QOBJ_REG(ldpd_conf, ldpd_conf); + + /* + * Create vty_conf as a duplicate of the main configuration. All + * configuration requests (e.g. CLI) act on vty_conf and then call + * ldp_reload() to merge the changes into ldpd_conf. + */ + vty_conf = ldp_dup_config(ldpd_conf); + + /* read configuration file and daemonize */ frr_config_fork(); /* setup pipes to children */ @@ -955,37 +963,33 @@ main_imsg_send_config(struct ldpd_conf *xconf) } int -ldp_reload_ref(struct ldpd_conf *xconf, void **ref) +ldp_reload(struct ldpd_conf *xconf) { - ldp_config_normalize(xconf, ref); + ldp_config_normalize(xconf); if (main_imsg_send_config(xconf) == -1) return (-1); - merge_config_ref(ldpd_conf, xconf, ref); + merge_config(ldpd_conf, xconf); - return (0); -} + vty_conf = ldp_dup_config(ldpd_conf); -int -ldp_reload(struct ldpd_conf *xconf) -{ - return ldp_reload_ref(xconf, NULL); + return (0); } static void -ldp_config_normalize(struct ldpd_conf *xconf, void **ref) +ldp_config_normalize(struct ldpd_conf *xconf) { struct l2vpn *l2vpn; struct l2vpn_pw *pw; if (!(xconf->flags & F_LDPD_ENABLED)) - ldp_config_reset_main(xconf, ref); + ldp_config_reset_main(xconf); else { if (!(xconf->ipv4.flags & F_LDPD_AF_ENABLED)) - ldp_config_reset_af(xconf, AF_INET, ref); + ldp_config_reset_af(xconf, AF_INET); if (!(xconf->ipv6.flags & F_LDPD_AF_ENABLED)) - ldp_config_reset_af(xconf, AF_INET6, ref); + ldp_config_reset_af(xconf, AF_INET6); } RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) { @@ -1007,28 +1011,24 @@ ldp_config_normalize(struct ldpd_conf *xconf, void **ref) } static void -ldp_config_reset_main(struct ldpd_conf *conf, void **ref) +ldp_config_reset_main(struct ldpd_conf *conf) { struct iface *iface; struct nbr_params *nbrp; while ((iface = RB_ROOT(&conf->iface_tree)) != NULL) { - if (ref && *ref == iface) - *ref = NULL; RB_REMOVE(iface_head, &conf->iface_tree, iface); free(iface); } while ((nbrp = RB_ROOT(&conf->nbrp_tree)) != NULL) { - if (ref && *ref == nbrp) - *ref = NULL; RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp); free(nbrp); } conf->rtr_id.s_addr = INADDR_ANY; - ldp_config_reset_af(conf, AF_INET, ref); - ldp_config_reset_af(conf, AF_INET6, ref); + ldp_config_reset_af(conf, AF_INET); + ldp_config_reset_af(conf, AF_INET6); conf->lhello_holdtime = LINK_DFLT_HOLDTIME; conf->lhello_interval = DEFAULT_HELLO_INTERVAL; conf->thello_holdtime = TARGETED_DFLT_HOLDTIME; @@ -1038,7 +1038,7 @@ ldp_config_reset_main(struct ldpd_conf *conf, void **ref) } static void -ldp_config_reset_af(struct ldpd_conf *conf, int af, void **ref) +ldp_config_reset_af(struct ldpd_conf *conf, int af) { struct ldpd_af_conf *af_conf; struct iface *iface; @@ -1054,8 +1054,6 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af, void **ref) if (tnbr->af != af) continue; - if (ref && *ref == tnbr) - *ref = NULL; RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr); free(tnbr); } @@ -1071,7 +1069,7 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af, void **ref) } struct ldpd_conf * -ldp_dup_config_ref(struct ldpd_conf *conf, void **ref) +ldp_dup_config(struct ldpd_conf *conf) { struct ldpd_conf *xconf; struct iface *iface, *xi; @@ -1086,7 +1084,6 @@ ldp_dup_config_ref(struct ldpd_conf *conf, void **ref) if (a == NULL) \ fatal(__func__); \ *a = *b; \ - if (ref && *ref == b) *ref = a; \ } while (0) COPY(xconf, conf); @@ -1137,12 +1134,6 @@ ldp_dup_config_ref(struct ldpd_conf *conf, void **ref) return (xconf); } -struct ldpd_conf * -ldp_dup_config(struct ldpd_conf *conf) -{ - return ldp_dup_config_ref(conf, NULL); -} - void ldp_clear_config(struct ldpd_conf *xconf) { @@ -1171,27 +1162,19 @@ ldp_clear_config(struct ldpd_conf *xconf) free(xconf); } -static void -merge_config_ref(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) +void +merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf) { merge_global(conf, xconf); merge_af(AF_INET, &conf->ipv4, &xconf->ipv4); merge_af(AF_INET6, &conf->ipv6, &xconf->ipv6); - merge_ifaces(conf, xconf, ref); - merge_tnbrs(conf, xconf, ref); - merge_nbrps(conf, xconf, ref); - merge_l2vpns(conf, xconf, ref); - if (ref && *ref == xconf) - *ref = conf; + merge_ifaces(conf, xconf); + merge_tnbrs(conf, xconf); + merge_nbrps(conf, xconf); + merge_l2vpns(conf, xconf); free(xconf); } -void -merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf) -{ - merge_config_ref(conf, xconf, NULL); -} - static void merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf) { @@ -1326,7 +1309,7 @@ merge_af(int af, struct ldpd_af_conf *af_conf, struct ldpd_af_conf *xa) } static void -merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) +merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf) { struct iface *iface, *itmp, *xi; @@ -1366,8 +1349,6 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) merge_iface_af(&iface->ipv4, &xi->ipv4); merge_iface_af(&iface->ipv6, &xi->ipv6); RB_REMOVE(iface_head, &xconf->iface_tree, xi); - if (ref && *ref == xi) - *ref = iface; free(xi); } } @@ -1385,7 +1366,7 @@ merge_iface_af(struct iface_af *ia, struct iface_af *xi) } static void -merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) +merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf) { struct tnbr *tnbr, *ttmp, *xt; @@ -1435,14 +1416,12 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) if (!(tnbr->flags & F_TNBR_CONFIGURED)) tnbr->flags |= F_TNBR_CONFIGURED; RB_REMOVE(tnbr_head, &xconf->tnbr_tree, xt); - if (ref && *ref == xt) - *ref = tnbr; free(xt); } } static void -merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) +merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) { struct nbr_params *nbrp, *ntmp, *xn; struct nbr *nbr; @@ -1554,14 +1533,12 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) } } RB_REMOVE(nbrp_head, &xconf->nbrp_tree, xn); - if (ref && *ref == xn) - *ref = nbrp; free(xn); } } static void -merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) +merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf) { struct l2vpn *l2vpn, *ltmp, *xl; struct l2vpn_if *lif; @@ -1613,16 +1590,14 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) } /* update existing l2vpns */ - merge_l2vpn(conf, l2vpn, xl, ref); + merge_l2vpn(conf, l2vpn, xl); RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl); - if (ref && *ref == xl) - *ref = l2vpn; free(xl); } } static void -merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void **ref) +merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) { struct l2vpn_if *lif, *ftmp, *xf; struct l2vpn_pw *pw, *ptmp, *xp; @@ -1656,8 +1631,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void } RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf); - if (ref && *ref == xf) - *ref = lif; free(xf); } @@ -1788,8 +1761,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void } RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp); - if (ref && *ref == xp) - *ref = pw; free(xp); } @@ -1842,8 +1813,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void } RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp); - if (ref && *ref == xp) - *ref = pw; free(xp); } diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index a8279ebf6..69235556f 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -645,7 +645,7 @@ struct ctl_pw { uint32_t status; }; -extern struct ldpd_conf *ldpd_conf; +extern struct ldpd_conf *ldpd_conf, *vty_conf; extern struct ldpd_global global; /* parse.y */ @@ -705,8 +705,6 @@ struct ldpd_af_global *ldp_af_global_get(struct ldpd_global *, int); int ldp_is_dual_stack(struct ldpd_conf *); in_addr_t ldp_rtr_id_get(struct ldpd_conf *); int ldp_reload(struct ldpd_conf *); -int ldp_reload_ref(struct ldpd_conf *, void **); -struct ldpd_conf *ldp_dup_config_ref(struct ldpd_conf *, void **ref); struct ldpd_conf *ldp_dup_config(struct ldpd_conf *); void ldp_clear_config(struct ldpd_conf *); void merge_config(struct ldpd_conf *, struct ldpd_conf *); -- cgit v1.2.3 From 1e7e440f5a5555b286e9b6265e9e481d11123fcd Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 25 Mar 2017 21:28:13 -0300 Subject: ldpd: ignore the SIGHUP signal in the child processes Only the parent process should handle the SIGHUP signal, but we need to make sure that this signal is ignored in the child processes so a command like "killall -SIGHUP ldpd" won't kill ldpd. Signed-off-by: Renato Westphal --- ldpd/lde.c | 4 ++++ ldpd/ldpe.c | 4 ++++ lib/sigevent.c | 3 ++- 3 files changed, 10 insertions(+), 1 deletion(-) (limited to 'ldpd') diff --git a/ldpd/lde.c b/ldpd/lde.c index 3247c8c1c..e927e4536 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -105,6 +105,10 @@ sigint(void) static struct quagga_signal_t lde_signals[] = { + { + .signal = SIGHUP, + /* ignore */ + }, { .signal = SIGINT, .handler = &sigint, diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 6c542c5e3..ada732d6f 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -87,6 +87,10 @@ sigint(void) static struct quagga_signal_t ldpe_signals[] = { + { + .signal = SIGHUP, + /* ignore */ + }, { .signal = SIGINT, .handler = &sigint, diff --git a/lib/sigevent.c b/lib/sigevent.c index a120028d8..09f07180c 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -108,7 +108,8 @@ quagga_sigevent_process (void) if (sig->caught > 0) { sig->caught = 0; - sig->handler (); + if (sig->handler) + sig->handler (); } } } -- cgit v1.2.3 From dbce358222e5483140389795f790cfabd93808e1 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Wed, 22 Mar 2017 12:53:36 -0300 Subject: ldpd: do a full configuration reload upon receiving a SIGHUP The rationale here is to do something very similar to what the original OpenBSD's ldpd(8) does to reload configuration files: * create a new empty base configuration (vty_conf); * parse the configuration file and store the result in vty_conf; * merge the new configuration into the current configuration. To do this, introduce a new global variable called "sighup" so that ldpd doesn't attempt to merge vty_conf into ldpd_conf for each command in the configuration file, which would be very disruptive. vty_conf should be merged only after the whole configuration file is parsed in order to avoid taking actions like shutting down neighbors when not necessary. Signed-off-by: Renato Westphal --- ldpd/ldp_vty_conf.c | 172 ++++++++++++++++++++++++++++++++++++++++------------ ldpd/ldpd.c | 21 +++++++ ldpd/ldpd.h | 1 + 3 files changed, 156 insertions(+), 38 deletions(-) (limited to 'ldpd') diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index 68e3a3601..f2b7d6f36 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -37,11 +37,17 @@ static void ldp_af_iface_config_write(struct vty *, int); static void ldp_af_config_write(struct vty *, int, struct ldpd_conf *, struct ldpd_af_conf *); static void ldp_l2vpn_pw_config_write(struct vty *, struct l2vpn_pw *); +static void ldp_vty_push_node(struct vty *, int, void *); +static void *ldp_vty_get_node(struct vty *, void *, int); static int ldp_vty_get_af(struct vty *); static int ldp_iface_is_configured(struct ldpd_conf *, const char *); static int ldp_vty_nbr_session_holdtime(struct vty *, struct vty_arg *[]); static int ldp_vty_af_session_holdtime(struct vty *, struct vty_arg *[]); +static struct iface *vty_iface; +static struct l2vpn *vty_l2vpn; +static struct l2vpn_pw *vty_pw; + static struct cmd_node interface_node = { INTERFACE_NODE, @@ -413,6 +419,94 @@ ldp_l2vpn_config_write(struct vty *vty) return (0); } +void +ldp_vty_push_node(struct vty *vty, int node, void *ptr) +{ + if (global.sighup) { + switch (node) { + case LDP_IPV4_IFACE_NODE: + case LDP_IPV6_IFACE_NODE: + vty_iface = ptr; + break; + case LDP_L2VPN_NODE: + vty_l2vpn = ptr; + break; + case LDP_PSEUDOWIRE_NODE: + vty_pw = ptr; + break; + default: + fatalx("ldp_vty_push_node: unexpected node"); + } + vty->node = node; + return; + } + + switch (node) { + case LDP_IPV4_IFACE_NODE: + case LDP_IPV6_IFACE_NODE: + VTY_PUSH_CONTEXT(node, (struct iface *)ptr); + break; + case LDP_L2VPN_NODE: + VTY_PUSH_CONTEXT(node, (struct l2vpn *)ptr); + break; + case LDP_PSEUDOWIRE_NODE: + VTY_PUSH_CONTEXT_SUB(node, (struct l2vpn_pw *)ptr); + break; + default: + fatalx("ldp_vty_push_node: unexpected node"); + } +} + +void * +ldp_vty_get_node(struct vty *vty, void *parent, int node) +{ + struct iface *iface; + struct l2vpn *l2vpn; + struct l2vpn_pw *pw; + + if (global.sighup) { + switch (node) { + case LDP_IPV4_IFACE_NODE: + case LDP_IPV6_IFACE_NODE: + return (vty_iface); + case LDP_L2VPN_NODE: + return (vty_l2vpn); + case LDP_PSEUDOWIRE_NODE: + return (vty_pw); + default: + fatalx("ldp_vty_get_node: unexpected node"); + } + } + + /* + * Since VTY_GET_CONTEXT() returns a pointer to an element of ldpd_conf, + * we have to find the equivalent element inside vty_conf (which should + * always exist as vty_conf is a duplicate of ldpd_conf). + */ + switch (node) { + case LDP_IPV4_IFACE_NODE: + case LDP_IPV6_IFACE_NODE: + iface = VTY_GET_CONTEXT(iface); + if (iface) + return (if_lookup_name(vty_conf, iface->name)); + break; + case LDP_L2VPN_NODE: + l2vpn = VTY_GET_CONTEXT(l2vpn); + if (l2vpn) + return (l2vpn_find(vty_conf, l2vpn->name)); + break; + case LDP_PSEUDOWIRE_NODE: + pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); + if (pw) + return (l2vpn_pw_find_name(parent, pw->ifname)); + break; + default: + fatalx("ldp_vty_get_node: unexpected node"); + } + + return (NULL); +} + static int ldp_vty_get_af(struct vty *vty) { @@ -590,7 +684,8 @@ ldp_vty_disc_holdtime(struct vty *vty, struct vty_arg *args[]) case LDP_IPV4_IFACE_NODE: case LDP_IPV6_IFACE_NODE: af = ldp_vty_get_af(vty); - iface = VTY_GET_CONTEXT(iface); + iface = ldp_vty_get_node(vty, NULL, vty->node); + VTY_CHECK_CONTEXT(iface); ia = iface_af_get(iface, af); if (disable) @@ -689,7 +784,8 @@ ldp_vty_disc_interval(struct vty *vty, struct vty_arg *args[]) case LDP_IPV4_IFACE_NODE: case LDP_IPV6_IFACE_NODE: af = ldp_vty_get_af(vty); - iface = VTY_GET_CONTEXT(iface); + iface = ldp_vty_get_node(vty, NULL, vty->node); + VTY_CHECK_CONTEXT(iface); ia = iface_af_get(iface, af); if (disable) @@ -898,10 +994,10 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) switch (af) { case AF_INET: - VTY_PUSH_CONTEXT(LDP_IPV4_IFACE_NODE, iface); + ldp_vty_push_node(vty, LDP_IPV4_IFACE_NODE, iface); break; case AF_INET6: - VTY_PUSH_CONTEXT(LDP_IPV6_IFACE_NODE, iface); + ldp_vty_push_node(vty, LDP_IPV6_IFACE_NODE, iface); break; default: break; @@ -1335,7 +1431,7 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[]) } if (l2vpn) { - VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn); + ldp_vty_push_node(vty, LDP_L2VPN_NODE, l2vpn); return (CMD_SUCCESS); } @@ -1344,7 +1440,7 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[]) RB_INSERT(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn); ldp_reload(vty_conf); - VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn); + ldp_vty_push_node(vty, LDP_L2VPN_NODE, l2vpn); return (CMD_SUCCESS); } @@ -1359,8 +1455,8 @@ ldp_vty_l2vpn_bridge(struct vty *vty, struct vty_arg *args[]) disable = (vty_get_arg_value(args, "no")) ? 1 : 0; ifname = vty_get_arg_value(args, "ifname"); - l2vpn = VTY_GET_CONTEXT(l2vpn); - l2vpn = l2vpn_find(vty_conf, l2vpn->name); + l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); + VTY_CHECK_CONTEXT(l2vpn); if (disable) memset(l2vpn->br_ifname, 0, sizeof(l2vpn->br_ifname)); @@ -1390,8 +1486,8 @@ ldp_vty_l2vpn_mtu(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - l2vpn = VTY_GET_CONTEXT(l2vpn); - l2vpn = l2vpn_find(vty_conf, l2vpn->name); + l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); + VTY_CHECK_CONTEXT(l2vpn); if (disable) l2vpn->mtu = DEFAULT_L2VPN_MTU; @@ -1419,8 +1515,8 @@ ldp_vty_l2vpn_pwtype(struct vty *vty, struct vty_arg *args[]) else pw_type = PW_TYPE_ETHERNET_TAGGED; - l2vpn = VTY_GET_CONTEXT(l2vpn); - l2vpn = l2vpn_find(vty_conf, l2vpn->name); + l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); + VTY_CHECK_CONTEXT(l2vpn); if (disable) l2vpn->pw_type = DEFAULT_PW_TYPE; @@ -1445,8 +1541,8 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) disable = (vty_get_arg_value(args, "no")) ? 1 : 0; ifname = vty_get_arg_value(args, "ifname"); - l2vpn = VTY_GET_CONTEXT(l2vpn); - l2vpn = l2vpn_find(vty_conf, l2vpn->name); + l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); + VTY_CHECK_CONTEXT(l2vpn); lif = l2vpn_if_find_name(l2vpn, ifname); if (disable) { @@ -1496,8 +1592,8 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) disable = (vty_get_arg_value(args, "no")) ? 1 : 0; ifname = vty_get_arg_value(args, "ifname"); - l2vpn = VTY_GET_CONTEXT(l2vpn); - l2vpn = l2vpn_find(vty_conf, l2vpn->name); + l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); + VTY_CHECK_CONTEXT(l2vpn); pw = l2vpn_pw_find_name(l2vpn, ifname); if (disable) { @@ -1511,7 +1607,7 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) } if (pw) { - VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw); + ldp_vty_push_node(vty, LDP_PSEUDOWIRE_NODE, pw); return (CMD_SUCCESS); } @@ -1533,7 +1629,7 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); ldp_reload(vty_conf); - VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw); + ldp_vty_push_node(vty, LDP_PSEUDOWIRE_NODE, pw); return (CMD_SUCCESS); } @@ -1549,10 +1645,10 @@ ldp_vty_l2vpn_pw_cword(struct vty *vty, struct vty_arg *args[]) disable = (vty_get_arg_value(args, "no")) ? 1 : 0; preference_str = vty_get_arg_value(args, "preference"); - l2vpn = VTY_GET_CONTEXT(l2vpn); - l2vpn = l2vpn_find(vty_conf, l2vpn->name); - pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - pw = l2vpn_pw_find_name(l2vpn, pw->ifname); + l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); + VTY_CHECK_CONTEXT(l2vpn); + pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE); + VTY_CHECK_CONTEXT(pw); if (disable) pw->flags |= F_PW_CWORD_CONF; @@ -1587,10 +1683,10 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - l2vpn = VTY_GET_CONTEXT(l2vpn); - l2vpn = l2vpn_find(vty_conf, l2vpn->name); - pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - pw = l2vpn_pw_find_name(l2vpn, pw->ifname); + l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); + VTY_CHECK_CONTEXT(l2vpn); + pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE); + VTY_CHECK_CONTEXT(pw); if (disable) { pw->af = AF_UNSPEC; @@ -1625,10 +1721,10 @@ ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - l2vpn = VTY_GET_CONTEXT(l2vpn); - l2vpn = l2vpn_find(vty_conf, l2vpn->name); - pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - pw = l2vpn_pw_find_name(l2vpn, pw->ifname); + l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); + VTY_CHECK_CONTEXT(l2vpn); + pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE); + VTY_CHECK_CONTEXT(pw); if (disable) pw->lsr_id.s_addr = INADDR_ANY; @@ -1659,10 +1755,10 @@ ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - l2vpn = VTY_GET_CONTEXT(l2vpn); - l2vpn = l2vpn_find(vty_conf, l2vpn->name); - pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - pw = l2vpn_pw_find_name(l2vpn, pw->ifname); + l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); + VTY_CHECK_CONTEXT(l2vpn); + pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE); + VTY_CHECK_CONTEXT(pw); if (disable) pw->pwid = 0; @@ -1683,10 +1779,10 @@ ldp_vty_l2vpn_pw_pwstatus(struct vty *vty, struct vty_arg *args[]) disable = (vty_get_arg_value(args, "no")) ? 1 : 0; - l2vpn = VTY_GET_CONTEXT(l2vpn); - l2vpn = l2vpn_find(vty_conf, l2vpn->name); - pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - pw = l2vpn_pw_find_name(l2vpn, pw->ifname); + l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); + VTY_CHECK_CONTEXT(l2vpn); + pw = ldp_vty_get_node(vty, l2vpn, LDP_PSEUDOWIRE_NODE); + VTY_CHECK_CONTEXT(pw); if (disable) pw->flags |= F_PW_STATUSTLV_CONF; diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index c3d72d022..96ae5ad87 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -89,6 +89,8 @@ static pid_t lde_pid; /* Master of threads. */ struct thread_master *master; +static struct frr_daemon_info ldpd_di; + /* ldpd privileges */ static zebra_capabilities_t _caps_p [] = { @@ -127,6 +129,22 @@ static void sighup(void) { log_info("SIGHUP received"); + + /* reset vty_conf */ + ldp_clear_config(vty_conf); + vty_conf = config_new_empty(); + ldp_config_reset_main(vty_conf); + + /* read configuration file without applying any changes */ + global.sighup = 1; + vty_read_config(ldpd_di.config_file, config_default); + global.sighup = 0; + + /* + * Apply the new configuration all at once, this way merge_config() + * will be the least disruptive as possible. + */ + ldp_reload(vty_conf); } /* SIGINT / SIGTERM handler. */ @@ -965,6 +983,9 @@ main_imsg_send_config(struct ldpd_conf *xconf) int ldp_reload(struct ldpd_conf *xconf) { + if (global.sighup) + return (0); + ldp_config_normalize(xconf); if (main_imsg_send_config(xconf) == -1) diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index 69235556f..a0474a5a2 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -503,6 +503,7 @@ struct ldpd_af_global { struct ldpd_global { int cmd_opts; + int sighup; time_t uptime; struct in_addr rtr_id; struct ldpd_af_global ipv4; -- cgit v1.2.3 From 52bd4c2321f49bec42ca466f5c395e78e6d7acc6 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 25 Mar 2017 20:52:42 -0300 Subject: ldpd: remove a few unnecessary functions The original ldpd(8) daemon in OpenBSD doesn't allow the user to put non-existing interfaces in the configuration file. For this reason, the l2vpn_if_find() and l2vpn_pw_find() functions take an ifindex as an argument. In FRR's ldpd we can put non-existing interfaces in the configuration, and they are activated as soon as they are available. For this reason, we can't lookup interfaces by their ifindex in this port. The l2vpn_if_find_name() and l2vpn_pw_find_name() functions were introduced to address this issue. However, since the "find-by-ifindex" functions are not being used anymore, we can just remove them and rename the *_find_name() functions removing the "_name" suffix. Signed-off-by: Renato Westphal --- ldpd/l2vpn.c | 31 ++----------------------------- ldpd/lde.h | 6 ++---- ldpd/ldp_vty_conf.c | 10 +++++----- ldpd/ldpd.c | 12 ++++++------ ldpd/ldpe.c | 2 +- 5 files changed, 16 insertions(+), 45 deletions(-) (limited to 'ldpd') diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c index 2516e6275..29302c465 100644 --- a/ldpd/l2vpn.c +++ b/ldpd/l2vpn.c @@ -133,19 +133,7 @@ l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif) } struct l2vpn_if * -l2vpn_if_find(struct l2vpn *l2vpn, unsigned int ifindex) -{ - struct l2vpn_if *lif; - - RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) - if (lif->ifindex == ifindex) - return (lif); - - return (NULL); -} - -struct l2vpn_if * -l2vpn_if_find_name(struct l2vpn *l2vpn, const char *ifname) +l2vpn_if_find(struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_if lif; strlcpy(lif.ifname, ifname, sizeof(lif.ifname)); @@ -201,22 +189,7 @@ l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif) } struct l2vpn_pw * -l2vpn_pw_find(struct l2vpn *l2vpn, unsigned int ifindex) -{ - struct l2vpn_pw *pw; - - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) - if (pw->ifindex == ifindex) - return (pw); - RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) - if (pw->ifindex == ifindex) - return (pw); - - return (NULL); -} - -struct l2vpn_pw * -l2vpn_pw_find_name(struct l2vpn *l2vpn, const char *ifname) +l2vpn_pw_find(struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_pw *pw; struct l2vpn_pw s; diff --git a/ldpd/lde.h b/ldpd/lde.h index d9836097a..9ab20e45e 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -213,12 +213,10 @@ void l2vpn_del(struct l2vpn *); void l2vpn_init(struct l2vpn *); void l2vpn_exit(struct l2vpn *); struct l2vpn_if *l2vpn_if_new(struct l2vpn *, struct kif *); -struct l2vpn_if *l2vpn_if_find(struct l2vpn *, unsigned int); -struct l2vpn_if *l2vpn_if_find_name(struct l2vpn *, const char *); +struct l2vpn_if *l2vpn_if_find(struct l2vpn *, const char *); void l2vpn_if_update(struct l2vpn_if *); struct l2vpn_pw *l2vpn_pw_new(struct l2vpn *, struct kif *); -struct l2vpn_pw *l2vpn_pw_find(struct l2vpn *, unsigned int); -struct l2vpn_pw *l2vpn_pw_find_name(struct l2vpn *, const char *); +struct l2vpn_pw *l2vpn_pw_find(struct l2vpn *, const char *); void l2vpn_pw_init(struct l2vpn_pw *); void l2vpn_pw_exit(struct l2vpn_pw *); void l2vpn_pw_reset(struct l2vpn_pw *); diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index f2b7d6f36..bab5e1736 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -498,7 +498,7 @@ ldp_vty_get_node(struct vty *vty, void *parent, int node) case LDP_PSEUDOWIRE_NODE: pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); if (pw) - return (l2vpn_pw_find_name(parent, pw->ifname)); + return (l2vpn_pw_find(parent, pw->ifname)); break; default: fatalx("ldp_vty_get_node: unexpected node"); @@ -531,9 +531,9 @@ ldp_iface_is_configured(struct ldpd_conf *xconf, const char *ifname) return (1); RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) { - if (l2vpn_if_find_name(l2vpn, ifname)) + if (l2vpn_if_find(l2vpn, ifname)) return (1); - if (l2vpn_pw_find_name(l2vpn, ifname)) + if (l2vpn_pw_find(l2vpn, ifname)) return (1); } @@ -1543,7 +1543,7 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); VTY_CHECK_CONTEXT(l2vpn); - lif = l2vpn_if_find_name(l2vpn, ifname); + lif = l2vpn_if_find(l2vpn, ifname); if (disable) { if (lif == NULL) @@ -1594,7 +1594,7 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); VTY_CHECK_CONTEXT(l2vpn); - pw = l2vpn_pw_find_name(l2vpn, ifname); + pw = l2vpn_pw_find(l2vpn, ifname); if (disable) { if (pw == NULL) diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 96ae5ad87..0f18c6e31 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -1633,7 +1633,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) /* merge intefaces */ RB_FOREACH_SAFE(lif, l2vpn_if_head, &l2vpn->if_tree, ftmp) { /* find deleted interfaces */ - if ((xf = l2vpn_if_find_name(xl, lif->ifname)) == NULL) { + if ((xf = l2vpn_if_find(xl, lif->ifname)) == NULL) { if (ldpd_process == PROC_MAIN) QOBJ_UNREG (lif); RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); @@ -1642,7 +1642,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) } RB_FOREACH_SAFE(xf, l2vpn_if_head, &xl->if_tree, ftmp) { /* find new interfaces */ - if ((lif = l2vpn_if_find_name(l2vpn, xf->ifname)) == NULL) { + if ((lif = l2vpn_if_find(l2vpn, xf->ifname)) == NULL) { RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf); RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, xf); xf->l2vpn = l2vpn; @@ -1659,7 +1659,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) RB_INIT(&pw_aux_list); RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_tree, ptmp) { /* find deleted active pseudowires */ - if ((xp = l2vpn_pw_find_name(xl, pw->ifname)) == NULL) { + if ((xp = l2vpn_pw_find(xl, pw->ifname)) == NULL) { switch (ldpd_process) { case PROC_LDE_ENGINE: l2vpn_pw_exit(pw); @@ -1678,7 +1678,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) } RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_tree, ptmp) { /* find new active pseudowires */ - if ((pw = l2vpn_pw_find_name(l2vpn, xp->ifname)) == NULL) { + if ((pw = l2vpn_pw_find(l2vpn, xp->ifname)) == NULL) { RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp); RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, xp); xp->l2vpn = l2vpn; @@ -1788,7 +1788,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) /* merge inactive pseudowires */ RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree, ptmp) { /* find deleted inactive pseudowires */ - if ((xp = l2vpn_pw_find_name(xl, pw->ifname)) == NULL) { + if ((xp = l2vpn_pw_find(xl, pw->ifname)) == NULL) { RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); if (ldpd_process == PROC_MAIN) QOBJ_UNREG (pw); @@ -1797,7 +1797,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) } RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_inactive_tree, ptmp) { /* find new inactive pseudowires */ - if ((pw = l2vpn_pw_find_name(l2vpn, xp->ifname)) == NULL) { + if ((pw = l2vpn_pw_find(l2vpn, xp->ifname)) == NULL) { RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp); RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, xp); xp->l2vpn = l2vpn; diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index ada732d6f..96a7052ec 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -303,7 +303,7 @@ ldpe_dispatch_main(struct thread *thread) } RB_FOREACH(l2vpn, l2vpn_head, &leconf->l2vpn_tree) { - lif = l2vpn_if_find_name(l2vpn, kif->ifname); + lif = l2vpn_if_find(l2vpn, kif->ifname); if (lif) { lif->flags = kif->flags; memcpy(lif->mac, kif->mac, -- cgit v1.2.3 From 5c3f00af13f1ac4f61dc7126741f7fd6e032151f Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Sat, 25 Mar 2017 20:57:03 -0300 Subject: ldpd: fix pseudowire merge algorithm The previous algorithm wasn't failsafe for full configuration reloads where several pseudowires can be inserted or removed at the same time. This patch introduces a much simpler logic that solves the problem in a better way. Signed-off-by: Renato Westphal --- ldpd/l2vpn.c | 18 +++++++++++++++ ldpd/lde.h | 2 ++ ldpd/ldpd.c | 72 +++++++++++++++++------------------------------------------- 3 files changed, 40 insertions(+), 52 deletions(-) (limited to 'ldpd') diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c index 29302c465..ca40636e0 100644 --- a/ldpd/l2vpn.c +++ b/ldpd/l2vpn.c @@ -201,6 +201,24 @@ l2vpn_pw_find(struct l2vpn *l2vpn, const char *ifname) return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s)); } +struct l2vpn_pw * +l2vpn_pw_find_active(struct l2vpn *l2vpn, const char *ifname) +{ + struct l2vpn_pw s; + + strlcpy(s.ifname, ifname, sizeof(s.ifname)); + return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_tree, &s)); +} + +struct l2vpn_pw * +l2vpn_pw_find_inactive(struct l2vpn *l2vpn, const char *ifname) +{ + struct l2vpn_pw s; + + strlcpy(s.ifname, ifname, sizeof(s.ifname)); + return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s)); +} + void l2vpn_pw_init(struct l2vpn_pw *pw) { diff --git a/ldpd/lde.h b/ldpd/lde.h index 9ab20e45e..d1089b44f 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -217,6 +217,8 @@ struct l2vpn_if *l2vpn_if_find(struct l2vpn *, const char *); void l2vpn_if_update(struct l2vpn_if *); struct l2vpn_pw *l2vpn_pw_new(struct l2vpn *, struct kif *); struct l2vpn_pw *l2vpn_pw_find(struct l2vpn *, const char *); +struct l2vpn_pw *l2vpn_pw_find_active(struct l2vpn *, const char *); +struct l2vpn_pw *l2vpn_pw_find_inactive(struct l2vpn *, const char *); void l2vpn_pw_init(struct l2vpn_pw *); void l2vpn_pw_exit(struct l2vpn_pw *); void l2vpn_pw_reset(struct l2vpn_pw *); diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 0f18c6e31..3023d9446 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -1591,6 +1591,22 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf) } } RB_FOREACH_SAFE(xl, l2vpn_head, &xconf->l2vpn_tree, ltmp) { + struct l2vpn_pw *xp, *ptmp; + + /* check if the pseudowires should be enabled or disabled */ + RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_tree, ptmp) { + if (xp->lsr_id.s_addr != INADDR_ANY && xp->pwid != 0) + continue; + RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp); + RB_INSERT(l2vpn_pw_head, &xl->pw_inactive_tree, xp); + } + RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_inactive_tree, ptmp) { + if (xp->lsr_id.s_addr == INADDR_ANY || xp->pwid == 0) + continue; + RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp); + RB_INSERT(l2vpn_pw_head, &xl->pw_tree, xp); + } + /* find new l2vpns */ if ((l2vpn = l2vpn_find(conf, xl->name)) == NULL) { RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl); @@ -1624,7 +1640,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) struct l2vpn_pw *pw, *ptmp, *xp; struct nbr *nbr; int reset_nbr, reinstall_pwfec, reinstall_tnbr; - struct l2vpn_pw_head pw_aux_list; int previous_pw_type, previous_mtu; previous_pw_type = l2vpn->pw_type; @@ -1656,10 +1671,9 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) } /* merge active pseudowires */ - RB_INIT(&pw_aux_list); RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_tree, ptmp) { /* find deleted active pseudowires */ - if ((xp = l2vpn_pw_find(xl, pw->ifname)) == NULL) { + if ((xp = l2vpn_pw_find_active(xl, pw->ifname)) == NULL) { switch (ldpd_process) { case PROC_LDE_ENGINE: l2vpn_pw_exit(pw); @@ -1678,7 +1692,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) } RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_tree, ptmp) { /* find new active pseudowires */ - if ((pw = l2vpn_pw_find(l2vpn, xp->ifname)) == NULL) { + if ((pw = l2vpn_pw_find_active(l2vpn, xp->ifname)) == NULL) { RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp); RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, xp); xp->l2vpn = l2vpn; @@ -1718,28 +1732,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) else reinstall_pwfec = 0; - /* check if the pseudowire should be disabled */ - if (xp->lsr_id.s_addr == INADDR_ANY || xp->pwid == 0) { - reinstall_tnbr = 0; - reset_nbr = 0; - reinstall_pwfec = 0; - - switch (ldpd_process) { - case PROC_LDE_ENGINE: - l2vpn_pw_exit(pw); - break; - case PROC_LDP_ENGINE: - ldpe_l2vpn_pw_exit(pw); - break; - case PROC_MAIN: - break; - } - - /* remove from active list */ - RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw); - RB_INSERT(l2vpn_pw_head, &pw_aux_list, pw); - } - if (ldpd_process == PROC_LDP_ENGINE) { if (reinstall_tnbr) ldpe_l2vpn_pw_exit(pw); @@ -1788,7 +1780,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) /* merge inactive pseudowires */ RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree, ptmp) { /* find deleted inactive pseudowires */ - if ((xp = l2vpn_pw_find(xl, pw->ifname)) == NULL) { + if ((xp = l2vpn_pw_find_inactive(xl, pw->ifname)) == NULL) { RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); if (ldpd_process == PROC_MAIN) QOBJ_UNREG (pw); @@ -1797,7 +1789,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) } RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_inactive_tree, ptmp) { /* find new inactive pseudowires */ - if ((pw = l2vpn_pw_find(l2vpn, xp->ifname)) == NULL) { + if ((pw = l2vpn_pw_find_inactive(l2vpn, xp->ifname)) == NULL) { RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp); RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, xp); xp->l2vpn = l2vpn; @@ -1815,34 +1807,10 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) pw->ifindex = xp->ifindex; pw->flags = xp->flags; - /* check if the pseudowire should be activated */ - if (pw->lsr_id.s_addr != INADDR_ANY && pw->pwid != 0) { - /* remove from inactive list */ - RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); - RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, pw); - - switch (ldpd_process) { - case PROC_LDE_ENGINE: - l2vpn_pw_init(pw); - break; - case PROC_LDP_ENGINE: - ldpe_l2vpn_pw_init(pw); - break; - case PROC_MAIN: - break; - } - } - RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp); free(xp); } - /* insert pseudowires that were disabled in the inactive list */ - RB_FOREACH_SAFE(pw, l2vpn_pw_head, &pw_aux_list, ptmp) { - RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw); - RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); - } - l2vpn->pw_type = xl->pw_type; l2vpn->mtu = xl->mtu; strlcpy(l2vpn->br_ifname, xl->br_ifname, sizeof(l2vpn->br_ifname)); -- cgit v1.2.3