diff --git a/.gitignore b/.gitignore index 546faf6926..507b193b4b 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,7 @@ build m4/*.m4 !m4/ax_sys_weak_alias.m4 !m4/ax_compare_version.m4 +!m4/ax_prog_perl_modules.m4 debian/autoreconf.after debian/autoreconf.before debian/files diff --git a/README b/README index 4476947490..95aa5eb248 100644 --- a/README +++ b/README @@ -1,9 +1,9 @@ -Quagga is free software that manages various IPv4 and IPv6 routing +Free Range Routing is free software that manages various IPv4 and IPv6 routing protocols. -Currently Quagga supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1, +Currently Free Range Routing supports BGP4, BGP4+, OSPFv2, OSPFv3, RIPv1, RIPv2, RIPng, PIM-SSM and LDP as well as very early support for IS-IS. See the file REPORTING-BUGS to report bugs. -Quagga is free software. See the file COPYING for copying conditions. +Free Range Routing is free software. See the file COPYING for copying conditions. diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 0e03392faf..4cf1f0daed 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1849,8 +1849,8 @@ int bgp_mp_reach_parse (struct bgp_attr_parser_args *args, struct bgp_nlri *mp_update) { - afi_t afi; - safi_t safi; + afi_t pkt_afi, afi; + safi_t pkt_safi, safi; bgp_size_t nlri_len; size_t start; struct stream *s; @@ -1874,8 +1874,20 @@ bgp_mp_reach_parse (struct bgp_attr_parser_args *args, } /* Load AFI, SAFI. */ - afi = stream_getw (s); - safi = stream_getc (s); + pkt_afi = stream_getw (s); + pkt_safi = stream_getc (s); + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) + { + /* Log if AFI or SAFI is unrecognized. This is not an error unless + * the attribute is otherwise malformed. + */ + if (bgp_debug_update(peer, NULL, NULL, 0)) + zlog_debug ("%s: MP_REACH received AFI %u or SAFI %u is unrecognized", + peer->host, pkt_afi, pkt_safi); + return BGP_ATTR_PARSE_ERROR; + } /* Get nexthop length. */ attre->mp_nexthop_len = stream_getc (s); @@ -1988,8 +2000,8 @@ bgp_mp_unreach_parse (struct bgp_attr_parser_args *args, struct bgp_nlri *mp_withdraw) { struct stream *s; - afi_t afi; - safi_t safi; + afi_t pkt_afi, afi; + safi_t pkt_safi, safi; u_int16_t withdraw_len; struct peer *const peer = args->peer; struct attr *const attr = args->attr; @@ -2001,9 +2013,21 @@ bgp_mp_unreach_parse (struct bgp_attr_parser_args *args, if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE)) return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; - afi = stream_getw (s); - safi = stream_getc (s); - + pkt_afi = stream_getw (s); + pkt_safi = stream_getc (s); + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) + { + /* Log if AFI or SAFI is unrecognized. This is not an error unless + * the attribute is otherwise malformed. + */ + if (bgp_debug_update(peer, NULL, NULL, 0)) + zlog_debug ("%s: MP_UNREACH received AFI %u or SAFI %u is unrecognized", + peer->host, pkt_afi, pkt_safi); + return BGP_ATTR_PARSE_ERROR; + } + withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE; mp_withdraw->afi = afi; @@ -2624,6 +2648,8 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi, struct attr *attr) { size_t sizep; + afi_t pkt_afi; + safi_t pkt_safi; /* Set extended bit always to encode the attribute length as 2 bytes */ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN); @@ -2631,8 +2657,12 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, afi_t nh_afi, sizep = stream_get_endp (s); stream_putw (s, 0); /* Marker: Attribute length. */ - stream_putw (s, afi); - stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi); + + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); + + stream_putw (s, pkt_afi); /* AFI */ + stream_putc (s, pkt_safi); /* SAFI */ /* Nexthop */ switch (nh_afi) @@ -3249,6 +3279,8 @@ size_t bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi) { unsigned long attrlen_pnt; + afi_t pkt_afi; + safi_t pkt_safi; /* Set extended bit always to encode the attribute length as 2 bytes */ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN); @@ -3257,8 +3289,12 @@ bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi) attrlen_pnt = stream_get_endp (s); stream_putw (s, 0); /* Length of this attribute. */ - stream_putw (s, afi); - stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi); + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); + + stream_putw (s, pkt_afi); + stream_putc (s, pkt_safi); + return attrlen_pnt; } diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 9e1b4392c9..4a06881041 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -79,9 +79,13 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso if (hdr->code == CAPABILITY_CODE_MP) { + afi_t afi; + safi_t safi; + + bgp_map_afi_safi_iana2int (ntohs(mpc.afi), mpc.safi, &afi, &safi); if (use_json) { - switch (ntohs (mpc.afi)) + switch (afi) { case AFI_IP: json_object_string_add(json_cap, "capabilityErrorMultiProtocolAfi", "IPv4"); @@ -93,7 +97,7 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso json_object_int_add(json_cap, "capabilityErrorMultiProtocolAfiUnknown", ntohs (mpc.afi)); break; } - switch (mpc.safi) + switch (safi) { case SAFI_UNICAST: json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "unicast"); @@ -101,7 +105,7 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso case SAFI_MULTICAST: json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "multicast"); break; - case SAFI_MPLS_LABELED_VPN: + case SAFI_MPLS_VPN: json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "MPLS-labeled VPN"); break; case SAFI_ENCAP: @@ -115,7 +119,7 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso else { vty_out (vty, " Capability error for: Multi protocol "); - switch (ntohs (mpc.afi)) + switch (afi) { case AFI_IP: vty_out (vty, "AFI IPv4, "); @@ -127,7 +131,7 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi)); break; } - switch (mpc.safi) + switch (safi) { case SAFI_UNICAST: vty_out (vty, "SAFI Unicast"); @@ -135,7 +139,7 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso case SAFI_MULTICAST: vty_out (vty, "SAFI Multicast"); break; - case SAFI_MPLS_LABELED_VPN: + case SAFI_MPLS_VPN: vty_out (vty, "SAFI MPLS-labeled VPN"); break; case SAFI_ENCAP: @@ -178,35 +182,6 @@ bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc) mpc->safi = stream_getc (s); } -int -bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi) -{ - switch (afi) - { - case AFI_IP: - case AFI_IP6: - switch (*safi) - { - /* BGP MPLS-labeled VPN SAFI isn't contigious with others, remap */ - case SAFI_MPLS_LABELED_VPN: - *safi = SAFI_MPLS_VPN; - case SAFI_UNICAST: - case SAFI_MULTICAST: - case SAFI_MPLS_VPN: - case SAFI_ENCAP: - return 1; - } - break; - case AFI_ETHER: - default: - break; - } - - zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi); - - return 0; -} - /* Set negotiated capability value. */ static int bgp_capability_mp (struct peer *peer, struct capability_header *hdr) @@ -228,7 +203,8 @@ bgp_capability_mp (struct peer *peer, struct capability_header *hdr) zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u", peer->host, mpc.afi, mpc.safi); - if (!bgp_afi_safi_valid_indices (mpc.afi, &mpc.safi)) + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int (mpc.afi, mpc.safi, &mpc.afi, &mpc.safi)) return -1; /* Now safi remapped, and afi/safi are valid array indices */ @@ -271,8 +247,8 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) { struct stream *s = BGP_INPUT (peer); struct capability_orf_entry entry; - afi_t afi; - safi_t safi; + afi_t pkt_afi, afi; + safi_t pkt_safi, safi; u_char type; u_char mode; u_int16_t sm_cap = 0; /* capability send-mode receive */ @@ -282,22 +258,25 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) /* ORF Entry header */ bgp_capability_mp_data (s, &entry.mpc); entry.num = stream_getc (s); - afi = entry.mpc.afi; - safi = entry.mpc.safi; + pkt_afi = entry.mpc.afi; + pkt_safi = entry.mpc.safi; if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u", peer->host, entry.mpc.afi, entry.mpc.safi); - /* Check AFI and SAFI. */ - if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi)) + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) { zlog_info ("%s Addr-family %d/%d not supported." " Ignoring the ORF capability", - peer->host, entry.mpc.afi, entry.mpc.safi); + peer->host, pkt_afi, pkt_safi); return 0; } + entry.mpc.afi = afi; + entry.mpc.safi = safi; + /* validate number field */ if (CAPABILITY_CODE_ORF_LEN + (entry.num * 2) > hdr->length) { @@ -321,7 +300,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) case ORF_MODE_RECEIVE: break; default: - bgp_capability_orf_not_support (peer, afi, safi, type, mode); + bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode); continue; } /* ORF Type and afi/safi error checks */ @@ -334,7 +313,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) case ORF_TYPE_PREFIX: break; default: - bgp_capability_orf_not_support (peer, afi, safi, type, mode); + bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode); continue; } break; @@ -344,12 +323,12 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) case ORF_TYPE_PREFIX_OLD: break; default: - bgp_capability_orf_not_support (peer, afi, safi, type, mode); + bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode); continue; } break; default: - bgp_capability_orf_not_support (peer, afi, safi, type, mode); + bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode); continue; } @@ -358,7 +337,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) || (afi == AFI_IP && safi == SAFI_MULTICAST) || (afi == AFI_IP6 && safi == SAFI_UNICAST))) { - bgp_capability_orf_not_support (peer, afi, safi, type, mode); + bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode); continue; } @@ -367,7 +346,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) " as %s for afi/safi: %d/%d", peer->host, LOOKUP (orf_type_str, type), LOOKUP (orf_mode_str, mode), - entry.mpc.afi, safi); + pkt_afi, pkt_safi); if (hdr->code == CAPABILITY_CODE_ORF) { @@ -381,7 +360,7 @@ bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr) } else { - bgp_capability_orf_not_support (peer, afi, safi, type, mode); + bgp_capability_orf_not_support (peer, pkt_afi, pkt_safi, type, mode); continue; } @@ -437,23 +416,26 @@ bgp_capability_restart (struct peer *peer, struct capability_header *caphdr) while (stream_get_getp (s) + 4 <= end) { - afi_t afi = stream_getw (s); - safi_t safi = stream_getc (s); + afi_t afi; + safi_t safi; + afi_t pkt_afi = stream_getw (s); + safi_t pkt_safi = stream_getc (s); u_char flag = stream_getc (s); - if (!bgp_afi_safi_valid_indices (afi, &safi)) + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) { if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported." " Ignore the Graceful Restart capability for this AFI/SAFI", - peer->host, afi, safi); + peer->host, pkt_afi, pkt_safi); } else if (!peer->afc[afi][safi]) { if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled." " Ignore the Graceful Restart capability", - peer->host, afi, safi); + peer->host, pkt_afi, pkt_safi); } else { @@ -512,22 +494,25 @@ bgp_capability_addpath (struct peer *peer, struct capability_header *hdr) while (stream_get_getp (s) + 4 <= end) { - afi_t afi = stream_getw (s); - safi_t safi = stream_getc (s); + afi_t afi; + safi_t safi; + afi_t pkt_afi = stream_getw (s); + safi_t pkt_safi = stream_getc (s); u_char send_receive = stream_getc (s); if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s OPEN has AddPath CAP for afi/safi: %u/%u%s%s", - peer->host, afi, safi, + peer->host, pkt_afi, pkt_safi, (send_receive & BGP_ADDPATH_RX) ? ", receive" : "", (send_receive & BGP_ADDPATH_TX) ? ", transmit" : ""); - if (!bgp_afi_safi_valid_indices (afi, &safi)) + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) { if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported." " Ignore the Addpath Attribute for this AFI/SAFI", - peer->host, afi, safi); + peer->host, pkt_afi, pkt_safi); continue; } else if (!peer->afc[afi][safi]) @@ -535,7 +520,7 @@ bgp_capability_addpath (struct peer *peer, struct capability_header *hdr) if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled." " Ignore the AddPath capability for this AFI/SAFI", - peer->host, afi, safi); + peer->host, pkt_afi, pkt_safi); continue; } @@ -565,20 +550,21 @@ bgp_capability_enhe (struct peer *peer, struct capability_header *hdr) while (stream_get_getp (s) + 6 <= end) { - afi_t afi = stream_getw (s); - safi_t safi = stream_getw (s); - afi_t nh_afi = stream_getw (s); + afi_t afi, pkt_afi = stream_getw (s); + safi_t safi, pkt_safi = stream_getw (s); + afi_t nh_afi, pkt_nh_afi = stream_getw (s); if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Received with afi/safi/next-hop afi: %u/%u/%u", - peer->host, afi, safi, nh_afi); + peer->host, pkt_afi, pkt_safi, pkt_nh_afi); - if (!bgp_afi_safi_valid_indices (afi, &safi)) + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) { if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported." " Ignore the ENHE Attribute for this AFI/SAFI", - peer->host, afi, safi); + peer->host, pkt_afi, pkt_safi); continue; } @@ -587,11 +573,13 @@ bgp_capability_enhe (struct peer *peer, struct capability_header *hdr) * possibilities, so we ignore other values with a log. Also, only * Unicast SAFI is currently supported (and expected). */ + nh_afi = afi_iana2int (pkt_nh_afi); + if (afi != AFI_IP || safi != SAFI_UNICAST || nh_afi != AFI_IP6) { zlog_warn ("%s Unexpected afi/safi/next-hop afi: %u/%u/%u " "in Extended Next-hop capability, ignoring", - peer->host, afi, safi, nh_afi); + peer->host, pkt_afi, pkt_safi, pkt_nh_afi); continue; } @@ -1174,9 +1162,11 @@ bgp_open_capability_orf (struct stream *s, struct peer *peer, unsigned long orfp; unsigned long numberp; int number_of_orfs = 0; + afi_t pkt_afi; + safi_t pkt_safi; - if (safi == SAFI_MPLS_VPN) - safi = SAFI_MPLS_LABELED_VPN; + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); stream_putc (s, BGP_OPEN_OPT_CAP); capp = stream_get_endp (s); /* Set Capability Len Pointer */ @@ -1184,9 +1174,9 @@ bgp_open_capability_orf (struct stream *s, struct peer *peer, stream_putc (s, code); /* Capability Code */ orfp = stream_get_endp (s); /* Set ORF Len Pointer */ stream_putc (s, 0); /* ORF Length */ - stream_putw (s, afi); + stream_putw (s, pkt_afi); stream_putc (s, 0); - stream_putc (s, safi); + stream_putc (s, pkt_safi); numberp = stream_get_endp (s); /* Set Number Pointer */ stream_putc (s, 0); /* Number of ORFs */ @@ -1235,8 +1225,8 @@ bgp_open_capability (struct stream *s, struct peer *peer) { u_char len; unsigned long cp, capp, rcapp; - afi_t afi; - safi_t safi; + afi_t afi, pkt_afi; + safi_t safi, pkt_safi; as_t local_as; u_int32_t restart_time; u_char afi_safi_count = 0; @@ -1254,55 +1244,29 @@ bgp_open_capability (struct stream *s, struct peer *peer) || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY)) return; - /* IPv4 unicast. */ - if (peer->afc[AFI_IP][SAFI_UNICAST]) - { - peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1; - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); - stream_putc (s, CAPABILITY_CODE_MP); - stream_putc (s, CAPABILITY_CODE_MP_LEN); - stream_putw (s, AFI_IP); - stream_putc (s, 0); - stream_putc (s, SAFI_UNICAST); - } - /* IPv4 multicast. */ - if (peer->afc[AFI_IP][SAFI_MULTICAST]) - { - peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1; - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); - stream_putc (s, CAPABILITY_CODE_MP); - stream_putc (s, CAPABILITY_CODE_MP_LEN); - stream_putw (s, AFI_IP); - stream_putc (s, 0); - stream_putc (s, SAFI_MULTICAST); - } - /* IPv4 VPN */ - if (peer->afc[AFI_IP][SAFI_MPLS_VPN]) - { - peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1; - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); - stream_putc (s, CAPABILITY_CODE_MP); - stream_putc (s, CAPABILITY_CODE_MP_LEN); - stream_putw (s, AFI_IP); - stream_putc (s, 0); - stream_putc (s, SAFI_MPLS_LABELED_VPN); - } - /* ENCAP */ - if (peer->afc[AFI_IP][SAFI_ENCAP]) - { - peer->afc_adv[AFI_IP][SAFI_ENCAP] = 1; - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); - stream_putc (s, CAPABILITY_CODE_MP); - stream_putc (s, CAPABILITY_CODE_MP_LEN); - stream_putw (s, AFI_IP); - stream_putc (s, 0); - stream_putc (s, SAFI_ENCAP); - } - /* Currently supporting RFC-5549 for Link-Local peering only */ + /* MP capability for configured AFI, SAFI */ + for (afi = AFI_IP ; afi < AFI_MAX ; afi++) + for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) + { + if (peer->afc[afi][safi]) + { + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); + + peer->afc_adv[afi][safi] = 1; + stream_putc (s, BGP_OPEN_OPT_CAP); + stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); + stream_putc (s, CAPABILITY_CODE_MP); + stream_putc (s, CAPABILITY_CODE_MP_LEN); + stream_putw (s, pkt_afi); + stream_putc (s, 0); + stream_putc (s, pkt_safi); + } + } + + /* Extended nexthop capability - currently supporting RFC-5549 for + * Link-Local peering only + */ if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE) && peer->su.sa.sa_family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr)) @@ -1322,54 +1286,6 @@ bgp_open_capability (struct stream *s, struct peer *peer) if (CHECK_FLAG (peer->af_cap[AFI_IP][SAFI_UNICAST], PEER_CAP_ENHE_AF_RCV)) SET_FLAG (peer->af_cap[AFI_IP][SAFI_UNICAST], PEER_CAP_ENHE_AF_NEGO); } - /* IPv6 unicast. */ - if (peer->afc[AFI_IP6][SAFI_UNICAST]) - { - peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1; - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); - stream_putc (s, CAPABILITY_CODE_MP); - stream_putc (s, CAPABILITY_CODE_MP_LEN); - stream_putw (s, AFI_IP6); - stream_putc (s, 0); - stream_putc (s, SAFI_UNICAST); - } - /* IPv6 multicast. */ - if (peer->afc[AFI_IP6][SAFI_MULTICAST]) - { - peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1; - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); - stream_putc (s, CAPABILITY_CODE_MP); - stream_putc (s, CAPABILITY_CODE_MP_LEN); - stream_putw (s, AFI_IP6); - stream_putc (s, 0); - stream_putc (s, SAFI_MULTICAST); - } - /* IPv6 VPN. */ - if (peer->afc[AFI_IP6][SAFI_MPLS_VPN]) - { - peer->afc_adv[AFI_IP6][SAFI_MPLS_VPN] = 1; - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); - stream_putc (s, CAPABILITY_CODE_MP); - stream_putc (s, CAPABILITY_CODE_MP_LEN); - stream_putw (s, AFI_IP6); - stream_putc (s, 0); - stream_putc (s, SAFI_MPLS_LABELED_VPN); - } - /* IPv6 ENCAP. */ - if (peer->afc[AFI_IP6][SAFI_ENCAP]) - { - peer->afc_adv[AFI_IP6][SAFI_ENCAP] = 1; - stream_putc (s, BGP_OPEN_OPT_CAP); - stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); - stream_putc (s, CAPABILITY_CODE_MP); - stream_putc (s, CAPABILITY_CODE_MP_LEN); - stream_putw (s, AFI_IP6); - stream_putc (s, 0); - stream_putc (s, SAFI_ENCAP); - } /* Route refresh. */ SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV); @@ -1418,8 +1334,11 @@ bgp_open_capability (struct stream *s, struct peer *peer) for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) if (peer->afc[afi][safi]) { - stream_putw (s, afi); - stream_putc (s, safi); + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); + + stream_putw (s, pkt_afi); + stream_putc (s, pkt_safi); if (adv_addpath_tx) { @@ -1533,8 +1452,10 @@ bgp_open_capability (struct stream *s, struct peer *peer) for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) if (peer->afc[afi][safi]) { - stream_putw (s, afi); - stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi); + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); + stream_putw (s, pkt_afi); + stream_putc (s, pkt_safi); if (bgp_flag_check(peer->bgp, BGP_FLAG_GR_PRESERVE_FWD)) stream_putc (s, RESTART_F_BIT); else diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h index 8ec0a5416b..b0a396ec11 100644 --- a/bgpd/bgp_open.h +++ b/bgpd/bgp_open.h @@ -115,6 +115,5 @@ extern int bgp_open_option_parse (struct peer *, u_char, int *); extern void bgp_open_capability (struct stream *, struct peer *); extern void bgp_capability_vty_out (struct vty *, struct peer *, u_char, json_object *); extern as_t peek_for_as4_capability (struct peer *, u_char); -extern int bgp_afi_safi_valid_indices (afi_t, safi_t *); #endif /* _QUAGGA_BGP_OPEN_H */ diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index dffca37dd3..38470a3c7e 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -147,6 +147,8 @@ static struct stream * bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi) { struct stream *s; + afi_t pkt_afi; + safi_t pkt_safi; if (DISABLE_BGP_ANNOUNCE) return NULL; @@ -169,13 +171,16 @@ bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi) } else { + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); + /* Total Path Attribute Length */ stream_putw (s, 6); stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI); stream_putc (s, 3); - stream_putw (s, afi); - stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi); + stream_putw (s, pkt_afi); + stream_putc (s, pkt_safi); } bgp_packet_set_size (s); @@ -690,15 +695,16 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi, struct stream *s; struct bgp_filter *filter; int orf_refresh = 0; + afi_t pkt_afi; + safi_t pkt_safi; if (DISABLE_BGP_ANNOUNCE) return; filter = &peer->filter[afi][safi]; - /* Adjust safi code. */ - if (safi == SAFI_MPLS_VPN) - safi = SAFI_MPLS_LABELED_VPN; + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); s = stream_new (BGP_MAX_PACKET_SIZE); @@ -709,9 +715,9 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi, bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD); /* Encode Route Refresh message. */ - stream_putw (s, afi); + stream_putw (s, pkt_afi); stream_putc (s, 0); - stream_putc (s, safi); + stream_putc (s, pkt_safi); if (orf_type == ORF_TYPE_PREFIX || orf_type == ORF_TYPE_PREFIX_OLD) @@ -734,7 +740,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi, zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d", peer->host, orf_type, (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"), - afi, safi); + pkt_afi, pkt_safi); } else { @@ -746,7 +752,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi, zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d", peer->host, orf_type, (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"), - afi, safi); + pkt_afi, pkt_safi); } /* Total ORF Entry Len. */ @@ -761,7 +767,7 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi, { if (! orf_refresh) zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d", - peer->host, afi, safi); + peer->host, pkt_afi, pkt_safi); } /* Add packet to the peer. */ @@ -776,10 +782,11 @@ bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi, int capability_code, int action) { struct stream *s; + afi_t pkt_afi; + safi_t pkt_safi; - /* Adjust safi code. */ - if (safi == SAFI_MPLS_VPN) - safi = SAFI_MPLS_LABELED_VPN; + /* Convert AFI, SAFI to values for packet. */ + bgp_map_afi_safi_int2iana (afi, safi, &pkt_afi, &pkt_safi); s = stream_new (BGP_MAX_PACKET_SIZE); @@ -792,14 +799,14 @@ bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi, stream_putc (s, action); stream_putc (s, CAPABILITY_CODE_MP); stream_putc (s, CAPABILITY_CODE_MP_LEN); - stream_putw (s, afi); + stream_putw (s, pkt_afi); stream_putc (s, 0); - stream_putc (s, safi); + stream_putc (s, pkt_safi); if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d", peer->host, action == CAPABILITY_ACTION_SET ? - "Advertising" : "Removing", afi, safi); + "Advertising" : "Removing", pkt_afi, pkt_safi); } /* Set packet size. */ @@ -1329,7 +1336,6 @@ bgp_nlri_parse (struct peer *peer, struct attr *attr, struct bgp_nlri *packet) case SAFI_MULTICAST: return bgp_nlri_parse_ip (peer, attr, packet); case SAFI_MPLS_VPN: - case SAFI_MPLS_LABELED_VPN: return bgp_nlri_parse_vpn (peer, attr, packet); case SAFI_ENCAP: return bgp_nlri_parse_encap (peer, attr, packet); @@ -1508,26 +1514,6 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) if (!nlris[i].nlri) continue; - /* We use afi and safi as indices into tables and what not. It would - * be impossible, at this time, to support unknown afi/safis. And - * anyway, the peer needs to be configured to enable the afi/safi - * explicitly which requires UI support. - * - * Ignore unknown afi/safi NLRIs. - * - * Note: This means nlri[x].afi/safi still can not be trusted for - * indexing later in this function! - * - * Note2: This will also remap the wire code-point for VPN safi to the - * internal safi_t point, as needs be. - */ - if(!bgp_afi_safi_valid_indices (nlris[i].afi, &nlris[i].safi)) - { - zlog_info ("%s [Info] UPDATE with unsupported AFI/SAFI %u/%u", - peer->host, nlris[i].afi, nlris[i].safi); - continue; - } - /* NLRI is processed iff the peer if configured for the specific afi/safi */ if (!peer->afc[nlris[i].afi][nlris[i].safi]) { @@ -1586,9 +1572,7 @@ bgp_update_receive (struct peer *peer, bgp_size_t size) safi = SAFI_UNICAST; } else if (attr.flag & ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI) - && nlris[NLRI_MP_WITHDRAW].length == 0 - && bgp_afi_safi_valid_indices (nlris[NLRI_MP_WITHDRAW].afi, - &nlris[NLRI_MP_WITHDRAW].safi)) + && nlris[NLRI_MP_WITHDRAW].length == 0) { afi = nlris[NLRI_MP_WITHDRAW].afi; safi = nlris[NLRI_MP_WITHDRAW].safi; @@ -1727,8 +1711,8 @@ bgp_keepalive_receive (struct peer *peer, bgp_size_t size) static void bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) { - afi_t afi; - safi_t safi; + afi_t pkt_afi, afi; + safi_t pkt_safi, safi; struct stream *s; struct peer_af *paf; struct update_group *updgrp; @@ -1757,28 +1741,22 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) s = peer->ibuf; /* Parse packet. */ - afi = stream_getw (s); + pkt_afi = stream_getw (s); (void)stream_getc (s); - safi = stream_getc (s); + pkt_safi = stream_getc (s); if (bgp_debug_update(peer, NULL, NULL, 0)) zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d", - peer->host, afi, safi); + peer->host, pkt_afi, pkt_safi); - /* Check AFI and SAFI. */ - if ((afi != AFI_IP && afi != AFI_IP6) - || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST - && safi != SAFI_MPLS_LABELED_VPN)) + /* Convert AFI, SAFI to internal values and check. */ + if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) { zlog_info ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored", - peer->host, afi, safi); + peer->host, pkt_afi, pkt_safi); return; } - /* Adjust safi code. */ - if (safi == SAFI_MPLS_LABELED_VPN) - safi = SAFI_MPLS_VPN; - if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) { u_char *end; @@ -1954,8 +1932,8 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length) struct capability_mp_data mpc; struct capability_header *hdr; u_char action; - afi_t afi; - safi_t safi; + afi_t pkt_afi, afi; + safi_t pkt_safi, safi; end = pnt + length; @@ -1999,18 +1977,19 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length) /* We know MP Capability Code. */ if (hdr->code == CAPABILITY_CODE_MP) { - afi = ntohs (mpc.afi); - safi = mpc.safi; + pkt_afi = ntohs (mpc.afi); + pkt_safi = mpc.safi; /* Ignore capability when override-capability is set. */ if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) continue; - if (!bgp_afi_safi_valid_indices (afi, &safi)) + /* Convert AFI, SAFI to internal values. */ + if (bgp_map_afi_safi_iana2int (pkt_afi, pkt_safi, &afi, &safi)) { if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid " - "(%u/%u)", peer->host, afi, safi); + "(%u/%u)", peer->host, pkt_afi, pkt_safi); continue; } @@ -2020,7 +1999,7 @@ bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length) peer->host, action == CAPABILITY_ACTION_SET ? "Advertising" : "Removing", - ntohs(mpc.afi) , mpc.safi); + pkt_afi, pkt_safi); if (action == CAPABILITY_ACTION_SET) { diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 09d5a84988..b25101f28f 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2113,6 +2113,9 @@ int bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, safi_t safi, int always) { + afi_t pkt_afi; + safi_t pkt_safi; + if (!CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) return 0; @@ -2130,15 +2133,15 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) return 0; + /* Convert AFI, SAFI to values for packet. */ + pkt_afi = afi_int2iana (afi); + pkt_safi = safi_int2iana (safi); { u_int8_t ndata[7]; - if (safi == SAFI_MPLS_VPN) - safi = SAFI_MPLS_LABELED_VPN; - - ndata[0] = (afi >> 8); - ndata[1] = afi; - ndata[2] = safi; + ndata[0] = (pkt_afi >> 8); + ndata[1] = pkt_afi; + ndata[2] = pkt_safi; ndata[3] = (peer->pmax[afi][safi] >> 24); ndata[4] = (peer->pmax[afi][safi] >> 16); ndata[5] = (peer->pmax[afi][safi] >> 8); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 95b7250d33..6d23af03e4 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -2944,12 +2944,14 @@ DEFUN (neighbor_local_as, int idx_number = 3; struct peer *peer; int ret; + as_t as; peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); if (! peer) return CMD_WARNING; - ret = peer_local_as_set (peer, atoi (argv[idx_number]->arg), 0, 0); + VTY_GET_INTEGER_RANGE ("Local AS", as, argv[idx_number]->arg, 1, BGP_AS4_MAX); + ret = peer_local_as_set (peer, as, 0, 0); return bgp_vty_return (vty, ret); } @@ -2966,12 +2968,14 @@ DEFUN (neighbor_local_as_no_prepend, int idx_number = 3; struct peer *peer; int ret; + as_t as; peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); if (! peer) return CMD_WARNING; - ret = peer_local_as_set (peer, atoi (argv[idx_number]->arg), 1, 0); + VTY_GET_INTEGER_RANGE ("Local AS", as, argv[idx_number]->arg, 1, BGP_AS4_MAX); + ret = peer_local_as_set (peer, as, 1, 0); return bgp_vty_return (vty, ret); } @@ -2989,12 +2993,14 @@ DEFUN (neighbor_local_as_no_prepend_replace_as, int idx_number = 3; struct peer *peer; int ret; + as_t as; peer = peer_and_group_lookup_vty (vty, argv[idx_peer]->arg); if (! peer) return CMD_WARNING; - ret = peer_local_as_set (peer, atoi (argv[idx_number]->arg), 1, 1); + VTY_GET_INTEGER_RANGE ("Local AS", as, argv[idx_number]->arg, 1, BGP_AS4_MAX); + ret = peer_local_as_set (peer, as, 1, 1); return bgp_vty_return (vty, ret); } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index f9c3f9af4b..5457822f3b 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -651,6 +651,35 @@ bgp_listen_limit_unset (struct bgp *bgp) return 0; } +int +bgp_map_afi_safi_iana2int (afi_t pkt_afi, safi_t pkt_safi, + afi_t *afi, safi_t *safi) +{ + /* Map from IANA values to internal values, return error if + * values are unrecognized. + */ + *afi = afi_iana2int (pkt_afi); + *safi = safi_iana2int (pkt_safi); + if (*afi == AFI_MAX || *safi == SAFI_MAX) + return -1; + + return 0; +} + +int +bgp_map_afi_safi_int2iana (afi_t afi, safi_t safi, + afi_t *pkt_afi, safi_t *pkt_safi) +{ + /* Map from internal values to IANA values, return error if + * internal values are bad (unexpected). + */ + if (afi == AFI_MAX || safi == SAFI_MAX) + return -1; + *pkt_afi = afi_int2iana (afi); + *pkt_safi = safi_int2iana (safi); + return 0; +} + struct peer_af * peer_af_create (struct peer *peer, afi_t afi, safi_t safi) { diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 9befd63703..2718805130 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1078,10 +1078,6 @@ struct bgp_nlri #define BGP_DEFAULT_RESTART_TIME 120 #define BGP_DEFAULT_STALEPATH_TIME 360 -/* RFC4364 */ -#define SAFI_MPLS_LABELED_VPN 128 -#define BGP_SAFI_VPN 128 - /* BGP uptime string length. */ #define BGP_UPTIME_LEN 25 @@ -1358,6 +1354,13 @@ extern void bgp_route_map_terminate(void); extern int peer_cmp (struct peer *p1, struct peer *p2); +extern int +bgp_map_afi_safi_iana2int (afi_t pkt_afi, safi_t pkt_safi, + afi_t *afi, safi_t *safi); +extern int +bgp_map_afi_safi_int2iana (afi_t afi, safi_t safi, + afi_t *pkt_afi, safi_t *pkt_safi); + extern struct peer_af * peer_af_create (struct peer *, afi_t, safi_t); extern struct peer_af * peer_af_find (struct peer *, afi_t, safi_t); extern int peer_af_delete (struct peer *, afi_t, safi_t); diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index 25c05e65f8..716a1fb537 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -4086,7 +4086,6 @@ rfapiBgpInfoFilteredImportFunction (safi_t safi) switch (safi) { case SAFI_MPLS_VPN: - case BGP_SAFI_VPN: return rfapiBgpInfoFilteredImportVPN; case SAFI_ENCAP: @@ -4203,7 +4202,7 @@ rfapiProcessUpdate ( label); } - if (safi == SAFI_MPLS_VPN || safi == BGP_SAFI_VPN) + if (safi == SAFI_MPLS_VPN) { vnc_direct_bgp_rh_add_route (bgp, afi, p, peer, attr); } @@ -4332,7 +4331,7 @@ rfapiProcessWithdraw ( } /* TBD the deletion should happen after the lifetime expires */ - if (safi == SAFI_MPLS_VPN || safi == BGP_SAFI_VPN) + if (safi == SAFI_MPLS_VPN) vnc_direct_bgp_rh_del_route (bgp, afi, p, peer); if (safi == SAFI_MPLS_VPN) diff --git a/configure.ac b/configure.ac index 8050b9c832..fcc0de1b22 100755 --- a/configure.ac +++ b/configure.ac @@ -292,6 +292,8 @@ if test $ac_cv_lib_json_c_json_object_get = no; then fi fi +AX_PROG_PERL_MODULES(XML::LibXML, , AC_MSG_ERROR(XML::LibXML perl module is needed to compile)) + AC_ARG_ENABLE([dev_build], AS_HELP_STRING([--enable-dev-build], [build for development])) diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 0ece4c919a..da24a7f0d3 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -544,6 +544,14 @@ lsp_update (struct isis_lsp *lsp, struct stream *stream, if (dnode) dnode_destroy (dict_delete (area->lspdb[level - 1], dnode)); + if (lsp->own_lsp) + { + zlog_err("ISIS-Upd (%s): BUG updating LSP %s still marked as own LSP", + area->area_tag, rawlspid_print(lsp->lsp_header->lsp_id)); + lsp_clear_data(lsp); + lsp->own_lsp = 0; + } + /* rebuild the lsp data */ lsp_update_data (lsp, stream, area, level); diff --git a/ldpd/.gitignore b/ldpd/.gitignore index be90d42119..e4ee82587a 100644 --- a/ldpd/.gitignore +++ b/ldpd/.gitignore @@ -15,4 +15,4 @@ TAGS .arch-ids *~ *.loT - +ldp_vty_cmds.c diff --git a/ldpd/Makefile.am b/ldpd/Makefile.am index c292adf6fc..e7da216a65 100644 --- a/ldpd/Makefile.am +++ b/ldpd/Makefile.am @@ -9,6 +9,8 @@ AM_CFLAGS = $(WERROR) noinst_LIBRARIES = libldp.a sbin_PROGRAMS = ldpd +BUILT_SOURCES = ldp_vty_cmds.c + libldp_a_SOURCES = \ accept.c address.c adjacency.c control.c hello.c init.c interface.c \ keepalive.c l2vpn.c labelmapping.c lde.c lde_lib.c ldpd.c \ @@ -19,6 +21,9 @@ libldp_a_SOURCES = \ 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 > $@ + ldpd_SOURCES = ldpd.c ldpd_LDADD = libldp.a ../lib/libzebra.la @LIBCAP@ diff --git a/ldpd/adjacency.c b/ldpd/adjacency.c index 3607ee96b3..2e7b43296a 100644 --- a/ldpd/adjacency.c +++ b/ldpd/adjacency.c @@ -25,12 +25,55 @@ #include "ldpe.h" #include "log.h" +static __inline int adj_compare(struct adj *, struct adj *); static int adj_itimer(struct thread *); -static void tnbr_del(struct tnbr *); +static __inline int tnbr_compare(struct tnbr *, struct tnbr *); +static void tnbr_del(struct ldpd_conf *, struct tnbr *); static int tnbr_hello_timer(struct thread *); static void tnbr_start_hello_timer(struct tnbr *); static void tnbr_stop_hello_timer(struct tnbr *); +RB_GENERATE(global_adj_head, adj, global_entry, adj_compare) +RB_GENERATE(nbr_adj_head, adj, nbr_entry, adj_compare) +RB_GENERATE(ia_adj_head, adj, ia_entry, adj_compare) +RB_GENERATE(tnbr_head, tnbr, entry, tnbr_compare) + +static __inline int +adj_compare(struct adj *a, struct adj *b) +{ + if (a->source.type < b->source.type) + return (-1); + if (a->source.type > b->source.type) + return (1); + + switch (a->source.type) { + case HELLO_LINK: + if (strcmp(a->source.link.ia->iface->name, + b->source.link.ia->iface->name) < 0) + return (-1); + if (strcmp(a->source.link.ia->iface->name, + b->source.link.ia->iface->name) > 0) + return (1); + if (a->source.link.ia->af < b->source.link.ia->af) + return (-1); + if (a->source.link.ia->af > b->source.link.ia->af) + return (1); + return (ldp_addrcmp(a->source.link.ia->af, + &a->source.link.src_addr, &b->source.link.src_addr)); + case HELLO_TARGETED: + if (a->source.target->af < b->source.target->af) + return (-1); + if (a->source.target->af > b->source.target->af) + return (1); + return (ldp_addrcmp(a->source.target->af, + &a->source.target->addr, &b->source.target->addr)); + default: + fatalx("adj_get_af: unknown hello type"); + } + + return (0); +} + struct adj * adj_new(struct in_addr lsr_id, struct hello_source *source, union ldpd_addr *addr) @@ -48,11 +91,11 @@ adj_new(struct in_addr lsr_id, struct hello_source *source, adj->source = *source; adj->trans_addr = *addr; - LIST_INSERT_HEAD(&global.adj_list, adj, global_entry); + RB_INSERT(global_adj_head, &global.adj_tree, adj); switch (source->type) { case HELLO_LINK: - LIST_INSERT_HEAD(&source->link.ia->adj_list, adj, ia_entry); + RB_INSERT(ia_adj_head, &source->link.ia->adj_tree, adj); break; case HELLO_TARGETED: source->target->adj = adj; @@ -70,12 +113,12 @@ adj_del_single(struct adj *adj) adj_stop_itimer(adj); - LIST_REMOVE(adj, global_entry); + RB_REMOVE(global_adj_head, &global.adj_tree, adj); if (adj->nbr) - LIST_REMOVE(adj, nbr_entry); + RB_REMOVE(nbr_adj_head, &adj->nbr->adj_tree, adj); switch (adj->source.type) { case HELLO_LINK: - LIST_REMOVE(adj, ia_entry); + RB_REMOVE(ia_adj_head, &adj->source.link.ia->adj_tree, adj); break; case HELLO_TARGETED: adj->source.target->adj = NULL; @@ -99,7 +142,7 @@ adj_del(struct adj *adj, uint32_t notif_status) * then delete it. */ if (nbr && nbr_adj_count(nbr, nbr->af) == 0) { - LIST_FOREACH_SAFE(adj, &nbr->adj_list, nbr_entry, atmp) + RB_FOREACH_SAFE(adj, nbr_adj_head, &nbr->adj_tree, atmp) adj_del_single(adj); session_shutdown(nbr, notif_status, 0, 0); nbr_del(nbr); @@ -109,27 +152,9 @@ adj_del(struct adj *adj, uint32_t notif_status) struct adj * adj_find(struct hello_source *source) { - struct adj *adj; - - LIST_FOREACH(adj, &global.adj_list, global_entry) { - if (adj->source.type != source->type) - continue; - - switch (source->type) { - case HELLO_LINK: - if (ldp_addrcmp(source->link.ia->af, - &adj->source.link.src_addr, - &source->link.src_addr) == 0) - return (adj); - break; - case HELLO_TARGETED: - if (adj->source.target == source->target) - return (adj); - break; - } - } - - return (NULL); + struct adj adj; + adj.source = *source; + return (RB_FIND(global_adj_head, &global.adj_tree, &adj)); } int @@ -161,7 +186,7 @@ adj_itimer(struct thread *thread) if (!(adj->source.target->flags & F_TNBR_CONFIGURED) && adj->source.target->pw_count == 0) { /* remove dynamic targeted neighbor */ - tnbr_del(adj->source.target); + tnbr_del(leconf, adj->source.target); return (0); } adj->source.target->adj = NULL; @@ -188,6 +213,17 @@ adj_stop_itimer(struct adj *adj) /* targeted neighbors */ +static __inline int +tnbr_compare(struct tnbr *a, struct tnbr *b) +{ + if (a->af < b->af) + return (-1); + if (a->af > b->af) + return (1); + + return (ldp_addrcmp(a->af, &a->addr, &b->addr)); +} + struct tnbr * tnbr_new(int af, union ldpd_addr *addr) { @@ -204,34 +240,30 @@ tnbr_new(int af, union ldpd_addr *addr) } static void -tnbr_del(struct tnbr *tnbr) +tnbr_del(struct ldpd_conf *xconf, struct tnbr *tnbr) { tnbr_stop_hello_timer(tnbr); if (tnbr->adj) adj_del(tnbr->adj, S_SHUTDOWN); - LIST_REMOVE(tnbr, entry); + RB_REMOVE(tnbr_head, &xconf->tnbr_tree, tnbr); free(tnbr); } struct tnbr * tnbr_find(struct ldpd_conf *xconf, int af, union ldpd_addr *addr) { - struct tnbr *tnbr; - - LIST_FOREACH(tnbr, &xconf->tnbr_list, entry) - if (af == tnbr->af && - ldp_addrcmp(af, addr, &tnbr->addr) == 0) - return (tnbr); - - return (NULL); + struct tnbr tnbr; + tnbr.af = af; + tnbr.addr = *addr; + return (RB_FIND(tnbr_head, &xconf->tnbr_tree, &tnbr)); } struct tnbr * -tnbr_check(struct tnbr *tnbr) +tnbr_check(struct ldpd_conf *xconf, struct tnbr *tnbr) { if (!(tnbr->flags & (F_TNBR_CONFIGURED|F_TNBR_DYNAMIC)) && tnbr->pw_count == 0) { - tnbr_del(tnbr); + tnbr_del(xconf, tnbr); return (NULL); } @@ -276,7 +308,7 @@ tnbr_update_all(int af) struct tnbr *tnbr; /* update targeted neighbors */ - LIST_FOREACH(tnbr, &leconf->tnbr_list, entry) + RB_FOREACH(tnbr, tnbr_head, &leconf->tnbr_tree) if (tnbr->af == af || af == AF_UNSPEC) tnbr_update(tnbr); } diff --git a/ldpd/hello.c b/ldpd/hello.c index 755b25aa85..95be1d5111 100644 --- a/ldpd/hello.c +++ b/ldpd/hello.c @@ -261,7 +261,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af, if (tnbr && (tnbr->flags & F_TNBR_DYNAMIC) && !((flags & F_HELLO_REQ_TARG))) { tnbr->flags &= ~F_TNBR_DYNAMIC; - tnbr = tnbr_check(tnbr); + tnbr = tnbr_check(leconf, tnbr); } if (!tnbr) { @@ -273,7 +273,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af, tnbr = tnbr_new(af, src); tnbr->flags |= F_TNBR_DYNAMIC; tnbr_update(tnbr); - LIST_INSERT_HEAD(&leconf->tnbr_list, tnbr, entry); + RB_INSERT(tnbr_head, &leconf->tnbr_tree, tnbr); } source.type = HELLO_TARGETED; @@ -364,7 +364,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af, adj = adj_new(lsr_id, &source, &trans_addr); if (nbr) { adj->nbr = nbr; - LIST_INSERT_HEAD(&nbr->adj_list, adj, nbr_entry); + RB_INSERT(nbr_adj_head, &nbr->adj_tree, adj); } } diff --git a/ldpd/interface.c b/ldpd/interface.c index b6472fe5e8..8fea91b878 100644 --- a/ldpd/interface.c +++ b/ldpd/interface.c @@ -26,6 +26,7 @@ #include "sockopt.h" +static __inline int iface_compare(struct iface *, struct iface *); static struct if_addr *if_addr_new(struct kaddr *); static struct if_addr *if_addr_lookup(struct if_addr_head *, struct kaddr *); static int if_start(struct iface *, int); @@ -39,6 +40,14 @@ static int if_leave_ipv4_group(struct iface *, struct in_addr *); static int if_join_ipv6_group(struct iface *, struct in6_addr *); static int if_leave_ipv6_group(struct iface *, struct in6_addr *); +RB_GENERATE(iface_head, iface, entry, iface_compare) + +static __inline int +iface_compare(struct iface *a, struct iface *b) +{ + return (strcmp(a->name, b->name)); +} + struct iface * if_new(struct kif *kif) { @@ -57,30 +66,18 @@ if_new(struct kif *kif) iface->ipv4.iface = iface; iface->ipv4.enabled = 0; iface->ipv4.state = IF_STA_DOWN; - LIST_INIT(&iface->ipv4.adj_list); + RB_INIT(&iface->ipv4.adj_tree); /* ipv6 */ iface->ipv6.af = AF_INET6; iface->ipv6.iface = iface; iface->ipv6.enabled = 0; iface->ipv6.state = IF_STA_DOWN; - LIST_INIT(&iface->ipv6.adj_list); + RB_INIT(&iface->ipv6.adj_tree); return (iface); } -struct iface * -if_lookup(struct ldpd_conf *xconf, unsigned short ifindex) -{ - struct iface *iface; - - LIST_FOREACH(iface, &xconf->iface_list, entry) - if (iface->ifindex == ifindex) - return (iface); - - return (NULL); -} - void if_exit(struct iface *iface) { @@ -100,17 +97,25 @@ if_exit(struct iface *iface) } struct iface * -if_lookup_name(struct ldpd_conf *xconf, const char *ifname) +if_lookup(struct ldpd_conf *xconf, unsigned short ifindex) { struct iface *iface; - LIST_FOREACH(iface, &xconf->iface_list, entry) - if (strcmp(iface->name, ifname) == 0) + RB_FOREACH(iface, iface_head, &xconf->iface_tree) + if (iface->ifindex == ifindex) return (iface); return (NULL); } +struct iface * +if_lookup_name(struct ldpd_conf *xconf, const char *ifname) +{ + struct iface iface; + strlcpy(iface.name, ifname, sizeof(iface.name)); + return (RB_FIND(iface_head, &xconf->iface_tree, &iface)); +} + void if_update_info(struct iface *iface, struct kif *kif) { @@ -288,7 +293,7 @@ if_reset(struct iface *iface, int af) ia = iface_af_get(iface, af); if_stop_hello_timer(ia); - while ((adj = LIST_FIRST(&ia->adj_list)) != NULL) + while ((adj = RB_ROOT(&ia->adj_tree)) != NULL) adj_del(adj, S_SHUTDOWN); /* try to cleanup */ @@ -380,7 +385,7 @@ if_update_all(int af) { struct iface *iface; - LIST_FOREACH(iface, &leconf->iface_list, entry) + RB_FOREACH(iface, iface_head, &leconf->iface_tree) if_update(iface, af); } @@ -460,7 +465,7 @@ if_to_ctl(struct iface_af *ia) ictl.uptime = 0; ictl.adj_cnt = 0; - LIST_FOREACH(adj, &ia->adj_list, ia_entry) + RB_FOREACH(adj, ia_adj_head, &ia->adj_tree) ictl.adj_cnt++; return (&ictl); diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c index 851ff77b73..c1d0437fba 100644 --- a/ldpd/l2vpn.c +++ b/ldpd/l2vpn.c @@ -26,7 +26,20 @@ #include "lde.h" #include "log.h" -static void l2vpn_pw_fec(struct l2vpn_pw *, struct fec *); +static void l2vpn_pw_fec(struct l2vpn_pw *, struct fec *); +static __inline int l2vpn_compare(struct l2vpn *, struct l2vpn *); +static __inline int l2vpn_if_compare(struct l2vpn_if *, struct l2vpn_if *); +static __inline int l2vpn_pw_compare(struct l2vpn_pw *, struct l2vpn_pw *); + +RB_GENERATE(l2vpn_head, l2vpn, entry, l2vpn_compare) +RB_GENERATE(l2vpn_if_head, l2vpn_if, entry, l2vpn_if_compare) +RB_GENERATE(l2vpn_pw_head, l2vpn_pw, entry, l2vpn_pw_compare) + +static __inline int +l2vpn_compare(struct l2vpn *a, struct l2vpn *b) +{ + return (strcmp(a->name, b->name)); +} struct l2vpn * l2vpn_new(const char *name) @@ -42,9 +55,9 @@ l2vpn_new(const char *name) l2vpn->mtu = DEFAULT_L2VPN_MTU; l2vpn->pw_type = DEFAULT_PW_TYPE; - LIST_INIT(&l2vpn->if_list); - LIST_INIT(&l2vpn->pw_list); - LIST_INIT(&l2vpn->pw_inactive_list); + RB_INIT(&l2vpn->if_tree); + RB_INIT(&l2vpn->pw_tree); + RB_INIT(&l2vpn->pw_inactive_tree); return (l2vpn); } @@ -52,13 +65,9 @@ l2vpn_new(const char *name) struct l2vpn * l2vpn_find(struct ldpd_conf *xconf, const char *name) { - struct l2vpn *l2vpn; - - LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) - if (strcmp(l2vpn->name, name) == 0) - return (l2vpn); - - return (NULL); + struct l2vpn l2vpn; + strlcpy(l2vpn.name, name, sizeof(l2vpn.name)); + return (RB_FIND(l2vpn_head, &xconf->l2vpn_tree, &l2vpn)); } void @@ -67,16 +76,16 @@ l2vpn_del(struct l2vpn *l2vpn) struct l2vpn_if *lif; struct l2vpn_pw *pw; - while ((lif = LIST_FIRST(&l2vpn->if_list)) != NULL) { - LIST_REMOVE(lif, entry); + while ((lif = RB_ROOT(&l2vpn->if_tree)) != NULL) { + RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); free(lif); } - while ((pw = LIST_FIRST(&l2vpn->pw_list)) != NULL) { - LIST_REMOVE(pw, entry); + while ((pw = RB_ROOT(&l2vpn->pw_tree)) != NULL) { + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw); free(pw); } - while ((pw = LIST_FIRST(&l2vpn->pw_inactive_list)) != NULL) { - LIST_REMOVE(pw, entry); + while ((pw = RB_ROOT(&l2vpn->pw_inactive_tree)) != NULL) { + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); free(pw); } @@ -88,7 +97,7 @@ l2vpn_init(struct l2vpn *l2vpn) { struct l2vpn_pw *pw; - LIST_FOREACH(pw, &l2vpn->pw_list, entry) + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) l2vpn_pw_init(pw); } @@ -97,10 +106,16 @@ l2vpn_exit(struct l2vpn *l2vpn) { struct l2vpn_pw *pw; - LIST_FOREACH(pw, &l2vpn->pw_list, entry) + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) l2vpn_pw_exit(pw); } +static __inline int +l2vpn_if_compare(struct l2vpn_if *a, struct l2vpn_if *b) +{ + return (strcmp(a->ifname, b->ifname)); +} + struct l2vpn_if * l2vpn_if_new(struct l2vpn *l2vpn, struct kif *kif) { @@ -122,7 +137,7 @@ l2vpn_if_find(struct l2vpn *l2vpn, unsigned int ifindex) { struct l2vpn_if *lif; - LIST_FOREACH(lif, &l2vpn->if_list, entry) + RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) if (lif->ifindex == ifindex) return (lif); @@ -132,15 +147,16 @@ l2vpn_if_find(struct l2vpn *l2vpn, unsigned int ifindex) struct l2vpn_if * l2vpn_if_find_name(struct l2vpn *l2vpn, const char *ifname) { - struct l2vpn_if *lif; - - LIST_FOREACH(lif, &l2vpn->if_list, entry) - if (strcmp(lif->ifname, ifname) == 0) - return (lif); - - return (NULL); + struct l2vpn_if lif; + strlcpy(lif.ifname, ifname, sizeof(lif.ifname)); + return (RB_FIND(l2vpn_if_head, &l2vpn->if_tree, &lif)); } +static __inline int +l2vpn_pw_compare(struct l2vpn_pw *a, struct l2vpn_pw *b) +{ + return (strcmp(a->ifname, b->ifname)); +} struct l2vpn_pw * l2vpn_pw_new(struct l2vpn *l2vpn, struct kif *kif) @@ -162,10 +178,10 @@ l2vpn_pw_find(struct l2vpn *l2vpn, unsigned int ifindex) { struct l2vpn_pw *pw; - LIST_FOREACH(pw, &l2vpn->pw_list, entry) + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) if (pw->ifindex == ifindex) return (pw); - LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) if (pw->ifindex == ifindex) return (pw); @@ -176,15 +192,13 @@ struct l2vpn_pw * l2vpn_pw_find_name(struct l2vpn *l2vpn, const char *ifname) { struct l2vpn_pw *pw; + struct l2vpn_pw s; - LIST_FOREACH(pw, &l2vpn->pw_list, entry) - if (strcmp(pw->ifname, ifname) == 0) - return (pw); - LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) - if (strcmp(pw->ifname, ifname) == 0) - return (pw); - - return (NULL); + 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)); } void @@ -399,8 +413,8 @@ l2vpn_sync_pws(int af, union ldpd_addr *addr) struct fec_node *fn; struct fec_nh *fnh; - LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry) { - LIST_FOREACH(pw, &l2vpn->pw_list, entry) { + RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) { + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) { if (af != pw->af || ldp_addrcmp(af, &pw->addr, addr)) continue; @@ -428,8 +442,8 @@ l2vpn_pw_ctl(pid_t pid) struct l2vpn_pw *pw; static struct ctl_pw pwctl; - LIST_FOREACH(l2vpn, &ldeconf->l2vpn_list, entry) - LIST_FOREACH(pw, &l2vpn->pw_list, entry) { + RB_FOREACH(l2vpn, l2vpn_head, &ldeconf->l2vpn_tree) + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) { memset(&pwctl, 0, sizeof(pwctl)); strlcpy(pwctl.l2vpn_name, pw->l2vpn->name, sizeof(pwctl.l2vpn_name)); @@ -459,7 +473,7 @@ l2vpn_binding_ctl(pid_t pid) fn = (struct fec_node *)f; if (fn->local_label == NO_LABEL && - LIST_EMPTY(&fn->downstream)) + RB_EMPTY(&fn->downstream)) continue; memset(&pwctl, 0, sizeof(pwctl)); @@ -477,7 +491,7 @@ l2vpn_binding_ctl(pid_t pid) } else pwctl.local_label = NO_LABEL; - LIST_FOREACH(me, &fn->downstream, entry) + RB_FOREACH(me, lde_map_head, &fn->downstream) if (f->u.pwid.lsr_id.s_addr == me->nexthop->id.s_addr) break; @@ -508,7 +522,7 @@ ldpe_l2vpn_init(struct l2vpn *l2vpn) { struct l2vpn_pw *pw; - LIST_FOREACH(pw, &l2vpn->pw_list, entry) + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) ldpe_l2vpn_pw_init(pw); } @@ -517,7 +531,7 @@ ldpe_l2vpn_exit(struct l2vpn *l2vpn) { struct l2vpn_pw *pw; - LIST_FOREACH(pw, &l2vpn->pw_list, entry) + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) ldpe_l2vpn_pw_exit(pw); } @@ -530,7 +544,7 @@ ldpe_l2vpn_pw_init(struct l2vpn_pw *pw) if (tnbr == NULL) { tnbr = tnbr_new(pw->af, &pw->addr); tnbr_update(tnbr); - LIST_INSERT_HEAD(&leconf->tnbr_list, tnbr, entry); + RB_INSERT(tnbr_head, &leconf->tnbr_tree, tnbr); } tnbr->pw_count++; @@ -544,6 +558,6 @@ ldpe_l2vpn_pw_exit(struct l2vpn_pw *pw) tnbr = tnbr_find(leconf, pw->af, &pw->addr); if (tnbr) { tnbr->pw_count--; - tnbr_check(tnbr); + tnbr_check(leconf, tnbr); } } diff --git a/ldpd/lde.c b/ldpd/lde.c index c2a5cf088c..0aa422c23a 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -45,12 +45,14 @@ static struct lde_nbr *lde_nbr_find(uint32_t); static void lde_nbr_clear(void); static void lde_nbr_addr_update(struct lde_nbr *, struct lde_addr *, int); +static __inline int lde_map_compare(struct lde_map *, struct lde_map *); static void lde_map_free(void *); static int lde_address_add(struct lde_nbr *, struct lde_addr *); static int lde_address_del(struct lde_nbr *, struct lde_addr *); static void lde_address_list_free(struct lde_nbr *); RB_GENERATE(nbr_tree, lde_nbr, entry, lde_nbr_compare) +RB_GENERATE(lde_map_head, lde_map, entry, lde_map_compare) struct ldpd_conf *ldeconf; struct nbr_tree lde_nbrs = RB_INITIALIZER(&lde_nbrs); @@ -471,10 +473,10 @@ lde_dispatch_parent(struct thread *thread) fatal(NULL); memcpy(nconf, imsg.data, sizeof(struct ldpd_conf)); - LIST_INIT(&nconf->iface_list); - LIST_INIT(&nconf->tnbr_list); - LIST_INIT(&nconf->nbrp_list); - LIST_INIT(&nconf->l2vpn_list); + RB_INIT(&nconf->iface_tree); + RB_INIT(&nconf->tnbr_tree); + RB_INIT(&nconf->nbrp_tree); + RB_INIT(&nconf->l2vpn_tree); break; case IMSG_RECONF_IFACE: if ((niface = malloc(sizeof(struct iface))) == NULL) @@ -482,37 +484,37 @@ lde_dispatch_parent(struct thread *thread) memcpy(niface, imsg.data, sizeof(struct iface)); LIST_INIT(&niface->addr_list); - LIST_INIT(&niface->ipv4.adj_list); - LIST_INIT(&niface->ipv6.adj_list); + RB_INIT(&niface->ipv4.adj_tree); + RB_INIT(&niface->ipv6.adj_tree); niface->ipv4.iface = niface; niface->ipv6.iface = niface; - LIST_INSERT_HEAD(&nconf->iface_list, niface, entry); + RB_INSERT(iface_head, &nconf->iface_tree, niface); break; case IMSG_RECONF_TNBR: if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL) fatal(NULL); memcpy(ntnbr, imsg.data, sizeof(struct tnbr)); - LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry); + RB_INSERT(tnbr_head, &nconf->tnbr_tree, ntnbr); break; case IMSG_RECONF_NBRP: if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL) fatal(NULL); memcpy(nnbrp, imsg.data, sizeof(struct nbr_params)); - LIST_INSERT_HEAD(&nconf->nbrp_list, nnbrp, entry); + RB_INSERT(nbrp_head, &nconf->nbrp_tree, nnbrp); break; case IMSG_RECONF_L2VPN: if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL) fatal(NULL); memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn)); - LIST_INIT(&nl2vpn->if_list); - LIST_INIT(&nl2vpn->pw_list); - LIST_INIT(&nl2vpn->pw_inactive_list); + RB_INIT(&nl2vpn->if_tree); + RB_INIT(&nl2vpn->pw_tree); + RB_INIT(&nl2vpn->pw_inactive_tree); - LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry); + RB_INSERT(l2vpn_head, &nconf->l2vpn_tree, nl2vpn); break; case IMSG_RECONF_L2VPN_IF: if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL) @@ -520,7 +522,7 @@ lde_dispatch_parent(struct thread *thread) memcpy(nlif, imsg.data, sizeof(struct l2vpn_if)); nlif->l2vpn = nl2vpn; - LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry); + RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif); break; case IMSG_RECONF_L2VPN_PW: if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL) @@ -528,7 +530,7 @@ lde_dispatch_parent(struct thread *thread) memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); npw->l2vpn = nl2vpn; - LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry); + RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw); break; case IMSG_RECONF_L2VPN_IPW: if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL) @@ -536,7 +538,7 @@ lde_dispatch_parent(struct thread *thread) memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); npw->l2vpn = nl2vpn; - LIST_INSERT_HEAD(&nl2vpn->pw_inactive_list, npw, entry); + RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw); break; case IMSG_RECONF_END: merge_config(ldeconf, nconf); @@ -1141,6 +1143,13 @@ lde_nbr_addr_update(struct lde_nbr *ln, struct lde_addr *lde_addr, int removed) } } +static __inline int +lde_map_compare(struct lde_map *a, struct lde_map *b) +{ + return (ldp_addrcmp(AF_INET, (union ldpd_addr *)&a->nexthop->id, + (union ldpd_addr *)&b->nexthop->id)); +} + struct lde_map * lde_map_add(struct lde_nbr *ln, struct fec_node *fn, int sent) { @@ -1154,13 +1163,15 @@ lde_map_add(struct lde_nbr *ln, struct fec_node *fn, int sent) me->nexthop = ln; if (sent) { - LIST_INSERT_HEAD(&fn->upstream, me, entry); + RB_INSERT(lde_map_head, &fn->upstream, me); + me->head = &fn->upstream; if (fec_insert(&ln->sent_map, &me->fec)) log_warnx("failed to add %s to sent map", log_fec(&me->fec)); /* XXX on failure more cleanup is needed */ } else { - LIST_INSERT_HEAD(&fn->downstream, me, entry); + RB_INSERT(lde_map_head, &fn->downstream, me); + me->head = &fn->downstream; if (fec_insert(&ln->recv_map, &me->fec)) log_warnx("failed to add %s to recv map", log_fec(&me->fec)); @@ -1185,7 +1196,7 @@ lde_map_free(void *ptr) { struct lde_map *map = ptr; - LIST_REMOVE(map, entry); + RB_REMOVE(lde_map_head, map->head, map); free(map); } diff --git a/ldpd/lde.h b/ldpd/lde.h index 5f5d37defb..fe90b2c852 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -62,10 +62,13 @@ struct lde_req { /* mapping entries */ struct lde_map { struct fec fec; - LIST_ENTRY(lde_map) entry; + struct lde_map_head *head; /* fec_node's upstream/downstream */ + RB_ENTRY(lde_map) entry; struct lde_nbr *nexthop; struct map map; }; +RB_HEAD(lde_map_head, lde_map); +RB_PROTOTYPE(lde_map_head, lde_map, entry, lde_map_cmp); /* withdraw entries */ struct lde_wdraw { @@ -112,8 +115,8 @@ struct fec_node { struct fec fec; LIST_HEAD(, fec_nh) nexthops; /* fib nexthops */ - LIST_HEAD(, lde_map) downstream; /* recv mappings */ - LIST_HEAD(, lde_map) upstream; /* sent mappings */ + struct lde_map_head downstream; /* recv mappings */ + struct lde_map_head upstream; /* sent mappings */ uint32_t local_label; void *data; /* fec specific data */ diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c index 14ac592af9..df65edad1a 100644 --- a/ldpd/lde_lib.c +++ b/ldpd/lde_lib.c @@ -159,7 +159,7 @@ rt_dump(pid_t pid) RB_FOREACH(f, fec_tree, &ft) { fn = (struct fec_node *)f; if (fn->local_label == NO_LABEL && - LIST_EMPTY(&fn->downstream)) + RB_EMPTY(&fn->downstream)) continue; rtctl.first = 1; @@ -179,7 +179,7 @@ rt_dump(pid_t pid) } rtctl.local_label = fn->local_label; - LIST_FOREACH(me, &fn->downstream, entry) { + RB_FOREACH(me, lde_map_head, &fn->downstream) { rtctl.in_use = lde_nbr_is_nexthop(fn, me->nexthop); rtctl.nexthop = me->nexthop->id; rtctl.remote_label = me->map.label; @@ -188,7 +188,7 @@ rt_dump(pid_t pid) &rtctl, sizeof(rtctl)); rtctl.first = 0; } - if (LIST_EMPTY(&fn->downstream)) { + if (RB_EMPTY(&fn->downstream)) { rtctl.in_use = 0; rtctl.nexthop.s_addr = INADDR_ANY; rtctl.remote_label = NO_LABEL; @@ -224,10 +224,10 @@ fec_free(void *arg) while ((fnh = LIST_FIRST(&fn->nexthops))) fec_nh_del(fnh); - if (!LIST_EMPTY(&fn->downstream)) + if (!RB_EMPTY(&fn->downstream)) log_warnx("%s: fec %s downstream list not empty", __func__, log_fec(&fn->fec)); - if (!LIST_EMPTY(&fn->upstream)) + if (!RB_EMPTY(&fn->upstream)) log_warnx("%s: fec %s upstream list not empty", __func__, log_fec(&fn->fec)); @@ -251,8 +251,8 @@ fec_add(struct fec *fec) fn->fec = *fec; fn->local_label = NO_LABEL; - LIST_INIT(&fn->upstream); - LIST_INIT(&fn->downstream); + RB_INIT(&fn->upstream); + RB_INIT(&fn->downstream); LIST_INIT(&fn->nexthops); if (fec_insert(&ft, &fn->fec)) @@ -774,8 +774,8 @@ lde_gc_timer(struct thread *thread) fn = (struct fec_node *) fec; if (!LIST_EMPTY(&fn->nexthops) || - !LIST_EMPTY(&fn->downstream) || - !LIST_EMPTY(&fn->upstream)) + !RB_EMPTY(&fn->downstream) || + !RB_EMPTY(&fn->upstream)) continue; fec_remove(&ft, &fn->fec); diff --git a/ldpd/ldp_debug.c b/ldpd/ldp_debug.c index 15dd06a0f3..86b679d8aa 100644 --- a/ldpd/ldp_debug.c +++ b/ldpd/ldp_debug.c @@ -74,7 +74,7 @@ ldp_vty_debug(struct vty *vty, struct vty_arg *args[]) DEBUG_OFF(event, EVENT); else DEBUG_ON(event, EVENT); - } else if (strcmp(type_str, "messages") == 0) { + } else if (strcmp(type_str, "messages") == 0) { all = (vty_get_arg_value(args, "all")) ? 1 : 0; dir_str = vty_get_arg_value(args, "dir"); if (dir_str == NULL) @@ -99,7 +99,7 @@ ldp_vty_debug(struct vty *vty, struct vty_arg *args[]) DEBUG_ON(msg, MSG_SEND_ALL); } } - } else if (strcmp(type_str, "zebra") == 0) { + } else if (strcmp(type_str, "zebra") == 0) { if (disable) DEBUG_OFF(zebra, ZEBRA); else diff --git a/ldpd/ldp_vty_cmds.c b/ldpd/ldp_vty_cmds.c deleted file mode 100644 index 8aa593cf2c..0000000000 --- a/ldpd/ldp_vty_cmds.c +++ /dev/null @@ -1,1726 +0,0 @@ -/* Auto-generated from ldp_vty.xml. */ -/* Do not edit! */ - -#include - -#include "command.h" -#include "vty.h" -#include "ldp_vty.h" - -DEFUN (ldp_mpls_ldp, - ldp_mpls_ldp_cmd, - "mpls ldp", - "Global MPLS configuration subcommands\n" - "Label Distribution Protocol\n") -{ - struct vty_arg *args[] = { NULL }; - return ldp_vty_mpls_ldp (vty, args); -} - -DEFUN (ldp_l2vpn_word_type_vpls, - ldp_l2vpn_word_type_vpls_cmd, - "l2vpn WORD type vpls", - "Configure l2vpn commands\n" - "L2VPN name\n" - "L2VPN type\n" - "Virtual Private LAN Service\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "name", .value = argv[1]->arg }, - NULL - }; - return ldp_vty_l2vpn (vty, args); -} - -DEFUN (ldp_no_mpls_ldp, - ldp_no_mpls_ldp_cmd, - "no mpls ldp", - "Negate a command or set its defaults\n" - "Global MPLS configuration subcommands\n" - "Label Distribution Protocol\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - NULL - }; - return ldp_vty_mpls_ldp (vty, args); -} - -DEFUN (ldp_no_l2vpn_word_type_vpls, - ldp_no_l2vpn_word_type_vpls_cmd, - "no l2vpn WORD type vpls", - "Negate a command or set its defaults\n" - "Configure l2vpn commands\n" - "L2VPN name\n" - "L2VPN type\n" - "Virtual Private LAN Service\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "name", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_l2vpn (vty, args); -} - -DEFUN (ldp_address_family_ipv4, - ldp_address_family_ipv4_cmd, - "address-family ipv4", - "Configure Address Family and its parameters\n" - "IPv4\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "address-family", .value = "ipv4" }, - NULL - }; - return ldp_vty_address_family (vty, args); -} - -DEFUN (ldp_address_family_ipv6, - ldp_address_family_ipv6_cmd, - "address-family ipv6", - "Configure Address Family and its parameters\n" - "IPv6\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "address-family", .value = "ipv6" }, - NULL - }; - return ldp_vty_address_family (vty, args); -} - -DEFUN (ldp_discovery_hello_holdtime_disc_time, - ldp_discovery_hello_holdtime_disc_time_cmd, - "discovery hello holdtime (1-65535)", - "Configure discovery parameters\n" - "LDP Link Hellos\n" - "Hello holdtime\n" - "Time (seconds) - 65535 implies infinite\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "hello_type", .value = "hello" }, - &(struct vty_arg) { .name = "seconds", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_disc_holdtime (vty, args); -} - -DEFUN (ldp_discovery_hello_interval_disc_time, - ldp_discovery_hello_interval_disc_time_cmd, - "discovery hello interval (1-65535)", - "Configure discovery parameters\n" - "LDP Link Hellos\n" - "Hello interval\n" - "Time (seconds)\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "hello_type", .value = "hello" }, - &(struct vty_arg) { .name = "seconds", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_disc_interval (vty, args); -} - -DEFUN (ldp_discovery_targeted_hello_holdtime_disc_time, - ldp_discovery_targeted_hello_holdtime_disc_time_cmd, - "discovery targeted-hello holdtime (1-65535)", - "Configure discovery parameters\n" - "LDP Targeted Hellos\n" - "Targeted hello holdtime\n" - "Time (seconds) - 65535 implies infinite\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "hello_type", .value = "targeted-hello" }, - &(struct vty_arg) { .name = "seconds", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_disc_holdtime (vty, args); -} - -DEFUN (ldp_discovery_targeted_hello_interval_disc_time, - ldp_discovery_targeted_hello_interval_disc_time_cmd, - "discovery targeted-hello interval (1-65535)", - "Configure discovery parameters\n" - "LDP Targeted Hellos\n" - "Targeted hello interval\n" - "Time (seconds)\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "hello_type", .value = "targeted-hello" }, - &(struct vty_arg) { .name = "seconds", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_disc_interval (vty, args); -} - -DEFUN (ldp_dual_stack_transport_connection_prefer_ipv4, - ldp_dual_stack_transport_connection_prefer_ipv4_cmd, - "dual-stack transport-connection prefer ipv4", - "Configure dual stack parameters\n" - "Configure TCP transport parameters\n" - "Configure prefered address family for TCP transport connection with neighbor\n" - "IPv4\n") -{ - struct vty_arg *args[] = { NULL }; - return ldp_vty_trans_pref_ipv4 (vty, args); -} - -DEFUN (ldp_dual_stack_cisco_interop, - ldp_dual_stack_cisco_interop_cmd, - "dual-stack cisco-interop", - "Configure dual stack parameters\n" - "Use Cisco non-compliant format to send and interpret the Dual-Stack capability TLV\n") -{ - struct vty_arg *args[] = { NULL }; - return ldp_vty_ds_cisco_interop (vty, args); -} - -DEFUN (ldp_neighbor_ipv4_password_word, - ldp_neighbor_ipv4_password_word_cmd, - "neighbor A.B.C.D password WORD", - "Configure neighbor parameters\n" - "LDP Id of neighbor\n" - "Configure password for MD5 authentication\n" - "The password\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "lsr_id", .value = argv[1]->arg }, - &(struct vty_arg) { .name = "password", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_neighbor_password (vty, args); -} - -DEFUN (ldp_neighbor_ipv4_session_holdtime_session_time, - ldp_neighbor_ipv4_session_holdtime_session_time_cmd, - "neighbor A.B.C.D session holdtime (15-65535)", - "Configure neighbor parameters\n" - "LDP Id of neighbor\n" - "Configure session parameters\n" - "Configure session holdtime\n" - "Time (seconds)\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "lsr_id", .value = argv[1]->arg }, - &(struct vty_arg) { .name = "seconds", .value = argv[4]->arg }, - NULL - }; - return ldp_vty_session_holdtime (vty, args); -} - -DEFUN (ldp_neighbor_ipv4_ttl_security_disable, - ldp_neighbor_ipv4_ttl_security_disable_cmd, - "neighbor A.B.C.D ttl-security disable", - "Configure neighbor parameters\n" - "LDP Id of neighbor\n" - "LDP ttl security check\n" - "Disable ttl security\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "lsr_id", .value = argv[1]->arg }, - NULL - }; - return ldp_vty_neighbor_ttl_security (vty, args); -} - -DEFUN (ldp_neighbor_ipv4_ttl_security_hops_hops, - ldp_neighbor_ipv4_ttl_security_hops_hops_cmd, - "neighbor A.B.C.D ttl-security hops (1-254)", - "Configure neighbor parameters\n" - "LDP Id of neighbor\n" - "LDP ttl security check\n" - "IP hops\n" - "maximum number of hops\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "lsr_id", .value = argv[1]->arg }, - &(struct vty_arg) { .name = "hops", .value = argv[4]->arg }, - NULL - }; - return ldp_vty_neighbor_ttl_security (vty, args); -} - -DEFUN (ldp_router_id_ipv4, - ldp_router_id_ipv4_cmd, - "router-id A.B.C.D", - "Configure router Id\n" - "LSR Id (in form of an IPv4 address)\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "addr", .value = argv[1]->arg }, - NULL - }; - return ldp_vty_router_id (vty, args); -} - -DEFUN (ldp_no_address_family_ipv4, - ldp_no_address_family_ipv4_cmd, - "no address-family ipv4", - "Negate a command or set its defaults\n" - "Configure Address Family and its parameters\n" - "IPv4\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "address-family", .value = "ipv4" }, - NULL - }; - return ldp_vty_address_family (vty, args); -} - -DEFUN (ldp_no_address_family_ipv6, - ldp_no_address_family_ipv6_cmd, - "no address-family ipv6", - "Negate a command or set its defaults\n" - "Configure Address Family and its parameters\n" - "IPv6\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "address-family", .value = "ipv6" }, - NULL - }; - return ldp_vty_address_family (vty, args); -} - -DEFUN (ldp_no_discovery_hello_holdtime_disc_time, - ldp_no_discovery_hello_holdtime_disc_time_cmd, - "no discovery hello holdtime (1-65535)", - "Negate a command or set its defaults\n" - "Configure discovery parameters\n" - "LDP Link Hellos\n" - "Hello holdtime\n" - "Time (seconds) - 65535 implies infinite\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "hello_type", .value = "hello" }, - &(struct vty_arg) { .name = "seconds", .value = argv[4]->arg }, - NULL - }; - return ldp_vty_disc_holdtime (vty, args); -} - -DEFUN (ldp_no_discovery_hello_interval_disc_time, - ldp_no_discovery_hello_interval_disc_time_cmd, - "no discovery hello interval (1-65535)", - "Negate a command or set its defaults\n" - "Configure discovery parameters\n" - "LDP Link Hellos\n" - "Hello interval\n" - "Time (seconds)\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "hello_type", .value = "hello" }, - &(struct vty_arg) { .name = "seconds", .value = argv[4]->arg }, - NULL - }; - return ldp_vty_disc_interval (vty, args); -} - -DEFUN (ldp_no_discovery_targeted_hello_holdtime_disc_time, - ldp_no_discovery_targeted_hello_holdtime_disc_time_cmd, - "no discovery targeted-hello holdtime (1-65535)", - "Negate a command or set its defaults\n" - "Configure discovery parameters\n" - "LDP Targeted Hellos\n" - "Targeted hello holdtime\n" - "Time (seconds) - 65535 implies infinite\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "hello_type", .value = "targeted-hello" }, - &(struct vty_arg) { .name = "seconds", .value = argv[4]->arg }, - NULL - }; - return ldp_vty_disc_holdtime (vty, args); -} - -DEFUN (ldp_no_discovery_targeted_hello_interval_disc_time, - ldp_no_discovery_targeted_hello_interval_disc_time_cmd, - "no discovery targeted-hello interval (1-65535)", - "Negate a command or set its defaults\n" - "Configure discovery parameters\n" - "LDP Targeted Hellos\n" - "Targeted hello interval\n" - "Time (seconds)\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "hello_type", .value = "targeted-hello" }, - &(struct vty_arg) { .name = "seconds", .value = argv[4]->arg }, - NULL - }; - return ldp_vty_disc_interval (vty, args); -} - -DEFUN (ldp_no_dual_stack_transport_connection_prefer_ipv4, - ldp_no_dual_stack_transport_connection_prefer_ipv4_cmd, - "no dual-stack transport-connection prefer ipv4", - "Negate a command or set its defaults\n" - "Configure dual stack parameters\n" - "Configure TCP transport parameters\n" - "Configure prefered address family for TCP transport connection with neighbor\n" - "IPv4\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - NULL - }; - return ldp_vty_trans_pref_ipv4 (vty, args); -} - -DEFUN (ldp_no_dual_stack_cisco_interop, - ldp_no_dual_stack_cisco_interop_cmd, - "no dual-stack cisco-interop", - "Negate a command or set its defaults\n" - "Configure dual stack parameters\n" - "Use Cisco non-compliant format to send and interpret the Dual-Stack capability TLV\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - NULL - }; - return ldp_vty_ds_cisco_interop (vty, args); -} - -DEFUN (ldp_no_neighbor_ipv4_password_word, - ldp_no_neighbor_ipv4_password_word_cmd, - "no neighbor A.B.C.D password WORD", - "Negate a command or set its defaults\n" - "Configure neighbor parameters\n" - "LDP Id of neighbor\n" - "Configure password for MD5 authentication\n" - "The password\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "lsr_id", .value = argv[2]->arg }, - &(struct vty_arg) { .name = "password", .value = argv[4]->arg }, - NULL - }; - return ldp_vty_neighbor_password (vty, args); -} - -DEFUN (ldp_no_neighbor_ipv4_session_holdtime_session_time, - ldp_no_neighbor_ipv4_session_holdtime_session_time_cmd, - "no neighbor A.B.C.D session holdtime (15-65535)", - "Negate a command or set its defaults\n" - "Configure neighbor parameters\n" - "LDP Id of neighbor\n" - "Configure session parameters\n" - "Configure session holdtime\n" - "Time (seconds)\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "lsr_id", .value = argv[2]->arg }, - &(struct vty_arg) { .name = "seconds", .value = argv[5]->arg }, - NULL - }; - return ldp_vty_session_holdtime (vty, args); -} - -DEFUN (ldp_no_neighbor_ipv4_ttl_security_disable, - ldp_no_neighbor_ipv4_ttl_security_disable_cmd, - "no neighbor A.B.C.D ttl-security disable", - "Negate a command or set its defaults\n" - "Configure neighbor parameters\n" - "LDP Id of neighbor\n" - "LDP ttl security check\n" - "Disable ttl security\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "lsr_id", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_neighbor_ttl_security (vty, args); -} - -DEFUN (ldp_no_neighbor_ipv4_ttl_security_hops_hops, - ldp_no_neighbor_ipv4_ttl_security_hops_hops_cmd, - "no neighbor A.B.C.D ttl-security hops (1-254)", - "Negate a command or set its defaults\n" - "Configure neighbor parameters\n" - "LDP Id of neighbor\n" - "LDP ttl security check\n" - "IP hops\n" - "maximum number of hops\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "lsr_id", .value = argv[2]->arg }, - &(struct vty_arg) { .name = "hops", .value = argv[5]->arg }, - NULL - }; - return ldp_vty_neighbor_ttl_security (vty, args); -} - -DEFUN (ldp_no_router_id_ipv4, - ldp_no_router_id_ipv4_cmd, - "no router-id A.B.C.D", - "Negate a command or set its defaults\n" - "Configure router Id\n" - "LSR Id (in form of an IPv4 address)\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "addr", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_router_id (vty, args); -} - -DEFUN (ldp_discovery_targeted_hello_accept, - ldp_discovery_targeted_hello_accept_cmd, - "discovery targeted-hello accept", - "Configure discovery parameters\n" - "LDP Targeted Hellos\n" - "Accept and respond to targeted hellos\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "hello_type", .value = "targeted-hello" }, - NULL - }; - return ldp_vty_targeted_hello_accept (vty, args); -} - -DEFUN (ldp_label_local_advertise_explicit_null, - ldp_label_local_advertise_explicit_null_cmd, - "label local advertise explicit-null", - "Configure label control and policies\n" - "Configure local label control and policies\n" - "Configure outbound label advertisement control\n" - "Configure explicit-null advertisement\n") -{ - struct vty_arg *args[] = { NULL }; - return ldp_vty_explicit_null (vty, args); -} - -DEFUN (ldp_ttl_security_disable, - ldp_ttl_security_disable_cmd, - "ttl-security disable", - "LDP ttl security check\n" - "Disable ttl security\n") -{ - struct vty_arg *args[] = { NULL }; - return ldp_vty_ttl_security (vty, args); -} - -DEFUN (ldp_session_holdtime_session_time, - ldp_session_holdtime_session_time_cmd, - "session holdtime (15-65535)", - "Configure session parameters\n" - "Configure session holdtime\n" - "Time (seconds)\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "seconds", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_session_holdtime (vty, args); -} - -DEFUN (ldp_interface_ifname, - ldp_interface_ifname_cmd, - "interface IFNAME", - "Enable LDP on an interface and enter interface submode\n" - "Interface's name\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "ifname", .value = argv[1]->arg }, - NULL - }; - return ldp_vty_interface (vty, args); -} - -DEFUN (ldp_discovery_transport_address_ipv4, - ldp_discovery_transport_address_ipv4_cmd, - "discovery transport-address A.B.C.D", - "Configure discovery parameters\n" - "Specify transport address for TCP connection\n" - "IP address to be used as transport address\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "addr", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_trans_addr (vty, args); -} - -DEFUN (ldp_neighbor_ipv4_targeted, - ldp_neighbor_ipv4_targeted_cmd, - "neighbor A.B.C.D targeted", - "Configure neighbor parameters\n" - "IP address of neighbor\n" - "Establish targeted session\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "addr", .value = argv[1]->arg }, - NULL - }; - return ldp_vty_neighbor_targeted (vty, args); -} - -DEFUN (ldp_no_discovery_targeted_hello_accept, - ldp_no_discovery_targeted_hello_accept_cmd, - "no discovery targeted-hello accept", - "Negate a command or set its defaults\n" - "Configure discovery parameters\n" - "LDP Targeted Hellos\n" - "Accept and respond to targeted hellos\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "hello_type", .value = "targeted-hello" }, - NULL - }; - return ldp_vty_targeted_hello_accept (vty, args); -} - -DEFUN (ldp_no_label_local_advertise_explicit_null, - ldp_no_label_local_advertise_explicit_null_cmd, - "no label local advertise explicit-null", - "Negate a command or set its defaults\n" - "Configure label control and policies\n" - "Configure local label control and policies\n" - "Configure outbound label advertisement control\n" - "Configure explicit-null advertisement\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - NULL - }; - return ldp_vty_explicit_null (vty, args); -} - -DEFUN (ldp_no_ttl_security_disable, - ldp_no_ttl_security_disable_cmd, - "no ttl-security disable", - "Negate a command or set its defaults\n" - "LDP ttl security check\n" - "Disable ttl security\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - NULL - }; - return ldp_vty_ttl_security (vty, args); -} - -DEFUN (ldp_no_session_holdtime_session_time, - ldp_no_session_holdtime_session_time_cmd, - "no session holdtime (15-65535)", - "Negate a command or set its defaults\n" - "Configure session parameters\n" - "Configure session holdtime\n" - "Time (seconds)\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "seconds", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_session_holdtime (vty, args); -} - -DEFUN (ldp_no_interface_ifname, - ldp_no_interface_ifname_cmd, - "no interface IFNAME", - "Negate a command or set its defaults\n" - "Enable LDP on an interface and enter interface submode\n" - "Interface's name\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "ifname", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_interface (vty, args); -} - -DEFUN (ldp_no_discovery_transport_address_ipv4, - ldp_no_discovery_transport_address_ipv4_cmd, - "no discovery transport-address A.B.C.D", - "Negate a command or set its defaults\n" - "Configure discovery parameters\n" - "Specify transport address for TCP connection\n" - "IP address to be used as transport address\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "addr", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_trans_addr (vty, args); -} - -DEFUN (ldp_no_neighbor_ipv4_targeted, - ldp_no_neighbor_ipv4_targeted_cmd, - "no neighbor A.B.C.D targeted", - "Negate a command or set its defaults\n" - "Configure neighbor parameters\n" - "IP address of neighbor\n" - "Establish targeted session\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "addr", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_neighbor_targeted (vty, args); -} - -DEFUN (ldp_discovery_transport_address_ipv6, - ldp_discovery_transport_address_ipv6_cmd, - "discovery transport-address X:X::X:X", - "Configure discovery parameters\n" - "Specify transport address for TCP connection\n" - "IPv6 address to be used as transport address\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "addr", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_trans_addr (vty, args); -} - -DEFUN (ldp_neighbor_ipv6_targeted, - ldp_neighbor_ipv6_targeted_cmd, - "neighbor X:X::X:X targeted", - "Configure neighbor parameters\n" - "IPv6 address of neighbor\n" - "Establish targeted session\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "addr", .value = argv[1]->arg }, - NULL - }; - return ldp_vty_neighbor_targeted (vty, args); -} - -DEFUN (ldp_no_discovery_transport_address_ipv6, - ldp_no_discovery_transport_address_ipv6_cmd, - "no discovery transport-address X:X::X:X", - "Negate a command or set its defaults\n" - "Configure discovery parameters\n" - "Specify transport address for TCP connection\n" - "IPv6 address to be used as transport address\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "addr", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_trans_addr (vty, args); -} - -DEFUN (ldp_no_neighbor_ipv6_targeted, - ldp_no_neighbor_ipv6_targeted_cmd, - "no neighbor X:X::X:X targeted", - "Negate a command or set its defaults\n" - "Configure neighbor parameters\n" - "IPv6 address of neighbor\n" - "Establish targeted session\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "addr", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_neighbor_targeted (vty, args); -} - -DEFUN (ldp_bridge_ifname, - ldp_bridge_ifname_cmd, - "bridge IFNAME", - "Bridge interface\n" - "Interface's name\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "ifname", .value = argv[1]->arg }, - NULL - }; - return ldp_vty_l2vpn_bridge (vty, args); -} - -DEFUN (ldp_mtu_mtu, - ldp_mtu_mtu_cmd, - "mtu (1500-9180)", - "set Maximum Transmission Unit\n" - "Maximum Transmission Unit value\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "mtu", .value = argv[1]->arg }, - NULL - }; - return ldp_vty_l2vpn_mtu (vty, args); -} - -DEFUN (ldp_member_interface_ifname, - ldp_member_interface_ifname_cmd, - "member interface IFNAME", - "L2VPN member configuration\n" - "Local interface\n" - "Interface's name\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "ifname", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_l2vpn_interface (vty, args); -} - -DEFUN (ldp_member_pseudowire_ifname, - ldp_member_pseudowire_ifname_cmd, - "member pseudowire IFNAME", - "L2VPN member configuration\n" - "Pseudowire interface\n" - "Interface's name\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "ifname", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_l2vpn_pseudowire (vty, args); -} - -DEFUN (ldp_vc_type_pwtype, - ldp_vc_type_pwtype_cmd, - "vc type ", - "Virtual Circuit options\n" - "Virtual Circuit type to use\n" - "Ethernet (type 5)\n" - "Ethernet-tagged (type 4)\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "type", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_l2vpn_pwtype (vty, args); -} - -DEFUN (ldp_no_bridge_ifname, - ldp_no_bridge_ifname_cmd, - "no bridge IFNAME", - "Negate a command or set its defaults\n" - "Bridge interface\n" - "Interface's name\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "ifname", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_l2vpn_bridge (vty, args); -} - -DEFUN (ldp_no_mtu_mtu, - ldp_no_mtu_mtu_cmd, - "no mtu (1500-9180)", - "Negate a command or set its defaults\n" - "set Maximum Transmission Unit\n" - "Maximum Transmission Unit value\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "mtu", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_l2vpn_mtu (vty, args); -} - -DEFUN (ldp_no_member_interface_ifname, - ldp_no_member_interface_ifname_cmd, - "no member interface IFNAME", - "Negate a command or set its defaults\n" - "L2VPN member configuration\n" - "Local interface\n" - "Interface's name\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "ifname", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_l2vpn_interface (vty, args); -} - -DEFUN (ldp_no_member_pseudowire_ifname, - ldp_no_member_pseudowire_ifname_cmd, - "no member pseudowire IFNAME", - "Negate a command or set its defaults\n" - "L2VPN member configuration\n" - "Pseudowire interface\n" - "Interface's name\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "ifname", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_l2vpn_pseudowire (vty, args); -} - -DEFUN (ldp_no_vc_type_pwtype, - ldp_no_vc_type_pwtype_cmd, - "no vc type ", - "Negate a command or set its defaults\n" - "Virtual Circuit options\n" - "Virtual Circuit type to use\n" - "Ethernet (type 5)\n" - "Ethernet-tagged (type 4)\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "type", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_l2vpn_pwtype (vty, args); -} - -DEFUN (ldp_control_word_cword, - ldp_control_word_cword_cmd, - "control-word ", - "Control-word options\n" - "Exclude control-word in pseudowire packets\n" - "Include control-word in pseudowire packets\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "preference", .value = argv[1]->arg }, - NULL - }; - return ldp_vty_l2vpn_pw_cword (vty, args); -} - -DEFUN (ldp_neighbor_address_addr, - ldp_neighbor_address_addr_cmd, - "neighbor address ", - "Remote endpoint configuration\n" - "Specify the IPv4 or IPv6 address of the remote endpoint\n" - "IPv4 address\n" - "IPv6 address\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "addr", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_l2vpn_pw_nbr_addr (vty, args); -} - -DEFUN (ldp_neighbor_lsr_id_ipv4, - ldp_neighbor_lsr_id_ipv4_cmd, - "neighbor lsr-id A.B.C.D", - "Remote endpoint configuration\n" - "Specify the LSR-ID of the remote endpoint\n" - "IPv4 address\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "lsr-id", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_l2vpn_pw_nbr_id (vty, args); -} - -DEFUN (ldp_pw_id_pwid, - ldp_pw_id_pwid_cmd, - "pw-id (1-4294967295)", - "Set the Virtual Circuit ID\n" - "Virtual Circuit ID value\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "pwid", .value = argv[1]->arg }, - NULL - }; - return ldp_vty_l2vpn_pw_pwid (vty, args); -} - -DEFUN (ldp_pw_status_disable, - ldp_pw_status_disable_cmd, - "pw-status disable", - "Configure PW status\n" - "Disable PW status\n") -{ - struct vty_arg *args[] = { NULL }; - return ldp_vty_l2vpn_pw_pwstatus (vty, args); -} - -DEFUN (ldp_no_control_word_cword, - ldp_no_control_word_cword_cmd, - "no control-word ", - "Negate a command or set its defaults\n" - "Control-word options\n" - "Exclude control-word in pseudowire packets\n" - "Include control-word in pseudowire packets\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "preference", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_l2vpn_pw_cword (vty, args); -} - -DEFUN (ldp_no_neighbor_address_addr, - ldp_no_neighbor_address_addr_cmd, - "no neighbor address ", - "Negate a command or set its defaults\n" - "Remote endpoint configuration\n" - "Specify the IPv4 or IPv6 address of the remote endpoint\n" - "IPv4 address\n" - "IPv6 address\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "addr", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_l2vpn_pw_nbr_addr (vty, args); -} - -DEFUN (ldp_no_neighbor_lsr_id_ipv4, - ldp_no_neighbor_lsr_id_ipv4_cmd, - "no neighbor lsr-id A.B.C.D", - "Negate a command or set its defaults\n" - "Remote endpoint configuration\n" - "Specify the LSR-ID of the remote endpoint\n" - "IPv4 address\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "lsr-id", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_l2vpn_pw_nbr_id (vty, args); -} - -DEFUN (ldp_no_pw_id_pwid, - ldp_no_pw_id_pwid_cmd, - "no pw-id (1-4294967295)", - "Negate a command or set its defaults\n" - "Set the Virtual Circuit ID\n" - "Virtual Circuit ID value\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "pwid", .value = argv[2]->arg }, - NULL - }; - return ldp_vty_l2vpn_pw_pwid (vty, args); -} - -DEFUN (ldp_no_pw_status_disable, - ldp_no_pw_status_disable_cmd, - "no pw-status disable", - "Negate a command or set its defaults\n" - "Configure PW status\n" - "Disable PW status\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - NULL - }; - return ldp_vty_l2vpn_pw_pwstatus (vty, args); -} - -DEFUN (ldp_show_mpls_ldp_neighbor, - ldp_show_mpls_ldp_neighbor_cmd, - "show mpls ldp neighbor", - "Show running system information\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "Neighbor information\n") -{ - struct vty_arg *args[] = { NULL }; - return ldp_vty_show_neighbor (vty, args); -} - -DEFUN (ldp_show_mpls_ldp_binding, - ldp_show_mpls_ldp_binding_cmd, - "show mpls ldp binding", - "Show running system information\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "Label Information Base (LIB) information\n") -{ - struct vty_arg *args[] = { NULL }; - return ldp_vty_show_binding (vty, args); -} - -DEFUN (ldp_show_mpls_ldp_discovery, - ldp_show_mpls_ldp_discovery_cmd, - "show mpls ldp discovery", - "Show running system information\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "Discovery Hello Information\n") -{ - struct vty_arg *args[] = { NULL }; - return ldp_vty_show_discovery (vty, args); -} - -DEFUN (ldp_show_mpls_ldp_interface, - ldp_show_mpls_ldp_interface_cmd, - "show mpls ldp interface", - "Show running system information\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "interface information\n") -{ - struct vty_arg *args[] = { NULL }; - return ldp_vty_show_interface (vty, args); -} - -DEFUN (ldp_show_mpls_ldp_address_family_binding, - ldp_show_mpls_ldp_address_family_binding_cmd, - "show mpls ldp binding", - "Show running system information\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "IPv4 Address Family\n" - "IPv6 Address Family\n" - "Label Information Base (LIB) information\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "address-family", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_show_binding (vty, args); -} - -DEFUN (ldp_show_mpls_ldp_address_family_discovery, - ldp_show_mpls_ldp_address_family_discovery_cmd, - "show mpls ldp discovery", - "Show running system information\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "IPv4 Address Family\n" - "IPv6 Address Family\n" - "Discovery Hello Information\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "address-family", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_show_discovery (vty, args); -} - -DEFUN (ldp_show_mpls_ldp_address_family_interface, - ldp_show_mpls_ldp_address_family_interface_cmd, - "show mpls ldp interface", - "Show running system information\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "IPv4 Address Family\n" - "IPv6 Address Family\n" - "interface information\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "address-family", .value = argv[3]->arg }, - NULL - }; - return ldp_vty_show_interface (vty, args); -} - -DEFUN (ldp_show_l2vpn_atom_binding, - ldp_show_l2vpn_atom_binding_cmd, - "show l2vpn atom binding", - "Show running system information\n" - "Show information about Layer2 VPN\n" - "Show Any Transport over MPLS information\n" - "Show AToM label binding information\n") -{ - struct vty_arg *args[] = { NULL }; - return ldp_vty_show_atom_binding (vty, args); -} - -DEFUN (ldp_show_l2vpn_atom_vc, - ldp_show_l2vpn_atom_vc_cmd, - "show l2vpn atom vc", - "Show running system information\n" - "Show information about Layer2 VPN\n" - "Show Any Transport over MPLS information\n" - "Show AToM virtual circuit information\n") -{ - struct vty_arg *args[] = { NULL }; - return ldp_vty_show_atom_vc (vty, args); -} - -DEFUN (ldp_show_debugging_mpls_ldp, - ldp_show_debugging_mpls_ldp_cmd, - "show debugging mpls ldp", - "Show running system information\n" - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n") -{ - struct vty_arg *args[] = { NULL }; - return ldp_vty_show_debugging (vty, args); -} - -DEFUN (ldp_clear_mpls_ldp_neighbor, - ldp_clear_mpls_ldp_neighbor_cmd, - "clear mpls ldp neighbor", - "Reset functions\n" - "Reset MPLS statistical information\n" - "Clear LDP state\n" - "Clear LDP neighbor sessions\n") -{ - struct vty_arg *args[] = { NULL }; - return ldp_vty_clear_nbr (vty, args); -} - -DEFUN (ldp_clear_mpls_ldp_neighbor_addr, - ldp_clear_mpls_ldp_neighbor_addr_cmd, - "clear mpls ldp neighbor ", - "Reset functions\n" - "Reset MPLS statistical information\n" - "Clear LDP state\n" - "Clear LDP neighbor sessions\n" - "IPv4 address\n" - "IPv6 address\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "addr", .value = argv[4]->arg }, - NULL - }; - return ldp_vty_clear_nbr (vty, args); -} - -DEFUN (ldp_debug_mpls_ldp_discovery_hello_dir, - ldp_debug_mpls_ldp_discovery_hello_dir_cmd, - "debug mpls ldp discovery hello ", - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "Discovery messages\n" - "Discovery hello message\n" - "Received messages\n" - "Sent messages\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "type", .value = "discovery" }, - &(struct vty_arg) { .name = "dir", .value = argv[5]->arg }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -DEFUN (ldp_debug_mpls_ldp_errors, - ldp_debug_mpls_ldp_errors_cmd, - "debug mpls ldp errors", - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "Errors\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "type", .value = "errors" }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -DEFUN (ldp_debug_mpls_ldp_event, - ldp_debug_mpls_ldp_event_cmd, - "debug mpls ldp event", - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "LDP event information\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "type", .value = "event" }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -DEFUN (ldp_debug_mpls_ldp_messages_recv, - ldp_debug_mpls_ldp_messages_recv_cmd, - "debug mpls ldp messages recv", - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "Messages\n" - "Received messages, excluding periodic Keep Alives\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "type", .value = "messages" }, - &(struct vty_arg) { .name = "dir", .value = "recv" }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -DEFUN (ldp_debug_mpls_ldp_messages_recv_all, - ldp_debug_mpls_ldp_messages_recv_all_cmd, - "debug mpls ldp messages recv all", - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "Messages\n" - "Received messages, excluding periodic Keep Alives\n" - "Received messages, including periodic Keep Alives\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "type", .value = "messages" }, - &(struct vty_arg) { .name = "dir", .value = "recv" }, - &(struct vty_arg) { .name = "all", .value = "all" }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -DEFUN (ldp_debug_mpls_ldp_messages_sent, - ldp_debug_mpls_ldp_messages_sent_cmd, - "debug mpls ldp messages sent", - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "Messages\n" - "Sent messages, excluding periodic Keep Alives\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "type", .value = "messages" }, - &(struct vty_arg) { .name = "dir", .value = "sent" }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -DEFUN (ldp_debug_mpls_ldp_messages_sent_all, - ldp_debug_mpls_ldp_messages_sent_all_cmd, - "debug mpls ldp messages sent all", - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "Messages\n" - "Sent messages, excluding periodic Keep Alives\n" - "Sent messages, including periodic Keep Alives\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "type", .value = "messages" }, - &(struct vty_arg) { .name = "dir", .value = "sent" }, - &(struct vty_arg) { .name = "all", .value = "all" }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -DEFUN (ldp_debug_mpls_ldp_zebra, - ldp_debug_mpls_ldp_zebra_cmd, - "debug mpls ldp zebra", - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "LDP zebra information\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "type", .value = "zebra" }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -DEFUN (ldp_no_debug_mpls_ldp_discovery_hello_dir, - ldp_no_debug_mpls_ldp_discovery_hello_dir_cmd, - "no debug mpls ldp discovery hello ", - "Negate a command or set its defaults\n" - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "Discovery messages\n" - "Discovery hello message\n" - "Received messages\n" - "Sent messages\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "type", .value = "discovery" }, - &(struct vty_arg) { .name = "dir", .value = argv[6]->arg }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -DEFUN (ldp_no_debug_mpls_ldp_errors, - ldp_no_debug_mpls_ldp_errors_cmd, - "no debug mpls ldp errors", - "Negate a command or set its defaults\n" - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "Errors\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "type", .value = "errors" }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -DEFUN (ldp_no_debug_mpls_ldp_event, - ldp_no_debug_mpls_ldp_event_cmd, - "no debug mpls ldp event", - "Negate a command or set its defaults\n" - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "LDP event information\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "type", .value = "event" }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -DEFUN (ldp_no_debug_mpls_ldp_messages_recv, - ldp_no_debug_mpls_ldp_messages_recv_cmd, - "no debug mpls ldp messages recv", - "Negate a command or set its defaults\n" - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "Messages\n" - "Received messages, excluding periodic Keep Alives\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "type", .value = "messages" }, - &(struct vty_arg) { .name = "dir", .value = "recv" }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -DEFUN (ldp_no_debug_mpls_ldp_messages_recv_all, - ldp_no_debug_mpls_ldp_messages_recv_all_cmd, - "no debug mpls ldp messages recv all", - "Negate a command or set its defaults\n" - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "Messages\n" - "Received messages, excluding periodic Keep Alives\n" - "Received messages, including periodic Keep Alives\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "type", .value = "messages" }, - &(struct vty_arg) { .name = "dir", .value = "recv" }, - &(struct vty_arg) { .name = "all", .value = "all" }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -DEFUN (ldp_no_debug_mpls_ldp_messages_sent, - ldp_no_debug_mpls_ldp_messages_sent_cmd, - "no debug mpls ldp messages sent", - "Negate a command or set its defaults\n" - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "Messages\n" - "Sent messages, excluding periodic Keep Alives\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "type", .value = "messages" }, - &(struct vty_arg) { .name = "dir", .value = "sent" }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -DEFUN (ldp_no_debug_mpls_ldp_messages_sent_all, - ldp_no_debug_mpls_ldp_messages_sent_all_cmd, - "no debug mpls ldp messages sent all", - "Negate a command or set its defaults\n" - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "Messages\n" - "Sent messages, excluding periodic Keep Alives\n" - "Sent messages, including periodic Keep Alives\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "type", .value = "messages" }, - &(struct vty_arg) { .name = "dir", .value = "sent" }, - &(struct vty_arg) { .name = "all", .value = "all" }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -DEFUN (ldp_no_debug_mpls_ldp_zebra, - ldp_no_debug_mpls_ldp_zebra_cmd, - "no debug mpls ldp zebra", - "Negate a command or set its defaults\n" - "Debugging functions\n" - "MPLS information\n" - "Label Distribution Protocol\n" - "LDP zebra information\n") -{ - struct vty_arg *args[] = - { - &(struct vty_arg) { .name = "no", .value = "no" }, - &(struct vty_arg) { .name = "type", .value = "zebra" }, - NULL - }; - return ldp_vty_debug (vty, args); -} - -void -ldp_vty_init (void) -{ - install_element (CONFIG_NODE, &ldp_mpls_ldp_cmd); - install_element (CONFIG_NODE, &ldp_l2vpn_word_type_vpls_cmd); - install_element (CONFIG_NODE, &ldp_no_mpls_ldp_cmd); - install_element (CONFIG_NODE, &ldp_no_l2vpn_word_type_vpls_cmd); - install_element (CONFIG_NODE, &ldp_debug_mpls_ldp_discovery_hello_dir_cmd); - install_element (CONFIG_NODE, &ldp_debug_mpls_ldp_errors_cmd); - install_element (CONFIG_NODE, &ldp_debug_mpls_ldp_event_cmd); - install_element (CONFIG_NODE, &ldp_debug_mpls_ldp_messages_recv_cmd); - install_element (CONFIG_NODE, &ldp_debug_mpls_ldp_messages_recv_all_cmd); - install_element (CONFIG_NODE, &ldp_debug_mpls_ldp_messages_sent_cmd); - install_element (CONFIG_NODE, &ldp_debug_mpls_ldp_messages_sent_all_cmd); - install_element (CONFIG_NODE, &ldp_debug_mpls_ldp_zebra_cmd); - install_element (CONFIG_NODE, &ldp_no_debug_mpls_ldp_discovery_hello_dir_cmd); - install_element (CONFIG_NODE, &ldp_no_debug_mpls_ldp_errors_cmd); - install_element (CONFIG_NODE, &ldp_no_debug_mpls_ldp_event_cmd); - install_element (CONFIG_NODE, &ldp_no_debug_mpls_ldp_messages_recv_cmd); - install_element (CONFIG_NODE, &ldp_no_debug_mpls_ldp_messages_recv_all_cmd); - install_element (CONFIG_NODE, &ldp_no_debug_mpls_ldp_messages_sent_cmd); - install_element (CONFIG_NODE, &ldp_no_debug_mpls_ldp_messages_sent_all_cmd); - install_element (CONFIG_NODE, &ldp_no_debug_mpls_ldp_zebra_cmd); - install_node (&ldp_node, ldp_config_write); - install_default (LDP_NODE); - install_element (LDP_NODE, &ldp_address_family_ipv4_cmd); - install_element (LDP_NODE, &ldp_address_family_ipv6_cmd); - install_element (LDP_NODE, &ldp_discovery_hello_holdtime_disc_time_cmd); - install_element (LDP_NODE, &ldp_discovery_hello_interval_disc_time_cmd); - install_element (LDP_NODE, &ldp_discovery_targeted_hello_holdtime_disc_time_cmd); - install_element (LDP_NODE, &ldp_discovery_targeted_hello_interval_disc_time_cmd); - install_element (LDP_NODE, &ldp_dual_stack_transport_connection_prefer_ipv4_cmd); - install_element (LDP_NODE, &ldp_dual_stack_cisco_interop_cmd); - install_element (LDP_NODE, &ldp_neighbor_ipv4_password_word_cmd); - install_element (LDP_NODE, &ldp_neighbor_ipv4_session_holdtime_session_time_cmd); - install_element (LDP_NODE, &ldp_neighbor_ipv4_ttl_security_disable_cmd); - install_element (LDP_NODE, &ldp_neighbor_ipv4_ttl_security_hops_hops_cmd); - install_element (LDP_NODE, &ldp_router_id_ipv4_cmd); - install_element (LDP_NODE, &ldp_no_address_family_ipv4_cmd); - install_element (LDP_NODE, &ldp_no_address_family_ipv6_cmd); - install_element (LDP_NODE, &ldp_no_discovery_hello_holdtime_disc_time_cmd); - install_element (LDP_NODE, &ldp_no_discovery_hello_interval_disc_time_cmd); - install_element (LDP_NODE, &ldp_no_discovery_targeted_hello_holdtime_disc_time_cmd); - install_element (LDP_NODE, &ldp_no_discovery_targeted_hello_interval_disc_time_cmd); - install_element (LDP_NODE, &ldp_no_dual_stack_transport_connection_prefer_ipv4_cmd); - install_element (LDP_NODE, &ldp_no_dual_stack_cisco_interop_cmd); - install_element (LDP_NODE, &ldp_no_neighbor_ipv4_password_word_cmd); - install_element (LDP_NODE, &ldp_no_neighbor_ipv4_session_holdtime_session_time_cmd); - install_element (LDP_NODE, &ldp_no_neighbor_ipv4_ttl_security_disable_cmd); - install_element (LDP_NODE, &ldp_no_neighbor_ipv4_ttl_security_hops_hops_cmd); - install_element (LDP_NODE, &ldp_no_router_id_ipv4_cmd); - install_node (&ldp_ipv4_node, NULL); - install_default (LDP_IPV4_NODE); - install_element (LDP_IPV4_NODE, &ldp_discovery_hello_holdtime_disc_time_cmd); - install_element (LDP_IPV4_NODE, &ldp_discovery_hello_interval_disc_time_cmd); - install_element (LDP_IPV4_NODE, &ldp_discovery_targeted_hello_holdtime_disc_time_cmd); - install_element (LDP_IPV4_NODE, &ldp_discovery_targeted_hello_interval_disc_time_cmd); - install_element (LDP_IPV4_NODE, &ldp_discovery_targeted_hello_accept_cmd); - install_element (LDP_IPV4_NODE, &ldp_label_local_advertise_explicit_null_cmd); - install_element (LDP_IPV4_NODE, &ldp_ttl_security_disable_cmd); - install_element (LDP_IPV4_NODE, &ldp_session_holdtime_session_time_cmd); - install_element (LDP_IPV4_NODE, &ldp_interface_ifname_cmd); - install_element (LDP_IPV4_NODE, &ldp_discovery_transport_address_ipv4_cmd); - install_element (LDP_IPV4_NODE, &ldp_neighbor_ipv4_targeted_cmd); - install_element (LDP_IPV4_NODE, &ldp_no_discovery_hello_holdtime_disc_time_cmd); - install_element (LDP_IPV4_NODE, &ldp_no_discovery_hello_interval_disc_time_cmd); - install_element (LDP_IPV4_NODE, &ldp_no_discovery_targeted_hello_holdtime_disc_time_cmd); - install_element (LDP_IPV4_NODE, &ldp_no_discovery_targeted_hello_interval_disc_time_cmd); - install_element (LDP_IPV4_NODE, &ldp_no_discovery_targeted_hello_accept_cmd); - install_element (LDP_IPV4_NODE, &ldp_no_label_local_advertise_explicit_null_cmd); - install_element (LDP_IPV4_NODE, &ldp_no_ttl_security_disable_cmd); - install_element (LDP_IPV4_NODE, &ldp_no_session_holdtime_session_time_cmd); - install_element (LDP_IPV4_NODE, &ldp_no_interface_ifname_cmd); - install_element (LDP_IPV4_NODE, &ldp_no_discovery_transport_address_ipv4_cmd); - install_element (LDP_IPV4_NODE, &ldp_no_neighbor_ipv4_targeted_cmd); - install_node (&ldp_ipv6_node, NULL); - install_default (LDP_IPV6_NODE); - install_element (LDP_IPV6_NODE, &ldp_discovery_hello_holdtime_disc_time_cmd); - install_element (LDP_IPV6_NODE, &ldp_discovery_hello_interval_disc_time_cmd); - install_element (LDP_IPV6_NODE, &ldp_discovery_targeted_hello_holdtime_disc_time_cmd); - install_element (LDP_IPV6_NODE, &ldp_discovery_targeted_hello_interval_disc_time_cmd); - install_element (LDP_IPV6_NODE, &ldp_discovery_targeted_hello_accept_cmd); - install_element (LDP_IPV6_NODE, &ldp_label_local_advertise_explicit_null_cmd); - install_element (LDP_IPV6_NODE, &ldp_ttl_security_disable_cmd); - install_element (LDP_IPV6_NODE, &ldp_session_holdtime_session_time_cmd); - install_element (LDP_IPV6_NODE, &ldp_interface_ifname_cmd); - install_element (LDP_IPV6_NODE, &ldp_discovery_transport_address_ipv6_cmd); - install_element (LDP_IPV6_NODE, &ldp_neighbor_ipv6_targeted_cmd); - install_element (LDP_IPV6_NODE, &ldp_no_discovery_hello_holdtime_disc_time_cmd); - install_element (LDP_IPV6_NODE, &ldp_no_discovery_hello_interval_disc_time_cmd); - install_element (LDP_IPV6_NODE, &ldp_no_discovery_targeted_hello_holdtime_disc_time_cmd); - install_element (LDP_IPV6_NODE, &ldp_no_discovery_targeted_hello_interval_disc_time_cmd); - install_element (LDP_IPV6_NODE, &ldp_no_discovery_targeted_hello_accept_cmd); - install_element (LDP_IPV6_NODE, &ldp_no_label_local_advertise_explicit_null_cmd); - install_element (LDP_IPV6_NODE, &ldp_no_ttl_security_disable_cmd); - install_element (LDP_IPV6_NODE, &ldp_no_session_holdtime_session_time_cmd); - install_element (LDP_IPV6_NODE, &ldp_no_interface_ifname_cmd); - install_element (LDP_IPV6_NODE, &ldp_no_discovery_transport_address_ipv6_cmd); - install_element (LDP_IPV6_NODE, &ldp_no_neighbor_ipv6_targeted_cmd); - install_node (&ldp_ipv4_iface_node, NULL); - install_default (LDP_IPV4_IFACE_NODE); - install_element (LDP_IPV4_IFACE_NODE, &ldp_discovery_hello_holdtime_disc_time_cmd); - install_element (LDP_IPV4_IFACE_NODE, &ldp_discovery_hello_interval_disc_time_cmd); - install_element (LDP_IPV4_IFACE_NODE, &ldp_no_discovery_hello_holdtime_disc_time_cmd); - install_element (LDP_IPV4_IFACE_NODE, &ldp_no_discovery_hello_interval_disc_time_cmd); - install_node (&ldp_ipv6_iface_node, NULL); - install_default (LDP_IPV6_IFACE_NODE); - install_element (LDP_IPV6_IFACE_NODE, &ldp_discovery_hello_holdtime_disc_time_cmd); - install_element (LDP_IPV6_IFACE_NODE, &ldp_discovery_hello_interval_disc_time_cmd); - install_element (LDP_IPV6_IFACE_NODE, &ldp_no_discovery_hello_holdtime_disc_time_cmd); - install_element (LDP_IPV6_IFACE_NODE, &ldp_no_discovery_hello_interval_disc_time_cmd); - install_node (&ldp_l2vpn_node, ldp_l2vpn_config_write); - install_default (LDP_L2VPN_NODE); - install_element (LDP_L2VPN_NODE, &ldp_bridge_ifname_cmd); - install_element (LDP_L2VPN_NODE, &ldp_mtu_mtu_cmd); - install_element (LDP_L2VPN_NODE, &ldp_member_interface_ifname_cmd); - install_element (LDP_L2VPN_NODE, &ldp_member_pseudowire_ifname_cmd); - install_element (LDP_L2VPN_NODE, &ldp_vc_type_pwtype_cmd); - install_element (LDP_L2VPN_NODE, &ldp_no_bridge_ifname_cmd); - install_element (LDP_L2VPN_NODE, &ldp_no_mtu_mtu_cmd); - install_element (LDP_L2VPN_NODE, &ldp_no_member_interface_ifname_cmd); - install_element (LDP_L2VPN_NODE, &ldp_no_member_pseudowire_ifname_cmd); - install_element (LDP_L2VPN_NODE, &ldp_no_vc_type_pwtype_cmd); - install_node (&ldp_pseudowire_node, NULL); - install_default (LDP_PSEUDOWIRE_NODE); - install_element (LDP_PSEUDOWIRE_NODE, &ldp_control_word_cword_cmd); - install_element (LDP_PSEUDOWIRE_NODE, &ldp_neighbor_address_addr_cmd); - install_element (LDP_PSEUDOWIRE_NODE, &ldp_neighbor_lsr_id_ipv4_cmd); - install_element (LDP_PSEUDOWIRE_NODE, &ldp_pw_id_pwid_cmd); - install_element (LDP_PSEUDOWIRE_NODE, &ldp_pw_status_disable_cmd); - install_element (LDP_PSEUDOWIRE_NODE, &ldp_no_control_word_cword_cmd); - install_element (LDP_PSEUDOWIRE_NODE, &ldp_no_neighbor_address_addr_cmd); - install_element (LDP_PSEUDOWIRE_NODE, &ldp_no_neighbor_lsr_id_ipv4_cmd); - install_element (LDP_PSEUDOWIRE_NODE, &ldp_no_pw_id_pwid_cmd); - install_element (LDP_PSEUDOWIRE_NODE, &ldp_no_pw_status_disable_cmd); - install_node (&ldp_debug_node, ldp_debug_config_write); - install_element (ENABLE_NODE, &ldp_debug_mpls_ldp_discovery_hello_dir_cmd); - install_element (ENABLE_NODE, &ldp_debug_mpls_ldp_errors_cmd); - install_element (ENABLE_NODE, &ldp_debug_mpls_ldp_event_cmd); - install_element (ENABLE_NODE, &ldp_debug_mpls_ldp_messages_recv_cmd); - install_element (ENABLE_NODE, &ldp_debug_mpls_ldp_messages_recv_all_cmd); - install_element (ENABLE_NODE, &ldp_debug_mpls_ldp_messages_sent_cmd); - install_element (ENABLE_NODE, &ldp_debug_mpls_ldp_messages_sent_all_cmd); - install_element (ENABLE_NODE, &ldp_debug_mpls_ldp_zebra_cmd); - install_element (ENABLE_NODE, &ldp_no_debug_mpls_ldp_discovery_hello_dir_cmd); - install_element (ENABLE_NODE, &ldp_no_debug_mpls_ldp_errors_cmd); - install_element (ENABLE_NODE, &ldp_no_debug_mpls_ldp_event_cmd); - install_element (ENABLE_NODE, &ldp_no_debug_mpls_ldp_messages_recv_cmd); - install_element (ENABLE_NODE, &ldp_no_debug_mpls_ldp_messages_recv_all_cmd); - install_element (ENABLE_NODE, &ldp_no_debug_mpls_ldp_messages_sent_cmd); - install_element (ENABLE_NODE, &ldp_no_debug_mpls_ldp_messages_sent_all_cmd); - install_element (ENABLE_NODE, &ldp_no_debug_mpls_ldp_zebra_cmd); - install_element (VIEW_NODE, &ldp_show_mpls_ldp_neighbor_cmd); - install_element (VIEW_NODE, &ldp_show_mpls_ldp_binding_cmd); - install_element (VIEW_NODE, &ldp_show_mpls_ldp_discovery_cmd); - install_element (VIEW_NODE, &ldp_show_mpls_ldp_interface_cmd); - install_element (VIEW_NODE, &ldp_show_mpls_ldp_address_family_binding_cmd); - install_element (VIEW_NODE, &ldp_show_mpls_ldp_address_family_discovery_cmd); - install_element (VIEW_NODE, &ldp_show_mpls_ldp_address_family_interface_cmd); - install_element (VIEW_NODE, &ldp_show_l2vpn_atom_binding_cmd); - install_element (VIEW_NODE, &ldp_show_l2vpn_atom_vc_cmd); - install_element (VIEW_NODE, &ldp_show_debugging_mpls_ldp_cmd); - install_element (VIEW_NODE, &ldp_clear_mpls_ldp_neighbor_cmd); - install_element (VIEW_NODE, &ldp_clear_mpls_ldp_neighbor_addr_cmd); -} \ No newline at end of file diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index f2b21d8175..e408abb091 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -142,7 +142,7 @@ ldp_af_iface_config_write(struct vty *vty, int af) struct iface *iface; struct iface_af *ia; - LIST_FOREACH(iface, &ldpd_conf->iface_list, entry) { + RB_FOREACH(iface, iface_head, &ldpd_conf->iface_tree) { ia = iface_af_get(iface, af); if (!ia->enabled) continue; @@ -213,7 +213,7 @@ ldp_af_config_write(struct vty *vty, int af, struct ldpd_conf *conf, vty_out(vty, " session holdtime %u%s", af_conf->keepalive, VTY_NEWLINE); - LIST_FOREACH(tnbr, &ldpd_conf->tnbr_list, entry) { + RB_FOREACH(tnbr, tnbr_head, &ldpd_conf->tnbr_tree) { if (tnbr->af == af) { vty_out(vty, " !%s", VTY_NEWLINE); vty_out(vty, " neighbor %s targeted%s", @@ -265,7 +265,7 @@ ldp_config_write(struct vty *vty) if (ldpd_conf->flags & F_LDPD_DS_CISCO_INTEROP) vty_out(vty, " dual-stack cisco-interop%s", VTY_NEWLINE); - LIST_FOREACH(nbrp, &ldpd_conf->nbrp_list, entry) { + RB_FOREACH(nbrp, nbrp_head, &ldpd_conf->nbrp_tree) { if (nbrp->flags & F_NBRP_KEEPALIVE) vty_out(vty, " neighbor %s session holdtime %u%s", inet_ntoa(nbrp->lsr_id), nbrp->keepalive, @@ -341,7 +341,7 @@ ldp_l2vpn_config_write(struct vty *vty) struct l2vpn_if *lif; struct l2vpn_pw *pw; - LIST_FOREACH(l2vpn, &ldpd_conf->l2vpn_list, entry) { + RB_FOREACH(l2vpn, l2vpn_head, &ldpd_conf->l2vpn_tree) { vty_out(vty, "l2vpn %s type vpls%s", l2vpn->name, VTY_NEWLINE); if (l2vpn->pw_type != DEFAULT_PW_TYPE) @@ -354,13 +354,13 @@ ldp_l2vpn_config_write(struct vty *vty) vty_out(vty, " bridge %s%s", l2vpn->br_ifname, VTY_NEWLINE); - LIST_FOREACH(lif, &l2vpn->if_list, entry) + RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) vty_out(vty, " member interface %s%s", lif->ifname, VTY_NEWLINE); - LIST_FOREACH(pw, &l2vpn->pw_list, entry) + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) ldp_l2vpn_pw_config_write(vty, pw); - LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) ldp_l2vpn_pw_config_write(vty, pw); vty_out(vty, " !%s", VTY_NEWLINE); @@ -393,7 +393,7 @@ ldp_iface_is_configured(struct ldpd_conf *xconf, const char *ifname) if (if_lookup_name(xconf, ifname)) return (1); - LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) { + RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) { if (l2vpn_if_find_name(l2vpn, ifname)) return (1); if (l2vpn_pw_find_name(l2vpn, ifname)) @@ -740,7 +740,7 @@ ldp_vty_nbr_session_holdtime(struct vty *vty, struct vty_arg *args[]) } else { if (nbrp == NULL) { nbrp = nbr_params_new(lsr_id); - LIST_INSERT_HEAD(&vty_conf->nbrp_list, nbrp, entry); + RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp); } else if (nbrp->keepalive == secs) goto cancel; @@ -857,7 +857,7 @@ ldp_vty_interface(struct vty *vty, struct vty_arg *args[]) ia = iface_af_get(iface, af); ia->enabled = 1; - LIST_INSERT_HEAD(&vty_conf->iface_list, iface, entry); + RB_INSERT(iface_head, &vty_conf->iface_tree, iface); ldp_reload_ref(vty_conf, (void **)&iface); } else { memset(&kif, 0, sizeof(kif)); @@ -955,7 +955,7 @@ ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[]) if (tnbr == NULL) goto cancel; - LIST_REMOVE(tnbr, entry); + RB_REMOVE(tnbr_head, &vty_conf->tnbr_tree, tnbr); free(tnbr); ldp_reload(vty_conf); return (CMD_SUCCESS); @@ -966,7 +966,7 @@ ldp_vty_neighbor_targeted(struct vty *vty, struct vty_arg *args[]) tnbr = tnbr_new(af, &addr); tnbr->flags |= F_TNBR_CONFIGURED; - LIST_INSERT_HEAD(&vty_conf->tnbr_list, tnbr, entry); + RB_INSERT(tnbr_head, &vty_conf->tnbr_tree, tnbr); ldp_reload(vty_conf); @@ -1129,7 +1129,7 @@ ldp_vty_neighbor_password(struct vty *vty, struct vty_arg *args[]) } else { if (nbrp == NULL) { nbrp = nbr_params_new(lsr_id); - LIST_INSERT_HEAD(&vty_conf->nbrp_list, nbrp, entry); + 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; @@ -1195,7 +1195,7 @@ ldp_vty_neighbor_ttl_security(struct vty *vty, struct vty_arg *args[]) } else { if (nbrp == NULL) { nbrp = nbr_params_new(lsr_id); - LIST_INSERT_HEAD(&vty_conf->nbrp_list, nbrp, entry); + RB_INSERT(nbrp_head, &vty_conf->nbrp_tree, nbrp); } nbrp->flags |= F_NBRP_GTSM; @@ -1235,7 +1235,7 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[]) if (l2vpn == NULL) goto cancel; - LIST_REMOVE(l2vpn, entry); + RB_REMOVE(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn); l2vpn_del(l2vpn); ldp_reload(vty_conf); return (CMD_SUCCESS); @@ -1248,9 +1248,9 @@ ldp_vty_l2vpn(struct vty *vty, struct vty_arg *args[]) l2vpn = l2vpn_new(name_str); l2vpn->type = L2VPN_TYPE_VPLS; - LIST_INSERT_HEAD(&vty_conf->l2vpn_list, l2vpn, entry); + RB_INSERT(l2vpn_head, &vty_conf->l2vpn_tree, l2vpn); - ldp_reload(vty_conf); + ldp_reload_ref(vty_conf, (void **)&l2vpn); VTY_PUSH_CONTEXT(LDP_L2VPN_NODE, l2vpn); return (CMD_SUCCESS); @@ -1369,7 +1369,7 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) if (lif == NULL) goto cancel; - LIST_REMOVE(lif, entry); + RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); free(lif); ldp_reload(vty_conf); return (CMD_SUCCESS); @@ -1392,7 +1392,7 @@ ldp_vty_l2vpn_interface(struct vty *vty, struct vty_arg *args[]) } lif = l2vpn_if_new(l2vpn, &kif); - LIST_INSERT_HEAD(&l2vpn->if_list, lif, entry); + RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); ldp_reload_ref(vty_conf, (void **)&l2vpn); @@ -1425,14 +1425,14 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) if (pw == NULL) goto cancel; - LIST_REMOVE(pw, entry); + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); free(pw); ldp_reload(vty_conf); return (CMD_SUCCESS); } if (pw) { - VTY_PUSH_CONTEXT(LDP_PSEUDOWIRE_NODE, pw); + VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw); goto cancel; } @@ -1451,10 +1451,10 @@ ldp_vty_l2vpn_pseudowire(struct vty *vty, struct vty_arg *args[]) pw = l2vpn_pw_new(l2vpn, &kif); pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF; - LIST_INSERT_HEAD(&l2vpn->pw_inactive_list, pw, entry); + RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); ldp_reload_ref(vty_conf, (void **)&pw); - VTY_PUSH_CONTEXT(LDP_PSEUDOWIRE_NODE, pw); + VTY_PUSH_CONTEXT_SUB(LDP_PSEUDOWIRE_NODE, pw); return (CMD_SUCCESS); @@ -1474,7 +1474,7 @@ 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(l2vpn_pw); + pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); if (disable) @@ -1510,7 +1510,7 @@ ldp_vty_l2vpn_pw_nbr_addr(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - pw = VTY_GET_CONTEXT(l2vpn_pw); + pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); if (disable) { @@ -1546,7 +1546,7 @@ ldp_vty_l2vpn_pw_nbr_id(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - pw = VTY_GET_CONTEXT(l2vpn_pw); + pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); if (disable) @@ -1578,7 +1578,7 @@ ldp_vty_l2vpn_pw_pwid(struct vty *vty, struct vty_arg *args[]) return (CMD_WARNING); } - pw = VTY_GET_CONTEXT(l2vpn_pw); + pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); if (disable) @@ -1600,7 +1600,7 @@ ldp_vty_l2vpn_pw_pwstatus(struct vty *vty, struct vty_arg *args[]) disable = (vty_get_arg_value(args, "no")) ? 1 : 0; - pw = VTY_GET_CONTEXT(l2vpn_pw); + pw = VTY_GET_CONTEXT_SUB(l2vpn_pw); vty_conf = ldp_dup_config_ref(ldpd_conf, (void **)&pw); if (disable) @@ -1641,14 +1641,14 @@ iface_new_api(struct ldpd_conf *conf, const char *name) } iface = if_new(&kif); - LIST_INSERT_HEAD(&conf->iface_list, iface, entry); + RB_INSERT(iface_head, &conf->iface_tree, iface); return (iface); } void -iface_del_api(struct iface *iface) +iface_del_api(struct ldpd_conf *conf, struct iface *iface) { - LIST_REMOVE(iface, entry); + RB_REMOVE(iface_head, &conf->iface_tree, iface); free(iface); } @@ -1665,14 +1665,14 @@ tnbr_new_api(struct ldpd_conf *conf, int af, union ldpd_addr *addr) tnbr = tnbr_new(af, addr); tnbr->flags |= F_TNBR_CONFIGURED; - LIST_INSERT_HEAD(&conf->tnbr_list, tnbr, entry); + RB_INSERT(tnbr_head, &conf->tnbr_tree, tnbr); return (tnbr); } void -tnbr_del_api(struct tnbr *tnbr) +tnbr_del_api(struct ldpd_conf *conf, struct tnbr *tnbr) { - LIST_REMOVE(tnbr, entry); + RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr); free(tnbr); } @@ -1685,14 +1685,14 @@ nbrp_new_api(struct ldpd_conf *conf, struct in_addr lsr_id) return (NULL); nbrp = nbr_params_new(lsr_id); - LIST_INSERT_HEAD(&conf->nbrp_list, nbrp, entry); + RB_INSERT(nbrp_head, &conf->nbrp_tree, nbrp); return (nbrp); } void -nbrp_del_api(struct nbr_params *nbrp) +nbrp_del_api(struct ldpd_conf *conf, struct nbr_params *nbrp) { - LIST_REMOVE(nbrp, entry); + RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp); free(nbrp); } @@ -1706,29 +1706,29 @@ l2vpn_new_api(struct ldpd_conf *conf, const char *name) l2vpn = l2vpn_new(name); l2vpn->type = L2VPN_TYPE_VPLS; - LIST_INSERT_HEAD(&conf->l2vpn_list, l2vpn, entry); + RB_INSERT(l2vpn_head, &conf->l2vpn_tree, l2vpn); return (l2vpn); } void -l2vpn_del_api(struct l2vpn *l2vpn) +l2vpn_del_api(struct ldpd_conf *conf, struct l2vpn *l2vpn) { struct l2vpn_if *lif; struct l2vpn_pw *pw; - while ((lif = LIST_FIRST(&l2vpn->if_list)) != NULL) { - LIST_REMOVE(lif, entry); + while ((lif = RB_ROOT(&l2vpn->if_tree)) != NULL) { + RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); free(lif); } - while ((pw = LIST_FIRST(&l2vpn->pw_list)) != NULL) { - LIST_REMOVE(pw, entry); + while ((pw = RB_ROOT(&l2vpn->pw_tree)) != NULL) { + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw); free(pw); } - while ((pw = LIST_FIRST(&l2vpn->pw_inactive_list)) != NULL) { - LIST_REMOVE(pw, entry); + while ((pw = RB_ROOT(&l2vpn->pw_inactive_tree)) != NULL) { + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); free(pw); } - LIST_REMOVE(l2vpn, entry); + RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn); free(l2vpn); } @@ -1752,14 +1752,14 @@ l2vpn_if_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn, } lif = l2vpn_if_new(l2vpn, &kif); - LIST_INSERT_HEAD(&l2vpn->if_list, lif, entry); + RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, lif); return (lif); } void -l2vpn_if_del_api(struct l2vpn_if *lif) +l2vpn_if_del_api(struct l2vpn *l2vpn, struct l2vpn_if *lif) { - LIST_REMOVE(lif, entry); + RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); free(lif); } @@ -1784,13 +1784,13 @@ l2vpn_pw_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn, pw = l2vpn_pw_new(l2vpn, &kif); pw->flags = F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF; - LIST_INSERT_HEAD(&l2vpn->pw_inactive_list, pw, entry); + RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); return (pw); } void -l2vpn_pw_del_api(struct l2vpn_pw *pw) +l2vpn_pw_del_api(struct l2vpn *l2vpn, struct l2vpn_pw *pw) { - LIST_REMOVE(pw, entry); + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); free(pw); } diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 8a9847bdfd..391e013376 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -850,40 +850,40 @@ main_imsg_send_config(struct ldpd_conf *xconf) sizeof(*xconf)) == -1) return (-1); - LIST_FOREACH(iface, &xconf->iface_list, entry) { + RB_FOREACH(iface, iface_head, &xconf->iface_tree) { if (main_imsg_compose_both(IMSG_RECONF_IFACE, iface, sizeof(*iface)) == -1) return (-1); } - LIST_FOREACH(tnbr, &xconf->tnbr_list, entry) { + RB_FOREACH(tnbr, tnbr_head, &xconf->tnbr_tree) { if (main_imsg_compose_both(IMSG_RECONF_TNBR, tnbr, sizeof(*tnbr)) == -1) return (-1); } - LIST_FOREACH(nbrp, &xconf->nbrp_list, entry) { + RB_FOREACH(nbrp, nbrp_head, &xconf->nbrp_tree) { if (main_imsg_compose_both(IMSG_RECONF_NBRP, nbrp, sizeof(*nbrp)) == -1) return (-1); } - LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) { + RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) { if (main_imsg_compose_both(IMSG_RECONF_L2VPN, l2vpn, sizeof(*l2vpn)) == -1) return (-1); - LIST_FOREACH(lif, &l2vpn->if_list, entry) { + RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) { if (main_imsg_compose_both(IMSG_RECONF_L2VPN_IF, lif, sizeof(*lif)) == -1) return (-1); } - LIST_FOREACH(pw, &l2vpn->pw_list, entry) { + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) { if (main_imsg_compose_both(IMSG_RECONF_L2VPN_PW, pw, sizeof(*pw)) == -1) return (-1); } - LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) { + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) { if (main_imsg_compose_both(IMSG_RECONF_L2VPN_IPW, pw, sizeof(*pw)) == -1) return (-1); @@ -930,15 +930,15 @@ ldp_config_normalize(struct ldpd_conf *xconf, void **ref) ldp_config_reset_af(xconf, AF_INET6, ref); } - LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) { - LIST_FOREACH(pw, &l2vpn->pw_list, entry) { + RB_FOREACH(l2vpn, l2vpn_head, &xconf->l2vpn_tree) { + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) { if (pw->flags & F_PW_STATIC_NBR_ADDR) continue; pw->af = AF_INET; pw->addr.v4 = pw->lsr_id; } - LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) { + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) { if (pw->flags & F_PW_STATIC_NBR_ADDR) continue; @@ -954,17 +954,17 @@ ldp_config_reset_main(struct ldpd_conf *conf, void **ref) struct iface *iface; struct nbr_params *nbrp; - while ((iface = LIST_FIRST(&conf->iface_list)) != NULL) { + while ((iface = RB_ROOT(&conf->iface_tree)) != NULL) { if (ref && *ref == iface) *ref = NULL; - LIST_REMOVE(iface, entry); + RB_REMOVE(iface_head, &conf->iface_tree, iface); free(iface); } - while ((nbrp = LIST_FIRST(&conf->nbrp_list)) != NULL) { + while ((nbrp = RB_ROOT(&conf->nbrp_tree)) != NULL) { if (ref && *ref == nbrp) *ref = NULL; - LIST_REMOVE(nbrp, entry); + RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp); free(nbrp); } @@ -987,18 +987,18 @@ ldp_config_reset_af(struct ldpd_conf *conf, int af, void **ref) struct iface_af *ia; struct tnbr *tnbr, *ttmp; - LIST_FOREACH(iface, &conf->iface_list, entry) { + RB_FOREACH(iface, iface_head, &conf->iface_tree) { ia = iface_af_get(iface, af); ia->enabled = 0; } - LIST_FOREACH_SAFE(tnbr, &conf->tnbr_list, entry, ttmp) { + RB_FOREACH_SAFE(tnbr, tnbr_head, &conf->tnbr_tree, ttmp) { if (tnbr->af != af) continue; if (ref && *ref == tnbr) *ref = NULL; - LIST_REMOVE(tnbr, entry); + RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr); free(tnbr); } @@ -1032,46 +1032,46 @@ ldp_dup_config_ref(struct ldpd_conf *conf, void **ref) } while (0) COPY(xconf, conf); - LIST_INIT(&xconf->iface_list); - LIST_INIT(&xconf->tnbr_list); - LIST_INIT(&xconf->nbrp_list); - LIST_INIT(&xconf->l2vpn_list); + RB_INIT(&xconf->iface_tree); + RB_INIT(&xconf->tnbr_tree); + RB_INIT(&xconf->nbrp_tree); + RB_INIT(&xconf->l2vpn_tree); - LIST_FOREACH(iface, &conf->iface_list, entry) { + RB_FOREACH(iface, iface_head, &conf->iface_tree) { COPY(xi, iface); xi->ipv4.iface = xi; xi->ipv6.iface = xi; - LIST_INSERT_HEAD(&xconf->iface_list, xi, entry); + RB_INSERT(iface_head, &xconf->iface_tree, xi); } - LIST_FOREACH(tnbr, &conf->tnbr_list, entry) { + RB_FOREACH(tnbr, tnbr_head, &conf->tnbr_tree) { COPY(xt, tnbr); - LIST_INSERT_HEAD(&xconf->tnbr_list, xt, entry); + RB_INSERT(tnbr_head, &xconf->tnbr_tree, xt); } - LIST_FOREACH(nbrp, &conf->nbrp_list, entry) { + RB_FOREACH(nbrp, nbrp_head, &conf->nbrp_tree) { COPY(xn, nbrp); - LIST_INSERT_HEAD(&xconf->nbrp_list, xn, entry); + RB_INSERT(nbrp_head, &xconf->nbrp_tree, xn); } - LIST_FOREACH(l2vpn, &conf->l2vpn_list, entry) { + RB_FOREACH(l2vpn, l2vpn_head, &conf->l2vpn_tree) { COPY(xl, l2vpn); - LIST_INIT(&xl->if_list); - LIST_INIT(&xl->pw_list); - LIST_INIT(&xl->pw_inactive_list); - LIST_INSERT_HEAD(&xconf->l2vpn_list, xl, entry); + RB_INIT(&xl->if_tree); + RB_INIT(&xl->pw_tree); + RB_INIT(&xl->pw_inactive_tree); + RB_INSERT(l2vpn_head, &xconf->l2vpn_tree, xl); - LIST_FOREACH(lif, &l2vpn->if_list, entry) { + RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) { COPY(xf, lif); xf->l2vpn = xl; - LIST_INSERT_HEAD(&xl->if_list, xf, entry); + RB_INSERT(l2vpn_if_head, &xl->if_tree, xf); } - LIST_FOREACH(pw, &l2vpn->pw_list, entry) { + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) { COPY(xp, pw); xp->l2vpn = xl; - LIST_INSERT_HEAD(&xl->pw_list, xp, entry); + RB_INSERT(l2vpn_pw_head, &xl->pw_tree, xp); } - LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) { + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) { COPY(xp, pw); xp->l2vpn = xl; - LIST_INSERT_HEAD(&xl->pw_inactive_list, xp, entry); + RB_INSERT(l2vpn_pw_head, &xl->pw_inactive_tree, xp); } } #undef COPY @@ -1093,20 +1093,20 @@ ldp_clear_config(struct ldpd_conf *xconf) struct nbr_params *nbrp; struct l2vpn *l2vpn; - while ((iface = LIST_FIRST(&xconf->iface_list)) != NULL) { - LIST_REMOVE(iface, entry); + while ((iface = RB_ROOT(&xconf->iface_tree)) != NULL) { + RB_REMOVE(iface_head, &xconf->iface_tree, iface); free(iface); } - while ((tnbr = LIST_FIRST(&xconf->tnbr_list)) != NULL) { - LIST_REMOVE(tnbr, entry); + while ((tnbr = RB_ROOT(&xconf->tnbr_tree)) != NULL) { + RB_REMOVE(tnbr_head, &xconf->tnbr_tree, tnbr); free(tnbr); } - while ((nbrp = LIST_FIRST(&xconf->nbrp_list)) != NULL) { - LIST_REMOVE(nbrp, entry); + while ((nbrp = RB_ROOT(&xconf->nbrp_tree)) != NULL) { + RB_REMOVE(nbrp_head, &xconf->nbrp_tree, nbrp); free(nbrp); } - while ((l2vpn = LIST_FIRST(&xconf->l2vpn_list)) != NULL) { - LIST_REMOVE(l2vpn, entry); + while ((l2vpn = RB_ROOT(&xconf->l2vpn_tree)) != NULL) { + RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, l2vpn); l2vpn_del(l2vpn); } @@ -1236,10 +1236,10 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) { struct iface *iface, *itmp, *xi; - LIST_FOREACH_SAFE(iface, &conf->iface_list, entry, itmp) { + RB_FOREACH_SAFE(iface, iface_head, &conf->iface_tree, itmp) { /* find deleted interfaces */ if ((xi = if_lookup_name(xconf, iface->name)) == NULL) { - LIST_REMOVE(iface, entry); + RB_REMOVE(iface_head, &conf->iface_tree, iface); switch (ldpd_process) { case PROC_LDE_ENGINE: @@ -1254,11 +1254,11 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) free(iface); } } - LIST_FOREACH_SAFE(xi, &xconf->iface_list, entry, itmp) { + RB_FOREACH_SAFE(xi, iface_head, &xconf->iface_tree, itmp) { /* find new interfaces */ if ((iface = if_lookup_name(conf, xi->name)) == NULL) { - LIST_REMOVE(xi, entry); - LIST_INSERT_HEAD(&conf->iface_list, xi, entry); + RB_REMOVE(iface_head, &xconf->iface_tree, xi); + RB_INSERT(iface_head, &conf->iface_tree, xi); if (ldpd_process == PROC_MAIN) { QOBJ_REG (xi, iface); @@ -1271,7 +1271,7 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) /* update existing interfaces */ merge_iface_af(&iface->ipv4, &xi->ipv4); merge_iface_af(&iface->ipv6, &xi->ipv6); - LIST_REMOVE(xi, entry); + RB_REMOVE(iface_head, &xconf->iface_tree, xi); if (ref && *ref == xi) *ref = iface; free(xi); @@ -1295,7 +1295,7 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) { struct tnbr *tnbr, *ttmp, *xt; - LIST_FOREACH_SAFE(tnbr, &conf->tnbr_list, entry, ttmp) { + RB_FOREACH_SAFE(tnbr, tnbr_head, &conf->tnbr_tree, ttmp) { if (!(tnbr->flags & F_TNBR_CONFIGURED)) continue; @@ -1303,26 +1303,26 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) if ((xt = tnbr_find(xconf, tnbr->af, &tnbr->addr)) == NULL) { switch (ldpd_process) { case PROC_LDE_ENGINE: - LIST_REMOVE(tnbr, entry); + RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr); free(tnbr); break; case PROC_LDP_ENGINE: tnbr->flags &= ~F_TNBR_CONFIGURED; - tnbr_check(tnbr); + tnbr_check(conf, tnbr); break; case PROC_MAIN: - LIST_REMOVE(tnbr, entry); + RB_REMOVE(tnbr_head, &conf->tnbr_tree, tnbr); QOBJ_UNREG (tnbr); free(tnbr); break; } } } - LIST_FOREACH_SAFE(xt, &xconf->tnbr_list, entry, ttmp) { + RB_FOREACH_SAFE(xt, tnbr_head, &xconf->tnbr_tree, ttmp) { /* find new tnbrs */ if ((tnbr = tnbr_find(conf, xt->af, &xt->addr)) == NULL) { - LIST_REMOVE(xt, entry); - LIST_INSERT_HEAD(&conf->tnbr_list, xt, entry); + RB_REMOVE(tnbr_head, &xconf->tnbr_tree, xt); + RB_INSERT(tnbr_head, &conf->tnbr_tree, xt); switch (ldpd_process) { case PROC_LDE_ENGINE: @@ -1340,7 +1340,7 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) /* update existing tnbrs */ if (!(tnbr->flags & F_TNBR_CONFIGURED)) tnbr->flags |= F_TNBR_CONFIGURED; - LIST_REMOVE(xt, entry); + RB_REMOVE(tnbr_head, &xconf->tnbr_tree, xt); if (ref && *ref == xt) *ref = tnbr; free(xt); @@ -1354,7 +1354,7 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) struct nbr *nbr; int nbrp_changed; - LIST_FOREACH_SAFE(nbrp, &conf->nbrp_list, entry, ntmp) { + RB_FOREACH_SAFE(nbrp, nbrp_head, &conf->nbrp_tree, ntmp) { /* find deleted nbrps */ if ((xn = nbr_params_find(xconf, nbrp->lsr_id)) == NULL) { switch (ldpd_process) { @@ -1380,15 +1380,15 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) QOBJ_UNREG (nbrp); break; } - LIST_REMOVE(nbrp, entry); + RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp); free(nbrp); } } - LIST_FOREACH_SAFE(xn, &xconf->nbrp_list, entry, ntmp) { + RB_FOREACH_SAFE(xn, nbrp_head, &xconf->nbrp_tree, ntmp) { /* find new nbrps */ if ((nbrp = nbr_params_find(conf, xn->lsr_id)) == NULL) { - LIST_REMOVE(xn, entry); - LIST_INSERT_HEAD(&conf->nbrp_list, xn, entry); + RB_REMOVE(nbrp_head, &xconf->nbrp_tree, xn); + RB_INSERT(nbrp_head, &conf->nbrp_tree, xn); switch (ldpd_process) { case PROC_LDE_ENGINE: @@ -1455,7 +1455,7 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) nbr_establish_connection(nbr); } } - LIST_REMOVE(xn, entry); + RB_REMOVE(nbrp_head, &xconf->nbrp_tree, xn); if (ref && *ref == xn) *ref = nbrp; free(xn); @@ -1469,10 +1469,10 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) struct l2vpn_if *lif; struct l2vpn_pw *pw; - LIST_FOREACH_SAFE(l2vpn, &conf->l2vpn_list, entry, ltmp) { + RB_FOREACH_SAFE(l2vpn, l2vpn_head, &conf->l2vpn_tree, ltmp) { /* find deleted l2vpns */ if ((xl = l2vpn_find(xconf, l2vpn->name)) == NULL) { - LIST_REMOVE(l2vpn, entry); + RB_REMOVE(l2vpn_head, &conf->l2vpn_tree, l2vpn); switch (ldpd_process) { case PROC_LDE_ENGINE: @@ -1482,11 +1482,11 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) ldpe_l2vpn_exit(l2vpn); break; case PROC_MAIN: - LIST_FOREACH(lif, &l2vpn->if_list, entry) + RB_FOREACH(lif, l2vpn_if_head, &l2vpn->if_tree) QOBJ_UNREG (lif); - LIST_FOREACH(pw, &l2vpn->pw_list, entry) + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_tree) QOBJ_UNREG (pw); - LIST_FOREACH(pw, &l2vpn->pw_inactive_list, entry) + RB_FOREACH(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree) QOBJ_UNREG (pw); QOBJ_UNREG (l2vpn); break; @@ -1494,11 +1494,11 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) l2vpn_del(l2vpn); } } - LIST_FOREACH_SAFE(xl, &xconf->l2vpn_list, entry, ltmp) { + RB_FOREACH_SAFE(xl, l2vpn_head, &xconf->l2vpn_tree, ltmp) { /* find new l2vpns */ if ((l2vpn = l2vpn_find(conf, xl->name)) == NULL) { - LIST_REMOVE(xl, entry); - LIST_INSERT_HEAD(&conf->l2vpn_list, xl, entry); + RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl); + RB_INSERT(l2vpn_head, &conf->l2vpn_tree, xl); switch (ldpd_process) { case PROC_LDE_ENGINE: @@ -1516,7 +1516,7 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf, void **ref) /* update existing l2vpns */ merge_l2vpn(conf, l2vpn, xl, ref); - LIST_REMOVE(xl, entry); + RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl); if (ref && *ref == xl) *ref = l2vpn; free(xl); @@ -1530,42 +1530,42 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void struct l2vpn_pw *pw, *ptmp, *xp; struct nbr *nbr; int reset_nbr, reinstall_pwfec, reinstall_tnbr; - LIST_HEAD(, l2vpn_pw) pw_aux_list; + struct l2vpn_pw_head pw_aux_list; int previous_pw_type, previous_mtu; previous_pw_type = l2vpn->pw_type; previous_mtu = l2vpn->mtu; /* merge intefaces */ - LIST_FOREACH_SAFE(lif, &l2vpn->if_list, entry, ftmp) { + 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 (ldpd_process == PROC_MAIN) QOBJ_UNREG (lif); - LIST_REMOVE(lif, entry); + RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif); free(lif); } } - LIST_FOREACH_SAFE(xf, &xl->if_list, entry, ftmp) { + RB_FOREACH_SAFE(xf, l2vpn_if_head, &xl->if_tree, ftmp) { /* find new interfaces */ if ((lif = l2vpn_if_find_name(l2vpn, xf->ifname)) == NULL) { - LIST_REMOVE(xf, entry); - LIST_INSERT_HEAD(&l2vpn->if_list, xf, entry); + RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf); + RB_INSERT(l2vpn_if_head, &l2vpn->if_tree, xf); xf->l2vpn = l2vpn; if (ldpd_process == PROC_MAIN) QOBJ_REG (xf, l2vpn_if); continue; } - LIST_REMOVE(xf, entry); + RB_REMOVE(l2vpn_if_head, &xl->if_tree, xf); if (ref && *ref == xf) *ref = lif; free(xf); } /* merge active pseudowires */ - LIST_INIT(&pw_aux_list); - LIST_FOREACH_SAFE(pw, &l2vpn->pw_list, entry, ptmp) { + 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) { switch (ldpd_process) { @@ -1580,15 +1580,15 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void break; } - LIST_REMOVE(pw, entry); + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw); free(pw); } } - LIST_FOREACH_SAFE(xp, &xl->pw_list, entry, ptmp) { + 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) { - LIST_REMOVE(xp, entry); - LIST_INSERT_HEAD(&l2vpn->pw_list, xp, entry); + RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp); + RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, xp); xp->l2vpn = l2vpn; switch (ldpd_process) { @@ -1644,8 +1644,8 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void } /* remove from active list */ - LIST_REMOVE(pw, entry); - LIST_INSERT_HEAD(&pw_aux_list, pw, entry); + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw); + RB_INSERT(l2vpn_pw_head, &pw_aux_list, pw); } if (ldpd_process == PROC_LDP_ENGINE) { @@ -1689,27 +1689,27 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void l2vpn->mtu = previous_mtu; } - LIST_REMOVE(xp, entry); + RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp); if (ref && *ref == xp) *ref = pw; free(xp); } /* merge inactive pseudowires */ - LIST_FOREACH_SAFE(pw, &l2vpn->pw_inactive_list, entry, ptmp) { + 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) { - LIST_REMOVE(pw, entry); + RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw); if (ldpd_process == PROC_MAIN) QOBJ_UNREG (pw); free(pw); } } - LIST_FOREACH_SAFE(xp, &xl->pw_inactive_list, entry, ptmp) { + 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) { - LIST_REMOVE(xp, entry); - LIST_INSERT_HEAD(&l2vpn->pw_inactive_list, xp, entry); + RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp); + RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, xp); xp->l2vpn = l2vpn; if (ldpd_process == PROC_MAIN) QOBJ_REG (xp, l2vpn_pw); @@ -1728,8 +1728,8 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void /* check if the pseudowire should be activated */ if (pw->lsr_id.s_addr != INADDR_ANY && pw->pwid != 0) { /* remove from inactive list */ - LIST_REMOVE(pw, entry); - LIST_INSERT_HEAD(&l2vpn->pw_list, pw, entry); + 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: @@ -1743,16 +1743,16 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl, void } } - LIST_REMOVE(xp, entry); + 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 */ - LIST_FOREACH_SAFE(pw, &pw_aux_list, entry, ptmp) { - LIST_REMOVE(pw, entry); - LIST_INSERT_HEAD(&l2vpn->pw_inactive_list, pw, entry); + 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; @@ -1770,10 +1770,10 @@ config_new_empty(void) if (xconf == NULL) fatal(NULL); - LIST_INIT(&xconf->iface_list); - LIST_INIT(&xconf->tnbr_list); - LIST_INIT(&xconf->nbrp_list); - LIST_INIT(&xconf->l2vpn_list); + RB_INIT(&xconf->iface_tree); + RB_INIT(&xconf->tnbr_tree); + RB_INIT(&xconf->nbrp_tree); + RB_INIT(&xconf->l2vpn_tree); return (xconf); } diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index 630b192489..4d575597ae 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -196,7 +196,10 @@ enum nbr_action { NBR_ACT_CLOSE_SESSION }; -TAILQ_HEAD(mapping_head, mapping_entry); +/* forward declarations */ +RB_HEAD(global_adj_head, adj); +RB_HEAD(nbr_adj_head, adj); +RB_HEAD(ia_adj_head, adj); struct map { uint8_t type; @@ -256,7 +259,7 @@ struct iface_af { int af; int enabled; int state; - LIST_HEAD(, adj) adj_list; + struct ia_adj_head adj_tree; time_t uptime; struct thread *hello_timer; uint16_t hello_holdtime; @@ -264,7 +267,7 @@ struct iface_af { }; struct iface { - LIST_ENTRY(iface) entry; + RB_ENTRY(iface) entry; char name[IF_NAMESIZE]; unsigned int ifindex; struct if_addr_head addr_list; @@ -275,11 +278,13 @@ struct iface { struct iface_af ipv6; QOBJ_FIELDS }; +RB_HEAD(iface_head, iface); +RB_PROTOTYPE(iface_head, iface, entry, iface_compare); DECLARE_QOBJ_TYPE(iface) /* source of targeted hellos */ struct tnbr { - LIST_ENTRY(tnbr) entry; + RB_ENTRY(tnbr) entry; struct thread *hello_timer; struct adj *adj; int af; @@ -289,6 +294,8 @@ struct tnbr { uint8_t flags; QOBJ_FIELDS }; +RB_HEAD(tnbr_head, tnbr); +RB_PROTOTYPE(tnbr_head, tnbr, entry, tnbr_compare); DECLARE_QOBJ_TYPE(tnbr) #define F_TNBR_CONFIGURED 0x01 #define F_TNBR_DYNAMIC 0x02 @@ -300,7 +307,7 @@ enum auth_method { /* neighbor specific parameters */ struct nbr_params { - LIST_ENTRY(nbr_params) entry; + RB_ENTRY(nbr_params) entry; struct in_addr lsr_id; uint16_t keepalive; int gtsm_enabled; @@ -313,23 +320,27 @@ struct nbr_params { uint8_t flags; QOBJ_FIELDS }; +RB_HEAD(nbrp_head, nbr_params); +RB_PROTOTYPE(nbrp_head, nbr_params, entry, nbr_params_compare); DECLARE_QOBJ_TYPE(nbr_params) #define F_NBRP_KEEPALIVE 0x01 #define F_NBRP_GTSM 0x02 #define F_NBRP_GTSM_HOPS 0x04 struct l2vpn_if { - LIST_ENTRY(l2vpn_if) entry; + RB_ENTRY(l2vpn_if) entry; struct l2vpn *l2vpn; char ifname[IF_NAMESIZE]; unsigned int ifindex; uint16_t flags; QOBJ_FIELDS }; +RB_HEAD(l2vpn_if_head, l2vpn_if); +RB_PROTOTYPE(l2vpn_if_head, l2vpn_if, entry, l2vpn_if_compare); DECLARE_QOBJ_TYPE(l2vpn_if) struct l2vpn_pw { - LIST_ENTRY(l2vpn_pw) entry; + RB_ENTRY(l2vpn_pw) entry; struct l2vpn *l2vpn; struct in_addr lsr_id; int af; @@ -343,6 +354,8 @@ struct l2vpn_pw { uint8_t flags; QOBJ_FIELDS }; +RB_HEAD(l2vpn_pw_head, l2vpn_pw); +RB_PROTOTYPE(l2vpn_pw_head, l2vpn_pw, entry, l2vpn_pw_compare); DECLARE_QOBJ_TYPE(l2vpn_pw) #define F_PW_STATUSTLV_CONF 0x01 /* status tlv configured */ #define F_PW_STATUSTLV 0x02 /* status tlv negotiated */ @@ -352,18 +365,20 @@ DECLARE_QOBJ_TYPE(l2vpn_pw) #define F_PW_STATIC_NBR_ADDR 0x20 /* static neighbor address configured */ struct l2vpn { - LIST_ENTRY(l2vpn) entry; + RB_ENTRY(l2vpn) entry; char name[L2VPN_NAME_LEN]; int type; int pw_type; int mtu; char br_ifname[IF_NAMESIZE]; unsigned int br_ifindex; - LIST_HEAD(, l2vpn_if) if_list; - LIST_HEAD(, l2vpn_pw) pw_list; - LIST_HEAD(, l2vpn_pw) pw_inactive_list; + struct l2vpn_if_head if_tree; + struct l2vpn_pw_head pw_tree; + struct l2vpn_pw_head pw_inactive_tree; QOBJ_FIELDS }; +RB_HEAD(l2vpn_head, l2vpn); +RB_PROTOTYPE(l2vpn_head, l2vpn, entry, l2vpn_compare); DECLARE_QOBJ_TYPE(l2vpn) #define L2VPN_TYPE_VPWS 1 #define L2VPN_TYPE_VPLS 2 @@ -404,10 +419,10 @@ struct ldpd_conf { struct in_addr rtr_id; struct ldpd_af_conf ipv4; struct ldpd_af_conf ipv6; - LIST_HEAD(, iface) iface_list; - LIST_HEAD(, tnbr) tnbr_list; - LIST_HEAD(, nbr_params) nbrp_list; - LIST_HEAD(, l2vpn) l2vpn_list; + struct iface_head iface_tree; + struct tnbr_head tnbr_tree; + struct nbrp_head nbrp_tree; + struct l2vpn_head l2vpn_tree; uint16_t lhello_holdtime; uint16_t lhello_interval; uint16_t thello_holdtime; @@ -438,7 +453,7 @@ struct ldpd_global { uint32_t conf_seqnum; int pfkeysock; struct if_addr_head addr_list; - LIST_HEAD(, adj) adj_list; + struct global_adj_head adj_tree; struct in_addr mcast_addr_v4; struct in6_addr mcast_addr_v6; TAILQ_HEAD(, pending_conn) pending_conns; @@ -627,23 +642,28 @@ void config_clear(struct ldpd_conf *); /* ldp_vty_conf.c */ /* NOTE: the parameters' names should be preserved because of codegen */ -struct iface *iface_new_api(struct ldpd_conf *cfg, +struct iface *iface_new_api(struct ldpd_conf *conf, const char *name); -void iface_del_api(struct iface *iface); -struct tnbr *tnbr_new_api(struct ldpd_conf *cfg, int af, +void iface_del_api(struct ldpd_conf *conf, + struct iface *iface); +struct tnbr *tnbr_new_api(struct ldpd_conf *conf, int af, union ldpd_addr *addr); -void tnbr_del_api(struct tnbr *tnbr); -struct nbr_params *nbrp_new_api(struct ldpd_conf *cfg, +void tnbr_del_api(struct ldpd_conf *conf, struct tnbr *tnbr); +struct nbr_params *nbrp_new_api(struct ldpd_conf *conf, struct in_addr lsr_id); -void nbrp_del_api(struct nbr_params *nbrp); -struct l2vpn *l2vpn_new_api(struct ldpd_conf *cfg, const char *name); -void l2vpn_del_api(struct l2vpn *l2vpn); +void nbrp_del_api(struct ldpd_conf *conf, + struct nbr_params *nbrp); +struct l2vpn *l2vpn_new_api(struct ldpd_conf *conf, const char *name); +void l2vpn_del_api(struct ldpd_conf *conf, + struct l2vpn *l2vpn); struct l2vpn_if *l2vpn_if_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn, const char *ifname); -void l2vpn_if_del_api(struct l2vpn_if *lif); +void l2vpn_if_del_api(struct l2vpn *l2vpn, + struct l2vpn_if *lif); struct l2vpn_pw *l2vpn_pw_new_api(struct ldpd_conf *conf, struct l2vpn *l2vpn, const char *ifname); -void l2vpn_pw_del_api(struct l2vpn_pw *pw); +void l2vpn_pw_del_api(struct l2vpn *l2vpn, + struct l2vpn_pw *pw); /* socket.c */ int ldp_create_socket(int, enum socket_type); diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c index 37a3d79a28..1a60af8f41 100644 --- a/ldpd/ldpe.c +++ b/ldpd/ldpe.c @@ -111,7 +111,7 @@ ldpe(const char *user, const char *group) ldpd_process = PROC_LDP_ENGINE; LIST_INIT(&global.addr_list); - LIST_INIT(&global.adj_list); + RB_INIT(&global.adj_tree); TAILQ_INIT(&global.pending_conns); if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1) fatal("inet_pton"); @@ -209,7 +209,7 @@ ldpe_shutdown(void) LIST_REMOVE(if_addr, entry); free(if_addr); } - while ((adj = LIST_FIRST(&global.adj_list)) != NULL) + while ((adj = RB_ROOT(&global.adj_tree)) != NULL) adj_del(adj, S_SHUTDOWN); /* clean up */ @@ -414,10 +414,10 @@ ldpe_dispatch_main(struct thread *thread) fatal(NULL); memcpy(nconf, imsg.data, sizeof(struct ldpd_conf)); - LIST_INIT(&nconf->iface_list); - LIST_INIT(&nconf->tnbr_list); - LIST_INIT(&nconf->nbrp_list); - LIST_INIT(&nconf->l2vpn_list); + RB_INIT(&nconf->iface_tree); + RB_INIT(&nconf->tnbr_tree); + RB_INIT(&nconf->nbrp_tree); + RB_INIT(&nconf->l2vpn_tree); break; case IMSG_RECONF_IFACE: if ((niface = malloc(sizeof(struct iface))) == NULL) @@ -425,37 +425,37 @@ ldpe_dispatch_main(struct thread *thread) memcpy(niface, imsg.data, sizeof(struct iface)); LIST_INIT(&niface->addr_list); - LIST_INIT(&niface->ipv4.adj_list); - LIST_INIT(&niface->ipv6.adj_list); + RB_INIT(&niface->ipv4.adj_tree); + RB_INIT(&niface->ipv6.adj_tree); niface->ipv4.iface = niface; niface->ipv6.iface = niface; - LIST_INSERT_HEAD(&nconf->iface_list, niface, entry); + RB_INSERT(iface_head, &nconf->iface_tree, niface); break; case IMSG_RECONF_TNBR: if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL) fatal(NULL); memcpy(ntnbr, imsg.data, sizeof(struct tnbr)); - LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry); + RB_INSERT(tnbr_head, &nconf->tnbr_tree, ntnbr); break; case IMSG_RECONF_NBRP: if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL) fatal(NULL); memcpy(nnbrp, imsg.data, sizeof(struct nbr_params)); - LIST_INSERT_HEAD(&nconf->nbrp_list, nnbrp, entry); + RB_INSERT(nbrp_head, &nconf->nbrp_tree, nnbrp); break; case IMSG_RECONF_L2VPN: if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL) fatal(NULL); memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn)); - LIST_INIT(&nl2vpn->if_list); - LIST_INIT(&nl2vpn->pw_list); - LIST_INIT(&nl2vpn->pw_inactive_list); + RB_INIT(&nl2vpn->if_tree); + RB_INIT(&nl2vpn->pw_tree); + RB_INIT(&nl2vpn->pw_inactive_tree); - LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry); + RB_INSERT(l2vpn_head, &nconf->l2vpn_tree, nl2vpn); break; case IMSG_RECONF_L2VPN_IF: if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL) @@ -463,7 +463,7 @@ ldpe_dispatch_main(struct thread *thread) memcpy(nlif, imsg.data, sizeof(struct l2vpn_if)); nlif->l2vpn = nl2vpn; - LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry); + RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif); break; case IMSG_RECONF_L2VPN_PW: if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL) @@ -471,7 +471,7 @@ ldpe_dispatch_main(struct thread *thread) memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); npw->l2vpn = nl2vpn; - LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry); + RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw); break; case IMSG_RECONF_L2VPN_IPW: if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL) @@ -479,7 +479,7 @@ ldpe_dispatch_main(struct thread *thread) memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); npw->l2vpn = nl2vpn; - LIST_INSERT_HEAD(&nl2vpn->pw_inactive_list, npw, entry); + RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw); break; case IMSG_RECONF_END: merge_config(leconf, nconf); @@ -743,12 +743,12 @@ ldpe_remove_dynamic_tnbrs(int af) { struct tnbr *tnbr, *safe; - LIST_FOREACH_SAFE(tnbr, &leconf->tnbr_list, entry, safe) { + RB_FOREACH_SAFE(tnbr, tnbr_head, &leconf->tnbr_tree, safe) { if (tnbr->af != af) continue; tnbr->flags &= ~F_TNBR_DYNAMIC; - tnbr_check(tnbr); + tnbr_check(leconf, tnbr); } } @@ -772,7 +772,7 @@ ldpe_iface_af_ctl(struct ctl_conn *c, int af, unsigned int idx) struct iface_af *ia; struct ctl_iface *ictl; - LIST_FOREACH(iface, &leconf->iface_list, entry) { + RB_FOREACH(iface, iface_head, &leconf->iface_tree) { if (idx == 0 || idx == iface->ifindex) { ia = iface_af_get(iface, af); if (!ia->enabled) @@ -805,7 +805,7 @@ ldpe_adj_ctl(struct ctl_conn *c) imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0); - LIST_FOREACH(iface, &leconf->iface_list, entry) { + RB_FOREACH(iface, iface_head, &leconf->iface_tree) { memset(&ictl, 0, sizeof(ictl)); ictl.active_v4 = (iface->ipv4.state == IF_STA_ACTIVE); ictl.active_v6 = (iface->ipv6.state == IF_STA_ACTIVE); @@ -814,25 +814,25 @@ ldpe_adj_ctl(struct ctl_conn *c) continue; strlcpy(ictl.name, iface->name, sizeof(ictl.name)); - if (LIST_EMPTY(&iface->ipv4.adj_list) && - LIST_EMPTY(&iface->ipv6.adj_list)) + if (RB_EMPTY(&iface->ipv4.adj_tree) && + RB_EMPTY(&iface->ipv6.adj_tree)) ictl.no_adj = 1; imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_IFACE, 0, 0, -1, &ictl, sizeof(ictl)); - LIST_FOREACH(adj, &iface->ipv4.adj_list, ia_entry) { + RB_FOREACH(adj, ia_adj_head, &iface->ipv4.adj_tree) { actl = adj_to_ctl(adj); imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ, 0, 0, -1, actl, sizeof(struct ctl_adj)); } - LIST_FOREACH(adj, &iface->ipv6.adj_list, ia_entry) { + RB_FOREACH(adj, ia_adj_head, &iface->ipv6.adj_tree) { actl = adj_to_ctl(adj); imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ, 0, 0, -1, actl, sizeof(struct ctl_adj)); } } - LIST_FOREACH(tnbr, &leconf->tnbr_list, entry) { + RB_FOREACH(tnbr, tnbr_head, &leconf->tnbr_tree) { memset(&tctl, 0, sizeof(tctl)); tctl.af = tnbr->af; tctl.addr = tnbr->addr; @@ -869,7 +869,7 @@ ldpe_nbr_ctl(struct ctl_conn *c) imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl, sizeof(struct ctl_nbr)); - LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) { + RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree) { actl = adj_to_ctl(adj); imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR_DISC, 0, 0, -1, actl, sizeof(struct ctl_adj)); diff --git a/ldpd/ldpe.h b/ldpd/ldpe.h index aab1a7fd9b..81add63836 100644 --- a/ldpd/ldpe.h +++ b/ldpd/ldpe.h @@ -32,6 +32,9 @@ #define min(x,y) ((x) <= (y) ? (x) : (y)) #define max(x,y) ((x) > (y) ? (x) : (y)) +/* forward declarations */ +TAILQ_HEAD(mapping_head, mapping_entry); + struct hello_source { enum hello_type type; struct { @@ -42,9 +45,7 @@ struct hello_source { }; struct adj { - LIST_ENTRY(adj) global_entry; - LIST_ENTRY(adj) nbr_entry; - LIST_ENTRY(adj) ia_entry; + RB_ENTRY(adj) global_entry, nbr_entry, ia_entry; struct in_addr lsr_id; struct nbr *nbr; int ds_tlv; @@ -53,6 +54,9 @@ struct adj { uint16_t holdtime; union ldpd_addr trans_addr; }; +RB_PROTOTYPE(global_adj_head, adj, global_entry, adj_compare) +RB_PROTOTYPE(nbr_adj_head, adj, nbr_entry, adj_compare) +RB_PROTOTYPE(ia_adj_head, adj, ia_entry, adj_compare) struct tcp_conn { struct nbr *nbr; @@ -67,7 +71,7 @@ struct tcp_conn { struct nbr { RB_ENTRY(nbr) id_tree, addr_tree, pid_tree; struct tcp_conn *tcp; - LIST_HEAD(, adj) adj_list; /* adjacencies */ + struct nbr_adj_head adj_tree; /* adjacencies */ struct thread *ev_connect; struct thread *keepalive_timer; struct thread *keepalive_timeout; @@ -225,7 +229,7 @@ void adj_start_itimer(struct adj *); void adj_stop_itimer(struct adj *); struct tnbr *tnbr_new(int, union ldpd_addr *); struct tnbr *tnbr_find(struct ldpd_conf *, int, union ldpd_addr *); -struct tnbr *tnbr_check(struct tnbr *); +struct tnbr *tnbr_check(struct ldpd_conf *, struct tnbr *); void tnbr_update(struct tnbr *); void tnbr_update_all(int); uint16_t tnbr_get_hello_holdtime(struct tnbr *); diff --git a/ldpd/neighbor.c b/ldpd/neighbor.c index 8376a01549..d24ceb1229 100644 --- a/ldpd/neighbor.c +++ b/ldpd/neighbor.c @@ -39,10 +39,13 @@ static void nbr_start_itimeout(struct nbr *); static int nbr_idtimer(struct thread *); static int nbr_act_session_operational(struct nbr *); static void nbr_send_labelmappings(struct nbr *); +static __inline int nbr_params_compare(struct nbr_params *, + struct nbr_params *); RB_GENERATE(nbr_id_head, nbr, id_tree, nbr_id_compare) RB_GENERATE(nbr_addr_head, nbr, addr_tree, nbr_addr_compare) RB_GENERATE(nbr_pid_head, nbr, pid_tree, nbr_pid_compare) +RB_GENERATE(nbrp_head, nbr_params, entry, nbr_params_compare) struct { int state; @@ -226,7 +229,7 @@ nbr_new(struct in_addr id, int af, int ds_tlv, union ldpd_addr *addr, if ((nbr = calloc(1, sizeof(*nbr))) == NULL) fatal(__func__); - LIST_INIT(&nbr->adj_list); + RB_INIT(&nbr->adj_tree); nbr->state = NBR_STA_PRESENT; nbr->peerid = 0; nbr->af = af; @@ -241,10 +244,10 @@ nbr_new(struct in_addr id, int af, int ds_tlv, union ldpd_addr *addr, nbr->raddr_scope = scope_id; nbr->conf_seqnum = 0; - LIST_FOREACH(adj, &global.adj_list, global_entry) { + RB_FOREACH(adj, global_adj_head, &global.adj_tree) { if (adj->lsr_id.s_addr == nbr->id.s_addr) { adj->nbr = nbr; - LIST_INSERT_HEAD(&nbr->adj_list, adj, nbr_entry); + RB_INSERT(nbr_adj_head, &nbr->adj_tree, adj); } } @@ -363,7 +366,7 @@ nbr_adj_count(struct nbr *nbr, int af) struct adj *adj; int total = 0; - LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) + RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree) if (adj_get_af(adj) == af) total++; @@ -621,7 +624,7 @@ nbr_establish_connection(struct nbr *nbr) * Send an extra hello to guarantee that the remote peer has formed * an adjacency as well. */ - LIST_FOREACH(adj, &nbr->adj_list, nbr_entry) + RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree) send_hello(adj->source.type, adj->source.link.ia, adj->source.target); @@ -752,6 +755,12 @@ nbr_send_labelmappings(struct nbr *nbr) NULL, 0); } +static __inline int +nbr_params_compare(struct nbr_params *a, struct nbr_params *b) +{ + return (ntohl(a->lsr_id.s_addr) - ntohl(b->lsr_id.s_addr)); +} + struct nbr_params * nbr_params_new(struct in_addr lsr_id) { @@ -769,13 +778,9 @@ nbr_params_new(struct in_addr lsr_id) struct nbr_params * nbr_params_find(struct ldpd_conf *xconf, struct in_addr lsr_id) { - struct nbr_params *nbrp; - - LIST_FOREACH(nbrp, &xconf->nbrp_list, entry) - if (nbrp->lsr_id.s_addr == lsr_id.s_addr) - return (nbrp); - - return (NULL); + struct nbr_params nbrp; + nbrp.lsr_id = lsr_id; + return (RB_FIND(nbrp_head, &xconf->nbrp_tree, &nbrp)); } uint16_t diff --git a/ldpd/socket.c b/ldpd/socket.c index 1bb0837401..eaea9973a0 100644 --- a/ldpd/socket.c +++ b/ldpd/socket.c @@ -85,6 +85,8 @@ ldp_create_socket(int af, enum socket_type type) if (ldpd_privs.change(ZPRIVS_RAISE)) log_warn("%s: could not raise privs", __func__); if (sock_set_reuse(fd, 1) == -1) { + if (ldpd_privs.change(ZPRIVS_LOWER)) + log_warn("%s: could not lower privs", __func__); close(fd); return (-1); } diff --git a/lib/vrf.c b/lib/vrf.c index 14501c5265..ce8ffe75d5 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -381,7 +381,7 @@ vrf_bitmap_set (vrf_bitmap_t bmap, vrf_id_t vrf_id) u_char group = VRF_BITMAP_GROUP (vrf_id); u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id); - if (bmap == VRF_BITMAP_NULL) + if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN) return; if (bm->groups[group] == NULL) @@ -399,7 +399,8 @@ vrf_bitmap_unset (vrf_bitmap_t bmap, vrf_id_t vrf_id) u_char group = VRF_BITMAP_GROUP (vrf_id); u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id); - if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL) + if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN || + bm->groups[group] == NULL) return; UNSET_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)], @@ -413,7 +414,8 @@ vrf_bitmap_check (vrf_bitmap_t bmap, vrf_id_t vrf_id) u_char group = VRF_BITMAP_GROUP (vrf_id); u_char offset = VRF_BITMAP_BIT_OFFSET (vrf_id); - if (bmap == VRF_BITMAP_NULL || bm->groups[group] == NULL) + if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN || + bm->groups[group] == NULL) return 0; return CHECK_FLAG (bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP (offset)], diff --git a/lib/vty.c b/lib/vty.c index a0bcf130ef..e47ad1e59a 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -508,18 +508,6 @@ vty_write (struct vty *vty, const char *buf, size_t nbytes) buffer_put (vty->obuf, buf, nbytes); } -/* Ensure length of input buffer. Is buffer is short, double it. */ -static void -vty_ensure (struct vty *vty, int length) -{ - if (vty->max <= length) - { - vty->max *= 2; - vty->buf = XREALLOC (MTYPE_VTY, vty->buf, vty->max); - vty->error_buf = XREALLOC (MTYPE_VTY, vty->error_buf, vty->max); - } -} - /* Basic function to insert character into vty. */ static void vty_self_insert (struct vty *vty, char c) @@ -527,7 +515,9 @@ vty_self_insert (struct vty *vty, char c) int i; int length; - vty_ensure (vty, vty->length + 1); + if (vty->length + 1 > VTY_BUFSIZ) + return; + length = vty->length - vty->cp; memmove (&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length); vty->buf[vty->cp] = c; @@ -544,26 +534,29 @@ vty_self_insert (struct vty *vty, char c) static void vty_self_insert_overwrite (struct vty *vty, char c) { - vty_ensure (vty, vty->length + 1); + if (vty->cp == vty->length) + { + vty_self_insert (vty, c); + return; + } + vty->buf[vty->cp++] = c; - - if (vty->cp > vty->length) - vty->length++; - - if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE)) - return; - vty_write (vty, &c, 1); } -/* Insert a word into vty interface with overwrite mode. */ +/** + * Insert a string into vty->buf at the current cursor position. + * + * If the resultant string would be larger than VTY_BUFSIZ it is + * truncated to fit. + */ static void vty_insert_word_overwrite (struct vty *vty, char *str) { - int len = strlen (str); - vty_write (vty, str, len); - strcpy (&vty->buf[vty->cp], str); - vty->cp += len; + size_t nwrite = MIN ((int) strlen (str), VTY_BUFSIZ - vty->cp); + vty_write (vty, str, nwrite); + strncpy (&vty->buf[vty->cp], str, nwrite); + vty->cp += nwrite; vty->length = vty->cp; } @@ -2148,36 +2141,45 @@ vtysh_read (struct thread *thread) printf ("line: %.*s\n", nbytes, buf); #endif /* VTYSH_DEBUG */ - for (p = buf; p < buf+nbytes; p++) + if (vty->length + nbytes > VTY_BUFSIZ) { - vty_ensure(vty, vty->length+1); - vty->buf[vty->length++] = *p; - if (*p == '\0') + /* Clear command line buffer. */ + vty->cp = vty->length = 0; + vty_clear_buf (vty); + vty_out (vty, "%% Command is too long.%s", VTY_NEWLINE); + } + else + { + for (p = buf; p < buf+nbytes; p++) { - /* Pass this line to parser. */ - ret = vty_execute (vty); - /* Note that vty_execute clears the command buffer and resets - vty->length to 0. */ + vty->buf[vty->length++] = *p; + if (*p == '\0') + { + /* Pass this line to parser. */ + ret = vty_execute (vty); + /* Note that vty_execute clears the command buffer and resets + vty->length to 0. */ - /* Return result. */ + /* Return result. */ #ifdef VTYSH_DEBUG - printf ("result: %d\n", ret); - printf ("vtysh node: %d\n", vty->node); + printf ("result: %d\n", ret); + printf ("vtysh node: %d\n", vty->node); #endif /* VTYSH_DEBUG */ - /* hack for asynchronous "write integrated" - * - other commands in "buf" will be ditched - * - input during pending config-write is "unsupported" */ - if (ret == CMD_SUSPEND) - break; + /* hack for asynchronous "write integrated" + * - other commands in "buf" will be ditched + * - input during pending config-write is "unsupported" */ + if (ret == CMD_SUSPEND) + break; - /* warning: watchfrr hardcodes this result write */ - header[3] = ret; - buffer_put(vty->obuf, header, 4); + /* warning: watchquagga hardcodes this result write */ + header[3] = ret; + buffer_put(vty->obuf, header, 4); - if (!vty->t_write && (vtysh_flush(vty) < 0)) - /* Try to flush results; exit if a write error occurs. */ - return 0; + if (!vty->t_write && (vtysh_flush(vty) < 0)) + /* Try to flush results; exit if a write error occurs. */ + return 0; + } } } diff --git a/lib/vty.h b/lib/vty.h index 24bdcd1817..f0b833d4d8 100644 --- a/lib/vty.h +++ b/lib/vty.h @@ -26,7 +26,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "sockunion.h" #include "qobj.h" -#define VTY_BUFSIZ 512 +#define VTY_BUFSIZ 4096 #define VTY_MAXHIST 20 /* VTY struct. */ diff --git a/lib/zebra.h b/lib/zebra.h index 3a9ad15bf4..5a58cf8e6e 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -473,9 +473,28 @@ typedef enum { #define SAFI_MULTICAST 2 #define SAFI_MPLS_VPN 3 #define SAFI_RESERVED_4 4 -#define SAFI_ENCAP 7 /* per IANA */ +#define SAFI_ENCAP 5 #define SAFI_RESERVED_5 5 -#define SAFI_MAX 8 +#define SAFI_MAX 6 + +/* + * The above AFI and SAFI definitions are for internal use. The protocol + * definitions (IANA values) as for example used in BGP protocol packets + * are defined below and these will get mapped to/from the internal values + * in the appropriate places. + * The rationale is that the protocol (IANA) values may be sparse and are + * not optimal for use in data-structure sizing. + * Note: Only useful (i.e., supported) values are defined below. + */ +#define IANA_AFI_RESERVED 0 +#define IANA_AFI_IPV4 1 +#define IANA_AFI_IPV6 2 + +#define IANA_SAFI_RESERVED 0 +#define IANA_SAFI_UNICAST 1 +#define IANA_SAFI_MULTICAST 2 +#define IANA_SAFI_ENCAP 7 +#define IANA_SAFI_MPLS_VPN 128 /* Default Administrative Distance of each protocol. */ #define ZEBRA_KERNEL_DISTANCE_DEFAULT 0 @@ -509,4 +528,48 @@ typedef uint32_t route_tag_t; #define ROUTE_TAG_MAX UINT32_MAX #define ROUTE_TAG_PRI PRIu32 +static inline afi_t afi_iana2int (afi_t afi) +{ + if (afi == IANA_AFI_IPV4) + return AFI_IP; + if (afi == IANA_AFI_IPV6) + return AFI_IP6; + return AFI_MAX; +} + +static inline afi_t afi_int2iana (afi_t afi) +{ + if (afi == AFI_IP) + return IANA_AFI_IPV4; + if (afi == AFI_IP6) + return IANA_AFI_IPV6; + return IANA_AFI_RESERVED; +} + +static inline safi_t safi_iana2int (safi_t safi) +{ + if (safi == IANA_SAFI_UNICAST) + return SAFI_UNICAST; + if (safi == IANA_SAFI_MULTICAST) + return SAFI_MULTICAST; + if (safi == IANA_SAFI_MPLS_VPN) + return SAFI_MPLS_VPN; + if (safi == IANA_SAFI_ENCAP) + return SAFI_ENCAP; + return SAFI_MAX; +} + +static inline safi_t safi_int2iana (safi_t safi) +{ + if (safi == SAFI_UNICAST) + return IANA_SAFI_UNICAST; + if (safi == SAFI_MULTICAST) + return IANA_SAFI_MULTICAST; + if (safi == SAFI_MPLS_VPN) + return IANA_SAFI_MPLS_VPN; + if (safi == SAFI_ENCAP) + return IANA_SAFI_ENCAP; + return IANA_SAFI_RESERVED; +} + #endif /* _ZEBRA_H */ diff --git a/m4/ax_prog_perl_modules.m4 b/m4/ax_prog_perl_modules.m4 new file mode 100644 index 0000000000..11a326c930 --- /dev/null +++ b/m4/ax_prog_perl_modules.m4 @@ -0,0 +1,77 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_prog_perl_modules.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PROG_PERL_MODULES([MODULES], [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +# +# DESCRIPTION +# +# Checks to see if the given perl modules are available. If true the shell +# commands in ACTION-IF-TRUE are executed. If not the shell commands in +# ACTION-IF-FALSE are run. Note if $PERL is not set (for example by +# calling AC_CHECK_PROG, or AC_PATH_PROG), AC_CHECK_PROG(PERL, perl, perl) +# will be run. +# +# MODULES is a space separated list of module names. To check for a +# minimum version of a module, append the version number to the module +# name, separated by an equals sign. +# +# Example: +# +# AX_PROG_PERL_MODULES( Text::Wrap Net::LDAP=1.0.3, , +# AC_MSG_WARN(Need some Perl modules) +# +# LICENSE +# +# Copyright (c) 2009 Dean Povey +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 7 + +AU_ALIAS([AC_PROG_PERL_MODULES], [AX_PROG_PERL_MODULES]) +AC_DEFUN([AX_PROG_PERL_MODULES],[dnl + +m4_define([ax_perl_modules]) +m4_foreach([ax_perl_module], m4_split(m4_normalize([$1])), + [ + m4_append([ax_perl_modules], + [']m4_bpatsubst(ax_perl_module,=,[ ])[' ]) + ]) + +# Make sure we have perl +if test -z "$PERL"; then +AC_CHECK_PROG(PERL,perl,perl) +fi + +if test "x$PERL" != x; then + ax_perl_modules_failed=0 + for ax_perl_module in ax_perl_modules; do + AC_MSG_CHECKING(for perl module $ax_perl_module) + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL -e "use $ax_perl_module; exit" > /dev/null 2>&1 + if test $? -ne 0; then + AC_MSG_RESULT(no); + ax_perl_modules_failed=1 + else + AC_MSG_RESULT(ok); + fi + done + + # Run optional shell commands + if test "$ax_perl_modules_failed" = 0; then + : + $2 + else + : + $3 + fi +else + AC_MSG_WARN(could not find perl) +fi])dnl diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index 527d2ecfa7..f75a35fa50 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -424,12 +424,9 @@ ospf6_abr_originate_summary_to_area (struct ospf6_route *route, else { summary->path.origin.type = htons (OSPF6_LSTYPE_INTER_PREFIX); - if (route->type == OSPF6_DEST_TYPE_RANGE) - summary->path.origin.id = route->linkstate_id; - else - summary->path.origin.id = - ospf6_new_ls_id (summary->path.origin.type, - summary->path.origin.adv_router, area->lsdb); + summary->path.origin.id = + ospf6_new_ls_id (summary->path.origin.type, + summary->path.origin.adv_router, area->lsdb); } summary = ospf6_route_add (summary, summary_table); } diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index 06ff40a983..d9cf97a713 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -472,8 +472,6 @@ DEFUN (area_range, range->prefix = prefix; range->path.area_id = oa->area_id; range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC; - range->linkstate_id = - (u_int32_t) htonl(ospf6_new_range_ls_id (oa->range_table)); } if (argc > idx_type) @@ -559,8 +557,6 @@ DEFUN (no_area_range, /* purge the old aggregated summary LSA */ ospf6_abr_originate_summary(range); } - ospf6_release_range_ls_id(oa->range_table, - (u_int32_t) ntohl(range->linkstate_id)); ospf6_route_remove (range, oa->range_table); return CMD_SUCCESS; diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c index 04bea84ae5..1d4b557cd5 100644 --- a/ospf6d/ospf6_lsdb.c +++ b/ospf6d/ospf6_lsdb.c @@ -547,24 +547,6 @@ ospf6_lsdb_show (struct vty *vty, enum ospf_lsdb_show_level level, } } -/* Decide new Link State ID to originate for the range. */ -u_int32_t -ospf6_new_range_ls_id (struct ospf6_route_table *range_table) -{ - u_int32_t id; - - bf_assign_index(range_table->idspace, id); - return (id); -} - -/* Release the LS ID back to the ID pool */ -void -ospf6_release_range_ls_id (struct ospf6_route_table *range_table, - u_int32_t id) -{ - bf_release_index(range_table->idspace, id); -} - u_int32_t ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router, struct ospf6_lsdb *lsdb) diff --git a/ospf6d/ospf6_lsdb.h b/ospf6d/ospf6_lsdb.h index a8bfcae882..b21d9ee282 100644 --- a/ospf6d/ospf6_lsdb.h +++ b/ospf6d/ospf6_lsdb.h @@ -81,9 +81,6 @@ extern void ospf6_lsdb_show (struct vty *vty, extern u_int32_t ospf6_new_ls_id (u_int16_t type, u_int32_t adv_router, struct ospf6_lsdb *lsdb); -extern u_int32_t ospf6_new_range_ls_id (struct ospf6_route_table *range_table); -extern void ospf6_release_range_ls_id (struct ospf6_route_table *range_table, - u_int32_t id); extern u_int32_t ospf6_new_ls_seqnum (u_int16_t type, u_int32_t id, u_int32_t adv_router, struct ospf6_lsdb *lsdb); diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index f24ee84c8e..e9bb2493ff 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -682,7 +682,7 @@ ospf6_neighbor_show (struct vty *vty, struct ospf6_neighbor *on) "I/F", "State", VNL); */ - vty_out (vty, "%-15s %3d %11s %6s/%-12s %11s %s[%s]%s", + vty_out (vty, "%-15s %3d %11s %8s/%-12s %11s %s[%s]%s", router_id, on->priority, deadtime, ospf6_neighbor_state_str[on->state], nstate, duration, on->ospf6_if->interface->name, @@ -711,7 +711,7 @@ ospf6_neighbor_show_drchoice (struct vty *vty, struct ospf6_neighbor *on) timersub (&now, &on->last_changed, &res); timerstring (&res, duration, sizeof (duration)); - vty_out (vty, "%-15s %6s/%-11s %-15s %-15s %s[%s]%s", + vty_out (vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]%s", router_id, ospf6_neighbor_state_str[on->state], duration, drouter, bdrouter, on->ospf6_if->interface->name, ospf6_interface_state_str[on->ospf6_if->state], @@ -856,11 +856,11 @@ DEFUN (show_ipv6_ospf6_neighbor, } if (showfunc == ospf6_neighbor_show) - vty_out (vty, "%-15s %3s %11s %6s/%-12s %11s %s[%s]%s", + vty_out (vty, "%-15s %3s %11s %8s/%-12s %11s %s[%s]%s", "Neighbor ID", "Pri", "DeadTime", "State", "IfState", "Duration", "I/F", "State", VNL); else if (showfunc == ospf6_neighbor_show_drchoice) - vty_out (vty, "%-15s %6s/%-11s %-15s %-15s %s[%s]%s", + vty_out (vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]%s", "RouterID", "State", "Duration", "DR", "BDR", "I/F", "State", VNL); diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index fb24e05728..6d6c0d3640 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -1266,10 +1266,15 @@ DEFUN (no_ospf_area_vlink, /* message-digest-key */ /* Delete one key */ i++; - vl_config.crypto_key_id = strtol (argv[i]->arg, NULL, 10); - if (vl_config.crypto_key_id < 0) + if (i < argc) + { + vl_config.crypto_key_id = strtol (argv[i]->arg, NULL, 10); + if (vl_config.crypto_key_id < 0) + return CMD_WARNING; + vl_config.md5_key = NULL; + } + else return CMD_WARNING; - vl_config.md5_key = NULL; break; } diff --git a/tests/bgp_capability_test.c b/tests/bgp_capability_test.c index 7fa4be5611..3ee6a121e4 100644 --- a/tests/bgp_capability_test.c +++ b/tests/bgp_capability_test.c @@ -124,21 +124,21 @@ static struct test_segment mp_segments[] = "MP IP6/MPLS-labeled VPN", { CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x80 }, 6, SHOULD_PARSE, 0, - 1, AFI_IP6, SAFI_MPLS_LABELED_VPN, VALID_AFI, + 1, AFI_IP6, IANA_SAFI_MPLS_VPN, VALID_AFI, }, /* 7 */ { "MP5", "MP IP6/MPLS-VPN", { CAPABILITY_CODE_MP, 0x4, 0x0, 0x2, 0x0, 0x4 }, 6, SHOULD_PARSE, 0, - 1, AFI_IP6, SAFI_MPLS_VPN, VALID_AFI, + 1, AFI_IP6, IANA_SAFI_MPLS_VPN, VALID_AFI, }, /* 8 */ { "MP6", "MP IP4/MPLS-laveled VPN", { CAPABILITY_CODE_MP, 0x4, 0x0, 0x1, 0x0, 0x80 }, 6, SHOULD_PARSE, 0, - 1, AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, + 1, AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, }, /* 10 */ { "MP8", @@ -585,22 +585,26 @@ parse_test (struct peer *peer, struct test_segment *t, int type) if (!ret && t->validate_afi) { - safi_t safi = t->safi; + afi_t afi; + safi_t safi; - if (bgp_afi_safi_valid_indices (t->afi, &safi) != t->afi_valid) - failed++; - - printf ("MP: %u/%u (%u): recv %u, nego %u\n", - t->afi, t->safi, safi, - peer->afc_recv[t->afi][safi], - peer->afc_nego[t->afi][safi]); + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_iana2int (t->afi, t->safi, &afi, &safi)) + { + if (t->afi_valid == VALID_AFI) + failed++; + } + printf ("MP: %u(%u)/%u(%u): recv %u, nego %u\n", + t->afi, afi, t->safi, safi, + peer->afc_recv[afi][safi], + peer->afc_nego[afi][safi]); if (t->afi_valid == VALID_AFI) { - if (!peer->afc_recv[t->afi][safi]) + if (!peer->afc_recv[afi][safi]) failed++; - if (!peer->afc_nego[t->afi][safi]) + if (!peer->afc_nego[afi][safi]) failed++; } } diff --git a/tests/bgp_mp_attr_test.c b/tests/bgp_mp_attr_test.c index dfb8ed9f7a..f7c2af4405 100644 --- a/tests/bgp_mp_attr_test.c +++ b/tests/bgp_mp_attr_test.c @@ -317,7 +317,7 @@ static struct test_segment { { "IPv4-VPNv4", "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs", { - /* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, /* nexthop bytes */ 12, /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ 0, 0, 0, 0, @@ -338,12 +338,12 @@ static struct test_segment { }, (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)), SHOULD_PARSE, - AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, + AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, }, { "IPv4-VPNv4-bogus-plen", "IPv4/MPLS-labeled VPN MP Reach, RD, Nexthop, NLRI / bogus p'len", { - /* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, /* nexthop bytes */ 12, /* RD */ 0, 0, 1, 2, 0, 0xff, 3, 4, @@ -355,12 +355,12 @@ static struct test_segment { }, (3 + 1 + 3*4 + 1 + 3 + 4 + 1), SHOULD_ERR, - AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, + AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, }, { "IPv4-VPNv4-plen1-short", "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen short", { - /* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, /* nexthop bytes */ 12, /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ 0, 0, 0, 0, @@ -381,12 +381,12 @@ static struct test_segment { }, (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)), SHOULD_ERR, - AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, + AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, }, { "IPv4-VPNv4-plen1-long", "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, 1st plen long", { - /* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, /* nexthop bytes */ 12, /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ 0, 0, 0, 0, @@ -407,12 +407,12 @@ static struct test_segment { }, (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)), SHOULD_ERR, - AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, + AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, }, { "IPv4-VPNv4-plenn-long", "IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRIs, last plen long", { - /* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, /* nexthop bytes */ 12, /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ 0, 0, 0, 0, @@ -434,12 +434,12 @@ static struct test_segment { }, (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3) + 1), SHOULD_ERR, - AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, + AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, }, { "IPv4-VPNv4-plenn-short", "IPv4/VPNv4 MP Reach, RD, Nexthop, 2 NLRIs, last plen short", { - /* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, /* nexthop bytes */ 12, /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ 0, 0, 0, 0, @@ -460,12 +460,12 @@ static struct test_segment { }, (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)), SHOULD_ERR, - AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, + AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, }, { "IPv4-VPNv4-bogus-rd-type", "IPv4/VPNv4 MP Reach, RD, NH, 2 NLRI, unknown RD in 1st (log, but parse)", { - /* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, /* nexthop bytes */ 12, /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ 0, 0, 0, 0, @@ -486,12 +486,12 @@ static struct test_segment { }, (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3)), SHOULD_PARSE, - AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, + AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, }, { "IPv4-VPNv4-0-nlri", "IPv4/VPNv4 MP Reach, RD, Nexthop, 3 NLRI, 3rd 0 bogus", { - /* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, /* nexthop bytes */ 12, /* RD */ 0, 0, 0, 0, /* RD defined to be 0 */ 0, 0, 0, 0, @@ -513,7 +513,7 @@ static struct test_segment { }, (4 + 12 + 1 + (1+3+8+2) + (1+3+8+3) + 1), SHOULD_ERR, - AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, + AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, }, /* From bug #385 */ @@ -625,7 +625,7 @@ static struct test_segment mp_unreach_segments [] = { "IPv4-unreach-VPNv4", "IPv4/MPLS-labeled VPN MP Unreach, RD, 3 NLRIs", { - /* AFI / SAFI */ 0x0, AFI_IP, SAFI_MPLS_LABELED_VPN, + /* AFI / SAFI */ 0x0, AFI_IP, IANA_SAFI_MPLS_VPN, /* NLRI tuples */ 88 + 16, 0, 1, 2, /* tag */ /* rd, 8 octets */ @@ -641,7 +641,7 @@ static struct test_segment mp_unreach_segments [] = }, (3 + (1+3+8+2) + (1+3+8+3)), SHOULD_PARSE, - AFI_IP, SAFI_MPLS_LABELED_VPN, VALID_AFI, + AFI_IP, IANA_SAFI_MPLS_VPN, VALID_AFI, }, { NULL, NULL, {0}, 0, 0} }; @@ -656,19 +656,6 @@ handle_result (struct peer *peer, struct test_segment *t, { int oldfailed = failed; - if (!parse_ret) - { - safi_t safi = t->safi; - - if (bgp_afi_safi_valid_indices (t->afi, &safi) != t->afi_valid) - failed++; - - printf ("MP: %u/%u (%u): recv %u, nego %u\n", - t->afi, t->safi, safi, - peer->afc_recv[t->afi][safi], - peer->afc_nego[t->afi][safi]); - } - printf ("mp attr parsed?: %s\n", parse_ret ? "no" : "yes"); if (!parse_ret) printf ("nrli parsed?: %s\n", nlri_ret ? "no" : "yes"); @@ -720,9 +707,20 @@ parse_test (struct peer *peer, struct test_segment *t, int type) parse_ret = bgp_mp_reach_parse (&attr_args, &nlri); else parse_ret = bgp_mp_unreach_parse (&attr_args, &nlri); - - if (parse_ret == 0 && t->afi_valid == VALID_AFI) - assert (nlri.afi == t->afi && nlri.safi == t->safi); + if (!parse_ret) + { + afi_t pkt_afi; + safi_t pkt_safi; + + /* Convert AFI, SAFI to internal values, check. */ + if (bgp_map_afi_safi_int2iana (nlri.afi, nlri.safi, &pkt_afi, &pkt_safi)) + assert (0); + + printf ("MP: %u(%u)/%u(%u): recv %u, nego %u\n", + nlri.afi , pkt_afi, nlri.safi, pkt_safi, + peer->afc_recv[nlri.afi][nlri.safi], + peer->afc_nego[nlri.afi][nlri.safi]); + } if (!parse_ret) { @@ -731,7 +729,7 @@ parse_test (struct peer *peer, struct test_segment *t, int type) else nlri_ret = bgp_nlri_parse (peer, NULL, &nlri); } - + zlog_err("xxxxxxxxxxxxxxxx nlri ret %u", nlri_ret); handle_result (peer, t, parse_ret, nlri_ret); } diff --git a/tests/bgpd.tests/aspathtest.exp b/tests/bgpd.tests/aspathtest.exp index dfecec7801..f5f262f80a 100644 --- a/tests/bgpd.tests/aspathtest.exp +++ b/tests/bgpd.tests/aspathtest.exp @@ -3,7 +3,7 @@ set testprefix "aspathtest " set aborted 0 set color 1 -spawn "./aspathtest" +spawn sh -c "exec ./aspathtest 2>/dev/null" # proc onetest { test_name note start } { # proc headerline { line } { diff --git a/tests/bgpd.tests/ecommtest.exp b/tests/bgpd.tests/ecommtest.exp index 074952fab8..cbeb03af52 100644 --- a/tests/bgpd.tests/ecommtest.exp +++ b/tests/bgpd.tests/ecommtest.exp @@ -3,7 +3,7 @@ set testprefix "ecommtest " set aborted 0 set color 0 -spawn "./ecommtest" +spawn sh -c "exec ./ecommtest 2>/dev/null" # proc simpletest { start } { diff --git a/tests/bgpd.tests/testbgpcap.exp b/tests/bgpd.tests/testbgpcap.exp index 2572623f06..aba6906bc0 100644 --- a/tests/bgpd.tests/testbgpcap.exp +++ b/tests/bgpd.tests/testbgpcap.exp @@ -3,7 +3,7 @@ set testprefix "testbgpcap " set aborted 0 set color 1 -spawn "./testbgpcap" +spawn sh -c "exec ./testbgpcap 2>/dev/null" # proc simpletest { start } { diff --git a/tests/bgpd.tests/testbgpmpath.exp b/tests/bgpd.tests/testbgpmpath.exp index 96a51e390c..6820f636a4 100644 --- a/tests/bgpd.tests/testbgpmpath.exp +++ b/tests/bgpd.tests/testbgpmpath.exp @@ -3,7 +3,7 @@ set testprefix "testbgpmpath " set aborted 0 set color 1 -spawn "./testbgpmpath" +spawn sh -c "exec ./testbgpmpath 2>/dev/null" # proc simpletest { start } { diff --git a/tests/bgpd.tests/testbgpmpattr.exp b/tests/bgpd.tests/testbgpmpattr.exp index e6d7305a68..1abce3fc9a 100644 --- a/tests/bgpd.tests/testbgpmpattr.exp +++ b/tests/bgpd.tests/testbgpmpattr.exp @@ -3,7 +3,7 @@ set testprefix "testbgpmpattr " set aborted 0 set color 1 -spawn "./testbgpmpattr" +spawn sh -c "exec ./testbgpmpattr 2>/dev/null" # proc simpletest { start } { diff --git a/tests/libzebra.tests/tabletest.exp b/tests/libzebra.tests/tabletest.exp index 5838d4fc7c..7496994b7f 100644 --- a/tests/libzebra.tests/tabletest.exp +++ b/tests/libzebra.tests/tabletest.exp @@ -2,7 +2,7 @@ set timeout 10 set testprefix "tabletest " set aborted 0 -spawn "./tabletest" +spawn sh -c "exec ./tabletest 2>/dev/null" for {set i 0} {$i < 6} {incr i 1} { onesimple "cmp $i" "Verifying cmp"; } for {set i 0} {$i < 11} {incr i 1} { onesimple "succ $i" "Verifying successor"; } diff --git a/tests/libzebra.tests/test-timer-correctness.exp b/tests/libzebra.tests/test-timer-correctness.exp index 83531c7df8..570150cd51 100644 --- a/tests/libzebra.tests/test-timer-correctness.exp +++ b/tests/libzebra.tests/test-timer-correctness.exp @@ -2,6 +2,6 @@ set timeout 10 set testprefix "test-timer-correctness" set aborted 0 -spawn "./test-timer-correctness" +spawn sh -c "exec ./test-timer-correctness 2>/dev/null" onesimple "" "Expected output and actual output match." diff --git a/tests/libzebra.tests/testnexthopiter.exp b/tests/libzebra.tests/testnexthopiter.exp index be35a0a2b8..777b753995 100644 --- a/tests/libzebra.tests/testnexthopiter.exp +++ b/tests/libzebra.tests/testnexthopiter.exp @@ -2,7 +2,7 @@ set timeout 10 set testprefix "testnexthopiter " set aborted 0 -spawn "./testnexthopiter" +spawn sh -c "exec ./testnexthopiter 2>/dev/null" onesimple "simple" "Simple test passed." onesimple "prng" "PRNG test passed." diff --git a/tests/libzebra.tests/teststream.exp b/tests/libzebra.tests/teststream.exp index ca602e305b..c977bb4417 100644 --- a/tests/libzebra.tests/teststream.exp +++ b/tests/libzebra.tests/teststream.exp @@ -1,5 +1,5 @@ set timeout 10 -spawn "./teststream" +spawn sh -c "exec ./teststream 2>/dev/null" expect { "endp: 15, readable: 15, writeable: 1009" { } diff --git a/tools/xml2cli.pl b/tools/xml2cli.pl index 1b45e7f726..e0980421bd 100755 --- a/tools/xml2cli.pl +++ b/tools/xml2cli.pl @@ -141,6 +141,8 @@ sub generate_arguments { # argument is the name of the node if ($node{'input'} or $node{'type'} eq "select") { $arg_value = "argv[" . $argc . "]->arg"; + } elsif ($node{'optional'}) { + $arg_value = "(argc > " . $argc . " ? argv[" . $argc. "]->arg : NULL)"; } else { $arg_value = '"' . $node{'name'} . '"'; } @@ -196,7 +198,11 @@ sub generate_code { $helpstr .= $::options{$options_name}{'help'}; } else { $funcname .= $node{'name'} . " "; - $cmdstr .= $node{'name'} . " "; + if ($node{'optional'}) { + $cmdstr .= "[" . $node{'name'} . "] "; + } else { + $cmdstr .= $node{'name'} . " "; + } $helpstr .= "\n \"" . $node{'help'} . "\\n\""; } @@ -279,6 +285,7 @@ sub parse_tree { $node{'help'} = $xml_node->findvalue('./@help'); $node{'function'} = $xml_node->findvalue('./@function'); $node{'ifdef'} = $xml_node->findvalue('./@ifdef'); + $node{'optional'} = $xml_node->findvalue('./@optional'); # push node to stack push (@nodes, \%node); diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c index 903e2bbe91..122d6db6d7 100644 --- a/watchfrr/watchfrr.c +++ b/watchfrr/watchfrr.c @@ -65,149 +65,136 @@ /* Needs to be global, referenced somewhere inside libzebra. */ struct thread_master *master; -typedef enum -{ - MODE_MONITOR = 0, - MODE_GLOBAL_RESTART, - MODE_SEPARATE_RESTART, - MODE_PHASED_ZEBRA_RESTART, - MODE_PHASED_ALL_RESTART +typedef enum { + MODE_MONITOR = 0, + MODE_GLOBAL_RESTART, + MODE_SEPARATE_RESTART, + MODE_PHASED_ZEBRA_RESTART, + MODE_PHASED_ALL_RESTART } watch_mode_t; -static const char *mode_str[] = -{ - "monitor", - "global restart", - "individual daemon restart", - "phased zebra restart", - "phased global restart for any failure", +static const char *mode_str[] = { + "monitor", + "global restart", + "individual daemon restart", + "phased zebra restart", + "phased global restart for any failure", }; -typedef enum -{ - PHASE_NONE = 0, - PHASE_STOPS_PENDING, - PHASE_WAITING_DOWN, - PHASE_ZEBRA_RESTART_PENDING, - PHASE_WAITING_ZEBRA_UP +typedef enum { + PHASE_NONE = 0, + PHASE_STOPS_PENDING, + PHASE_WAITING_DOWN, + PHASE_ZEBRA_RESTART_PENDING, + PHASE_WAITING_ZEBRA_UP } restart_phase_t; -static const char *phase_str[] = -{ - "None", - "Stop jobs running", - "Waiting for other daemons to come down", - "Zebra restart job running", - "Waiting for zebra to come up", - "Start jobs running", +static const char *phase_str[] = { + "None", + "Stop jobs running", + "Waiting for other daemons to come down", + "Zebra restart job running", + "Waiting for zebra to come up", + "Start jobs running", }; #define PHASE_TIMEOUT (3*gs.restart_timeout) -struct restart_info -{ - const char *name; - const char *what; - pid_t pid; - struct timeval time; - long interval; - struct thread *t_kill; - int kills; +struct restart_info { + const char *name; + const char *what; + pid_t pid; + struct timeval time; + long interval; + struct thread *t_kill; + int kills; }; -static struct global_state -{ - watch_mode_t mode; - restart_phase_t phase; - struct thread *t_phase_hanging; - const char *vtydir; - long period; - long timeout; - long restart_timeout; - long min_restart_interval; - long max_restart_interval; - int do_ping; - struct daemon *daemons; - const char *restart_command; - const char *start_command; - const char *stop_command; - struct restart_info restart; - int unresponsive_restart; - int loglevel; - struct daemon *special; /* points to zebra when doing phased restart */ - int numdaemons; - int numpids; - int numdown; /* # of daemons that are not UP or UNRESPONSIVE */ +static struct global_state { + watch_mode_t mode; + restart_phase_t phase; + struct thread *t_phase_hanging; + const char *vtydir; + long period; + long timeout; + long restart_timeout; + long min_restart_interval; + long max_restart_interval; + int do_ping; + struct daemon *daemons; + const char *restart_command; + const char *start_command; + const char *stop_command; + struct restart_info restart; + int unresponsive_restart; + int loglevel; + struct daemon *special; /* points to zebra when doing phased restart */ + int numdaemons; + int numpids; + int numdown; /* # of daemons that are not UP or UNRESPONSIVE */ } gs = { - .mode = MODE_MONITOR, - .phase = PHASE_NONE, - .vtydir = VTYDIR, - .period = 1000*DEFAULT_PERIOD, - .timeout = DEFAULT_TIMEOUT, - .restart_timeout = DEFAULT_RESTART_TIMEOUT, - .loglevel = DEFAULT_LOGLEVEL, - .min_restart_interval = DEFAULT_MIN_RESTART, - .max_restart_interval = DEFAULT_MAX_RESTART, - .do_ping = 1, -}; +.mode = MODE_MONITOR,.phase = PHASE_NONE,.vtydir = VTYDIR,.period = + 1000 * DEFAULT_PERIOD,.timeout = + DEFAULT_TIMEOUT,.restart_timeout = + DEFAULT_RESTART_TIMEOUT,.loglevel = + DEFAULT_LOGLEVEL,.min_restart_interval = + DEFAULT_MIN_RESTART,.max_restart_interval = + DEFAULT_MAX_RESTART,.do_ping = 1,}; -typedef enum -{ - DAEMON_INIT, - DAEMON_DOWN, - DAEMON_CONNECTING, - DAEMON_UP, - DAEMON_UNRESPONSIVE +typedef enum { + DAEMON_INIT, + DAEMON_DOWN, + DAEMON_CONNECTING, + DAEMON_UP, + DAEMON_UNRESPONSIVE } daemon_state_t; #define IS_UP(DMN) \ (((DMN)->state == DAEMON_UP) || ((DMN)->state == DAEMON_UNRESPONSIVE)) -static const char *state_str[] = -{ - "Init", - "Down", - "Connecting", - "Up", - "Unresponsive", +static const char *state_str[] = { + "Init", + "Down", + "Connecting", + "Up", + "Unresponsive", }; struct daemon { - const char *name; - daemon_state_t state; - int fd; - struct timeval echo_sent; - u_int connect_tries; - struct thread *t_wakeup; - struct thread *t_read; - struct thread *t_write; - struct daemon *next; - struct restart_info restart; + const char *name; + daemon_state_t state; + int fd; + struct timeval echo_sent; + u_int connect_tries; + struct thread *t_wakeup; + struct thread *t_read; + struct thread *t_write; + struct daemon *next; + struct restart_info restart; }; -static const struct option longopts[] = -{ - { "daemon", no_argument, NULL, 'd'}, - { "statedir", required_argument, NULL, 'S'}, - { "no-echo", no_argument, NULL, 'e'}, - { "loglevel", required_argument, NULL, 'l'}, - { "interval", required_argument, NULL, 'i'}, - { "timeout", required_argument, NULL, 't'}, - { "restart-timeout", required_argument, NULL, 'T'}, - { "restart", required_argument, NULL, 'r'}, - { "start-command", required_argument, NULL, 's'}, - { "kill-command", required_argument, NULL, 'k'}, - { "restart-all", required_argument, NULL, 'R'}, - { "all-restart", no_argument, NULL, 'a'}, - { "always-all-restart", no_argument, NULL, 'A'}, - { "unresponsive-restart", no_argument, NULL, 'z'}, - { "min-restart-interval", required_argument, NULL, 'm'}, - { "max-restart-interval", required_argument, NULL, 'M'}, - { "pid-file", required_argument, NULL, 'p'}, - { "blank-string", required_argument, NULL, 'b'}, - { "help", no_argument, NULL, 'h'}, - { "version", no_argument, NULL, 'v'}, - { NULL, 0, NULL, 0 } +static const struct option longopts[] = { + {"daemon", no_argument, NULL, 'd'}, + {"statedir", required_argument, NULL, 'S'}, + {"no-echo", no_argument, NULL, 'e'}, + {"loglevel", required_argument, NULL, 'l'}, + {"interval", required_argument, NULL, 'i'}, + {"timeout", required_argument, NULL, 't'}, + {"restart-timeout", required_argument, NULL, 'T'}, + {"restart", required_argument, NULL, 'r'}, + {"start-command", required_argument, NULL, 's'}, + {"kill-command", required_argument, NULL, 'k'}, + {"restart-all", required_argument, NULL, 'R'}, + {"all-restart", no_argument, NULL, 'a'}, + {"always-all-restart", no_argument, NULL, 'A'}, + {"unresponsive-restart", no_argument, NULL, 'z'}, + {"min-restart-interval", required_argument, NULL, 'm'}, + {"max-restart-interval", required_argument, NULL, 'M'}, + {"pid-file", required_argument, NULL, 'p'}, + {"blank-string", required_argument, NULL, 'b'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {NULL, 0, NULL, 0} }; static int try_connect(struct daemon *dmn); @@ -215,14 +202,13 @@ static int wakeup_send_echo(struct thread *t_wakeup); static void try_restart(struct daemon *dmn); static void phase_check(void); -static int -usage(const char *progname, int status) +static int usage(const char *progname, int status) { - if (status != 0) - fprintf(stderr, "Try `%s --help' for more information.\n", progname); - else - { - printf("Usage : %s [OPTION...] ...\n\n\ + if (status != 0) + fprintf(stderr, "Try `%s --help' for more information.\n", + progname); + else { + printf("Usage : %s [OPTION...] ...\n\n\ Watchdog program to monitor status of frr daemons and try to restart\n\ them if they are down or unresponsive. It determines whether a daemon is\n\ up based on whether it can connect to the daemon's vty unix stream socket.\n\ @@ -266,12 +252,9 @@ the -m and -M options allow you to control the minimum delay between\n\ restart commands. The minimum restart delay is recalculated each time\n\ a restart is attempted: if the time since the last restart attempt exceeds\n\ twice the -M value, then the restart delay is set to the -m value.\n\ -Otherwise, the interval is doubled (but capped at the -M value).\n\n", - progname,mode_str[0],progname,mode_str[1],progname,mode_str[2], - progname,mode_str[3],progname,mode_str[4],progname,mode_str[2], - mode_str[3]); +Otherwise, the interval is doubled (but capped at the -M value).\n\n", progname, mode_str[0], progname, mode_str[1], progname, mode_str[2], progname, mode_str[3], progname, mode_str[4], progname, mode_str[2], mode_str[3]); - printf("Options:\n\ + printf("Options:\n\ -d, --daemon Run in daemon mode. In this mode, error messages are sent\n\ to syslog instead of stdout.\n\ -S, --statedir Set the vty socket directory (default is %s)\n\ @@ -329,221 +312,203 @@ Otherwise, the interval is doubled (but capped at the -M value).\n\n", it with a space. This is an ugly hack to circumvent problems\n\ passing command-line arguments with embedded spaces.\n\ -v, --version Print program version\n\ --h, --help Display this help and exit\n", - VTYDIR,DEFAULT_LOGLEVEL,LOG_EMERG,LOG_DEBUG,LOG_DEBUG, - DEFAULT_MIN_RESTART,DEFAULT_MAX_RESTART, - DEFAULT_PERIOD,DEFAULT_TIMEOUT,DEFAULT_RESTART_TIMEOUT, - DEFAULT_PIDFILE); - } +-h, --help Display this help and exit\n", VTYDIR, DEFAULT_LOGLEVEL, LOG_EMERG, LOG_DEBUG, LOG_DEBUG, DEFAULT_MIN_RESTART, DEFAULT_MAX_RESTART, DEFAULT_PERIOD, DEFAULT_TIMEOUT, DEFAULT_RESTART_TIMEOUT, DEFAULT_PIDFILE); + } - return status; + return status; } -static pid_t -run_background(char *shell_cmd) +static pid_t run_background(char *shell_cmd) { - pid_t child; + pid_t child; - switch (child = fork()) - { - case -1: - zlog_err("fork failed, cannot run command [%s]: %s", - shell_cmd,safe_strerror(errno)); - return -1; - case 0: - /* Child process. */ - /* Use separate process group so child processes can be killed easily. */ - if (setpgid(0,0) < 0) - zlog_warn("warning: setpgid(0,0) failed: %s",safe_strerror(errno)); - { - char shell[] = "sh"; - char dashc[] = "-c"; - char * const argv[4] = { shell, dashc, shell_cmd, NULL}; - execv("/bin/sh", argv); - zlog_err("execv(/bin/sh -c '%s') failed: %s", - shell_cmd,safe_strerror(errno)); - _exit(127); - } - default: - /* Parent process: we will reap the child later. */ - zlog_err("Forked background command [pid %d]: %s",(int)child,shell_cmd); - return child; - } + switch (child = fork()) { + case -1: + zlog_err("fork failed, cannot run command [%s]: %s", + shell_cmd, safe_strerror(errno)); + return -1; + case 0: + /* Child process. */ + /* Use separate process group so child processes can be killed easily. */ + if (setpgid(0, 0) < 0) + zlog_warn("warning: setpgid(0,0) failed: %s", + safe_strerror(errno)); + { + char shell[] = "sh"; + char dashc[] = "-c"; + char *const argv[4] = { shell, dashc, shell_cmd, NULL }; + execv("/bin/sh", argv); + zlog_err("execv(/bin/sh -c '%s') failed: %s", + shell_cmd, safe_strerror(errno)); + _exit(127); + } + default: + /* Parent process: we will reap the child later. */ + zlog_err("Forked background command [pid %d]: %s", (int)child, + shell_cmd); + return child; + } } -static struct timeval * -time_elapsed(struct timeval *result, const struct timeval *start_time) +static struct timeval *time_elapsed(struct timeval *result, + const struct timeval *start_time) { - gettimeofday(result,NULL); - result->tv_sec -= start_time->tv_sec; - result->tv_usec -= start_time->tv_usec; - while (result->tv_usec < 0) - { - result->tv_usec += 1000000L; - result->tv_sec--; - } - return result; + gettimeofday(result, NULL); + result->tv_sec -= start_time->tv_sec; + result->tv_usec -= start_time->tv_usec; + while (result->tv_usec < 0) { + result->tv_usec += 1000000L; + result->tv_sec--; + } + return result; } -static int -restart_kill(struct thread *t_kill) +static int restart_kill(struct thread *t_kill) { - struct restart_info *restart = THREAD_ARG(t_kill); - struct timeval delay; + struct restart_info *restart = THREAD_ARG(t_kill); + struct timeval delay; - time_elapsed(&delay,&restart->time); - zlog_warn("Warning: %s %s child process %d still running after " - "%ld seconds, sending signal %d", - restart->what,restart->name,(int)restart->pid, (long)delay.tv_sec, - (restart->kills ? SIGKILL : SIGTERM)); - kill(-restart->pid,(restart->kills ? SIGKILL : SIGTERM)); - restart->kills++; - restart->t_kill = thread_add_timer(master,restart_kill,restart, - gs.restart_timeout); - return 0; + time_elapsed(&delay, &restart->time); + zlog_warn("Warning: %s %s child process %d still running after " + "%ld seconds, sending signal %d", + restart->what, restart->name, (int)restart->pid, + (long)delay.tv_sec, (restart->kills ? SIGKILL : SIGTERM)); + kill(-restart->pid, (restart->kills ? SIGKILL : SIGTERM)); + restart->kills++; + restart->t_kill = thread_add_timer(master, restart_kill, restart, + gs.restart_timeout); + return 0; } -static struct restart_info * -find_child(pid_t child) +static struct restart_info *find_child(pid_t child) { - if (gs.mode == MODE_GLOBAL_RESTART) - { - if (gs.restart.pid == child) - return &gs.restart; - } - else - { - struct daemon *dmn; - for (dmn = gs.daemons; dmn; dmn = dmn->next) - { - if (dmn->restart.pid == child) - return &dmn->restart; - } - } - return NULL; + if (gs.mode == MODE_GLOBAL_RESTART) { + if (gs.restart.pid == child) + return &gs.restart; + } else { + struct daemon *dmn; + for (dmn = gs.daemons; dmn; dmn = dmn->next) { + if (dmn->restart.pid == child) + return &dmn->restart; + } + } + return NULL; } -static void -sigchild(void) +static void sigchild(void) { - pid_t child; - int status; - const char *name; - const char *what; - struct restart_info *restart; + pid_t child; + int status; + const char *name; + const char *what; + struct restart_info *restart; - switch (child = waitpid(-1,&status,WNOHANG)) - { - case -1: - zlog_err("waitpid failed: %s",safe_strerror(errno)); - return; - case 0: - zlog_warn("SIGCHLD received, but waitpid did not reap a child"); - return; - } + switch (child = waitpid(-1, &status, WNOHANG)) { + case -1: + zlog_err("waitpid failed: %s", safe_strerror(errno)); + return; + case 0: + zlog_warn("SIGCHLD received, but waitpid did not reap a child"); + return; + } - if (child == integrated_write_pid) - { - integrated_write_sigchld(status); - return; - } + if (child == integrated_write_pid) { + integrated_write_sigchld(status); + return; + } - if ((restart = find_child(child)) != NULL) - { - name = restart->name; - what = restart->what; - restart->pid = 0; - gs.numpids--; - thread_cancel(restart->t_kill); - restart->t_kill = NULL; - /* Update restart time to reflect the time the command completed. */ - gettimeofday(&restart->time,NULL); - } - else - { - zlog_err("waitpid returned status for an unknown child process %d", - (int)child); - name = "(unknown)"; - what = "background"; - } - if (WIFSTOPPED(status)) - zlog_warn("warning: %s %s process %d is stopped", - what,name,(int)child); - else if (WIFSIGNALED(status)) - zlog_warn("%s %s process %d terminated due to signal %d", - what,name,(int)child,WTERMSIG(status)); - else if (WIFEXITED(status)) - { - if (WEXITSTATUS(status) != 0) - zlog_warn("%s %s process %d exited with non-zero status %d", - what,name,(int)child,WEXITSTATUS(status)); - else - zlog_debug("%s %s process %d exited normally",what,name,(int)child); - } - else - zlog_err("cannot interpret %s %s process %d wait status 0x%x", - what,name,(int)child,status); - phase_check(); + if ((restart = find_child(child)) != NULL) { + name = restart->name; + what = restart->what; + restart->pid = 0; + gs.numpids--; + thread_cancel(restart->t_kill); + restart->t_kill = NULL; + /* Update restart time to reflect the time the command completed. */ + gettimeofday(&restart->time, NULL); + } else { + zlog_err + ("waitpid returned status for an unknown child process %d", + (int)child); + name = "(unknown)"; + what = "background"; + } + if (WIFSTOPPED(status)) + zlog_warn("warning: %s %s process %d is stopped", + what, name, (int)child); + else if (WIFSIGNALED(status)) + zlog_warn("%s %s process %d terminated due to signal %d", + what, name, (int)child, WTERMSIG(status)); + else if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != 0) + zlog_warn + ("%s %s process %d exited with non-zero status %d", + what, name, (int)child, WEXITSTATUS(status)); + else + zlog_debug("%s %s process %d exited normally", what, + name, (int)child); + } else + zlog_err("cannot interpret %s %s process %d wait status 0x%x", + what, name, (int)child, status); + phase_check(); } static int run_job(struct restart_info *restart, const char *cmdtype, const char *command, int force, int update_interval) { - struct timeval delay; + struct timeval delay; - if (gs.loglevel > LOG_DEBUG+1) - zlog_debug("attempting to %s %s",cmdtype,restart->name); + if (gs.loglevel > LOG_DEBUG + 1) + zlog_debug("attempting to %s %s", cmdtype, restart->name); - if (restart->pid) - { - if (gs.loglevel > LOG_DEBUG+1) - zlog_debug("cannot %s %s, previous pid %d still running", - cmdtype,restart->name,(int)restart->pid); - return -1; - } + if (restart->pid) { + if (gs.loglevel > LOG_DEBUG + 1) + zlog_debug + ("cannot %s %s, previous pid %d still running", + cmdtype, restart->name, (int)restart->pid); + return -1; + } - /* Note: time_elapsed test must come before the force test, since we need - to make sure that delay is initialized for use below in updating the - restart interval. */ - if ((time_elapsed(&delay,&restart->time)->tv_sec < restart->interval) && - !force) - { - if (gs.loglevel > LOG_DEBUG+1) - zlog_debug("postponing %s %s: " - "elapsed time %ld < retry interval %ld", - cmdtype,restart->name,(long)delay.tv_sec,restart->interval); - return -1; - } + /* Note: time_elapsed test must come before the force test, since we need + to make sure that delay is initialized for use below in updating the + restart interval. */ + if ((time_elapsed(&delay, &restart->time)->tv_sec < restart->interval) + && !force) { + if (gs.loglevel > LOG_DEBUG + 1) + zlog_debug("postponing %s %s: " + "elapsed time %ld < retry interval %ld", + cmdtype, restart->name, (long)delay.tv_sec, + restart->interval); + return -1; + } - gettimeofday(&restart->time,NULL); - restart->kills = 0; - { - char cmd[strlen(command)+strlen(restart->name)+1]; - snprintf(cmd,sizeof(cmd),command,restart->name); - if ((restart->pid = run_background(cmd)) > 0) - { - restart->t_kill = thread_add_timer(master,restart_kill,restart, - gs.restart_timeout); - restart->what = cmdtype; - gs.numpids++; - } - else - restart->pid = 0; - } + gettimeofday(&restart->time, NULL); + restart->kills = 0; + { + char cmd[strlen(command) + strlen(restart->name) + 1]; + snprintf(cmd, sizeof(cmd), command, restart->name); + if ((restart->pid = run_background(cmd)) > 0) { + restart->t_kill = + thread_add_timer(master, restart_kill, restart, + gs.restart_timeout); + restart->what = cmdtype; + gs.numpids++; + } else + restart->pid = 0; + } - /* Calculate the new restart interval. */ - if (update_interval) - { - if (delay.tv_sec > 2*gs.max_restart_interval) - restart->interval = gs.min_restart_interval; - else if ((restart->interval *= 2) > gs.max_restart_interval) - restart->interval = gs.max_restart_interval; - if (gs.loglevel > LOG_DEBUG+1) - zlog_debug("restart %s interval is now %ld", - restart->name,restart->interval); - } - return restart->pid; + /* Calculate the new restart interval. */ + if (update_interval) { + if (delay.tv_sec > 2 * gs.max_restart_interval) + restart->interval = gs.min_restart_interval; + else if ((restart->interval *= 2) > gs.max_restart_interval) + restart->interval = gs.max_restart_interval; + if (gs.loglevel > LOG_DEBUG + 1) + zlog_debug("restart %s interval is now %ld", + restart->name, restart->interval); + } + return restart->pid; } #define SET_READ_HANDLER(DMN) \ @@ -551,889 +516,874 @@ run_job(struct restart_info *restart, const char *cmdtype, const char *command, #define SET_WAKEUP_DOWN(DMN) \ (DMN)->t_wakeup = thread_add_timer_msec(master,wakeup_down,(DMN), \ - FUZZY(gs.period)) + FUZZY(gs.period)) #define SET_WAKEUP_UNRESPONSIVE(DMN) \ (DMN)->t_wakeup = thread_add_timer_msec(master,wakeup_unresponsive,(DMN), \ - FUZZY(gs.period)) + FUZZY(gs.period)) #define SET_WAKEUP_ECHO(DMN) \ (DMN)->t_wakeup = thread_add_timer_msec(master,wakeup_send_echo,(DMN), \ FUZZY(gs.period)) -static int -wakeup_down(struct thread *t_wakeup) +static int wakeup_down(struct thread *t_wakeup) { - struct daemon *dmn = THREAD_ARG(t_wakeup); + struct daemon *dmn = THREAD_ARG(t_wakeup); - dmn->t_wakeup = NULL; - if (try_connect(dmn) < 0) - SET_WAKEUP_DOWN(dmn); - if ((dmn->connect_tries > 1) && (dmn->state != DAEMON_UP)) - try_restart(dmn); - return 0; + dmn->t_wakeup = NULL; + if (try_connect(dmn) < 0) + SET_WAKEUP_DOWN(dmn); + if ((dmn->connect_tries > 1) && (dmn->state != DAEMON_UP)) + try_restart(dmn); + return 0; } -static int -wakeup_init(struct thread *t_wakeup) +static int wakeup_init(struct thread *t_wakeup) { - struct daemon *dmn = THREAD_ARG(t_wakeup); + struct daemon *dmn = THREAD_ARG(t_wakeup); - dmn->t_wakeup = NULL; - if (try_connect(dmn) < 0) - { - SET_WAKEUP_DOWN(dmn); - zlog_err("%s state -> down : initial connection attempt failed", - dmn->name); - dmn->state = DAEMON_DOWN; - } - return 0; -} - -static void -daemon_down(struct daemon *dmn, const char *why) -{ - if (IS_UP(dmn) || (dmn->state == DAEMON_INIT)) - zlog_err("%s state -> down : %s",dmn->name,why); - else if (gs.loglevel > LOG_DEBUG) - zlog_debug("%s still down : %s",dmn->name,why); - if (IS_UP(dmn)) - gs.numdown++; - dmn->state = DAEMON_DOWN; - if (dmn->fd >= 0) - { - close(dmn->fd); - dmn->fd = -1; - } - THREAD_OFF(dmn->t_read); - THREAD_OFF(dmn->t_write); - THREAD_OFF(dmn->t_wakeup); - if (try_connect(dmn) < 0) - SET_WAKEUP_DOWN(dmn); - phase_check(); -} - -static int -handle_read(struct thread *t_read) -{ - struct daemon *dmn = THREAD_ARG(t_read); - static const char resp[sizeof(PING_TOKEN)+4] = PING_TOKEN "\n"; - char buf[sizeof(resp)+100]; - ssize_t rc; - struct timeval delay; - - dmn->t_read = NULL; - if ((rc = read(dmn->fd,buf,sizeof(buf))) < 0) - { - char why[100]; - - if (ERRNO_IO_RETRY(errno)) - { - /* Pretend it never happened. */ - SET_READ_HANDLER(dmn); - return 0; + dmn->t_wakeup = NULL; + if (try_connect(dmn) < 0) { + SET_WAKEUP_DOWN(dmn); + zlog_err("%s state -> down : initial connection attempt failed", + dmn->name); + dmn->state = DAEMON_DOWN; } - snprintf(why,sizeof(why),"unexpected read error: %s", - safe_strerror(errno)); - daemon_down(dmn,why); - return 0; - } - if (rc == 0) - { - daemon_down(dmn,"read returned EOF"); - return 0; - } - if (!dmn->echo_sent.tv_sec) - { - char why[sizeof(buf)+100]; - snprintf(why,sizeof(why),"unexpected read returns %d bytes: %.*s", - (int)rc,(int)rc,buf); - daemon_down(dmn,why); - return 0; - } + return 0; +} - /* We are expecting an echo response: is there any chance that the - response would not be returned entirely in the first read? That - seems inconceivable... */ - if ((rc != sizeof(resp)) || memcmp(buf,resp,sizeof(resp))) - { - char why[100+sizeof(buf)]; - snprintf(why,sizeof(why),"read returned bad echo response of %d bytes " - "(expecting %u): %.*s", - (int)rc,(u_int)sizeof(resp),(int)rc,buf); - daemon_down(dmn,why); - return 0; - } - - time_elapsed(&delay,&dmn->echo_sent); - dmn->echo_sent.tv_sec = 0; - if (dmn->state == DAEMON_UNRESPONSIVE) - { - if (delay.tv_sec < gs.timeout) - { - dmn->state = DAEMON_UP; - zlog_warn("%s state -> up : echo response received after %ld.%06ld " - "seconds", dmn->name, - (long)delay.tv_sec, (long)delay.tv_usec); +static void daemon_down(struct daemon *dmn, const char *why) +{ + if (IS_UP(dmn) || (dmn->state == DAEMON_INIT)) + zlog_err("%s state -> down : %s", dmn->name, why); + else if (gs.loglevel > LOG_DEBUG) + zlog_debug("%s still down : %s", dmn->name, why); + if (IS_UP(dmn)) + gs.numdown++; + dmn->state = DAEMON_DOWN; + if (dmn->fd >= 0) { + close(dmn->fd); + dmn->fd = -1; } - else - zlog_warn("%s: slow echo response finally received after %ld.%06ld " - "seconds", dmn->name, - (long)delay.tv_sec, (long)delay.tv_usec); - } - else if (gs.loglevel > LOG_DEBUG+1) - zlog_debug("%s: echo response received after %ld.%06ld seconds", - dmn->name, (long)delay.tv_sec, (long)delay.tv_usec); + THREAD_OFF(dmn->t_read); + THREAD_OFF(dmn->t_write); + THREAD_OFF(dmn->t_wakeup); + if (try_connect(dmn) < 0) + SET_WAKEUP_DOWN(dmn); + phase_check(); +} - SET_READ_HANDLER(dmn); - if (dmn->t_wakeup) - thread_cancel(dmn->t_wakeup); - SET_WAKEUP_ECHO(dmn); +static int handle_read(struct thread *t_read) +{ + struct daemon *dmn = THREAD_ARG(t_read); + static const char resp[sizeof(PING_TOKEN) + 4] = PING_TOKEN "\n"; + char buf[sizeof(resp) + 100]; + ssize_t rc; + struct timeval delay; - return 0; + dmn->t_read = NULL; + if ((rc = read(dmn->fd, buf, sizeof(buf))) < 0) { + char why[100]; + + if (ERRNO_IO_RETRY(errno)) { + /* Pretend it never happened. */ + SET_READ_HANDLER(dmn); + return 0; + } + snprintf(why, sizeof(why), "unexpected read error: %s", + safe_strerror(errno)); + daemon_down(dmn, why); + return 0; + } + if (rc == 0) { + daemon_down(dmn, "read returned EOF"); + return 0; + } + if (!dmn->echo_sent.tv_sec) { + char why[sizeof(buf) + 100]; + snprintf(why, sizeof(why), + "unexpected read returns %d bytes: %.*s", (int)rc, + (int)rc, buf); + daemon_down(dmn, why); + return 0; + } + + /* We are expecting an echo response: is there any chance that the + response would not be returned entirely in the first read? That + seems inconceivable... */ + if ((rc != sizeof(resp)) || memcmp(buf, resp, sizeof(resp))) { + char why[100 + sizeof(buf)]; + snprintf(why, sizeof(why), + "read returned bad echo response of %d bytes " + "(expecting %u): %.*s", (int)rc, (u_int) sizeof(resp), + (int)rc, buf); + daemon_down(dmn, why); + return 0; + } + + time_elapsed(&delay, &dmn->echo_sent); + dmn->echo_sent.tv_sec = 0; + if (dmn->state == DAEMON_UNRESPONSIVE) { + if (delay.tv_sec < gs.timeout) { + dmn->state = DAEMON_UP; + zlog_warn + ("%s state -> up : echo response received after %ld.%06ld " + "seconds", dmn->name, (long)delay.tv_sec, + (long)delay.tv_usec); + } else + zlog_warn + ("%s: slow echo response finally received after %ld.%06ld " + "seconds", dmn->name, (long)delay.tv_sec, + (long)delay.tv_usec); + } else if (gs.loglevel > LOG_DEBUG + 1) + zlog_debug("%s: echo response received after %ld.%06ld seconds", + dmn->name, (long)delay.tv_sec, (long)delay.tv_usec); + + SET_READ_HANDLER(dmn); + if (dmn->t_wakeup) + thread_cancel(dmn->t_wakeup); + SET_WAKEUP_ECHO(dmn); + + return 0; } /* * Wait till we notice that all daemons are ready before * we send we are ready to systemd */ -static void -daemon_send_ready (void) +static void daemon_send_ready(void) { - static int sent = 0; - if (!sent && gs.numdown == 0) - { + static int sent = 0; + if (!sent && gs.numdown == 0) { #if defined (HAVE_CUMULUS) - FILE *fp; + FILE *fp; - fp = fopen(DAEMON_VTY_DIR "/watchfrr.started", "w"); - fclose(fp); + fp = fopen(DAEMON_VTY_DIR "/watchfrr.started", "w"); + fclose(fp); #endif - zlog_notice ("Watchfrr: Notifying Systemd we are up and running"); - systemd_send_started(master, 0); - sent = 1; - } + zlog_notice + ("Watchfrr: Notifying Systemd we are up and running"); + systemd_send_started(master, 0); + sent = 1; + } } -static void -daemon_up(struct daemon *dmn, const char *why) +static void daemon_up(struct daemon *dmn, const char *why) { - dmn->state = DAEMON_UP; - gs.numdown--; - dmn->connect_tries = 0; - zlog_notice("%s state -> up : %s",dmn->name,why); - daemon_send_ready(); - if (gs.do_ping) - SET_WAKEUP_ECHO(dmn); - phase_check(); + dmn->state = DAEMON_UP; + gs.numdown--; + dmn->connect_tries = 0; + zlog_notice("%s state -> up : %s", dmn->name, why); + daemon_send_ready(); + if (gs.do_ping) + SET_WAKEUP_ECHO(dmn); + phase_check(); } -static int -check_connect(struct thread *t_write) +static int check_connect(struct thread *t_write) { - struct daemon *dmn = THREAD_ARG(t_write); - int sockerr; - socklen_t reslen = sizeof(sockerr); + struct daemon *dmn = THREAD_ARG(t_write); + int sockerr; + socklen_t reslen = sizeof(sockerr); - dmn->t_write = NULL; - if (getsockopt(dmn->fd,SOL_SOCKET,SO_ERROR,(char *)&sockerr,&reslen) < 0) - { - zlog_warn("%s: check_connect: getsockopt failed: %s", - dmn->name,safe_strerror(errno)); - daemon_down(dmn,"getsockopt failed checking connection success"); - return 0; - } - if ((reslen == sizeof(sockerr)) && sockerr) - { - char why[100]; - snprintf(why,sizeof(why), - "getsockopt reports that connection attempt failed: %s", - safe_strerror(sockerr)); - daemon_down(dmn,why); - return 0; - } + dmn->t_write = NULL; + if (getsockopt(dmn->fd, SOL_SOCKET, SO_ERROR, (char *)&sockerr, &reslen) + < 0) { + zlog_warn("%s: check_connect: getsockopt failed: %s", dmn->name, + safe_strerror(errno)); + daemon_down(dmn, + "getsockopt failed checking connection success"); + return 0; + } + if ((reslen == sizeof(sockerr)) && sockerr) { + char why[100]; + snprintf(why, sizeof(why), + "getsockopt reports that connection attempt failed: %s", + safe_strerror(sockerr)); + daemon_down(dmn, why); + return 0; + } - daemon_up(dmn,"delayed connect succeeded"); - return 0; + daemon_up(dmn, "delayed connect succeeded"); + return 0; } -static int -wakeup_connect_hanging(struct thread *t_wakeup) +static int wakeup_connect_hanging(struct thread *t_wakeup) { - struct daemon *dmn = THREAD_ARG(t_wakeup); - char why[100]; + struct daemon *dmn = THREAD_ARG(t_wakeup); + char why[100]; - dmn->t_wakeup = NULL; - snprintf(why,sizeof(why),"connection attempt timed out after %ld seconds", - gs.timeout); - daemon_down(dmn,why); - return 0; + dmn->t_wakeup = NULL; + snprintf(why, sizeof(why), + "connection attempt timed out after %ld seconds", gs.timeout); + daemon_down(dmn, why); + return 0; } /* Making connection to protocol daemon. */ -static int -try_connect(struct daemon *dmn) +static int try_connect(struct daemon *dmn) { - int sock; - struct sockaddr_un addr; - socklen_t len; + int sock; + struct sockaddr_un addr; + socklen_t len; - if (gs.loglevel > LOG_DEBUG+1) - zlog_debug("%s: attempting to connect",dmn->name); - dmn->connect_tries++; + if (gs.loglevel > LOG_DEBUG + 1) + zlog_debug("%s: attempting to connect", dmn->name); + dmn->connect_tries++; - memset (&addr, 0, sizeof (struct sockaddr_un)); - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s.vty", - gs.vtydir,dmn->name); + memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s.vty", + gs.vtydir, dmn->name); #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN - len = addr.sun_len = SUN_LEN(&addr); + len = addr.sun_len = SUN_LEN(&addr); #else - len = sizeof (addr.sun_family) + strlen (addr.sun_path); -#endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */ + len = sizeof(addr.sun_family) + strlen(addr.sun_path); +#endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */ - /* Quick check to see if we might succeed before we go to the trouble - of creating a socket. */ - if (access(addr.sun_path, W_OK) < 0) - { - if (errno != ENOENT) - zlog_err("%s: access to socket %s denied: %s", - dmn->name,addr.sun_path,safe_strerror(errno)); - return -1; - } - - if ((sock = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) - { - zlog_err("%s(%s): cannot make socket: %s", - __func__,addr.sun_path, safe_strerror(errno)); - return -1; - } - - if (set_nonblocking(sock) < 0 || set_cloexec(sock) < 0) - { - zlog_err("%s(%s): set_nonblocking/cloexec(%d) failed", - __func__, addr.sun_path, sock); - close(sock); - return -1; - } - - if (connect (sock, (struct sockaddr *) &addr, len) < 0) - { - if ((errno != EINPROGRESS) && (errno != EWOULDBLOCK)) - { - if (gs.loglevel > LOG_DEBUG) - zlog_debug("%s(%s): connect failed: %s", - __func__,addr.sun_path, safe_strerror(errno)); - close (sock); - return -1; + /* Quick check to see if we might succeed before we go to the trouble + of creating a socket. */ + if (access(addr.sun_path, W_OK) < 0) { + if (errno != ENOENT) + zlog_err("%s: access to socket %s denied: %s", + dmn->name, addr.sun_path, + safe_strerror(errno)); + return -1; } - if (gs.loglevel > LOG_DEBUG) - zlog_debug("%s: connection in progress",dmn->name); - dmn->state = DAEMON_CONNECTING; - dmn->fd = sock; - dmn->t_write = thread_add_write(master,check_connect,dmn,dmn->fd); - dmn->t_wakeup = thread_add_timer(master,wakeup_connect_hanging,dmn, - gs.timeout); - SET_READ_HANDLER(dmn); - return 0; - } - dmn->fd = sock; - SET_READ_HANDLER(dmn); - daemon_up(dmn,"connect succeeded"); - return 1; -} - -static int -phase_hanging(struct thread *t_hanging) -{ - gs.t_phase_hanging = NULL; - zlog_err("Phase [%s] hanging for %ld seconds, aborting phased restart", - phase_str[gs.phase],PHASE_TIMEOUT); - gs.phase = PHASE_NONE; - return 0; -} - -static void -set_phase(restart_phase_t new_phase) -{ - gs.phase = new_phase; - if (gs.t_phase_hanging) - thread_cancel(gs.t_phase_hanging); - gs.t_phase_hanging = thread_add_timer(master,phase_hanging,NULL, - PHASE_TIMEOUT); -} - -static void -phase_check(void) -{ - switch (gs.phase) - { - case PHASE_NONE: - break; - case PHASE_STOPS_PENDING: - if (gs.numpids) - break; - zlog_info("Phased restart: all routing daemon stop jobs have completed."); - set_phase(PHASE_WAITING_DOWN); - /*FALLTHRU*/ - case PHASE_WAITING_DOWN: - if (gs.numdown+IS_UP(gs.special) < gs.numdaemons) - break; - zlog_info("Phased restart: all routing daemons now down."); - run_job(&gs.special->restart,"restart",gs.restart_command,1,1); - set_phase(PHASE_ZEBRA_RESTART_PENDING); - /*FALLTHRU*/ - case PHASE_ZEBRA_RESTART_PENDING: - if (gs.special->restart.pid) - break; - zlog_info("Phased restart: %s restart job completed.",gs.special->name); - set_phase(PHASE_WAITING_ZEBRA_UP); - /*FALLTHRU*/ - case PHASE_WAITING_ZEBRA_UP: - if (!IS_UP(gs.special)) - break; - zlog_info("Phased restart: %s is now up.",gs.special->name); - { - struct daemon *dmn; - for (dmn = gs.daemons; dmn; dmn = dmn->next) - { - if (dmn != gs.special) - run_job(&dmn->restart,"start",gs.start_command,1,0); - } - } - gs.phase = PHASE_NONE; - THREAD_OFF(gs.t_phase_hanging); - zlog_notice("Phased global restart has completed."); - break; - } -} - -static void -try_restart(struct daemon *dmn) -{ - switch (gs.mode) - { - case MODE_MONITOR: - return; - case MODE_GLOBAL_RESTART: - run_job(&gs.restart,"restart",gs.restart_command,0,1); - break; - case MODE_SEPARATE_RESTART: - run_job(&dmn->restart,"restart",gs.restart_command,0,1); - break; - case MODE_PHASED_ZEBRA_RESTART: - if (dmn != gs.special) - { - if ((gs.special->state == DAEMON_UP) && (gs.phase == PHASE_NONE)) - run_job(&dmn->restart,"restart",gs.restart_command,0,1); - else - zlog_debug("%s: postponing restart attempt because master %s daemon " - "not up [%s], or phased restart in progress", - dmn->name,gs.special->name,state_str[gs.special->state]); - break; - } - /*FALLTHRU*/ - case MODE_PHASED_ALL_RESTART: - if ((gs.phase != PHASE_NONE) || gs.numpids) - { - if (gs.loglevel > LOG_DEBUG+1) - zlog_debug("postponing phased global restart: restart already in " - "progress [%s], or outstanding child processes [%d]", - phase_str[gs.phase],gs.numpids); - break; - } - /* Is it too soon for a restart? */ - { - struct timeval delay; - if (time_elapsed(&delay,&gs.special->restart.time)->tv_sec < - gs.special->restart.interval) - { - if (gs.loglevel > LOG_DEBUG+1) - zlog_debug("postponing phased global restart: " - "elapsed time %ld < retry interval %ld", - (long)delay.tv_sec,gs.special->restart.interval); - break; + if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + zlog_err("%s(%s): cannot make socket: %s", + __func__, addr.sun_path, safe_strerror(errno)); + return -1; } - } - run_job(&gs.restart,"restart",gs.restart_command,0,1); - break; - default: - zlog_err("error: unknown restart mode %d",gs.mode); - break; - } + + if (set_nonblocking(sock) < 0 || set_cloexec(sock) < 0) { + zlog_err("%s(%s): set_nonblocking/cloexec(%d) failed", + __func__, addr.sun_path, sock); + close(sock); + return -1; + } + + if (connect(sock, (struct sockaddr *)&addr, len) < 0) { + if ((errno != EINPROGRESS) && (errno != EWOULDBLOCK)) { + if (gs.loglevel > LOG_DEBUG) + zlog_debug("%s(%s): connect failed: %s", + __func__, addr.sun_path, + safe_strerror(errno)); + close(sock); + return -1; + } + if (gs.loglevel > LOG_DEBUG) + zlog_debug("%s: connection in progress", dmn->name); + dmn->state = DAEMON_CONNECTING; + dmn->fd = sock; + dmn->t_write = + thread_add_write(master, check_connect, dmn, dmn->fd); + dmn->t_wakeup = + thread_add_timer(master, wakeup_connect_hanging, dmn, + gs.timeout); + SET_READ_HANDLER(dmn); + return 0; + } + + dmn->fd = sock; + SET_READ_HANDLER(dmn); + daemon_up(dmn, "connect succeeded"); + return 1; } -static int -wakeup_unresponsive(struct thread *t_wakeup) +static int phase_hanging(struct thread *t_hanging) { - struct daemon *dmn = THREAD_ARG(t_wakeup); - - dmn->t_wakeup = NULL; - if (dmn->state != DAEMON_UNRESPONSIVE) - zlog_err("%s: no longer unresponsive (now %s), " - "wakeup should have been cancelled!", - dmn->name,state_str[dmn->state]); - else - { - SET_WAKEUP_UNRESPONSIVE(dmn); - try_restart(dmn); - } - return 0; + gs.t_phase_hanging = NULL; + zlog_err("Phase [%s] hanging for %ld seconds, aborting phased restart", + phase_str[gs.phase], PHASE_TIMEOUT); + gs.phase = PHASE_NONE; + return 0; } -static int -wakeup_no_answer(struct thread *t_wakeup) +static void set_phase(restart_phase_t new_phase) { - struct daemon *dmn = THREAD_ARG(t_wakeup); - - dmn->t_wakeup = NULL; - dmn->state = DAEMON_UNRESPONSIVE; - zlog_err("%s state -> unresponsive : no response yet to ping " - "sent %ld seconds ago",dmn->name,gs.timeout); - if (gs.unresponsive_restart) - { - SET_WAKEUP_UNRESPONSIVE(dmn); - try_restart(dmn); - } - return 0; + gs.phase = new_phase; + if (gs.t_phase_hanging) + thread_cancel(gs.t_phase_hanging); + gs.t_phase_hanging = thread_add_timer(master, phase_hanging, NULL, + PHASE_TIMEOUT); } -static int -wakeup_send_echo(struct thread *t_wakeup) +static void phase_check(void) { - static const char echocmd[] = "echo " PING_TOKEN; - ssize_t rc; - struct daemon *dmn = THREAD_ARG(t_wakeup); + switch (gs.phase) { + case PHASE_NONE: + break; + case PHASE_STOPS_PENDING: + if (gs.numpids) + break; + zlog_info + ("Phased restart: all routing daemon stop jobs have completed."); + set_phase(PHASE_WAITING_DOWN); - dmn->t_wakeup = NULL; - if (((rc = write(dmn->fd,echocmd,sizeof(echocmd))) < 0) || - ((size_t)rc != sizeof(echocmd))) - { - char why[100+sizeof(echocmd)]; - snprintf(why,sizeof(why),"write '%s' returned %d instead of %u", - echocmd,(int)rc,(u_int)sizeof(echocmd)); - daemon_down(dmn,why); - } - else - { - gettimeofday(&dmn->echo_sent,NULL); - dmn->t_wakeup = thread_add_timer(master,wakeup_no_answer,dmn,gs.timeout); - } - return 0; + /*FALLTHRU*/ + case PHASE_WAITING_DOWN: + if (gs.numdown + IS_UP(gs.special) < gs.numdaemons) + break; + zlog_info("Phased restart: all routing daemons now down."); + run_job(&gs.special->restart, "restart", gs.restart_command, 1, + 1); + set_phase(PHASE_ZEBRA_RESTART_PENDING); + + /*FALLTHRU*/ + case PHASE_ZEBRA_RESTART_PENDING: + if (gs.special->restart.pid) + break; + zlog_info("Phased restart: %s restart job completed.", + gs.special->name); + set_phase(PHASE_WAITING_ZEBRA_UP); + + /*FALLTHRU*/ + case PHASE_WAITING_ZEBRA_UP: + if (!IS_UP(gs.special)) + break; + zlog_info("Phased restart: %s is now up.", gs.special->name); + { + struct daemon *dmn; + for (dmn = gs.daemons; dmn; dmn = dmn->next) { + if (dmn != gs.special) + run_job(&dmn->restart, "start", + gs.start_command, 1, 0); + } + } + gs.phase = PHASE_NONE; + THREAD_OFF(gs.t_phase_hanging); + zlog_notice("Phased global restart has completed."); + break; + } } -static void -sigint(void) +static void try_restart(struct daemon *dmn) { - zlog_notice("Terminating on signal"); - systemd_send_stopping (); - exit(0); + switch (gs.mode) { + case MODE_MONITOR: + return; + case MODE_GLOBAL_RESTART: + run_job(&gs.restart, "restart", gs.restart_command, 0, 1); + break; + case MODE_SEPARATE_RESTART: + run_job(&dmn->restart, "restart", gs.restart_command, 0, 1); + break; + case MODE_PHASED_ZEBRA_RESTART: + if (dmn != gs.special) { + if ((gs.special->state == DAEMON_UP) + && (gs.phase == PHASE_NONE)) + run_job(&dmn->restart, "restart", + gs.restart_command, 0, 1); + else + zlog_debug + ("%s: postponing restart attempt because master %s daemon " + "not up [%s], or phased restart in progress", + dmn->name, gs.special->name, + state_str[gs.special->state]); + break; + } + + /*FALLTHRU*/ + case MODE_PHASED_ALL_RESTART: + if ((gs.phase != PHASE_NONE) || gs.numpids) { + if (gs.loglevel > LOG_DEBUG + 1) + zlog_debug + ("postponing phased global restart: restart already in " + "progress [%s], or outstanding child processes [%d]", + phase_str[gs.phase], gs.numpids); + break; + } + /* Is it too soon for a restart? */ + { + struct timeval delay; + if (time_elapsed(&delay, &gs.special->restart.time)-> + tv_sec < gs.special->restart.interval) { + if (gs.loglevel > LOG_DEBUG + 1) + zlog_debug + ("postponing phased global restart: " + "elapsed time %ld < retry interval %ld", + (long)delay.tv_sec, + gs.special->restart.interval); + break; + } + } + run_job(&gs.restart, "restart", gs.restart_command, 0, 1); + break; + default: + zlog_err("error: unknown restart mode %d", gs.mode); + break; + } } -static int -valid_command(const char *cmd) +static int wakeup_unresponsive(struct thread *t_wakeup) { - char *p; + struct daemon *dmn = THREAD_ARG(t_wakeup); - return ((p = strchr(cmd,'%')) != NULL) && (*(p+1) == 's') && !strchr(p+1,'%'); + dmn->t_wakeup = NULL; + if (dmn->state != DAEMON_UNRESPONSIVE) + zlog_err("%s: no longer unresponsive (now %s), " + "wakeup should have been cancelled!", + dmn->name, state_str[dmn->state]); + else { + SET_WAKEUP_UNRESPONSIVE(dmn); + try_restart(dmn); + } + return 0; +} + +static int wakeup_no_answer(struct thread *t_wakeup) +{ + struct daemon *dmn = THREAD_ARG(t_wakeup); + + dmn->t_wakeup = NULL; + dmn->state = DAEMON_UNRESPONSIVE; + zlog_err("%s state -> unresponsive : no response yet to ping " + "sent %ld seconds ago", dmn->name, gs.timeout); + if (gs.unresponsive_restart) { + SET_WAKEUP_UNRESPONSIVE(dmn); + try_restart(dmn); + } + return 0; +} + +static int wakeup_send_echo(struct thread *t_wakeup) +{ + static const char echocmd[] = "echo " PING_TOKEN; + ssize_t rc; + struct daemon *dmn = THREAD_ARG(t_wakeup); + + dmn->t_wakeup = NULL; + if (((rc = write(dmn->fd, echocmd, sizeof(echocmd))) < 0) || + ((size_t) rc != sizeof(echocmd))) { + char why[100 + sizeof(echocmd)]; + snprintf(why, sizeof(why), + "write '%s' returned %d instead of %u", echocmd, + (int)rc, (u_int) sizeof(echocmd)); + daemon_down(dmn, why); + } else { + gettimeofday(&dmn->echo_sent, NULL); + dmn->t_wakeup = + thread_add_timer(master, wakeup_no_answer, dmn, gs.timeout); + } + return 0; +} + +static void sigint(void) +{ + zlog_notice("Terminating on signal"); + systemd_send_stopping(); + exit(0); +} + +static int valid_command(const char *cmd) +{ + char *p; + + return ((p = strchr(cmd, '%')) != NULL) && (*(p + 1) == 's') + && !strchr(p + 1, '%'); } /* This is an ugly hack to circumvent problems with passing command-line arguments that contain spaces. The fix is to use a configuration file. */ -static char * -translate_blanks(const char *cmd, const char *blankstr) +static char *translate_blanks(const char *cmd, const char *blankstr) { - char *res; - char *p; - size_t bslen = strlen(blankstr); + char *res; + char *p; + size_t bslen = strlen(blankstr); - if (!(res = strdup(cmd))) - { - perror("strdup"); - exit(1); - } - while ((p = strstr(res,blankstr)) != NULL) - { - *p = ' '; - if (bslen != 1) - memmove(p+1,p+bslen,strlen(p+bslen)+1); - } - return res; + if (!(res = strdup(cmd))) { + perror("strdup"); + exit(1); + } + while ((p = strstr(res, blankstr)) != NULL) { + *p = ' '; + if (bslen != 1) + memmove(p + 1, p + bslen, strlen(p + bslen) + 1); + } + return res; } -struct zebra_privs_t watchfrr_privs = -{ +struct zebra_privs_t watchfrr_privs = { #ifdef VTY_GROUP - .vty_group = VTY_GROUP, + .vty_group = VTY_GROUP, #endif }; -int -main(int argc, char **argv) +int main(int argc, char **argv) { - const char *progname; - int opt; - int daemon_mode = 0; - const char *pidfile = DEFAULT_PIDFILE; - const char *special = "zebra"; - const char *blankstr = NULL; - static struct quagga_signal_t my_signals[] = - { - { - .signal = SIGINT, - .handler = sigint, - }, - { - .signal = SIGTERM, - .handler = sigint, - }, - { - .signal = SIGCHLD, - .handler = sigchild, - }, - }; + const char *progname; + int opt; + int daemon_mode = 0; + const char *pidfile = DEFAULT_PIDFILE; + const char *special = "zebra"; + const char *blankstr = NULL; + static struct quagga_signal_t my_signals[] = { + { + .signal = SIGINT, + .handler = sigint, + }, + { + .signal = SIGTERM, + .handler = sigint, + }, + { + .signal = SIGCHLD, + .handler = sigchild, + }, + }; - if ((progname = strrchr (argv[0], '/')) != NULL) - progname++; - else - progname = argv[0]; - - gs.restart.name = "all"; - while ((opt = getopt_long(argc, argv, "aAb:dek:l:m:M:i:p:r:R:S:s:t:T:zvh", - longopts, 0)) != EOF) - { - switch (opt) - { - case 0: - break; - case 'a': - if ((gs.mode != MODE_MONITOR) && (gs.mode != MODE_SEPARATE_RESTART)) - { - fputs("Ambiguous operating mode selected.\n",stderr); - return usage(progname,1); - } - gs.mode = MODE_PHASED_ZEBRA_RESTART; - break; - case 'A': - if ((gs.mode != MODE_MONITOR) && (gs.mode != MODE_SEPARATE_RESTART)) - { - fputs("Ambiguous operating mode selected.\n",stderr); - return usage(progname,1); - } - gs.mode = MODE_PHASED_ALL_RESTART; - break; - case 'b': - blankstr = optarg; - break; - case 'd': - daemon_mode = 1; - break; - case 'e': - gs.do_ping = 0; - break; - case 'k': - if (!valid_command(optarg)) - { - fprintf(stderr,"Invalid kill command, must contain '%%s': %s\n", - optarg); - return usage(progname,1); - } - gs.stop_command = optarg; - break; - case 'l': - { - char garbage[3]; - if ((sscanf(optarg,"%d%1s",&gs.loglevel,garbage) != 1) || - (gs.loglevel < LOG_EMERG)) - { - fprintf(stderr,"Invalid loglevel argument: %s\n",optarg); - return usage(progname,1); - } - } - break; - case 'm': - { - char garbage[3]; - if ((sscanf(optarg,"%ld%1s", - &gs.min_restart_interval,garbage) != 1) || - (gs.min_restart_interval < 0)) - { - fprintf(stderr,"Invalid min_restart_interval argument: %s\n", - optarg); - return usage(progname,1); - } - } - break; - case 'M': - { - char garbage[3]; - if ((sscanf(optarg,"%ld%1s", - &gs.max_restart_interval,garbage) != 1) || - (gs.max_restart_interval < 0)) - { - fprintf(stderr,"Invalid max_restart_interval argument: %s\n", - optarg); - return usage(progname,1); - } - } - break; - case 'i': - { - char garbage[3]; - int period; - if ((sscanf(optarg,"%d%1s",&period,garbage) != 1) || - (gs.period < 1)) - { - fprintf(stderr,"Invalid interval argument: %s\n",optarg); - return usage(progname,1); - } - gs.period = 1000*period; - } - break; - case 'p': - pidfile = optarg; - break; - case 'r': - if ((gs.mode == MODE_GLOBAL_RESTART) || - (gs.mode == MODE_SEPARATE_RESTART)) - { - fputs("Ambiguous operating mode selected.\n",stderr); - return usage(progname,1); - } - if (!valid_command(optarg)) - { - fprintf(stderr, - "Invalid restart command, must contain '%%s': %s\n", - optarg); - return usage(progname,1); - } - gs.restart_command = optarg; - if (gs.mode == MODE_MONITOR) - gs.mode = MODE_SEPARATE_RESTART; - break; - case 'R': - if (gs.mode != MODE_MONITOR) - { - fputs("Ambiguous operating mode selected.\n",stderr); - return usage(progname,1); - } - if (strchr(optarg,'%')) - { - fprintf(stderr, - "Invalid restart-all arg, must not contain '%%s': %s\n", - optarg); - return usage(progname,1); - } - gs.restart_command = optarg; - gs.mode = MODE_GLOBAL_RESTART; - break; - case 's': - if (!valid_command(optarg)) - { - fprintf(stderr,"Invalid start command, must contain '%%s': %s\n", - optarg); - return usage(progname,1); - } - gs.start_command = optarg; - break; - case 'S': - gs.vtydir = optarg; - break; - case 't': - { - char garbage[3]; - if ((sscanf(optarg,"%ld%1s",&gs.timeout,garbage) != 1) || - (gs.timeout < 1)) - { - fprintf(stderr,"Invalid timeout argument: %s\n",optarg); - return usage(progname,1); - } - } - break; - case 'T': - { - char garbage[3]; - if ((sscanf(optarg,"%ld%1s",&gs.restart_timeout,garbage) != 1) || - (gs.restart_timeout < 1)) - { - fprintf(stderr,"Invalid restart timeout argument: %s\n",optarg); - return usage(progname,1); - } - } - break; - case 'z': - gs.unresponsive_restart = 1; - break; - case 'v': - printf ("%s version %s\n", progname, FRR_VERSION); - puts("Copyright 2004 Andrew J. Schorr"); - return 0; - case 'h': - return usage(progname,0); - default: - fputs("Invalid option.\n",stderr); - return usage(progname,1); - } - } - - if (gs.unresponsive_restart && (gs.mode == MODE_MONITOR)) - { - fputs("Option -z requires a -r or -R restart option.\n",stderr); - return usage(progname,1); - } - switch (gs.mode) - { - case MODE_MONITOR: - if (gs.restart_command || gs.start_command || gs.stop_command) - { - fprintf(stderr,"No kill/(re)start commands needed for %s mode.\n", - mode_str[gs.mode]); - return usage(progname,1); - } - break; - case MODE_GLOBAL_RESTART: - case MODE_SEPARATE_RESTART: - if (!gs.restart_command || gs.start_command || gs.stop_command) - { - fprintf(stderr,"No start/kill commands needed in [%s] mode.\n", - mode_str[gs.mode]); - return usage(progname,1); - } - break; - case MODE_PHASED_ZEBRA_RESTART: - case MODE_PHASED_ALL_RESTART: - if (!gs.restart_command || !gs.start_command || !gs.stop_command) - { - fprintf(stderr, - "Need start, kill, and restart commands in [%s] mode.\n", - mode_str[gs.mode]); - return usage(progname,1); - } - break; - } - - if (blankstr) - { - if (gs.restart_command) - gs.restart_command = translate_blanks(gs.restart_command,blankstr); - if (gs.start_command) - gs.start_command = translate_blanks(gs.start_command,blankstr); - if (gs.stop_command) - gs.stop_command = translate_blanks(gs.stop_command,blankstr); - } - - gs.restart.interval = gs.min_restart_interval; - - zprivs_init (&watchfrr_privs); - - master = thread_master_create(); - cmd_init(-1); - memory_init(); - vty_init(master); - watchfrr_vty_init(); - vty_serv_sock(NULL, 0, WATCHFRR_VTYSH_PATH); - - signal_init (master, array_size(my_signals), my_signals); - srandom(time(NULL)); - - { - int i; - struct daemon *tail = NULL; - - for (i = optind; i < argc; i++) - { - struct daemon *dmn; - - if (!(dmn = (struct daemon *)calloc(1,sizeof(*dmn)))) - { - fprintf(stderr,"calloc(1,%u) failed: %s\n", - (u_int)sizeof(*dmn), safe_strerror(errno)); - return 1; - } - dmn->name = dmn->restart.name = argv[i]; - dmn->state = DAEMON_INIT; - gs.numdaemons++; - gs.numdown++; - dmn->fd = -1; - dmn->t_wakeup = thread_add_timer_msec(master,wakeup_init,dmn, - 100+(random() % 900)); - dmn->restart.interval = gs.min_restart_interval; - if (tail) - tail->next = dmn; + if ((progname = strrchr(argv[0], '/')) != NULL) + progname++; else - gs.daemons = dmn; - tail = dmn; + progname = argv[0]; + gs.restart.name = "all"; + while ((opt = + getopt_long(argc, argv, "aAb:dek:l:m:M:i:p:r:R:S:s:t:T:zvh", + longopts, 0)) != EOF) { + switch (opt) { + case 0: + break; + case 'a': + if ((gs.mode != MODE_MONITOR) + && (gs.mode != MODE_SEPARATE_RESTART)) { + fputs("Ambiguous operating mode selected.\n", + stderr); + return usage(progname, 1); + } + gs.mode = MODE_PHASED_ZEBRA_RESTART; + break; + case 'A': + if ((gs.mode != MODE_MONITOR) + && (gs.mode != MODE_SEPARATE_RESTART)) { + fputs("Ambiguous operating mode selected.\n", + stderr); + return usage(progname, 1); + } + gs.mode = MODE_PHASED_ALL_RESTART; + break; + case 'b': + blankstr = optarg; + break; + case 'd': + daemon_mode = 1; + break; + case 'e': + gs.do_ping = 0; + break; + case 'k': + if (!valid_command(optarg)) { + fprintf(stderr, + "Invalid kill command, must contain '%%s': %s\n", + optarg); + return usage(progname, 1); + } + gs.stop_command = optarg; + break; + case 'l': + { + char garbage[3]; + if ((sscanf + (optarg, "%d%1s", &gs.loglevel, + garbage) != 1) + || (gs.loglevel < LOG_EMERG)) { + fprintf(stderr, + "Invalid loglevel argument: %s\n", + optarg); + return usage(progname, 1); + } + } + break; + case 'm': + { + char garbage[3]; + if ((sscanf(optarg, "%ld%1s", + &gs.min_restart_interval, + garbage) != 1) + || (gs.min_restart_interval < 0)) { + fprintf(stderr, + "Invalid min_restart_interval argument: %s\n", + optarg); + return usage(progname, 1); + } + } + break; + case 'M': + { + char garbage[3]; + if ((sscanf(optarg, "%ld%1s", + &gs.max_restart_interval, + garbage) != 1) + || (gs.max_restart_interval < 0)) { + fprintf(stderr, + "Invalid max_restart_interval argument: %s\n", + optarg); + return usage(progname, 1); + } + } + break; + case 'i': + { + char garbage[3]; + int period; + if ((sscanf(optarg, "%d%1s", &period, garbage) + != 1) || (gs.period < 1)) { + fprintf(stderr, + "Invalid interval argument: %s\n", + optarg); + return usage(progname, 1); + } + gs.period = 1000 * period; + } + break; + case 'p': + pidfile = optarg; + break; + case 'r': + if ((gs.mode == MODE_GLOBAL_RESTART) || + (gs.mode == MODE_SEPARATE_RESTART)) { + fputs("Ambiguous operating mode selected.\n", + stderr); + return usage(progname, 1); + } + if (!valid_command(optarg)) { + fprintf(stderr, + "Invalid restart command, must contain '%%s': %s\n", + optarg); + return usage(progname, 1); + } + gs.restart_command = optarg; + if (gs.mode == MODE_MONITOR) + gs.mode = MODE_SEPARATE_RESTART; + break; + case 'R': + if (gs.mode != MODE_MONITOR) { + fputs("Ambiguous operating mode selected.\n", + stderr); + return usage(progname, 1); + } + if (strchr(optarg, '%')) { + fprintf(stderr, + "Invalid restart-all arg, must not contain '%%s': %s\n", + optarg); + return usage(progname, 1); + } + gs.restart_command = optarg; + gs.mode = MODE_GLOBAL_RESTART; + break; + case 's': + if (!valid_command(optarg)) { + fprintf(stderr, + "Invalid start command, must contain '%%s': %s\n", + optarg); + return usage(progname, 1); + } + gs.start_command = optarg; + break; + case 'S': + gs.vtydir = optarg; + break; + case 't': + { + char garbage[3]; + if ((sscanf + (optarg, "%ld%1s", &gs.timeout, + garbage) != 1) || (gs.timeout < 1)) { + fprintf(stderr, + "Invalid timeout argument: %s\n", + optarg); + return usage(progname, 1); + } + } + break; + case 'T': + { + char garbage[3]; + if ((sscanf + (optarg, "%ld%1s", &gs.restart_timeout, + garbage) != 1) + || (gs.restart_timeout < 1)) { + fprintf(stderr, + "Invalid restart timeout argument: %s\n", + optarg); + return usage(progname, 1); + } + } + break; + case 'z': + gs.unresponsive_restart = 1; + break; + case 'v': + printf("%s version %s\n", progname, FRR_VERSION); + puts("Copyright 2004 Andrew J. Schorr"); + return 0; + case 'h': + return usage(progname, 0); + default: + fputs("Invalid option.\n", stderr); + return usage(progname, 1); + } + } + + if (gs.unresponsive_restart && (gs.mode == MODE_MONITOR)) { + fputs("Option -z requires a -r or -R restart option.\n", + stderr); + return usage(progname, 1); + } + switch (gs.mode) { + case MODE_MONITOR: + if (gs.restart_command || gs.start_command || gs.stop_command) { + fprintf(stderr, + "No kill/(re)start commands needed for %s mode.\n", + mode_str[gs.mode]); + return usage(progname, 1); + } + break; + case MODE_GLOBAL_RESTART: + case MODE_SEPARATE_RESTART: + if (!gs.restart_command || gs.start_command || gs.stop_command) { + fprintf(stderr, + "No start/kill commands needed in [%s] mode.\n", + mode_str[gs.mode]); + return usage(progname, 1); + } + break; + case MODE_PHASED_ZEBRA_RESTART: + case MODE_PHASED_ALL_RESTART: + if (!gs.restart_command || !gs.start_command + || !gs.stop_command) { + fprintf(stderr, + "Need start, kill, and restart commands in [%s] mode.\n", + mode_str[gs.mode]); + return usage(progname, 1); + } + break; + } + + if (blankstr) { + if (gs.restart_command) + gs.restart_command = + translate_blanks(gs.restart_command, blankstr); + if (gs.start_command) + gs.start_command = + translate_blanks(gs.start_command, blankstr); + if (gs.stop_command) + gs.stop_command = + translate_blanks(gs.stop_command, blankstr); + } + + gs.restart.interval = gs.min_restart_interval; + + zprivs_init(&watchfrr_privs); + + master = thread_master_create(); + cmd_init(-1); + memory_init(); + vty_init(master); + watchfrr_vty_init(); + vty_serv_sock(NULL, 0, WATCHFRR_VTYSH_PATH); + + signal_init(master, array_size(my_signals), my_signals); + srandom(time(NULL)); + + { + int i; + struct daemon *tail = NULL; + + for (i = optind; i < argc; i++) { + struct daemon *dmn; + + if (!(dmn = (struct daemon *)calloc(1, sizeof(*dmn)))) { + fprintf(stderr, "calloc(1,%u) failed: %s\n", + (u_int) sizeof(*dmn), + safe_strerror(errno)); + return 1; + } + dmn->name = dmn->restart.name = argv[i]; + dmn->state = DAEMON_INIT; + gs.numdaemons++; + gs.numdown++; + dmn->fd = -1; + dmn->t_wakeup = + thread_add_timer_msec(master, wakeup_init, dmn, + 100 + (random() % 900)); + dmn->restart.interval = gs.min_restart_interval; + if (tail) + tail->next = dmn; + else + gs.daemons = dmn; + tail = dmn; + + if (((gs.mode == MODE_PHASED_ZEBRA_RESTART) || + (gs.mode == MODE_PHASED_ALL_RESTART)) && + !strcmp(dmn->name, special)) + gs.special = dmn; + } + } + if (!gs.daemons) { + fputs("Must specify one or more daemons to monitor.\n", stderr); + return usage(progname, 1); + } if (((gs.mode == MODE_PHASED_ZEBRA_RESTART) || - (gs.mode == MODE_PHASED_ALL_RESTART)) && - !strcmp(dmn->name,special)) - gs.special = dmn; - } - } - if (!gs.daemons) - { - fputs("Must specify one or more daemons to monitor.\n",stderr); - return usage(progname,1); - } - if (((gs.mode == MODE_PHASED_ZEBRA_RESTART) || - (gs.mode == MODE_PHASED_ALL_RESTART)) && !gs.special) - { - fprintf(stderr,"In mode [%s], but cannot find master daemon %s\n", - mode_str[gs.mode],special); - return usage(progname,1); - } - - zlog_default = openzlog(progname, ZLOG_WATCHFRR, 0, - LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON); - zlog_set_level(NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED); - if (daemon_mode) - { - zlog_set_level(NULL, ZLOG_DEST_SYSLOG, MIN(gs.loglevel,LOG_DEBUG)); - if (daemon (0, 0) < 0) - { - fprintf(stderr, "Watchfrr daemon failed: %s", strerror(errno)); - exit (1); + (gs.mode == MODE_PHASED_ALL_RESTART)) && !gs.special) { + fprintf(stderr, + "In mode [%s], but cannot find master daemon %s\n", + mode_str[gs.mode], special); + return usage(progname, 1); } - } - else - zlog_set_level(NULL, ZLOG_DEST_STDOUT, MIN(gs.loglevel,LOG_DEBUG)); - /* Make sure we're not already running. */ - pid_output (pidfile); + zlog_default = openzlog(progname, ZLOG_WATCHFRR, 0, + LOG_CONS | LOG_NDELAY | LOG_PID, LOG_DAEMON); + zlog_set_level(NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED); + if (daemon_mode) { + zlog_set_level(NULL, ZLOG_DEST_SYSLOG, + MIN(gs.loglevel, LOG_DEBUG)); + if (daemon(0, 0) < 0) { + fprintf(stderr, "Watchfrr daemon failed: %s", + strerror(errno)); + exit(1); + } + } else + zlog_set_level(NULL, ZLOG_DEST_STDOUT, + MIN(gs.loglevel, LOG_DEBUG)); - /* Announce which daemons are being monitored. */ - { - struct daemon *dmn; - size_t len = 0; + /* Make sure we're not already running. */ + pid_output(pidfile); - for (dmn = gs.daemons; dmn; dmn = dmn->next) - len += strlen(dmn->name)+1; - - { - char buf[len+1]; - char *p = buf; - - for (dmn = gs.daemons; dmn; dmn = dmn->next) + /* Announce which daemons are being monitored. */ { - if (p != buf) - *p++ = ' '; - strcpy(p,dmn->name); - p += strlen(p); + struct daemon *dmn; + size_t len = 0; + + for (dmn = gs.daemons; dmn; dmn = dmn->next) + len += strlen(dmn->name) + 1; + + { + char buf[len + 1]; + char *p = buf; + + for (dmn = gs.daemons; dmn; dmn = dmn->next) { + if (p != buf) + *p++ = ' '; + strcpy(p, dmn->name); + p += strlen(p); + } + zlog_notice("%s %s watching [%s], mode [%s]", + progname, FRR_VERSION, buf, + mode_str[gs.mode]); + } } - zlog_notice("%s %s watching [%s], mode [%s]", - progname, FRR_VERSION, buf, mode_str[gs.mode]); - } - } - { - struct thread thread; + { + struct thread thread; - while (thread_fetch (master, &thread)) - thread_call (&thread); - } + while (thread_fetch(master, &thread)) + thread_call(&thread); + } - systemd_send_stopping (); - /* Not reached. */ - return 0; + systemd_send_stopping(); + /* Not reached. */ + return 0; } diff --git a/watchfrr/watchfrr.h b/watchfrr/watchfrr.h index 4a479c72e6..719ad4dfd8 100644 --- a/watchfrr/watchfrr.h +++ b/watchfrr/watchfrr.h @@ -26,4 +26,4 @@ extern void watchfrr_vty_init(void); extern pid_t integrated_write_pid; extern void integrated_write_sigchld(int status); -#endif /* FRR_WATCHFRR_H */ +#endif /* FRR_WATCHFRR_H */ diff --git a/watchfrr/watchfrr_vty.c b/watchfrr/watchfrr_vty.c index 4fffb020d7..bf3e1510a7 100644 --- a/watchfrr/watchfrr_vty.c +++ b/watchfrr/watchfrr_vty.c @@ -31,18 +31,18 @@ pid_t integrated_write_pid; static int integrated_result_fd; -DEFUN (config_write_integrated, - config_write_integrated_cmd, - "write integrated", - "Write running configuration to memory, network, or terminal\n" - "Write integrated all-daemon Frr.conf file\n") +DEFUN(config_write_integrated, + config_write_integrated_cmd, + "write integrated", + "Write running configuration to memory, network, or terminal\n" + "Write integrated all-daemon Frr.conf file\n") { pid_t child; sigset_t oldmask, sigmask; if (integrated_write_pid != -1) { vty_out(vty, "%% configuration write already in progress.%s", - VTY_NEWLINE); + VTY_NEWLINE); return CMD_WARNING; } @@ -61,20 +61,20 @@ DEFUN (config_write_integrated, child = fork(); if (child == -1) { vty_out(vty, "%% configuration write fork() failed: %s.%s", - safe_strerror(errno), VTY_NEWLINE); + safe_strerror(errno), VTY_NEWLINE); sigprocmask(SIG_SETMASK, &oldmask, NULL); return CMD_WARNING; } if (child != 0) { - /* note: the VTY won't write a command return value to vtysh; the - * session temporarily enters an intentional "hang" state. This is - * to make sure latency in vtysh doing the config write (several - * seconds is not rare to see) does not interfere with watchfrr's - * supervisor job. - * - * The fd is duplicated here so we don't need to hold a vty pointer - * (which could become invalid in the meantime). - */ + /* note: the VTY won't write a command return value to vtysh; the + * session temporarily enters an intentional "hang" state. This is + * to make sure latency in vtysh doing the config write (several + * seconds is not rare to see) does not interfere with watchfrr's + * supervisor job. + * + * The fd is duplicated here so we don't need to hold a vty pointer + * (which could become invalid in the meantime). + */ integrated_write_pid = child; integrated_result_fd = dup(vty->wfd); sigprocmask(SIG_SETMASK, &oldmask, NULL); @@ -93,7 +93,7 @@ DEFUN (config_write_integrated, /* unbuffered write; we just messed with stdout... */ char msg[512]; snprintf(msg, sizeof(msg), "error executing %s: %s\n", - VTYSH_BIN_PATH, safe_strerror(errno)); + VTYSH_BIN_PATH, safe_strerror(errno)); write(1, msg, strlen(msg)); exit(1); } @@ -104,11 +104,11 @@ void integrated_write_sigchld(int status) if (WIFEXITED(status)) { zlog_info("configuration write completed with exit code %d", - WEXITSTATUS(status)); + WEXITSTATUS(status)); reply[3] = WEXITSTATUS(status); } else if (WIFSIGNALED(status)) { zlog_warn("configuration write terminated by signal %d", - WTERMSIG(status)); + WTERMSIG(status)); } else { zlog_warn("configuration write terminated"); } diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 27ef5f934d..3138e7c867 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -104,7 +104,7 @@ zebra_static_ipv4 (struct vty *vty, safi_t safi, int add_cmd, /* tag */ if (tag_str) - tag = atol(tag_str); + VTY_GET_INTEGER_RANGE("tag", tag, tag_str, 0, 4294967295); /* VRF id */ zvrf = zebra_vrf_lookup_by_name (vrf_id_str); @@ -1340,12 +1340,12 @@ DEFUN (show_ip_route_tag, if (strmatch(argv[idx_vrf]->text, "vrf")) { VRF_GET_ID (vrf_id, argv[idx_name]->arg); - tag = atol(argv[idx_tag]->arg); + VTY_GET_INTEGER_RANGE("tag", tag, argv[idx_tag]->arg, 0, 4294967295); } else { idx_tag -= 2; - tag = atol(argv[idx_tag]->arg); + VTY_GET_INTEGER_RANGE("tag", tag, argv[idx_tag]->arg, 0, 4294967295); } table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, vrf_id); @@ -1918,7 +1918,7 @@ DEFUN (show_ip_route_vrf_all_tag, route_tag_t tag = 0; if (argv[idx_number]->arg) - tag = atol(argv[idx_number]->arg); + VTY_GET_INTEGER_RANGE("tag", tag, argv[idx_number]->arg, 0, 4294967295); RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { @@ -2356,7 +2356,7 @@ static_ipv6_func (struct vty *vty, int add_cmd, const char *dest_str, /* tag */ if (tag_str) - tag = atol(tag_str); + VTY_GET_INTEGER_RANGE("tag", tag, tag_str, 0, 4294967295); /* When gateway is valid IPv6 addrees, then gate is treated as nexthop address other case gate is treated as interface name. */ @@ -2866,12 +2866,12 @@ DEFUN (show_ipv6_route_tag, if (strmatch(argv[idx_vrf]->text, "vrf")) { VRF_GET_ID (vrf_id, argv[idx_name]->arg); - tag = atol(argv[idx_tag]->arg); + VTY_GET_INTEGER_RANGE("tag", tag, argv[idx_tag]->arg, 0, 4294967295); } else { idx_tag -= 2; - tag = atol(argv[idx_tag]->arg); + VTY_GET_INTEGER_RANGE("tag", tag, argv[idx_tag]->arg, 0, 4294967295); } table = zebra_vrf_table (AFI_IP6, SAFI_UNICAST, vrf_id); @@ -3252,7 +3252,7 @@ DEFUN (show_ipv6_route_vrf_all_tag, route_tag_t tag = 0; if (argv[idx_number]->arg) - tag = atol(argv[idx_number]->arg); + VTY_GET_INTEGER_RANGE("tag", tag, argv[idx_number]->arg, 0, 4294967295); RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {