From d5b8c21628320ca1d55e9cb687f2a9d941133068 Mon Sep 17 00:00:00 2001 From: kssoman Date: Fri, 17 Aug 2018 08:47:48 -0700 Subject: [PATCH 01/66] zebra : Zebra does not properly track which route-maps are changed (#2493) * Check for the modified routemap in zebra_route_map_process_update_cb() * Added zebra_rib_table_rm_update() for RIB routemap processing * Added zebra_nht_rm_update() for NHT routemap processing Signed-off-by: kssoman --- zebra/redistribute.c | 7 ++-- zebra/redistribute.h | 3 +- zebra/rib.h | 2 + zebra/zebra_rib.c | 13 ++++-- zebra/zebra_routemap.c | 95 +++++++++++++++++++++++++++++++++++++++--- 5 files changed, 105 insertions(+), 15 deletions(-) diff --git a/zebra/redistribute.c b/zebra/redistribute.c index e3101fbe72..640d58e17e 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -715,7 +715,7 @@ int zebra_import_table_config(struct vty *vty) return write; } -void zebra_import_table_rm_update() +void zebra_import_table_rm_update(const char *rmap) { afi_t afi; int i; @@ -730,9 +730,8 @@ void zebra_import_table_rm_update() continue; rmap_name = zebra_get_import_table_route_map(afi, i); - if (!rmap_name) - return; - + if ((!rmap_name) || (strcmp(rmap_name, rmap) != 0)) + continue; table = zebra_vrf_other_route_table(afi, i, VRF_DEFAULT); for (rn = route_top(table); rn; rn = route_next(rn)) { diff --git a/zebra/redistribute.h b/zebra/redistribute.h index a0fbd13cf9..f67480da9c 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -71,6 +71,5 @@ extern int is_zebra_import_table_enabled(afi_t, uint32_t table_id); extern int zebra_import_table_config(struct vty *); -extern void zebra_import_table_rm_update(void); - +extern void zebra_import_table_rm_update(const char *rmap); #endif /* _ZEBRA_REDISTRIBUTE_H */ diff --git a/zebra/rib.h b/zebra/rib.h index a37b2bf221..f821c6edb4 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -325,6 +325,8 @@ extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id); extern void rib_update(vrf_id_t vrf_id, rib_update_event_t event); +extern void rib_update_table(struct route_table *table, + rib_update_event_t event); extern void rib_sweep_route(void); extern void rib_sweep_table(struct route_table *table); extern void rib_close_table(struct route_table *table); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 69f6ff9de7..46042b793a 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -2637,8 +2637,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, } /* Schedule routes of a particular table (address-family) based on event. */ -static void rib_update_table(struct route_table *table, - rib_update_event_t event) +void rib_update_table(struct route_table *table, rib_update_event_t event) { struct route_node *rn; struct route_entry *re, *next; @@ -2718,12 +2717,18 @@ void rib_update(vrf_id_t vrf_id, rib_update_event_t event) /* Process routes of interested address-families. */ table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id); - if (table) + if (table) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s : AFI_IP event %d", __func__, event); rib_update_table(table, event); + } table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id); - if (table) + if (table) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s : AFI_IP6 event %d", __func__, event); rib_update_table(table, event); + } } /* Delete self installed routes after zebra is relaunched. */ diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index fc17ee3491..2ee4b40465 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -1281,11 +1281,101 @@ static struct route_map_rule_cmd route_set_src_cmd = { "src", route_set_src, route_set_src_compile, route_set_src_free, }; +/* The function checks if the changed routemap specified by parameter rmap + * matches the configured protocol routemaps in proto_rm table. If there is + * a match then rib_update_table() to process the routes. + */ +static void zebra_rib_table_rm_update(const char *rmap) +{ + int i = 0; + struct route_table *table; + char *rmap_name; + char afi_ip = 0; + char afi_ipv6 = 0; + + for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) { + /* Check for ip routemap table */ + rmap_name = proto_rm[AFI_IP][i]; + if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s : AFI_IP rmap %s, route type %s", + __func__, rmap, zebra_route_string(i)); + /* There is single rib table for all protocols */ + if (afi_ip == 0) { + table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, + VRF_DEFAULT); + if (table) { + afi_ip = 1; + rib_update_table(table, + RIB_UPDATE_RMAP_CHANGE); + } + } + } + + /* Check for ipv6 routemap table */ + rmap_name = proto_rm[AFI_IP6][i]; + if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s : AFI_IP6 rmap %s,route type %s", + __func__, rmap, zebra_route_string(i)); + if (afi_ipv6 == 0) { + table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, + VRF_DEFAULT); + if (table) { + afi_ipv6 = 1; + rib_update_table(table, + RIB_UPDATE_RMAP_CHANGE); + } + } + } + } +} + +/* The function checks if the changed routemap specified by parameter rmap + * matches the configured protocol routemaps in nht_rm table. If there is + * a match then zebra_evaluate_rnh() to process the nexthops. + */ +static void zebra_nht_rm_update(const char *rmap) +{ + int i = 0; + char *rmap_name; + char afi_ip = 0; + char afi_ipv6 = 0; + + for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) { + rmap_name = nht_rm[AFI_IP][i]; + if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s : AFI_IP rmap %s route type %s", + __func__, rmap, zebra_route_string(i)); + if (afi_ip == 0) { + afi_ip = 1; + zebra_evaluate_rnh(0, AF_INET, 1, + RNH_NEXTHOP_TYPE, NULL); + } + } + rmap_name = nht_rm[AFI_IP6][i]; + if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s : AFI_IP6 rmap %s route type %s", + __func__, rmap, zebra_route_string(i)); + if (afi_ipv6 == 0) { + afi_ipv6 = 1; + zebra_evaluate_rnh(0, AF_INET6, 1, + RNH_NEXTHOP_TYPE, NULL); + } + } + } +} + static void zebra_route_map_process_update_cb(char *rmap_name) { if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("Event handler for route-map: %s", rmap_name); + zebra_import_table_rm_update(rmap_name); + zebra_rib_table_rm_update(rmap_name); + zebra_nht_rm_update(rmap_name); } static int zebra_route_map_update_timer(struct thread *thread) @@ -1307,11 +1397,6 @@ static int zebra_route_map_update_timer(struct thread *thread) * 1) VRF Aware * 2) Route-map aware */ - zebra_import_table_rm_update(); - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - return (0); } From 01ba4505823d38acb4ba27487efbba2965f0a69a Mon Sep 17 00:00:00 2001 From: kssoman Date: Fri, 17 Aug 2018 08:53:28 -0700 Subject: [PATCH 02/66] zebra : routemap "match ipv6 address prefix list" does not work * Added code for "match ipv6 address prefix list" command * Added common function route_match_address_prefix_list() to process routemap for AFI_IP and AFI_IP6 address family Signed-off-by: kssoman --- zebra/zebra_routemap.c | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 2ee4b40465..7a6bc6684d 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -1033,13 +1033,13 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = { /* `match ip address prefix-list PREFIX_LIST' */ static route_map_result_t -route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_address_prefix_list(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object, afi_t afi) { struct prefix_list *plist; if (type == RMAP_ZEBRA) { - plist = prefix_list_lookup(AFI_IP, (char *)rule); + plist = prefix_list_lookup(afi, (char *)rule); if (plist == NULL) return RMAP_NOMATCH; @@ -1050,21 +1050,41 @@ route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, return RMAP_NOMATCH; } -static void *route_match_ip_address_prefix_list_compile(const char *arg) +static route_map_result_t +route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) +{ + return (route_match_address_prefix_list(rule, prefix, type, object, + AFI_IP)); +} + +static void *route_match_address_prefix_list_compile(const char *arg) { return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); } -static void route_match_ip_address_prefix_list_free(void *rule) +static void route_match_address_prefix_list_free(void *rule) { XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = { "ip address prefix-list", route_match_ip_address_prefix_list, - route_match_ip_address_prefix_list_compile, - route_match_ip_address_prefix_list_free}; + route_match_address_prefix_list_compile, + route_match_address_prefix_list_free}; +static route_map_result_t +route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) +{ + return (route_match_address_prefix_list(rule, prefix, type, object, + AFI_IP6)); +} + +static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = { + "ipv6 address prefix-list", route_match_ipv6_address_prefix_list, + route_match_address_prefix_list_compile, + route_match_address_prefix_list_free}; /* `match ip address prefix-len PREFIXLEN' */ @@ -1640,12 +1660,19 @@ void zebra_route_map_init() route_map_match_tag_hook(generic_match_add); route_map_no_match_tag_hook(generic_match_delete); + route_map_match_ipv6_address_hook(generic_match_add); + route_map_no_match_ipv6_address_hook(generic_match_delete); + + route_map_match_ipv6_address_prefix_list_hook(generic_match_add); + route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete); + route_map_install_match(&route_match_tag_cmd); route_map_install_match(&route_match_interface_cmd); route_map_install_match(&route_match_ip_next_hop_cmd); route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd); route_map_install_match(&route_match_ip_address_cmd); route_map_install_match(&route_match_ip_address_prefix_list_cmd); + route_map_install_match(&route_match_ipv6_address_prefix_list_cmd); route_map_install_match(&route_match_ip_address_prefix_len_cmd); route_map_install_match(&route_match_ipv6_address_prefix_len_cmd); route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd); From b46dfd2022198b3f72ad033a7f943027d0c4455d Mon Sep 17 00:00:00 2001 From: Don Slice Date: Fri, 17 Aug 2018 19:22:55 +0000 Subject: [PATCH 03/66] bgpd: add json output to bgp route-leak show command Ticket: CM-20259 Signed-off-by: Don Slice --- bgpd/bgp_vty.c | 205 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 144 insertions(+), 61 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index fda458cb84..bfcd280975 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -10995,7 +10995,7 @@ DEFUN (show_ip_bgp_attr_info, } static int bgp_show_route_leak_vty(struct vty *vty, const char *name, - afi_t afi, safi_t safi) + afi_t afi, safi_t safi, uint8_t use_json) { struct bgp *bgp; struct listnode *node; @@ -11004,64 +11004,145 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, char *ecom_str; vpn_policy_direction_t dir; - if (name) { - bgp = bgp_lookup_by_name(name); + if (use_json) { + json_object *json = NULL; + json_object *json_import_vrfs = NULL; + json_object *json_export_vrfs = NULL; + + json = json_object_new_object(); + json_import_vrfs = json_object_new_array(); + json_export_vrfs = json_object_new_array(); + + /* Provide context for the block */ + json_object_string_add(json, "vrf", name ? name : "default"); + json_object_string_add(json, "afiSafi", + afi_safi_print(afi, safi)); + + bgp = name ? bgp_lookup_by_name(name) : bgp_get_default(); + + if (!bgp) { + json_object_boolean_true_add(json, + "bgpNoSuchInstance"); + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, + JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + + return CMD_WARNING; + } + + if (!CHECK_FLAG(bgp->af_flags[afi][safi], + BGP_CONFIG_VRF_TO_VRF_IMPORT)) { + json_object_string_add(json, "importFromVrfs", "none"); + json_object_string_add(json, "importRts", "none"); + } else { + for (ALL_LIST_ELEMENTS_RO( + bgp->vpn_policy[afi].import_vrf, + node, vname)) + json_object_array_add(json_import_vrfs, + json_object_new_string(vname)); + + dir = BGP_VPN_POLICY_DIR_FROMVPN; + ecom_str = ecommunity_ecom2str( + bgp->vpn_policy[afi].rtlist[dir], + ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + json_object_object_add(json, "importFromVrfs", + json_import_vrfs); + json_object_string_add(json, "importRts", ecom_str); + + XFREE(MTYPE_ECOMMUNITY_STR, ecom_str); + } + + if (!CHECK_FLAG(bgp->af_flags[afi][safi], + BGP_CONFIG_VRF_TO_VRF_EXPORT)) { + json_object_string_add(json, "exportToVrfs", "none"); + json_object_string_add(json, "routeDistinguisher", + "none"); + json_object_string_add(json, "exportRts", "none"); + } else { + for (ALL_LIST_ELEMENTS_RO( + bgp->vpn_policy[afi].export_vrf, + node, vname)) + json_object_array_add(json_export_vrfs, + json_object_new_string(vname)); + json_object_object_add(json, "exportToVrfs", + json_export_vrfs); + json_object_string_add(json, "routeDistinguisher", + prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, + buf1, RD_ADDRSTRLEN)); + + dir = BGP_VPN_POLICY_DIR_TOVPN; + ecom_str = ecommunity_ecom2str( + bgp->vpn_policy[afi].rtlist[dir], + ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + json_object_string_add(json, "exportRts", ecom_str); + + XFREE(MTYPE_ECOMMUNITY_STR, ecom_str); + } + + vty_out(vty, "%s\n", + json_object_to_json_string_ext(json, + JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + + } else { + bgp = name ? bgp_lookup_by_name(name) : bgp_get_default(); + if (!bgp) { vty_out(vty, "%% No such BGP instance exist\n"); return CMD_WARNING; } - } else { - bgp = bgp_get_default(); - if (!bgp) { + + if (!CHECK_FLAG(bgp->af_flags[afi][safi], + BGP_CONFIG_VRF_TO_VRF_IMPORT)) vty_out(vty, - "%% Default BGP instance does not exist\n"); - return CMD_WARNING; - } - } + "This VRF is not importing %s routes from any other VRF\n", + afi_safi_print(afi, safi)); + else { + vty_out(vty, + "This VRF is importing %s routes from the following VRFs:\n", + afi_safi_print(afi, safi)); - if (!CHECK_FLAG(bgp->af_flags[afi][safi], - BGP_CONFIG_VRF_TO_VRF_IMPORT)) { - vty_out(vty, - "This VRF is not importing %s routes from any other VRF\n", - afi_safi_print(afi, safi)); - } else { - vty_out(vty, - "This VRF is importing %s routes from the following VRFs:\n", - afi_safi_print(afi, safi)); - for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].import_vrf, node, - vname)) { - vty_out(vty, " %s\n", vname); - } - dir = BGP_VPN_POLICY_DIR_FROMVPN; - ecom_str = ecommunity_ecom2str( - bgp->vpn_policy[afi].rtlist[dir], - ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - vty_out(vty, "Import RT(s): %s\n", ecom_str); - XFREE(MTYPE_ECOMMUNITY_STR, ecom_str); - } + for (ALL_LIST_ELEMENTS_RO( + bgp->vpn_policy[afi].import_vrf, + node, vname)) + vty_out(vty, " %s\n", vname); - if (!CHECK_FLAG(bgp->af_flags[afi][safi], - BGP_CONFIG_VRF_TO_VRF_EXPORT)) { - vty_out(vty, - "This VRF is not exporting %s routes to any other VRF\n", - afi_safi_print(afi, safi)); - } else { - vty_out(vty, - "This VRF is exporting %s routes to the following VRFs:\n", - afi_safi_print(afi, safi)); - for (ALL_LIST_ELEMENTS_RO(bgp->vpn_policy[afi].export_vrf, node, - vname)) { - vty_out(vty, " %s\n", vname); + dir = BGP_VPN_POLICY_DIR_FROMVPN; + ecom_str = ecommunity_ecom2str( + bgp->vpn_policy[afi].rtlist[dir], + ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + vty_out(vty, "Import RT(s): %s\n", ecom_str); + + XFREE(MTYPE_ECOMMUNITY_STR, ecom_str); + } + + if (!CHECK_FLAG(bgp->af_flags[afi][safi], + BGP_CONFIG_VRF_TO_VRF_EXPORT)) + vty_out(vty, + "This VRF is not exporting %s routes to any other VRF\n", + afi_safi_print(afi, safi)); + else { + vty_out(vty, + "This VRF is exporting %s routes to the ollowing VRFs:\n", + afi_safi_print(afi, safi)); + + for (ALL_LIST_ELEMENTS_RO( + bgp->vpn_policy[afi].export_vrf, + node, vname)) + vty_out(vty, " %s\n", vname); + + vty_out(vty, "RD: %s\n", + prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, + buf1, RD_ADDRSTRLEN)); + + dir = BGP_VPN_POLICY_DIR_TOVPN; + ecom_str = ecommunity_ecom2str( + bgp->vpn_policy[afi].rtlist[dir], + ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + vty_out(vty, "Export RT: %s\n", ecom_str); } - vty_out(vty, "RD: %s\n", - prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, - buf1, RD_ADDRSTRLEN)); - dir = BGP_VPN_POLICY_DIR_TOVPN; - ecom_str = ecommunity_ecom2str( - bgp->vpn_policy[afi].rtlist[dir], - ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - vty_out(vty, "Emport RT: %s\n", ecom_str); - XFREE(MTYPE_ECOMMUNITY_STR, ecom_str); } return CMD_SUCCESS; @@ -11069,20 +11150,22 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, /* "show [ip] bgp route-leak" command. */ DEFUN (show_ip_bgp_route_leak, - show_ip_bgp_route_leak_cmd, - "show [ip] bgp [ VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] route-leak", - SHOW_STR - IP_STR - BGP_STR - BGP_INSTANCE_HELP_STR - BGP_AFI_HELP_STR - BGP_SAFI_HELP_STR - "Route leaking information\n") +show_ip_bgp_route_leak_cmd, +"show [ip] bgp [ VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] route-leak [json]", + SHOW_STR + IP_STR + BGP_STR + BGP_INSTANCE_HELP_STR + BGP_AFI_HELP_STR + BGP_SAFI_HELP_STR + "Route leaking information\n" + JSON_STR) { char *vrf = NULL; afi_t afi = AFI_MAX; safi_t safi = SAFI_MAX; + uint8_t uj = use_json(argc, argv); int idx = 0; /* show [ip] bgp */ @@ -11110,7 +11193,7 @@ DEFUN (show_ip_bgp_route_leak, return CMD_WARNING; } - return bgp_show_route_leak_vty(vty, vrf, afi, safi); + return bgp_show_route_leak_vty(vty, vrf, afi, safi, uj); } static void bgp_show_all_instances_updgrps_vty(struct vty *vty, afi_t afi, From 4ed8f3f619fa5d16667b513830d35029a4a227e6 Mon Sep 17 00:00:00 2001 From: Martin Winter Date: Fri, 10 Aug 2018 18:35:06 -0700 Subject: [PATCH 04/66] snapcraft: Add RPKI to snap package Signed-off-by: Martin Winter --- snapcraft/README.usage.md | 19 +++++++++++++++---- snapcraft/scripts/bgpd-service | 9 ++++++++- snapcraft/scripts/set-options | 25 ++++++++++++++++++++++++- snapcraft/snapcraft.yaml.in | 25 +++++++++++++++++++++++-- 4 files changed, 70 insertions(+), 8 deletions(-) diff --git a/snapcraft/README.usage.md b/snapcraft/README.usage.md index 50711b13b7..a7b51a5656 100644 --- a/snapcraft/README.usage.md +++ b/snapcraft/README.usage.md @@ -31,7 +31,7 @@ Commands defined by this snap - `frr.readme`: Returns this document `cat README_usage.md` - `frr.set`: - Allows to enable `FPM` module. See FPM section below + Allows to enable `FPM` and/or disable RPKIi module. See Module section below and for debugging defined at this time (May get removed later - do not depend on them). These are mainly intended to debug the Snap @@ -100,13 +100,13 @@ are named `eth0`, `eth1` and `eth2`, then the additional lines in These settings require either a reboot or a manual configuration with `sysctl` as well. -FPM Module +Modules ---------- -The `frr.set` allows to turn FPM module on or off. +The `frr.set` allows to turn FPM module ond the RPKI module on or off. frr.set fpm {disable|protobuf|netlink} - Disables FPM or enables FPM with selected mode + Disables FPM or enables FPM with selected mode (default: disabled) By default, the FPM module is disabled, but installed with netlink and protobuf support. To enable the FPM module, use the `frr.set fpm protobuf` @@ -114,6 +114,17 @@ or `frr.set fpm netlink` command. The command will only enable the mode for the next restart of zebra. Please reboot or restart zebra after changing the mode to become effective. + frr.set rpki {enable|disable} + + Disables or enables BGP RPKI (default: enabled) + +By default, the RPKI module is enabled. To disable the RPKI module +use the `frr.set rpki disable` command. The command will only enable +the module after the next restart of the bgp daemon. Please reboot or +restart bgpd after changing the mode to become effective. +(Normally, there is no need to disable the module as it has no effect +if there are no RPKI configurations in BGP) + FAQ --- - frr.vtysh displays `--MORE--` on long output. How to suppress this? diff --git a/snapcraft/scripts/bgpd-service b/snapcraft/scripts/bgpd-service index 4072031eda..6c3a6f5959 100644 --- a/snapcraft/scripts/bgpd-service +++ b/snapcraft/scripts/bgpd-service @@ -5,9 +5,16 @@ set -e -x if ! [ -e $SNAP_DATA/bgpd.conf ]; then cp $SNAP/etc/frr/bgpd.conf.default $SNAP_DATA/bgpd.conf fi +# If no RPKI option is specified, then we create a default +# with RPKI enabled +if ! [ -e $SNAP_DATA/rpki.conf ]; then + echo "-M rpki" > $SNAP_DATA/rpki.conf +fi +EXTRA_OPTIONS="`cat $SNAP_DATA/rpki.conf`" exec $SNAP/sbin/bgpd \ -f $SNAP_DATA/bgpd.conf \ --pid_file $SNAP_DATA/bgpd.pid \ --socket $SNAP_DATA/zsock \ - --vty_socket $SNAP_DATA + --vty_socket $SNAP_DATA \ + --moduledir $SNAP/lib/frr/modules $EXTRA_OPTIONS diff --git a/snapcraft/scripts/set-options b/snapcraft/scripts/set-options index e76e321ef8..0637d2ce5d 100755 --- a/snapcraft/scripts/set-options +++ b/snapcraft/scripts/set-options @@ -28,11 +28,34 @@ case $1 in ;; esac ;; + rpki) + case $2 in + disable) + echo "" > $SNAP_DATA/rpki.conf + echo "RPKI module disabled. Please restart FRR" + ;; + enable) + echo "-M rpki" > $SNAP_DATA/rpki.conf + echo "RPKI module enabled. Please restart FRR" + ;; + *) + echo "Usage:" + echo " ${SNAP_NAME}.set rpki {disable|enable}" + echo "" + echo " Disables BGP RPKI module or enables it (default: enabled)" + echo " Mode will be saved for next restart of bgpd, but bgpd" + echo " is not automatically restarted" + exit 1 + ;; + esac + ;; *) echo "Usage:" echo " ${SNAP_NAME}.set fpm {disable|protobuf|netlink}" + echo " ${SNAP_NAME}.set rpki {disable|enable}" echo "" - echo " Disables FPM or enables FPM with selected mode" + echo " fpm: Disables FPM or enables FPM with selected mode" + echo " rpki: Disables BGP RPKI or enables it (default: enabled)" exit 1 ;; esac diff --git a/snapcraft/snapcraft.yaml.in b/snapcraft/snapcraft.yaml.in index 563a05c5a7..b70d6efee2 100644 --- a/snapcraft/snapcraft.yaml.in +++ b/snapcraft/snapcraft.yaml.in @@ -136,7 +136,7 @@ apps: - network-bind - network-control bgpd-debug: - command: sbin/bgpd -f $SNAP_DATA/bgpd.conf --pid_file $SNAP_DATA/bgpd.pid --socket $SNAP_DATA/zsock --vty_socket $SNAP_DATA + command: sbin/bgpd -f $SNAP_DATA/bgpd.conf --pid_file $SNAP_DATA/bgpd.pid --socket $SNAP_DATA/zsock --vty_socket $SNAP_DATA --moduledir $SNAP/lib/frr/modules `cat $SNAP_DATA/rpki.conf 2> /dev/null` plugs: - network - network-bind @@ -221,8 +221,27 @@ apps: - network-control parts: + rtrlib: + build-packages: + - cmake + - make + - gcc + - libssh-dev + stage-packages: + - libssh-4 + prime: + - lib/x86_64-linux-gnu/librtr.so* + - usr/lib/x86_64-linux-gnu/libssh.so* + source: https://github.com/rtrlib/rtrlib.git + source-type: git + source-tag: v0.5.0 + plugin: cmake + configflags: + - -DCMAKE_BUILD_TYPE=Release frr: - build-packages: + after: [rtrlib] + build-packages: + - gcc - autoconf - automake - libtool @@ -247,6 +266,7 @@ parts: - flex - python3-dev - protobuf-c-compiler + - python3-sphinx stage-packages: - coreutils - iproute2 @@ -276,6 +296,7 @@ parts: - --enable-ldpd - --enable-fpm - --enable-protobuf + - --enable-rpki - --enable-configfile-mask=0640 - --enable-logfile-mask=0640 - --localstatedir=/var/run From de6058ab915c50cdc7b19b544b519c4b9b4543d6 Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Mon, 20 Aug 2018 07:51:34 -0700 Subject: [PATCH 05/66] bgpd: unregister VNI learning from zebra on default instance delete The code for this was always there but was not kicking in because of an incorrect dependency on is_evpn_enabled. This API attempts to locate the default instance from bgp_master's instance list. Only the instance currently being deleted has already been removed from the instance list by the time bgp_delete->bgp_zebra_instance_deregister is executed. Symptom of this bug used to show up when a default instance is deleted and created again. In that case bgp_zebra_instance_register would not be effective as zebra ignores the register as dup (dereg didn't happen in the first place) so bgpd wouldn't reload already configured L2-VNIs. root@cel-sea-03:~# net show bgp l2vpn evpn vni |grep 1000 * 1000 L2 169.253.0.11:9 6646:1000 6646:1000 vrf1 root@cel-sea-03:~# grep "router bgp" /etc/frr/frr.conf router bgp 6646 root@cel-sea-03:~# sed -i 's/6646/6656/' /etc/frr/frr.conf root@cel-sea-03:~# grep "router bgp" /etc/frr/frr.conf router bgp 6656 root@cel-sea-03:~# systemctl reload frr root@cel-sea-03:~# net show bgp l2vpn evpn vni |grep 1000 root@cel-sea-03:~# Fix simply changes the order of dereg to make bgp_zebra_instance_deregister actually happen (by doing it before the default instance is removed from the master list). Ticket: CM-21566 Signed-off-by: Anuradha Karuppiah --- bgpd/bgpd.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index c8b4e3acf5..0219c1e982 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -3187,15 +3187,16 @@ int bgp_delete(struct bgp *bgp) .import_redirect_rtlist); bgp->vpn_policy[afi].import_redirect_rtlist = NULL; } - /* Remove visibility via the master list - there may however still be - * routes to be processed still referencing the struct bgp. - */ - listnode_delete(bm->bgp, bgp); /* Deregister from Zebra, if needed */ if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) bgp_zebra_instance_deregister(bgp); + /* Remove visibility via the master list - there may however still be + * routes to be processed still referencing the struct bgp. + */ + listnode_delete(bm->bgp, bgp); + /* Free interfaces in this instance. */ bgp_if_finish(bgp); From 1491ad1ec43bbec55a948760dd1c625acfe6bf37 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 20 Aug 2018 13:17:34 -0400 Subject: [PATCH 06/66] doc, debianpkg: Cleanup tcp-zebra configure options Since we removed --enable-tcp-zebra cleanup the last remaining vestiges of that code from the system. Signed-off-by: Donald Sharp --- debianpkg/backports/ubuntu12.04/debian/rules | 8 -------- debianpkg/backports/ubuntu14.04/debian/rules | 8 -------- debianpkg/rules | 8 -------- doc/manpages/common-options.rst | 2 +- 4 files changed, 1 insertion(+), 25 deletions(-) diff --git a/debianpkg/backports/ubuntu12.04/debian/rules b/debianpkg/backports/ubuntu12.04/debian/rules index 3a6c80297e..086238eda5 100755 --- a/debianpkg/backports/ubuntu12.04/debian/rules +++ b/debianpkg/backports/ubuntu12.04/debian/rules @@ -10,7 +10,6 @@ WANT_LDP ?= 1 WANT_PIM ?= 1 WANT_OSPFAPI ?= 1 -WANT_TCP_ZEBRA ?= 0 WANT_BGP_VNC ?= 1 WANT_CUMULUS_MODE ?= 0 WANT_MULTIPATH ?= 1 @@ -65,12 +64,6 @@ else USE_OSPFAPI=--enable-ospfapi=no endif -ifeq ($(WANT_TCP_ZEBRA),1) - USE_TCP_ZEBRA=--enable-tcp-zebra -else - USE_TCP_ZEBRA=--disable-tcp-zebra -endif - ifeq ($(WANT_BGP_VNC), 1) USE_BGP_VNC=--enable-bgp-vnc=yes else @@ -123,7 +116,6 @@ override_dh_auto_configure: $(USE_OSPFAPI) \ $(USE_MULTIPATH) \ $(USE_LDP) \ - $(USE_TCP_ZEBRA) \ --enable-fpm \ $(USE_FRR_USER) $(USE_FRR_GROUP) \ $(USE_FRR_VTY_GROUP) \ diff --git a/debianpkg/backports/ubuntu14.04/debian/rules b/debianpkg/backports/ubuntu14.04/debian/rules index f7468d6f79..559a27e256 100755 --- a/debianpkg/backports/ubuntu14.04/debian/rules +++ b/debianpkg/backports/ubuntu14.04/debian/rules @@ -10,7 +10,6 @@ WANT_LDP ?= 1 WANT_PIM ?= 1 WANT_OSPFAPI ?= 1 -WANT_TCP_ZEBRA ?= 0 WANT_BGP_VNC ?= 1 WANT_CUMULUS_MODE ?= 0 WANT_MULTIPATH ?= 1 @@ -75,12 +74,6 @@ else USE_OSPFAPI=--enable-ospfapi=no endif -ifeq ($(WANT_TCP_ZEBRA),1) - USE_TCP_ZEBRA=--enable-tcp-zebra -else - USE_TCP_ZEBRA=--disable-tcp-zebra -endif - ifeq ($(WANT_BGP_VNC), 1) USE_BGP_VNC=--enable-bgp-vnc=yes else @@ -152,7 +145,6 @@ override_dh_auto_configure: $(USE_OSPFAPI) \ $(USE_MULTIPATH) \ $(USE_LDP) \ - $(USE_TCP_ZEBRA) \ --enable-fpm \ $(USE_FRR_USER) $(USE_FRR_GROUP) \ $(USE_FRR_VTY_GROUP) \ diff --git a/debianpkg/rules b/debianpkg/rules index c1cb865490..28d291e40a 100755 --- a/debianpkg/rules +++ b/debianpkg/rules @@ -10,7 +10,6 @@ WANT_LDP ?= 1 WANT_PIM ?= 1 WANT_OSPFAPI ?= 1 -WANT_TCP_ZEBRA ?= 0 WANT_BGP_VNC ?= 1 WANT_CUMULUS_MODE ?= 0 WANT_MULTIPATH ?= 1 @@ -75,12 +74,6 @@ else USE_OSPFAPI=--enable-ospfapi=no endif -ifeq ($(WANT_TCP_ZEBRA),1) - USE_TCP_ZEBRA=--enable-tcp-zebra -else - USE_TCP_ZEBRA=--disable-tcp-zebra -endif - ifeq ($(WANT_BGP_VNC), 1) USE_BGP_VNC=--enable-bgp-vnc=yes else @@ -152,7 +145,6 @@ override_dh_auto_configure: $(USE_OSPFAPI) \ $(USE_MULTIPATH) \ $(USE_LDP) \ - $(USE_TCP_ZEBRA) \ --enable-fpm \ $(USE_FRR_USER) $(USE_FRR_GROUP) \ $(USE_FRR_VTY_GROUP) \ diff --git a/doc/manpages/common-options.rst b/doc/manpages/common-options.rst index 1e99010505..5fff6fca66 100644 --- a/doc/manpages/common-options.rst +++ b/doc/manpages/common-options.rst @@ -126,7 +126,7 @@ These following options control the daemon's VTY (interactive command line) inte staticd 2616 bfdd 2617 - Port 2607 is used for ospfd's Opaque LSA API, while port 2600 is used for the (insecure) TCP-ZEBRA interface. + Port 2607 is used for ospfd's Opaque LSA API. .. option:: --vty_socket vty-path From 04c9077f814d0f3c525de59212488a4204bc74b2 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Mon, 20 Aug 2018 19:36:11 +0000 Subject: [PATCH 07/66] bgpd: fix issues with bgp route-leak json commit Signed-off-by: Don Slice --- bgpd/bgp_vty.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index bfcd280975..984c602002 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -11036,6 +11036,7 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, BGP_CONFIG_VRF_TO_VRF_IMPORT)) { json_object_string_add(json, "importFromVrfs", "none"); json_object_string_add(json, "importRts", "none"); + json_object_free(json_import_vrfs); } else { for (ALL_LIST_ELEMENTS_RO( bgp->vpn_policy[afi].import_vrf, @@ -11060,6 +11061,7 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, json_object_string_add(json, "routeDistinguisher", "none"); json_object_string_add(json, "exportRts", "none"); + json_object_free(json_export_vrfs); } else { for (ALL_LIST_ELEMENTS_RO( bgp->vpn_policy[afi].export_vrf, @@ -11125,7 +11127,7 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, afi_safi_print(afi, safi)); else { vty_out(vty, - "This VRF is exporting %s routes to the ollowing VRFs:\n", + "This VRF is exporting %s routes to the following VRFs:\n", afi_safi_print(afi, safi)); for (ALL_LIST_ELEMENTS_RO( @@ -11142,6 +11144,7 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, bgp->vpn_policy[afi].rtlist[dir], ECOMMUNITY_FORMAT_ROUTE_MAP, 0); vty_out(vty, "Export RT: %s\n", ecom_str); + XFREE(MTYPE_ECOMMUNITY_STR, ecom_str); } } @@ -11150,8 +11153,8 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, /* "show [ip] bgp route-leak" command. */ DEFUN (show_ip_bgp_route_leak, -show_ip_bgp_route_leak_cmd, -"show [ip] bgp [ VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] route-leak [json]", + show_ip_bgp_route_leak_cmd, + "show [ip] bgp [ VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_CMD_STR"]] route-leak [json]", SHOW_STR IP_STR BGP_STR From 3b12dd8204a3a47b3cec6501031b46d778dc3196 Mon Sep 17 00:00:00 2001 From: Christian Franke Date: Mon, 20 Aug 2018 22:44:13 +0200 Subject: [PATCH 08/66] doc: bfdd manpage should be included in the manpage index Signed-off-by: Christian Franke --- doc/manpages/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/manpages/index.rst b/doc/manpages/index.rst index e95dd26e84..c62835c770 100644 --- a/doc/manpages/index.rst +++ b/doc/manpages/index.rst @@ -6,6 +6,7 @@ .. toctree:: :maxdepth: 2 + bfdd bgpd eigrpd isisd From 6ce24e5247ee5645eba3acbbc77d44b625b82a49 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Mon, 20 Aug 2018 21:05:57 +0000 Subject: [PATCH 09/66] bgpd: fix additional issue with bgp route-leak json commit Signed-off-by: Don Slice --- bgpd/bgp_vty.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 984c602002..98d9ffcceb 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -11010,8 +11010,6 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, json_object *json_export_vrfs = NULL; json = json_object_new_object(); - json_import_vrfs = json_object_new_array(); - json_export_vrfs = json_object_new_array(); /* Provide context for the block */ json_object_string_add(json, "vrf", name ? name : "default"); @@ -11036,8 +11034,9 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, BGP_CONFIG_VRF_TO_VRF_IMPORT)) { json_object_string_add(json, "importFromVrfs", "none"); json_object_string_add(json, "importRts", "none"); - json_object_free(json_import_vrfs); } else { + json_import_vrfs = json_object_new_array(); + for (ALL_LIST_ELEMENTS_RO( bgp->vpn_policy[afi].import_vrf, node, vname)) @@ -11061,8 +11060,9 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, json_object_string_add(json, "routeDistinguisher", "none"); json_object_string_add(json, "exportRts", "none"); - json_object_free(json_export_vrfs); } else { + json_export_vrfs = json_object_new_array(); + for (ALL_LIST_ELEMENTS_RO( bgp->vpn_policy[afi].export_vrf, node, vname)) From e36ff3f3a8fce1f5947406d24ed93261e1b3bf1c Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 17 Aug 2018 11:34:22 -0300 Subject: [PATCH 10/66] bfdd: fix documentation warnings * Extend dashes on 'OSPF BFD Configuration' title; * Add JSON output code indentation; Signed-off-by: Rafael Zalamena --- doc/user/bfd.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/user/bfd.rst b/doc/user/bfd.rst index 8eb9efe789..986d1494a5 100644 --- a/doc/user/bfd.rst +++ b/doc/user/bfd.rst @@ -179,7 +179,7 @@ The following commands are available inside the BGP configuration node. .. _bfd-ospf-peer-config: OSPF BFD Configuration ---------------------- +---------------------- The following commands are available inside the interface configuration node. @@ -364,7 +364,7 @@ You can inspect the current BFD peer status with the following commands: Echo transmission interval: 50ms frr# show bfd peer 192.168.0.1 json -{"multihop":false,"peer":"192.168.0.1","id":1,"remote-id":1,"status":"up","uptime":161,"diagnostic":"ok","remote-diagnostic":"ok","receive-interval":300,"transmit-interval":300,"echo-interval":50,"remote-receive-interval":300,"remote-transmit-interval":300,"remote-echo-interval":50} + {"multihop":false,"peer":"192.168.0.1","id":1,"remote-id":1,"status":"up","uptime":161,"diagnostic":"ok","remote-diagnostic":"ok","receive-interval":300,"transmit-interval":300,"echo-interval":50,"remote-receive-interval":300,"remote-transmit-interval":300,"remote-echo-interval":50} You can also inspect peer session counters with the following commands: @@ -402,4 +402,4 @@ You can also inspect peer session counters with the following commands: Zebra notifications: 4 frr# show bfd peer 192.168.0.1 counters json -{"multihop":false,"peer":"192.168.0.1","control-packet-input":348,"control-packet-output":685,"echo-packet-input":6815,"echo-packet-output":6816,"session-up":1,"session-down":0,"zebra-notifications":4} + {"multihop":false,"peer":"192.168.0.1","control-packet-input":348,"control-packet-output":685,"echo-packet-input":6815,"echo-packet-output":6816,"session-up":1,"session-down":0,"zebra-notifications":4} From 5b3d4186defcf9faa15fce45703ee8c5a80f74db Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 20 Aug 2018 20:41:37 -0400 Subject: [PATCH 11/66] ospfd: Add ospf_lsa_new_and_data function and abstract away In all but one instance we were following this pattern with ospf_lsa_new: ospf_lsa_new() ospf_lsa_data_new() so let's create a ospf_lsa_new_and_data to abstract this bit of fun and cleanup all the places where it assumes these function calls can fail. Signed-off-by: Donald Sharp --- ospfd/ospf_apiserver.c | 14 +------------- ospfd/ospf_ext.c | 30 ++---------------------------- ospfd/ospf_flood.c | 3 +-- ospfd/ospf_lsa.c | 31 +++++++++++++++---------------- ospfd/ospf_lsa.h | 1 + ospfd/ospf_packet.c | 3 +-- ospfd/ospf_ri.c | 13 +------------ ospfd/ospf_te.c | 13 +------------ 8 files changed, 23 insertions(+), 85 deletions(-) diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c index c0ce971f0c..57e0ae5ec9 100644 --- a/ospfd/ospf_apiserver.c +++ b/ospfd/ospf_apiserver.c @@ -1425,19 +1425,7 @@ struct ospf_lsa *ospf_apiserver_opaque_lsa_new(struct ospf_area *area, newlsa->length = htons(length); /* Create OSPF LSA. */ - if ((new = ospf_lsa_new()) == NULL) { - zlog_warn("ospf_apiserver_opaque_lsa_new: ospf_lsa_new() ?"); - stream_free(s); - return NULL; - } - - if ((new->data = ospf_lsa_data_new(length)) == NULL) { - zlog_warn( - "ospf_apiserver_opaque_lsa_new: ospf_lsa_data_new() ?"); - ospf_lsa_unlock(&new); - stream_free(s); - return NULL; - } + new = ospf_lsa_new_and_data(length); new->area = area; new->oi = oi; diff --git a/ospfd/ospf_ext.c b/ospfd/ospf_ext.c index b8d14c351e..f6ed9b81b9 100644 --- a/ospfd/ospf_ext.c +++ b/ospfd/ospf_ext.c @@ -977,20 +977,7 @@ static struct ospf_lsa *ospf_ext_pref_lsa_new(struct ospf_area *area, lsah->length = htons(length); /* Now, create an OSPF LSA instance. */ - new = ospf_lsa_new(); - if (new == NULL) { - zlog_warn("EXT (%s): ospf_lsa_new() error", __func__); - stream_free(s); - return NULL; - } - new->data = ospf_lsa_data_new(length); - if (new->data == NULL) { - zlog_warn("EXT (%s): ospf_lsa_data_new() error", __func__); - ospf_lsa_unlock(&new); - new = NULL; - stream_free(s); - return NULL; - } + new = ospf_lsa_new_and_data(length); /* Segment Routing belongs only to default VRF */ new->vrf_id = VRF_DEFAULT; @@ -1056,20 +1043,7 @@ static struct ospf_lsa *ospf_ext_link_lsa_new(struct ospf_area *area, lsah->length = htons(length); /* Now, create an OSPF LSA instance. */ - new = ospf_lsa_new(); - if (new == NULL) { - zlog_warn("EXT (%s): ospf_lsa_new() error", __func__); - stream_free(s); - return NULL; - } - new->data = ospf_lsa_data_new(length); - if (new->data == NULL) { - zlog_warn("EXT (%s): ospf_lsa_data_new() error", __func__); - ospf_lsa_unlock(&new); - new = NULL; - stream_free(s); - return NULL; - } + new = ospf_lsa_new_and_data(length); /* Segment Routing belongs only to default VRF */ new->vrf_id = VRF_DEFAULT; diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index 002c6bba8d..b4e9dda58a 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -810,8 +810,7 @@ struct ospf_lsa *ospf_ls_request_new(struct lsa_header *lsah) { struct ospf_lsa *new; - new = ospf_lsa_new(); - new->data = ospf_lsa_data_new(OSPF_LSA_HEADER_SIZE); + new = ospf_lsa_new_and_data(OSPF_LSA_HEADER_SIZE); memcpy(new->data, lsah, OSPF_LSA_HEADER_SIZE); return new; diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 2651cf717b..47d8b2f57a 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -167,6 +167,16 @@ struct ospf_lsa *ospf_lsa_new() return new; } +struct ospf_lsa *ospf_lsa_new_and_data(size_t size) +{ + struct ospf_lsa *new; + + new = ospf_lsa_new(); + new->data = ospf_lsa_data_new(size); + + return new; +} + /* Duplicate OSPF LSA. */ struct ospf_lsa *ospf_lsa_dup(struct ospf_lsa *lsa) { @@ -781,17 +791,13 @@ static struct ospf_lsa *ospf_router_lsa_new(struct ospf_area *area) lsah->length = htons(length); /* Now, create OSPF LSA instance. */ - if ((new = ospf_lsa_new()) == NULL) { - zlog_err("%s: Unable to create new lsa", __func__); - return NULL; - } + new = ospf_lsa_new_and_data(length); new->area = area; SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); new->vrf_id = area->ospf->vrf_id; /* Copy LSA data to store, discard stream. */ - new->data = ospf_lsa_data_new(length); memcpy(new->data, lsah, length); stream_free(s); @@ -997,17 +1003,13 @@ static struct ospf_lsa *ospf_network_lsa_new(struct ospf_interface *oi) lsah->length = htons(length); /* Create OSPF LSA instance. */ - if ((new = ospf_lsa_new()) == NULL) { - zlog_err("%s: ospf_lsa_new returned NULL", __func__); - return NULL; - } + new = ospf_lsa_new_and_data(length); new->area = oi->area; SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); new->vrf_id = oi->ospf->vrf_id; /* Copy LSA to store. */ - new->data = ospf_lsa_data_new(length); memcpy(new->data, lsah, length); stream_free(s); @@ -1181,13 +1183,12 @@ static struct ospf_lsa *ospf_summary_lsa_new(struct ospf_area *area, lsah->length = htons(length); /* Create OSPF LSA instance. */ - new = ospf_lsa_new(); + new = ospf_lsa_new_and_data(length); new->area = area; SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); new->vrf_id = area->ospf->vrf_id; /* Copy LSA to store. */ - new->data = ospf_lsa_data_new(length); memcpy(new->data, lsah, length); stream_free(s); @@ -1323,13 +1324,12 @@ static struct ospf_lsa *ospf_summary_asbr_lsa_new(struct ospf_area *area, lsah->length = htons(length); /* Create OSPF LSA instance. */ - new = ospf_lsa_new(); + new = ospf_lsa_new_and_data(length); new->area = area; SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_SELF_CHECKED); new->vrf_id = area->ospf->vrf_id; /* Copy LSA to store. */ - new->data = ospf_lsa_data_new(length); memcpy(new->data, lsah, length); stream_free(s); @@ -1629,14 +1629,13 @@ static struct ospf_lsa *ospf_external_lsa_new(struct ospf *ospf, lsah->length = htons(length); /* Now, create OSPF LSA instance. */ - new = ospf_lsa_new(); + new = ospf_lsa_new_and_data(length); new->area = NULL; SET_FLAG(new->flags, OSPF_LSA_SELF | OSPF_LSA_APPROVED | OSPF_LSA_SELF_CHECKED); new->vrf_id = ospf->vrf_id; /* Copy LSA data to store, discard stream. */ - new->data = ospf_lsa_data_new(length); memcpy(new->data, lsah, length); stream_free(s); diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index f8f7b28d4e..ba4c4c1cac 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -235,6 +235,7 @@ extern int ospf_check_nbr_status(struct ospf *); /* Prototype for LSA primitive. */ extern struct ospf_lsa *ospf_lsa_new(void); +extern struct ospf_lsa *ospf_lsa_new_and_data(size_t size); extern struct ospf_lsa *ospf_lsa_dup(struct ospf_lsa *); extern void ospf_lsa_free(struct ospf_lsa *); extern struct ospf_lsa *ospf_lsa_lock(struct ospf_lsa *); diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index f1d4a39dba..56b83d22d5 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -1742,7 +1742,7 @@ static struct list *ospf_ls_upd_list_lsa(struct ospf_neighbor *nbr, } /* Create OSPF LSA instance. */ - lsa = ospf_lsa_new(); + lsa = ospf_lsa_new_and_data(length); lsa->vrf_id = oi->ospf->vrf_id; /* We may wish to put some error checking if type NSSA comes in @@ -1761,7 +1761,6 @@ static struct list *ospf_ls_upd_list_lsa(struct ospf_neighbor *nbr, break; } - lsa->data = ospf_lsa_data_new(length); memcpy(lsa->data, lsah, length); if (IS_DEBUG_OSPF_EVENT) diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c index fa7dd04d19..c9d0a53c8d 100644 --- a/ospfd/ospf_ri.c +++ b/ospfd/ospf_ri.c @@ -775,18 +775,7 @@ static struct ospf_lsa *ospf_router_info_lsa_new() lsah->length = htons(length); /* Now, create an OSPF LSA instance. */ - if ((new = ospf_lsa_new()) == NULL) { - zlog_warn("ospf_router_info_lsa_new: ospf_lsa_new() ?"); - stream_free(s); - return NULL; - } - if ((new->data = ospf_lsa_data_new(length)) == NULL) { - zlog_warn("ospf_router_info_lsa_new: ospf_lsa_data_new() ?"); - ospf_lsa_unlock(&new); - new = NULL; - stream_free(s); - return new; - } + new = ospf_lsa_new_and_data(length); new->area = OspfRI.area; /* Area must be null if the Opaque type is AS scope, fulfill otherwise */ diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index cc2d9282fe..a9dc1c18e3 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -1201,18 +1201,7 @@ static struct ospf_lsa *ospf_mpls_te_lsa_new(struct ospf *ospf, lsah->length = htons(length); /* Now, create an OSPF LSA instance. */ - if ((new = ospf_lsa_new()) == NULL) { - zlog_warn("%s: ospf_lsa_new() ?", __func__); - stream_free(s); - return NULL; - } - if ((new->data = ospf_lsa_data_new(length)) == NULL) { - zlog_warn("%s: ospf_lsa_data_new() ?", __func__); - ospf_lsa_unlock(&new); - new = NULL; - stream_free(s); - return new; - } + new = ospf_lsa_new_and_data(length); new->vrf_id = ospf->vrf_id; if (area && area->ospf) From b2111f08a5da39ac7de7489aab37f35b812aedba Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Tue, 21 Aug 2018 11:09:36 +0200 Subject: [PATCH 12/66] lib: fix show error all show error all was displaying 0 value for code, whereas real code value was not displayed. Signed-off-by: Philippe Guibert --- lib/ferr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ferr.c b/lib/ferr.c index 2fa5db6f34..d1b9d514b4 100644 --- a/lib/ferr.c +++ b/lib/ferr.c @@ -146,7 +146,7 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json) char ubuf[256]; snprintf(pbuf, sizeof(pbuf), "\nError %"PRIu32" - %s", - code, ref->title); + ref->code, ref->title); memset(ubuf, '=', strlen(pbuf)); ubuf[sizeof(ubuf) - 1] = '\0'; From 19c0412aadd7ee454c9cfb4beffad69232c27330 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 21 Aug 2018 08:40:51 -0400 Subject: [PATCH 13/66] ospfd: Remove unused function The ospf_external_route_lookup function was not being used so let's just remove it. Unfortunately the removal was not quite so simple as that ospf_asbr.h was being used to generate a reference for the `struct ospf_route` data structure, so we need to fix up the compile by fixing up header inclusions so that ospf_route.h is actually included Signed-off-by: Donald Sharp --- ospfclient/ospf_apiclient.c | 1 + ospfd/ospf_asbr.c | 20 -------------------- ospfd/ospf_asbr.h | 2 -- ospfd/ospf_main.c | 1 + ospfd/ospf_snmp.c | 1 + ospfd/ospfd.c | 2 +- 6 files changed, 4 insertions(+), 23 deletions(-) diff --git a/ospfclient/ospf_apiclient.c b/ospfclient/ospf_apiclient.c index db624ae074..50485cc7e2 100644 --- a/ospfclient/ospf_apiclient.c +++ b/ospfclient/ospf_apiclient.c @@ -46,6 +46,7 @@ #include "ospfd/ospf_lsdb.h" #include "ospfd/ospf_neighbor.h" #include "ospfd/ospf_dump.h" +#include "ospfd/ospf_route.h" #include "ospfd/ospf_zebra.h" #include "ospfd/ospf_api.h" diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c index 18c1077da0..8e8f655305 100644 --- a/ospfd/ospf_asbr.c +++ b/ospfd/ospf_asbr.c @@ -73,26 +73,6 @@ void ospf_external_route_remove(struct ospf *ospf, struct prefix_ipv4 *p) p->prefixlen); } -/* Lookup external route. */ -struct ospf_route *ospf_external_route_lookup(struct ospf *ospf, - struct prefix_ipv4 *p) -{ - struct route_node *rn; - - rn = route_node_lookup(ospf->old_external_route, (struct prefix *)p); - if (rn) { - route_unlock_node(rn); - if (rn->info) - return rn->info; - } - - zlog_warn("Route[%s/%d]: lookup, no such prefix", inet_ntoa(p->prefix), - p->prefixlen); - - return NULL; -} - - /* Add an External info for AS-external-LSA. */ struct external_info *ospf_external_info_new(uint8_t type, unsigned short instance) diff --git a/ospfd/ospf_asbr.h b/ospfd/ospf_asbr.h index 370c6787b4..ac7bd68b5f 100644 --- a/ospfd/ospf_asbr.h +++ b/ospfd/ospf_asbr.h @@ -68,8 +68,6 @@ extern void ospf_external_info_delete(struct ospf *, uint8_t, unsigned short, extern struct external_info *ospf_external_info_lookup(struct ospf *, uint8_t, unsigned short, struct prefix_ipv4 *); -extern struct ospf_route *ospf_external_route_lookup(struct ospf *, - struct prefix_ipv4 *); extern void ospf_asbr_status_update(struct ospf *, uint8_t); extern void ospf_redistribute_withdraw(struct ospf *, uint8_t, unsigned short); diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index 6dadc05bba..8853802d07 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -49,6 +49,7 @@ #include "ospfd/ospf_lsdb.h" #include "ospfd/ospf_neighbor.h" #include "ospfd/ospf_dump.h" +#include "ospfd/ospf_route.h" #include "ospfd/ospf_zebra.h" #include "ospfd/ospf_vty.h" #include "ospfd/ospf_bfd.h" diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c index c90db031dc..19d2e6a952 100644 --- a/ospfd/ospf_snmp.c +++ b/ospfd/ospf_snmp.c @@ -47,6 +47,7 @@ #include "ospfd/ospf_flood.h" #include "ospfd/ospf_ism.h" #include "ospfd/ospf_dump.h" +#include "ospfd/ospf_route.h" #include "ospfd/ospf_zebra.h" /* OSPF2-MIB. */ diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index ac8f0d92c3..bfaedf2fe7 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -52,10 +52,10 @@ #include "ospfd/ospf_spf.h" #include "ospfd/ospf_packet.h" #include "ospfd/ospf_dump.h" +#include "ospfd/ospf_route.h" #include "ospfd/ospf_zebra.h" #include "ospfd/ospf_abr.h" #include "ospfd/ospf_flood.h" -#include "ospfd/ospf_route.h" #include "ospfd/ospf_ase.h" From dce2036b6addc24c675d8ec2cd5dd30293bb2b81 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Tue, 21 Aug 2018 15:15:38 +0000 Subject: [PATCH 14/66] lib: fix deadlock in log.c Daemons could deadlock when log file could not be opened during a log rotation. Signed-off-by: Quentin Young --- lib/log.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/log.c b/lib/log.c index e011a78f1c..361521f568 100644 --- a/lib/log.c +++ b/lib/log.c @@ -868,11 +868,16 @@ int zlog_rotate(void) save_errno = errno; umask(oldumask); if (zl->fp == NULL) { + + pthread_mutex_unlock(&loglock); + flog_err_sys( LIB_ERR_SYSTEM_CALL, "Log rotate failed: cannot open file %s for append: %s", zl->filename, safe_strerror(save_errno)); ret = -1; + + pthread_mutex_lock(&loglock); } else { logfile_fd = fileno(zl->fp); zl->maxlvl[ZLOG_DEST_FILE] = level; From 503d1ec6eb5a505c57b78a65a9c7ea94b932355e Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Mon, 20 Aug 2018 18:32:00 +0200 Subject: [PATCH 15/66] bgpd: avoid memory leak in bgp flowspec list, plus usage of bool Avoid memory leak in bgp flowspec list. Usage of bool parameter instead of int, to handle the number of entries PBR. Signed-off-by: Philippe Guibert --- bgpd/bgp_flowspec_vty.c | 10 +++++----- bgpd/bgp_route.c | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c index f8c0613208..31d2c540fa 100644 --- a/bgpd/bgp_flowspec_vty.c +++ b/bgpd/bgp_flowspec_vty.c @@ -335,7 +335,7 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p, struct listnode *node; struct bgp_pbr_match_entry *bpme; struct bgp_pbr_match *bpm; - int unit = 0; + bool list_began = false; struct list *list_bpm; list_bpm = list_new(); @@ -347,14 +347,14 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p, if (listnode_lookup(list_bpm, bpm)) continue; listnode_add(list_bpm, bpm); - if (unit == 0) + if (!list_began) { vty_out(vty, " ("); - else + list_began = true; + } else vty_out(vty, ", "); vty_out(vty, "%s", bpm->ipset_name); - unit++; } - if (unit) + if (list_began) vty_out(vty, ")"); vty_out(vty, "\n"); list_delete_and_null(&list_bpm); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 041049d05b..eedfe7503e 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -198,8 +198,7 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra) bgp_unlock(e->bgp_orig); if ((*extra)->bgp_fs_pbr) - list_delete_all_node((*extra)->bgp_fs_pbr); - (*extra)->bgp_fs_pbr = NULL; + list_delete_and_null(&((*extra)->bgp_fs_pbr)); XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra); *extra = NULL; From 5a430eee9ac745da9ea2116ea95a080d485a41f9 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Tue, 21 Aug 2018 10:38:27 +0200 Subject: [PATCH 16/66] bgpd: simplify fs add pbr entry Simplify the fs pbr entry creation. Signed-off-by: Philippe Guibert --- bgpd/bgp_pbr.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index 129c143a64..8faab9735a 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -1807,7 +1807,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, bgp_pbr_match_alloc_intern); /* new, then self allocate ipset_name and unique */ - if (bpm && bpm->unique == 0) { + if (bpm->unique == 0) { bpm->unique = ++bgp_pbr_match_counter_unique; /* 0 value is forbidden */ sprintf(bpm->ipset_name, "match%p", bpm); @@ -1838,10 +1838,9 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, temp2.src_port_max = src_port ? src_port->max_port : 0; temp2.dst_port_max = dst_port ? dst_port->max_port : 0; temp2.proto = bpf->protocol; - if (bpm) - bpme = hash_get(bpm->entry_hash, &temp2, - bgp_pbr_match_entry_alloc_intern); - if (bpme && bpme->unique == 0) { + bpme = hash_get(bpm->entry_hash, &temp2, + bgp_pbr_match_entry_alloc_intern); + if (bpme->unique == 0) { bpme->unique = ++bgp_pbr_match_entry_counter_unique; /* 0 value is forbidden */ bpme->backpointer = bpm; @@ -1853,7 +1852,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, bpme_found = true; /* already installed */ - if (bpme_found && bpme) { + if (bpme_found) { struct bgp_info_extra *extra = bgp_info_extra_get(binfo); if (extra && extra->bgp_fs_pbr && From 45837bc40dcf64ea3f99e7838abc0a580a4e8ca8 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Tue, 21 Aug 2018 10:43:33 +0200 Subject: [PATCH 17/66] bgpd: pbr entry log message changed to zlog_debug pbr entry log message changed to zlog_debug. Signed-off-by: Philippe Guibert --- bgpd/bgp_pbr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index 8faab9735a..b182fde1e2 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -1680,7 +1680,7 @@ static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add) ? "!" : "", bpf->dscp->val); } - zlog_info("BGP: %s FS PBR from %s to %s, %s %s", + zlog_debug("BGP: %s FS PBR from %s to %s, %s %s", add ? "adding" : "removing", bpf->src == NULL ? "" : prefix2str(bpf->src, bufsrc, sizeof(bufsrc)), From bd27ea43e9972d1c8ae794441fd2db83a8d896fc Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 15 Aug 2018 05:49:29 +0200 Subject: [PATCH 18/66] build: wrap "fallthrough" attr This generates a warning on gcc versions before 7.0. Signed-off-by: David Lamparter --- lib/compiler.h | 9 +++++++++ tests/bgpd/test_capability.c | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/compiler.h b/lib/compiler.h index b19c33f65e..24b8fafd10 100644 --- a/lib/compiler.h +++ b/lib/compiler.h @@ -24,6 +24,9 @@ #if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5) # define _RET_NONNULL , returns_nonnull #endif +#if __has_attribute(fallthrough) +# define _FALLTHROUGH __attribute__((fallthrough)); +#endif # define _CONSTRUCTOR(x) constructor(x) #elif defined(__GNUC__) #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9) @@ -34,6 +37,9 @@ # define _DESTRUCTOR(x) destructor(x) # define _ALLOC_SIZE(x) alloc_size(x) #endif +#if __GNUC__ >= 7 +# define _FALLTHROUGH __attribute__((fallthrough)); +#endif #endif #ifdef __sun @@ -55,6 +61,9 @@ #ifndef _ALLOC_SIZE # define _ALLOC_SIZE(x) #endif +#ifndef _FALLTHROUGH +#define _FALLTHROUGH +#endif /* * for warnings on macros, put in the macro content like this: diff --git a/tests/bgpd/test_capability.c b/tests/bgpd/test_capability.c index 4612bdc26b..fef7d39ff5 100644 --- a/tests/bgpd/test_capability.c +++ b/tests/bgpd/test_capability.c @@ -821,7 +821,7 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type) switch (type) { case CAPABILITY: len += 2; /* to cover the OPT-Param header */ - __attribute__ ((fallthrough)); + _FALLTHROUGH case OPT_PARAM: printf("len: %u\n", len); /* peek_for_as4 wants getp at capibility*/ From a2dc7057e0bd3a5f5c28de9896bf905e6dd5eb4b Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 18 Aug 2018 04:33:38 +0200 Subject: [PATCH 19/66] *: fix gcc-8 format-overflow warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit e.g. pimd/pim_oil.c: In function ‘pim_channel_oil_dump’: pimd/pim_oil.c:51:19: error: ‘%d’ directive writing between 1 and 11 bytes into a region of size 10 [-Werror=format-overflow=] Build on gcc-8.2.0 is warning-free after this patch. Signed-off-by: David Lamparter --- bgpd/bgp_flowspec.c | 2 +- pimd/pim_cmd.c | 4 ++-- pimd/pim_oil.c | 11 ++++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c index 6695596c6f..e29508bf36 100644 --- a/bgpd/bgp_flowspec.c +++ b/bgpd/bgp_flowspec.c @@ -148,7 +148,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, if (BGP_DEBUG(flowspec, FLOWSPEC)) { char return_string[BGP_FLOWSPEC_NLRI_STRING_MAX]; - char local_string[BGP_FLOWSPEC_NLRI_STRING_MAX * 2]; + char local_string[BGP_FLOWSPEC_NLRI_STRING_MAX*2+16]; char ec_string[BGP_FLOWSPEC_NLRI_STRING_MAX]; char *s = NULL; diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 7c45ce261a..611d8d3681 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -323,8 +323,8 @@ static void pim_show_assert_winner_metric_helper(struct vty *vty, char addr_str[INET_ADDRSTRLEN]; struct pim_assert_metric *am; struct in_addr ifaddr; - char pref_str[5]; - char metr_str[7]; + char pref_str[16]; + char metr_str[16]; ifaddr = pim_ifp->primary_address; diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index f0f336fb73..a0debc0c78 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -37,19 +37,20 @@ char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size) { + char *out; struct prefix_sg sg; int i; sg.src = c_oil->oil.mfcc_origin; sg.grp = c_oil->oil.mfcc_mcastgrp; - sprintf(buf, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg), - c_oil->oil.mfcc_parent); + snprintf(buf, size, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg), + c_oil->oil.mfcc_parent); + out = buf + strlen(buf); for (i = 0; i < MAXVIFS; i++) { if (c_oil->oil.mfcc_ttls[i] != 0) { - char buf1[10]; - sprintf(buf1, "%d ", i); - strcat(buf, buf1); + snprintf(out, buf + size - out, "%d ", i); + out += strlen(out); } } From 0e70e6c89d69976cde1b79bba6ac23d233b19566 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 18 Aug 2018 04:47:27 +0200 Subject: [PATCH 20/66] lib/bgpd: re-fix bgp_info_extra_free() Make the wart slightly less bad... also there is still a possible write after free here. This needs to be fixed again, properly, by some structure changes. Signed-off-by: David Lamparter --- bgpd/bgp_route.c | 20 ++++++++++++++++++-- bgpd/bgp_table.h | 4 ++-- lib/table.h | 8 ++------ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 041049d05b..bf97e26230 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -188,8 +188,24 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra) if (e->parent) { struct bgp_info *bi = (struct bgp_info *)e->parent; - if (bi->net) - bi->net = bgp_unlock_node((struct bgp_node *)bi->net); + if (bi->net) { + /* FIXME: since multiple e may have the same e->parent + * and e->parent->net is holding a refcount for each + * of them, we need to do some fudging here. + * + * WARNING: if bi->net->lock drops to 0, bi may be + * freed as well (because bi->net was holding the + * last reference to bi) => write after free! + */ + unsigned refcount; + + bi = bgp_info_lock(bi); + refcount = bi->net->lock - 1; + bgp_unlock_node((struct bgp_node *)bi->net); + if (!refcount) + bi->net = NULL; + bgp_info_unlock(bi); + } bgp_info_unlock(e->parent); e->parent = NULL; } diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index f7eac09546..60c2cbd4a4 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -128,9 +128,9 @@ static inline struct bgp_node *bgp_node_parent_nolock(struct bgp_node *node) /* * bgp_unlock_node */ -static inline struct bgp_node *bgp_unlock_node(struct bgp_node *node) +static inline void bgp_unlock_node(struct bgp_node *node) { - return (struct bgp_node *)route_unlock_node(bgp_node_to_rnode(node)); + route_unlock_node(bgp_node_to_rnode(node)); } /* diff --git a/lib/table.h b/lib/table.h index ac7df3e695..8304abe59b 100644 --- a/lib/table.h +++ b/lib/table.h @@ -235,17 +235,13 @@ static inline struct route_node *route_lock_node(struct route_node *node) } /* Unlock node. */ -static inline struct route_node *route_unlock_node(struct route_node *node) +static inline void route_unlock_node(struct route_node *node) { assert(node->lock > 0); (*(unsigned *)&node->lock)--; - if (node->lock == 0) { + if (node->lock == 0) route_node_delete(node); - return NULL; - } - - return node; } /* From e83f3b316a3a582f31031c9eba0273259a155711 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 22 Aug 2018 00:00:32 -0700 Subject: [PATCH 21/66] pimd: Fix pim_mroute_del crash while terminating pimd When pimd is getting terminated, pim_upstream_del() gets called as part of cleaning process. pim_upstream_del() deletes the route and assigns NULL to the up->channel_oil. It also deletes each if_channel by calling the function pim_ifchannel_delete(). pim_ifchannel_delete() internally calls the caller function pim_upstream_del(), if it is the last ifchannel for that upstream. So pim_upstream_del is getting called twice, which will access the up->channel_oil which was already set to NULL before. This results in crash. Fix: pim_ifchannel_delete() should call pim_upstream_del (caller function) only if the up->ref_count > 0. Added an assert(up->ref_count > 0) in the function pim_upstream_del(). Signed-off-by: Sarita Patra --- pimd/pim_ifchannel.c | 11 ++++++++++- pimd/pim_upstream.c | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 92a78c4bb4..3137345037 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -174,7 +174,16 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch) ifchannel list is empty before deleting upstream_del ref count will take care of it. */ - pim_upstream_del(pim_ifp->pim, ch->upstream, __PRETTY_FUNCTION__); + if (ch->upstream->ref_count > 0) + pim_upstream_del(pim_ifp->pim, ch->upstream, + __PRETTY_FUNCTION__); + + else + zlog_warn("%s: Avoiding deletion of upstream with ref_count %d " + "from ifchannel(%s): %s", __PRETTY_FUNCTION__, + ch->upstream->ref_count, ch->interface->name, + ch->sg_str); + ch->upstream = NULL; THREAD_OFF(ch->t_ifjoin_expiry_timer); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index db89125a98..15cbf6fbc3 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -167,6 +167,8 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim, up->ref_count, up->flags, up->channel_oil->oil_ref_count); + assert(up->ref_count > 0); + --up->ref_count; if (up->ref_count >= 1) From 3d4c0b49dacb454dbcf4dc3b56f8ccd8bb5202e5 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Wed, 22 Aug 2018 09:19:04 +0200 Subject: [PATCH 22/66] lib: change vrf_is_mapped_on_netns API The function handles not a vrf pointer instead of a vrf_id value. Signed-off-by: Philippe Guibert --- bgpd/bgp_network.c | 3 ++- lib/if.c | 3 ++- lib/vrf.c | 6 ++---- lib/vrf.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 0664fdfd1c..22d5d35c82 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -672,7 +672,8 @@ static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen, listener->fd = sock; /* this socket needs a change of ns. record bgp back pointer */ - if (bgp->vrf_id != VRF_DEFAULT && vrf_is_mapped_on_netns(bgp->vrf_id)) + if (bgp->vrf_id != VRF_DEFAULT && vrf_is_mapped_on_netns( + vrf_lookup_by_id(bgp->vrf_id))) listener->bgp = bgp; memcpy(&listener->su, sa, salen); diff --git a/lib/if.c b/lib/if.c index 6023624dc1..11c4f1b5dc 100644 --- a/lib/if.c +++ b/lib/if.c @@ -393,7 +393,8 @@ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id, int vty) * this should not be considered as an update * then create the new interface */ - if (ifp->vrf_id != vrf_id && vrf_is_mapped_on_netns(vrf_id)) + if (ifp->vrf_id != vrf_id && vrf_is_mapped_on_netns( + vrf_lookup_by_id(vrf_id))) return if_create(name, vrf_id); /* If it came from the kernel * or by way of zclient, believe it and update diff --git a/lib/vrf.c b/lib/vrf.c index 36111dfeae..3c7342bb98 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -682,10 +682,8 @@ int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname, return CMD_SUCCESS; } -int vrf_is_mapped_on_netns(vrf_id_t vrf_id) +int vrf_is_mapped_on_netns(struct vrf *vrf) { - struct vrf *vrf = vrf_lookup_by_id(vrf_id); - if (!vrf || vrf->data.l.netns_name[0] == '\0') return 0; if (vrf->vrf_id == VRF_DEFAULT) @@ -887,7 +885,7 @@ int vrf_bind(vrf_id_t vrf_id, int fd, char *name) if (fd < 0 || name == NULL) return fd; - if (vrf_is_mapped_on_netns(vrf_id)) + if (vrf_is_mapped_on_netns(vrf_lookup_by_id(vrf_id))) return fd; #ifdef SO_BINDTODEVICE ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)+1); diff --git a/lib/vrf.h b/lib/vrf.h index 0f4f36be50..56ba101ff0 100644 --- a/lib/vrf.h +++ b/lib/vrf.h @@ -237,7 +237,7 @@ extern vrf_id_t vrf_get_default_id(void); #define VRF_DEFAULT vrf_get_default_id() /* VRF is mapped on netns or not ? */ -int vrf_is_mapped_on_netns(vrf_id_t vrf_id); +int vrf_is_mapped_on_netns(struct vrf *vrf); /* VRF switch from NETNS */ extern int vrf_switch_to_netns(vrf_id_t vrf_id); From f69f6f56f58bbbfd069fa8dd108e04aec6caf623 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Wed, 22 Aug 2018 09:19:50 +0200 Subject: [PATCH 23/66] staticd: remove usage of vrf_is_backend_netns in staticd this function had to be used only inside zebra ( this was written in the header vrf.h). To keep the functionality, a more generic API is used. Signed-off-by: Philippe Guibert --- staticd/static_vty.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/staticd/static_vty.c b/staticd/static_vty.c index 98153f7149..771d8d1de3 100644 --- a/staticd/static_vty.c +++ b/staticd/static_vty.c @@ -766,7 +766,7 @@ DEFPY(ip_route_blackhole, "Table to configure\n" "The table number to configure\n") { - if (table_str && !vrf_is_backend_netns()) { + if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -805,7 +805,7 @@ DEFPY(ip_route_blackhole_vrf, VTY_DECLVAR_CONTEXT(vrf, vrf); struct static_vrf *svrf = vrf->info; - if (table_str && !vrf_is_backend_netns()) { + if (table_str && !vrf_is_mapped_on_netns(vrf)) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -868,7 +868,7 @@ DEFPY(ip_route_address_interface, return CMD_WARNING_CONFIG_FAILED; } - if (table_str && !vrf_is_backend_netns()) { + if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -924,7 +924,7 @@ DEFPY(ip_route_address_interface_vrf, struct static_vrf *svrf = vrf->info; struct static_vrf *nh_svrf; - if (table_str && !vrf_is_backend_netns()) { + if (table_str && !vrf_is_mapped_on_netns(vrf)) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -984,7 +984,7 @@ DEFPY(ip_route, struct static_vrf *nh_svrf; const char *flag = NULL; - if (table_str && !vrf_is_backend_netns()) { + if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1049,7 +1049,7 @@ DEFPY(ip_route_vrf, struct static_vrf *nh_svrf; const char *flag = NULL; - if (table_str && !vrf_is_backend_netns()) { + if (table_str && !vrf_is_mapped_on_netns(vrf)) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1104,7 +1104,7 @@ DEFPY(ipv6_route_blackhole, "Table to configure\n" "The table number to configure\n") { - if (table_str && !vrf_is_backend_netns()) { + if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1144,7 +1144,7 @@ DEFPY(ipv6_route_blackhole_vrf, VTY_DECLVAR_CONTEXT(vrf, vrf); struct static_vrf *svrf = vrf->info; - if (table_str && !vrf_is_backend_netns()) { + if (table_str && !vrf_is_mapped_on_netns(vrf)) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1195,7 +1195,7 @@ DEFPY(ipv6_route_address_interface, struct static_vrf *svrf; struct static_vrf *nh_svrf; - if (table_str && !vrf_is_backend_netns()) { + if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1255,7 +1255,7 @@ DEFPY(ipv6_route_address_interface_vrf, struct static_vrf *svrf = vrf->info; struct static_vrf *nh_svrf; - if (table_str && !vrf_is_backend_netns()) { + if (table_str && !vrf_is_mapped_on_netns(vrf)) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1309,7 +1309,7 @@ DEFPY(ipv6_route, struct static_vrf *svrf; struct static_vrf *nh_svrf; - if (table_str && !vrf_is_backend_netns()) { + if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1368,7 +1368,7 @@ DEFPY(ipv6_route_vrf, struct static_vrf *svrf = vrf->info; struct static_vrf *nh_svrf; - if (table_str && !vrf_is_backend_netns()) { + if (table_str && !vrf_is_mapped_on_netns(vrf)) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; From 31d4a8e5f0dab3bec0de4dfed626ae8469e86398 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Wed, 22 Aug 2018 10:04:06 +0200 Subject: [PATCH 24/66] staticd: do not forget to set table id marker on zebra message Table identifier is not read if table id marker is not set. Signed-off-by: Philippe Guibert --- staticd/static_zebra.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index f3175e91fa..2ea4667e07 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -273,8 +273,10 @@ extern void static_zebra_route_add(struct route_node *rn, SET_FLAG(api.message, ZAPI_MESSAGE_TAG); api.tag = si_changed->tag; } - api.tableid = si_changed->table_id; - + if (si_changed->table_id != 0) { + SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID); + api.tableid = si_changed->table_id; + } zlog_debug("Distance sent down: %d %d", si_changed->distance, install); for (/*loaded above*/; si; si = si->next) { api_nh = &api.nexthops[nh_num]; From 7a2c24df0219229baeb80b334029611d449c75ad Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Wed, 22 Aug 2018 10:04:49 +0200 Subject: [PATCH 25/66] static: remove useless debug variable Signed-off-by: Philippe Guibert --- staticd/static_zebra.c | 1 - 1 file changed, 1 deletion(-) diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index 2ea4667e07..56ba70eaf8 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -277,7 +277,6 @@ extern void static_zebra_route_add(struct route_node *rn, SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID); api.tableid = si_changed->table_id; } - zlog_debug("Distance sent down: %d %d", si_changed->distance, install); for (/*loaded above*/; si; si = si->next) { api_nh = &api.nexthops[nh_num]; if (si->nh_vrf_id == VRF_UNKNOWN) From 4388866917c8766832346c6fddceb86ec7e34a19 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 21 Aug 2018 20:06:27 -0400 Subject: [PATCH 26/66] lib: Add stream_resize_orig and stream_resize_inplace Start setup for handling of stream_resize into old and new functions. Create a stream_resize_inplace function that takes a double pointer to allow for a realloc operation to return the possibly moved pointer. Add a CONFDATE for removal as well. Signed-off-by: Donald Sharp --- lib/stream.c | 7 ++++++- lib/stream.h | 9 ++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/stream.c b/lib/stream.c index cf9af4d3bb..50ee9a5d56 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -166,7 +166,12 @@ struct stream *stream_dupcat(struct stream *s1, struct stream *s2, return new; } -size_t stream_resize(struct stream *s, size_t newsize) +size_t stream_resize_inplace(struct stream **sptr, size_t newsize) +{ + return stream_resize_orig(*sptr, newsize); +} + +size_t stream_resize_orig(struct stream *s, size_t newsize) { uint8_t *newdata; STREAM_VERIFY_SANE(s); diff --git a/lib/stream.h b/lib/stream.h index e808f039c6..e8cd76362e 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -154,7 +154,14 @@ extern struct stream *stream_new(size_t); extern void stream_free(struct stream *); extern struct stream *stream_copy(struct stream *, struct stream *src); extern struct stream *stream_dup(struct stream *); -extern size_t stream_resize(struct stream *, size_t); + +#if CONFDATE > 20190821 +CPP_NOTICE("lib: time to remove stream_resize_orig") +#endif +extern size_t stream_resize_orig(struct stream *s, size_t newsize); +#define stream_resize stream_resize_orig +extern size_t stream_resize_inplace(struct stream **sptr, size_t newsize); + extern size_t stream_get_getp(struct stream *); extern size_t stream_get_endp(struct stream *); extern size_t stream_get_size(struct stream *); From db3c830afe3017eb2bc6f972e10404547c1a5d69 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 21 Aug 2018 20:22:28 -0400 Subject: [PATCH 27/66] isisd, ospfd, tests: Switch to using stream_resize_inplace Switch code and tests to use new stream_resize_inplace functionality. Signed-off-by: Donald Sharp --- isisd/isis_circuit.c | 2 +- ospfd/ospf_lsa.c | 48 +++++++++++++++++++++-------------------- tests/lib/test_stream.c | 2 +- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 7cf83f20fa..cd4b76139f 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -536,7 +536,7 @@ void isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream) *stream = stream_new(stream_size); } else { if (STREAM_SIZE(*stream) != stream_size) - stream_resize(*stream, stream_size); + stream_resize_inplace(stream, stream_size); stream_reset(*stream); } } diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 47d8b2f57a..7c8a68994f 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -416,7 +416,7 @@ static uint16_t ospf_link_cost(struct ospf_interface *oi) } /* Set a link information. */ -static char link_info_set(struct stream *s, struct in_addr id, +static char link_info_set(struct stream **s, struct in_addr id, struct in_addr data, uint8_t type, uint8_t tos, uint16_t cost) { @@ -425,11 +425,11 @@ static char link_info_set(struct stream *s, struct in_addr id, * more. * we try accomodate those here. */ - if (STREAM_WRITEABLE(s) < OSPF_ROUTER_LSA_LINK_SIZE) { + if (STREAM_WRITEABLE(*s) < OSPF_ROUTER_LSA_LINK_SIZE) { size_t ret = OSPF_MAX_LSA_SIZE; /* Can we enlarge the stream still? */ - if (STREAM_SIZE(s) == OSPF_MAX_LSA_SIZE) { + if (STREAM_SIZE(*s) == OSPF_MAX_LSA_SIZE) { /* we futz the size here for simplicity, really we need * to account * for just: @@ -441,30 +441,31 @@ static char link_info_set(struct stream *s, struct in_addr id, * * Simpler just to subtract OSPF_MAX_LSA_SIZE though. */ - ret = stream_resize( + ret = stream_resize_inplace( s, OSPF_MAX_PACKET_SIZE - OSPF_MAX_LSA_SIZE); } if (ret == OSPF_MAX_LSA_SIZE) { zlog_warn( "%s: Out of space in LSA stream, left %zd, size %zd", - __func__, STREAM_WRITEABLE(s), STREAM_SIZE(s)); + __func__, STREAM_WRITEABLE(*s), + STREAM_SIZE(*s)); return 0; } } /* TOS based routing is not supported. */ - stream_put_ipv4(s, id.s_addr); /* Link ID. */ - stream_put_ipv4(s, data.s_addr); /* Link Data. */ - stream_putc(s, type); /* Link Type. */ - stream_putc(s, tos); /* TOS = 0. */ - stream_putw(s, cost); /* Link Cost. */ + stream_put_ipv4(*s, id.s_addr); /* Link ID. */ + stream_put_ipv4(*s, data.s_addr); /* Link Data. */ + stream_putc(*s, type); /* Link Type. */ + stream_putc(*s, tos); /* TOS = 0. */ + stream_putw(*s, cost); /* Link Cost. */ return 1; } /* Describe Point-to-Point link (Section 12.4.1.1). */ -static int lsa_link_ptop_set(struct stream *s, struct ospf_interface *oi) +static int lsa_link_ptop_set(struct stream **s, struct ospf_interface *oi) { int links = 0; struct ospf_neighbor *nbr; @@ -510,7 +511,7 @@ static int lsa_link_ptop_set(struct stream *s, struct ospf_interface *oi) } /* Describe Broadcast Link. */ -static int lsa_link_broadcast_set(struct stream *s, struct ospf_interface *oi) +static int lsa_link_broadcast_set(struct stream **s, struct ospf_interface *oi) { struct ospf_neighbor *dr; struct in_addr id, mask; @@ -556,7 +557,7 @@ static int lsa_link_broadcast_set(struct stream *s, struct ospf_interface *oi) } } -static int lsa_link_loopback_set(struct stream *s, struct ospf_interface *oi) +static int lsa_link_loopback_set(struct stream **s, struct ospf_interface *oi) { struct in_addr id, mask; @@ -570,7 +571,8 @@ static int lsa_link_loopback_set(struct stream *s, struct ospf_interface *oi) } /* Describe Virtual Link. */ -static int lsa_link_virtuallink_set(struct stream *s, struct ospf_interface *oi) +static int lsa_link_virtuallink_set(struct stream **s, + struct ospf_interface *oi) { struct ospf_neighbor *nbr; uint16_t cost = ospf_link_cost(oi); @@ -593,7 +595,7 @@ static int lsa_link_virtuallink_set(struct stream *s, struct ospf_interface *oi) 12.4.1.4.*/ /* from "edward rrr" http://marc.theaimsgroup.com/?l=zebra&m=100739222210507&w=2 */ -static int lsa_link_ptomp_set(struct stream *s, struct ospf_interface *oi) +static int lsa_link_ptomp_set(struct stream **s, struct ospf_interface *oi) { int links = 0; struct route_node *rn; @@ -634,7 +636,7 @@ static int lsa_link_ptomp_set(struct stream *s, struct ospf_interface *oi) } /* Set router-LSA link information. */ -static int router_lsa_link_set(struct stream *s, struct ospf_area *area) +static int router_lsa_link_set(struct stream **s, struct ospf_area *area) { struct listnode *node; struct ospf_interface *oi; @@ -677,28 +679,28 @@ static int router_lsa_link_set(struct stream *s, struct ospf_area *area) } /* Set router-LSA body. */ -static void ospf_router_lsa_body_set(struct stream *s, struct ospf_area *area) +static void ospf_router_lsa_body_set(struct stream **s, struct ospf_area *area) { unsigned long putp; uint16_t cnt; /* Set flags. */ - stream_putc(s, router_lsa_flags(area)); + stream_putc(*s, router_lsa_flags(area)); /* Set Zero fields. */ - stream_putc(s, 0); + stream_putc(*s, 0); /* Keep pointer to # links. */ - putp = stream_get_endp(s); + putp = stream_get_endp(*s); /* Forward word */ - stream_putw(s, 0); + stream_putw(*s, 0); /* Set all link information. */ cnt = router_lsa_link_set(s, area); /* Set # of links here. */ - stream_putw_at(s, putp, cnt); + stream_putw_at(*s, putp, cnt); } static int ospf_stub_router_timer(struct thread *t) @@ -783,7 +785,7 @@ static struct ospf_lsa *ospf_router_lsa_new(struct ospf_area *area) OSPF_ROUTER_LSA, ospf->router_id, ospf->router_id); /* Set router-LSA body fields. */ - ospf_router_lsa_body_set(s, area); + ospf_router_lsa_body_set(&s, area); /* Set length. */ length = stream_get_endp(s); diff --git a/tests/lib/test_stream.c b/tests/lib/test_stream.c index 5dc751a1b2..2ecfc87942 100644 --- a/tests/lib/test_stream.c +++ b/tests/lib/test_stream.c @@ -57,7 +57,7 @@ int main(void) print_stream(s); - stream_resize(s, stream_get_endp(s)); + stream_resize_inplace(&s, stream_get_endp(s)); print_stream(s); From de75223eafe083d4d6c82155a6bf8b328f806634 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 21 Aug 2018 20:34:42 -0400 Subject: [PATCH 28/66] lib: Convert stream_new to use one malloc Modify stream.c to have stream_new call one malloc call instead of two. Also change stream_resize_orig to use stream_resize_inplace and to send an error to the developer to switch over. Signed-off-by: Donald Sharp --- lib/stream.c | 48 +++++++++++++++++++++++------------------------- lib/stream.h | 11 ++++++----- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/lib/stream.c b/lib/stream.c index 50ee9a5d56..55e7f64358 100644 --- a/lib/stream.c +++ b/lib/stream.c @@ -28,9 +28,9 @@ #include "network.h" #include "prefix.h" #include "log.h" +#include "lib_errors.h" DEFINE_MTYPE_STATIC(LIB, STREAM, "Stream") -DEFINE_MTYPE_STATIC(LIB, STREAM_DATA, "Stream data") DEFINE_MTYPE_STATIC(LIB, STREAM_FIFO, "Stream FIFO") /* Tests whether a position is valid */ @@ -100,9 +100,7 @@ struct stream *stream_new(size_t size) assert(size > 0); - s = XMALLOC(MTYPE_STREAM, sizeof(struct stream)); - - s->data = XMALLOC(MTYPE_STREAM_DATA, size); + s = XMALLOC(MTYPE_STREAM, sizeof(struct stream) + size); s->getp = s->endp = 0; s->next = NULL; @@ -116,7 +114,6 @@ void stream_free(struct stream *s) if (!s) return; - XFREE(MTYPE_STREAM_DATA, s->data); XFREE(MTYPE_STREAM, s); } @@ -168,30 +165,31 @@ struct stream *stream_dupcat(struct stream *s1, struct stream *s2, size_t stream_resize_inplace(struct stream **sptr, size_t newsize) { - return stream_resize_orig(*sptr, newsize); + struct stream *orig = *sptr; + + STREAM_VERIFY_SANE(orig); + + orig = XREALLOC(MTYPE_STREAM, orig, sizeof(struct stream) + newsize); + + orig->size = newsize; + + if (orig->endp > orig->size) + orig->endp = orig->size; + if (orig->getp > orig->endp) + orig->getp = orig->endp; + + STREAM_VERIFY_SANE(orig); + + *sptr = orig; + return orig->size; } -size_t stream_resize_orig(struct stream *s, size_t newsize) +size_t __attribute__((deprecated))stream_resize_orig(struct stream *s, + size_t newsize) { - uint8_t *newdata; - STREAM_VERIFY_SANE(s); + assert("stream_resize: Switch code to use stream_resize_inplace" == NULL); - newdata = XREALLOC(MTYPE_STREAM_DATA, s->data, newsize); - - if (newdata == NULL) - return s->size; - - s->data = newdata; - s->size = newsize; - - if (s->endp > s->size) - s->endp = s->size; - if (s->getp > s->endp) - s->getp = s->endp; - - STREAM_VERIFY_SANE(s); - - return s->size; + return stream_resize_inplace(&s, newsize); } size_t stream_get_getp(struct stream *s) diff --git a/lib/stream.h b/lib/stream.h index e8cd76362e..ef9366e1ae 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -98,14 +98,15 @@ struct stream { struct stream *next; - /* Remainder is ***private*** to stream + /* + * Remainder is ***private*** to stream * direct access is frowned upon! * Use the appropriate functions/macros */ - size_t getp; /* next get position */ - size_t endp; /* last valid data position */ - size_t size; /* size of data segment */ - unsigned char *data; /* data pointer */ + size_t getp; /* next get position */ + size_t endp; /* last valid data position */ + size_t size; /* size of data segment */ + unsigned char data[0]; /* data pointer */ }; /* First in first out queue structure. */ From e923dd62ef715147a3e0d28a8e9dccb9371defcb Mon Sep 17 00:00:00 2001 From: kssoman Date: Wed, 22 Aug 2018 05:00:15 -0700 Subject: [PATCH 29/66] bgpd : Change of options in redistribute command does not get applied * Added parameter in bgp_redistribute_set() to indicate change in redistribute option * If there is change, call bgp_redistribute_unreg() to withdraw routes Signed-off-by: kssoman --- bgpd/bgp_vty.c | 83 +++++++++++++++++++++++++++++------------------- bgpd/bgp_zebra.c | 8 ++++- bgpd/bgp_zebra.h | 3 +- 3 files changed, 59 insertions(+), 35 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index e3efbbf252..69e3de3b2a 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -11460,7 +11460,7 @@ DEFUN (bgp_redistribute_ipv4, } bgp_redist_add(bgp, AFI_IP, type, 0); - return bgp_redistribute_set(bgp, AFI_IP, type, 0); + return bgp_redistribute_set(bgp, AFI_IP, type, 0, false); } ALIAS_HIDDEN( @@ -11481,6 +11481,7 @@ DEFUN (bgp_redistribute_ipv4_rmap, int idx_word = 3; int type; struct bgp_redist *red; + bool changed; type = proto_redistnum(AFI_IP, argv[idx_protocol]->text); if (type < 0) { @@ -11489,8 +11490,8 @@ DEFUN (bgp_redistribute_ipv4_rmap, } red = bgp_redist_add(bgp, AFI_IP, type, 0); - bgp_redistribute_rmap_set(red, argv[idx_word]->arg); - return bgp_redistribute_set(bgp, AFI_IP, type, 0); + changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed); } ALIAS_HIDDEN( @@ -11514,6 +11515,7 @@ DEFUN (bgp_redistribute_ipv4_metric, int type; uint32_t metric; struct bgp_redist *red; + bool changed; type = proto_redistnum(AFI_IP, argv[idx_protocol]->text); if (type < 0) { @@ -11523,8 +11525,8 @@ DEFUN (bgp_redistribute_ipv4_metric, metric = strtoul(argv[idx_number]->arg, NULL, 10); red = bgp_redist_add(bgp, AFI_IP, type, 0); - bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric); - return bgp_redistribute_set(bgp, AFI_IP, type, 0); + changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric); + return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed); } ALIAS_HIDDEN( @@ -11551,6 +11553,7 @@ DEFUN (bgp_redistribute_ipv4_rmap_metric, int type; uint32_t metric; struct bgp_redist *red; + bool changed; type = proto_redistnum(AFI_IP, argv[idx_protocol]->text); if (type < 0) { @@ -11560,9 +11563,9 @@ DEFUN (bgp_redistribute_ipv4_rmap_metric, metric = strtoul(argv[idx_number]->arg, NULL, 10); red = bgp_redist_add(bgp, AFI_IP, type, 0); - bgp_redistribute_rmap_set(red, argv[idx_word]->arg); - bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric); - return bgp_redistribute_set(bgp, AFI_IP, type, 0); + changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric); + return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed); } ALIAS_HIDDEN( @@ -11593,6 +11596,7 @@ DEFUN (bgp_redistribute_ipv4_metric_rmap, int type; uint32_t metric; struct bgp_redist *red; + bool changed; type = proto_redistnum(AFI_IP, argv[idx_protocol]->text); if (type < 0) { @@ -11602,9 +11606,9 @@ DEFUN (bgp_redistribute_ipv4_metric_rmap, metric = strtoul(argv[idx_number]->arg, NULL, 10); red = bgp_redist_add(bgp, AFI_IP, type, 0); - bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric); - bgp_redistribute_rmap_set(red, argv[idx_word]->arg); - return bgp_redistribute_set(bgp, AFI_IP, type, 0); + changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric); + changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed); } ALIAS_HIDDEN( @@ -11640,7 +11644,7 @@ DEFUN (bgp_redistribute_ipv4_ospf, protocol = ZEBRA_ROUTE_TABLE; bgp_redist_add(bgp, AFI_IP, protocol, instance); - return bgp_redistribute_set(bgp, AFI_IP, protocol, instance); + return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, false); } ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf, bgp_redistribute_ipv4_ospf_hidden_cmd, @@ -11667,6 +11671,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap, struct bgp_redist *red; unsigned short instance; int protocol; + bool changed; if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) protocol = ZEBRA_ROUTE_OSPF; @@ -11675,8 +11680,8 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap, instance = strtoul(argv[idx_number]->arg, NULL, 10); red = bgp_redist_add(bgp, AFI_IP, protocol, instance); - bgp_redistribute_rmap_set(red, argv[idx_word]->arg); - return bgp_redistribute_set(bgp, AFI_IP, protocol, instance); + changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed); } ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_rmap, @@ -11707,6 +11712,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric, struct bgp_redist *red; unsigned short instance; int protocol; + bool changed; if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) protocol = ZEBRA_ROUTE_OSPF; @@ -11717,8 +11723,9 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric, metric = strtoul(argv[idx_number_2]->arg, NULL, 10); red = bgp_redist_add(bgp, AFI_IP, protocol, instance); - bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric); - return bgp_redistribute_set(bgp, AFI_IP, protocol, instance); + changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, + metric); + return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed); } ALIAS_HIDDEN(bgp_redistribute_ipv4_ospf_metric, @@ -11752,6 +11759,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric, struct bgp_redist *red; unsigned short instance; int protocol; + bool changed; if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) protocol = ZEBRA_ROUTE_OSPF; @@ -11762,9 +11770,10 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric, metric = strtoul(argv[idx_number_2]->arg, NULL, 10); red = bgp_redist_add(bgp, AFI_IP, protocol, instance); - bgp_redistribute_rmap_set(red, argv[idx_word]->arg); - bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric); - return bgp_redistribute_set(bgp, AFI_IP, protocol, instance); + changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, + metric); + return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed); } ALIAS_HIDDEN( @@ -11801,6 +11810,7 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap, struct bgp_redist *red; unsigned short instance; int protocol; + bool changed; if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) protocol = ZEBRA_ROUTE_OSPF; @@ -11811,9 +11821,10 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap, metric = strtoul(argv[idx_number_2]->arg, NULL, 10); red = bgp_redist_add(bgp, AFI_IP, protocol, instance); - bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric); - bgp_redistribute_rmap_set(red, argv[idx_word]->arg); - return bgp_redistribute_set(bgp, AFI_IP, protocol, instance); + changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, + metric); + changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed); } ALIAS_HIDDEN( @@ -11921,7 +11932,7 @@ DEFUN (bgp_redistribute_ipv6, } bgp_redist_add(bgp, AFI_IP6, type, 0); - return bgp_redistribute_set(bgp, AFI_IP6, type, 0); + return bgp_redistribute_set(bgp, AFI_IP6, type, 0, false); } DEFUN (bgp_redistribute_ipv6_rmap, @@ -11937,6 +11948,7 @@ DEFUN (bgp_redistribute_ipv6_rmap, int idx_word = 3; int type; struct bgp_redist *red; + bool changed; type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); if (type < 0) { @@ -11945,8 +11957,8 @@ DEFUN (bgp_redistribute_ipv6_rmap, } red = bgp_redist_add(bgp, AFI_IP6, type, 0); - bgp_redistribute_rmap_set(red, argv[idx_word]->arg); - return bgp_redistribute_set(bgp, AFI_IP6, type, 0); + changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed); } DEFUN (bgp_redistribute_ipv6_metric, @@ -11963,6 +11975,7 @@ DEFUN (bgp_redistribute_ipv6_metric, int type; uint32_t metric; struct bgp_redist *red; + bool changed; type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); if (type < 0) { @@ -11972,8 +11985,8 @@ DEFUN (bgp_redistribute_ipv6_metric, metric = strtoul(argv[idx_number]->arg, NULL, 10); red = bgp_redist_add(bgp, AFI_IP6, type, 0); - bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric); - return bgp_redistribute_set(bgp, AFI_IP6, type, 0); + changed = bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric); + return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed); } DEFUN (bgp_redistribute_ipv6_rmap_metric, @@ -11993,6 +12006,7 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric, int type; uint32_t metric; struct bgp_redist *red; + bool changed; type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); if (type < 0) { @@ -12002,9 +12016,10 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric, metric = strtoul(argv[idx_number]->arg, NULL, 10); red = bgp_redist_add(bgp, AFI_IP6, type, 0); - bgp_redistribute_rmap_set(red, argv[idx_word]->arg); - bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric); - return bgp_redistribute_set(bgp, AFI_IP6, type, 0); + changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, + metric); + return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed); } DEFUN (bgp_redistribute_ipv6_metric_rmap, @@ -12024,6 +12039,7 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap, int type; uint32_t metric; struct bgp_redist *red; + bool changed; type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); if (type < 0) { @@ -12033,9 +12049,10 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap, metric = strtoul(argv[idx_number]->arg, NULL, 10); red = bgp_redist_add(bgp, AFI_IP6, type, 0); - bgp_redistribute_metric_set(bgp, red, AFI_IP6, SAFI_UNICAST, metric); - bgp_redistribute_rmap_set(red, argv[idx_word]->arg); - return bgp_redistribute_set(bgp, AFI_IP6, type, 0); + changed = bgp_redistribute_metric_set(bgp, red, AFI_IP6, SAFI_UNICAST, + metric); + changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed); } DEFUN (no_bgp_redistribute_ipv6, diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 9591fe673f..7bd0b1bfa3 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1574,8 +1574,14 @@ static void bgp_redist_del(struct bgp *bgp, afi_t afi, uint8_t type, /* Other routes redistribution into BGP. */ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type, - unsigned short instance) + unsigned short instance, bool changed) { + /* If redistribute options are changed call + * bgp_redistribute_unreg() to reset the option and withdraw + * the routes + */ + if (changed) + bgp_redistribute_unreg(bgp, afi, type, instance); /* Return if already redistribute flag is set. */ if (instance) { diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index e3c88b9db6..546d72402a 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -51,7 +51,8 @@ extern struct bgp_redist *bgp_redist_lookup(struct bgp *, afi_t, uint8_t, unsigned short); extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, uint8_t, unsigned short); -extern int bgp_redistribute_set(struct bgp *, afi_t, int, unsigned short); +extern int bgp_redistribute_set(struct bgp *, afi_t, int, unsigned short, + bool changed); extern int bgp_redistribute_resend(struct bgp *, afi_t, int, unsigned short); extern int bgp_redistribute_rmap_set(struct bgp_redist *, const char *); extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, afi_t, From 4ce826764487b07c2bc3f2bf0f1986001afd93c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20R=C3=B6thke?= Date: Wed, 18 Jul 2018 15:41:34 +0200 Subject: [PATCH 30/66] bgpd: fix deadlock in rpki code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some situations rtrlib does not release the locks for its internal data structures before calling a callback. This can lead to deadlocks when a lot of routes must be revalidated because the sync socket buffer will fill up and block the rtrlib thread. The bgpd main thread then waits for rtrlibs internal locks to be released indefinitely. This is fixed by using nonblocking sockets instead of blocking ones and setting a flag to revalidate everything, if it would block. Signed-off-by: Marcel Röthke --- bgpd/bgp_rpki.c | 50 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 52c5dc5e90..9a42bb7a85 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -47,6 +47,7 @@ #include "bgpd/bgp_attr.h" #include "bgpd/bgp_aspath.h" #include "bgpd/bgp_route.h" +#include "lib/network.h" #include "lib/thread.h" #include "rtrlib/rtrlib.h" #include "rtrlib/rtr_mgr.h" @@ -131,12 +132,14 @@ static route_map_result_t route_match(void *rule, const struct prefix *prefix, static void *route_match_compile(const char *arg); static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi, safi_t safi); +static void revalidate_all_routes(void); static struct rtr_mgr_config *rtr_config; static struct list *cache_list; static int rtr_is_running; static int rtr_is_stopping; static int rtr_is_starting; +static _Atomic int rtr_update_overflow; static int rpki_debug; static unsigned int polling_period; static unsigned int expire_interval; @@ -345,6 +348,19 @@ static int bgpd_sync_callback(struct thread *thread) thread_add_read(bm->master, bgpd_sync_callback, NULL, rpki_sync_socket_bgpd, NULL); + + if (atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst)) { + while (read(rpki_sync_socket_bgpd, &rec, + sizeof(struct pfx_record)) + != -1) + ; + + atomic_store_explicit(&rtr_update_overflow, 0, + memory_order_seq_cst); + revalidate_all_routes(); + return 0; + } + int retval = read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record)); if (retval != sizeof(struct pfx_record)) { @@ -442,28 +458,53 @@ static void rpki_update_cb_sync_rtr(struct pfx_table *p __attribute__((unused)), const struct pfx_record rec, const bool added __attribute__((unused))) { - if (rtr_is_stopping || rtr_is_starting) + if (rtr_is_stopping || rtr_is_starting + || atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst)) return; int retval = write(rpki_sync_socket_rtr, &rec, sizeof(struct pfx_record)); - if (retval != sizeof(struct pfx_record)) + if (retval == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) + atomic_store_explicit(&rtr_update_overflow, 1, + memory_order_seq_cst); + + else if (retval != sizeof(struct pfx_record)) RPKI_DEBUG("Could not write to rpki_sync_socket_rtr"); } static void rpki_init_sync_socket(void) { int fds[2]; + const char *msg; RPKI_DEBUG("initializing sync socket"); if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, fds) != 0) { - RPKI_DEBUG("Could not open rpki sync socket"); - return; + msg = "could not open rpki sync socketpair"; + goto err; } rpki_sync_socket_rtr = fds[0]; rpki_sync_socket_bgpd = fds[1]; + + if (set_nonblocking(rpki_sync_socket_rtr) != 0) { + msg = "could not set rpki_sync_socket_rtr to non blocking"; + goto err; + } + + if (set_nonblocking(rpki_sync_socket_bgpd) != 0) { + msg = "could not set rpki_sync_socket_bgpd to non blocking"; + goto err; + } + + thread_add_read(bm->master, bgpd_sync_callback, NULL, rpki_sync_socket_bgpd, NULL); + + return; + +err: + zlog_err("RPKI: %s", msg); + abort(); + } static int bgp_rpki_init(struct thread_master *master) @@ -514,6 +555,7 @@ static int start(void) rtr_is_stopping = 0; rtr_is_starting = 1; + rtr_update_overflow = 0; if (list_isempty(cache_list)) { RPKI_DEBUG( From 0b2c4b35605279fbaeadd899185802eb1c2ef89e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20R=C3=B6thke?= Date: Thu, 19 Jul 2018 17:57:40 +0200 Subject: [PATCH 31/66] bgpd: fix wrong allocation size in rpki route map MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcel Röthke --- bgpd/bgp_rpki.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 9a42bb7a85..1371ce8026 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -232,7 +232,7 @@ static void *route_match_compile(const char *arg) { int *rpki_status; - rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t)); + rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int)); if (strcmp(arg, "valid") == 0) *rpki_status = RPKI_VALID; From 31a2af325e67b6ae4bb3c110b4e49c77dd523dec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20R=C3=B6thke?= Date: Thu, 19 Jul 2018 17:58:05 +0200 Subject: [PATCH 32/66] bgpd: use correct bgp tables for rpki revalidation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcel Röthke --- bgpd/bgp_rpki.c | 73 +++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 1371ce8026..53fc221f3e 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -372,26 +372,36 @@ static int bgpd_sync_callback(struct thread *thread) afi_t afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6; for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) { - safi_t safi; + struct peer *peer; + struct listnode *peer_listnode; - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { - if (!bgp->rib[afi][safi]) - continue; + for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) { + safi_t safi; - struct list *matches = list_new(); + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (!peer->bgp->rib[afi][safi]) + continue; - matches->del = (void (*)(void *))bgp_unlock_node; + struct list *matches = list_new(); - bgp_table_range_lookup(bgp->rib[afi][safi], prefix, - rec.max_len, matches); + matches->del = + (void (*)(void *))bgp_unlock_node; + + bgp_table_range_lookup( + peer->bgp->rib[afi][safi], prefix, + rec.max_len, matches); - struct bgp_node *bgp_node; + struct bgp_node *bgp_node; + struct listnode *bgp_listnode; - for (ALL_LIST_ELEMENTS_RO(matches, node, bgp_node)) - revalidate_bgp_node(bgp_node, afi, safi); + for (ALL_LIST_ELEMENTS_RO(matches, bgp_listnode, + bgp_node)) + revalidate_bgp_node(bgp_node, afi, + safi); - list_delete_and_null(&matches); + list_delete_and_null(&matches); + } } } @@ -414,14 +424,13 @@ static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi, label = bgp_info->extra->label; num_labels = bgp_info->extra->num_labels; } - ret = bgp_update(ain->peer, &bgp_node->p, 0, ain->attr, afi, - safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, - label, num_labels, 1, NULL); + ret = bgp_update(ain->peer, &bgp_node->p, ain->addpath_rx_id, + ain->attr, afi, safi, ZEBRA_ROUTE_BGP, + BGP_ROUTE_NORMAL, NULL, label, num_labels, 1, + NULL); - if (ret < 0) { - bgp_unlock_node(bgp_node); + if (ret < 0) return; - } } } @@ -429,25 +438,23 @@ static void revalidate_all_routes(void) { struct bgp *bgp; struct listnode *node; - struct bgp_node *bgp_node; for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) { - for (size_t i = 0; i < 2; i++) { - safi_t safi; - afi_t afi = (i == 0) ? AFI_IP : AFI_IP6; + struct peer *peer; + struct listnode *peer_listnode; - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { - if (!bgp->rib[afi][safi]) - continue; + for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) { - for (bgp_node = - bgp_table_top(bgp->rib[afi][safi]); - bgp_node; - bgp_node = bgp_route_next(bgp_node)) { - if (bgp_node->info != NULL) { - revalidate_bgp_node(bgp_node, - afi, safi); - } + for (size_t i = 0; i < 2; i++) { + safi_t safi; + afi_t afi = (i == 0) ? AFI_IP : AFI_IP6; + + for (safi = SAFI_UNICAST; safi < SAFI_MAX; + safi++) { + if (!peer->bgp->rib[afi][safi]) + continue; + + bgp_soft_reconfig_in(peer, afi, safi); } } } From 3e5d2f718a6d486dd49721567c526f15ead31946 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Wed, 22 Aug 2018 17:39:12 +0200 Subject: [PATCH 33/66] doc/developer: logging guide This roughly outlines when to use which logging function. It's certainly something to have to point people to, so they get things nice and right - and so we get at least somewhat consistent behaviour for the user. Signed-off-by: David Lamparter --- doc/Makefile.am | 1 + doc/developer/library.rst | 1 + doc/developer/logging.rst | 131 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 doc/developer/logging.rst diff --git a/doc/Makefile.am b/doc/Makefile.am index 6f72585485..f421865054 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -193,6 +193,7 @@ EXTRA_DIST = frr-sphinx.mk \ developer/index.rst \ developer/ldpd-basic-test-setup.md \ developer/library.rst \ + developer/logging.rst \ developer/Makefile.in \ developer/maintainer-release-build.rst \ developer/memtypes.rst \ diff --git a/doc/developer/library.rst b/doc/developer/library.rst index f6efa33051..77b2f229b7 100644 --- a/doc/developer/library.rst +++ b/doc/developer/library.rst @@ -7,6 +7,7 @@ Library Facilities (libfrr) .. toctree:: :maxdepth: 2 + logging memtypes hooks cli diff --git a/doc/developer/logging.rst b/doc/developer/logging.rst new file mode 100644 index 0000000000..4338d900e6 --- /dev/null +++ b/doc/developer/logging.rst @@ -0,0 +1,131 @@ +Developer's Guide to Logging +============================ + +One of the most frequent decisions to make while writing code for FRR is what +to log, what level to log it at, and when to log it. Here is a list of +recommendations for these decisions. + + +Errors and warnings +------------------- + +If it is something that the user will want to look at and maybe do +something, it is either an **error** or a **warning**. + +We're expecting that warnings and errors are in some way visible to the +user (in the worst case by looking at the log after the network broke, but +maybe by a syslog collector from all routers.) Therefore, anything that +needs to get the user in the loop—and only these things—are warnings or +errors. + +Note that this doesn't neccessarily mean the user needs to fix something in +the FRR instance. It also includes when we detect something else needs +fixing, for example another router, the system we're running on, or the +configuration. The common point is that the user should probably do +*something*. + +Deciding between a warning and an error is slightly less obvious; the rule +of thumb here is that an error will cause considerable fallout beyond its +direct effect. Closing a BGP session due to a malformed update is an error +since all routes from the peer are dropped; discarding one route because +its attributes don't make sense is a warning. + +This also loosely corresponds to the kind of reaction we're expecting from +the user. An error is likely to need immediate response while a warning +might be snoozed for a bit and addressed as part of general maintenance. +If a problem will self-repair (e.g. by retransmits), it should be a +warning—unless the impact until that self-repair is very harsh. + +Examples for warnings: + +* a BGP update, LSA or LSP could not be processed, but operation is + proceeding and the broken pieces are likely to self-fix later +* some kind of controller cannot be reached, but we can work without it +* another router is using some unknown or unsupported capability + +Examples for errors: + +* dropping a BGP session due to malformed data +* a socket for routing protocol operation cannot be opened +* desynchronization from network state because something went wrong +* *everything that we as developers would really like to be notified about, + i.e. some assumption in the code isn't holding up* + + +Informational messages +---------------------- + +Anything that provides introspection to the user during normal operation +is an **info** message. + +This includes all kinds of operational state transitions and events, +especially if they might be interesting to the user during the course of +figuring out a warning or an error. + +By itself, these messages should mostly be statements of fact. They might +indicate the order and relationship in which things happened. Also covered +are conditions that might be "operational issues" like a link failure due +to an unplugged cable. If it's pretty much the point of running a routing +daemon for, it's not a warning or an error, just business as usual. + +The user should be able to see the state of these bits from operational +state output, i.e. `show interface` or `show foobar neighbors`. The log +message indicating the change may have been printed weeks ago, but the +state can always be viewed. (If some state change has an info message but +no "show" command, maybe that command needs to be added.) + +Examples: + +* all kinds of up/down state changes + + * interface coming up or going down + * addresses being added or deleted + * peers and neighbors coming up or going down + +* rejection of some routes due to user-configured route maps +* backwards compatibility handling because another system on the network + has a different or smaller feature set + +.. note:: + The previously used **notify** priority is replaced with *info* in all + cases. We don't currently have a well-defined use case for it. + + +Debug messages and asserts +-------------------------- + +Everything that is only interesting on-demand, or only while developing, +is a **debug** message. It might be interesting to the user for a +particularly evasive issue, but in general these are details that an +average user might not even be able to make sense of. + +Most (or all?) debug messages should be behind a `debug foobar` category +switch that controls which subset of these messages is currently +interesting and thus printed. If a debug message doesn't have such a +guard, there should be a good explanation as to why. + +Conversely, debug messages are the only thing that should be guarded by +these switches. Neither info nor warning or error messages should be +hidden in this way. + +**Asserts** should only be used as pretty crashes. We are expecting that +asserts remain enabled in production builds, but please try to not use +asserts in a way that would cause a security problem if the assert wasn't +there (i.e. don't use them for length checks.) + +The purpose of asserts is mainly to help development and bug hunting. If +the daemon crashes, then having some more information is nice, and the +assert can provide crucial hints that cut down on the time needed to track +an issue. That said, if the issue can be reasonably handled and/or isn't +going to crash the daemon, it shouldn't be an assert. + +For anything else where internal constraints are violated but we're not +breaking due to it, it's an error instead (not a debug.) These require +"user action" of notifying the developers. + +Examples: + +* mismatched :code:`prev`/:code:`next` pointers in lists +* some field that is absolutely needed is :code:`NULL` +* any other kind of data structure corruption that will cause the daemon + to crash sooner or later, one way or another From b2a9fc6b2362fba18324f9e2ce2c9b04bae262b1 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 22 Aug 2018 16:08:26 -0700 Subject: [PATCH 34/66] bgpd: Fix memory leak show ip bgp json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root Cause: In the function bgp_show_table(), we are creating a json object and a json array with the same name as “json_paths”. First it will create a json object variable "json_paths" pointing to the memory allocated for the json object. Then it will create a json array for each bap node rn (if rn->info is available) with the same name as json_paths. Because of this, json_paths which was pointing to the memory allocated for the json object earlier, now will be overwritten with the memory allocated for the json array. As per the existing code, at the end of each iteration loop of bgp node, it will deallocate the memory used by the json array and assigned NULL to the variable json_paths. Since we don’t have the pointer pointing to the memory allocated for json object, will be not able to de-allocate the memory, which is a memory leak here. Fix: Removing this json object since it is never getting used in this function. Testing: Reproduced the memory leak with valgrind. With the fix, memory leak gets resolved and checked with valgrind. Signed-off-by: Sarita Patra saritap@vmware.com --- bgpd/bgp_route.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 343f094b20..e38257d564 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8202,7 +8202,6 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, vty_out(vty, " \"routeDistinguishers\" : {"); ++*json_header_depth; } - json_paths = json_object_new_object(); } if (use_json && rd) { @@ -8429,8 +8428,6 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, *total_cum = total_count; } if (use_json) { - if (json_paths) - json_object_free(json_paths); if (rd) { vty_out(vty, " }%s ", (is_last ? "" : ",")); } From 10744c9c388d618d83d2bf9c041671aaffa4b193 Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Wed, 22 Aug 2018 17:27:28 +0000 Subject: [PATCH 35/66] lib: error codes are uint32_t's Signed-off-by: Quentin Young --- lib/log.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/log.h b/lib/log.h index 980f3ddf4b..7d05b84641 100644 --- a/lib/log.h +++ b/lib/log.h @@ -87,7 +87,7 @@ extern void zlog_debug(const char *format, ...) PRINTF_ATTRIBUTE(1, 2); /* For logs which have error codes associated with them */ #define flog_err(ferr_id, format, ...) \ - zlog_err("[EC %d] " format, ferr_id, ##__VA_ARGS__) + zlog_err("[EC %"PRIu32"] " format, ferr_id, ##__VA_ARGS__) #define flog_err_sys(ferr_id, format, ...) \ flog_err(ferr_id, format, ##__VA_ARGS__) From 7df407eda8b501b6319f9c563ee5f72f9199d8a6 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Tue, 31 Jul 2018 18:45:39 -0700 Subject: [PATCH 36/66] bgpd: check existing l3vni for any l2vni creation Scan all bgp vrf instances and respective L3VNI against the VNI which is being configured. Ticket:CM-21859 Testing Done: Configure l3vni, try to configure same vni as l2vni under router bgp, address-family l2vpn evpn. The configuration is rejected. show evpn vni VNI Type VxLAN IF # MACs # ARPs # Remote VTEPs Tenant VRF 4001 L3 vx-4001 0 0 n/a vrf1 TOR(config)# router bgp 5546 TOR(config-router)# address-family l2vpn evpn TOR(config-router-af)# vni 4001 % Failed to create VNI Signed-off-by: Chirag Shah --- bgpd/bgp_evpn.c | 17 +++++++++++++++++ bgpd/bgp_evpn_private.h | 1 + bgpd/bgp_evpn_vty.c | 8 ++++++++ 3 files changed, 26 insertions(+) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index ce9f93f8a2..9e814516b7 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -4931,6 +4931,23 @@ void bgp_evpn_derive_auto_rd(struct bgp *bgp, struct bgpevpn *vpn) UNSET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD); } +/* + * Lookup L3-VNI + */ +bool bgp_evpn_lookup_l3vni_l2vni_table(vni_t vni) +{ + struct list *inst = bm->bgp; + struct listnode *node; + struct bgp *bgp_vrf; + + for (ALL_LIST_ELEMENTS_RO(inst, node, bgp_vrf)) { + if (bgp_vrf->l3vni == vni) + return true; + } + + return false; +} + /* * Lookup VNI. */ diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index 8d71c3123e..f0017f3533 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -503,4 +503,5 @@ extern struct evpnes *bgp_evpn_lookup_es(struct bgp *bgp, esi_t *esi); extern struct evpnes *bgp_evpn_es_new(struct bgp *bgp, esi_t *esi, struct ipaddr *originator_ip); extern void bgp_evpn_es_free(struct bgp *bgp, struct evpnes *es); +extern bool bgp_evpn_lookup_l3vni_l2vni_table(vni_t vni); #endif /* _BGP_EVPN_PRIVATE_H */ diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 3828ce216b..b553cb42a5 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -1888,6 +1888,14 @@ static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni) vpn = bgp_evpn_lookup_vni(bgp, vni); if (!vpn) { + /* Check if this L2VNI is already configured as L3VNI */ + if (bgp_evpn_lookup_l3vni_l2vni_table(vni)) { + flog_err(BGP_ERR_VNI, + "%u: Failed to create L2VNI %u, it is configured as L3VNI", + bgp->vrf_id, vni); + return NULL; + } + /* tenant vrf will be updated when we get local_vni_add from * zebra */ From 54c174250c381580b0477e6eade2c03c4109ed64 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Mon, 13 Aug 2018 17:07:22 -0700 Subject: [PATCH 37/66] zebra: mark router flag for neigh update The neigh update can come prior to mac add update. In this case, the mac will be auto created for the vni. set router flag to local neigh update for mac with auto flag. The neigh update will be informed to bgpd once local mac is learnt. Unset router flag if the neigh update comes without the router flag for an existing neigh entry. Signed-off-by: Chirag Shah --- zebra/zebra_vxlan.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 04f9be8ade..a4f5f7b954 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -2060,6 +2060,12 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, n->ifindex = ifp->ifindex; } + /*Mark Router flag (R-bit) */ + if (router_flag) + SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + else + UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + /* Before we program this in BGP, we need to check if MAC is locally * learnt as well */ @@ -2074,10 +2080,6 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, return 0; } - /*Set router flag (R-bit) */ - if (router_flag) - SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); - /* Inform BGP. */ if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug("Neigh %s (MAC %s) is now ACTIVE on L2-VNI %u with flags 0x%x", @@ -4965,10 +4967,11 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp, if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s-> L2-VNI %u", + "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s %s-> L2-VNI %u", ipaddr2str(ip, buf2, sizeof(buf2)), prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name, ifp->ifindex, state, ext_learned ? "ext-learned " : "", + router_flag ? "router " : "", zvni->vni); /* Is this about a local neighbor or a remote one? */ From 29c2ce7cfc283337e60d5498fb72f291528603b4 Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Wed, 15 Aug 2018 13:32:03 -0700 Subject: [PATCH 38/66] zebra: check router_flag change for neigh update Neigh update can have router_flag change, from unset to set and viceversa. This is the case where MAC, IP and VLAN are same but entry's flag moved from R to not R bit and reverse case. Router flag change needs to trigger bgpd to inform all evpn peers to remove from the evpn route. Testing Done: Send GARP with and without R bit from host and validate neigh entry and evpn neigh and mac-ip route entry in zebra and bgpd. Check Peer VTEP evpn route entry where router flag is (un)set. With R-bit Route [2]:[0]:[0]:[48]:[00:1f:2f:db:45:a6]:[128]:[2006:33:33:2::10] VNI 1001 Imported from 27.0.0.16:5:[2]:[0]:[0]:[48]:[00:1f:2f:db:45:a6]:[128]:[2006:33:33:2::10] 4435 5551 27.0.0.16 from MSP1(uplink-1) (27.0.0.9) Origin IGP, valid, external, bestpath-from-AS 4435, best Extended Community: RT:5551:1001 ET:8 ND:Router Flag AddPath ID: RX 0, TX 1261 Last update: Wed Aug 15 20:52:14 2018 Without R-bit Route [2]:[0]:[0]:[48]:[00:1f:2f:db:45:a6]:[128]:[2006:33:33:2::10] VNI 1001 Imported from 27.0.0.16:5:[2]:[0]:[0]:[48]:[00:1f:2f:db:45:a6]:[128]:[2006:33:33:2::10] 4435 5551 27.0.0.16 from MSP2(uplink-2) (27.0.0.10) Origin IGP, valid, external, bestpath-from-AS 4435, best Extended Community: RT:5551:1001 ET:8 AddPath ID: RX 0, TX 1263 Last update: Wed Aug 15 20:53:10 2018 Signed-off-by: Chirag Shah --- zebra/zebra_vxlan.c | 61 +++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index a4f5f7b954..0b034fd3b5 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -1961,6 +1961,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, char buf2[INET6_ADDRSTRLEN]; zebra_neigh_t *n = NULL; zebra_mac_t *zmac = NULL, *old_zmac = NULL; + bool check_rbit = false; /* create a dummy MAC if the MAC is not already present */ zmac = zvni_mac_lookup(zvni, macaddr); @@ -1990,35 +1991,41 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, n = zvni_neigh_lookup(zvni, ip); if (n) { if (CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL)) { + + if (router_flag != + (CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) + ? 1 : 0)) + check_rbit = true; + if (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN) == 0) { /* Update any params and return - client doesn't * care about a purely local change. */ n->ifindex = ifp->ifindex; - return 0; - } + } else { - /* If the MAC has changed, - * need to issue a delete first - * as this means a different MACIP route. - * Also, need to do some unlinking/relinking. - */ - zvni_neigh_send_del_to_client(zvni->vni, &n->ip, + /* If the MAC has changed, + * need to issue a delete first + * as this means a different MACIP route. + * Also, need to do some unlinking/relinking. + */ + zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, 0); - old_zmac = zvni_mac_lookup(zvni, &n->emac); - if (old_zmac) { - listnode_delete(old_zmac->neigh_list, n); - zvni_deref_ip2mac(zvni, old_zmac, 0); + old_zmac = zvni_mac_lookup(zvni, &n->emac); + if (old_zmac) { + listnode_delete(old_zmac->neigh_list, n); + zvni_deref_ip2mac(zvni, old_zmac, 0); + } + + /* Update the forwarding info. */ + n->ifindex = ifp->ifindex; + memcpy(&n->emac, macaddr, ETH_ALEN); + + /* Link to new MAC */ + listnode_add_sort(zmac->neigh_list, n); } - /* Update the forwarding info. */ - n->ifindex = ifp->ifindex; - memcpy(&n->emac, macaddr, ETH_ALEN); - - /* Link to new MAC */ - listnode_add_sort(zmac->neigh_list, n); - } else /* Neighbor has moved from remote to local. */ { @@ -2042,6 +2049,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, n->r_vtep_ip.s_addr = 0; SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); n->ifindex = ifp->ifindex; + check_rbit = true; } } else { /* New neighbor - create */ @@ -2058,6 +2066,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, /* Set "local" forwarding info. */ SET_FLAG(n->flags, ZEBRA_NEIGH_LOCAL); n->ifindex = ifp->ifindex; + check_rbit = true; } /*Mark Router flag (R-bit) */ @@ -2072,11 +2081,21 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) { if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( - "Skipping neigh %s add to client as MAC %s is not local on VNI %u", + "Skipping neigh %s add to client as MAC %s is not local on VNI %u with flags 0x%x", + ipaddr2str(ip, buf2, sizeof(buf2)), + prefix_mac2str(macaddr, buf, sizeof(buf)), + zvni->vni, n->flags); + + return 0; + } + + if (!check_rbit) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "Skipping neigh %s with MAC %s on VNI %u add to client as router flag is not set.", ipaddr2str(ip, buf2, sizeof(buf2)), prefix_mac2str(macaddr, buf, sizeof(buf)), zvni->vni); - return 0; } From 7d08917b321f480c26a1a7f794906d65fff0fdfa Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Fri, 17 Aug 2018 13:38:06 -0700 Subject: [PATCH 39/66] zebra: mark router flag for remote neigh update Handle Remote Neigh entry state change from Router to Host. Remote MAC-IP update may not continue EVPN NA Extended community, Zebra need to accomodate if router_flag change for existing neigh and install with or without Router Flag (R-bit). Testing: Have locally run MAC/IP (neigh entry) with R-bit set, Checke on remote VTEP 'show bgp evpn route ...mac ip' and 'show evpn arp-cache ...' contians router flag. Change host to remove R-bit, which locally learnt entry removes Router flag. This results in remote vtep to remove R-bit from neigh entry. Signed-off-by: Chirag Shah --- zebra/zebra_vxlan.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 0b034fd3b5..f63879159d 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -5173,7 +5173,8 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) char buf[ETHER_ADDR_STRLEN]; char buf1[INET6_ADDRSTRLEN]; uint8_t sticky = 0; - u_char remote_gw = 0; + uint8_t remote_gw = 0; + uint8_t router_flag = 0; uint8_t flags = 0; struct interface *ifp = NULL; struct zebra_if *zif = NULL; @@ -5216,6 +5217,7 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) STREAM_GETC(s, flags); sticky = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); remote_gw = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW); + router_flag = CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); l++; if (IS_ZEBRA_DEBUG_VXLAN) @@ -5347,6 +5349,8 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) */ n = zvni_neigh_lookup(zvni, &ip); if (!n || !CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) + || ((CHECK_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG) ? 1 : 0) + != router_flag) || (memcmp(&n->emac, &macaddr, sizeof(macaddr)) != 0) || !IPV4_ADDR_SAME(&n->r_vtep_ip, &vtep_ip)) update_neigh = 1; @@ -5387,6 +5391,8 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS) /* Set router flag (R-bit) to this Neighbor entry */ if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG)) SET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); + else + UNSET_FLAG(n->flags, ZEBRA_NEIGH_ROUTER_FLAG); /* Install the entry. */ zvni_neigh_install(zvni, n); From a6f235f3416c3ecb635420033572d790b7db0ede Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 22 Aug 2018 21:05:29 -0400 Subject: [PATCH 40/66] lib: Seperate out Poll data from thread memory statistics We were storing Poll data for the read and write memory information in MTYPE_THREAD, so a show run would not be able to show actual amount of memory associated with the `struct thread`. Remove unnecessary NULL checks on malloc. Signed-off-by: Donald Sharp --- lib/thread.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/lib/thread.c b/lib/thread.c index 898e9e9fce..c6894be4ee 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -36,6 +36,7 @@ DEFINE_MTYPE_STATIC(LIB, THREAD, "Thread") DEFINE_MTYPE_STATIC(LIB, THREAD_MASTER, "Thread master") +DEFINE_MTYPE_STATIC(LIB, THREAD_POLL, "Thread Poll Info") DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats") #if defined(__APPLE__) @@ -423,19 +424,11 @@ struct thread_master *thread_master_create(const char *name) /* Initialize I/O task data structures */ getrlimit(RLIMIT_NOFILE, &limit); rv->fd_limit = (int)limit.rlim_cur; - rv->read = - XCALLOC(MTYPE_THREAD, sizeof(struct thread *) * rv->fd_limit); - if (rv->read == NULL) { - XFREE(MTYPE_THREAD_MASTER, rv); - return NULL; - } - rv->write = - XCALLOC(MTYPE_THREAD, sizeof(struct thread *) * rv->fd_limit); - if (rv->write == NULL) { - XFREE(MTYPE_THREAD, rv->read); - XFREE(MTYPE_THREAD_MASTER, rv); - return NULL; - } + rv->read = XCALLOC(MTYPE_THREAD_POLL, + sizeof(struct thread *) * rv->fd_limit); + + rv->write = XCALLOC(MTYPE_THREAD_POLL, + sizeof(struct thread *) * rv->fd_limit); rv->cpu_record = hash_create_size( 8, (unsigned int (*)(void *))cpu_record_hash_key, @@ -580,7 +573,7 @@ static void thread_array_free(struct thread_master *m, m->alloc--; } } - XFREE(MTYPE_THREAD, thread_array); + XFREE(MTYPE_THREAD_POLL, thread_array); } static void thread_queue_free(struct thread_master *m, struct pqueue *queue) From 9ab2969de83dce29e16112c61c0e2d0d38c349b6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 15 Aug 2018 14:53:51 -0400 Subject: [PATCH 41/66] bgpd: Remove warn to file an issue A warn with a backtrace does not need another warn to file an issue with Quagga, so just remove it. Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index e38257d564..8626658149 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -358,8 +358,6 @@ static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_info *ri) "%s: Asked to decrement 0 prefix count for peer %s", __func__, ri->peer->host); zlog_backtrace(LOG_WARNING); - zlog_warn("%s: Please report to Quagga bugzilla", - __func__); } } else if (BGP_INFO_COUNTABLE(ri) && !CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) { From d8d084d97febb886748be2f77790b0ee9cbe08dd Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 16 Aug 2018 12:21:25 -0400 Subject: [PATCH 42/66] bgpd: convert zlog_warns to debugs or errors Several zlog_warns were being used to tell the end user that bgp had detected a bug. These all look like information added during development that can be noted as debugs or logged as an error situation. Signed-off-by: Donald Sharp --- bgpd/bgp_route.c | 38 ++++++++++++-------------------------- bgpd/bgpd.c | 11 ----------- 2 files changed, 12 insertions(+), 37 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 8626658149..ed3b75f87c 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -38,6 +38,7 @@ #include "queue.h" #include "memory.h" #include "lib/json.h" +#include "lib_errors.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" @@ -353,12 +354,9 @@ static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_info *ri) /* slight hack, but more robust against errors. */ if (ri->peer->pcount[table->afi][table->safi]) ri->peer->pcount[table->afi][table->safi]--; - else { - zlog_warn( - "%s: Asked to decrement 0 prefix count for peer %s", - __func__, ri->peer->host); - zlog_backtrace(LOG_WARNING); - } + else + flog_err(LIB_ERR_DEVELOPMENT, + "Asked to decrement 0 prefix count for peer"); } else if (BGP_INFO_COUNTABLE(ri) && !CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) { SET_FLAG(ri->flags, BGP_INFO_COUNTED); @@ -1052,8 +1050,8 @@ static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p, #define FILTER_EXIST_WARN(F, f, filter) \ if (BGP_DEBUG(update, UPDATE_IN) && !(F##_IN(filter))) \ - zlog_warn("%s: Could not find configured input %s-list %s!", \ - peer->host, #f, F##_IN_NAME(filter)); + zlog_debug("%s: Could not find configured input %s-list %s!", \ + peer->host, #f, F##_IN_NAME(filter)); if (DISTRIBUTE_IN_NAME(filter)) { FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter); @@ -1091,8 +1089,8 @@ static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p, #define FILTER_EXIST_WARN(F, f, filter) \ if (BGP_DEBUG(update, UPDATE_OUT) && !(F##_OUT(filter))) \ - zlog_warn("%s: Could not find configured output %s-list %s!", \ - peer->host, #f, F##_OUT_NAME(filter)); + zlog_debug("%s: Could not find configured output %s-list %s!", \ + peer->host, #f, F##_OUT_NAME(filter)); if (DISTRIBUTE_OUT_NAME(filter)) { FILTER_EXIST_WARN(DISTRIBUTE, distribute, filter); @@ -9807,8 +9805,6 @@ static int bgp_peer_count_walker(struct thread *t) pc->count[PCOUNT_ADJ_IN]++; for (ri = rn->info; ri; ri = ri->next) { - char buf[SU_ADDRSTRLEN]; - if (ri->peer != peer) continue; @@ -9830,22 +9826,12 @@ static int bgp_peer_count_walker(struct thread *t) if (CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) { pc->count[PCOUNT_COUNTED]++; if (CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) - zlog_warn( - "%s [pcount] %s/%d is counted but flags 0x%x", - peer->host, - inet_ntop(rn->p.family, - &rn->p.u.prefix, buf, - SU_ADDRSTRLEN), - rn->p.prefixlen, ri->flags); + flog_err(LIB_ERR_DEVELOPMENT, + "Attempting to count but flags say it is unusable"); } else { if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) - zlog_warn( - "%s [pcount] %s/%d not counted but flags 0x%x", - peer->host, - inet_ntop(rn->p.family, - &rn->p.u.prefix, buf, - SU_ADDRSTRLEN), - rn->p.prefixlen, ri->flags); + flog_err(LIB_ERR_DEVELOPMENT, + "Not counted but flags say we should"); } } } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index c8b4e3acf5..746967a3b3 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -6631,17 +6631,6 @@ char *peer_uptime(time_t uptime2, char *buf, size_t len, uint8_t use_json, time_t uptime1, epoch_tbuf; struct tm *tm; - /* Check buffer length. */ - if (len < BGP_UPTIME_LEN) { - if (!use_json) { - zlog_warn("peer_uptime (): buffer shortage %lu", - (unsigned long)len); - /* XXX: should return status instead of buf... */ - snprintf(buf, len, " "); - } - return buf; - } - /* If there is no connection has been done before print `never'. */ if (uptime2 == 0) { if (use_json) { From 807ed4e9c0386b648d1cd15b6b7518d082aa7c01 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 16 Aug 2018 13:51:13 -0400 Subject: [PATCH 43/66] lib: Remove smux option for snmp The smux.c code has not been able to compile for 2+ years and no-one has noticed. Additionally net-snmp has marked smux integration as deprecated for quite some time as well. Since no-one has noticed and it's been broken and smux integration is deprecated let's just remove this from the code base. From looking at the code, it sure looks like SNMP could use a decent cleanup. Signed-off-by: Donald Sharp --- configure.ac | 7 +- doc/user/snmp.rst | 115 +--- lib/smux.c | 1416 --------------------------------------------- lib/subdir.am | 2 - 4 files changed, 8 insertions(+), 1532 deletions(-) delete mode 100644 lib/smux.c diff --git a/configure.ac b/configure.ac index 96e201cc42..715b1b7ef7 100755 --- a/configure.ac +++ b/configure.ac @@ -382,7 +382,7 @@ AC_ARG_ENABLE(bgp-vnc, AC_ARG_WITH(rfp-path, AS_HELP_STRING([--with-rfp-path[=DIR]],[path to replaced stub RFP used with BGP VNC])) AC_ARG_ENABLE(snmp, - AS_HELP_STRING([--enable-snmp=ARG], [enable SNMP support (smux or agentx)])) + AS_HELP_STRING([--enable-snmp], [enable SNMP support for agentx])) AC_ARG_ENABLE(zeromq, AS_HELP_STRING([--enable-zeromq], [enable ZeroMQ handler (libfrrzmq)])) AC_ARG_WITH(libpam, @@ -1496,14 +1496,13 @@ int main(void); yes) SNMP_METHOD=agentx ;; - smux|agentx) + agentx) SNMP_METHOD="${enable_snmp}" ;; *) - AC_MSG_ERROR([--enable-snmp given with an unknown method (${enable_snmp}). Use smux or agentx]) + AC_MSG_ERROR([--enable-snmp given with an unknown method (${enable_snmp}). Use yes or agentx]) ;; esac - AH_TEMPLATE([SNMP_SMUX], [Use SNMP SMUX to interface with snmpd]) AH_TEMPLATE([SNMP_AGENTX], [Use SNMP AgentX to interface with snmpd]) AC_DEFINE_UNQUOTED(AS_TR_CPP(SNMP_${SNMP_METHOD}),,SNMP method to interface with snmpd) fi diff --git a/doc/user/snmp.rst b/doc/user/snmp.rst index 38918ff250..5579969c0e 100644 --- a/doc/user/snmp.rst +++ b/doc/user/snmp.rst @@ -7,8 +7,8 @@ SNMP Support :abbr:`SNMP (Simple Network Managing Protocol)` is a widely implemented feature for collecting network information from router and/or host. FRR itself does not support SNMP agent (server daemon) functionality but is able to connect to -a SNMP agent using the SMUX protocol (:rfc:`1227`) or the AgentX protocol -(:rfc:`2741`) and make the routing protocol MIBs available through it. +a SNMP agent using the the AgentX protocol (:rfc:`2741`) and make the +routing protocol MIBs available through it. Note that SNMP Support needs to be enabled at compile-time and loaded as module on daemon startup. Refer to :ref:`loadable-module-support` on the latter. @@ -18,16 +18,10 @@ on daemon startup. Refer to :ref:`loadable-module-support` on the latter. Getting and installing an SNMP agent ==================================== -There are several SNMP agent which support SMUX or AgentX. We recommend to use +The supported SNMP agent is AgentX. We recommend to use the latest version of `net-snmp` which was formerly known as `ucd-snmp`. It is free and open software and available at `http://www.net-snmp.org/ `_ -and as binary package for most Linux distributions. `net-snmp` has to be -compiled with `--with-mib-modules=agentx` to be able to accept connections from -FRR using AgentX protocol or with `--with-mib-modules=smux` to use SMUX -protocol. - -Nowadays, SMUX is a legacy protocol. The AgentX protocol should be preferred -for any new deployment. Both protocols have the same coverage. +and as binary package for most Linux distributions. .. _agentx-configuration: @@ -42,7 +36,7 @@ master SNMP agent (snmpd) and each of the FRR daemons must be configured. In :file:`/etc/snmp/snmpd.conf`, the ``master agentx`` directive should be added. In each of the FRR daemons, ``agentx`` command will enable AgentX support. -:file:`/etc/snmp/snmpd.conf`: +:file:`/etc/snmp/zebra.conf`: :: @@ -97,105 +91,6 @@ need to configure FRR to use another transport, you can configure it through agentXSocket tcp:192.168.15.12:705 -.. _smux-configuration: - -SMUX configuration -================== - -To enable SMUX protocol support, FRR must have been build with the -:option:`--enable-snmp` option. - -A separate connection has then to be established between the SNMP agent (snmpd) -and each of the FRR daemons. This connections each use different OID numbers -and passwords. Be aware that this OID number is not the one that is used in -queries by clients, it is solely used for the intercommunication of the -daemons. - -In the following example the ospfd daemon will be connected to the snmpd daemon -using the password "frr_ospfd". For testing it is recommending to take exactly -the below snmpd.conf as wrong access restrictions can be hard to debug. - -:file:`/etc/snmp/snmpd.conf`: - -:: - - # - # example access restrictions setup - # - com2sec readonly default public - group MyROGroup v1 readonly - view all included .1 80 - access MyROGroup "" any noauth exact all none none - # - # the following line is relevant for FRR - # - smuxpeer .1.3.6.1.4.1.3317.1.2.5 frr_ospfd - -:file:`/etc/frr/ospf`: - -:: - - ! ... the rest of ospfd.conf has been omitted for clarity ... - ! - smux peer .1.3.6.1.4.1.3317.1.2.5 frr_ospfd - ! - - -After restarting snmpd and frr, a successful connection can be verified in the -syslog and by querying the SNMP daemon: - -:: - - snmpd[12300]: [smux_accept] accepted fd 12 from 127.0.0.1:36255 - snmpd[12300]: accepted smux peer: \\ - oid GNOME-PRODUCT-ZEBRA-MIB::ospfd, frr-0.96.5 - - # snmpwalk -c public -v1 localhost .1.3.6.1.2.1.14.1.1 - OSPF-MIB::ospfRouterId.0 = IpAddress: 192.168.42.109 - - -Be warned that the current version (5.1.1) of the Net-SNMP daemon writes a line -for every SNMP connect to the syslog which can lead to enormous log file sizes. -If that is a problem you should consider to patch snmpd and comment out the -troublesome `snmp_log()` line in the function `netsnmp_agent_check_packet()` in -`agent/snmp_agent.c`. - -MIB and command reference -========================= - -The following OID numbers are used for the interprocess communication of snmpd and -the FRR daemons with SMUX only.:: - - . (OIDs below .iso.org.dod.internet.private.enterprises) - zebra .1.3.6.1.4.1.3317.1.2.1 .gnome.gnomeProducts.zebra.zserv - bgpd .1.3.6.1.4.1.3317.1.2.2 .gnome.gnomeProducts.zebra.bgpd - ripd .1.3.6.1.4.1.3317.1.2.3 .gnome.gnomeProducts.zebra.ripd - ospfd .1.3.6.1.4.1.3317.1.2.5 .gnome.gnomeProducts.zebra.ospfd - ospf6d .1.3.6.1.4.1.3317.1.2.6 .gnome.gnomeProducts.zebra.ospf6d - - -Sadly, SNMP has not been implemented in all daemons yet. The following -OID numbers are used for querying the SNMP daemon by a client::: - - zebra .1.3.6.1.2.1.4.24 .iso.org.dot.internet.mgmt.mib-2.ip.ipForward - ospfd .1.3.6.1.2.1.14 .iso.org.dot.internet.mgmt.mib-2.ospf - bgpd .1.3.6.1.2.1.15 .iso.org.dot.internet.mgmt.mib-2.bgp - ripd .1.3.6.1.2.1.23 .iso.org.dot.internet.mgmt.mib-2.rip2 - ospf6d .1.3.6.1.3.102 .iso.org.dod.internet.experimental.ospfv3 - - -The following syntax is understood by the FRR daemons for configuring SNMP -using SMUX: - -.. index:: smux peer OID -.. clicmd:: smux peer OID -.. index:: no smux peer OID -.. clicmd:: no smux peer OID -.. index:: smux peer OID PASSWORD -.. clicmd:: smux peer OID PASSWORD -.. index:: no smux peer OID PASSWORD -.. clicmd:: no smux peer OID PASSWORD - Here is the syntax for using AgentX: .. index:: agentx diff --git a/lib/smux.c b/lib/smux.c deleted file mode 100644 index 51abfccba3..0000000000 --- a/lib/smux.c +++ /dev/null @@ -1,1416 +0,0 @@ -/* SNMP support - * Copyright (C) 1999 Kunihiro Ishiguro - * - * This file is part of GNU Zebra. - * - * GNU Zebra is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * GNU Zebra is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; see the file COPYING; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#ifdef SNMP_SMUX -#include -#include - -#include "log.h" -#include "thread.h" -#include "linklist.h" -#include "command.h" -#include -#include "memory.h" -#include "sockunion.h" -#include "smux.h" - -#define SMUX_PORT_DEFAULT 199 - -#define SMUXMAXPKTSIZE 1500 -#define SMUXMAXSTRLEN 256 - -#define SMUX_OPEN (ASN_APPLICATION | ASN_CONSTRUCTOR | 0) -#define SMUX_CLOSE (ASN_APPLICATION | ASN_PRIMITIVE | 1) -#define SMUX_RREQ (ASN_APPLICATION | ASN_CONSTRUCTOR | 2) -#define SMUX_RRSP (ASN_APPLICATION | ASN_PRIMITIVE | 3) -#define SMUX_SOUT (ASN_APPLICATION | ASN_PRIMITIVE | 4) - -#define SMUX_GET (ASN_CONTEXT | ASN_CONSTRUCTOR | 0) -#define SMUX_GETNEXT (ASN_CONTEXT | ASN_CONSTRUCTOR | 1) -#define SMUX_GETRSP (ASN_CONTEXT | ASN_CONSTRUCTOR | 2) -#define SMUX_SET (ASN_CONTEXT | ASN_CONSTRUCTOR | 3) -#define SMUX_TRAP (ASN_CONTEXT | ASN_CONSTRUCTOR | 4) - -#define SMUX_MAX_FAILURE 3 - -/* SNMP tree. */ -struct subtree { - /* Tree's oid. */ - oid name[MAX_OID_LEN]; - uint8_t name_len; - - /* List of the variables. */ - struct variable *variables; - - /* Length of the variables list. */ - int variables_num; - - /* Width of the variables list. */ - int variables_width; - - /* Registered flag. */ - int registered; -}; - -#define min(A,B) ((A) < (B) ? (A) : (B)) - -enum smux_event { SMUX_SCHEDULE, SMUX_CONNECT, SMUX_READ }; - -void smux_event(enum smux_event, int); - - -/* SMUX socket. */ -int smux_sock = -1; - -/* SMUX subtree list. */ -struct list *treelist; - -/* SMUX oid. */ -oid *smux_oid = NULL; -size_t smux_oid_len; - -/* SMUX password. */ -char *smux_passwd = NULL; - -/* SMUX read threads. */ -struct thread *smux_read_thread; - -/* SMUX connect thrads. */ -struct thread *smux_connect_thread; - -/* SMUX debug flag. */ -int debug_smux = 0; - -/* SMUX failure count. */ -int fail = 0; - -/* SMUX node. */ -static struct cmd_node smux_node = { - SMUX_NODE, "" /* SMUX has no interface. */ -}; - -/* thread master */ -static struct thread_master *smux_master; - -static int oid_compare_part(oid *o1, int o1_len, oid *o2, int o2_len) -{ - int i; - - for (i = 0; i < min(o1_len, o2_len); i++) { - if (o1[i] < o2[i]) - return -1; - else if (o1[i] > o2[i]) - return 1; - } - if (o1_len < o2_len) - return -1; - - return 0; -} - -static void smux_oid_dump(const char *prefix, const oid *oid, size_t oid_len) -{ - unsigned int i; - int first = 1; - char buf[MAX_OID_LEN * 3]; - - buf[0] = '\0'; - - for (i = 0; i < oid_len; i++) { - sprintf(buf + strlen(buf), "%s%d", first ? "" : ".", - (int)oid[i]); - first = 0; - } - zlog_debug("%s: %s", prefix, buf); -} - -static int smux_socket(void) -{ - int ret; - struct addrinfo hints, *res0, *res; - int gai; - int sock = 0; - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - gai = getaddrinfo(NULL, "smux", &hints, &res0); - if (gai == EAI_SERVICE) { - char servbuf[NI_MAXSERV]; - sprintf(servbuf, "%d", SMUX_PORT_DEFAULT); - servbuf[sizeof(servbuf) - 1] = '\0'; - gai = getaddrinfo(NULL, servbuf, &hints, &res0); - } - if (gai) { - zlog_warn("Cannot locate loopback service smux"); - return -1; - } - for (res = res0; res; res = res->ai_next) { - if (res->ai_family != AF_INET && res->ai_family != AF_INET6) - continue; - - sock = socket(res->ai_family, res->ai_socktype, - res->ai_protocol); - if (sock < 0) - continue; - sockopt_reuseaddr(sock); - sockopt_reuseport(sock); - ret = connect(sock, res->ai_addr, res->ai_addrlen); - if (ret < 0) { - close(sock); - sock = -1; - continue; - } - break; - } - freeaddrinfo(res0); - if (sock < 0) - zlog_warn("Can't connect to SNMP agent with SMUX"); - return sock; -} - -static void smux_getresp_send(oid objid[], size_t objid_len, long reqid, - long errstat, long errindex, uint8_t val_type, - void *arg, size_t arg_len) -{ - uint8_t buf[BUFSIZ]; - uint8_t *ptr, *h1, *h1e, *h2, *h2e; - size_t len, length; - - ptr = buf; - len = BUFSIZ; - length = len; - - if (debug_smux) { - zlog_debug("SMUX GETRSP send"); - zlog_debug("SMUX GETRSP reqid: %ld", reqid); - } - - h1 = ptr; - /* Place holder h1 for complete sequence */ - ptr = asn_build_sequence(ptr, &len, (uint8_t)SMUX_GETRSP, 0); - h1e = ptr; - - ptr = asn_build_int( - ptr, &len, - (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &reqid, - sizeof(reqid)); - - if (debug_smux) - zlog_debug("SMUX GETRSP errstat: %ld", errstat); - - ptr = asn_build_int( - ptr, &len, - (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), - &errstat, sizeof(errstat)); - if (debug_smux) - zlog_debug("SMUX GETRSP errindex: %ld", errindex); - - ptr = asn_build_int( - ptr, &len, - (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), - &errindex, sizeof(errindex)); - - h2 = ptr; - /* Place holder h2 for one variable */ - ptr = asn_build_sequence(ptr, &len, - (uint8_t)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); - h2e = ptr; - - ptr = snmp_build_var_op(ptr, objid, &objid_len, val_type, arg_len, arg, - &len); - - /* Now variable size is known, fill in size */ - asn_build_sequence(h2, &length, - (uint8_t)(ASN_SEQUENCE | ASN_CONSTRUCTOR), - ptr - h2e); - - /* Fill in size of whole sequence */ - asn_build_sequence(h1, &length, (uint8_t)SMUX_GETRSP, ptr - h1e); - - if (debug_smux) - zlog_debug("SMUX getresp send: %td", (ptr - buf)); - - send(smux_sock, buf, (ptr - buf), 0); -} - -static uint8_t *smux_var(uint8_t *ptr, size_t len, oid objid[], - size_t *objid_len, size_t *var_val_len, - uint8_t *var_val_type, void **var_value) -{ - uint8_t type; - uint8_t val_type; - size_t val_len; - uint8_t *val; - - if (debug_smux) - zlog_debug("SMUX var parse: len %zd", len); - - /* Parse header. */ - ptr = asn_parse_header(ptr, &len, &type); - - if (debug_smux) { - zlog_debug("SMUX var parse: type %d len %zd", type, len); - zlog_debug("SMUX var parse: type must be %d", - (ASN_SEQUENCE | ASN_CONSTRUCTOR)); - } - - /* Parse var option. */ - *objid_len = MAX_OID_LEN; - ptr = snmp_parse_var_op(ptr, objid, objid_len, &val_type, &val_len, - &val, &len); - - if (var_val_len) - *var_val_len = val_len; - - if (var_value) - *var_value = (void *)val; - - if (var_val_type) - *var_val_type = val_type; - - /* Requested object id length is objid_len. */ - if (debug_smux) - smux_oid_dump("Request OID", objid, *objid_len); - - if (debug_smux) - zlog_debug("SMUX val_type: %d", val_type); - - /* Check request value type. */ - if (debug_smux) - switch (val_type) { - case ASN_NULL: - /* In case of SMUX_GET or SMUX_GET_NEXT val_type is set - to - ASN_NULL. */ - zlog_debug("ASN_NULL"); - break; - - case ASN_INTEGER: - zlog_debug("ASN_INTEGER"); - break; - case ASN_COUNTER: - case ASN_GAUGE: - case ASN_TIMETICKS: - case ASN_UINTEGER: - zlog_debug("ASN_COUNTER"); - break; - case ASN_COUNTER64: - zlog_debug("ASN_COUNTER64"); - break; - case ASN_IPADDRESS: - zlog_debug("ASN_IPADDRESS"); - break; - case ASN_OCTET_STR: - zlog_debug("ASN_OCTET_STR"); - break; - case ASN_OPAQUE: - case ASN_NSAP: - case ASN_OBJECT_ID: - zlog_debug("ASN_OPAQUE"); - break; - case SNMP_NOSUCHOBJECT: - zlog_debug("SNMP_NOSUCHOBJECT"); - break; - case SNMP_NOSUCHINSTANCE: - zlog_debug("SNMP_NOSUCHINSTANCE"); - break; - case SNMP_ENDOFMIBVIEW: - zlog_debug("SNMP_ENDOFMIBVIEW"); - break; - case ASN_BIT_STR: - zlog_debug("ASN_BIT_STR"); - break; - default: - zlog_debug("Unknown type"); - break; - } - return ptr; -} - -/* NOTE: all 3 functions (smux_set, smux_get & smux_getnext) are based on - ucd-snmp smux and as such suppose, that the peer receives in the message - only one variable. Fortunately, IBM seems to do the same in AIX. */ - -static int smux_set(oid *reqid, size_t *reqid_len, uint8_t val_type, void *val, - size_t val_len, int action) -{ - int j; - struct subtree *subtree; - struct variable *v; - int subresult; - oid *suffix; - size_t suffix_len; - int result; - uint8_t *statP = NULL; - WriteMethod *write_method = NULL; - struct listnode *node, *nnode; - - /* Check */ - for (ALL_LIST_ELEMENTS(treelist, node, nnode, subtree)) { - subresult = oid_compare_part(reqid, *reqid_len, subtree->name, - subtree->name_len); - - /* Subtree matched. */ - if (subresult == 0) { - /* Prepare suffix. */ - suffix = reqid + subtree->name_len; - suffix_len = *reqid_len - subtree->name_len; - result = subresult; - - /* Check variables. */ - for (j = 0; j < subtree->variables_num; j++) { - v = &subtree->variables[j]; - - /* Always check suffix */ - result = oid_compare_part(suffix, suffix_len, - v->name, v->namelen); - - /* This is exact match so result must be zero. - */ - if (result == 0) { - if (debug_smux) - zlog_debug( - "SMUX function call index is %d", - v->magic); - - statP = (*v->findVar)( - v, suffix, &suffix_len, 1, - &val_len, &write_method); - - if (write_method) { - return (*write_method)( - action, val, val_type, - val_len, statP, suffix, - suffix_len); - } else { - return SNMP_ERR_READONLY; - } - } - - /* If above execution is failed or oid is small - (so - there is no further match). */ - if (result < 0) - return SNMP_ERR_NOSUCHNAME; - } - } - } - return SNMP_ERR_NOSUCHNAME; -} - -static int smux_get(oid *reqid, size_t *reqid_len, int exact, uint8_t *val_type, - void **val, size_t *val_len) -{ - int j; - struct subtree *subtree; - struct variable *v; - int subresult; - oid *suffix; - size_t suffix_len; - int result; - WriteMethod *write_method = NULL; - struct listnode *node, *nnode; - - /* Check */ - for (ALL_LIST_ELEMENTS(treelist, node, nnode, subtree)) { - subresult = oid_compare_part(reqid, *reqid_len, subtree->name, - subtree->name_len); - - /* Subtree matched. */ - if (subresult == 0) { - /* Prepare suffix. */ - suffix = reqid + subtree->name_len; - suffix_len = *reqid_len - subtree->name_len; - result = subresult; - - /* Check variables. */ - for (j = 0; j < subtree->variables_num; j++) { - v = &subtree->variables[j]; - - /* Always check suffix */ - result = oid_compare_part(suffix, suffix_len, - v->name, v->namelen); - - /* This is exact match so result must be zero. - */ - if (result == 0) { - if (debug_smux) - zlog_debug( - "SMUX function call index is %d", - v->magic); - - *val = (*v->findVar)( - v, suffix, &suffix_len, exact, - val_len, &write_method); - - /* There is no instance. */ - if (*val == NULL) - return SNMP_NOSUCHINSTANCE; - - /* Call is suceed. */ - *val_type = v->type; - - return 0; - } - - /* If above execution is failed or oid is small - (so - there is no further match). */ - if (result < 0) - return SNMP_ERR_NOSUCHNAME; - } - } - } - return SNMP_ERR_NOSUCHNAME; -} - -static int smux_getnext(oid *reqid, size_t *reqid_len, int exact, - uint8_t *val_type, void **val, size_t *val_len) -{ - int j; - oid save[MAX_OID_LEN]; - int savelen = 0; - struct subtree *subtree; - struct variable *v; - int subresult; - oid *suffix; - size_t suffix_len; - int result; - WriteMethod *write_method = NULL; - struct listnode *node, *nnode; - - - /* Save incoming request. */ - oid_copy(save, reqid, *reqid_len); - savelen = *reqid_len; - - /* Check */ - for (ALL_LIST_ELEMENTS(treelist, node, nnode, subtree)) { - subresult = oid_compare_part(reqid, *reqid_len, subtree->name, - subtree->name_len); - - /* If request is in the tree. The agent has to make sure we - only receive requests we have registered for. */ - /* Unfortunately, that's not true. In fact, a SMUX subagent has - to - behave as if it manages the whole SNMP MIB tree itself. It's - the - duty of the master agent to collect the best answer and - return it - to the manager. See RFC 1227 chapter 3.1.6 for the glory - details - :-). ucd-snmp really behaves bad here as it actually might - ask - multiple times for the same GETNEXT request as it throws away - the - answer when it expects it in a different subtree and might - come - back later with the very same request. --jochen */ - - if (subresult <= 0) { - /* Prepare suffix. */ - suffix = reqid + subtree->name_len; - suffix_len = *reqid_len - subtree->name_len; - if (subresult < 0) { - oid_copy(reqid, subtree->name, - subtree->name_len); - *reqid_len = subtree->name_len; - } - for (j = 0; j < subtree->variables_num; j++) { - result = subresult; - v = &subtree->variables[j]; - - /* Next then check result >= 0. */ - if (result == 0) - result = oid_compare_part( - suffix, suffix_len, v->name, - v->namelen); - - if (result <= 0) { - if (debug_smux) - zlog_debug( - "SMUX function call index is %d", - v->magic); - if (result < 0) { - oid_copy(suffix, v->name, - v->namelen); - suffix_len = v->namelen; - } - *val = (*v->findVar)( - v, suffix, &suffix_len, exact, - val_len, &write_method); - *reqid_len = - suffix_len + subtree->name_len; - if (*val) { - *val_type = v->type; - return 0; - } - } - } - } - } - memcpy(reqid, save, savelen * sizeof(oid)); - *reqid_len = savelen; - - return SNMP_ERR_NOSUCHNAME; -} - -/* GET message header. */ -static uint8_t *smux_parse_get_header(uint8_t *ptr, size_t *len, long *reqid) -{ - uint8_t type; - long errstat; - long errindex; - - /* Request ID. */ - ptr = asn_parse_int(ptr, len, &type, reqid, sizeof(*reqid)); - - if (debug_smux) - zlog_debug("SMUX GET reqid: %d len: %d", (int)*reqid, - (int)*len); - - /* Error status. */ - ptr = asn_parse_int(ptr, len, &type, &errstat, sizeof(errstat)); - - if (debug_smux) - zlog_debug("SMUX GET errstat %ld len: %zd", errstat, *len); - - /* Error index. */ - ptr = asn_parse_int(ptr, len, &type, &errindex, sizeof(errindex)); - - if (debug_smux) - zlog_debug("SMUX GET errindex %ld len: %zd", errindex, *len); - - return ptr; -} - -static void smux_parse_set(uint8_t *ptr, size_t len, int action) -{ - long reqid; - oid oid[MAX_OID_LEN]; - size_t oid_len; - uint8_t val_type; - void *val; - size_t val_len; - int ret; - - if (debug_smux) - zlog_debug("SMUX SET(%s) message parse: len %zd", - (RESERVE1 == action) - ? "RESERVE1" - : ((FREE == action) ? "FREE" : "COMMIT"), - len); - - /* Parse SET message header. */ - ptr = smux_parse_get_header(ptr, &len, &reqid); - - /* Parse SET message object ID. */ - ptr = smux_var(ptr, len, oid, &oid_len, &val_len, &val_type, &val); - - ret = smux_set(oid, &oid_len, val_type, val, val_len, action); - if (debug_smux) - zlog_debug("SMUX SET ret %d", ret); - - /* Return result. */ - if (RESERVE1 == action) - smux_getresp_send(oid, oid_len, reqid, ret, 3, ASN_NULL, NULL, - 0); -} - -static void smux_parse_get(uint8_t *ptr, size_t len, int exact) -{ - long reqid; - oid oid[MAX_OID_LEN]; - size_t oid_len; - uint8_t val_type; - void *val; - size_t val_len; - int ret; - - if (debug_smux) - zlog_debug("SMUX GET message parse: len %zd", len); - - /* Parse GET message header. */ - ptr = smux_parse_get_header(ptr, &len, &reqid); - - /* Parse GET message object ID. We needn't the value come */ - ptr = smux_var(ptr, len, oid, &oid_len, NULL, NULL, NULL); - - /* Traditional getstatptr. */ - if (exact) - ret = smux_get(oid, &oid_len, exact, &val_type, &val, &val_len); - else - ret = smux_getnext(oid, &oid_len, exact, &val_type, &val, - &val_len); - - /* Return result. */ - if (ret == 0) - smux_getresp_send(oid, oid_len, reqid, 0, 0, val_type, val, - val_len); - else - smux_getresp_send(oid, oid_len, reqid, ret, 3, ASN_NULL, NULL, - 0); -} - -/* Parse SMUX_CLOSE message. */ -static void smux_parse_close(uint8_t *ptr, int len) -{ - long reason = 0; - - while (len--) { - reason = (reason << 8) | (long)*ptr; - ptr++; - } - zlog_info("SMUX_CLOSE with reason: %ld", reason); -} - -/* SMUX_RRSP message. */ -static void smux_parse_rrsp(uint8_t *ptr, size_t len) -{ - uint8_t val; - long errstat; - - ptr = asn_parse_int(ptr, &len, &val, &errstat, sizeof(errstat)); - - if (debug_smux) - zlog_debug("SMUX_RRSP value: %d errstat: %ld", val, errstat); -} - -/* Parse SMUX message. */ -static int smux_parse(uint8_t *ptr, size_t len) -{ - /* This buffer we'll use for SOUT message. We could allocate it with - malloc and save only static pointer/lenght, but IMHO static - buffer is a faster solusion. */ - static uint8_t sout_save_buff[SMUXMAXPKTSIZE]; - static int sout_save_len = 0; - - int len_income = len; /* see note below: YYY */ - uint8_t type; - uint8_t rollback; - - rollback = ptr[2]; /* important only for SMUX_SOUT */ - -process_rest: /* see note below: YYY */ - - /* Parse SMUX message type and subsequent length. */ - ptr = asn_parse_header(ptr, &len, &type); - - if (debug_smux) - zlog_debug("SMUX message received type: %d rest len: %zd", type, - len); - - switch (type) { - case SMUX_OPEN: - /* Open must be not send from SNMP agent. */ - zlog_warn("SMUX_OPEN received: resetting connection."); - return -1; - break; - case SMUX_RREQ: - /* SMUX_RREQ message is invalid for us. */ - zlog_warn("SMUX_RREQ received: resetting connection."); - return -1; - break; - case SMUX_SOUT: - /* SMUX_SOUT message is now valied for us. */ - if (debug_smux) - zlog_debug("SMUX_SOUT(%s)", - rollback ? "rollback" : "commit"); - - if (sout_save_len > 0) { - smux_parse_set(sout_save_buff, sout_save_len, - rollback ? FREE : COMMIT); - sout_save_len = 0; - } else - zlog_warn("SMUX_SOUT sout_save_len=%d - invalid", - (int)sout_save_len); - - if (len_income > 3) { - /* YYY: this strange code has to solve the "slow peer" - problem: When agent sends SMUX_SOUT message it - doesn't - wait any responce and may send some next message to - subagent. Then the peer in 'smux_read()' will recieve - from socket the 'concatenated' buffer, contaning both - SMUX_SOUT message and the next one - (SMUX_GET/SMUX_GETNEXT/SMUX_GET). So we should check: - if - the buffer is longer than 3 ( length of SMUX_SOUT ), - we - must process the rest of it. This effect may be - observed - if 'debug_smux' is set to '1' */ - ptr++; - len = len_income - 3; - goto process_rest; - } - break; - case SMUX_GETRSP: - /* SMUX_GETRSP message is invalid for us. */ - zlog_warn("SMUX_GETRSP received: resetting connection."); - return -1; - break; - case SMUX_CLOSE: - /* Close SMUX connection. */ - if (debug_smux) - zlog_debug("SMUX_CLOSE"); - smux_parse_close(ptr, len); - return -1; - break; - case SMUX_RRSP: - /* This is response for register message. */ - if (debug_smux) - zlog_debug("SMUX_RRSP"); - smux_parse_rrsp(ptr, len); - break; - case SMUX_GET: - /* Exact request for object id. */ - if (debug_smux) - zlog_debug("SMUX_GET"); - smux_parse_get(ptr, len, 1); - break; - case SMUX_GETNEXT: - /* Next request for object id. */ - if (debug_smux) - zlog_debug("SMUX_GETNEXT"); - smux_parse_get(ptr, len, 0); - break; - case SMUX_SET: - /* SMUX_SET is supported with some limitations. */ - if (debug_smux) - zlog_debug("SMUX_SET"); - - /* save the data for future SMUX_SOUT */ - memcpy(sout_save_buff, ptr, len); - sout_save_len = len; - smux_parse_set(ptr, len, RESERVE1); - break; - default: - zlog_info("Unknown type: %d", type); - break; - } - return 0; -} - -/* SMUX message read function. */ -static int smux_read(struct thread *t) -{ - int sock; - int len; - uint8_t buf[SMUXMAXPKTSIZE]; - int ret; - - /* Clear thread. */ - sock = THREAD_FD(t); - smux_read_thread = NULL; - - if (debug_smux) - zlog_debug("SMUX read start"); - - /* Read message from SMUX socket. */ - len = recv(sock, buf, SMUXMAXPKTSIZE, 0); - - if (len < 0) { - zlog_warn("Can't read all SMUX packet: %s", - safe_strerror(errno)); - close(sock); - smux_sock = -1; - smux_event(SMUX_CONNECT, 0); - return -1; - } - - if (len == 0) { - zlog_warn("SMUX connection closed: %d", sock); - close(sock); - smux_sock = -1; - smux_event(SMUX_CONNECT, 0); - return -1; - } - - if (debug_smux) - zlog_debug("SMUX read len: %d", len); - - /* Parse the message. */ - ret = smux_parse(buf, len); - - if (ret < 0) { - close(sock); - smux_sock = -1; - smux_event(SMUX_CONNECT, 0); - return -1; - } - - /* Regiser read thread. */ - smux_event(SMUX_READ, sock); - - return 0; -} - -static int smux_open(int sock) -{ - uint8_t buf[BUFSIZ]; - uint8_t *ptr; - size_t len; - long version; - const char progname[] = FRR_SMUX_NAME "-" FRR_VERSION; - - if (debug_smux) { - smux_oid_dump("SMUX open oid", smux_oid, smux_oid_len); - zlog_debug("SMUX open progname: %s", progname); - zlog_debug("SMUX open password: %s", smux_passwd); - } - - ptr = buf; - len = BUFSIZ; - - /* SMUX Header. As placeholder. */ - ptr = asn_build_header(ptr, &len, (uint8_t)SMUX_OPEN, 0); - - /* SMUX Open. */ - version = 0; - ptr = asn_build_int( - ptr, &len, - (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), - &version, sizeof(version)); - - /* SMUX connection oid. */ - ptr = asn_build_objid( - ptr, &len, - (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), - smux_oid, smux_oid_len); - - /* SMUX connection description. */ - ptr = asn_build_string( - ptr, &len, - (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), - (const uint8_t *)progname, strlen(progname)); - - /* SMUX connection password. */ - ptr = asn_build_string( - ptr, &len, - (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR), - (uint8_t *)smux_passwd, strlen(smux_passwd)); - - /* Fill in real SMUX header. We exclude ASN header size (2). */ - len = BUFSIZ; - asn_build_header(buf, &len, (uint8_t)SMUX_OPEN, (ptr - buf) - 2); - - return send(sock, buf, (ptr - buf), 0); -} - -/* `ename` is ignored. Instead of using the provided enterprise OID, - the SMUX peer is used. This keep compatibility with the previous - versions of Quagga. - - All other fields are used as they are intended. */ -int smux_trap(struct variable *vp, size_t vp_len, const oid *ename, - size_t enamelen, const oid *name, size_t namelen, - const oid *iname, size_t inamelen, - const struct trap_object *trapobj, size_t trapobjlen, - uint8_t sptrap) -{ - unsigned int i; - uint8_t buf[BUFSIZ]; - uint8_t *ptr; - size_t len, length; - struct in_addr addr; - unsigned long val; - uint8_t *h1, *h1e; - - ptr = buf; - len = BUFSIZ; - length = len; - - /* When SMUX connection is not established. */ - if (smux_sock < 0) - return 0; - - /* SMUX header. */ - ptr = asn_build_header(ptr, &len, (uint8_t)SMUX_TRAP, 0); - - /* Sub agent enterprise oid. */ - ptr = asn_build_objid( - ptr, &len, - (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), - smux_oid, smux_oid_len); - - /* IP address. */ - addr.s_addr = 0; - ptr = asn_build_string( - ptr, &len, - (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_IPADDRESS), - (uint8_t *)&addr, sizeof(addr)); - - /* Generic trap integer. */ - val = SNMP_TRAP_ENTERPRISESPECIFIC; - ptr = asn_build_int( - ptr, &len, - (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), - (long *)&val, sizeof(val)); - - /* Specific trap integer. */ - val = sptrap; - ptr = asn_build_int( - ptr, &len, - (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), - (long *)&val, sizeof(val)); - - /* Timeticks timestamp. */ - val = 0; - ptr = asn_build_unsigned_int( - ptr, &len, - (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_TIMETICKS), &val, - sizeof(val)); - - /* Variables. */ - h1 = ptr; - ptr = asn_build_sequence(ptr, &len, - (uint8_t)(ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); - - - /* Iteration for each objects. */ - h1e = ptr; - for (i = 0; i < trapobjlen; i++) { - int ret; - oid oid[MAX_OID_LEN]; - size_t oid_len; - void *val; - size_t val_len; - uint8_t val_type; - - /* Make OID. */ - if (trapobj[i].namelen > 0) { - oid_copy(oid, name, namelen); - oid_copy(oid + namelen, trapobj[i].name, - trapobj[i].namelen); - oid_copy(oid + namelen + trapobj[i].namelen, iname, - inamelen); - oid_len = namelen + trapobj[i].namelen + inamelen; - } else { - oid_copy(oid, name, namelen); - oid_copy(oid + namelen, trapobj[i].name, - trapobj[i].namelen * (-1)); - oid_len = namelen + trapobj[i].namelen * (-1); - } - - if (debug_smux) { - smux_oid_dump("Trap", name, namelen); - if (trapobj[i].namelen < 0) - smux_oid_dump("Trap", trapobj[i].name, - (-1) * (trapobj[i].namelen)); - else { - smux_oid_dump("Trap", trapobj[i].name, - (trapobj[i].namelen)); - smux_oid_dump("Trap", iname, inamelen); - } - smux_oid_dump("Trap", oid, oid_len); - zlog_info("BUFSIZ: %d // oid_len: %lu", BUFSIZ, - (unsigned long)oid_len); - } - - ret = smux_get(oid, &oid_len, 1, &val_type, &val, &val_len); - - if (debug_smux) - zlog_debug("smux_get result %d", ret); - - if (ret == 0) - ptr = snmp_build_var_op(ptr, oid, &oid_len, val_type, - val_len, val, &len); - } - - /* Now variable size is known, fill in size */ - asn_build_sequence(h1, &length, - (uint8_t)(ASN_SEQUENCE | ASN_CONSTRUCTOR), - ptr - h1e); - - /* Fill in size of whole sequence */ - len = BUFSIZ; - asn_build_header(buf, &len, (uint8_t)SMUX_TRAP, (ptr - buf) - 2); - - return send(smux_sock, buf, (ptr - buf), 0); -} - -static int smux_register(int sock) -{ - uint8_t buf[BUFSIZ]; - uint8_t *ptr; - int ret; - size_t len; - long priority; - long operation; - struct subtree *subtree; - struct listnode *node, *nnode; - - ret = 0; - - for (ALL_LIST_ELEMENTS(treelist, node, nnode, subtree)) { - ptr = buf; - len = BUFSIZ; - - /* SMUX RReq Header. */ - ptr = asn_build_header(ptr, &len, (uint8_t)SMUX_RREQ, 0); - - /* Register MIB tree. */ - ptr = asn_build_objid(ptr, &len, - (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE - | ASN_OBJECT_ID), - subtree->name, subtree->name_len); - - /* Priority. */ - priority = -1; - ptr = asn_build_int( - ptr, &len, - (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), - &priority, sizeof(priority)); - - /* Operation. */ - operation = 2; /* Register R/W */ - ptr = asn_build_int( - ptr, &len, - (uint8_t)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), - &operation, sizeof(operation)); - - if (debug_smux) { - smux_oid_dump("SMUX register oid", subtree->name, - subtree->name_len); - zlog_debug("SMUX register priority: %ld", priority); - zlog_debug("SMUX register operation: %ld", operation); - } - - len = BUFSIZ; - asn_build_header(buf, &len, (uint8_t)SMUX_RREQ, - (ptr - buf) - 2); - ret = send(sock, buf, (ptr - buf), 0); - if (ret < 0) - return ret; - } - return ret; -} - -/* Try to connect to SNMP agent. */ -static int smux_connect(struct thread *t) -{ - int ret; - - if (debug_smux) - zlog_debug("SMUX connect try %d", fail + 1); - - /* Clear thread poner of myself. */ - smux_connect_thread = NULL; - - /* Make socket. Try to connect. */ - smux_sock = smux_socket(); - if (smux_sock < 0) { - if (++fail < SMUX_MAX_FAILURE) - smux_event(SMUX_CONNECT, 0); - return 0; - } - - /* Send OPEN PDU. */ - ret = smux_open(smux_sock); - if (ret < 0) { - zlog_warn("SMUX open message send failed: %s", - safe_strerror(errno)); - close(smux_sock); - smux_sock = -1; - if (++fail < SMUX_MAX_FAILURE) - smux_event(SMUX_CONNECT, 0); - return -1; - } - - /* Send any outstanding register PDUs. */ - ret = smux_register(smux_sock); - if (ret < 0) { - zlog_warn("SMUX register message send failed: %s", - safe_strerror(errno)); - close(smux_sock); - smux_sock = -1; - if (++fail < SMUX_MAX_FAILURE) - smux_event(SMUX_CONNECT, 0); - return -1; - } - - /* Everything goes fine. */ - smux_event(SMUX_READ, smux_sock); - - return 0; -} - -/* Clear all SMUX related resources. */ -static void smux_stop(void) -{ - if (smux_read_thread) { - thread_cancel(smux_read_thread); - smux_read_thread = NULL; - } - - if (smux_connect_thread) { - thread_cancel(smux_connect_thread); - smux_connect_thread = NULL; - } - - if (smux_sock >= 0) { - close(smux_sock); - smux_sock = -1; - } -} - - -void smux_event(enum smux_event event, int sock) -{ - switch (event) { - case SMUX_SCHEDULE: - smux_connect_thread = NULL; - thread_add_event(smux_master, smux_connect, NULL, 0, - &smux_connect_thread); - break; - case SMUX_CONNECT: - smux_connect_thread = NULL; - thread_add_timer(smux_master, smux_connect, NULL, 10, - &smux_connect_thread); - break; - case SMUX_READ: - smux_read_thread = NULL; - thread_add_read(smux_master, smux_read, NULL, sock, - &smux_read_thread); - break; - default: - break; - } -} - -static int smux_str2oid(const char *str, oid *oid, size_t *oid_len) -{ - int len; - int val; - - len = 0; - val = 0; - *oid_len = 0; - - if (*str == '.') - str++; - if (*str == '\0') - return 0; - - while (1) { - if (!isdigit(*str)) - return -1; - - while (isdigit(*str)) { - val *= 10; - val += (*str - '0'); - str++; - } - - if (*str == '\0') - break; - if (*str != '.') - return -1; - - oid[len++] = val; - val = 0; - str++; - } - - oid[len++] = val; - *oid_len = len; - - return 0; -} - -static oid *smux_oid_dup(oid *objid, size_t objid_len) -{ - oid *new; - - new = XMALLOC(MTYPE_TMP, sizeof(oid) * objid_len); - oid_copy(new, objid, objid_len); - - return new; -} - -static int smux_peer_oid(struct vty *vty, const char *oid_str, - const char *passwd_str) -{ - int ret; - oid oid[MAX_OID_LEN]; - size_t oid_len; - - ret = smux_str2oid(oid_str, oid, &oid_len); - if (ret != 0) { - vty_out(vty, "object ID malformed\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - if (smux_oid) { - free(smux_oid); - smux_oid = NULL; - } - - /* careful, smux_passwd might point to string constant */ - if (smux_passwd) { - free(smux_passwd); - smux_passwd = NULL; - } - - smux_oid = smux_oid_dup(oid, oid_len); - smux_oid_len = oid_len; - - if (passwd_str) - smux_passwd = strdup(passwd_str); - else - smux_passwd = strdup(""); - - return 0; -} - -static int smux_peer_default(void) -{ - if (smux_oid) { - free(smux_oid); - smux_oid = NULL; - } - - /* careful, smux_passwd might be pointing at string constant */ - if (smux_passwd) { - free(smux_passwd); - smux_passwd = NULL; - } - - return CMD_SUCCESS; -} - -DEFUN (smux_peer, - smux_peer_cmd, - "smux peer OID", - "SNMP MUX protocol settings\n" - "SNMP MUX peer settings\n" - "Object ID used in SMUX peering\n") -{ - int idx_oid = 2; - if (smux_peer_oid(vty, argv[idx_oid]->arg, NULL) == 0) { - smux_start(); - return CMD_SUCCESS; - } else - return CMD_WARNING_CONFIG_FAILED; -} - -DEFUN (smux_peer_password, - smux_peer_password_cmd, - "smux peer OID PASSWORD", - "SNMP MUX protocol settings\n" - "SNMP MUX peer settings\n" - "SMUX peering object ID\n" - "SMUX peering password\n") -{ - int idx_oid = 2; - if (smux_peer_oid(vty, argv[idx_oid]->arg, argv[3]->rg) == 0) { - smux_start(); - return CMD_SUCCESS; - } else - return CMD_WARNING_CONFIG_FAILED; -} - -DEFUN (no_smux_peer, - no_smux_peer_cmd, - "no smux peer [OID [PASSWORD]]", - NO_STR - "SNMP MUX protocol settings\n" - "SNMP MUX peer settings\n" - "SMUX peering object ID\n" - "SMUX peering password\n") -{ - smux_stop(); - return smux_peer_default(); -} - -static int config_write_smux(struct vty *vty) -{ - int first = 1; - unsigned int i; - - if (smux_oid) { - vty_out(vty, "smux peer "); - for (i = 0; i < smux_oid_len; i++) { - vty_out(vty, "%s%d", first ? "" : ".", - (int)smux_oid[i]); - first = 0; - } - vty_out(vty, " %s\n", smux_passwd); - } - return 0; -} - -/* Register subtree to smux master tree. */ -void smux_register_mib(const char *descr, struct variable *var, size_t width, - int num, oid name[], size_t namelen) -{ - struct subtree *tree; - - tree = (struct subtree *)malloc(sizeof(struct subtree)); - oid_copy(tree->name, name, namelen); - tree->name_len = namelen; - tree->variables = var; - tree->variables_num = num; - tree->variables_width = width; - tree->registered = 0; - listnode_add_sort(treelist, tree); -} - -/* Compare function to keep treelist sorted */ -static int smux_tree_cmp(struct subtree *tree1, struct subtree *tree2) -{ - return oid_compare(tree1->name, tree1->name_len, tree2->name, - tree2->name_len); -} - -/* Initialize some values then schedule first SMUX connection. */ -void smux_init(struct thread_master *tm) -{ - assert(tm); - /* copy callers thread master */ - smux_master = tm; - - /* Make MIB tree. */ - treelist = list_new(); - treelist->cmp = (int (*)(void *, void *))smux_tree_cmp; - - /* Install commands. */ - install_node(&smux_node, config_write_smux); - - install_element(CONFIG_NODE, &smux_peer_cmd); - install_element(CONFIG_NODE, &smux_peer_password_cmd); - install_element(CONFIG_NODE, &no_smux_peer_cmd); - install_element(CONFIG_NODE, &no_smux_peer_oid_cmd); - install_element(CONFIG_NODE, &no_smux_peer_oid_password_cmd); -} - -void smux_start(void) -{ - /* Close any existing connections. */ - smux_stop(); - - /* Schedule first connection. */ - smux_event(SMUX_SCHEDULE, 0); -} -#endif /* SNMP_SMUX */ diff --git a/lib/subdir.am b/lib/subdir.am index b938dbcea3..50cfd70a57 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -150,7 +150,6 @@ pkginclude_HEADERS += \ lib/sha256.h \ lib/sigevent.h \ lib/skiplist.h \ - lib/smux.h \ lib/sockopt.h \ lib/sockunion.h \ lib/spf_backoff.h \ @@ -199,7 +198,6 @@ lib_libfrrsnmp_la_LDFLAGS = -version-info 0:0:0 lib_libfrrsnmp_la_LIBADD = lib/libfrr.la $(SNMP_LIBS) lib_libfrrsnmp_la_SOURCES = \ lib/agentx.c \ - lib/smux.c \ lib/snmp.c \ # end From 07436e2a526ec10355eb8aa7efc6063d8eb5eeb5 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 16 Aug 2018 13:56:44 -0400 Subject: [PATCH 44/66] lib: Remove zlog_warn from some places in buffer.c zlog_warn was being used to inform user of impossible situations or for normal operations. Remove these from the code. Signed-off-by: Donald Sharp --- lib/buffer.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/lib/buffer.c b/lib/buffer.c index 0292c85dac..1799c6b94f 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -274,19 +274,12 @@ buffer_status_t buffer_flush_window(struct buffer *b, int fd, int width, if (!b->head) return BUFFER_EMPTY; - if (height < 1) { - zlog_warn( - "%s called with non-positive window height %d, forcing to 1", - __func__, height); + if (height < 1) height = 1; - } else if (height >= 2) + else if (height >= 2) height--; - if (width < 1) { - zlog_warn( - "%s called with non-positive window width %d, forcing to 1", - __func__, width); + if (width < 1) width = 1; - } /* For erase and more data add two to b's buffer_data count.*/ if (b->head->next == NULL) { @@ -334,11 +327,6 @@ buffer_status_t buffer_flush_window(struct buffer *b, int fd, int width, { iov_alloc *= 2; if (iov != small_iov) { - zlog_warn( - "%s: growing iov array to %d; " - "width %d, height %d, size %lu", - __func__, iov_alloc, width, height, - (unsigned long)b->size); iov = XREALLOC(MTYPE_TMP, iov, iov_alloc * sizeof(*iov)); } else { From 496764bbfbf66980fd533669eb213b2777f94b6a Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 16 Aug 2018 13:59:27 -0400 Subject: [PATCH 45/66] lib: Remove default case statement from a enum driven switch We are using a enum to drive a switch statement and we have a default case statement that can never be entered because we know all the enum states have been covered. Remove it from the code as that it cannot happen. Signed-off-by: Donald Sharp --- lib/spf_backoff.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/spf_backoff.c b/lib/spf_backoff.c index c420c25f04..41d4e2bb57 100644 --- a/lib/spf_backoff.c +++ b/lib/spf_backoff.c @@ -143,7 +143,7 @@ static int spf_backoff_holddown_elapsed(struct thread *thread) long spf_backoff_schedule(struct spf_backoff *backoff) { - long rv; + long rv = 0; struct timeval now; gettimeofday(&now, NULL); @@ -176,9 +176,6 @@ long spf_backoff_schedule(struct spf_backoff *backoff) else rv = backoff->long_delay; break; - default: - zlog_warn("SPF Back-off(%s) in unknown state", backoff->name); - rv = backoff->init_delay; } backoff_debug( From 03548ae8180f3e73468ce577368a9239e50ec848 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Mon, 20 Aug 2018 08:08:28 -0400 Subject: [PATCH 46/66] lib: Convert debug to error situation This debug should be moved to an error situation since it's a developmental escape that needs to be fixed. Signed-off-by: Donald Sharp --- lib/if.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/if.c b/lib/if.c index 11c4f1b5dc..943436f356 100644 --- a/lib/if.c +++ b/lib/if.c @@ -1141,7 +1141,7 @@ const char *if_link_type_str(enum zebra_link_type llt) llts(ZEBRA_LLT_IEEE802154, "IEEE 802.15.4"); llts(ZEBRA_LLT_IEEE802154_PHY, "IEEE 802.15.4 Phy"); default: - zlog_warn("Unknown value %d", llt); + flog_err(LIB_ERR_DEVELOPMENT, "Unknown value %d", llt); return "Unknown type!"; #undef llts } From 6ed04aa2ebcb350046cbffa2e7452e8588aa7690 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Wed, 22 Aug 2018 20:59:46 -0400 Subject: [PATCH 47/66] lib: Limit depth of unused thread list The master->unused list was unbounded during normal operation. A full BGP feed on my machine left 11k threads on the unused list, taking up over 2mb of data. This seemed a bit excessive, reduce to a limit of 10. Also fix a crash that this exposed where we assumed that a thread structure was not deleted. Future committers can make this configurable? or modify the value to something better for their system. I am dubious of the value of this. Signed-off-by: Donald Sharp --- lib/thread.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/thread.c b/lib/thread.c index c6894be4ee..52bc79ffe6 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -532,17 +532,23 @@ static struct thread *thread_trim_head(struct thread_list *list) return NULL; } +#define THREAD_UNUSED_DEPTH 10 + /* Move thread to unuse list. */ static void thread_add_unuse(struct thread_master *m, struct thread *thread) { assert(m != NULL && thread != NULL); assert(thread->next == NULL); assert(thread->prev == NULL); - thread->ref = NULL; - thread->type = THREAD_UNUSED; thread->hist->total_active--; - thread_list_add(&m->unuse, thread); + memset(thread, 0, sizeof(struct thread)); + thread->type = THREAD_UNUSED; + + if (m->unuse.count < THREAD_UNUSED_DEPTH) + thread_list_add(&m->unuse, thread); + else + XFREE(MTYPE_THREAD, thread); } /* Free all unused thread. */ @@ -1175,17 +1181,19 @@ void thread_cancel_event(struct thread_master *master, void *arg) */ void thread_cancel(struct thread *thread) { - assert(thread->master->owner == pthread_self()); + struct thread_master *master = thread->master; - pthread_mutex_lock(&thread->master->mtx); + assert(master->owner == pthread_self()); + + pthread_mutex_lock(&master->mtx); { struct cancel_req *cr = XCALLOC(MTYPE_TMP, sizeof(struct cancel_req)); cr->thread = thread; - listnode_add(thread->master->cancel_req, cr); - do_thread_cancel(thread->master); + listnode_add(master->cancel_req, cr); + do_thread_cancel(master); } - pthread_mutex_unlock(&thread->master->mtx); + pthread_mutex_unlock(&master->mtx); } /** From 61a484a90a4a7c0ddfabc5425261c1ed76976c5c Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Wed, 22 Aug 2018 20:05:04 +0000 Subject: [PATCH 48/66] bgpd: fix rpki exit command If a command returns a nonzero exit status and VTYSH has a corresponding command, VTYSH will skip executing its own version. If this happens in a command that changes CLI nodes we get node desynchronization. Signed-off-by: Quentin Young --- bgpd/bgp_rpki.c | 4 ++-- vtysh/vtysh.c | 35 +++++++++++++++++------------------ 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 52c5dc5e90..14e5193332 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -1210,10 +1210,10 @@ DEFUN_NOSH (rpki_exit, "exit", "Exit rpki configuration and restart rpki session\n") { - int ret = reset(false); + reset(false); vty->node = CONFIG_NODE; - return ret == SUCCESS ? CMD_SUCCESS : CMD_WARNING; + return CMD_SUCCESS; } DEFUN_NOSH (rpki_quit, diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index ef4d1a0835..c249115fd3 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -1435,24 +1435,6 @@ DEFUNSH(VTYSH_BGPD, return CMD_SUCCESS; } -DEFUNSH(VTYSH_BGPD, - rpki_exit, - rpki_exit_cmd, - "exit", - "Exit current mode and down to previous mode\n") -{ - vty->node = CONFIG_NODE; - return CMD_SUCCESS; -} - -DEFUNSH(VTYSH_BGPD, - rpki_quit, - rpki_quit_cmd, - "quit", - "Exit current mode and down to previous mode\n") -{ - return rpki_exit(self, vty, argc, argv); -} #endif DEFUNSH(VTYSH_BGPD, address_family_evpn, address_family_evpn_cmd, @@ -1790,6 +1772,7 @@ static int vtysh_exit(struct vty *vty) case VTY_NODE: case KEYCHAIN_NODE: case BFD_NODE: + case RPKI_NODE: vtysh_execute("end"); vtysh_execute("configure terminal"); vty->node = CONFIG_NODE; @@ -1883,8 +1866,24 @@ DEFUNSH(VTYSH_BGPD, exit_vnc_config, exit_vnc_config_cmd, "exit-vnc", || vty->node == BGP_VNC_L2_GROUP_NODE) vty->node = BGP_NODE; return CMD_SUCCESS; + } +#if defined(HAVE_RPKI) +DEFUNSH(VTYSH_BGPD, rpki_exit, rpki_exit_cmd, "exit", + "Exit current mode and down to previous mode\n") +{ + vtysh_exit(vty); + return CMD_SUCCESS; +} + +DEFUNSH(VTYSH_BGPD, rpki_quit, rpki_quit_cmd, "quit", + "Exit current mode and down to previous mode\n") +{ + return rpki_exit(self, vty, argc, argv); +} +#endif /* HAVE_RPKI */ + DEFUNSH(VTYSH_PIMD|VTYSH_ZEBRA, exit_vrf_config, exit_vrf_config_cmd, "exit-vrf", "Exit from VRF configuration mode\n") { From fec4ca191ef4e7d9576feba756f728b21819ec45 Mon Sep 17 00:00:00 2001 From: Don Slice Date: Tue, 21 Aug 2018 18:03:00 +0000 Subject: [PATCH 49/66] zebra: if multiple connecteds, select loopback or vrf if present Signed-off-by: Don Slice --- lib/if.c | 8 ++++++++ lib/if.h | 1 + pimd/pim_iface.c | 8 -------- pimd/pim_iface.h | 2 -- pimd/pim_pim.c | 4 ++-- zebra/zebra_rib.c | 26 +++++++++++++++++++++++--- 6 files changed, 34 insertions(+), 15 deletions(-) diff --git a/lib/if.c b/lib/if.c index 943436f356..2bf0c6e6b5 100644 --- a/lib/if.c +++ b/lib/if.c @@ -472,6 +472,14 @@ int if_is_vrf(struct interface *ifp) return CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK); } +bool if_is_loopback_or_vrf(struct interface *ifp) +{ + if (if_is_loopback(ifp) || if_is_vrf(ifp)) + return true; + + return false; +} + /* Does this interface support broadcast ? */ int if_is_broadcast(struct interface *ifp) { diff --git a/lib/if.h b/lib/if.h index 3a9c4af848..a861cf2d85 100644 --- a/lib/if.h +++ b/lib/if.h @@ -497,6 +497,7 @@ extern int if_is_operative(struct interface *); extern int if_is_no_ptm_operative(struct interface *); extern int if_is_loopback(struct interface *); extern int if_is_vrf(struct interface *ifp); +extern bool if_is_loopback_or_vrf(struct interface *ifp); extern int if_is_broadcast(struct interface *); extern int if_is_pointopoint(struct interface *); extern int if_is_multicast(struct interface *); diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index e79e91d7df..72ccf3ab1e 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -1495,14 +1495,6 @@ int pim_if_connected_to_source(struct interface *ifp, struct in_addr src) return 0; } -bool pim_if_is_loopback(struct interface *ifp) -{ - if (if_is_loopback(ifp) || if_is_vrf(ifp)) - return true; - - return false; -} - bool pim_if_is_vrf_device(struct interface *ifp) { if (if_is_vrf(ifp)) diff --git a/pimd/pim_iface.h b/pimd/pim_iface.h index cf025cbd4a..02926a6973 100644 --- a/pimd/pim_iface.h +++ b/pimd/pim_iface.h @@ -207,8 +207,6 @@ void pim_if_create_pimreg(struct pim_instance *pim); int pim_if_connected_to_source(struct interface *ifp, struct in_addr src); int pim_update_source_set(struct interface *ifp, struct in_addr source); -bool pim_if_is_loopback(struct interface *ifp); - bool pim_if_is_vrf_device(struct interface *ifp); int pim_if_ifchannel_count(struct pim_interface *pim_ifp); diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index b103da2e1b..7113d5405e 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -655,7 +655,7 @@ static int pim_hello_send(struct interface *ifp, uint16_t holdtime) { struct pim_interface *pim_ifp = ifp->info; - if (pim_if_is_loopback(ifp)) + if (if_is_loopback_or_vrf(ifp)) return 0; if (hello_send(ifp, holdtime)) { @@ -757,7 +757,7 @@ void pim_hello_restart_triggered(struct interface *ifp) /* * No need to ever start loopback or vrf device hello's */ - if (pim_if_is_loopback(ifp)) + if (if_is_loopback_or_vrf(ifp)) return; /* diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 99b83d5cd9..ab07549ec2 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1501,17 +1501,37 @@ static struct route_entry *rib_choose_best(struct route_entry *current, /* filter route selection in following order: * - connected beats other types + * - if both connected, loopback or vrf wins * - lower distance beats higher * - lower metric beats higher for equal distance * - last, hence oldest, route wins tie break. */ - /* Connected routes. Pick the last connected + /* Connected routes. Check to see if either are a vrf + * or loopback interface. If not, pick the last connected * route of the set of lowest metric connected routes. */ if (alternate->type == ZEBRA_ROUTE_CONNECT) { - if (current->type != ZEBRA_ROUTE_CONNECT - || alternate->metric <= current->metric) + if (current->type != ZEBRA_ROUTE_CONNECT) + return alternate; + + /* both are connected. are either loop or vrf? */ + struct nexthop *nexthop = NULL; + + for (ALL_NEXTHOPS(alternate->ng, nexthop)) { + if (if_is_loopback_or_vrf(if_lookup_by_index( + nexthop->ifindex, alternate->vrf_id))) + return alternate; + } + + for (ALL_NEXTHOPS(current->ng, nexthop)) { + if (if_is_loopback_or_vrf(if_lookup_by_index( + nexthop->ifindex, current->vrf_id))) + return current; + } + + /* Neither are loop or vrf so pick best metric */ + if (alternate->metric <= current->metric) return alternate; return current; From 4a8bf85858da85e5ec51921d3530402c4e42f68d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 23 Aug 2018 19:58:36 -0400 Subject: [PATCH 50/66] lib: Convert vrf bit-map to a hash. Memory sizes of the vrf bit-map was insane for a system with a moderate number of data on it: Zebra: VRF bit-map : 601 65536 39391944 Having a full 32bit integer bit space is problematically large, switch over to a hash to store bit data. We do not need to waste so much space. VRF bit-map : 13 8 312 Signed-off-by: Donald Sharp --- lib/vrf.c | 116 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 64 insertions(+), 52 deletions(-) diff --git a/lib/vrf.c b/lib/vrf.c index 3c7342bb98..ecd09a6b91 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -342,91 +342,103 @@ void *vrf_info_lookup(vrf_id_t vrf_id) } /* - * VRF bit-map + * VRF hash for storing set or not. */ - -#define VRF_BITMAP_NUM_OF_GROUPS 1024 -#define VRF_BITMAP_NUM_OF_BITS_IN_GROUP (UINT32_MAX / VRF_BITMAP_NUM_OF_GROUPS) -#define VRF_BITMAP_NUM_OF_BYTES_IN_GROUP \ - (VRF_BITMAP_NUM_OF_BITS_IN_GROUP / CHAR_BIT + 1) /* +1 for ensure */ - -#define VRF_BITMAP_GROUP(_id) ((_id) / VRF_BITMAP_NUM_OF_BITS_IN_GROUP) -#define VRF_BITMAP_BIT_OFFSET(_id) ((_id) % VRF_BITMAP_NUM_OF_BITS_IN_GROUP) - -#define VRF_BITMAP_INDEX_IN_GROUP(_bit_offset) ((_bit_offset) / CHAR_BIT) -#define VRF_BITMAP_FLAG(_bit_offset) \ - (((uint8_t)1) << ((_bit_offset) % CHAR_BIT)) - -struct vrf_bitmap { - uint8_t *groups[VRF_BITMAP_NUM_OF_GROUPS]; +struct vrf_bit_set { + vrf_id_t vrf_id; + bool set; }; +static unsigned int vrf_hash_bitmap_key(void *data) +{ + struct vrf_bit_set *bit = data; + + return bit->vrf_id; +} + +static int vrf_hash_bitmap_cmp(const void *a, const void *b) +{ + const struct vrf_bit_set *bit1 = a; + const struct vrf_bit_set *bit2 = b; + + return bit1->vrf_id == bit2->vrf_id; +} + +static void *vrf_hash_bitmap_alloc(void *data) +{ + struct vrf_bit_set *copy = data; + struct vrf_bit_set *bit; + + bit = XMALLOC(MTYPE_VRF_BITMAP, sizeof(*bit)); + bit->vrf_id = copy->vrf_id; + + return bit; +} + +static void vrf_hash_bitmap_free(void *data) +{ + struct vrf_bit_set *bit = data; + + XFREE(MTYPE_VRF_BITMAP, bit); +} + vrf_bitmap_t vrf_bitmap_init(void) { - return (vrf_bitmap_t)XCALLOC(MTYPE_VRF_BITMAP, - sizeof(struct vrf_bitmap)); + return hash_create_size(32, vrf_hash_bitmap_key, vrf_hash_bitmap_cmp, + "VRF BIT HASH"); } void vrf_bitmap_free(vrf_bitmap_t bmap) { - struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap; - int i; + struct hash *vrf_hash = bmap; - if (bmap == VRF_BITMAP_NULL) + if (vrf_hash == NULL) return; - for (i = 0; i < VRF_BITMAP_NUM_OF_GROUPS; i++) - if (bm->groups[i]) - XFREE(MTYPE_VRF_BITMAP, bm->groups[i]); - - XFREE(MTYPE_VRF_BITMAP, bm); + hash_clean(vrf_hash, vrf_hash_bitmap_free); + hash_free(vrf_hash); } void vrf_bitmap_set(vrf_bitmap_t bmap, vrf_id_t vrf_id) { - struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap; - uint8_t group = VRF_BITMAP_GROUP(vrf_id); - uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id); + struct vrf_bit_set lookup = { .vrf_id = vrf_id }; + struct hash *vrf_hash = bmap; + struct vrf_bit_set *bit; - if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN) + if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN) return; - if (bm->groups[group] == NULL) - bm->groups[group] = XCALLOC(MTYPE_VRF_BITMAP, - VRF_BITMAP_NUM_OF_BYTES_IN_GROUP); - - SET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)], - VRF_BITMAP_FLAG(offset)); + bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc); + bit->set = true; } void vrf_bitmap_unset(vrf_bitmap_t bmap, vrf_id_t vrf_id) { - struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap; - uint8_t group = VRF_BITMAP_GROUP(vrf_id); - uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id); + struct vrf_bit_set lookup = { .vrf_id = vrf_id }; + struct hash *vrf_hash = bmap; + struct vrf_bit_set *bit; - if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN - || bm->groups[group] == NULL) + if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN) return; - UNSET_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)], - VRF_BITMAP_FLAG(offset)); + bit = hash_get(vrf_hash, &lookup, vrf_hash_bitmap_alloc); + bit->set = false; } int vrf_bitmap_check(vrf_bitmap_t bmap, vrf_id_t vrf_id) { - struct vrf_bitmap *bm = (struct vrf_bitmap *)bmap; - uint8_t group = VRF_BITMAP_GROUP(vrf_id); - uint8_t offset = VRF_BITMAP_BIT_OFFSET(vrf_id); + struct vrf_bit_set lookup = { .vrf_id = vrf_id }; + struct hash *vrf_hash = bmap; + struct vrf_bit_set *bit; - if (bmap == VRF_BITMAP_NULL || vrf_id == VRF_UNKNOWN - || bm->groups[group] == NULL) + if (vrf_hash == NULL || vrf_id == VRF_UNKNOWN) return 0; - return CHECK_FLAG(bm->groups[group][VRF_BITMAP_INDEX_IN_GROUP(offset)], - VRF_BITMAP_FLAG(offset)) - ? 1 - : 0; + bit = hash_lookup(vrf_hash, &lookup); + if (bit) + return bit->set; + + return 0; } static void vrf_autocomplete(vector comps, struct cmd_token *token) From 4ec715c8304a796dbba76692a5767ef507671ca3 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Aug 2018 10:49:20 -0400 Subject: [PATCH 51/66] zebra: Remove unmaintained and uncompilable code The zebra/client_main.c code is not being maintained or used. Remove from system. Especially since the encode/decode zapi functionality it `purports` to be testing is deprecated and now being removed. Signed-off-by: Donald Sharp --- zebra/client_main.c | 208 -------------------------------------------- zebra/subdir.am | 5 -- 2 files changed, 213 deletions(-) delete mode 100644 zebra/client_main.c diff --git a/zebra/client_main.c b/zebra/client_main.c deleted file mode 100644 index 1ead7ee1fd..0000000000 --- a/zebra/client_main.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * GNU Zebra client test main routine. - * Copyright (C) 1997 Kunihiro Ishiguro - * - * This file is part of GNU Zebra. - * - * GNU Zebra is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * GNU Zebra is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; see the file COPYING; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include "prefix.h" -#include "stream.h" -#include "zclient.h" -#include "thread.h" -#include "table.h" -#include "zebra/rib.h" -#include "zebra/zserv.h" - -struct thread *master; - -/* Zebra client structure. */ -struct zclient *zclient = NULL; - -/* Zebra socket. */ -int sock; - -/* IPv4 route add and delete test. */ -void zebra_test_ipv4(int command, int type, char *prefix, char *gateway, - uint8_t distance) -{ - struct zapi_ipv4 api; - struct prefix_ipv4 p; - struct in_addr gate; - struct in_addr *gpnt; - - str2prefix_ipv4(prefix, &p); - if (!inet_aton(gateway, &gate)) { - printf("Gateway specified: %s is illegal\n", gateway); - return; - } - - gpnt = &gate; - - api.vrf_id = VRF_DEFAULT; - api.type = type; - api.flags = 0; - - api.message = 0; - SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); - api.nexthop_num = 1; - api.nexthop = &gpnt; - api.ifindex_num = 0; - if (distance) { - SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); - api.distance = distance; - } - - - switch (command) { - case ZEBRA_IPV4_ROUTE_ADD: - zapi_ipv4_add(zclient, &p, &api); - break; - case ZEBRA_IPV4_ROUTE_DELETE: - zapi_ipv4_delete(zclient, &p, &api); - break; - } -} - -/* IPv6 route add and delete test. */ -void zebra_test_v6(int sock) -{ - struct prefix_ipv6 p; - struct in6_addr nexthop; - - str2prefix_ipv6("3ffe:506::2/128", &p); - inet_pton(AF_INET6, "::1", &nexthop); - - /* zebra_ipv6_add (sock, ZEBRA_ROUTE_STATIC, 0, &p, &nexthop, 1); */ - - sleep(5); - /* zebra_ipv6_delete (sock, ZEBRA_ROUTE_STATIC, 0, &p, &nexthop, 1); */ -} - -/* Print out usage and exit. */ -void usage_exit() -{ - fprintf(stderr, "Usage: client filename\n"); - exit(1); -} - -struct zebra_info { - char *str; - int type; -} zebra_type[] = {{"static", ZEBRA_ROUTE_STATIC}, - {"rip", ZEBRA_ROUTE_RIP}, - {"ripng", ZEBRA_ROUTE_RIPNG}, - {"ospf", ZEBRA_ROUTE_OSPF}, - {"ospf6", ZEBRA_ROUTE_OSPF6}, - {"bgp", ZEBRA_ROUTE_BGP}, - {"nhrp", ZEBRA_ROUTE_NHRP}, - {"pim", ZEBRA_ROUTE_PIM}, - {NULL, 0}}; - -/* Zebra route simulator. */ -void zebra_sim(FILE *fp) -{ - char buf[BUFSIZ]; - char distance_str[BUFSIZ]; - uint8_t distance; - - while (fgets(buf, sizeof buf, fp)) { - int i; - int ret; - int type; - char str[BUFSIZ], command[BUFSIZ], prefix[BUFSIZ], - gateway[BUFSIZ]; - - distance = 0; - - if (*buf == '#') - continue; - - type = ZEBRA_ROUTE_STATIC; - - ret = sscanf(buf, "%s %s %s %s %s\n", command, str, prefix, - gateway, distance_str); - - if (ret == 5) { - distance = atoi(distance_str); - } else { - ret = sscanf(buf, "%s %s %s %s\n", command, str, prefix, - gateway); - - if (ret != 4) - continue; - } - - i = 0; - while (zebra_type[i++].str) { - if (strcmp(zebra_type[i].str, str) == 0) { - type = zebra_type[i].type; - break; - } - } - - if (strcmp(command, "add") == 0) { - zebra_test_ipv4(ZEBRA_IPV4_ROUTE_ADD, type, prefix, - gateway, distance); - printf("%s", buf); - continue; - } - - if (strcmp(command, "del") == 0) { - zebra_test_ipv4(ZEBRA_IPV4_ROUTE_DELETE, type, prefix, - gateway, distance); - printf("%s", buf); - continue; - } - } -} - -/* Test zebra client main routine. */ -int main(int argc, char **argv) -{ - struct thread_master *master; - FILE *fp; - - if (argc == 1) - usage_exit(); - - master = thread_master_create(NULL); - /* Establish connection to zebra. */ - zclient = zclient_new_notify(master, &zclient_options_default); - zclient->enable = 1; - zclient_socket_connect(zclient); - - /* Open simulation file. */ - fp = fopen(argv[1], "r"); - if (fp == NULL) { - fprintf(stderr, - "%% Can't open configuration file %s due to '%s'\n", - argv[1], safe_strerror(errno)); - exit(1); - } - - /* Do main work. */ - zebra_sim(fp); - - sleep(100); - - fclose(fp); - close(sock); - - return 0; -} diff --git a/zebra/subdir.am b/zebra/subdir.am index f44574b236..69f7bc2041 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -146,8 +146,3 @@ EXTRA_DIST += \ zebra/GNOME-SMI \ zebra/GNOME-PRODUCT-ZEBRA-MIB \ # end - -# -- unmaintained -- -# noinst_PROGRAMS += zebra/client -# zebra_client_SOURCES = zebra/client_main.c -# zebra_client_LDADD = lib/libfrr.la From 0477276088dc20c7be195168441e895cbc567cbf Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Aug 2018 10:56:15 -0400 Subject: [PATCH 52/66] doc, lib, zebra: Remove deprecated encode and decode functionality The ZEBRA_IPV4_ROUTE_[ADD|DELETE] and ZEBRA_IPV6_ROUTE_[ADD|DELETE] functionality has been deprecated for a year now, let's remove this code from the system. Signed-off-by: Donald Sharp --- doc/developer/zebra.rst | 8 - lib/log.c | 4 - lib/zclient.c | 239 +--------------- lib/zclient.h | 85 +----- zebra/zapi_msg.c | 612 ---------------------------------------- 5 files changed, 8 insertions(+), 940 deletions(-) diff --git a/doc/developer/zebra.rst b/doc/developer/zebra.rst index 3d64b67115..1bf31e9624 100644 --- a/doc/developer/zebra.rst +++ b/doc/developer/zebra.rst @@ -102,14 +102,6 @@ Zebra Protocol Commands +-----------------------------------+-------+ | ZEBRA_INTERFACE_DOWN | 6 | +-----------------------------------+-------+ -| ZEBRA_IPV4_ROUTE_ADD | 7 | -+-----------------------------------+-------+ -| ZEBRA_IPV4_ROUTE_DELETE | 8 | -+-----------------------------------+-------+ -| ZEBRA_IPV6_ROUTE_ADD | 9 | -+-----------------------------------+-------+ -| ZEBRA_IPV6_ROUTE_DELETE | 10 | -+-----------------------------------+-------+ | ZEBRA_REDISTRIBUTE_ADD | 11 | +-----------------------------------+-------+ | ZEBRA_REDISTRIBUTE_DELETE | 12 | diff --git a/lib/log.c b/lib/log.c index 361521f568..b067018e08 100644 --- a/lib/log.c +++ b/lib/log.c @@ -908,10 +908,6 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_ROUTE_ADD), DESC_ENTRY(ZEBRA_ROUTE_DELETE), DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_OWNER), - DESC_ENTRY(ZEBRA_IPV4_ROUTE_ADD), - DESC_ENTRY(ZEBRA_IPV4_ROUTE_DELETE), - DESC_ENTRY(ZEBRA_IPV6_ROUTE_ADD), - DESC_ENTRY(ZEBRA_IPV6_ROUTE_DELETE), DESC_ENTRY(ZEBRA_REDISTRIBUTE_ADD), DESC_ENTRY(ZEBRA_REDISTRIBUTE_DELETE), DESC_ENTRY(ZEBRA_REDISTRIBUTE_DEFAULT_ADD), diff --git a/lib/zclient.c b/lib/zclient.c index cc91705ee2..b2bafcb7d8 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -676,11 +676,11 @@ int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p, * "xdr_encode"-like interface that allows daemon (client) to send * a message to zebra server for a route that needs to be * added/deleted to the kernel. Info about the route is specified - * by the caller in a struct zapi_ipv4. zapi_ipv4_read() then writes + * by the caller in a struct zapi_route. zapi_route_encode() then writes * the info down the zclient socket using the stream_* functions. * * The corresponding read ("xdr_decode") function on the server - * side is zread_ipv4_add()/zread_ipv4_delete(). + * side is zapi_route_decode(). * * 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 A B C D E F * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -707,21 +707,16 @@ int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p, * is set to 1 and a nexthop of type NEXTHOP_TYPE_BLACKHOLE is the sole * nexthop. * - * The original struct zapi_ipv4, zapi_ipv4_route() and zread_ipv4_*() - * infrastructure was built around the traditional (32-bit "gate OR - * ifindex") nexthop data unit. A special encoding can be used to feed - * onlink (64-bit "gate AND ifindex") nexthops into zapi_ipv4_route() - * using the same zapi_ipv4 structure. This is done by setting zapi_ipv4 - * fields as follows: + * The original struct zapi_route_*() infrastructure was built around + * the traditional (32-bit "gate OR ifindex") nexthop data unit. + * A special encoding can be used to feed onlink (64-bit "gate AND ifindex") + * nexthops into zapi_route_encode() using the same zapi_route structure. + * This is done by setting zapi_route fields as follows: * - .message |= ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_ONLINK * - .nexthop_num == .ifindex_num * - .nexthop and .ifindex are filled with gate and ifindex parts of * each compound nexthop, both in the same order * - * zapi_ipv4_route() will produce two nexthop data units for each such - * interleaved 64-bit nexthop. On the zserv side of the socket it will be - * mapped to a singlle NEXTHOP_TYPE_IPV4_IFINDEX_OL RIB nexthop structure. - * * If ZAPI_MESSAGE_DISTANCE is set, the distance value is written as a 1 * byte value. * @@ -734,226 +729,6 @@ int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p, * * XXX: No attention paid to alignment. */ -int zapi_ipv4_route(uint8_t cmd, struct zclient *zclient, struct prefix_ipv4 *p, - struct zapi_ipv4 *api) -{ - int i; - int psize; - struct stream *s; - - /* Reset stream. */ - s = zclient->obuf; - stream_reset(s); - - /* Some checks for labeled-unicast. The current expectation is that each - * nexthop is accompanied by a label in the case of labeled-unicast. - */ - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL) - && CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { - /* We expect prefixes installed with labels and the number to - * match - * the number of nexthops. - */ - assert(api->label_num == api->nexthop_num); - } - - zclient_create_header(s, cmd, api->vrf_id); - - /* Put type and nexthop. */ - stream_putc(s, api->type); - stream_putw(s, api->instance); - stream_putl(s, api->flags); - stream_putc(s, api->message); - stream_putw(s, api->safi); - - /* Put prefix information. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (uint8_t *)&p->prefix, psize); - - /* Nexthop, ifindex, distance and metric information. */ - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { - stream_putc(s, api->nexthop_num + api->ifindex_num); - - for (i = 0; i < api->nexthop_num; i++) { - stream_putc(s, NEXTHOP_TYPE_IPV4); - stream_put_in_addr(s, api->nexthop[i]); - /* For labeled-unicast, each nexthop is followed by - * label. */ - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) - stream_putl(s, api->label[i]); - } - for (i = 0; i < api->ifindex_num; i++) { - stream_putc(s, NEXTHOP_TYPE_IFINDEX); - stream_putl(s, api->ifindex[i]); - } - } - - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE)) - stream_putc(s, api->distance); - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC)) - stream_putl(s, api->metric); - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG)) - stream_putl(s, api->tag); - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU)) - stream_putl(s, api->mtu); - - /* Put length at the first point of the stream. */ - stream_putw_at(s, 0, stream_get_endp(s)); - - return zclient_send_message(zclient); -} - -int zapi_ipv4_route_ipv6_nexthop(uint8_t cmd, struct zclient *zclient, - struct prefix_ipv4 *p, struct zapi_ipv6 *api) -{ - int i; - int psize; - struct stream *s; - - /* Reset stream. */ - s = zclient->obuf; - stream_reset(s); - - /* Some checks for labeled-unicast. The current expectation is that each - * nexthop is accompanied by a label in the case of labeled-unicast. - */ - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL) - && CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { - /* We expect prefixes installed with labels and the number to - * match - * the number of nexthops. - */ - assert(api->label_num == api->nexthop_num); - } - - zclient_create_header(s, cmd, api->vrf_id); - - /* Put type and nexthop. */ - stream_putc(s, api->type); - stream_putw(s, api->instance); - stream_putl(s, api->flags); - stream_putc(s, api->message); - stream_putw(s, api->safi); - - /* Put prefix information. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (uint8_t *)&p->prefix, psize); - - /* Nexthop, ifindex, distance and metric information. */ - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { - stream_putc(s, api->nexthop_num + api->ifindex_num); - - for (i = 0; i < api->nexthop_num; i++) { - stream_putc(s, NEXTHOP_TYPE_IPV6); - stream_write(s, (uint8_t *)api->nexthop[i], 16); - /* For labeled-unicast, each nexthop is followed by - * label. */ - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) - stream_putl(s, api->label[i]); - } - for (i = 0; i < api->ifindex_num; i++) { - stream_putc(s, NEXTHOP_TYPE_IFINDEX); - stream_putl(s, api->ifindex[i]); - } - } - - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE)) - stream_putc(s, api->distance); - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC)) - stream_putl(s, api->metric); - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG)) - stream_putl(s, api->tag); - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU)) - stream_putl(s, api->mtu); - - /* Put length at the first point of the stream. */ - stream_putw_at(s, 0, stream_get_endp(s)); - - return zclient_send_message(zclient); -} - -int zapi_ipv6_route(uint8_t cmd, struct zclient *zclient, struct prefix_ipv6 *p, - struct prefix_ipv6 *src_p, struct zapi_ipv6 *api) -{ - int i; - int psize; - struct stream *s; - - /* either we have !SRCPFX && src_p == NULL, or SRCPFX && src_p != NULL - */ - assert(!(api->message & ZAPI_MESSAGE_SRCPFX) == !src_p); - - /* Reset stream. */ - s = zclient->obuf; - stream_reset(s); - - /* Some checks for labeled-unicast. The current expectation is that each - * nexthop is accompanied by a label in the case of labeled-unicast. - */ - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL) - && CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { - /* We expect prefixes installed with labels and the number to - * match - * the number of nexthops. - */ - assert(api->label_num == api->nexthop_num); - } - - zclient_create_header(s, cmd, api->vrf_id); - - /* Put type and nexthop. */ - stream_putc(s, api->type); - stream_putw(s, api->instance); - stream_putl(s, api->flags); - stream_putc(s, api->message); - stream_putw(s, api->safi); - - /* Put prefix information. */ - psize = PSIZE(p->prefixlen); - stream_putc(s, p->prefixlen); - stream_write(s, (uint8_t *)&p->prefix, psize); - - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_SRCPFX)) { - psize = PSIZE(src_p->prefixlen); - stream_putc(s, src_p->prefixlen); - stream_write(s, (uint8_t *)&src_p->prefix, psize); - } - - /* Nexthop, ifindex, distance and metric information. */ - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_NEXTHOP)) { - stream_putc(s, api->nexthop_num + api->ifindex_num); - - for (i = 0; i < api->nexthop_num; i++) { - stream_putc(s, NEXTHOP_TYPE_IPV6); - stream_write(s, (uint8_t *)api->nexthop[i], 16); - /* For labeled-unicast, each nexthop is followed by - * label. */ - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_LABEL)) - stream_putl(s, api->label[i]); - } - for (i = 0; i < api->ifindex_num; i++) { - stream_putc(s, NEXTHOP_TYPE_IFINDEX); - stream_putl(s, api->ifindex[i]); - } - } - - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_DISTANCE)) - stream_putc(s, api->distance); - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_METRIC)) - stream_putl(s, api->metric); - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TAG)) - stream_putl(s, api->tag); - if (CHECK_FLAG(api->message, ZAPI_MESSAGE_MTU)) - stream_putl(s, api->mtu); - - /* Put length at the first point of the stream. */ - stream_putw_at(s, 0, stream_get_endp(s)); - - return zclient_send_message(zclient); -} - int zclient_route_send(uint8_t cmd, struct zclient *zclient, struct zapi_route *api) { diff --git a/lib/zclient.h b/lib/zclient.h index 962b1707c9..b8ff85e80f 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -73,10 +73,6 @@ typedef enum { ZEBRA_ROUTE_ADD, ZEBRA_ROUTE_DELETE, ZEBRA_ROUTE_NOTIFY_OWNER, - ZEBRA_IPV4_ROUTE_ADD, - ZEBRA_IPV4_ROUTE_DELETE, - ZEBRA_IPV6_ROUTE_ADD, - ZEBRA_IPV6_ROUTE_DELETE, ZEBRA_REDISTRIBUTE_ADD, ZEBRA_REDISTRIBUTE_DELETE, ZEBRA_REDISTRIBUTE_DEFAULT_ADD, @@ -286,7 +282,7 @@ struct zclient { */ #define ZAPI_MESSAGE_TABLEID 0x80 -#define ZSERV_VERSION 5 +#define ZSERV_VERSION 6 /* Zserv protocol message header */ struct zmsghdr { uint16_t length; @@ -353,37 +349,6 @@ struct zapi_route { uint32_t tableid; }; -/* Zebra IPv4 route message API. */ -struct zapi_ipv4 { - uint8_t type; - unsigned short instance; - - uint32_t flags; - - uint8_t message; - - safi_t safi; - - uint8_t nexthop_num; - struct in_addr **nexthop; - - uint8_t ifindex_num; - ifindex_t *ifindex; - - uint8_t label_num; - unsigned int *label; - - uint8_t distance; - - uint32_t metric; - - route_tag_t tag; - - uint32_t mtu; - - vrf_id_t vrf_id; -}; - struct zapi_pw { char ifname[IF_NAMESIZE]; ifindex_t ifindex; @@ -600,15 +565,6 @@ extern struct interface *zebra_interface_vrf_update_read(struct stream *s, extern void zebra_interface_if_set_value(struct stream *, struct interface *); extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid); -/* clang-format off */ -#if CONFDATE > 20180823 -CPP_NOTICE("zapi_ipv4_route, zapi_ipv6_route, zapi_ipv4_route_ipv6_nexthop as well as the zapi_ipv4 and zapi_ipv6 data structures should be removed now"); -#endif -/* clang-format on */ - -extern int zapi_ipv4_route(uint8_t, struct zclient *, struct prefix_ipv4 *, - struct zapi_ipv4 *) __attribute__((deprecated)); - extern struct interface *zebra_interface_link_params_read(struct stream *); extern size_t zebra_interface_link_params_write(struct stream *, struct interface *); @@ -635,45 +591,6 @@ extern void zebra_read_pw_status_update(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id, struct zapi_pw_status *pw); -/* IPv6 prefix add and delete function prototype. */ - -struct zapi_ipv6 { - uint8_t type; - unsigned short instance; - - uint32_t flags; - - uint8_t message; - - safi_t safi; - - uint8_t nexthop_num; - struct in6_addr **nexthop; - - uint8_t ifindex_num; - ifindex_t *ifindex; - - uint8_t label_num; - unsigned int *label; - - uint8_t distance; - - uint32_t metric; - - route_tag_t tag; - - uint32_t mtu; - - vrf_id_t vrf_id; -}; - -extern int zapi_ipv6_route(uint8_t cmd, struct zclient *zclient, - struct prefix_ipv6 *p, struct prefix_ipv6 *src_p, - struct zapi_ipv6 *api) __attribute__((deprecated)); -extern int zapi_ipv4_route_ipv6_nexthop(uint8_t, struct zclient *, - struct prefix_ipv4 *, - struct zapi_ipv6 *) - __attribute__((deprecated)); extern int zclient_route_send(uint8_t, struct zclient *, struct zapi_route *); extern int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p, bool exact_match, diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 008fc8f066..6990fd95f5 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1584,202 +1584,6 @@ static void zread_route_del(ZAPI_HANDLER_ARGS) } } -/* This function support multiple nexthop. */ -/* - * Parse the ZEBRA_IPV4_ROUTE_ADD sent from client. Update re and - * add kernel route. - */ -static void zread_ipv4_add(ZAPI_HANDLER_ARGS) -{ - int i; - struct route_entry *re; - struct prefix p; - uint8_t message; - struct in_addr nhop_addr; - uint8_t nexthop_num; - uint8_t nexthop_type; - struct stream *s; - ifindex_t ifindex; - safi_t safi; - int ret; - enum lsp_types_t label_type = ZEBRA_LSP_NONE; - mpls_label_t label; - struct nexthop *nexthop; - enum blackhole_type bh_type = BLACKHOLE_NULL; - - /* Get input stream. */ - s = msg; - - /* Allocate new re. */ - re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); - - /* Type, flags, message. */ - STREAM_GETC(s, re->type); - if (re->type > ZEBRA_ROUTE_MAX) { - zlog_warn("%s: Specified route type %d is not a legal value\n", - __PRETTY_FUNCTION__, re->type); - XFREE(MTYPE_RE, re); - return; - } - STREAM_GETW(s, re->instance); - STREAM_GETL(s, re->flags); - STREAM_GETC(s, message); - STREAM_GETW(s, safi); - re->uptime = time(NULL); - - /* IPv4 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv4)); - p.family = AF_INET; - STREAM_GETC(s, p.prefixlen); - if (p.prefixlen > IPV4_MAX_BITLEN) { - zlog_warn( - "%s: Specified prefix length %d is greater than what v4 can be", - __PRETTY_FUNCTION__, p.prefixlen); - XFREE(MTYPE_RE, re); - return; - } - STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen)); - - /* VRF ID */ - re->vrf_id = zvrf_id(zvrf); - - /* Nexthop parse. */ - if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) { - STREAM_GETC(s, nexthop_num); - zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, - nexthop_num); - - if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) - label_type = lsp_type_from_re_type(client->proto); - - for (i = 0; i < nexthop_num; i++) { - STREAM_GETC(s, nexthop_type); - - switch (nexthop_type) { - case NEXTHOP_TYPE_IFINDEX: - STREAM_GETL(s, ifindex); - route_entry_nexthop_ifindex_add(re, ifindex, - re->vrf_id); - break; - case NEXTHOP_TYPE_IPV4: - STREAM_GET(&nhop_addr.s_addr, s, - IPV4_MAX_BYTELEN); - nexthop = route_entry_nexthop_ipv4_add( - re, &nhop_addr, NULL, re->vrf_id); - /* - * For labeled-unicast, each nexthop is followed - * by the label. - */ - if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) { - STREAM_GETL(s, label); - nexthop_add_labels(nexthop, label_type, - 1, &label); - } - break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - STREAM_GET(&nhop_addr.s_addr, s, - IPV4_MAX_BYTELEN); - STREAM_GETL(s, ifindex); - route_entry_nexthop_ipv4_ifindex_add( - re, &nhop_addr, NULL, ifindex, - re->vrf_id); - break; - case NEXTHOP_TYPE_IPV6: - zlog_warn( - "%s: Please use ZEBRA_ROUTE_ADD if you want to pass v6 nexthops", - __PRETTY_FUNCTION__); - nexthops_free(re->ng.nexthop); - XFREE(MTYPE_RE, re); - return; - case NEXTHOP_TYPE_BLACKHOLE: - route_entry_nexthop_blackhole_add(re, bh_type); - break; - default: - zlog_warn( - "%s: Specified nexthop type: %d does not exist", - __PRETTY_FUNCTION__, nexthop_type); - nexthops_free(re->ng.nexthop); - XFREE(MTYPE_RE, re); - return; - } - } - } - - /* Distance. */ - if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) - STREAM_GETC(s, re->distance); - - /* Metric. */ - if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) - STREAM_GETL(s, re->metric); - - /* Tag */ - if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) - STREAM_GETL(s, re->tag); - else - re->tag = 0; - - if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU)) - STREAM_GETL(s, re->mtu); - else - re->mtu = 0; - - /* Table */ - re->table = zvrf->table_id; - - ret = rib_add_multipath(AFI_IP, safi, &p, NULL, re); - - /* Stats */ - if (ret > 0) - client->v4_route_add_cnt++; - else if (ret < 0) - client->v4_route_upd8_cnt++; - - return; - -stream_failure: - nexthops_free(re->ng.nexthop); - XFREE(MTYPE_RE, re); -} - -/* Zebra server IPv4 prefix delete function. */ -static void zread_ipv4_delete(ZAPI_HANDLER_ARGS) -{ - struct stream *s; - struct zapi_ipv4 api; - struct prefix p; - uint32_t table_id; - - s = msg; - - /* Type, flags, message. */ - STREAM_GETC(s, api.type); - STREAM_GETW(s, api.instance); - STREAM_GETL(s, api.flags); - STREAM_GETC(s, api.message); - STREAM_GETW(s, api.safi); - - /* IPv4 prefix. */ - memset(&p, 0, sizeof(struct prefix)); - p.family = AF_INET; - STREAM_GETC(s, p.prefixlen); - if (p.prefixlen > IPV4_MAX_BITLEN) { - zlog_warn("%s: Passed in prefixlen %d is impossible", - __PRETTY_FUNCTION__, p.prefixlen); - return; - } - STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen)); - - table_id = zvrf->table_id; - - rib_delete(AFI_IP, api.safi, zvrf_id(zvrf), api.type, api.instance, - api.flags, &p, NULL, NULL, table_id, 0, 0, false); - client->v4_route_del_cnt++; - -stream_failure: - return; -} - /* MRIB Nexthop lookup for IPv4. */ static void zread_ipv4_nexthop_lookup_mrib(ZAPI_HANDLER_ARGS) { @@ -1794,417 +1598,6 @@ stream_failure: return; } -/* Zebra server IPv6 prefix add function. */ -static void zread_ipv4_route_ipv6_nexthop_add(ZAPI_HANDLER_ARGS) -{ - unsigned int i; - struct stream *s; - struct in6_addr nhop_addr; - struct route_entry *re; - uint8_t message; - uint8_t nexthop_num; - uint8_t nexthop_type; - struct prefix p; - safi_t safi; - static struct in6_addr nexthops[MULTIPATH_NUM]; - static unsigned int ifindices[MULTIPATH_NUM]; - int ret; - static mpls_label_t labels[MULTIPATH_NUM]; - enum lsp_types_t label_type = ZEBRA_LSP_NONE; - mpls_label_t label; - struct nexthop *nexthop; - enum blackhole_type bh_type = BLACKHOLE_NULL; - - /* Get input stream. */ - s = msg; - - memset(&nhop_addr, 0, sizeof(struct in6_addr)); - - /* Allocate new re. */ - re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); - - /* Type, flags, message. */ - STREAM_GETC(s, re->type); - if (re->type > ZEBRA_ROUTE_MAX) { - zlog_warn("%s: Specified route type: %d is not a legal value\n", - __PRETTY_FUNCTION__, re->type); - XFREE(MTYPE_RE, re); - return; - } - STREAM_GETW(s, re->instance); - STREAM_GETL(s, re->flags); - STREAM_GETC(s, message); - STREAM_GETW(s, safi); - re->uptime = time(NULL); - - /* IPv4 prefix. */ - memset(&p, 0, sizeof(struct prefix_ipv4)); - p.family = AF_INET; - STREAM_GETC(s, p.prefixlen); - if (p.prefixlen > IPV4_MAX_BITLEN) { - zlog_warn( - "%s: Prefix Length %d is greater than what a v4 address can use", - __PRETTY_FUNCTION__, p.prefixlen); - XFREE(MTYPE_RE, re); - return; - } - STREAM_GET(&p.u.prefix4, s, PSIZE(p.prefixlen)); - - /* VRF ID */ - re->vrf_id = zvrf_id(zvrf); - - /* - * We need to give nh-addr, nh-ifindex with the same next-hop object - * to the re to ensure that IPv6 multipathing works; need to coalesce - * these. Clients should send the same number of paired set of - * next-hop-addr/next-hop-ifindices. - */ - if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) { - unsigned int nh_count = 0; - unsigned int if_count = 0; - unsigned int max_nh_if = 0; - - STREAM_GETC(s, nexthop_num); - zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, - nexthop_num); - - if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) - label_type = lsp_type_from_re_type(client->proto); - - for (i = 0; i < nexthop_num; i++) { - STREAM_GETC(s, nexthop_type); - - switch (nexthop_type) { - case NEXTHOP_TYPE_IPV6: - STREAM_GET(&nhop_addr, s, 16); - if (nh_count < MULTIPATH_NUM) { - /* - * For labeled-unicast, each nexthop is - * followed by the label. - */ - if (CHECK_FLAG(message, - ZAPI_MESSAGE_LABEL)) { - STREAM_GETL(s, label); - labels[nh_count] = label; - } - nexthops[nh_count] = nhop_addr; - nh_count++; - } - break; - case NEXTHOP_TYPE_IFINDEX: - if (if_count < multipath_num) - STREAM_GETL(s, ifindices[if_count++]); - break; - case NEXTHOP_TYPE_BLACKHOLE: - route_entry_nexthop_blackhole_add(re, bh_type); - break; - default: - zlog_warn( - "%s: Please use ZEBRA_ROUTE_ADD if you want to pass non v6 nexthops", - __PRETTY_FUNCTION__); - nexthops_free(re->ng.nexthop); - XFREE(MTYPE_RE, re); - return; - } - } - - max_nh_if = (nh_count > if_count) ? nh_count : if_count; - for (i = 0; i < max_nh_if; i++) { - if ((i < nh_count) - && !IN6_IS_ADDR_UNSPECIFIED(&nexthops[i])) { - if ((i < if_count) && ifindices[i]) - nexthop = - route_entry_nexthop_ipv6_ifindex_add( - re, &nexthops[i], - ifindices[i], - re->vrf_id); - else - nexthop = route_entry_nexthop_ipv6_add( - re, &nexthops[i], re->vrf_id); - - if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) - nexthop_add_labels(nexthop, label_type, - 1, &labels[i]); - } else { - if ((i < if_count) && ifindices[i]) - route_entry_nexthop_ifindex_add( - re, ifindices[i], re->vrf_id); - } - } - } - - /* Distance. */ - if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) - STREAM_GETC(s, re->distance); - - /* Metric. */ - if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) - STREAM_GETL(s, re->metric); - - /* Tag */ - if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) - STREAM_GETL(s, re->tag); - else - re->tag = 0; - - if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU)) - STREAM_GETL(s, re->mtu); - else - re->mtu = 0; - - /* Table */ - re->table = zvrf->table_id; - - ret = rib_add_multipath(AFI_IP6, safi, &p, NULL, re); - /* Stats */ - if (ret > 0) - client->v4_route_add_cnt++; - else if (ret < 0) - client->v4_route_upd8_cnt++; - - return; - -stream_failure: - nexthops_free(re->ng.nexthop); - XFREE(MTYPE_RE, re); -} - -static void zread_ipv6_add(ZAPI_HANDLER_ARGS) -{ - unsigned int i; - struct stream *s; - struct in6_addr nhop_addr; - ifindex_t ifindex; - struct route_entry *re; - uint8_t message; - uint8_t nexthop_num; - uint8_t nexthop_type; - struct prefix p; - struct prefix_ipv6 src_p, *src_pp; - safi_t safi; - static struct in6_addr nexthops[MULTIPATH_NUM]; - static unsigned int ifindices[MULTIPATH_NUM]; - int ret; - static mpls_label_t labels[MULTIPATH_NUM]; - enum lsp_types_t label_type = ZEBRA_LSP_NONE; - mpls_label_t label; - struct nexthop *nexthop; - enum blackhole_type bh_type = BLACKHOLE_NULL; - - /* Get input stream. */ - s = msg; - - memset(&nhop_addr, 0, sizeof(struct in6_addr)); - - /* Allocate new re. */ - re = XCALLOC(MTYPE_RE, sizeof(struct route_entry)); - - /* Type, flags, message. */ - STREAM_GETC(s, re->type); - if (re->type > ZEBRA_ROUTE_MAX) { - zlog_warn("%s: Specified route type: %d is not a legal value\n", - __PRETTY_FUNCTION__, re->type); - XFREE(MTYPE_RE, re); - return; - } - STREAM_GETW(s, re->instance); - STREAM_GETL(s, re->flags); - STREAM_GETC(s, message); - STREAM_GETW(s, safi); - re->uptime = time(NULL); - - /* IPv6 prefix. */ - memset(&p, 0, sizeof(p)); - p.family = AF_INET6; - STREAM_GETC(s, p.prefixlen); - if (p.prefixlen > IPV6_MAX_BITLEN) { - zlog_warn( - "%s: Specified prefix length %d is to large for v6 prefix", - __PRETTY_FUNCTION__, p.prefixlen); - XFREE(MTYPE_RE, re); - return; - } - STREAM_GET(&p.u.prefix6, s, PSIZE(p.prefixlen)); - - if (CHECK_FLAG(message, ZAPI_MESSAGE_SRCPFX)) { - memset(&src_p, 0, sizeof(src_p)); - src_p.family = AF_INET6; - STREAM_GETC(s, src_p.prefixlen); - if (src_p.prefixlen > IPV6_MAX_BITLEN) { - zlog_warn( - "%s: Specified src prefix length %d is to large for v6 prefix", - __PRETTY_FUNCTION__, src_p.prefixlen); - XFREE(MTYPE_RE, re); - return; - } - STREAM_GET(&src_p.prefix, s, PSIZE(src_p.prefixlen)); - src_pp = &src_p; - } else - src_pp = NULL; - - /* VRF ID */ - re->vrf_id = zvrf_id(zvrf); - - /* - * We need to give nh-addr, nh-ifindex with the same next-hop object - * to the re to ensure that IPv6 multipathing works; need to coalesce - * these. Clients should send the same number of paired set of - * next-hop-addr/next-hop-ifindices. - */ - if (CHECK_FLAG(message, ZAPI_MESSAGE_NEXTHOP)) { - unsigned int nh_count = 0; - unsigned int if_count = 0; - unsigned int max_nh_if = 0; - - STREAM_GETC(s, nexthop_num); - zserv_nexthop_num_warn(__func__, (const struct prefix *)&p, - nexthop_num); - - if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) - label_type = lsp_type_from_re_type(client->proto); - - for (i = 0; i < nexthop_num; i++) { - STREAM_GETC(s, nexthop_type); - - switch (nexthop_type) { - case NEXTHOP_TYPE_IPV6: - STREAM_GET(&nhop_addr, s, 16); - if (nh_count < MULTIPATH_NUM) { - /* - * For labeled-unicast, each nexthop is - * followed by label. - */ - if (CHECK_FLAG(message, - ZAPI_MESSAGE_LABEL)) { - STREAM_GETL(s, label); - labels[nh_count] = label; - } - nexthops[nh_count++] = nhop_addr; - } - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - STREAM_GET(&nhop_addr, s, 16); - STREAM_GETL(s, ifindex); - route_entry_nexthop_ipv6_ifindex_add( - re, &nhop_addr, ifindex, re->vrf_id); - break; - case NEXTHOP_TYPE_IFINDEX: - if (if_count < multipath_num) - STREAM_GETL(s, ifindices[if_count++]); - break; - case NEXTHOP_TYPE_BLACKHOLE: - route_entry_nexthop_blackhole_add(re, bh_type); - break; - default: - zlog_warn( - "%s: Please use ZEBRA_ROUTE_ADD if you want to pass non v6 nexthops", - __PRETTY_FUNCTION__); - nexthops_free(re->ng.nexthop); - XFREE(MTYPE_RE, re); - return; - } - } - - max_nh_if = (nh_count > if_count) ? nh_count : if_count; - for (i = 0; i < max_nh_if; i++) { - if ((i < nh_count) - && !IN6_IS_ADDR_UNSPECIFIED(&nexthops[i])) { - if ((i < if_count) && ifindices[i]) - nexthop = - route_entry_nexthop_ipv6_ifindex_add( - re, &nexthops[i], - ifindices[i], - re->vrf_id); - else - nexthop = route_entry_nexthop_ipv6_add( - re, &nexthops[i], re->vrf_id); - if (CHECK_FLAG(message, ZAPI_MESSAGE_LABEL)) - nexthop_add_labels(nexthop, label_type, - 1, &labels[i]); - } else { - if ((i < if_count) && ifindices[i]) - route_entry_nexthop_ifindex_add( - re, ifindices[i], re->vrf_id); - } - } - } - - /* Distance. */ - if (CHECK_FLAG(message, ZAPI_MESSAGE_DISTANCE)) - STREAM_GETC(s, re->distance); - - /* Metric. */ - if (CHECK_FLAG(message, ZAPI_MESSAGE_METRIC)) - STREAM_GETL(s, re->metric); - - /* Tag */ - if (CHECK_FLAG(message, ZAPI_MESSAGE_TAG)) - STREAM_GETL(s, re->tag); - else - re->tag = 0; - - if (CHECK_FLAG(message, ZAPI_MESSAGE_MTU)) - STREAM_GETL(s, re->mtu); - else - re->mtu = 0; - - re->table = zvrf->table_id; - - ret = rib_add_multipath(AFI_IP6, safi, &p, src_pp, re); - /* Stats */ - if (ret > 0) - client->v6_route_add_cnt++; - else if (ret < 0) - client->v6_route_upd8_cnt++; - - return; - -stream_failure: - nexthops_free(re->ng.nexthop); - XFREE(MTYPE_RE, re); -} - -/* Zebra server IPv6 prefix delete function. */ -static void zread_ipv6_delete(ZAPI_HANDLER_ARGS) -{ - struct stream *s; - struct zapi_ipv6 api; - struct prefix p; - struct prefix_ipv6 src_p, *src_pp; - - s = msg; - - /* Type, flags, message. */ - STREAM_GETC(s, api.type); - STREAM_GETW(s, api.instance); - STREAM_GETL(s, api.flags); - STREAM_GETC(s, api.message); - STREAM_GETW(s, api.safi); - - /* IPv4 prefix. */ - memset(&p, 0, sizeof(struct prefix)); - p.family = AF_INET6; - STREAM_GETC(s, p.prefixlen); - STREAM_GET(&p.u.prefix6, s, PSIZE(p.prefixlen)); - - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX)) { - memset(&src_p, 0, sizeof(struct prefix_ipv6)); - src_p.family = AF_INET6; - STREAM_GETC(s, src_p.prefixlen); - STREAM_GET(&src_p.prefix, s, PSIZE(src_p.prefixlen)); - src_pp = &src_p; - } else - src_pp = NULL; - - rib_delete(AFI_IP6, api.safi, zvrf_id(zvrf), api.type, api.instance, - api.flags, &p, src_pp, NULL, client->rtm_table, 0, 0, false); - - client->v6_route_del_cnt++; - -stream_failure: - return; -} - /* Register zebra server router-id information. Send current router-id */ static void zread_router_id_add(ZAPI_HANDLER_ARGS) { @@ -3011,11 +2404,6 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_INTERFACE_DELETE] = zread_interface_delete, [ZEBRA_ROUTE_ADD] = zread_route_add, [ZEBRA_ROUTE_DELETE] = zread_route_del, - [ZEBRA_IPV4_ROUTE_ADD] = zread_ipv4_add, - [ZEBRA_IPV4_ROUTE_DELETE] = zread_ipv4_delete, - [ZEBRA_IPV4_ROUTE_IPV6_NEXTHOP_ADD] = zread_ipv4_route_ipv6_nexthop_add, - [ZEBRA_IPV6_ROUTE_ADD] = zread_ipv6_add, - [ZEBRA_IPV6_ROUTE_DELETE] = zread_ipv6_delete, [ZEBRA_REDISTRIBUTE_ADD] = zebra_redistribute_add, [ZEBRA_REDISTRIBUTE_DELETE] = zebra_redistribute_delete, [ZEBRA_REDISTRIBUTE_DEFAULT_ADD] = zebra_redistribute_default_add, From ec4f07507b7a54fad3edad5188dee1bef7c350a6 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Aug 2018 15:21:04 -0400 Subject: [PATCH 53/66] bgpd: Fix CONFDATE to 2019 for a couple of items. While perusing CONFDATE I noticed that we had a couple CONFDATE 201805, which we were not picking up( for other reasons and fixed in a different PR ). But upon investigation of these I noticed that the commits where in 201805, so these CONFDATES should be in 2019 Signed-off-by: Donald Sharp --- bgpd/bgp_vty.c | 2 +- bgpd/bgpd.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 62f337a876..1460a26215 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -2019,7 +2019,7 @@ DEFUN (no_bgp_fast_external_failover, } /* "bgp enforce-first-as" configuration. */ -#if CONFDATE > 20180517 +#if CONFDATE > 20190517 CPP_NOTICE("bgpd: remove deprecated '[no] bgp enforce-first-as' commands") #endif diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 746967a3b3..5d9609ae01 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7345,7 +7345,7 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi, } /* clang-format off */ -#if CONFDATE > 20180517 +#if CONFDATE > 20190517 CPP_NOTICE("bgpd: remove 'bgp enforce-first-as' config migration from bgp_config_write") #endif /* clang-format on */ From cae770d31d306e5053c1c69509c03d11903217fa Mon Sep 17 00:00:00 2001 From: Christoffer Date: Thu, 23 Aug 2018 01:46:37 +0200 Subject: [PATCH 54/66] doc: Add documentation for IANA well-known communities Coded as part of #2684 and most code written while participating at BornHack@2018. bgp.rst: Explain what the communities does and a summarized edition of the communities purpose. Signed-off-by: Christoffer --- doc/user/bgp.rst | 74 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index f1209c2172..2cea24a8bd 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -1011,6 +1011,75 @@ is 4 octet long. The following format is used to define the community value. ``internet`` ``internet`` represents well-known communities value 0. +``graceful-shutdown`` + ``graceful-shutdown`` represents well-known communities value + ``GRACEFUL_SHUTDOWN`` ``0xFFFF0000`` ``65535:0``. :rfc:`8326` implements + the purpose Graceful BGP Session Shutdown to reduce the amount of + lost traffic when taking BGP sessions down for maintainance. The use + of the community needs to be supported from your peers side to + actually have any effect. + +``accept-own`` + ``accept-own`` represents well-known communities value ``ACCEPT_OWN`` + ``0xFFFF0001`` ``65535:1``. :rfc:`7611` implements a way to signal + to a router to accept routes with a local nexthop address. This + can be the case when doing policing and having traffic having a + nexthop located in another VRF but still local interface to the + router. It is recommended to read the RFC for full details. + +``route-filter-translated-v4`` + ``route-filter-translated-v4`` represents well-known communities value + ``ROUTE_FILTER_TRANSLATED_v4`` ``0xFFFF0002`` ``65535:2``. + +``route-filter-v4`` + ``route-filter-v4`` represents well-known communities value + ``ROUTE_FILTER_v4`` ``0xFFFF0003`` ``65535:3``. + +``route-filter-translated-v6`` + ``route-filter-translated-v6`` represents well-known communities value + ``ROUTE_FILTER_TRANSLATED_v6`` ``0xFFFF0004`` ``65535:4``. + +``route-filter-v6`` + ``route-filter-v6`` represents well-known communities value + ``ROUTE_FILTER_v6`` ``0xFFFF0005`` ``65535:5``. + +``llgr-stale`` + ``llgr-stale`` represents well-known communities value ``LLGR_STALE`` + ``0xFFFF0006`` ``65535:6``. + Assigned and intented only for use with routers supporting the + Long-lived Graceful Restart Capability as described in + :rfc:`draft-uttaro-idr-bgp-persistence`. + Routers recieving routes with this community may (depending on + implementation) choose allow to reject or modify routes on the + presence or absence of this community. + +``no-llgr`` + ``no-llgr`` represents well-known communities value ``NO_LLGR`` + ``0xFFFF0007`` ``65535:7``. + Assigned and intented only for use with routers supporting the + Long-lived Graceful Restart Capability as described in + :rfc:`draft-uttaro-idr-bgp-persistence`. + Routers recieving routes with this community may (depending on + implementation) choose allow to reject or modify routes on the + presence or absence of this community. + +``accept-own-nexthop`` + ``accept-own-nexthop`` represents well-known communities value + ``accept-own-nexthop`` ``0xFFFF0008`` ``65535:8``. + :rfc:`draft-agrewal-idr-accept-own-nexthop` describes + how to tag and label VPN routes to be able to send traffic between VRFs + via an internal layer 2 domain on the same PE device. Refer to + :rfc:`draft-agrewal-idr-accept-own-nexthop` for full details. + +``blackhole`` + ``blackhole`` represents well-known communities value ``BLACKHOLE`` + ``0xFFFF029A`` ``65535:666``. :rfc:`7999` documents sending prefixes to + EBGP peers and upstream for the purpose of blackholing traffic. + Prefixes tagged with the this community should normally not be + re-advertised from neighbors of the originating network. It is + recommended upon receiving prefixes tagged with this community to + add ``NO_EXPORT`` and ``NO_ADVERTISE``. + ``no-export`` ``no-export`` represents well-known communities value ``NO_EXPORT`` ``0xFFFFFF01``. All routes carry this value must not be advertised to @@ -1030,6 +1099,11 @@ is 4 octet long. The following format is used to define the community value. it is considered as external BGP peer, so the route will not be announced to the peer. +``no-peer`` + ``no-peer`` represents well-known communities value ``NOPEER`` + ``0xFFFFFF04`` ``65535:65284``. :rfc:`3765` is used to communicate to + another network how the originating network want the prefix propagated. + When the communities attribute is received duplicate community values in the attribute are ignored and value is sorted in numerical order. From c5f1e1b2403020be7b13a7cc4ce789b36d4dbe8b Mon Sep 17 00:00:00 2001 From: Christoffer Date: Fri, 24 Aug 2018 23:57:42 +0200 Subject: [PATCH 55/66] bgp: Add documentation for IANA well-known communities Coded as part of #2684 and most code written while participating at BornHack@2018. bgp_route.c: Changes regarding adding explanations for the IANA well-known communities added in #2684 Signed-off-by: Christoffer --- bgpd/bgp_route.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index ed3b75f87c..50c484d7de 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -8581,9 +8581,19 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, int count = 0; int best = 0; int suppress = 0; + int accept_own = 0; + int route_filter_translated_v4 = 0; + int route_filter_v4 = 0; + int route_filter_translated_v6 = 0; + int route_filter_v6 = 0; + int llgr_stale = 0; + int no_llgr = 0; + int accept_own_nexthop = 0; + int blackhole = 0; int no_export = 0; int no_advertise = 0; int local_as = 0; + int no_peer = 0; int first = 1; int has_valid_label = 0; mpls_label_t label = 0; @@ -8660,12 +8670,41 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, } else vty_out(vty, ", no best path"); - if (no_advertise) - vty_out(vty, ", not advertised to any peer"); + if (accept_own) + vty_out(vty, + ", accept own local route exported and imported in different VRF"); + else if (route_filter_translated_v4) + vty_out(vty, + ", mark translated RTs for VPNv4 route filtering"); + else if (route_filter_v4) + vty_out(vty, + ", attach RT as-is for VPNv4 route filtering"); + else if (route_filter_translated_v6) + vty_out(vty, + ", mark translated RTs for VPNv6 route filtering"); + else if (route_filter_v6) + vty_out(vty, + ", attach RT as-is for VPNv6 route filtering"); + else if (llgr_stale) + vty_out(vty, + ", mark routes to be retained for a longer time. Requeres support for Long-lived BGP Graceful Restart"); + else if (no_llgr) + vty_out(vty, + ", mark routes to not be treated according to Long-lived BGP Graceful Restart operations"); + else if (accept_own_nexthop) + vty_out(vty, + ", accept local nexthop"); + else if (blackhole) + vty_out(vty, ", inform peer to blackhole prefix"); else if (no_export) vty_out(vty, ", not advertised to EBGP peer"); + else if (no_advertise) + vty_out(vty, ", not advertised to any peer"); else if (local_as) vty_out(vty, ", not advertised outside local AS"); + else if (no_peer) + vty_out(vty, + ", inform EBGP peer not to advertise to their EBGP peers"); if (suppress) vty_out(vty, @@ -9026,6 +9065,10 @@ DEFUN (show_ip_bgp, |prefix-list WORD\ |filter-list WORD\ |statistics\ + |community [exact-match]\ |community-list <(1-500)|WORD> [exact-match]\ |A.B.C.D/M longer-prefixes\ |X:X::X:X/M longer-prefixes\ @@ -9045,6 +9088,23 @@ DEFUN (show_ip_bgp, "Display routes conforming to the filter-list\n" "Regular expression access list name\n" "BGP RIB advertisement statistics\n" + "Display routes matching the communities\n" + COMMUNITY_AANN_STR + "Do not send outside local AS (well-known community)\n" + "Do not advertise to any peer (well-known community)\n" + "Do not export to next AS (well-known community)\n" + "Graceful shutdown (well-known community)\n" + "Do not export to any peer (well-known community)\n" + "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n" + "Staled Long-lived Graceful Restart VPN route (well-known community)\n" + "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n" + "Should accept local VPN route if exported and imported into different VRF (well-known community)\n" + "Should accept VPN route with local nexthop (well-known community)\n" + "RT VPNv6 route filtering (well-known community)\n" + "RT VPNv4 route filtering (well-known community)\n" + "RT translated VPNv6 route filtering (well-known community)\n" + "RT translated VPNv4 route filtering (well-known community)\n" + "Exact match of the communities\n" "Display routes matching the community-list\n" "community-list number\n" "community-list name\n" From 96065dc3104a2f2dcfc2e7defd13a61662bd597e Mon Sep 17 00:00:00 2001 From: Chirag Shah Date: Fri, 24 Aug 2018 15:15:36 -0700 Subject: [PATCH 56/66] ospfd: interface speed change during intf add The problem is seen where speed mismatch caused ECMP route not being reflected with correct number paths (NHs). During cold boot, some interface speed updated by zebra as part of one shot timer and triggers interface add to clients. In this case, ospf already have created interface (bond interface), but speed was not updated, trigger to do interface speed change as part of interface add, which will trigger all Router LSA to use updated speed into cost calculation. Ticket:CM-22170 Testing Done: Bring up CLOS config with Spine and leafs. Leaf have CLAG pair, with same VRR ip address. At spine one of the bond connecting to leaf node was having higher speed than the paired device, With this fix, at spine (DUT) bond interface speed is equal from all peer nodes. Signed-off-by: Chirag Shah --- ospfd/ospf_ase.c | 16 +++++++++++----- ospfd/ospf_zebra.c | 16 +++++++++++----- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c index d84fd26ac4..0221d1e1b2 100644 --- a/ospfd/ospf_ase.c +++ b/ospfd/ospf_ase.c @@ -288,6 +288,7 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa) struct prefix_ipv4 asbr, p; struct route_node *rn; struct ospf_route *new, * or ; + char buf1[INET_ADDRSTRLEN]; int ret; assert(lsa); @@ -304,10 +305,14 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa) return 0; } - if (IS_DEBUG_OSPF(lsa, LSA)) + if (IS_DEBUG_OSPF(lsa, LSA)) { + snprintf(buf1, INET_ADDRSTRLEN, "%s", + inet_ntoa(al->header.adv_router)); zlog_debug( - "Route[External]: Calculate AS-external-LSA to %s/%d", - inet_ntoa(al->header.id), ip_masklen(al->mask)); + "Route[External]: Calculate AS-external-LSA to %s/%d adv_router %s", + inet_ntoa(al->header.id), ip_masklen(al->mask), buf1); + } + /* (1) If the cost specified by the LSA is LSInfinity, or if the LSA's LS age is equal to MaxAge, then examine the next LSA. */ if ((metric = GET_METRIC(al->e[0].metric)) >= OSPF_LS_INFINITY) { @@ -459,8 +464,9 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa) if (!rn || (or = rn->info) == NULL) { if (IS_DEBUG_OSPF(lsa, LSA)) - zlog_debug("Route[External]: Adding a new route %s/%d", - inet_ntoa(p.prefix), p.prefixlen); + zlog_debug("Route[External]: Adding a new route %s/%d with paths %u", + inet_ntoa(p.prefix), p.prefixlen, + listcount(asbr_route->paths)); ospf_route_add(ospf->new_external_route, &p, new, asbr_route); diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 0a7776cced..8c94a8ef99 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -111,10 +111,11 @@ static int ospf_interface_add(int command, struct zclient *zclient, if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) zlog_debug( - "Zebra: interface add %s vrf %s[%u] index %d flags %llx metric %d mtu %d", + "Zebra: interface add %s vrf %s[%u] index %d flags %llx metric %d mtu %d speed %u", ifp->name, ospf_vrf_id_to_name(ifp->vrf_id), ifp->vrf_id, ifp->ifindex, - (unsigned long long)ifp->flags, ifp->metric, ifp->mtu); + (unsigned long long)ifp->flags, ifp->metric, ifp->mtu, + ifp->speed); assert(ifp->info); @@ -128,6 +129,8 @@ static int ospf_interface_add(int command, struct zclient *zclient, if (!ospf) return 0; + ospf_if_recalculate_output_cost(ifp); + ospf_if_update(ospf, ifp); hook_call(ospf_if_update, ifp); @@ -448,14 +451,17 @@ void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p, count++; if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { - char buf[2][PREFIX2STR_BUFFER]; + char buf[2][INET_ADDRSTRLEN]; + struct interface *ifp; + + ifp = if_lookup_by_index(path->ifindex, ospf->vrf_id); zlog_debug( - "Zebra: Route add %s nexthop %s, ifindex=%d", + "Zebra: Route add %s nexthop %s, ifindex=%d %s", prefix2str(p, buf[0], sizeof(buf[0])), inet_ntop(AF_INET, &path->nexthop, buf[1], sizeof(buf[1])), - path->ifindex); + path->ifindex, ifp ? ifp->name : " "); } } api.nexthop_num = count; From 36372632dd96d853ee8f74ff805a515ad26949cf Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 25 Aug 2018 02:12:42 +0200 Subject: [PATCH 57/66] doc/user: add protocols vs. platform table A nicely-formatted colorful table of all our daemons and target OS'. Based off & intended to replace / extend https://github.com/FRRouting/frr/wiki/Features-and-Kernel-Support Signed-off-by: David Lamparter --- doc/user/_static/overrides.css | 47 ++++++++++++++++ doc/user/_static/overrides.js | 13 +++++ doc/user/conf.py | 1 + doc/user/overview.rst | 100 +++++++++++++++++++++++++++------ 4 files changed, 144 insertions(+), 17 deletions(-) create mode 100644 doc/user/_static/overrides.js diff --git a/doc/user/_static/overrides.css b/doc/user/_static/overrides.css index 0d871c961a..3143f8bb65 100644 --- a/doc/user/_static/overrides.css +++ b/doc/user/_static/overrides.css @@ -6,3 +6,50 @@ div.body { pre { background-color: #e2e2e2; } + +/* styling for the protocols vs. OS table in overview.rst */ +/* first, general bits */ +div.body td.mark { + text-align: center; + border-left: 1px solid #ccc; +} +table.mark th { + text-align: center; +} +table.mark td { + vertical-align: middle; +} +table.mark td[colspan="7"] { + text-align: center; + padding-top: 8pt; + padding-bottom: 2pt; +} +table.mark cite { + font-weight: bold; +} + +/* individual Y/N/... cells */ +td.mark { + width: 4.5em; +} +td.mark span { + display: block; + padding: 3px 1px; + border: 1px dotted #666; + width: 36pt; + margin:auto; +} +span.mark-y { background-color: #77ffaa; } +span.mark-geq { background-color: #aaff77; } +span.mark-cp { background-color: #ffbb55; } +span.mark-n { background-color: #ff8877; } +span.mark-dag { background-color: #ffee99; font-size: 8pt; padding:0px 1px; border-top:0px; } + +/* for the legend below */ +li span.mark { + display: inline-block; + padding: 3px 1px; + border: 1px dotted #666; + width: 36pt; + text-align: center; +} diff --git a/doc/user/_static/overrides.js b/doc/user/_static/overrides.js new file mode 100644 index 0000000000..73bf6123b5 --- /dev/null +++ b/doc/user/_static/overrides.js @@ -0,0 +1,13 @@ +/* special styling for the protocols vs. OS table in overview.rst + * + * unfortunately this can't be done in straight CSS because we're changing + * the styling on the parent. + */ +$(document).ready(function() { + $("span.mark:contains('Y')" ).addClass("mark-y" ).parent("td").addClass("mark"); + $("span.mark:contains('≥')" ).addClass("mark-geq").parent("td").addClass("mark"); + $("span.mark:contains('N')" ).addClass("mark-n" ).parent("td").addClass("mark"); + $("span.mark:contains('CP')").addClass("mark-cp" ).parent("td").addClass("mark"); + $("span.mark:contains('†')" ).addClass("mark-dag").parent("td").addClass("mark"); + $('td.mark').parents('table').addClass("mark").children('colgroup').remove(); +}); diff --git a/doc/user/conf.py b/doc/user/conf.py index 28081bca7d..2231989fe5 100644 --- a/doc/user/conf.py +++ b/doc/user/conf.py @@ -358,6 +358,7 @@ def setup(app): app.add_object_type('clicmd', 'clicmd') # css overrides for HTML theme app.add_stylesheet('overrides.css') + app.add_javascript('overrides.js') # load Pygments lexer for FRR config syntax # # NB: in Pygments 2.2+ this can be done with `load_lexer_from_file`, but we diff --git a/doc/user/overview.rst b/doc/user/overview.rst index 369f17dcba..369514d72d 100644 --- a/doc/user/overview.rst +++ b/doc/user/overview.rst @@ -150,27 +150,93 @@ Recent versions of the following compilers are well tested: .. _supported-protocols: -Supported Protocols & RFCs -========================== +Supported Protocols vs. Platform +================================ -The following well-known protocols are supported: +The following table lists all protocols cross-refrenced to all operating +systems that have at least CI build tests. Note that for features, only +features with system dependencies are included here. -- BGP -- Babel -- EIGRP -- IS-IS -- LDP -- NHRP -- OSPFv2 -- OSPFv3 -- PIM -- RIP -- RIPNG +.. role:: mark -The following technologies are supported as well: +.. comment - the :mark:`X` pieces mesh with a little bit of JavaScript and + CSS in _static/overrides.{js,css} respectively. The JS code looks at the + presence of the 'Y' 'N' '≥' '†' or 'CP' strings. This seemed to be the + best / least intrusive way of getting a nice table in HTML. The table + will look somewhat shoddy on other sphinx targets like PDF or info (but + should still be readable.) -- PBR (Policy Based Routing) -- VNC (Virtual Network Control) ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| Daemon / Feature | Linux | OpenBSD | FreeBSD | NetBSD | Solaris | ++==+================================+================+==============+============+============+============+ +| FRR Core | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| `zebra` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| | VRF | :mark:`≥4.8` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| | MPLS | :mark:`≥4.5` | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| `pbrd` (Policy Routing) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| WAN / Carrier protocols | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| `bgpd` (BGP) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| | VRF / L3VPN | :mark:`≥4.8` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | +| | | :mark:`†4.3` | | | | | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| | EVPN | :mark:`≥4.18` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | +| | | :mark:`†4.9` | | | | | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| | VNC (Virtual Network Control) | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| | Flowspec | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | :mark:`CP` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| `ldpd` (LDP) | :mark:`≥4.5` | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| | VPWS / PW | :mark:`N` | :mark:`≥5.8` | :mark:`N` | :mark:`N` | :mark:`N` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| | VPLS | :mark:`N` | :mark:`≥5.8` | :mark:`N` | :mark:`N` | :mark:`N` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| `nhrpd` (NHRP) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| Link-State Routing | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| `ospfd` (OSPFv2) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| | Segment Routing | :mark:`≥4.12` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| `ospf6d` (OSPFv3) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| `isisd` (IS-IS) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| Distance-Vector Routing | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| `ripd` (RIPv2) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| `ripngd` (RIPng) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| `babeld` (BABEL) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| `eigrpd` (EIGRP) | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| Multicast Routing | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| `pimd` (PIM) | :mark:`≥4.18` | :mark:`N` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| | SSM (Source Specific) | :mark:`Y` | :mark:`N` | :mark:`Y` | :mark:`Y` | :mark:`Y` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ +| | ASM (Any Source) | :mark:`Y` | :mark:`N` | :mark:`N` | :mark:`N` | :mark:`N` | ++--+--------------------------------+----------------+--------------+------------+------------+------------+ + +The indicators have the following semantics: + +* :mark:`Y` - daemon/feature fully functional +* :mark:`≥X.X` - fully functional with kernel version X.X or newer +* :mark:`†X.X` - restricted functionality or impaired performance with kernel version X.X or newer +* :mark:`CP` - control plane only (i.e. BGP route server / route reflector) +* :mark:`N` - daemon/feature not supported by operating system .. _supported-rfcs: From 3175ea5a1465e753bdfb0c53cde8056c1b513c6b Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 25 Aug 2018 02:16:59 +0200 Subject: [PATCH 58/66] doc/user: drop SMUX reference, rework intro Signed-off-by: David Lamparter --- doc/user/overview.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/user/overview.rst b/doc/user/overview.rst index 369514d72d..51bd6228e3 100644 --- a/doc/user/overview.rst +++ b/doc/user/overview.rst @@ -5,12 +5,12 @@ Overview ******** `FRR`_ is a routing software package that provides TCP/IP based routing -services with routing protocols support such as RIPv1, RIPv2, RIPng, OSPFv2, -OSPFv3, IS-IS, BGP-4, and BGP-4+ (:ref:`supported-rfcs`). FRR also supports +services with routing protocols support such as BGP, RIP, OSPF, IS-IS and more +(see :ref:`supported-protocols`). FRR also supports special BGP Route Reflector and Route Server behavior. In addition to traditional IPv4 routing protocols, FRR also supports IPv6 routing protocols. -With SNMP daemon which supports SMUX and AgentX protocol, FRR provides routing -protocol MIBs (:ref:`snmp-support`). +With an SNMP daemon that supports the AgentX protocol, FRR provides routing +protocol MIB read-only access (:ref:`snmp-support`). FRR uses an advanced software architecture to provide you with a high quality, multi server routing engine. FRR has an interactive user interface for each From 086f18fad23a0a2e6ef53f52e4127c932fe0a20e Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 25 Aug 2018 02:21:10 +0200 Subject: [PATCH 59/66] build: drop unused SMUX client OID MIBs These MIB OIDs were only used to identify clients on the SMUX protocol. And even for that, they were essentially pointless. Signed-off-by: David Lamparter --- debianpkg/backports/ubuntu12.04/debian/rules | 6 +- debianpkg/backports/ubuntu14.04/debian/rules | 6 +- debianpkg/rules | 6 +- zebra/GNOME-PRODUCT-ZEBRA-MIB | 78 -------------------- zebra/GNOME-SMI | 53 ------------- zebra/subdir.am | 5 -- 6 files changed, 3 insertions(+), 151 deletions(-) delete mode 100644 zebra/GNOME-PRODUCT-ZEBRA-MIB delete mode 100644 zebra/GNOME-SMI diff --git a/debianpkg/backports/ubuntu12.04/debian/rules b/debianpkg/backports/ubuntu12.04/debian/rules index 086238eda5..7495db89cb 100755 --- a/debianpkg/backports/ubuntu12.04/debian/rules +++ b/debianpkg/backports/ubuntu12.04/debian/rules @@ -154,12 +154,8 @@ override_dh_auto_install: mkdir -p debian/tmp/etc/frr/ perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample* - # installing the Frr specific SNMP MIB -ifeq ($(WANT_SNMP), 1) - install -D -m 644 ./zebra/GNOME-PRODUCT-ZEBRA-MIB debian/tmp/usr/share/snmp/mibs/GNOME-PRODUCT-ZEBRA-MIB -else + # leftover from previously shipping SMUX client OID MIB mkdir -p debian/tmp/usr/share/snmp/mibs -endif # cleaning .la files sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la diff --git a/debianpkg/backports/ubuntu14.04/debian/rules b/debianpkg/backports/ubuntu14.04/debian/rules index 559a27e256..c955d0c945 100755 --- a/debianpkg/backports/ubuntu14.04/debian/rules +++ b/debianpkg/backports/ubuntu14.04/debian/rules @@ -188,12 +188,8 @@ override_dh_auto_install: mkdir -p debian/tmp/etc/frr/ perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample* - # installing the Frr specific SNMP MIB -ifeq ($(WANT_SNMP), 1) - install -D -m 644 ./zebra/GNOME-PRODUCT-ZEBRA-MIB debian/tmp/usr/share/snmp/mibs/GNOME-PRODUCT-ZEBRA-MIB -else + # leftover from previously shipping SMUX client OID MIB mkdir -p debian/tmp/usr/share/snmp/mibs/ -endif # cleaning .la files sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la diff --git a/debianpkg/rules b/debianpkg/rules index 28d291e40a..811d45bc0b 100755 --- a/debianpkg/rules +++ b/debianpkg/rules @@ -186,12 +186,8 @@ override_dh_auto_install: mkdir -p debian/tmp/etc/frr/ perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample* - # installing the Frr specific SNMP MIB -ifeq ($(WANT_SNMP), 1) - install -D -m 644 ./zebra/GNOME-PRODUCT-ZEBRA-MIB debian/tmp/usr/share/snmp/mibs/GNOME-PRODUCT-ZEBRA-MIB -else + # leftover from previously shipping SMUX client OID MIB mkdir -p debian/tmp/usr/share/snmp/mibs/ -endif # cleaning .la files sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la diff --git a/zebra/GNOME-PRODUCT-ZEBRA-MIB b/zebra/GNOME-PRODUCT-ZEBRA-MIB deleted file mode 100644 index 96bcec5763..0000000000 --- a/zebra/GNOME-PRODUCT-ZEBRA-MIB +++ /dev/null @@ -1,78 +0,0 @@ -GNOME-PRODUCT-ZEBRA-MIB DEFINITIONS ::= BEGIN - -IMPORTS - MODULE-IDENTITY, - OBJECT-IDENTITY - FROM SNMPv2-SMI - gnomeProducts - FROM GNOME-SMI; - -zebra MODULE-IDENTITY - LAST-UPDATED "200004250000Z" - ORGANIZATION "GNOME project" - CONTACT-INFO - "GNU Network Object Model Environment project - - see http://www.gnome.org for contact persons of a particular - area or subproject of GNOME. - - Administrative contact for MIB module: - - Jochen Friedrich - Wingertstr. 70/1 - 68809 Neulussheim - Germany - - email: snmp@gnome.org" - DESCRIPTION - "The product registrations for the various zebra subdeamons. - These registrations are guaranteed to be unique and are used - for SMUX registration by default (if not overridden manually)." - ::= { gnomeProducts 2 } - -zserv OBJECT-IDENTITY - STATUS current - DESCRIPTION - "zserv is part of the zebra project which again is a GNU - endorsed internet routing program. - zserv is the main zebra process which implements routing - entries with the kernel and handles routing updates between - other routing protocols." - ::= { zebra 1 } - -bgpd OBJECT-IDENTITY - STATUS current - DESCRIPTION - "bgpd is part of the zebra project which again is a GNU - endorsed internet routing program." - ::= { zebra 2 } - -ripd OBJECT-IDENTITY - STATUS current - DESCRIPTION - "ripd is part of the zebra project which again is a GNU - endorsed internet routing program." - ::= { zebra 3 } - -ripngd OBJECT-IDENTITY - STATUS current - DESCRIPTION - "ripngd is part of the zebra project which again is a GNU - endorsed internet routing program." - ::= { zebra 4 } - -ospfd OBJECT-IDENTITY - STATUS current - DESCRIPTION - "ospfd is part of the zebra project which again is a GNU - endorsed internet routing program." - ::= { zebra 5 } - -ospf6d OBJECT-IDENTITY - STATUS current - DESCRIPTION - "ospf6d is part of the zebra project which again is a GNU - endorsed internet routing program." - ::= { zebra 6 } - -END diff --git a/zebra/GNOME-SMI b/zebra/GNOME-SMI deleted file mode 100644 index 164732bb40..0000000000 --- a/zebra/GNOME-SMI +++ /dev/null @@ -1,53 +0,0 @@ -GNOME-SMI DEFINITIONS ::= BEGIN - -IMPORTS - MODULE-IDENTITY, - OBJECT-IDENTITY, - enterprises - FROM SNMPv2-SMI; - -gnome MODULE-IDENTITY - LAST-UPDATED "9809010000Z" - ORGANIZATION "GNOME project" - CONTACT-INFO - "GNU Network Object Model Environment project - - see http://www.gnome.org for contact persons of a particular - area or subproject of GNOME. - - Administrative contact for MIB module: - - Jochen Friedrich - Wingertstr. 70/1 - 68809 Neulussheim - Germany - - email: snmp@gnome.org" - DESCRIPTION - "The Structure of GNOME." - ::= { enterprises 3317 } -- assigned by IANA - -gnomeProducts OBJECT-IDENTITY - STATUS current - DESCRIPTION - "gnomeProducts is the root OBJECT IDENTIFIER from - which sysObjectID values are assigned." - ::= { gnome 1 } - -gnomeMgmt OBJECT-IDENTITY - STATUS current - DESCRIPTION - "gnomeMgmt defines the subtree for production GNOME related - MIB registrations." - ::= { gnome 2 } - -gnomeTest OBJECT-IDENTITY - STATUS current - DESCRIPTION - "gnomeTest defines the subtree for testing GNOME related - MIB registrations." - ::= { gnome 3 } - --- more to come if necessary. - -END diff --git a/zebra/subdir.am b/zebra/subdir.am index 69f7bc2041..5dc3750315 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -141,8 +141,3 @@ if DEV_BUILD zebra_zebra_fpm_la_SOURCES += zebra/zebra_fpm_dt.c endif endif - -EXTRA_DIST += \ - zebra/GNOME-SMI \ - zebra/GNOME-PRODUCT-ZEBRA-MIB \ - # end From 3535a785b8b1f73c79cf6486aa72db7b4ca8bab9 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sat, 25 Aug 2018 02:54:38 +0200 Subject: [PATCH 60/66] lib: remove Linux 2.4 TCP-MD5 support Linux 2.6.0 was released in December of 2003... I'm pretty sure we don't need this Linux 2.4 support anymore. Signed-off-by: David Lamparter --- configure.ac | 6 ------ lib/sockopt.c | 26 +------------------------- 2 files changed, 1 insertion(+), 31 deletions(-) diff --git a/configure.ac b/configure.ac index 715b1b7ef7..be1c2763a1 100755 --- a/configure.ac +++ b/configure.ac @@ -418,8 +418,6 @@ AC_ARG_ENABLE(rusage, AS_HELP_STRING([--disable-rusage], [disable using getrusage])) AC_ARG_ENABLE(gcc_ultra_verbose, AS_HELP_STRING([--enable-gcc-ultra-verbose], [enable ultra verbose GCC warnings])) -AC_ARG_ENABLE(linux24_tcp_md5, - AS_HELP_STRING([--enable-linux24-tcp-md5], [enable support for old, Linux-2.4 RFC2385 patch])) AC_ARG_ENABLE(backtrace, AS_HELP_STRING([--disable-backtrace,], [disable crash backtraces (default autodetect)])) AC_ARG_ENABLE(time-check, @@ -644,10 +642,6 @@ AM_CONDITIONAL([HAVE_PROTOBUF], [test "x$have_protobuf" = "xyes"]) # End of logic for protobuf support. # -if test "${enable_linux24_tcp_md5}" = "yes"; then - AC_DEFINE(HAVE_TCP_MD5_LINUX24,,Old Linux 2.4 TCP MD5 Signature Patch) -fi - AC_MSG_CHECKING(if zebra should be configurable to send Route Advertisements) if test "${enable_rtadv}" != "no"; then AC_MSG_RESULT(yes) diff --git a/lib/sockopt.c b/lib/sockopt.c index 878b5ae09d..3febcb714d 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -580,31 +580,7 @@ int sockopt_tcp_rtt(int sock) int sockopt_tcp_signature(int sock, union sockunion *su, const char *password) { -#if defined(HAVE_TCP_MD5_LINUX24) && defined(GNU_LINUX) -/* Support for the old Linux 2.4 TCP-MD5 patch, taken from Hasso Tepper's - * version of the Quagga patch (based on work by Rick Payne, and Bruce - * Simpson) - */ -#define TCP_MD5_AUTH 13 -#define TCP_MD5_AUTH_ADD 1 -#define TCP_MD5_AUTH_DEL 2 - struct tcp_rfc2385_cmd { - uint8_t command; /* Command - Add/Delete */ - uint32_t address; /* IPV4 address associated */ - uint8_t keylen; /* MD5 Key len (do NOT assume 0 terminated - ascii) */ - void *key; /* MD5 Key */ - } cmd; - struct in_addr *addr = &su->sin.sin_addr; - - cmd.command = (password != NULL ? TCP_MD5_AUTH_ADD : TCP_MD5_AUTH_DEL); - cmd.address = addr->s_addr; - cmd.keylen = (password != NULL ? strlen(password) : 0); - cmd.key = password; - - return setsockopt(sock, IPPROTO_TCP, TCP_MD5_AUTH, &cmd, sizeof cmd); - -#elif HAVE_DECL_TCP_MD5SIG +#if HAVE_DECL_TCP_MD5SIG int ret; #ifndef GNU_LINUX /* From 1d30d1f4a8241ca45df4eb70181211f5af0ff487 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Thu, 23 Aug 2018 16:05:02 -0400 Subject: [PATCH 61/66] zebra: When registering a nexthop, we do not always need to re-eval The code prior to this change, was allowing clients to register for nexthop tracking. Then zebra would look up the rnh and send to that particular client any known data. Additionally zebra was blindly re-evaluating the rnh for every registration. This leads to interesting behavior in that all people registered for that nexthop will get callbacks even if nothing changes. Modify the code to know if we have evaluated the rnh or not and if so limit the re-evaluation to when absolutely necessary This is of particular importance to do because of nht callbacks for protocols cause those protocols to do not insignificant work and as more protocols are registering for nht callbacks we will cause more work than is necessary. Signed-off-by: Donald Sharp --- zebra/zapi_msg.c | 10 ++++++++-- zebra/zebra_rnh.c | 22 +++++++++++++++++----- zebra/zebra_rnh.h | 2 +- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 6990fd95f5..d95f78109c 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1022,6 +1022,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) unsigned short l = 0; uint8_t flags = 0; uint16_t type = cmd2type[hdr->command]; + bool exist; if (IS_ZEBRA_DEBUG_NHT) zlog_debug( @@ -1064,7 +1065,10 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) p.family); return; } - rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type); + rnh = zebra_add_rnh(&p, zvrf_id(zvrf), type, &exist); + if (!rnh) + return; + if (type == RNH_NEXTHOP_TYPE) { if (flags && !CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) @@ -1084,7 +1088,9 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf)); /* Anything not AF_INET/INET6 has been filtered out above */ - zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, &p); + if (!exist) + zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, + &p); } stream_failure: diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 156600c105..0b585af6a0 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -103,7 +103,8 @@ char *rnh_str(struct rnh *rnh, char *buf, int size) return buf; } -struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type) +struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type, + bool *exists) { struct route_table *table; struct route_node *rn; @@ -119,6 +120,7 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type) prefix2str(p, buf, sizeof(buf)); zlog_warn("%u: Add RNH %s type %d - table not found", vrfid, buf, type); + exists = false; return NULL; } @@ -136,7 +138,9 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type) route_lock_node(rn); rn->info = rnh; rnh->node = rn; - } + *exists = false; + } else + *exists = true; route_unlock_node(rn); return (rn->info); @@ -190,6 +194,14 @@ void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type) route_unlock_node(rn); } +/* + * This code will send to the registering client + * the looked up rnh. + * For a rnh that was created, there is no data + * so it will send an empty nexthop group + * If rnh exists then we know it has been evaluated + * and as such it will have a resolved rnh. + */ void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, vrf_id_t vrf_id) { @@ -201,8 +213,7 @@ void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, } if (!listnode_lookup(rnh->client_list, client)) { listnode_add(rnh->client_list, client); - send_client(rnh, client, type, - vrf_id); // Pending: check if its needed + send_client(rnh, client, type, vrf_id); } } @@ -247,9 +258,10 @@ void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw) { struct prefix nh; struct rnh *rnh; + bool exists; addr2hostprefix(pw->af, &pw->nexthop, &nh); - rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE); + rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE, &exists); if (rnh && !listnode_lookup(rnh->zebra_pseudowire_list, pw)) { listnode_add(rnh->zebra_pseudowire_list, pw); pw->rnh = rnh; diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index 9e09a1bc6f..f4b4b56390 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -68,7 +68,7 @@ static inline int rnh_resolve_via_default(int family) } extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, - rnh_type_t type); + rnh_type_t type, bool *exists); extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type); extern void zebra_free_rnh(struct rnh *rnh); From 74f0a94efdfca6c1b3a03d14bf095b6a8f8a2f1f Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Fri, 24 Aug 2018 20:42:45 -0400 Subject: [PATCH 62/66] staticd: refcount the nht add/removal When we add / remove a nexthop that we need to track, keep track of the number of times we have done this for each nexthop. Consequently keep track of the number of available nexthops, so that we can just install new routes when we get one that uses a pre-existing nexthop. Deletion of nexthops is done on refcount going to 0. Removal of routes is handled elsewhere for removal. Signed-off-by: Donald Sharp --- staticd/static_zebra.c | 92 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 2 deletions(-) diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index 56ba70eaf8..a87dc074df 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -34,6 +34,7 @@ #include "log.h" #include "nexthop.h" #include "nexthop_group.h" +#include "hash.h" #include "static_vrf.h" #include "static_routes.h" @@ -43,6 +44,7 @@ /* Zebra structure to hold current status. */ struct zclient *zclient; +static struct hash *static_nht_hash; static struct interface *zebra_interface_if_lookup(struct stream *s) { @@ -176,10 +178,16 @@ static void zebra_connected(struct zclient *zclient) zclient_send_reg_requests(zclient, VRF_DEFAULT); } +struct static_nht_data { + struct prefix *nh; + uint32_t refcount; + uint8_t nh_num; +}; static int static_zebra_nexthop_update(int command, struct zclient *zclient, zebra_size_t length, vrf_id_t vrf_id) { + struct static_nht_data *nhtd, lookup; struct zapi_route nhr; afi_t afi = AFI_IP; @@ -191,6 +199,14 @@ static int static_zebra_nexthop_update(int command, struct zclient *zclient, if (nhr.prefix.family == AF_INET6) afi = AFI_IP6; + memset(&lookup, 0, sizeof(lookup)); + lookup.nh = &nhr.prefix; + + nhtd = hash_lookup(static_nht_hash, &lookup); + if (nhtd) + nhtd->nh_num = nhr.nexthop_num; + + static_nht_update(&nhr.prefix, nhr.nexthop_num, afi, vrf_id); return 1; } @@ -200,10 +216,50 @@ static void static_zebra_capabilities(struct zclient_capabilities *cap) mpls_enabled = cap->mpls_enabled; } +static unsigned int static_nht_hash_key(void *data) +{ + struct static_nht_data *nhtd = data; + + return prefix_hash_key(nhtd->nh); +} + +static int static_nht_hash_cmp(const void *d1, const void *d2) +{ + const struct static_nht_data *nhtd1 = d1; + const struct static_nht_data *nhtd2 = d2; + + return prefix_same(nhtd1->nh, nhtd2->nh); +} + +static void *static_nht_hash_alloc(void *data) +{ + struct static_nht_data *copy = data; + struct static_nht_data *new; + + new = XMALLOC(MTYPE_TMP, sizeof(*new)); + + new->nh = prefix_new(); + prefix_copy(new->nh, copy->nh); + new->refcount = 0; + new->nh_num = 0; + + return new; +} + +static void static_nht_hash_free(void *data) +{ + struct static_nht_data *nhtd = data; + + prefix_free(nhtd->nh); + XFREE(MTYPE_TMP, nhtd); +} + void static_zebra_nht_register(struct static_route *si, bool reg) { + struct static_nht_data *nhtd, lookup; uint32_t cmd; struct prefix p; + afi_t afi = AFI_IP; cmd = (reg) ? ZEBRA_NEXTHOP_REGISTER : ZEBRA_NEXTHOP_UNREGISTER; @@ -224,20 +280,48 @@ void static_zebra_nht_register(struct static_route *si, bool reg) p.family = AF_INET; p.prefixlen = IPV4_MAX_BITLEN; p.u.prefix4 = si->addr.ipv4; + afi = AFI_IP; break; case STATIC_IPV6_GATEWAY: case STATIC_IPV6_GATEWAY_IFNAME: p.family = AF_INET6; p.prefixlen = IPV6_MAX_BITLEN; p.u.prefix6 = si->addr.ipv6; + afi = AFI_IP6; break; } + memset(&lookup, 0, sizeof(lookup)); + lookup.nh = &p; + + si->nh_registered = reg; + + if (reg) { + nhtd = hash_get(static_nht_hash, &lookup, + static_nht_hash_alloc); + nhtd->refcount++; + + if (nhtd->refcount > 1) { + static_nht_update(nhtd->nh, nhtd->nh_num, + afi, si->nh_vrf_id); + return; + } + } else { + nhtd = hash_lookup(static_nht_hash, &lookup); + if (!nhtd) + return; + + nhtd->refcount--; + if (nhtd->refcount >= 1) + return; + + hash_release(static_nht_hash, nhtd); + static_nht_hash_free(nhtd); + } + if (zclient_send_rnh(zclient, cmd, &p, false, si->nh_vrf_id) < 0) zlog_warn("%s: Failure to send nexthop to zebra", __PRETTY_FUNCTION__); - - si->nh_registered = reg; } extern void static_zebra_route_add(struct route_node *rn, @@ -373,4 +457,8 @@ void static_zebra_init(void) zclient->interface_address_delete = interface_address_delete; zclient->route_notify_owner = route_notify_owner; zclient->nexthop_update = static_zebra_nexthop_update; + + static_nht_hash = hash_create(static_nht_hash_key, + static_nht_hash_cmp, + "Static Nexthop Tracking hash"); } From 87da6a60191410ee957d6c5b58c0226f658c2ca4 Mon Sep 17 00:00:00 2001 From: Stephen Worley Date: Sat, 11 Aug 2018 18:36:22 -0400 Subject: [PATCH 63/66] zebra: Add support for static encap mpls labels We were ignoring mpls labels encapped with static routes. Added support for single and multipath labels. Signed-off-by: Stephen Worley Signed-off-by: Donald Sharp --- zebra/kernel_netlink.c | 12 ++++++++ zebra/kernel_netlink.h | 2 ++ zebra/rt_netlink.c | 64 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 73 insertions(+), 5 deletions(-) diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index ef7c26c9df..545b4d9d6d 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -467,6 +467,18 @@ void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, } } +/** + * netlink_parse_rtattr_nested() - Parses a nested route attribute + * @tb: Pointer to array for storing rtattr in. + * @max: Max number to store. + * @rta: Pointer to rtattr to look for nested items in. + */ +void netlink_parse_rtattr_nested(struct rtattr **tb, int max, + struct rtattr *rta) +{ + netlink_parse_rtattr(tb, max, RTA_DATA(rta), RTA_PAYLOAD(rta)); +} + int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type, const void *data, unsigned int alen) { diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index 65df15599d..af0cc83f4a 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -28,6 +28,8 @@ extern void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len); +extern void netlink_parse_rtattr_nested(struct rtattr **tb, int max, + struct rtattr *rta); extern int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type, const void *data, unsigned int alen); extern int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type, diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 6a258e6853..cab3f43b19 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -246,6 +246,33 @@ static vrf_id_t vrf_lookup_by_table(uint32_t table_id, ns_id_t ns_id) return VRF_DEFAULT; } +/** + * @parse_encap_mpls() - Parses encapsulated mpls attributes + * @tb: Pointer to rtattr to look for nested items in. + * @labels: Pointer to store labels in. + * + * Return: Number of mpls labels found. + */ +static int parse_encap_mpls(struct rtattr *tb, mpls_label_t *labels) +{ + struct rtattr *tb_encap[MPLS_IPTUNNEL_MAX + 1] = {0}; + mpls_lse_t *lses = NULL; + int num_labels = 0; + uint32_t ttl = 0; + uint32_t bos = 0; + uint32_t exp = 0; + mpls_label_t label = 0; + + netlink_parse_rtattr_nested(tb_encap, MPLS_IPTUNNEL_MAX, tb); + lses = (mpls_lse_t *)RTA_DATA(tb_encap[MPLS_IPTUNNEL_DST]); + while (!bos && num_labels < MPLS_MAX_LABELS) { + mpls_lse_decode(lses[num_labels], &label, &ttl, &exp, &bos); + labels[num_labels++] = label; + } + + return num_labels; +} + /* Looking up routing table by netlink interface. */ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, int startup) @@ -274,6 +301,10 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, void *src = NULL; /* IPv6 srcdest source prefix */ enum blackhole_type bh_type = BLACKHOLE_UNSPEC; + /* MPLS labels */ + mpls_label_t labels[MPLS_MAX_LABELS] = {0}; + int num_labels = 0; + rtm = NLMSG_DATA(h); if (startup && h->nlmsg_type != RTM_NEWROUTE) @@ -508,6 +539,17 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, } nh.vrf_id = nh_vrf_id; + if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE] + && *(uint16_t *)RTA_DATA(tb[RTA_ENCAP_TYPE]) + == LWTUNNEL_ENCAP_MPLS) { + num_labels = + parse_encap_mpls(tb[RTA_ENCAP], labels); + } + + if (num_labels) + nexthop_add_labels(&nh, ZEBRA_LSP_STATIC, + num_labels, labels); + rib_add(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p, &src_p, &nh, table, metric, mtu, distance, tag); } else { @@ -532,6 +574,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, re->tag = tag; for (;;) { + struct nexthop *nh = NULL; vrf_id_t nh_vrf_id; if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len) @@ -569,35 +612,46 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, if (tb[RTA_GATEWAY]) gate = RTA_DATA( tb[RTA_GATEWAY]); + if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE] + && *(uint16_t *)RTA_DATA( + tb[RTA_ENCAP_TYPE]) + == LWTUNNEL_ENCAP_MPLS) { + num_labels = parse_encap_mpls( + tb[RTA_ENCAP], labels); + } } if (gate) { if (rtm->rtm_family == AF_INET) { if (index) - route_entry_nexthop_ipv4_ifindex_add( + nh = route_entry_nexthop_ipv4_ifindex_add( re, gate, prefsrc, index, nh_vrf_id); else - route_entry_nexthop_ipv4_add( + nh = route_entry_nexthop_ipv4_add( re, gate, prefsrc, nh_vrf_id); } else if (rtm->rtm_family == AF_INET6) { if (index) - route_entry_nexthop_ipv6_ifindex_add( + nh = route_entry_nexthop_ipv6_ifindex_add( re, gate, index, nh_vrf_id); else - route_entry_nexthop_ipv6_add( + nh = route_entry_nexthop_ipv6_add( re, gate, nh_vrf_id); } } else - route_entry_nexthop_ifindex_add( + nh = route_entry_nexthop_ifindex_add( re, index, nh_vrf_id); + if (nh && num_labels) + nexthop_add_labels(nh, ZEBRA_LSP_STATIC, + num_labels, labels); + if (rtnh->rtnh_len == 0) break; From 344b4a29bf41577c25d1bfc2db62f22f412a7c0d Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 25 Aug 2018 18:26:01 -0400 Subject: [PATCH 64/66] isisd: Include header for function declaration isis_handle_pdu is called but not declared for usage by not including the appropriate header. Signed-off-by: Donald Sharp --- isisd/isis_bpf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c index d05dba33ee..7e8a4a4eda 100644 --- a/isisd/isis_bpf.c +++ b/isisd/isis_bpf.c @@ -43,6 +43,7 @@ #include "isisd/isis_constants.h" #include "isisd/isis_circuit.h" #include "isisd/isis_network.h" +#include "isisd/isis_pdu.h" #include "privs.h" From 184ce1c5d16850c56830ad02a6cb22151f553cf8 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 25 Aug 2018 18:27:11 -0400 Subject: [PATCH 65/66] lib: Cleanup uninted `top` variable in ferr.c The `top` variable could possibly be used without any initialization, remove the possibility. Signed-off-by: Donald Sharp --- lib/ferr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ferr.c b/lib/ferr.c index d1b9d514b4..17ec51c4bf 100644 --- a/lib/ferr.c +++ b/lib/ferr.c @@ -107,7 +107,7 @@ struct log_ref *log_ref_get(uint32_t code) void log_ref_display(struct vty *vty, uint32_t code, bool json) { struct log_ref *ref; - struct json_object *top, *obj; + struct json_object *top = NULL, *obj = NULL; struct list *errlist; struct listnode *ln; From f7dae31211dedf2e66f7d8bebdc9ff7f148eceef Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Sat, 25 Aug 2018 18:28:19 -0400 Subject: [PATCH 66/66] zebra: No prototype and uninited variables Add a header to cleanup no declaration and properly wrapper some variables to appropriate #ifdef. Signed-off-by: Donald Sharp --- zebra/if_ioctl.c | 1 + zebra/zebra_vxlan.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index d17a9cf498..176bb2bbad 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -37,6 +37,7 @@ #include "zebra/interface.h" #include "zebra/rib.h" +#include "zebra/rt.h" #include diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index f63879159d..b0fc0a39bd 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -1558,7 +1558,9 @@ static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n) struct zebra_if *zif; struct zebra_l2info_vxlan *vxl; struct interface *vlan_if; +#ifdef GNU_LINUX uint8_t flags; +#endif int ret = 0; if (!(n->flags & ZEBRA_NEIGH_REMOTE)) @@ -3369,7 +3371,9 @@ static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n) */ static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n) { +#ifdef GNU_LINUX uint8_t flags; +#endif int ret = 0; if (!is_l3vni_oper_up(zl3vni))