diff options
38 files changed, 625 insertions, 720 deletions
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index dba336051a..e94de682d5 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -806,7 +806,7 @@ DEFUN (no_auto_summary, } /* "router bgp" commands. */ -DEFUN (router_bgp, +DEFUN_NOSH (router_bgp, router_bgp_cmd, "router bgp [(1-4294967295) [<view|vrf> WORD]]", ROUTER_STR @@ -5647,7 +5647,7 @@ DEFUN (no_neighbor_addpath_tx_bestpath_per_as, PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS); } -DEFUN (address_family_ipv4_safi, +DEFUN_NOSH (address_family_ipv4_safi, address_family_ipv4_safi_cmd, "address-family ipv4 [<unicast|multicast|vpn|encap>]", "Enter Address Family command mode\n" @@ -5680,7 +5680,7 @@ DEFUN (address_family_ipv4_safi, return CMD_SUCCESS; } -DEFUN (address_family_ipv6_safi, +DEFUN_NOSH (address_family_ipv6_safi, address_family_ipv6_safi_cmd, "address-family ipv6 [<unicast|multicast|vpn|encap>]", "Enter Address Family command mode\n" @@ -5714,7 +5714,7 @@ DEFUN (address_family_ipv6_safi, } #ifdef KEEP_OLD_VPN_COMMANDS -DEFUN (address_family_vpnv4, +DEFUN_NOSH (address_family_vpnv4, address_family_vpnv4_cmd, "address-family vpnv4 [unicast]", "Enter Address Family command mode\n" @@ -5725,7 +5725,7 @@ DEFUN (address_family_vpnv4, return CMD_SUCCESS; } -DEFUN (address_family_vpnv6, +DEFUN_NOSH (address_family_vpnv6, address_family_vpnv6_cmd, "address-family vpnv6 [unicast]", "Enter Address Family command mode\n" @@ -5737,7 +5737,7 @@ DEFUN (address_family_vpnv6, } #endif -DEFUN (address_family_encap, +DEFUN_NOSH (address_family_encap, address_family_encap_cmd, "address-family <encap|encapv4>", "Enter Address Family command mode\n" @@ -5749,7 +5749,7 @@ DEFUN (address_family_encap, } -DEFUN (address_family_encapv6, +DEFUN_NOSH (address_family_encapv6, address_family_encapv6_cmd, "address-family encapv6", "Enter Address Family command mode\n" @@ -5759,7 +5759,7 @@ DEFUN (address_family_encapv6, return CMD_SUCCESS; } -DEFUN (address_family_evpn, +DEFUN_NOSH (address_family_evpn, address_family_evpn_cmd, "address-family <l2vpn evpn>", "Enter Address Family command mode\n" @@ -5771,7 +5771,7 @@ DEFUN (address_family_evpn, return CMD_SUCCESS; } -DEFUN (exit_address_family, +DEFUN_NOSH (exit_address_family, exit_address_family_cmd, "exit-address-family", "Exit from Address Family configuration mode\n") diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index 71086c8758..aa48b4924a 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.c +++ b/bgpd/rfapi/bgp_rfapi_cfg.c @@ -323,7 +323,7 @@ DEFUN (vnc_advertise_un_method, *-----------------------------------------------------------------------*/ -DEFUN (vnc_defaults, +DEFUN_NOSH (vnc_defaults, vnc_defaults_cmd, "vnc defaults", VNC_CONFIG_STR "Configure default NVE group\n") { @@ -2419,7 +2419,7 @@ vnc_routemap_event (route_map_event_t type, /* ignored */ *-----------------------------------------------------------------------*/ -DEFUN (vnc_nve_group, +DEFUN_NOSH (vnc_nve_group, vnc_nve_group_cmd, "vnc nve-group NAME", VNC_CONFIG_STR "Configure a NVE group\n" "Group name\n") @@ -3223,7 +3223,7 @@ DEFUN (vnc_nve_group_responselifetime, * with the lack of rigorous level control in the command handler. * TBD fix command handler. */ -DEFUN (exit_vnc, +DEFUN_NOSH (exit_vnc, exit_vnc_cmd, "exit-vnc", "Exit VNC configuration mode\n") @@ -3255,7 +3255,7 @@ static struct cmd_node bgp_vnc_nve_group_node = { * Note there are two types of NVEs, one for VPNs one for RFP NVEs *-----------------------------------------------------------------------*/ -DEFUN (vnc_vrf_policy, +DEFUN_NOSH (vnc_vrf_policy, vnc_vrf_policy_cmd, "vrf-policy NAME", "Configure a VRF policy group\n" @@ -3720,7 +3720,7 @@ DEFUN (vnc_vrf_policy_rd, return CMD_SUCCESS; } -DEFUN (exit_vrf_policy, +DEFUN_NOSH (exit_vrf_policy, exit_vrf_policy_cmd, "exit-vrf-policy", "Exit VRF policy configuration mode\n") @@ -3743,7 +3743,7 @@ static struct cmd_node bgp_vrf_policy_node = { *-----------------------------------------------------------------------*/ -DEFUN (vnc_l2_group, +DEFUN_NOSH (vnc_l2_group, vnc_l2_group_cmd, "vnc l2-group NAME", VNC_CONFIG_STR "Configure a L2 group\n" "Group name\n") diff --git a/doc/Building_FRR_on_OpenBSD6.md b/doc/Building_FRR_on_OpenBSD6.md index ab18e4ae49..14a703b1d3 100644 --- a/doc/Building_FRR_on_OpenBSD6.md +++ b/doc/Building_FRR_on_OpenBSD6.md @@ -1,12 +1,6 @@ Building FRR on OpenBSD 6 from Git Source ========================================= -OpenBSD restrictions: ---------------------- - -- MPLS is not tested on `OpenBSD`. It may work as it shares the - sources with the LDPd on OpenBSD. Bug reports and fixes are welcome - Install required packages ------------------------- @@ -60,7 +54,6 @@ an example) --enable-rtadv \ --enable-tcp-zebra \ --enable-fpm \ - --enable-ldpd \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion gmake @@ -98,6 +91,18 @@ Add the following lines to the end of `/etc/rc.conf`: **Reboot** to apply the config to the system +### Enable MPLS Forwarding + +To enable MPLS forwarding on a given interface, use the following command: + + sudo ifconfig em0 mpls + +Alternatively, to make MPLS forwarding persistent across reboots, add the "mpls" +keyword in the hostname.* files of the desired interfaces. Example: + + cat /etc/hostname.em0 + inet 10.0.1.1 255.255.255.0 mpls + ### Install rc.d init files (create them in /etc/rc.d - no example are included at this time with FRR source) diff --git a/doc/Building_FRR_on_Ubuntu1204.md b/doc/Building_FRR_on_Ubuntu1204.md index cc687f336b..03d66af629 100644 --- a/doc/Building_FRR_on_Ubuntu1204.md +++ b/doc/Building_FRR_on_Ubuntu1204.md @@ -93,7 +93,6 @@ an example.) --enable-rtadv \ --enable-tcp-zebra \ --enable-fpm \ - --enable-ldpd \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion make diff --git a/doc/Building_FRR_on_Ubuntu1604.md b/doc/Building_FRR_on_Ubuntu1604.md index 7b389523ac..996b8da898 100644 --- a/doc/Building_FRR_on_Ubuntu1604.md +++ b/doc/Building_FRR_on_Ubuntu1604.md @@ -54,7 +54,6 @@ an example.) --enable-rtadv \ --enable-tcp-zebra \ --enable-fpm \ - --enable-ldpd \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion make diff --git a/isisd/isisd.c b/isisd/isisd.c index 2863d2f678..f226c4a1f3 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -1576,7 +1576,7 @@ DEFUN (show_database, /* * 'router isis' command */ -DEFUN (router_isis, +DEFUN_NOSH (router_isis, router_isis_cmd, "router isis WORD", ROUTER_STR diff --git a/ldpd/Makefile.am b/ldpd/Makefile.am index 42e54138aa..19f819ae36 100644 --- a/ldpd/Makefile.am +++ b/ldpd/Makefile.am @@ -24,7 +24,9 @@ noinst_HEADERS = \ control.h lde.h ldpd.h ldpe.h ldp.h log.h ldp_debug.h ldp_vty.h ldp_vty_cmds.c: $(srcdir)/ldp_vty.xml $(srcdir)/../tools/xml2cli.pl - @PERL@ $(srcdir)/../tools/xml2cli.pl $(srcdir)/ldp_vty.xml > $@ + @PERL@ $(srcdir)/../tools/xml2cli.pl $(srcdir)/ldp_vty.xml | \ + sed -e 's%DEFUN \((ldp_\(interface_\|mpls_ldp\|address_family\|l2vpn_word\|member_pseudo\)\)%DEFUN_NOSH \1%' \ + > $@ ldpd_SOURCES = ldpd.c ldpd_LDADD = libldp.a ../lib/libfrr.la @LIBCAP@ diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c index 2516e62753..ca40636e09 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,30 +189,33 @@ l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif) } struct l2vpn_pw * -l2vpn_pw_find(struct l2vpn *l2vpn, unsigned int ifindex) +l2vpn_pw_find(struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_pw *pw; + struct l2vpn_pw s; - 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); + strlcpy(s.ifname, ifname, sizeof(s.ifname)); + pw = RB_FIND(l2vpn_pw_head, &l2vpn->pw_tree, &s); + if (pw) + return (pw); + 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; - return (NULL); + strlcpy(s.ifname, ifname, sizeof(s.ifname)); + return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_tree, &s)); } struct l2vpn_pw * -l2vpn_pw_find_name(struct l2vpn *l2vpn, const char *ifname) +l2vpn_pw_find_inactive(struct l2vpn *l2vpn, const char *ifname) { - struct l2vpn_pw *pw; struct l2vpn_pw s; strlcpy(s.ifname, ifname, sizeof(s.ifname)); - pw = RB_FIND(l2vpn_pw_head, &l2vpn->pw_tree, &s); - if (pw) - return (pw); return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s)); } diff --git a/ldpd/lde.c b/ldpd/lde.c index 3247c8c1cc..53fde32fd9 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -106,6 +106,10 @@ sigint(void) static struct quagga_signal_t lde_signals[] = { { + .signal = SIGHUP, + /* ignore */ + }, + { .signal = SIGINT, .handler = &sigint, }, @@ -166,7 +170,7 @@ lde(const char *user, const char *group, u_short instance) zprivs_init(&lde_privs); #ifdef HAVE_PLEDGE - if (pledge("stdio recvfd", NULL) == -1) + if (pledge("stdio recvfd unix", NULL) == -1) fatal("pledge"); #endif diff --git a/ldpd/lde.h b/ldpd/lde.h index d9836097af..d1089b44f4 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -213,12 +213,12 @@ 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 *); +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/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index f313bc147b..bab5e17368 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(parent, pw->ifname)); + break; + default: + fatalx("ldp_vty_get_node: unexpected node"); + } + + return (NULL); +} + static int ldp_vty_get_af(struct vty *vty) { @@ -437,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); } @@ -449,11 +543,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 +562,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 +570,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 +605,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 +633,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 +657,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); @@ -600,15 +684,15 @@ 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); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&iface); + iface = ldp_vty_get_node(vty, NULL, vty->node); + VTY_CHECK_CONTEXT(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 +704,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 +733,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 +757,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); @@ -703,15 +784,15 @@ 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); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&iface); + iface = ldp_vty_get_node(vty, NULL, vty->node); + VTY_CHECK_CONTEXT(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 +804,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 +835,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 +853,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 +872,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 +881,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 +902,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 +932,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 +943,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 +965,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 +980,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,33 +988,27 @@ 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) { 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; } 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 +1017,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 +1026,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 +1059,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 +1072,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 +1081,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 +1096,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 +1123,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 +1133,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 +1154,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 +1162,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 +1185,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 +1195,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 +1222,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 +1244,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 +1285,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 +1302,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 +1319,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 +1333,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 +1347,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 +1378,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 +1406,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 +1418,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); @@ -1417,28 +1431,23 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[]) } if (l2vpn) { - VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn); - goto cancel; + ldp_vty_push_node(vty, LDP_L2VPN_NODE, l2vpn); + 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); - VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn); - - return (CMD_SUCCESS); + ldp_reload(vty_conf); + ldp_vty_push_node(vty, LDP_L2VPN_NODE, l2vpn); -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; @@ -1446,15 +1455,15 @@ 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); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&l2vpn); + 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)); 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 +1471,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; @@ -1478,15 +1486,15 @@ ldp_vty_l2vpn_mtu(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - l2vpn = VTY_GET_CONTEXT(l2vpn); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&l2vpn); + l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); + VTY_CHECK_CONTEXT(l2vpn); 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 +1502,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; @@ -1508,15 +1515,15 @@ ldp_vty_l2vpn_pwtype(struct vty *vty, struct vty_arg *args[]) else pw_type = PW_TYPE_ETHERNET_TAGGED; - l2vpn = VTY_GET_CONTEXT(l2vpn); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&l2vpn); + l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); + VTY_CHECK_CONTEXT(l2vpn); 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 +1531,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; @@ -1535,14 +1541,13 @@ 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); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&l2vpn); - l2vpn = l2vpn_find(vty_conf, l2vpn->name); - lif = l2vpn_if_find_name(l2vpn, ifname); + l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); + VTY_CHECK_CONTEXT(l2vpn); + lif = l2vpn_if_find(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 +1556,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 +1574,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; @@ -1592,13 +1592,13 @@ 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); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&l2vpn); - pw = l2vpn_pw_find_name(l2vpn, ifname); + l2vpn = ldp_vty_get_node(vty, NULL, LDP_L2VPN_NODE); + VTY_CHECK_CONTEXT(l2vpn); + pw = l2vpn_pw_find(l2vpn, ifname); if (disable) { if (pw == NULL) - goto cancel; + return (CMD_SUCCESS); RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); free(pw); @@ -1607,13 +1607,13 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) } if (pw) { - VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw); - goto cancel; + ldp_vty_push_node(vty, LDP_PSEUDOWIRE_NODE, pw); + 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 +1628,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); - VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw); - - return (CMD_SUCCESS); + ldp_reload(vty_conf); + ldp_vty_push_node(vty, LDP_PSEUDOWIRE_NODE, pw); -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 +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"); - pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); + 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; @@ -1661,7 +1659,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 +1667,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 +1683,10 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); + 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; @@ -1698,7 +1698,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 +1706,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 +1721,17 @@ ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); + 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; else pw->lsr_id = lsr_id; - ldp_reload_ref(vty_conf, (void **)&pw); + ldp_reload(vty_conf); return (CMD_SUCCESS); } @@ -1737,7 +1739,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 +1755,17 @@ ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); + 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; else pw->pwid = pwid; - ldp_reload_ref(vty_conf, (void **)&pw); + ldp_reload(vty_conf); return (CMD_SUCCESS); } @@ -1769,21 +1773,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; - pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); - vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); + 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; 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/ldp_vty_exec.c b/ldpd/ldp_vty_exec.c index 616847b363..dfd5af9748 100644 --- a/ldpd/ldp_vty_exec.c +++ b/ldpd/ldp_vty_exec.c @@ -213,10 +213,10 @@ show_discovery_msg(struct vty *vty, struct imsg *imsg, vty_out(vty, "%-8s %-15s ", "Targeted", addr); if (strlen(addr) > 15) - vty_out(vty, "\n%46s", " "); + vty_out(vty, "%s%46s", VTY_NEWLINE, " "); break; } - vty_out(vty, "%9u\n", adj->holdtime); + vty_out(vty, "%9u%s", adj->holdtime, VTY_NEWLINE); break; case IMSG_CTL_END: vty_out(vty, "%s", VTY_NEWLINE); @@ -516,9 +516,9 @@ show_nbr_msg(struct vty *vty, struct imsg *imsg, struct show_params *params) af_name(nbr->af), inet_ntoa(nbr->id), nbr_state_name(nbr->nbr_state), addr); if (strlen(addr) > 15) - vty_out(vty, "\n%48s", " "); - vty_out(vty, " %8s\n", nbr->uptime == 0 ? "-" : - log_time(nbr->uptime)); + vty_out(vty, "%s%48s", VTY_NEWLINE, " "); + vty_out(vty, " %8s%s", nbr->uptime == 0 ? "-" : + log_time(nbr->uptime), VTY_NEWLINE); break; case IMSG_CTL_END: return (1); @@ -1031,10 +1031,10 @@ show_lib_msg(struct vty *vty, struct imsg *imsg, struct show_params *params) vty_out(vty, "%-4s %-20s", af_name(rt->af), dstnet); if (strlen(dstnet) > 20) - vty_out(vty, "\n%25s", " "); - vty_out(vty, " %-15s %-11s %-13s %6s\n", inet_ntoa(rt->nexthop), + vty_out(vty, "%s%25s", VTY_NEWLINE, " "); + vty_out(vty, " %-15s %-11s %-13s %6s%s", inet_ntoa(rt->nexthop), log_label(rt->local_label), log_label(rt->remote_label), - rt->in_use ? "yes" : "no"); + rt->in_use ? "yes" : "no", VTY_NEWLINE); break; case IMSG_CTL_END: vty_out(vty, "%s", VTY_NEWLINE); @@ -1603,9 +1603,9 @@ ldp_vty_show_binding(struct vty *vty, struct vty_arg *args[]) params.json = vty_get_arg_value(args, "json") ? 1 : 0; if (!params.detail && !params.json) - vty_out(vty, "%-4s %-20s %-15s %-11s %-13s %6s\n", "AF", + vty_out(vty, "%-4s %-20s %-15s %-11s %-13s %6s%s", "AF", "Destination", "Nexthop", "Local Label", "Remote Label", - "In Use"); + "In Use", VTY_NEWLINE); imsg_compose(&ibuf, IMSG_CTL_SHOW_LIB, 0, 0, -1, NULL, 0); return (ldp_vty_dispatch(vty, &ibuf, SHOW_LIB, ¶ms)); @@ -1632,8 +1632,8 @@ ldp_vty_show_discovery(struct vty *vty, struct vty_arg *args[]) params.json = vty_get_arg_value(args, "json") ? 1 : 0; if (!params.detail && !params.json) - vty_out(vty, "%-4s %-15s %-8s %-15s %9s\n", - "AF", "ID", "Type", "Source", "Holdtime"); + vty_out(vty, "%-4s %-15s %-8s %-15s %9s%s", + "AF", "ID", "Type", "Source", "Holdtime", VTY_NEWLINE); if (params.detail) imsg_compose(&ibuf, IMSG_CTL_SHOW_DISCOVERY_DTL, 0, 0, -1, @@ -1745,8 +1745,9 @@ ldp_vty_show_neighbor(struct vty *vty, struct vty_arg *args[]) params.detail = 1; if (!params.detail && !params.json) - vty_out(vty, "%-4s %-15s %-11s %-15s %8s\n", - "AF", "ID", "State", "Remote Address", "Uptime"); + vty_out(vty, "%-4s %-15s %-11s %-15s %8s%s", + "AF", "ID", "State", "Remote Address", "Uptime", + VTY_NEWLINE); imsg_compose(&ibuf, IMSG_CTL_SHOW_NBR, 0, 0, -1, NULL, 0); return (ldp_vty_dispatch(vty, &ibuf, SHOW_NBR, ¶ms)); diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 559a2474b3..3023d94469 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; @@ -90,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 [] = { @@ -128,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. */ @@ -264,31 +281,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 +328,34 @@ 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); + /* create base configuration with sane defaults */ + ldpd_conf = config_new_empty(); + 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 */ if ((iev_ldpe = calloc(1, sizeof(struct imsgev))) == NULL || (iev_ldpe_sync = calloc(1, sizeof(struct imsgev))) == NULL || @@ -392,6 +416,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 { @@ -956,37 +981,36 @@ 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); + if (global.sighup) + return (0); + + 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) { @@ -1008,28 +1032,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; @@ -1039,7 +1059,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; @@ -1055,8 +1075,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); } @@ -1072,7 +1090,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; @@ -1087,7 +1105,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); @@ -1138,12 +1155,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) { @@ -1172,27 +1183,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) { @@ -1327,7 +1330,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; @@ -1367,8 +1370,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); } } @@ -1386,7 +1387,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; @@ -1436,14 +1437,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; @@ -1555,14 +1554,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; @@ -1594,6 +1591,22 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) } } 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); @@ -1614,22 +1627,19 @@ 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; 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; @@ -1638,7 +1648,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void /* 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); @@ -1647,7 +1657,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void } 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; @@ -1657,16 +1667,13 @@ 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); } /* 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_name(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); @@ -1685,7 +1692,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void } 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_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; @@ -1725,28 +1732,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void 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); @@ -1789,15 +1774,13 @@ 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); } /* 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_inactive(xl, pw->ifname)) == NULL) { RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); if (ldpd_process == PROC_MAIN) QOBJ_UNREG (pw); @@ -1806,7 +1789,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void } 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_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; @@ -1824,36 +1807,10 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void 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); - if (ref && *ref == xp) - *ref = pw; 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)); @@ -1895,7 +1852,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); } diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index a8279ebf66..a0474a5a2d 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; @@ -645,7 +646,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 +706,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 *); diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 6c542c5e34..96a7052ec6 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -88,6 +88,10 @@ sigint(void) static struct quagga_signal_t ldpe_signals[] = { { + .signal = SIGHUP, + /* ignore */ + }, + { .signal = SIGINT, .handler = &sigint, }, @@ -299,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, diff --git a/lib/distribute.c b/lib/distribute.c index 2e76e352cb..01c338f177 100644 --- a/lib/distribute.c +++ b/lib/distribute.c @@ -524,14 +524,14 @@ distribute_list_init (int node) disthash = hash_create (distribute_hash_make, (int (*) (const void *, const void *)) distribute_cmp); - install_element (node, &distribute_list_cmd); - install_element (node, &no_distribute_list_cmd); -/* - install_element (RIP_NODE, &distribute_list_cmd); - install_element (RIP_NODE, &no_distribute_list_cmd); - install_element (RIPNG_NODE, &distribute_list_cmd); - install_element (RIPNG_NODE, &no_distribute_list_cmd); - */ + /* vtysh command-extraction doesn't grok install_element(node, ) */ + if (node == RIP_NODE) { + install_element (RIP_NODE, &distribute_list_cmd); + install_element (RIP_NODE, &no_distribute_list_cmd); + } else if (node == RIPNG_NODE) { + install_element (RIPNG_NODE, &distribute_list_cmd); + install_element (RIPNG_NODE, &no_distribute_list_cmd); + } /* install v6 */ if (node == RIPNG_NODE) { diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c index e3a7c979fc..97de943216 100644 --- a/lib/grammar_sandbox.c +++ b/lib/grammar_sandbox.c @@ -411,7 +411,7 @@ DEFUN (grammar_findambig, { int same = prev && !strcmp (prev->cmd, cur->cmd); if (printall && !same) - vty_out (vty, "'%s'%s", cur->cmd, VTY_NEWLINE); + vty_out (vty, "'%s' [%x]%s", cur->cmd, cur->el->daemon, VTY_NEWLINE); if (same) { vty_out (vty, "'%s' AMBIGUOUS:%s", cur->cmd, VTY_NEWLINE); diff --git a/lib/keychain.c b/lib/keychain.c index cd8039b95b..95a2c8e599 100644 --- a/lib/keychain.c +++ b/lib/keychain.c @@ -240,7 +240,7 @@ key_delete (struct keychain *keychain, struct key *key) key_free (key); } -DEFUN (key_chain, +DEFUN_NOSH (key_chain, key_chain_cmd, "key chain WORD", "Authentication key management\n" @@ -280,7 +280,7 @@ DEFUN (no_key_chain, return CMD_SUCCESS; } -DEFUN (key, +DEFUN_NOSH (key, key_cmd, "key (0-2147483647)", "Configure a key\n" @@ -304,7 +304,7 @@ ns_netns_pathname (struct vty *vty, const char *name) return pathname; } -DEFUN (ns_netns, +DEFUN_NOSH (ns_netns, ns_netns_cmd, "logical-router (1-65535) ns NAME", "Enable a logical-router\n" diff --git a/lib/routemap.c b/lib/routemap.c index 1647ac3668..cd34ffaae5 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -2538,7 +2538,7 @@ DEFUN (no_set_tag, -DEFUN (route_map, +DEFUN_NOSH (route_map, route_map_cmd, "route-map WORD <deny|permit> (1-65535)", "Create route-map or enter route-map command mode\n" @@ -2754,7 +2754,7 @@ DEFUN (no_rmap_continue, } -DEFUN (rmap_show_name, +DEFUN_NOSH (rmap_show_name, rmap_show_name_cmd, "show route-map [WORD]", SHOW_STR diff --git a/lib/sigevent.c b/lib/sigevent.c index a120028d81..09f07180ce 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 (); } } } @@ -474,7 +474,7 @@ vrf_socket (int domain, int type, int protocol, vrf_id_t vrf_id) } /* vrf CLI commands */ -DEFUN (vrf, +DEFUN_NOSH (vrf, vrf_cmd, "vrf NAME", "Select a VRF to configure\n" @@ -2660,7 +2660,7 @@ vty_event (enum event event, int sock, struct vty *vty) } } -DEFUN (config_who, +DEFUN_NOSH (config_who, config_who_cmd, "who", "Display who is on vty\n") @@ -2677,7 +2677,7 @@ DEFUN (config_who, } /* Move to vty configuration mode. */ -DEFUN (line_vty, +DEFUN_NOSH (line_vty, line_vty_cmd, "line vty", "Configure a terminal line\n" @@ -2867,7 +2867,7 @@ DEFUN (no_service_advanced_vty, return CMD_SUCCESS; } -DEFUN (terminal_monitor, +DEFUN_NOSH (terminal_monitor, terminal_monitor_cmd, "terminal monitor", "Set terminal line parameters\n" @@ -2877,7 +2877,7 @@ DEFUN (terminal_monitor, return CMD_SUCCESS; } -DEFUN (terminal_no_monitor, +DEFUN_NOSH (terminal_no_monitor, terminal_no_monitor_cmd, "terminal no monitor", "Set terminal line parameters\n" @@ -2888,7 +2888,7 @@ DEFUN (terminal_no_monitor, return CMD_SUCCESS; } -DEFUN (no_terminal_monitor, +DEFUN_NOSH (no_terminal_monitor, no_terminal_monitor_cmd, "no terminal monitor", NO_STR @@ -2899,7 +2899,7 @@ DEFUN (no_terminal_monitor, } -DEFUN (show_history, +DEFUN_NOSH (show_history, show_history_cmd, "show history", SHOW_STR diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index a367d1e141..74e49a21bb 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -288,7 +288,7 @@ ospf6_maxage_remove (struct ospf6 *o) } /* start ospf6 */ -DEFUN (router_ospf6, +DEFUN_NOSH (router_ospf6, router_ospf6_cmd, "router ospf6", ROUTER_STR diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 71befc84b5..c51e176c74 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -144,7 +144,7 @@ ospf_oi_count (struct interface *ifp) return i; } -DEFUN (router_ospf, +DEFUN_NOSH (router_ospf, router_ospf_cmd, "router ospf [(1-65535)]", "Enable a routing process\n" diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 6dc1fba375..5688d0e45d 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -898,6 +898,7 @@ void pim_ifchannel_prune(struct interface *ifp, THREAD_TIMER_ON(master, ch->t_ifjoin_expiry_timer, on_ifjoin_expiry_timer, ch, holdtime); + pim_upstream_update_join_desired(ch->upstream); } break; case PIM_IFJOIN_PRUNE_PENDING: diff --git a/pimd/pim_join.c b/pimd/pim_join.c index c531545541..884aa35bc5 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -493,7 +493,7 @@ int pim_joinprune_send(struct pim_rpf *rpf, curr_ptr += group_size; packet_left -= group_size; packet_size += group_size; - pim_msg_build_jp_groups (grp, group); + pim_msg_build_jp_groups (grp, group, group_size); grp = (struct pim_jp_groups *)curr_ptr; if (packet_left < sizeof (struct pim_jp_groups) || msg->num_groups == 255) diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c index 29faace322..251e67a351 100644 --- a/pimd/pim_jp_agg.c +++ b/pimd/pim_jp_agg.c @@ -83,10 +83,10 @@ pim_jp_agg_src_cmp (void *arg1, void *arg2) if (!js1->is_join && js2->is_join) return 1; - if (js1->up->sg.src.s_addr < js2->up->sg.src.s_addr) + if ((uint32_t)js1->up->sg.src.s_addr < (uint32_t)js2->up->sg.src.s_addr) return -1; - if (js1->up->sg.src.s_addr > js2->up->sg.src.s_addr) + if ((uint32_t)js1->up->sg.src.s_addr > (uint32_t)js2->up->sg.src.s_addr) return 1; return 0; diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c index 4018fd639e..e19893f5da 100644 --- a/pimd/pim_msg.c +++ b/pimd/pim_msg.c @@ -101,6 +101,7 @@ pim_msg_addr_encode_ipv4_source(uint8_t *buf, size_t pim_msg_get_jp_group_size (struct list *sources) { + struct pim_jp_sources *js; size_t size = 0; size += sizeof (struct pim_encoded_group_ipv4); @@ -108,17 +109,74 @@ pim_msg_get_jp_group_size (struct list *sources) size += sizeof (struct pim_encoded_source_ipv4) * sources->count; + js = listgetdata(listhead(sources)); + if (js && js->up->sg.src.s_addr == INADDR_ANY) + { + struct pim_upstream *child, *up; + struct listnode *up_node; + + up = js->up; + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug ("%s: Considering (%s) children for (S,G,rpt) prune", + __PRETTY_FUNCTION__, up->sg_str); + + for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) + { + if (child->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) + { + if (!pim_rpf_is_same(&up->rpf, &child->rpf)) + { + size += sizeof (struct pim_encoded_source_ipv4); + PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(child->flags); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug ("%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message", + __PRETTY_FUNCTION__, up->sg_str, child->sg_str); + } + else + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug ("%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)", + __PRETTY_FUNCTION__, up->sg_str, child->sg_str); + } + else if (pim_upstream_is_sg_rpt (child)) + { + if (pim_upstream_empty_inherited_olist (child)) + { + size += sizeof (struct pim_encoded_source_ipv4); + PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(child->flags); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug ("%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message", + __PRETTY_FUNCTION__, child->sg_str); + } + else if (!pim_rpf_is_same (&up->rpf, &child->rpf)) + { + size += sizeof (struct pim_encoded_source_ipv4); + PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(child->flags); + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug ("%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message", + __PRETTY_FUNCTION__, up->sg_str, child->sg_str); + } + else + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug ("%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message", + __PRETTY_FUNCTION__, up->sg_str, child->sg_str); + } + else + if (PIM_DEBUG_PIM_PACKETS) + zlog_debug ("%s: SPT bit is not set for (%s)", + __PRETTY_FUNCTION__, child->sg_str); + } + } return size; } size_t -pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_jp_agg_group *sgs) +pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_jp_agg_group *sgs, size_t size) { struct listnode *node, *nnode; struct pim_jp_sources *source; + struct pim_upstream *up = NULL; struct in_addr stosend; uint8_t bits; - size_t size = pim_msg_get_jp_group_size (sgs->sources); uint8_t tgroups = 0; memset (grp, 0, size); @@ -137,6 +195,7 @@ pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_jp_agg_group *sgs struct pim_rpf *rpf = pim_rp_g (source->up->sg.grp); bits = PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_WC_BIT | PIM_ENCODE_RPT_BIT; stosend = rpf->rpf_addr.u.prefix4; + up = source->up; } else { @@ -148,74 +207,26 @@ pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_jp_agg_group *sgs tgroups++; } - grp->joins = htons(grp->joins); - grp->prunes = htons(grp->prunes); - /* - * This is not implemented correctly at this point in time - * Make it stop. - */ -#if 0 - if (up->sg.src.s_addr == INADDR_ANY) + if (up) { struct pim_upstream *child; - struct listnode *up_node; - int send_prune = 0; - zlog_debug ("%s: Considering (%s) children for (S,G,rpt) prune", - __PRETTY_FUNCTION__, up->sg_str); - for (ALL_LIST_ELEMENTS_RO (up->sources, up_node, child)) + for (ALL_LIST_ELEMENTS(up->sources, node, nnode, child)) { - if (child->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) - { - if (!pim_rpf_is_same(&up->rpf, &child->rpf)) - { - send_prune = 1; - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: SPT Bit and RPF'(%s) != RPF'(S,G): Add Prune (%s,rpt) to compound message", - __PRETTY_FUNCTION__, up->sg_str, child->sg_str); - } - else - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: SPT Bit and RPF'(%s) == RPF'(S,G): Not adding Prune for (%s,rpt)", - __PRETTY_FUNCTION__, up->sg_str, child->sg_str); - } - else if (pim_upstream_is_sg_rpt (child)) - { - if (pim_upstream_empty_inherited_olist (child)) - { - send_prune = 1; - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: inherited_olist(%s,rpt) is NULL, Add Prune to compound message", - __PRETTY_FUNCTION__, child->sg_str); - } - else if (!pim_rpf_is_same (&up->rpf, &child->rpf)) - { - send_prune = 1; - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: RPF'(%s) != RPF'(%s,rpt), Add Prune to compound message", - __PRETTY_FUNCTION__, up->sg_str, child->sg_str); - } - else - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: RPF'(%s) == RPF'(%s,rpt), Do not add Prune to compound message", - __PRETTY_FUNCTION__, up->sg_str, child->sg_str); - } - else - if (PIM_DEBUG_PIM_PACKETS) - zlog_debug ("%s: SPT bit is not set for (%s)", - __PRETTY_FUNCTION__, child->sg_str); - if (send_prune) + if (PIM_UPSTREAM_FLAG_TEST_SEND_SG_RPT_PRUNE(child->flags)) { - pim_msg_curr = pim_msg_addr_encode_ipv4_source (pim_msg_curr, remain, - child->sg.src, - PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_RPT_BIT); - remain = pim_msg_curr - pim_msg; - *prunes = htons(ntohs(*prunes) + 1); - send_prune = 0; + pim_msg_addr_encode_ipv4_source ((uint8_t *)&grp->s[tgroups], + child->sg.src, + PIM_ENCODE_SPARSE_BIT | PIM_ENCODE_RPT_BIT); + tgroups++; + PIM_UPSTREAM_FLAG_UNSET_SEND_SG_RPT_PRUNE(child->flags); + grp->prunes++; } } } -#endif + + grp->joins = htons(grp->joins); + grp->prunes = htons(grp->prunes); return size; } diff --git a/pimd/pim_msg.h b/pimd/pim_msg.h index 9774ef3ed0..de663aa3b5 100644 --- a/pimd/pim_msg.h +++ b/pimd/pim_msg.h @@ -96,5 +96,5 @@ uint8_t *pim_msg_addr_encode_ipv4_source(uint8_t *buf, size_t pim_msg_get_jp_group_size (struct list *sources); -size_t pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_jp_agg_group *sgs); +size_t pim_msg_build_jp_groups (struct pim_jp_groups *grp, struct pim_jp_agg_group *sgs, size_t size); #endif /* PIM_MSG_H */ diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 327e4f07d7..d95849fce0 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -756,6 +756,16 @@ pim_upstream_evaluate_join_desired_interface (struct pim_upstream *up, */ if (parent && ch->upstream == parent) { + struct listnode *ch_node; + struct pim_ifchannel *child; + for (ALL_LIST_ELEMENTS_RO (ch->sources, ch_node, child)) + { + if (child->upstream == up) + { + if (PIM_IF_FLAG_TEST_S_G_RPT(child->flags)) + return 0; + } + } if (!pim_macro_ch_lost_assert (ch) && pim_macro_chisin_joins_or_include (ch)) return 1; } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 126824e988..e293c0c146 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -33,6 +33,7 @@ #define PIM_UPSTREAM_FLAG_MASK_SRC_PIM (1 << 4) #define PIM_UPSTREAM_FLAG_MASK_SRC_STREAM (1 << 5) #define PIM_UPSTREAM_FLAG_MASK_SRC_MSDP (1 << 6) +#define PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE (1 << 7) #define PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) #define PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) @@ -41,6 +42,7 @@ #define PIM_UPSTREAM_FLAG_TEST_SRC_PIM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_PIM) #define PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) #define PIM_UPSTREAM_FLAG_TEST_SRC_MSDP(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) +#define PIM_UPSTREAM_FLAG_TEST_SEND_SG_RPT_PRUNE(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE) #define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) #define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) @@ -49,6 +51,7 @@ #define PIM_UPSTREAM_FLAG_SET_SRC_PIM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_PIM) #define PIM_UPSTREAM_FLAG_SET_SRC_STREAM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) #define PIM_UPSTREAM_FLAG_SET_SRC_MSDP(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) +#define PIM_UPSTREAM_FLAG_SET_SEND_SG_RPT_PRUNE(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE) #define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED) #define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED) @@ -57,6 +60,7 @@ #define PIM_UPSTREAM_FLAG_UNSET_SRC_PIM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_PIM) #define PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_STREAM) #define PIM_UPSTREAM_FLAG_UNSET_SRC_MSDP(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_MSDP) +#define PIM_UPSTREAM_FLAG_UNSET_SEND_SG_RPT_PRUNE(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SEND_SG_RPT_PRUNE) enum pim_upstream_state { PIM_UPSTREAM_NOTJOINED, diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index bf2c838abb..d02560bfc2 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -53,9 +53,6 @@ static struct zclient *zclient = NULL; static int fib_lookup_if_vif_index(struct in_addr addr); -static int del_oif(struct channel_oil *channel_oil, - struct interface *oif, - uint32_t proto_mask); /* Router-id update message from zebra. */ static int pim_router_id_update_zebra(int command, struct zclient *zclient, @@ -521,8 +518,6 @@ pim_scan_individual_oil (struct channel_oil *c_oil, int in_vif_index) source_str, group_str, new_iif->name, input_iface_vif_index); } - - //del_oif(c_oil, new_iif, PIM_OIF_FLAG_PROTO_ANY); } /* update iif vif_index */ @@ -765,137 +760,6 @@ static int fib_lookup_if_vif_index(struct in_addr addr) return vif_index; } -static int del_oif(struct channel_oil *channel_oil, - struct interface *oif, - uint32_t proto_mask) -{ - struct pim_interface *pim_ifp; - int old_ttl; - - pim_ifp = oif->info; - - if (PIM_DEBUG_MROUTE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - proto_mask, oif->name, pim_ifp->mroute_vif_index); - } - - /* Prevent single protocol from unsubscribing same interface from - channel (S,G) multiple times */ - if (!(channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask)) { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: nonexistent protocol mask %u removed OIF %s (vif_index=%d, min_ttl=%d) from channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - proto_mask, oif->name, pim_ifp->mroute_vif_index, - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], - source_str, group_str); - } - return -2; - } - - /* Mark that protocol is no longer interested in this OIF */ - channel_oil->oif_flags[pim_ifp->mroute_vif_index] &= ~proto_mask; - - /* Allow multiple protocols to unsubscribe same interface from - channel (S,G) multiple times, by silently ignoring requests while - there is at least one protocol interested in the channel */ - if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & PIM_OIF_FLAG_PROTO_ANY) { - - /* Check the OIF keeps existing before returning, and only log - warning otherwise */ - if (channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] < 1) { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: protocol mask %u removing nonexistent OIF %s (vif_index=%d, min_ttl=%d) from channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - proto_mask, oif->name, pim_ifp->mroute_vif_index, - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index], - source_str, group_str); - } - } - - return 0; - } - - old_ttl = channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index]; - - if (old_ttl < 1) { - if (PIM_DEBUG_MROUTE) - { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: interface %s (vif_index=%d) is not output for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - oif->name, pim_ifp->mroute_vif_index, - source_str, group_str); - } - return -3; - } - - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = 0; - - if (pim_mroute_add(channel_oil, __PRETTY_FUNCTION__)) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_warn("%s %s: could not remove output interface %s (vif_index=%d) from channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - oif->name, pim_ifp->mroute_vif_index, - source_str, group_str); - - channel_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index] = old_ttl; - return -4; - } - - --channel_oil->oil_size; - - if (channel_oil->oil_size < 1) { - if (pim_mroute_del(channel_oil, __PRETTY_FUNCTION__)) { - if (PIM_DEBUG_MROUTE) - { - /* just log a warning in case of failure */ - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: failure removing OIL for channel (S,G)=(%s,%s)", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str); - } - } - } - - if (PIM_DEBUG_MROUTE) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<group?>", channel_oil->oil.mfcc_mcastgrp, group_str, sizeof(group_str)); - pim_inet4_dump("<source?>", channel_oil->oil.mfcc_origin, source_str, sizeof(source_str)); - zlog_debug("%s %s: (S,G)=(%s,%s): proto_mask=%u OIF=%s vif_index=%d: DONE", - __FILE__, __PRETTY_FUNCTION__, - source_str, group_str, - proto_mask, oif->name, pim_ifp->mroute_vif_index); - } - - return 0; -} - void igmp_source_forward_start(struct igmp_source *source) { struct igmp_group *group; @@ -1050,16 +914,16 @@ void igmp_source_forward_stop(struct igmp_source *source) Possibly because of multiple calls. When that happens, we enter the below if statement and this function returns early which in turn triggers the calling function to assert. - Making the call to del_oif and ignoring the return code - fixes the issue without ill effect, similar to - pim_forward_stop below. + Making the call to pim_channel_del_oif and ignoring the return code + fixes the issue without ill effect, similar to + pim_forward_stop below. */ - result = del_oif(source->source_channel_oil, - group->group_igmp_sock->interface, - PIM_OIF_FLAG_PROTO_IGMP); + result = pim_channel_del_oif(source->source_channel_oil, + group->group_igmp_sock->interface, + PIM_OIF_FLAG_PROTO_IGMP); if (result) { if (PIM_DEBUG_IGMP_TRACE) - zlog_debug("%s: del_oif() failed with return=%d", + zlog_debug("%s: pim_channel_del_oif() failed with return=%d", __func__, result); return; } @@ -1133,18 +997,9 @@ void pim_forward_stop(struct pim_ifchannel *ch) ch->sg_str, ch->interface->name); } - if (!up->channel_oil) { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug("%s: (S,G)=%s oif=%s missing channel OIL", - __PRETTY_FUNCTION__, - ch->sg_str, ch->interface->name); - - return; - } - - del_oif(up->channel_oil, - ch->interface, - PIM_OIF_FLAG_PROTO_PIM); + pim_channel_del_oif(up->channel_oil, + ch->interface, + PIM_OIF_FLAG_PROTO_PIM); } void diff --git a/ripd/ripd.c b/ripd/ripd.c index 82e460ced8..45d5bf1ead 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -2802,7 +2802,7 @@ rip_event (enum rip_event event, int sock) } } -DEFUN (router_rip, +DEFUN_NOSH (router_rip, router_rip_cmd, "router rip", "Enable a routing process\n" diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index caad85457a..a883bec3c4 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -2215,7 +2215,7 @@ DEFUN (clear_ipv6_rip, return CMD_SUCCESS; } -DEFUN (router_ripng, +DEFUN_NOSH (router_ripng, router_ripng_cmd, "router ripng", "Enable a routing process\n" diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index c1b1d705a4..5510482485 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -33,62 +33,6 @@ print <<EOF; EOF -$ignore{'"interface IFNAME"'} = "ignore"; -$ignore{'"interface IFNAME " "vrf (0-65535)"'} = "ignore"; -$ignore{'"interface IFNAME " "vrf NAME"'} = "ignore"; -$ignore{'"link-params"'} = "ignore"; -$ignore{'"vrf NAME"'} = "ignore"; -$ignore{'"ip vrf NAME"'} = "ignore"; -$ignore{'"router rip"'} = "ignore"; -$ignore{'"router ripng"'} = "ignore"; -$ignore{'"router ospf"'} = "ignore"; -$ignore{'"router ospf (1-65535)"'} = "ignore"; -$ignore{'"router ospf6"'} = "ignore"; -$ignore{'"mpls ldp"'} = "ignore"; -$ignore{'"l2vpn WORD type vpls"'} = "ignore"; -$ignore{'"member pseudowire IFNAME"'} = "ignore"; -$ignore{'"router bgp"'} = "ignore"; -$ignore{'"router bgp " "(1-4294967295)"'} = "ignore"; -$ignore{'"router bgp " "(1-4294967295)" " <view|vrf> WORD"'} = "ignore"; -$ignore{'"router bgp [(1-4294967295) [<view|vrf> WORD]]"'} = "ignore"; -$ignore{'"router isis WORD"'} = "ignore"; -$ignore{'"router zebra"'} = "ignore"; -$ignore{'"address-family ipv4"'} = "ignore"; -$ignore{'"address-family ipv4 [<unicast|multicast|vpn|encap>]"'} = "ignore"; -$ignore{'"address-family ipv6"'} = "ignore"; -$ignore{'"address-family ipv6 [<unicast|multicast|vpn|encap>]"'} = "ignore"; -$ignore{'"address-family vpnv4"'} = "ignore"; -$ignore{'"address-family vpnv4 unicast"'} = "ignore"; -$ignore{'"address-family ipv4 vrf NAME"'} = "ignore"; -$ignore{'"address-family <encap|encapv4>"'} = "ignore"; -$ignore{'"address-family encapv6"'} = "ignore"; -$ignore{'"address-family ipv4 encap"'} = "ignore"; -$ignore{'"address-family ipv6 encap"'} = "ignore"; -$ignore{'"address-family ipv6 vpn"'} = "ignore"; -$ignore{'"address-family vpnv6"'} = "ignore"; -$ignore{'"address-family vpnv6 unicast"'} = "ignore"; -$ignore{'"exit-address-family"'} = "ignore"; -$ignore{'"exit-link-params"'} = "ignore"; -$ignore{'"vnc defaults"'} = "ignore"; -$ignore{'"vnc l2-group NAME"'} = "ignore"; -$ignore{'"vnc nve-group NAME"'} = "ignore"; -$ignore{'"exit-vnc"'} = "ignore"; -$ignore{'"key chain WORD"'} = "ignore"; -$ignore{'"key (0-2147483647)"'} = "ignore"; -$ignore{'"route-map WORD <deny|permit> (1-65535)"'} = "ignore"; -$ignore{'"show route-map"'} = "ignore"; -$ignore{'"line vty"'} = "ignore"; -$ignore{'"who"'} = "ignore"; -$ignore{'"terminal monitor"'} = "ignore"; -$ignore{'"terminal no monitor"'} = "ignore"; -$ignore{'"show history"'} = "ignore"; -$ignore{'"router ospf [(1-65535)]"'} = "ignore"; -$ignore{'"address-family vpnv6 [unicast]"'} = "ignore"; -$ignore{'"address-family vpnv4 [unicast]"'} = "ignore"; -$ignore{'"logical-router (1-65535) ns NAME"'} = "ignore"; -$ignore{'"vrf-policy NAME"' } = "ignore"; -$ignore{'"exit-vrf-policy"' } = "ignore"; - my $cli_stomp = 0; foreach (@ARGV) { @@ -215,8 +159,7 @@ foreach (@ARGV) { $ecmd =~ s/\s+$//g; # Register $ecmd - if (defined ($cmd2str{$ecmd}) - && ! defined ($ignore{$cmd2str{$ecmd}})) { + if (defined ($cmd2str{$ecmd})) { my ($key); $key = $enode . "," . $cmd2str{$ecmd}; $ocmd{$key} = $ecmd; diff --git a/zebra/interface.c b/zebra/interface.c index 9abb54cec8..e9c54a629b 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1697,7 +1697,7 @@ link_param_cmd_unset (struct interface *ifp, uint32_t type) zebra_interface_parameters_update (ifp); } -DEFUN (link_params, +DEFUN_NOSH (link_params, link_params_cmd, "link-params", LINK_PARAMS_STR) @@ -1708,7 +1708,7 @@ DEFUN (link_params, return CMD_SUCCESS; } -DEFUN (exit_link_params, +DEFUN_NOSH (exit_link_params, exit_link_params_cmd, "exit-link-params", "Exit from Link Params configuration mode\n") diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c index b68b03e0c4..eaa80ac558 100644 --- a/zebra/zebra_mpls_openbsd.c +++ b/zebra/zebra_mpls_openbsd.c @@ -38,7 +38,7 @@ struct { } kr_state; static int -kernel_send_rtmsg (int action, mpls_label_t in_label, zebra_nhlfe_t *nhlfe) +kernel_send_rtmsg_v4 (int action, mpls_label_t in_label, zebra_nhlfe_t *nhlfe) { struct iovec iov[5]; struct rt_msghdr hdr; @@ -48,10 +48,10 @@ kernel_send_rtmsg (int action, mpls_label_t in_label, zebra_nhlfe_t *nhlfe) int ret; if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug ("kernel_send_rtmsg: 0x%x, label=%u", action, in_label); + zlog_debug ("%s: 0x%x, label=%u", __func__, action, in_label); /* initialize header */ - bzero(&hdr, sizeof (hdr)); + memset (&hdr, 0, sizeof (hdr)); hdr.rtm_version = RTM_VERSION; hdr.rtm_type = action; @@ -66,7 +66,7 @@ kernel_send_rtmsg (int action, mpls_label_t in_label, zebra_nhlfe_t *nhlfe) iov[iovcnt++].iov_len = sizeof (hdr); /* in label */ - bzero(&sa_label_in, sizeof (sa_label_in)); + memset (&sa_label_in, 0, sizeof (sa_label_in)); sa_label_in.smpls_len = sizeof (sa_label_in); sa_label_in.smpls_family = AF_MPLS; sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET); @@ -79,7 +79,7 @@ kernel_send_rtmsg (int action, mpls_label_t in_label, zebra_nhlfe_t *nhlfe) iov[iovcnt++].iov_len = sizeof (sa_label_in); /* nexthop */ - bzero(&nexthop, sizeof (nexthop)); + memset (&nexthop, 0, sizeof (nexthop)); nexthop.sin_len = sizeof (nexthop); nexthop.sin_family = AF_INET; nexthop.sin_addr = nhlfe->nexthop->gate.ipv4; @@ -94,7 +94,7 @@ kernel_send_rtmsg (int action, mpls_label_t in_label, zebra_nhlfe_t *nhlfe) /* If action is RTM_DELETE we have to get rid of MPLS infos */ if (action != RTM_DELETE) { - bzero(&sa_label_out, sizeof (sa_label_out)); + memset (&sa_label_out, 0, sizeof (sa_label_out)); sa_label_out.smpls_len = sizeof (sa_label_out); sa_label_out.smpls_family = AF_MPLS; sa_label_out.smpls_label = @@ -120,7 +120,116 @@ kernel_send_rtmsg (int action, mpls_label_t in_label, zebra_nhlfe_t *nhlfe) zlog_err ("Can't lower privileges"); if (ret == -1) - zlog_err ("kernel_send_rtmsg: %s", safe_strerror (errno)); + zlog_err ("%s: %s", __func__, safe_strerror (errno)); + + return ret; +} + +#if !defined(ROUNDUP) +#define ROUNDUP(a) \ + (((a) & (sizeof(long) - 1)) ? (1 + ((a) | (sizeof(long) - 1))) : (a)) +#endif + +static int +kernel_send_rtmsg_v6 (int action, mpls_label_t in_label, zebra_nhlfe_t *nhlfe) +{ + struct iovec iov[5]; + struct rt_msghdr hdr; + struct sockaddr_mpls sa_label_in, sa_label_out; + struct pad { + struct sockaddr_in6 addr; + char pad[sizeof(long)]; /* thank you IPv6 */ + } nexthop; + int iovcnt = 0; + int ret; + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: 0x%x, label=%u", __func__, action, in_label); + + /* initialize header */ + memset (&hdr, 0, sizeof (hdr)); + hdr.rtm_version = RTM_VERSION; + + hdr.rtm_type = action; + hdr.rtm_flags = RTF_UP; + hdr.rtm_fmask = RTF_MPLS; + hdr.rtm_seq = kr_state.rtseq++; /* overflow doesn't matter */ + hdr.rtm_msglen = sizeof (hdr); + hdr.rtm_hdrlen = sizeof (struct rt_msghdr); + hdr.rtm_priority = 0; + /* adjust iovec */ + iov[iovcnt].iov_base = &hdr; + iov[iovcnt++].iov_len = sizeof (hdr); + + /* in label */ + memset (&sa_label_in, 0, sizeof (sa_label_in)); + sa_label_in.smpls_len = sizeof (sa_label_in); + sa_label_in.smpls_family = AF_MPLS; + sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET); + /* adjust header */ + hdr.rtm_flags |= RTF_MPLS | RTF_MPATH; + hdr.rtm_addrs |= RTA_DST; + hdr.rtm_msglen += sizeof (sa_label_in); + /* adjust iovec */ + iov[iovcnt].iov_base = &sa_label_in; + iov[iovcnt++].iov_len = sizeof (sa_label_in); + + /* nexthop */ + memset (&nexthop, 0, sizeof (nexthop)); + nexthop.addr.sin6_len = sizeof (struct sockaddr_in6); + nexthop.addr.sin6_family = AF_INET6; + nexthop.addr.sin6_addr = nhlfe->nexthop->gate.ipv6; + if (IN6_IS_ADDR_LINKLOCAL (&nexthop.addr.sin6_addr)) + { + uint16_t tmp16; + struct sockaddr_in6 *sin6 = &nexthop.addr; + + nexthop.addr.sin6_scope_id = nhlfe->nexthop->ifindex; + + memcpy (&tmp16, &sin6->sin6_addr.s6_addr[2], sizeof (tmp16)); + tmp16 = htons (sin6->sin6_scope_id); + memcpy (&sin6->sin6_addr.s6_addr[2], &tmp16, sizeof (tmp16)); + sin6->sin6_scope_id = 0; + } + + /* adjust header */ + hdr.rtm_flags |= RTF_GATEWAY; + hdr.rtm_addrs |= RTA_GATEWAY; + hdr.rtm_msglen += ROUNDUP (sizeof (struct sockaddr_in6)); + /* adjust iovec */ + iov[iovcnt].iov_base = &nexthop; + iov[iovcnt++].iov_len = ROUNDUP (sizeof (struct sockaddr_in6)); + + /* If action is RTM_DELETE we have to get rid of MPLS infos */ + if (action != RTM_DELETE) + { + memset (&sa_label_out, 0, sizeof (sa_label_out)); + sa_label_out.smpls_len = sizeof (sa_label_out); + sa_label_out.smpls_family = AF_MPLS; + sa_label_out.smpls_label = + htonl(nhlfe->nexthop->nh_label->label[0] << MPLS_LABEL_OFFSET); + /* adjust header */ + hdr.rtm_addrs |= RTA_SRC; + hdr.rtm_flags |= RTF_MPLS; + hdr.rtm_msglen += sizeof (sa_label_out); + /* adjust iovec */ + iov[iovcnt].iov_base = &sa_label_out; + iov[iovcnt++].iov_len = sizeof (sa_label_out); + + if (nhlfe->nexthop->nh_label->label[0] == MPLS_LABEL_IMPLNULL) + hdr.rtm_mpls = MPLS_OP_POP; + else + hdr.rtm_mpls = MPLS_OP_SWAP; + } + + if (zserv_privs.change(ZPRIVS_RAISE)) + zlog_err ("Can't raise privileges"); + ret = writev (kr_state.fd, iov, iovcnt); + if (zserv_privs.change(ZPRIVS_LOWER)) + zlog_err ("Can't lower privileges"); + + if (ret == -1) + zlog_err ("%s: %s", __func__, safe_strerror (errno)); return ret; } @@ -141,10 +250,6 @@ kernel_lsp_cmd (int action, zebra_lsp_t *lsp) if (nexthop_num >= multipath_num) break; - /* XXX */ - if (NHLFE_FAMILY(nhlfe) == AF_INET6) - continue; - if (((action == RTM_ADD || action == RTM_CHANGE) && (CHECK_FLAG (nhlfe->flags, NHLFE_FLAG_SELECTED) && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))) || @@ -154,7 +259,17 @@ kernel_lsp_cmd (int action, zebra_lsp_t *lsp) { nexthop_num++; - kernel_send_rtmsg (action, lsp->ile.in_label, nhlfe); + switch (NHLFE_FAMILY(nhlfe)) + { + case AF_INET: + kernel_send_rtmsg_v4 (action, lsp->ile.in_label, nhlfe); + break; + case AF_INET6: + kernel_send_rtmsg_v6 (action, lsp->ile.in_label, nhlfe); + break; + default: + break; + } if (action == RTM_ADD || action == RTM_CHANGE) { SET_FLAG (nhlfe->flags, NHLFE_FLAG_INSTALLED); |
