diff options
114 files changed, 1802 insertions, 1010 deletions
diff --git a/Makefile.am b/Makefile.am index 5dc80b4983..ed22c60e7c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -115,3 +115,23 @@ noinst_HEADERS += defaults.h indent: tools/indent.py `find sharpd bgpd eigrpd include isisd lib nhrpd ospf6d ospfd pimd qpb ripd vtysh zebra -name '*.[ch]' | grep -v include/linux` + +if HAVE_GCOV + +coverage: check + @ find . -name '*.o' -exec gcov {} \; + +yorn: + @ echo "OK to upload coverage to https://coverage.io [y/N]:" + @ read yn; test "$$yn" = "y" + +upload-check-coverage: + @ if [ "x${COMMIT}" = "x" ]; then echo "COMMIT required"; exit 1; fi + @ if [ "x${TOKEN}" = "x" ]; then echo "TOKEN required"; exit 1; fi + curl -s https://codecov.io/bash | bash -s - -C ${COMMIT} -t ${TOKEN} + +force-check-coverage: coverage upload-check-coverage + +check-coverage: coverage yorn upload-check-coverage + +endif diff --git a/bgpd/IMPLEMENTATION.txt b/bgpd/IMPLEMENTATION.txt index fff360ab96..0f06359686 100644 --- a/bgpd/IMPLEMENTATION.txt +++ b/bgpd/IMPLEMENTATION.txt @@ -131,7 +131,6 @@ bgpd.h struct peer_group struct bgp_notify: (in-core representation of wire format?) struct bgp_nexthop: (v4 and v6 addresses, *ifp) - struct bgp_rd: router distinguisher: 8 octects struct bgp_filter: distribute, prefix, aslist, route_maps struct peer: neighbor structure (very rich/complex) struct bgp_nlri: reference to wire format diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index 0ffbe174ed..b2f34dd968 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -274,8 +274,7 @@ static void community_list_entry_add(struct community_list *list, /* Delete community-list entry from the list. */ static void community_list_entry_delete(struct community_list *list, - struct community_entry *entry, - int style) + struct community_entry *entry) { if (entry->next) entry->next->prev = entry->prev; @@ -882,7 +881,7 @@ int community_list_unset(struct community_list_handler *ch, const char *name, if (!entry) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; - community_list_entry_delete(list, entry, style); + community_list_entry_delete(list, entry); route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED); return 0; @@ -1040,7 +1039,7 @@ int lcommunity_list_unset(struct community_list_handler *ch, const char *name, if (!entry) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; - community_list_entry_delete(list, entry, style); + community_list_entry_delete(list, entry); return 0; } @@ -1057,8 +1056,6 @@ int extcommunity_list_set(struct community_list_handler *ch, const char *name, if (str == NULL) return COMMUNITY_LIST_ERR_MALFORMED_VAL; - entry = NULL; - /* Get community list. */ list = community_list_get(ch, name, EXTCOMMUNITY_LIST_MASTER); @@ -1149,7 +1146,7 @@ int extcommunity_list_unset(struct community_list_handler *ch, const char *name, if (!entry) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; - community_list_entry_delete(list, entry, style); + community_list_entry_delete(list, entry); route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED); return 0; diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 8c5356c998..2c372124d2 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -65,7 +65,6 @@ void ecommunity_free(struct ecommunity **ecom) if ((*ecom)->str) XFREE(MTYPE_ECOMMUNITY_STR, (*ecom)->str); XFREE(MTYPE_ECOMMUNITY, *ecom); - ecom = NULL; } static void ecommunity_hash_free(struct ecommunity *ecom) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 959418658c..a026df59a0 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -4639,7 +4639,6 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, int addpath_encoded; int psize = 0; uint8_t rtype; - uint8_t rlen; struct prefix p; /* Start processing the NLRI - there may be multiple in the MP_REACH */ @@ -4673,7 +4672,7 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, return -1; rtype = *pnt++; - psize = rlen = *pnt++; + psize = *pnt++; /* When packet overflow occur return immediately. */ if (pnt + psize > lim) @@ -5216,7 +5215,7 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, struct ethaddr *rmac, struct bgpevpn *vpn = NULL; as_t as = 0; - /* get the default instamce - required to get the AS number for VRF + /* get the default instance - required to get the AS number for VRF * auto-creatio */ bgp_def = bgp_get_default(); @@ -5319,11 +5318,12 @@ int bgp_evpn_local_l3vni_del(vni_t l3vni, vrf_id_t vrf_id) return -1; } - /* unimport remote routes from VRF, if it is AUTO vrf bgp_delete will - * take care of uninstalling the routes from zebra + /* Remove remote routes from BGT VRF even if BGP_VRF_AUTO is configured, + * bgp_delete would not remove/decrement bgp_info of the ip_prefix + * routes. This will uninstalling the routes from zebra and decremnt the + * bgp info count. */ - if (!CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_AUTO)) - uninstall_routes_for_vrf(bgp_vrf); + uninstall_routes_for_vrf(bgp_vrf); /* delete/withdraw all type-5 routes */ delete_withdraw_vrf_routes(bgp_vrf); diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c index 9b998d4497..2d336fa6d8 100644 --- a/bgpd/bgp_flowspec.c +++ b/bgpd/bgp_flowspec.c @@ -91,7 +91,6 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, afi_t afi; safi_t safi; int psize = 0; - uint8_t rlen; struct prefix p; int ret; void *temp; @@ -121,7 +120,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, if (pnt + 1 > lim) return -1; - psize = rlen = *pnt++; + psize = *pnt++; /* When packet overflow occur return immediately. */ if (pnt + psize > lim) { diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c index 90acd8fcb1..c695e7f125 100644 --- a/bgpd/bgp_flowspec_vty.c +++ b/bgpd/bgp_flowspec_vty.c @@ -274,7 +274,7 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p, else json_nlri_path = json_paths; } - if (display == NLRI_STRING_FORMAT_LARGE) + if (display == NLRI_STRING_FORMAT_LARGE && binfo) vty_out(vty, "BGP flowspec entry: (flags 0x%x)\n", binfo->flags); bgp_fs_nlri_get_string((unsigned char *) diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c index ceca644de2..8a051b7ff0 100644 --- a/bgpd/bgp_label.c +++ b/bgpd/bgp_label.c @@ -57,7 +57,7 @@ int bgp_parse_fec_update(void) memset(&p, 0, sizeof(struct prefix)); p.family = stream_getw(s); p.prefixlen = stream_getc(s); - stream_get(&p.u.prefix, s, PSIZE(p.prefixlen)); + stream_get(p.u.val, s, PSIZE(p.prefixlen)); label = stream_getl(s); /* hack for the bgp instance & SAFI = have to send/receive it */ diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c index 33f4d139b8..3e160bc56e 100644 --- a/bgpd/bgp_lcommunity.c +++ b/bgpd/bgp_lcommunity.c @@ -50,7 +50,6 @@ void lcommunity_free(struct lcommunity **lcom) if ((*lcom)->str) XFREE(MTYPE_LCOMMUNITY_STR, (*lcom)->str); XFREE(MTYPE_LCOMMUNITY, *lcom); - lcom = NULL; } static void lcommunity_hash_free(struct lcommunity *lcom) diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 3a854be534..f72104dd33 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -220,7 +220,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr, p.prefixlen = prefixlen - VPN_PREFIXLEN_MIN_BYTES * 8; /* exclude label & RD */ - memcpy(&p.u.prefix, pnt + VPN_PREFIXLEN_MIN_BYTES, + memcpy(p.u.val, pnt + VPN_PREFIXLEN_MIN_BYTES, psize - VPN_PREFIXLEN_MIN_BYTES); if (attr) { @@ -490,7 +490,7 @@ leak_update( * (only one hop back to ultimate parent for vrf-vpn-vrf scheme). * Using a loop here supports more complex intra-bgp import-export * schemes that could be implemented in the future. - * + * */ for (bi_ultimate = source_bi; bi_ultimate->extra && bi_ultimate->extra->parent; @@ -1356,8 +1356,7 @@ void vpn_leak_to_vrf_update_all(struct bgp *bgp_vrf, /* to */ struct bgp_node *prn; safi_t safi = SAFI_MPLS_VPN; - if (!bgp_vpn) - return; + assert(bgp_vpn); /* * Walk vpn table @@ -2253,3 +2252,66 @@ vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey) } return VRF_UNKNOWN; } + +/* + * The purpose of this function is to process leaks that were deferred + * from earlier per-vrf configuration due to not-yet-existing default + * vrf, in other words, configuration such as: + * + * router bgp MMM vrf FOO + * address-family ipv4 unicast + * rd vpn export 1:1 + * exit-address-family + * + * router bgp NNN + * ... + * + * This function gets called when the default instance ("router bgp NNN") + * is created. + */ +void vpn_leak_postchange_all(void) +{ + struct listnode *next; + struct bgp *bgp; + struct bgp *bgp_default = bgp_get_default(); + + assert(bgp_default); + + /* First, do any exporting from VRFs to the single VPN RIB */ + for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) { + + if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF) + continue; + + vpn_leak_postchange( + BGP_VPN_POLICY_DIR_TOVPN, + AFI_IP, + bgp_default, + bgp); + + vpn_leak_postchange( + BGP_VPN_POLICY_DIR_TOVPN, + AFI_IP6, + bgp_default, + bgp); + } + + /* Now, do any importing to VRFs from the single VPN RIB */ + for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) { + + if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF) + continue; + + vpn_leak_postchange( + BGP_VPN_POLICY_DIR_FROMVPN, + AFI_IP, + bgp_default, + bgp); + + vpn_leak_postchange( + BGP_VPN_POLICY_DIR_FROMVPN, + AFI_IP6, + bgp_default, + bgp); + } +} diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 384108dc0c..b0add40da9 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -182,6 +182,10 @@ static inline void vpn_leak_prechange(vpn_policy_direction_t direction, afi_t afi, struct bgp *bgp_vpn, struct bgp *bgp_vrf) { + /* Detect when default bgp instance is not (yet) defined by config */ + if (!bgp_vpn) + return; + if ((direction == BGP_VPN_POLICY_DIR_FROMVPN) && vpn_leak_from_vpn_active(bgp_vrf, afi, NULL)) { @@ -198,6 +202,10 @@ static inline void vpn_leak_postchange(vpn_policy_direction_t direction, afi_t afi, struct bgp *bgp_vpn, struct bgp *bgp_vrf) { + /* Detect when default bgp instance is not (yet) defined by config */ + if (!bgp_vpn) + return; + if (direction == BGP_VPN_POLICY_DIR_FROMVPN) vpn_leak_to_vrf_update_all(bgp_vrf, bgp_vpn, afi); if (direction == BGP_VPN_POLICY_DIR_TOVPN) { @@ -216,4 +224,6 @@ extern void vpn_policy_routemap_event(const char *rmap_name); extern vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey); +extern void vpn_leak_postchange_all(void); + #endif /* _QUAGGA_BGP_MPLSVPN_H */ diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 32011d210b..76bfa73fee 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -447,8 +447,6 @@ int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop, p.family = AF_INET; p.prefixlen = IPV4_MAX_BITLEN; - rn2 = NULL; - bgp = SUBGRP_INST(subgrp); rn1 = bgp_node_match(bgp->connected_table[AFI_IP], &np); if (!rn1) diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h index c92fd9b0a7..42ebe97f2e 100644 --- a/bgpd/bgp_open.h +++ b/bgpd/bgp_open.h @@ -34,21 +34,12 @@ struct capability_mp_data { uint8_t safi; /* iana_safi_t */ }; -struct capability_as4 { - uint32_t as4; -}; - struct graceful_restart_af { afi_t afi; safi_t safi; uint8_t flag; }; -struct capability_gr { - uint16_t restart_flag_time; - struct graceful_restart_af gr[]; -}; - /* Capability Code */ #define CAPABILITY_CODE_MP 1 /* Multiprotocol Extensions */ #define CAPABILITY_CODE_REFRESH 2 /* Route Refresh Capability */ diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index 45ec21631c..b5ddfd4b21 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -348,7 +348,7 @@ static bool bgp_pbr_extract_enumerate(struct bgp_pbr_match_val list[], void *valmask, uint8_t type_entry) { bool ret; - uint8_t unary_operator_val = unary_operator; + uint8_t unary_operator_val; bool double_check = false; if ((unary_operator & OPERATOR_UNARY_OR) && diff --git a/bgpd/bgp_pbr.h b/bgpd/bgp_pbr.h index 307a34e34f..e853784afd 100644 --- a/bgpd/bgp_pbr.h +++ b/bgpd/bgp_pbr.h @@ -57,17 +57,13 @@ struct bgp_pbr_match_val { uint16_t value; uint8_t compare_operator; uint8_t unary_operator; -} bgp_pbr_value_t; +}; #define FRAGMENT_DONT 1 #define FRAGMENT_IS 2 #define FRAGMENT_FIRST 4 #define FRAGMENT_LAST 8 -struct bgp_pbr_fragment_val { - uint8_t bitmask; -}; - struct bgp_pbr_entry_action { /* used to store enum bgp_pbr_action_enum enumerate */ uint8_t action; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 7057b62f2b..795bd15613 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -2168,7 +2168,6 @@ struct bgp_process_queue { static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi) { - struct prefix *p = &rn->p; struct bgp_info *new_select; struct bgp_info *old_select; struct bgp_info_pair old_and_new; @@ -2191,6 +2190,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, return; } + struct prefix *p = &rn->p; + debug = bgp_debug_bestpath(&rn->p); if (debug) { prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf)); @@ -2672,14 +2673,12 @@ static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_info *ri, struct peer *peer, afi_t afi, safi_t safi, struct prefix_rd *prd) { - int status = BGP_DAMP_NONE; - /* apply dampening, if result is suppressed, we'll be retaining * the bgp_info in the RIB for historical reference. */ if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) && peer->sort == BGP_PEER_EBGP) - if ((status = bgp_damp_withdraw(ri, rn, afi, safi, 0)) + if ((bgp_damp_withdraw(ri, rn, afi, safi, 0)) == BGP_DAMP_SUPPRESSED) { bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi, safi); @@ -4237,7 +4236,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr, } /* Fetch prefix from NLRI packet. */ - memcpy(&p.u.prefix, pnt, psize); + memcpy(p.u.val, pnt, psize); /* Check address. */ if (afi == AFI_IP && safi == SAFI_UNICAST) { diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index f7c79f873d..f9f5142cd0 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -1298,6 +1298,9 @@ static route_map_result_t route_set_ip_nexthop(void *rule, bgp_info->attr->nexthop = *rins->address; SET_FLAG(bgp_info->attr->rmap_change_flags, BATTR_RMAP_IPV4_NHOP_CHANGED); + /* case for MP-BGP : MPLS VPN */ + bgp_info->attr->mp_nexthop_global_in = *rins->address; + bgp_info->attr->mp_nexthop_len = sizeof(*rins->address); } } diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 82e857dbf4..774c484784 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -5,8 +5,8 @@ * Berlin * Copyright (C) 2016-2017 Colin Sames (colin.sames@haw-hamburg.de), for HAW * Hamburg - * Copyright (C) 2017 Marcel Röthke (marcel.roethke@haw-hamburg.de), for HAW - * Hamburg + * Copyright (C) 2017-2018 Marcel Röthke (marcel.roethke@haw-hamburg.de), + * for HAW Hamburg * * This file is part of FRRouting. * @@ -47,6 +47,7 @@ #include "bgpd/bgp_attr.h" #include "bgpd/bgp_aspath.h" #include "bgpd/bgp_route.h" +#include "lib/thread.h" #include "rtrlib/rtrlib.h" #include "rtrlib/rtr_mgr.h" #include "rtrlib/lib/ip.h" @@ -128,16 +129,22 @@ static void route_match_free(void *rule); static route_map_result_t route_match(void *rule, struct prefix *prefix, route_map_object_t type, void *object); 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 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 int rpki_debug; static unsigned int polling_period; static unsigned int expire_interval; static unsigned int retry_interval; static unsigned int timeout; static unsigned int initial_synchronisation_timeout; +static int rpki_sync_socket_rtr; +static int rpki_sync_socket_bgpd; static struct cmd_node rpki_node = {RPKI_NODE, "%s(config-rpki)# ", 1}; static struct route_map_rule_cmd route_match_rpki_cmd = { @@ -185,6 +192,22 @@ static void free_tr_socket(struct cache *cache) static int rpki_validate_prefix(struct peer *peer, struct attr *attr, struct prefix *prefix); +static void ipv6_addr_to_network_byte_order(const uint32_t *src, uint32_t *dest) +{ + int i; + + for (i = 0; i < 4; i++) + dest[i] = htonl(src[i]); +} + +static void ipv6_addr_to_host_byte_order(const uint32_t *src, uint32_t *dest) +{ + int i; + + for (i = 0; i < 4; i++) + dest[i] = ntohl(src[i]); +} + static route_map_result_t route_match(void *rule, struct prefix *prefix, route_map_object_t type, void *object) { @@ -295,10 +318,159 @@ inline int is_running(void) return rtr_is_running; } +static struct prefix *pfx_record_to_prefix(struct pfx_record *record) +{ + struct prefix *prefix = prefix_new(); + + prefix->prefixlen = record->min_len; + + if (record->prefix.ver == LRTR_IPV4) { + prefix->family = AF_INET; + prefix->u.prefix4.s_addr = htonl(record->prefix.u.addr4.addr); + } else { + prefix->family = AF_INET6; + ipv6_addr_to_network_byte_order(record->prefix.u.addr6.addr, + prefix->u.prefix6.s6_addr32); + } + + return prefix; +} + +static int bgpd_sync_callback(struct thread *thread) +{ + struct bgp *bgp; + struct listnode *node; + struct prefix *prefix; + struct pfx_record rec; + + thread_add_read(bm->master, bgpd_sync_callback, NULL, + rpki_sync_socket_bgpd, NULL); + int retval = + read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record)); + if (retval != sizeof(struct pfx_record)) { + RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd"); + return retval; + } + prefix = pfx_record_to_prefix(&rec); + + afi_t afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6; + + for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) { + safi_t safi; + + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (!bgp->rib[afi][safi]) + continue; + + struct list *matches = list_new(); + + matches->del = (void (*)(void *))bgp_unlock_node; + + bgp_table_range_lookup(bgp->rib[afi][safi], prefix, + rec.max_len, matches); + + + struct bgp_node *bgp_node; + + for (ALL_LIST_ELEMENTS_RO(matches, node, bgp_node)) + revalidate_bgp_node(bgp_node, afi, safi); + + list_delete_and_null(&matches); + } + } + + prefix_free(prefix); + return 0; +} + +static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi, + safi_t safi) +{ + struct bgp_adj_in *ain; + + for (ain = bgp_node->adj_in; ain; ain = ain->next) { + int ret; + struct bgp_info *bgp_info = bgp_node->info; + mpls_label_t *label = NULL; + uint32_t num_labels = 0; + + if (bgp_info && bgp_info->extra) { + 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); + + if (ret < 0) { + bgp_unlock_node(bgp_node); + return; + } + } +} + +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; + + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { + if (!bgp->rib[afi][safi]) + continue; + + 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); + } + } + } + } + } +} + +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) + return; + + int retval = + write(rpki_sync_socket_rtr, &rec, sizeof(struct pfx_record)); + 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]; + + RPKI_DEBUG("initializing sync socket"); + if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, fds) != 0) { + RPKI_DEBUG("Could not open rpki sync socket"); + return; + } + rpki_sync_socket_rtr = fds[0]; + rpki_sync_socket_bgpd = fds[1]; + thread_add_read(bm->master, bgpd_sync_callback, NULL, + rpki_sync_socket_bgpd, NULL); +} + static int bgp_rpki_init(struct thread_master *master) { rpki_debug = 0; rtr_is_running = 0; + rtr_is_stopping = 0; cache_list = list_new(); cache_list->del = (void (*)(void *)) & free_cache; @@ -310,6 +482,7 @@ static int bgp_rpki_init(struct thread_master *master) initial_synchronisation_timeout = INITIAL_SYNCHRONISATION_TIMEOUT_DEFAULT; install_cli_commands(); + rpki_init_sync_socket(); return 0; } @@ -318,6 +491,9 @@ static int bgp_rpki_fini(void) stop(); list_delete_and_null(&cache_list); + close(rpki_sync_socket_rtr); + close(rpki_sync_socket_bgpd); + return 0; } @@ -336,6 +512,9 @@ static int start(void) unsigned int waiting_time = 0; int ret; + rtr_is_stopping = 0; + rtr_is_starting = 1; + if (list_isempty(cache_list)) { RPKI_DEBUG( "No caches were found in config. Prefix validation is off."); @@ -345,9 +524,10 @@ static int start(void) int groups_len = listcount(cache_list); struct rtr_mgr_group *groups = get_groups(); + RPKI_DEBUG("Polling period: %d", polling_period); ret = rtr_mgr_init(&rtr_config, groups, groups_len, polling_period, - expire_interval, retry_interval, NULL, NULL, NULL, - NULL); + expire_interval, retry_interval, + rpki_update_cb_sync_rtr, NULL, NULL, NULL); if (ret == RTR_ERROR) { RPKI_DEBUG("Init rtr_mgr failed."); return ERROR; @@ -370,9 +550,13 @@ static int start(void) } if (rtr_mgr_conf_in_sync(rtr_config)) { RPKI_DEBUG("Got synchronisation with at least one RPKI cache!"); + RPKI_DEBUG("Forcing revalidation."); + rtr_is_starting = 0; + revalidate_all_routes(); } else { RPKI_DEBUG( "Timeout expired! Proceeding without RPKI validation data."); + rtr_is_starting = 0; } XFREE(MTYPE_BGP_RPKI_CACHE_GROUP, groups); @@ -382,6 +566,7 @@ static int start(void) static void stop(void) { + rtr_is_stopping = 1; if (rtr_is_running) { rtr_mgr_stop(rtr_config); rtr_mgr_free(rtr_config); @@ -479,13 +664,11 @@ static int rpki_validate_prefix(struct peer *peer, struct attr *attr, ip_addr_prefix.u.addr4.addr = ntohl(prefix->u.prefix4.s_addr); break; -#ifdef HAVE_IPV6 case AF_INET6: ip_addr_prefix.ver = LRTR_IPV6; ipv6_addr_to_host_byte_order(prefix->u.prefix6.s6_addr32, ip_addr_prefix.u.addr6.addr); break; -#endif /* HAVE_IPV6 */ default: return 0; @@ -858,7 +1041,7 @@ DEFPY (rpki_cache, "Preference of the cache server\n" "Preference value\n") { - int return_value = SUCCESS; + int return_value; // use ssh connection if (ssh_uname) { @@ -867,6 +1050,7 @@ DEFPY (rpki_cache, add_ssh_cache(cache, sshport, ssh_uname, ssh_privkey, ssh_pubkey, server_pubkey, preference); #else + return_value = SUCCESS; vty_out(vty, "ssh sockets are not supported. " "Please recompile rtrlib and frr with ssh support. " diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c index 613b924d0d..94e2d83cfe 100644 --- a/bgpd/bgp_table.c +++ b/bgpd/bgp_table.c @@ -114,3 +114,65 @@ struct bgp_table *bgp_table_init(struct bgp *bgp, afi_t afi, safi_t safi) return rt; } + +static struct bgp_node * +bgp_route_next_until_maxlen(struct bgp_node *node, const struct bgp_node *limit, + const uint8_t maxlen) +{ + if (node->l_left && node->p.prefixlen < maxlen + && node->l_left->p.prefixlen <= maxlen) { + return bgp_node_from_rnode(node->l_left); + } + if (node->l_right && node->p.prefixlen < maxlen + && node->l_right->p.prefixlen <= maxlen) { + return bgp_node_from_rnode(node->l_right); + } + + while (node->parent && node != limit) { + if (bgp_node_from_rnode(node->parent->l_left) == node + && node->parent->l_right) { + return bgp_node_from_rnode(node->parent->l_right); + } + node = bgp_node_from_rnode(node->parent); + } + return NULL; +} + +void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p, + uint8_t maxlen, struct list *matches) +{ + struct bgp_node *node = bgp_node_from_rnode(table->route_table->top); + struct bgp_node *matched = NULL; + + if (node == NULL) + return; + + while (node && node->p.prefixlen <= p->prefixlen + && prefix_match(&node->p, p)) { + if (node->info && node->p.prefixlen == p->prefixlen) { + matched = node; + break; + } + node = bgp_node_from_rnode(node->link[prefix_bit( + &p->u.prefix, node->p.prefixlen)]); + } + + if ((matched == NULL && node->p.prefixlen > maxlen) || !node->parent) + return; + else if (matched == NULL) + matched = node = bgp_node_from_rnode(node->parent); + + if (matched->info) { + bgp_lock_node(matched); + listnode_add(matches, matched); + } + + while ((node = bgp_route_next_until_maxlen(node, matched, maxlen))) { + if (prefix_match(p, &node->p)) { + if (node->info) { + bgp_lock_node(node); + listnode_add(matches, node); + } + } + } +} diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index 388c247227..60c2cbd4a4 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -24,6 +24,7 @@ #include "mpls.h" #include "table.h" #include "queue.h" +#include "linklist.h" struct bgp_table { /* table belongs to this instance */ @@ -309,4 +310,7 @@ static inline uint64_t bgp_table_version(struct bgp_table *table) return table->version; } +void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p, + uint8_t maxlen, struct list *matches); + #endif /* _QUAGGA_BGP_TABLE_H */ diff --git a/bgpd/bgp_vnc_types.h b/bgpd/bgp_vnc_types.h index 70f5646e94..f4202ff75e 100644 --- a/bgpd/bgp_vnc_types.h +++ b/bgpd/bgp_vnc_types.h @@ -25,16 +25,5 @@ typedef enum { BGP_VNC_SUBTLV_TYPE_RFPOPTION = 2, /* deprecated */ } bgp_vnc_subtlv_types; -/* - * VNC Attribute subtlvs - */ -struct bgp_vnc_subtlv_lifetime { - uint32_t lifetime; -}; - -struct bgp_vnc_subtlv_unaddr { - struct prefix un_address; /* IPv4 or IPv6; pfx length ignored */ -}; - #endif /* ENABLE_BGP_VNC */ #endif /* _QUAGGA_BGP_VNC_TYPES_H */ diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 86f3f97c49..e9d9a846af 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -928,6 +928,14 @@ DEFUN_NOSH (router_bgp, return CMD_WARNING_CONFIG_FAILED; } + /* + * If we just instantiated the default instance, complete + * any pending VRF-VPN leaking that was configured via + * earlier "router bgp X vrf FOO" blocks. + */ + if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) + vpn_leak_postchange_all(); + /* Pending: handle when user tries to change a view to vrf n vv. */ } @@ -3372,8 +3380,6 @@ DEFUN (neighbor_set_peer_group, struct peer *peer; struct peer_group *group; - peer = NULL; - ret = str2sockunion(argv[idx_peer]->arg, &su); if (ret < 0) { peer = peer_lookup_by_conf_if(bgp, argv[idx_peer]->arg); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index df3f9ddd6f..714f6791c1 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1190,7 +1190,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, mpls_label_t label; int nh_othervrf = 0; char buf_prefix[PREFIX_STRLEN]; /* filled in if we are debugging */ - bool is_evpn = false; + bool is_evpn; int nh_updated; /* Don't try to install if we're not connected to Zebra or Zebra doesn't diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 283949ab2a..e5b269eb70 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -888,129 +888,6 @@ static bool peergroup_filter_check(struct peer *peer, afi_t afi, safi_t safi, } } -/* Reset all address family specific configuration. */ -static void peer_af_flag_reset(struct peer *peer, afi_t afi, safi_t safi) -{ - int i; - struct bgp_filter *filter; - char orf_name[BUFSIZ]; - - filter = &peer->filter[afi][safi]; - - /* Clear neighbor filter and route-map */ - for (i = FILTER_IN; i < FILTER_MAX; i++) { - if (filter->dlist[i].name) { - XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[i].name); - filter->dlist[i].name = NULL; - } - if (filter->plist[i].name) { - XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[i].name); - filter->plist[i].name = NULL; - } - if (filter->aslist[i].name) { - XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[i].name); - filter->aslist[i].name = NULL; - } - } - for (i = RMAP_IN; i < RMAP_MAX; i++) { - if (filter->map[i].name) { - XFREE(MTYPE_BGP_FILTER_NAME, filter->map[i].name); - filter->map[i].name = NULL; - } - } - - /* Clear unsuppress map. */ - if (filter->usmap.name) - XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); - filter->usmap.name = NULL; - filter->usmap.map = NULL; - - /* Clear neighbor's all address family flags. */ - peer->af_flags[afi][safi] = 0; - - /* Clear neighbor's all address family sflags. */ - peer->af_sflags[afi][safi] = 0; - - /* Clear neighbor's all address family capabilities. */ - peer->af_cap[afi][safi] = 0; - - /* Clear ORF info */ - peer->orf_plist[afi][safi] = NULL; - sprintf(orf_name, "%s.%d.%d", peer->host, afi, safi); - prefix_bgp_orf_remove_all(afi, orf_name); - - /* Set default neighbor send-community. */ - if (!bgp_option_check(BGP_OPT_CONFIG_CISCO)) { - SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY); - SET_FLAG(peer->af_flags[afi][safi], - PEER_FLAG_SEND_EXT_COMMUNITY); - SET_FLAG(peer->af_flags[afi][safi], - PEER_FLAG_SEND_LARGE_COMMUNITY); - - SET_FLAG(peer->af_flags_invert[afi][safi], - PEER_FLAG_SEND_COMMUNITY); - SET_FLAG(peer->af_flags_invert[afi][safi], - PEER_FLAG_SEND_EXT_COMMUNITY); - SET_FLAG(peer->af_flags_invert[afi][safi], - PEER_FLAG_SEND_LARGE_COMMUNITY); - } - - /* Clear neighbor default_originate_rmap */ - if (peer->default_rmap[afi][safi].name) - XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); - peer->default_rmap[afi][safi].name = NULL; - peer->default_rmap[afi][safi].map = NULL; - - /* Clear neighbor maximum-prefix */ - peer->pmax[afi][safi] = 0; - peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT; -} - -/* peer global config reset */ -static void peer_global_config_reset(struct peer *peer) -{ - int saved_flags = 0; - - peer->change_local_as = 0; - peer->ttl = (peer_sort(peer) == BGP_PEER_IBGP ? MAXTTL : 1); - if (peer->update_source) { - sockunion_free(peer->update_source); - peer->update_source = NULL; - } - if (peer->update_if) { - XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if); - peer->update_if = NULL; - } - - if (peer_sort(peer) == BGP_PEER_IBGP) - peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV; - else - peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; - - /* These are per-peer specific flags and so we must preserve them */ - saved_flags |= CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY); - saved_flags |= CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN); - peer->flags = 0; - SET_FLAG(peer->flags, saved_flags); - - peer->holdtime = 0; - peer->keepalive = 0; - peer->connect = 0; - peer->v_connect = BGP_DEFAULT_CONNECT_RETRY; - - /* Reset some other configs back to defaults. */ - peer->v_start = BGP_INIT_START_TIMER; - peer->password = NULL; - peer->local_id = peer->bgp->router_id; - peer->v_holdtime = peer->bgp->default_holdtime; - peer->v_keepalive = peer->bgp->default_keepalive; - - bfd_info_free(&(peer->bfd_info)); - - /* Set back the CONFIG_NODE flag. */ - SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); -} - /* Check peer's AS number and determines if this peer is IBGP or EBGP */ static inline bgp_peer_sort_t peer_calc_sort(struct peer *peer) { @@ -1026,9 +903,11 @@ static inline bgp_peer_sort_t peer_calc_sort(struct peer *peer) else if (peer->as_type == AS_EXTERNAL) return BGP_PEER_EBGP; - else if (peer->as_type == AS_SPECIFIED && peer->as) + else if (peer->as_type == AS_SPECIFIED && peer->as) { + assert(bgp); return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP); + } else { struct peer *peer1; @@ -2819,61 +2698,6 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer, return 0; } -int peer_group_unbind(struct bgp *bgp, struct peer *peer, - struct peer_group *group) -{ - struct peer *other; - afi_t afi; - safi_t safi; - - if (group != peer->group) - return BGP_ERR_PEER_GROUP_MISMATCH; - - FOREACH_AFI_SAFI (afi, safi) { - if (peer->afc[afi][safi]) { - peer->afc[afi][safi] = 0; - peer_af_flag_reset(peer, afi, safi); - - if (peer_af_delete(peer, afi, safi) != 0) { - zlog_err( - "couldn't delete af structure for peer %s", - peer->host); - } - } - } - - assert(listnode_lookup(group->peer, peer)); - peer_unlock(peer); /* peer group list reference */ - listnode_delete(group->peer, peer); - peer->group = NULL; - other = peer->doppelganger; - - if (group->conf->as) { - peer_delete(peer); - if (other && other->status != Deleted) { - if (other->group) { - peer_unlock(other); - listnode_delete(group->peer, other); - } - other->group = NULL; - peer_delete(other); - } - return 0; - } - - bgp_bfd_deregister_peer(peer); - peer_global_config_reset(peer); - - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) { - peer->last_reset = PEER_DOWN_RMAP_UNBIND; - bgp_notify_send(peer, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_CONFIG_CHANGE); - } else - bgp_session_reset(peer); - - return 0; -} - static int bgp_startup_timer_expire(struct thread *thread) { struct bgp *bgp; @@ -3823,9 +3647,6 @@ struct peer_flag_action { /* Action when the flag is changed. */ enum peer_change_type type; - - /* Peer down cause */ - uint8_t peer_down; }; static const struct peer_flag_action peer_flag_action_list[] = { @@ -7647,10 +7468,6 @@ int bgp_config_write(struct vty *vty) vty_out(vty, " bgp default subgroup-pkt-queue-max %u\n", bgp->default_subgroup_pkt_queue_max); - /* BGP default autoshutdown neighbors */ - if (bgp->autoshutdown) - vty_out(vty, " bgp default shutdown\n"); - /* BGP client-to-client reflection. */ if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT)) vty_out(vty, " no bgp client-to-client reflection\n"); @@ -7804,6 +7621,16 @@ int bgp_config_write(struct vty *vty) /* listen range and limit for dynamic BGP neighbors */ bgp_config_write_listen(vty, bgp); + /* + * BGP default autoshutdown neighbors + * + * This must be placed after any peer and peer-group + * configuration, to avoid setting all peers to shutdown after + * a daemon restart, which is undesired behavior. (see #2286) + */ + if (bgp->autoshutdown) + vty_out(vty, " bgp default shutdown\n"); + /* No auto-summary */ if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) vty_out(vty, " no auto-summary\n"); @@ -7912,8 +7739,6 @@ static void bgp_if_finish(struct bgp *bgp) } } -extern void bgp_snmp_init(void); - static void bgp_viewvrf_autocomplete(vector comps, struct cmd_token *token) { struct vrf *vrf = NULL; diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 1fbc0a0db9..06eb86da95 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -590,13 +590,7 @@ struct bgp_nexthop { #define BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE 1 -/* BGP router distinguisher value. */ -#define BGP_RD_SIZE 8 - -struct bgp_rd { - uint8_t val[BGP_RD_SIZE]; -}; - +/* Route map direction */ #define RMAP_IN 0 #define RMAP_OUT 1 #define RMAP_MAX 2 @@ -1590,7 +1584,6 @@ extern int peer_afc_set(struct peer *, afi_t, safi_t, int); extern int peer_group_bind(struct bgp *, union sockunion *, struct peer *, struct peer_group *, as_t *); -extern int peer_group_unbind(struct bgp *, struct peer *, struct peer_group *); extern int peer_flag_set(struct peer *, uint32_t); extern int peer_flag_unset(struct peer *, uint32_t); diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c index 177244d277..a1f1169a7a 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -2336,7 +2336,7 @@ int rfapi_reopen(struct rfapi_descriptor *rfd, struct bgp *bgp) h = bgp->rfapi; - assert(!CHECK_FLAG(h->flags, RFAPI_INCALLBACK)); + assert(h != NULL && !CHECK_FLAG(h->flags, RFAPI_INCALLBACK)); if (CHECK_FLAG(rfd->flags, RFAPI_HD_FLAG_CLOSING_ADMINISTRATIVELY) @@ -3197,8 +3197,8 @@ DEFUN (debug_rfapi_register_vn_un_l2o, memset(optary, 0, sizeof(optary)); optary[opt_next].v.l2addr.logical_net_id = strtoul(argv[14]->arg, NULL, 10); - if ((rc = rfapiStr2EthAddr(argv[12]->arg, - &optary[opt_next].v.l2addr.macaddr))) { + if (rfapiStr2EthAddr(argv[12]->arg, + &optary[opt_next].v.l2addr.macaddr)) { vty_out(vty, "Bad mac address \"%s\"\n", argv[12]->arg); return CMD_WARNING_CONFIG_FAILED; } diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c index c71f59563f..60534fece0 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -2099,7 +2099,6 @@ rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd, nhp->vn_options = NULL; XFREE(MTYPE_RFAPI_NEXTHOP, nhp); - nhp = NULL; } } diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c index ae31c3fe9e..d4dd34d1dd 100644 --- a/bgpd/rfapi/vnc_export_bgp.c +++ b/bgpd/rfapi/vnc_export_bgp.c @@ -402,7 +402,6 @@ void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct route_node *rn, static void vnc_direct_bgp_vpn_enable_ce(struct bgp *bgp, afi_t afi) { - struct rfapi_cfg *hc; struct route_node *rn; struct bgp_info *ri; @@ -411,7 +410,7 @@ static void vnc_direct_bgp_vpn_enable_ce(struct bgp *bgp, afi_t afi) if (!bgp) return; - if (!(hc = bgp->rfapi_cfg)) + if (!(bgp->rfapi_cfg)) return; if (!VNC_EXPORT_BGP_CE_ENABLED(bgp->rfapi_cfg)) { diff --git a/bgpd/rfapi/vnc_import_bgp.c b/bgpd/rfapi/vnc_import_bgp.c index 4bc5535e1b..156572b57f 100644 --- a/bgpd/rfapi/vnc_import_bgp.c +++ b/bgpd/rfapi/vnc_import_bgp.c @@ -557,7 +557,6 @@ static void vnc_import_bgp_add_route_mode_resolve_nve( struct bgp_info *info) /* unicast info */ { afi_t afi = family2afi(prefix->family); - struct rfapi_cfg *hc = NULL; struct prefix pfx_unicast_nexthop = {0}; /* happy valgrind */ @@ -607,7 +606,7 @@ static void vnc_import_bgp_add_route_mode_resolve_nve( return; } - if (!(hc = bgp->rfapi_cfg)) { + if (!(bgp->rfapi_cfg)) { vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", __func__); return; @@ -698,7 +697,7 @@ static void vnc_import_bgp_add_route_mode_plain(struct bgp *bgp, struct peer *peer = info->peer; struct attr *attr = info->attr; struct attr hattr; - struct rfapi_cfg *hc = NULL; + struct rfapi_cfg *hc = bgp->rfapi_cfg; struct attr *iattr = NULL; struct rfapi_ip_addr vnaddr; @@ -723,7 +722,7 @@ static void vnc_import_bgp_add_route_mode_plain(struct bgp *bgp, return; } - if (!(hc = bgp->rfapi_cfg)) { + if (!hc) { vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", __func__); return; @@ -886,7 +885,6 @@ vnc_import_bgp_add_route_mode_nvegroup(struct bgp *bgp, struct prefix *prefix, struct peer *peer = info->peer; struct attr *attr = info->attr; struct attr hattr; - struct rfapi_cfg *hc = NULL; struct attr *iattr = NULL; struct rfapi_ip_addr vnaddr; @@ -911,7 +909,7 @@ vnc_import_bgp_add_route_mode_nvegroup(struct bgp *bgp, struct prefix *prefix, return; } - if (!(hc = bgp->rfapi_cfg)) { + if (!(bgp->rfapi_cfg)) { vnc_zlog_debug_verbose("%s: bgp->rfapi_cfg is NULL, skipping", __func__); return; @@ -2904,6 +2902,8 @@ void vnc_import_bgp_redist_disable(struct bgp *bgp, afi_t afi) struct rfapi_descriptor *rfd; vncHDBgpDirect.peer = bi->peer; + assert(bi->extra); + rfd = bi->extra->vnc.export .rfapi_handle; diff --git a/configure.ac b/configure.ac index 3ec29cc38f..8846fcdf71 100755 --- a/configure.ac +++ b/configure.ac @@ -226,7 +226,14 @@ AC_ARG_ENABLE([memory-sanitizer], AS_HELP_STRING([--enable-memory-sanitizer], \ ]) dnl if the user has specified any CFLAGS, override our settings -if test "x${enable_dev_build}" = "xyes"; then +if test "x${enable_gcov}" = "xyes"; then + if test "z$orig_cflags" = "z"; then + AC_C_FLAG([-coverage]) + AC_C_FLAG([-O0]) + fi + + LDFLAGS="${LDFLAGS} -lgcov" +elif test "x${enable_dev_build}" = "xyes"; then AC_DEFINE(DEV_BUILD,,Build for development) if test "z$orig_cflags" = "z"; then AC_C_FLAG([-g3]) @@ -441,6 +448,8 @@ AC_ARG_ENABLE([clippy-only], AS_HELP_STRING([--enable-clippy-only], [Only build clippy])) AC_ARG_ENABLE([numeric_version], AS_HELP_STRING([--enable-numeric-version], [Only numeric digits allowed in version (for Alpine)])) +AC_ARG_ENABLE([gcov], + AS_HELP_STRING([--enable-gcov], [Add code coverage information])) AS_IF([test "${enable_clippy_only}" != "yes"], [ AC_CHECK_HEADERS(json-c/json.h) @@ -692,6 +701,11 @@ AC_DEFINE_UNQUOTED(MULTIPATH_NUM, $MPATH_NUM, Maximum number of paths for a rout AC_DEFINE_UNQUOTED(VTYSH_PAGER, "$VTYSH_PAGER", [What pager to use]) +dnl -------------------- +dnl Enable code coverage +dnl -------------------- +AM_CONDITIONAL([HAVE_GCOV],[test '!' "$enable_gcov" = no]) + dnl ------------------------------------ dnl Alpine only accepts numeric versions dnl ------------------------------------ diff --git a/doc/Makefile.am b/doc/Makefile.am index 1f27e4a8e7..62cb3c2edb 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -183,6 +183,7 @@ EXTRA_DIST = frr-sphinx.mk \ developer/ldpd-basic-test-setup.md \ developer/library.rst \ developer/Makefile.in \ + developer/maintainer-release-build.rst \ developer/memtypes.rst \ developer/modules.rst \ developer/next-hop-tracking.rst \ diff --git a/doc/developer/maintainer-release-build.rst b/doc/developer/maintainer-release-build.rst new file mode 100644 index 0000000000..907bd14ee6 --- /dev/null +++ b/doc/developer/maintainer-release-build.rst @@ -0,0 +1,89 @@ +Release Build Procedure for FRR maintainers +========================================================= + +1. Rename branch (if needed) + +.. code-block:: shell + + git clone git@github.com:FRRouting/frr.git + cd frr + git checkout dev/5.0 + git push origin :refs/heads/dev/5.0 + git push origin dev/5.0:refs/heads/stable/5.0 + +2. Checkout the new stable branch: + +.. code-block:: shell + + git checkout stable/5.0 + +3. Update Changelog for RedHat Package: + + Edit :file:`redhat/frr.spec.in` and look for the ``%changelog`` section: + + - Change last (top of list) entry from ``%{version}`` to previous fixed + version number, i.e.:: + + * Tue Nov 7 2017 Martin Winter <mwinter@opensourcerouting.org> - %{version} + + to:: + + * Tue Nov 7 2017 Martin Winter <mwinter@opensourcerouting.org> - 3.0.2 + + - Add new entry to the top of the list with ``%{version}`` tag and changelog + for version. + Make sure to watch the format, i.e. the day is always 2 characters, with + the 1st character being a space if the day is one digit. + +4. Update Changelog for Debian Packages: + + Edit :file:`debianpkg/changelog.in`: + + - Change last (top of list) entry from ``@VERSION@`` to previous fixed + version number, i.e.:: + + frr (@VERSION@) RELEASED; urgency=medium + + to:: + + frr (3.0.2) RELEASED; urgency=medium + + - Add a new entry to the top of the list with a ``@VERSION@`` tag and + changelog for version. + +5. Change main version number: + + - Edit :file:`configure.ac` and change version in the ``AC_INIT`` command + - Create a new entry with the version as ``%{version}`` tag + +6. Test building at least a Red Hat and Ubuntu package (or create a PR to have + the CI system test them) + +7. Commit the changes, adding the changelog to the commit message + +8. Create a git tag for the version: + + .. code-block:: shell + + git tag -a frr-5.0 -m "FRRouting Release 5.0" + +9. Push the commit and tag(s) and watch for errors on CI: + + .. code-block:: shell + + git push + git push --tags + +10. Kick off the Release build plan on the CI system for the correct release + +11. Send a Release Announcement with changes to + ``announce@lists.frrouting.org`` + +12. Kick off the Snapcraft build plan for the correct release + +13. After CI plans succeed, release on GitHub by going to + https://github.com/FRRouting/frr/releases and selecting "Draft a new + release". + +14. Deploy Snapcraft release (after CI system finishes the tests for snapcraft + testplan) diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst index b29769da49..cd03d2733d 100644 --- a/doc/developer/workflow.rst +++ b/doc/developer/workflow.rst @@ -300,6 +300,37 @@ Documentation should be written in reStructuredText. Sphinx extensions may be utilized but pure ReST is preferred where possible. See :ref:`documentation`. +Code Reviews +============ + +Code quality is paramount for any large program. Consequently we require +reviews of all submitted patches by at least one person other than the +submitter before the patch is merged. + +Because of the nature of the software, FRR's maintainer list (i.e. those with +commit permissions) tends to contain employees / members of various +organizations. In order to prevent conflicts of interest, we use an honor +system in which submissions from an individual representing one company should +be merged by someone unaffiliated with that company. + +Guidelines for code review +"""""""""""""""""""""""""" + +- As a rule of thumb, the depth of the review should be proportional to the + scope and / or impact of the patch. + +- Anyone may review a patch. + +- When using GitHub reviews, marking "Approve" on a code review indicates + willingness to merge the PR. + +- For individuals with merge rights, marking "Changes requested" is equivalent + to a NAK. + +- For a PR you marked with "Changes requested", please respond to updates in a + timely manner to avoid impeding the flow of development. + + Coding Practices & Style ======================== diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 0ea93a62e7..579b0b6497 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -1783,8 +1783,8 @@ kernel routing tables. neighbor 10.0.0.3 remote-as 4 neighbor 10.0.0.4 remote-as 5 -.. index:: show ip bgp view NAME -.. clicmd:: show ip bgp view NAME +.. index:: show [ip] bgp view NAME +.. clicmd:: show [ip] bgp view NAME Display the routing table of BGP view ``NAME``. @@ -1864,22 +1864,22 @@ Debugging Show all enabled debugs. -.. index:: [no] debug neighbor-events -.. clicmd:: [no] debug neighbor-events +.. index:: [no] debug bgp neighbor-events +.. clicmd:: [no] debug bgp neighbor-events Enable or disable debugging for neighbor events. This provides general information on BGP events such as peer connection / disconnection, session establishment / teardown, and capability negotiation. -.. index:: [no] debug updates -.. clicmd:: [no] debug updates +.. index:: [no] debug bgp updates +.. clicmd:: [no] debug bgp updates Enable or disable debugging for BGP updates. This provides information on BGP UPDATE messages transmitted and received between local and remote instances. -.. index:: [no] debug keepalives -.. clicmd:: [no] debug keepalives +.. index:: [no] debug bgp keepalives +.. clicmd:: [no] debug bgp keepalives Enable or disable debugging for BGP keepalives. This provides information on BGP KEEPALIVE messages transmitted and received between local and remote @@ -1981,17 +1981,27 @@ Other BGP Commands Displaying BGP Information ========================== +The following four commands display the IPv6 and IPv4 routing tables, depending +on whether or not the ``ip`` keyword is used. +Actually, :clicmd:`show ip bgp` command was used on older `Quagga` routing +daemon project, while :clicmd:`show bgp` command is the new format. The choice +has been done to keep old format with IPv4 routing table, while new format +displays IPv6 routing table. + .. index:: show ip bgp .. clicmd:: show ip bgp .. index:: show ip bgp A.B.C.D .. clicmd:: show ip bgp A.B.C.D -.. index:: show ip bgp X:X::X:X -.. clicmd:: show ip bgp X:X::X:X +.. index:: show bgp +.. clicmd:: show bgp + +.. index:: show bgp X:X::X:X +.. clicmd:: show bgp X:X::X:X These commands display BGP routes. When no route is specified, the default - is to display all IPv4 BGP routes. + is to display all BGP routes. :: @@ -2004,31 +2014,56 @@ Displaying BGP Information Total number of prefixes 1 -.. index:: show ip bgp regexp LINE -.. clicmd:: show ip bgp regexp LINE +Some other commands provide additional options for filtering the output. + +.. index:: show [ip] bgp regexp LINE +.. clicmd:: show [ip] bgp regexp LINE This command displays BGP routes using AS path regular expression (:ref:`bgp-regular-expressions`). -.. index:: show bgp <ipv4|ipv6> summary -.. clicmd:: show bgp <ipv4|ipv6> summary +.. index:: show [ip] bgp summary +.. clicmd:: show [ip] bgp summary Show a bgp peer summary for the specified address family. -.. index:: show bgp <ipv4|ipv6> neighbor [PEER] -.. clicmd:: show bgp <ipv4|ipv6> neighbor [PEER] +The old command structure :clicmd:`show ip bgp` may be removed in the future +and should no longer be used. In order to reach the other BGP routing tables +other than the IPv6 routing table given by :clicmd:`show bgp`, the new command +structure is extended with :clicmd:`show bgp [afi] [safi]`. + +.. index:: show bgp [afi] [safi] +.. clicmd:: show bgp [afi] [safi] + +.. index:: show bgp <ipv4|ipv6> <unicast|multicast|vpn|labeled-unicast> +.. clicmd:: show bgp <ipv4|ipv6> <unicast|multicast|vpn|labeled-unicast> - This command shows information on a specific BGP `peer`. + These commands display BGP routes for the specific routing table indicated by + the selected afi and the selected safi. If no afi and no safi value is given, + the command falls back to the default IPv6 routing table -.. index:: show bgp <ipv4|ipv6> dampening dampened-paths -.. clicmd:: show bgp <ipv4|ipv6> dampening dampened-paths +.. index:: show bgp [afi] [safi] summary +.. clicmd:: show bgp [afi] [safi] summary - Display paths suppressed due to dampening. + Show a bgp peer summary for the specified address family, and subsequent + address-family. -.. index:: show bgp <ipv4|ipv6> dampening flap-statistics -.. clicmd:: show bgp <ipv4|ipv6> dampening flap-statistics +.. index:: show bgp [afi] [safi] neighbor [PEER] +.. clicmd:: show bgp [afi] [safi] neighbor [PEER] - Display flap statistics of routes. + This command shows information on a specific BGP peer of the relevant + afi and safi selected. + +.. index:: show bgp [afi] [safi] dampening dampened-paths +.. clicmd:: show bgp [afi] [safi] dampening dampened-paths + + Display paths suppressed due to dampening of the selected afi and safi + selected. + +.. index:: show bgp [afi] [safi] dampening flap-statistics +.. clicmd:: show bgp [afi] [safi] dampening flap-statistics + + Display flap statistics of routes of the selected afi and safi selected. .. _bgp-display-routes-by-community: @@ -2073,11 +2108,11 @@ Displaying Routes by AS Path This commands displays BGP routes that matches a regular expression `line` (:ref:`bgp-regular-expressions`). -.. index:: show ip bgp ipv4 vpn -.. clicmd:: show ip bgp ipv4 vpn +.. index:: show [ip] bgp ipv4 vpn +.. clicmd:: show [ip] bgp ipv4 vpn -.. index:: show ipv6 bgp ipv6 vpn -.. clicmd:: show ipv6 bgp ipv6 vpn +.. index:: show [ip] bgp ipv6 vpn +.. clicmd:: show [ip] bgp ipv6 vpn Print active IPV4 or IPV6 routes advertised via the VPN SAFI. @@ -2448,6 +2483,8 @@ Example of how to set up a 6-Bone connection. .. include:: rpki.rst +.. include:: flowspec.rst + .. [#med-transitivity-rant] For some set of objects to have an order, there *must* be some binary ordering relation that is defined for *every* combination of those objects, and that relation *must* be transitive. I.e.:, if the relation operator is <, and if a < b and b < c then that relation must carry over and it *must* be that a < c for the objects to have an order. The ordering relation may allow for equality, i.e. a < b and b < a may both be true and imply that a and b are equal in the order and not distinguished by it, in which case the set has a partial order. Otherwise, if there is an order, all the objects have a distinct place in the order and the set has a total order) .. [bgp-route-osci-cond] McPherson, D. and Gill, V. and Walton, D., "Border Gateway Protocol (BGP) Persistent Route Oscillation Condition", IETF RFC3345 .. [stable-flexible-ibgp] Flavel, A. and M. Roughan, "Stable and flexible iBGP", ACM SIGCOMM 2009 diff --git a/doc/user/conf.py b/doc/user/conf.py index 3fced11024..28081bca7d 100644 --- a/doc/user/conf.py +++ b/doc/user/conf.py @@ -131,7 +131,8 @@ language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build', 'rpki.rst', 'routeserver.rst', 'ospf_fundamentals.rst'] +exclude_patterns = ['_build', 'rpki.rst', 'routeserver.rst', + 'ospf_fundamentals.rst', 'flowspec.rst'] # The reST default role (used for this markup: `text`) to use for all # documents. diff --git a/doc/user/flowspec.rst b/doc/user/flowspec.rst new file mode 100644 index 0000000000..f6af88cac8 --- /dev/null +++ b/doc/user/flowspec.rst @@ -0,0 +1,351 @@ +.. _flowspec: + +Flowspec +======== + +.. _features-of-the-current-implementation-flowspec: + +Overview +--------- + +Flowspec introduces a new :abbr:`NLRI (Network Layer Reachability Information)` +encoding format that is used to distribute traffic rule flow specifications. +Basically, instead of simply relying on destination IP address for IP prefixes, +the IP prefix is replaced by a n-tuple consisting of a rule. That rule can be a +more or less complex combination of the following: + + +- Network source/destination (can be one or the other, or both). +- Layer 4 information for UDP/TCP: source port, destination port, or any port. +- Layer 4 information for ICMP type and ICMP code. +- Layer 4 information for TCP Flags. +- Layer 3 information: DSCP value, Protocol type, packet length, fragmentation. +- Misc layer 4 TCP flags. + +A combination of the above rules is applied for traffic filtering. This is +encoded as part of specific BGP extended communities and the action can range +from the obvious rerouting (to nexthop or to separate VRF) to shaping, or +discard. + +The following IETF drafts and RFCs have been used to implement FRR Flowspec: + +- :rfc:`5575` +- [Draft-IETF-IDR-Flowspec-redirect-IP]_ + +.. _design-principles-flowspec: + +Design Principles +----------------- + +FRR implements the Flowspec client side, that is to say that BGP is able to +receive Flowspec entries, but is not able to act as manager and send Flowspec +entries. + +Linux provides the following mechanisms to implement policy based routing: + +- Filtering the traffic with ``Netfilter``. + ``Netfilter`` provides a set of tools like ``ipset`` and ``iptables`` that are + powerful enough to be able to filter such Flowspec filter rule. + +- using non standard routing tables via ``iproute2`` (via the ``ip rule`` + command provided by ``iproute2``). + ``iproute2`` is already used by FRR's :ref:`pbr` daemon which provides basic + policy based routing based on IP source and destination criterion. + +Below example is an illustration of what Flowspec will inject in the underlying +system: + +.. code-block:: shell + + # linux shell + ipset create match0x102 hash:net,net counters + ipset add match0x102 32.0.0.0/16,40.0.0.0/16 + iptables -N match0x102 -t mangle + iptables -A match0x102 -t mangle -j MARK --set-mark 102 + iptables -A match0x102 -t mangle -j ACCEPT + iptables -i ntfp3 -t mangle -I PREROUTING -m set --match-set match0x102 + src,dst -g match0x102 + ip rule add fwmark 102 lookup 102 + ip route add 40.0.0.0/16 via 44.0.0.2 table 102 + +For handling an incoming Flowspec entry, the following workflow is applied: + +- Incoming Flowspec entries are handled by *bgpd*, stored in the BGP RIB. +- Flowspec entry is installed according to its complexity. + +It will be installed if one of the following filtering action is seen on the +BGP extended community: either redirect IP, or redirect VRF, in conjunction +with rate option, for redirecting traffic. Or rate option set to 0, for +discarding traffic. + +According to the degree of complexity of the Flowspec entry, it will be +installed in *zebra* RIB. For more information about what is supported in the +FRR implementation as rule, see :ref:`flowspec-known-issues` chapter. Flowspec +entry is split in several parts before being sent to *zebra*. + +- *zebra* daemon receives the policy routing configuration + +Policy Based Routing entities necessary to policy route the traffic in the +underlying system, are received by *zebra*. Two filtering contexts will be +created or appended in ``Netfilter``: ``ipset`` and ``iptable`` context. The +former is used to define an IP filter based on multiple criterium. For +instance, an ipset ``net:net`` is based on two ip addresses, while +``net,port,net`` is based on two ip addresses and one port (for ICMP, UDP, or +TCP). The way the filtering is used (for example, is src port or dst port +used?) is defined by the latter filtering context. ``iptable`` command will +reference the ``ipset`` context and will tell how to filter and what to do. In +our case, a marker will be set to indicate ``iproute2`` where to forward the +traffic to. Sometimes, for dropping action, there is no need to add a marker; +the ``iptable`` will tell to drop all packets matching the ``ipset`` entry. + +Configuration Guide +------------------- + +In order to configure an IPv4 Flowspec engine, use the following configuration. +As of today, it is only possible to configure Flowspec on the default VRF. + +.. code-block:: frr + + router bgp <AS> + neighbor <A.B.C.D> remote-as <remoteAS> + address-family ipv4 flowspec + neighbor <A.B.C.D> activate + exit + exit + +You can see Flowspec entries, by using one of the following show commands: + +.. index:: show bgp ipv4 flowspec [detail | A.B.C.D] +.. clicmd:: show bgp ipv4 flowspec [detail | A.B.C.D] + + +Per-interface configuration +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +One nice feature to use is the ability to apply Flowspec to a specific +interface, instead of applying it to the whole machine. Despite the following +IETF draft [Draft-IETF-IDR-Flowspec-Interface-Set]_ is not implemented, it is +possible to manually limit Flowspec application to some incoming interfaces. +Actually, not using it can result to some unexpected behaviour like accounting +twice the traffic, or slow down the traffic (filtering costs). To limit +Flowspec to one specific interface, use the following command, under +`flowspec address-family` node. + +.. index:: [no] local-install <IFNAME | any> +.. clicmd:: [no] local-install <IFNAME | any> + +By default, Flowspec is activated on all interfaces. Installing it to a named +interface will result in allowing only this interface. Conversely, enabling any +interface will flush all previously configured interfaces. + +VRF redirection +^^^^^^^^^^^^^^^ + +Another nice feature to configure is the ability to redirect traffic to a +separate VRF. This feature does not go against the ability to configure +Flowspec only on default VRF. Actually, when you receive incoming BGP flowspec +entries on that default VRF, you can redirect traffic to an other VRF. + +As a reminder, BGP flowspec entries have a BGP extended community that contains +a Route Target. Finding out a local VRF based on Route Target consists in the +following: + +- A configuration of each VRF must be done, with its Route Target set + Each VRF is being configured within a BGP VRF instance with its own Route + Target list. Route Target accepted format matches the following: + ``A.B.C.D:U16``, or ``U16:U32``, ``U32:U16``. + +- The first VRF with the matching Route Target will be selected to route traffic + to. Use the following command under ipv4 unicast address-family node + +.. index:: [no] rt redirect import RTLIST... +.. clicmd:: [no] rt redirect import RTLIST... + +In order to illustrate, if the Route Target configured in the Flowspec entry is +``E.F.G.H:II``, then a BGP VRF instance with the same Route Target will be set +set. That VRF will then be selected. The below full configuration example +depicts how Route Targets are configured and how VRFs and cross VRF +configuration is done. Note that the VRF are mapped on Linux Network +Namespaces. For data traffic to cross VRF boundaries, virtual ethernet +interfaces are created with private IP adressing scheme. + +.. code-block:: frr + + router bgp <ASx> + neighbor <A.B.C.D> remote-as <ASz> + address-family ipv4 flowspec + neighbor A.B.C.D activate + exit + exit + router bgp <ASy> vrf vrf2 + address-family ipv4 unicast + rt redirect import <E.F.G.H:II> + exit + exit + +Flowspec monitoring & troubleshooting +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can monitor policy-routing objects by using one of the following commands. +Those command rely on the filtering contexts configured from BGP, and get the +statistics information retrieved from the underlying system. In other words, +those statistics are retrieved from ``Netfilter``. + +.. index:: show pbr ipset IPSETNAME | iptable +.. clicmd:: show pbr ipset IPSETNAME | iptable + +``IPSETNAME`` is the policy routing object name created by ``ipset``. About +rule contexts, it is possible to know which rule has been configured to +policy-route some specific traffic. The :clicmd:`show pbr iptable` command +displays for forwarded traffic, which table is used. Then it is easy to use +that table identifier to dump the routing table that the forwarded traffic will +match. + +.. code-block:: frr + +.. index:: show ip route table TABLEID +.. clicmd:: show ip route table TABLEID + + ``TABLEID`` is the table number identifier referencing the non standard + routing table used in this example. + +.. index:: [no] debug bgp flowspec +.. clicmd:: [no] debug bgp flowspec + + You can troubleshoot Flowspec, or BGP policy based routing. For instance, if + you encounter some issues when decoding a Flowspec entry, you should enable + :clicmd:`debug bgp flowspec`. + +.. index:: [no] debug bgp pbr [error] +.. clicmd:: [no] debug bgp pbr [error] + + If you fail to apply the flowspec entry into *zebra*, there should be some + relationship with policy routing mechanism. Here, + :clicmd:`debug bgp pbr error` could help. + + To get information about policy routing contexts created/removed, only use + :clicmd:`debug bgp pbr` command. + +Ensuring that a Flowspec entry has been correctly installed and that incoming +traffic is policy-routed correctly can be checked as demonstrated below. First +of all, you must check whether the Flowspec entry has been installed or not. + +.. code-block:: frr + + CLI# show bgp ipv4 flowspec 5.5.5.2/32 + BGP flowspec entry: (flags 0x418) + Destination Address 5.5.5.2/32 + IP Protocol = 17 + Destination Port >= 50 , <= 90 + FS:redirect VRF RT:255.255.255.255:255 + received for 18:41:37 + installed in PBR (match0x271ce00) + +This means that the Flowspec entry has been installed in an ``iptable`` named +``match0x271ce00``. Once you have confirmation it is installed, you can check +whether you find the associate entry by executing following command. You can +also check whether incoming traffic has been matched by looking at counter +line. + +.. code-block:: frr + + CLI# show pbr ipset match0x271ce00 + IPset match0x271ce00 type net,port + to 5.5.5.0/24:proto 6:80-120 (8) + pkts 1000, bytes 1000000 + to 5.5.5.2:proto 17:50-90 (5) + pkts 1692918, bytes 157441374 + +As you can see, the entry is present. note that an ``iptable`` entry can be +used to host several Flowspec entries. In order to know where the matching +traffic is redirected to, you have to look at the policy routing rules. The +policy-routing is done by forwarding traffic to a routing table number. That +routing table number is reached by using a ``iptable``. The relationship +between the routing table number and the incoming traffic is a ``MARKER`` that +is set by the IPtable referencing the IPSet. In Flowspec case, ``iptable`` +referencing the ``ipset`` context have the same name. So it is easy to know +which routing table is used by issuing following command: + +.. code-block:: frr + + CLI# show pbr iptable + IPtable match0x271ce00 action redirect (5) + pkts 1700000, bytes 158000000 + table 257, fwmark 257 + ... + +As you can see, by using following Linux commands, the MARKER ``0x101`` is +present in both ``iptable`` and ``ip rule`` contexts. + +.. code-block:: shell + + # iptables -t mangle --list match0x271ce00 -v + Chain match0x271ce00 (1 references) + pkts bytes target prot opt in out source destination + 1700K 158M MARK all -- any any anywhere anywhere + MARK set 0x101 + 1700K 158M ACCEPT all -- any any anywhere anywhere + + # ip rule list + 0:from all lookup local + 0:from all fwmark 0x101 lookup 257 + 32766:from all lookup main + 32767:from all lookup default + +This allows us to see where the traffic is forwarded to. + +.. _flowspec-known-issues: + +Limitations / Known Issues +-------------------------- + +As you can see, Flowspec is rich and can be very complex. As of today, not all +Flowspec rules will be able to be converted into Policy Based Routing actions. + +- The ``Netfilter`` driver is not integrated into FRR yet. Not having this + piece of code prevents from injecting flowspec entries into the underlying + system. + +- There are some limitations around filtering contexts + + If I take example of UDP ports, or TCP ports in Flowspec, the information + can be a range of ports, or a unique value. This case is handled. + However, complexity can be increased, if the flow is a combination of a list + of range of ports and an enumerate of unique values. Here this case is not + handled. Similarly, it is not possible to create a filter for both src port + and dst port. For instance, filter on src port from [1-1000] and dst port = + 80. The same kind of complexity is not possible for packet length, ICMP type, + ICMP code. + +There are some other known issues: + +- The validation procedure depicted in :rfc:`5575` is not available. + + This validation procedure has not been implemented, as this feature was not + used in the existing setups you shared wih us. + +- The filtering action shaper value, if positive, is not used to apply shaping. + + If value is positive, the traffic is redirected to the wished destination, + without any other action configured by Flowspec. + It is recommended to configure Quality of Service if needed, more globally on + a per interface basis. + +- Upon an unexpected crash or other event, *zebra* may not have time to flush + PBR contexts. + + That is to say ``ipset``, ``iptable`` and ``ip rule`` contexts. This is also a + consequence due to the fact that ip rule / ipset / iptables are not discovered + at startup (not able to read appropriate contexts coming from Flowspec). + +Appendix +-------- + +More information with a public presentation that explains the design of Flowspec +inside FRRouting. + +[Presentation]_ + +.. [Draft-IETF-IDR-Flowspec-redirect-IP] <https://tools.ietf.org/id/draft-ietf-idr-flowspec-redirect-ip-02.txt> +.. [Draft-IETF-IDR-Flowspec-Interface-Set] <https://tools.ietf.org/id/draft-ietf-idr-flowspec-interfaceset-03.txt> +.. [Presentation] <https://docs.google.com/presentation/d/1ekQygUAG5yvQ3wWUyrw4Wcag0LgmbW1kV02IWcU4iUg/edit#slide=id.g378f0e1b5e_1_44> diff --git a/doc/user/installation.rst b/doc/user/installation.rst index 26d30f1e10..158e2c8595 100644 --- a/doc/user/installation.rst +++ b/doc/user/installation.rst @@ -205,6 +205,15 @@ options from the list below. hardcoded arrays that FRR builds towards, so we need to know how big to make these arrays at build time. +.. option:: --enable-gcov + + Code coverage reports from gcov require adjustments to the C and LD flags. + With this option, gcov instrumentation is added to the build and coverage + reports are created during execution. The check-coverage make target is + also created to ease report uploading to codecov.io. The upload requires + the COMMIT (git hash) and TOKEN (codecov upload token) environment variables + be set. + You may specify any combination of the above options to the configure script. By default, the executables are placed in :file:`/usr/local/sbin` and the configuration files in :file:`/usr/local/etc`. The :file:`/usr/local/` diff --git a/doc/user/rpki.rst b/doc/user/rpki.rst index 93a8e4396a..38b2b68e98 100644 --- a/doc/user/rpki.rst +++ b/doc/user/rpki.rst @@ -44,6 +44,9 @@ In a nutshell, the current implementation provides the following features - Route maps can be configured to match a specific RPKI validation state. This allows the creation of local policies, which handle BGP routes based on the outcome of the Prefix Origin Validation. +- Updates from the RPKI cache servers are directly applied and path selection + is updated accordingly. (Soft reconfiguration **must** be enabled for this + to work). .. _enabling-rpki: @@ -65,6 +68,32 @@ Enabling RPKI .. _configuring-rpki-rtr-cache-servers: +.. index:: daemons.conf + + When first installing FRR with RPKI support from the pre-packaged binaries. Remember + to append '-M rpki' in the /etc/frr/daemons.conf file to the bgpd_options. + + bgpd_options=" --daemon -A 127.0.0.1 -M rpki" + instead of the default setting + bgpd_options=" --daemon -A 127.0.0.1" + + + Else you will encounter an error when trying to enter RPKI configuration mode. Because + the rpki module is not loaded when the BGP daemon is initialized. + + Examples of the error: + + router(config)# debug rpki + % [BGP] Unknown command: debug rpki + + router(config)# rpki + % [BGP] Unknown command: rpki + + Note that the rpki commands will be available in vtysh when running 'find rpki'. + Even if the RPKI module is NOT loaded. + The RPKI commands will be unavailable if you try running the same command in the + cli specific to the BGP daemon. + Configuring RPKI/RTR Cache Servers ---------------------------------- diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index 180d2d7efd..08606c2128 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -521,6 +521,94 @@ entered within the VRF context the static routes are created in the VRF. show ip table vrf r1-cust1 table 43 +.. _zebra-mpls: + +MPLS Commands +============= + +You can configure static mpls entries in zebra. Basically, handling MPLS +consists of popping, swapping or pushing labels to IP packets. + +MPLS Acronyms +------------- + +:abbr:`LSR (Labeled Switch Router)` + Networking devices handling labels used to forward traffic between and through + them. + +:abbr:`LER (Labeled Edge Router)` + A Labeled edge router is located at the edge of an MPLS network, generally + between an IP network and an MPLS network. + +MPLS Push Action +---------------- + +The push action is generally used for LER devices, which want to encapsulate +all traffic for a wished destination into an MPLS label. This action is stored +in routing entry, and can be configured like a route: + +.. index:: [no] ip route NETWORK MASK GATEWAY|INTERFACE label LABEL +.. clicmd:: [no] ip route NETWORK MASK GATEWAY|INTERFACE label LABEL + + NETWORK ans MASK stand for the IP prefix entry to be added as static + route entry. + GATEWAY is the gateway IP address to reach, in order to reach the prefix. + INTERFACE is the interface behind which the prefix is located. + LABEL is the MPLS label to use to reach the prefix abovementioned. + + You can check that the static entry is stored in the zebra RIB database, by + looking at the presence of the entry. + + :: + + zebra(configure)# ip route 1.1.1.1/32 10.0.1.1 label 777 + zebra# show ip route + Codes: K - kernel route, C - connected, S - static, R - RIP, + O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP, + T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP, + F - PBR, + > - selected route, * - FIB route + + S>* 1.1.1.1/32 [1/0] via 10.0.1.1, r2-eth0, label 777, 00:39:42 + +MPLS Swap and Pop Action +------------------------ + +The swap action is generally used for LSR devices, which swap a packet with a +label, with an other label. The Pop action is used on LER devices, at the +termination of the MPLS traffic; this is used to remove MPLS header. + +.. index:: [no] mpls lsp INCOMING_LABEL GATEWAY OUTGOING_LABEL|explicit-null|implicit-null +.. clicmd:: [no] mpls lsp INCOMING_LABEL GATEWAY OUTGOING_LABEL|explicit-null|implicit-null + + INCOMING_LABEL and OUTGOING_LABEL are MPLS labels with values ranging from 16 + to 1048575. + GATEWAY is the gateway IP address where to send MPLS packet. + The outgoing label can either be a value or have an explicit-null label header. This + specific header can be read by IP devices. The incoming label can also be removed; in + that case the implicit-null keyword is used, and the outgoing packet emitted is an IP + packet without MPLS header. + +You can check that the MPLS actions are stored in the zebra MPLS table, by looking at the +presence of the entry. + +.. index:: show mpls table +.. clicmd:: show mpls table + +:: + + zebra(configure)# mpls lsp 18 10.125.0.2 implicit-null + zebra(configure)# mpls lsp 19 10.125.0.2 20 + zebra(configure)# mpls lsp 21 10.125.0.2 explicit-null + zebra# show mpls table + Inbound Outbound + Label Type Nexthop Label + -------- ------- --------------- -------- + 18 Static 10.125.0.2 implicit-null + 19 Static 10.125.0.2 20 + 21 Static 10.125.0.2 IPv4 Explicit Null + + .. _multicast-rib-commands: Multicast RIB Commands diff --git a/docker/alpine/Dockerfile-coverage b/docker/alpine/Dockerfile-coverage new file mode 100644 index 0000000000..5fdb1179b0 --- /dev/null +++ b/docker/alpine/Dockerfile-coverage @@ -0,0 +1,12 @@ +FROM alpine:3.7 +ARG commit +ARG token +ENV COMMIT=${commit} +ENV TOKEN=${token} +ADD . /src +RUN cd /src && \ + source alpine/APKBUILD.in && \ + apk add --no-cache alpine-sdk $makedepends $checkdepends && \ + ./bootstrap.sh && \ + ./configure --enable-gcov +ENTRYPOINT [ "/bin/sh", "-c", "cd /src && make && make -j 1 check-coverage" ] diff --git a/eigrpd/eigrp_hello.c b/eigrpd/eigrp_hello.c index d9e89357ca..2e55d57c31 100644 --- a/eigrpd/eigrp_hello.c +++ b/eigrpd/eigrp_hello.c @@ -417,7 +417,8 @@ void eigrp_sw_version_initialize(void) if (dash) dash[0] = '\0'; - ret = sscanf(ver_string, "%d.%d", &FRR_MAJOR, &FRR_MINOR); + ret = sscanf(ver_string, "%" SCNu32 ".%" SCNu32, &FRR_MAJOR, + &FRR_MINOR); if (ret != 2) zlog_err("Did not Properly parse %s, please fix VERSION string", VERSION); diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index 129b5aedde..027f30563f 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -725,12 +725,12 @@ static struct stream *eigrp_recv_packet(int fd, struct interface **ifp, zlog_warn("stream_recvmsg failed: %s", safe_strerror(errno)); return NULL; } - if ((unsigned int)ret < sizeof(iph)) /* ret must be > 0 now */ + if ((unsigned int)ret < sizeof(*iph)) /* ret must be > 0 now */ { zlog_warn( "eigrp_recv_packet: discarding runt packet of length %d " "(ip header size is %u)", - ret, (unsigned int)sizeof(iph)); + ret, (unsigned int)sizeof(*iph)); return NULL; } diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index ed0a5407b2..9113505581 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -691,7 +691,8 @@ void embedscope(struct sockaddr_in6 *); void recoverscope(struct sockaddr_in6 *); void addscope(struct sockaddr_in6 *, uint32_t); void clearscope(struct in6_addr *); -struct sockaddr *addr2sa(int af, union ldpd_addr *, uint16_t); +void addr2sa(int af, const union ldpd_addr *, uint16_t, + union sockunion *su); void sa2addr(struct sockaddr *, int *, union ldpd_addr *, in_port_t *); socklen_t sockaddr_len(struct sockaddr *); diff --git a/ldpd/neighbor.c b/ldpd/neighbor.c index 1c3f650dff..78a6131ca4 100644 --- a/ldpd/neighbor.c +++ b/ldpd/neighbor.c @@ -584,8 +584,8 @@ nbr_connect_cb(struct thread *thread) int nbr_establish_connection(struct nbr *nbr) { - struct sockaddr_storage local_sa; - struct sockaddr_storage remote_sa; + union sockunion local_su; + union sockunion remote_su; struct adj *adj; struct nbr_params *nbrp; #ifdef __OpenBSD__ @@ -619,16 +619,14 @@ nbr_establish_connection(struct nbr *nbr) #endif } - memcpy(&local_sa, addr2sa(nbr->af, &nbr->laddr, 0), sizeof(local_sa)); - memcpy(&remote_sa, addr2sa(nbr->af, &nbr->raddr, LDP_PORT), - sizeof(local_sa)); + addr2sa(nbr->af, &nbr->laddr, 0, &local_su); + addr2sa(nbr->af, &nbr->raddr, LDP_PORT, &remote_su); if (nbr->af == AF_INET6 && nbr->raddr_scope) - addscope((struct sockaddr_in6 *)&remote_sa, nbr->raddr_scope); + addscope(&remote_su.sin6, nbr->raddr_scope); - if (bind(nbr->fd, (struct sockaddr *)&local_sa, - sockaddr_len((struct sockaddr *)&local_sa)) == -1) { + if (bind(nbr->fd, &local_su.sa, sockaddr_len(&local_su.sa)) == -1) { log_warn("%s: error while binding socket to %s", __func__, - log_sockaddr((struct sockaddr *)&local_sa)); + log_sockaddr(&local_su.sa)); close(nbr->fd); return (-1); } @@ -646,15 +644,15 @@ nbr_establish_connection(struct nbr *nbr) send_hello(adj->source.type, adj->source.link.ia, adj->source.target); - if (connect(nbr->fd, (struct sockaddr *)&remote_sa, - sockaddr_len((struct sockaddr *)&remote_sa)) == -1) { + if (connect(nbr->fd, &remote_su.sa, sockaddr_len(&remote_su.sa)) + == -1) { if (errno == EINPROGRESS) { thread_add_write(master, nbr_connect_cb, nbr, nbr->fd, &nbr->ev_connect); return (0); } log_warn("%s: error while connecting to %s", __func__, - log_sockaddr((struct sockaddr *)&remote_sa)); + log_sockaddr(&remote_su.sa)); close(nbr->fd); return (-1); } diff --git a/ldpd/packet.c b/ldpd/packet.c index b0f9c5eb14..8ca90841de 100644 --- a/ldpd/packet.c +++ b/ldpd/packet.c @@ -70,7 +70,7 @@ int send_packet(int fd, int af, union ldpd_addr *dst, struct iface_af *ia, void *pkt, size_t len) { - struct sockaddr *sa; + union sockunion su; switch (af) { case AF_INET: @@ -97,10 +97,10 @@ send_packet(int fd, int af, union ldpd_addr *dst, struct iface_af *ia, fatalx("send_packet: unknown af"); } - sa = addr2sa(af, dst, LDP_PORT); - if (sendto(fd, pkt, len, 0, sa, sockaddr_len(sa)) == -1) { + addr2sa(af, dst, LDP_PORT, &su); + if (sendto(fd, pkt, len, 0, &su.sa, sockaddr_len(&su.sa)) == -1) { log_warn("%s: error sending packet to %s", __func__, - log_sockaddr(sa)); + log_sockaddr(&su.sa)); return (-1); } diff --git a/ldpd/pfkey.c b/ldpd/pfkey.c index a1a79dabfd..906737217c 100644 --- a/ldpd/pfkey.c +++ b/ldpd/pfkey.c @@ -64,17 +64,17 @@ pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir, ssize_t n; int len = 0; int iov_cnt; - struct sockaddr_storage ssrc, sdst, smask, dmask; - struct sockaddr *saptr; + struct sockaddr_storage smask, dmask; + union sockunion su_src, su_dst; if (!pid) pid = getpid(); /* we need clean sockaddr... no ports set */ - memset(&ssrc, 0, sizeof(ssrc)); memset(&smask, 0, sizeof(smask)); - if ((saptr = addr2sa(af, src, 0))) - memcpy(&ssrc, saptr, sizeof(ssrc)); + + addr2sa(af, src, 0, &su_src); + switch (af) { case AF_INET: memset(&((struct sockaddr_in *)&smask)->sin_addr, 0xff, 32/8); @@ -86,13 +86,13 @@ pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir, default: return (-1); } - smask.ss_family = ssrc.ss_family; - smask.ss_len = ssrc.ss_len; + smask.ss_family = su_src.sa.sa_family; + smask.ss_len = sockaddr_len(&su_src.sa); - memset(&sdst, 0, sizeof(sdst)); memset(&dmask, 0, sizeof(dmask)); - if ((saptr = addr2sa(af, dst, 0))) - memcpy(&sdst, saptr, sizeof(sdst)); + + addr2sa(af, dst, 0, &su_dst); + switch (af) { case AF_INET: memset(&((struct sockaddr_in *)&dmask)->sin_addr, 0xff, 32/8); @@ -104,8 +104,8 @@ pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir, default: return (-1); } - dmask.ss_family = sdst.ss_family; - dmask.ss_len = sdst.ss_len; + dmask.ss_family = su_dst.sa.sa_family; + dmask.ss_len = sockaddr_len(&su_dst.sa); memset(&smsg, 0, sizeof(smsg)); smsg.sadb_msg_version = PF_KEY_V2; @@ -138,11 +138,13 @@ pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir, memset(&sa_src, 0, sizeof(sa_src)); sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; - sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)) / 8; + sa_src.sadb_address_len = + (sizeof(sa_src) + ROUNDUP(sockaddr_len(&su_src.sa))) / 8; memset(&sa_dst, 0, sizeof(sa_dst)); sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST; - sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)) / 8; + sa_dst.sadb_address_len = + (sizeof(sa_dst) + ROUNDUP(sockaddr_len(&su_dst.sa))) / 8; sa.sadb_sa_auth = aalg; sa.sadb_sa_encrypt = SADB_X_EALG_AES; /* XXX */ @@ -195,8 +197,8 @@ pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir, iov[iov_cnt].iov_base = &sa_dst; iov[iov_cnt].iov_len = sizeof(sa_dst); iov_cnt++; - iov[iov_cnt].iov_base = &sdst; - iov[iov_cnt].iov_len = ROUNDUP(sdst.ss_len); + iov[iov_cnt].iov_base = &su_dst; + iov[iov_cnt].iov_len = ROUNDUP(sockaddr_len(&su_dst.sa)); smsg.sadb_msg_len += sa_dst.sadb_address_len; iov_cnt++; @@ -204,8 +206,8 @@ pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir, iov[iov_cnt].iov_base = &sa_src; iov[iov_cnt].iov_len = sizeof(sa_src); iov_cnt++; - iov[iov_cnt].iov_base = &ssrc; - iov[iov_cnt].iov_len = ROUNDUP(ssrc.ss_len); + iov[iov_cnt].iov_base = &su_src; + iov[iov_cnt].iov_len = ROUNDUP(sockaddr_len(&su_src.sa)); smsg.sadb_msg_len += sa_src.sadb_address_len; iov_cnt++; diff --git a/ldpd/socket.c b/ldpd/socket.c index eaea9973a0..aefa3461a8 100644 --- a/ldpd/socket.c +++ b/ldpd/socket.c @@ -37,7 +37,7 @@ ldp_create_socket(int af, enum socket_type type) { int fd, domain, proto; union ldpd_addr addr; - struct sockaddr_storage local_sa; + union sockunion local_su; #ifdef __OpenBSD__ int opt; #endif @@ -70,14 +70,12 @@ ldp_create_socket(int af, enum socket_type type) case LDP_SOCKET_DISC: /* listen on all addresses */ memset(&addr, 0, sizeof(addr)); - memcpy(&local_sa, addr2sa(af, &addr, LDP_PORT), - sizeof(local_sa)); + addr2sa(af, &addr, LDP_PORT, &local_su); break; case LDP_SOCKET_EDISC: case LDP_SOCKET_SESSION: addr = (ldp_af_conf_get(ldpd_conf, af))->trans_addr; - memcpy(&local_sa, addr2sa(af, &addr, LDP_PORT), - sizeof(local_sa)); + addr2sa(af, &addr, LDP_PORT, &local_su); /* ignore any possible error */ sock_set_bindany(fd, 1); break; @@ -90,8 +88,7 @@ ldp_create_socket(int af, enum socket_type type) close(fd); return (-1); } - if (bind(fd, (struct sockaddr *)&local_sa, - sockaddr_len((struct sockaddr *)&local_sa)) == -1) { + if (bind(fd, &local_su.sa, sockaddr_len(&local_su.sa)) == -1) { save_errno = errno; if (ldpd_privs.change(ZPRIVS_LOWER)) log_warn("%s: could not lower privs", __func__); @@ -307,7 +304,7 @@ sock_set_md5sig(int fd, int af, union ldpd_addr *addr, const char *password) if (fd == -1) return (0); #if HAVE_DECL_TCP_MD5SIG - memcpy(&su, addr2sa(af, addr, 0), sizeof(su)); + addr2sa(af, addr, 0, &su); if (ldpe_privs.change(ZPRIVS_RAISE)) { log_warn("%s: could not raise privs", __func__); diff --git a/ldpd/util.c b/ldpd/util.c index e735263f5f..12f9cb0ccf 100644 --- a/ldpd/util.c +++ b/ldpd/util.c @@ -305,14 +305,13 @@ clearscope(struct in6_addr *in6) } } -struct sockaddr * -addr2sa(int af, union ldpd_addr *addr, uint16_t port) +void +addr2sa(int af, const union ldpd_addr *addr, uint16_t port, union sockunion *su) { - static struct sockaddr_storage ss; - struct sockaddr_in *sa_in = (struct sockaddr_in *)&ss; - struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)&ss; + struct sockaddr_in *sa_in = &su->sin; + struct sockaddr_in6 *sa_in6 = &su->sin6; - memset(&ss, 0, sizeof(ss)); + memset(su, 0, sizeof(*su)); switch (af) { case AF_INET: sa_in->sin_family = AF_INET; @@ -333,8 +332,6 @@ addr2sa(int af, union ldpd_addr *addr, uint16_t port) default: fatalx("addr2sa: unknown af"); } - - return ((struct sockaddr *)&ss); } void diff --git a/lib/hash.c b/lib/hash.c index 37f6cdcc8f..ee5401b236 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -241,21 +241,15 @@ void hash_iterate(struct hash *hash, void (*func)(struct hash_backet *, void *), unsigned int i; struct hash_backet *hb; struct hash_backet *hbnext; - uint32_t count = 0; - for (i = 0; i < hash->size; i++) { + for (i = 0; i < hash->size; i++) for (hb = hash->index[i]; hb; hb = hbnext) { /* get pointer to next hash backet here, in case (*func) * decides to delete hb by calling hash_release */ hbnext = hb->next; (*func)(hb, arg); - count++; - } - if (count == hash->count) - return; - } } void hash_walk(struct hash *hash, int (*func)(struct hash_backet *, void *), @@ -265,7 +259,6 @@ void hash_walk(struct hash *hash, int (*func)(struct hash_backet *, void *), struct hash_backet *hb; struct hash_backet *hbnext; int ret = HASHWALK_CONTINUE; - uint32_t count = 0; for (i = 0; i < hash->size; i++) { for (hb = hash->index[i]; hb; hb = hbnext) { @@ -276,10 +269,7 @@ void hash_walk(struct hash *hash, int (*func)(struct hash_backet *, void *), ret = (*func)(hb, arg); if (ret == HASHWALK_ABORT) return; - count++; } - if (count == hash->count) - return; } } diff --git a/lib/hash.h b/lib/hash.h index c7e670b723..12c214e469 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -232,7 +232,9 @@ extern void *hash_release(struct hash *hash, void *data); * Iterate over the elements in a hash table. * * It is safe to delete items passed to the iteration function from the hash - * table during iteration. + * table during iteration. Please note that adding entries to the hash + * during the walk will cause undefined behavior in that some new entries + * will be walked and some will not. So do not do this. * * hash * hash table to operate on @@ -250,7 +252,9 @@ extern void hash_iterate(struct hash *hash, * Iterate over the elements in a hash table, stopping on condition. * * It is safe to delete items passed to the iteration function from the hash - * table during iteration. + * table during iteration. Please note that adding entries to the hash + * during the walk will cause undefined behavior in that some new entries + * will be walked and some will not. So do not do this. * * hash * hash table to operate on @@ -222,18 +222,6 @@ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id) struct vrf *vrf; struct interface if_tmp; - if (vrf_id == VRF_UNKNOWN) { - struct interface *ifp; - - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { - ifp = if_lookup_by_index(ifindex, vrf->vrf_id); - if (ifp) - return ifp; - } - - return NULL; - } - vrf = vrf_lookup_by_id(vrf_id); if (!vrf) return NULL; diff --git a/lib/netns_linux.c b/lib/netns_linux.c index a3fae8f39f..a80b51fa00 100644 --- a/lib/netns_linux.c +++ b/lib/netns_linux.c @@ -435,10 +435,13 @@ char *ns_netns_pathname(struct vty *vty, const char *name) if (!result) { if (vty) - vty_out(vty, "Invalid pathname: %s\n", + vty_out(vty, "Invalid pathname for %s: %s\n", + pathname, safe_strerror(errno)); else - zlog_warn("Invalid pathname: %s", safe_strerror(errno)); + zlog_warn("Invalid pathname for %s: %s", + pathname, + safe_strerror(errno)); return NULL; } check_base = basename(pathname); diff --git a/lib/nexthop_group.h b/lib/nexthop_group.h index a44f4e3542..473ecb34fc 100644 --- a/lib/nexthop_group.h +++ b/lib/nexthop_group.h @@ -56,6 +56,11 @@ void copy_nexthops(struct nexthop **tnh, struct nexthop *nh, (nhop); \ (nhop) = nexthop_next(nhop) +#define ALL_NEXTHOPS_PTR(head, nhop) \ + (nhop) = ((head)->nexthop); \ + (nhop); \ + (nhop) = nexthop_next(nhop) + struct nexthop_hold { char *nhvrf_name; diff --git a/lib/srcdest_table.c b/lib/srcdest_table.c index a70574cff2..32f8e8ca5b 100644 --- a/lib/srcdest_table.c +++ b/lib/srcdest_table.c @@ -127,7 +127,7 @@ route_table_delegate_t _srcdest_srcnode_delegate = { /* NB: read comments in code for refcounting before using! */ static struct route_node *srcdest_srcnode_get(struct route_node *rn, - struct prefix_ipv6 *src_p) + const struct prefix_ipv6 *src_p) { struct srcdest_rnode *srn; @@ -158,11 +158,12 @@ static struct route_node *srcdest_srcnode_get(struct route_node *rn, route_unlock_node(rn); } - return route_node_get(srn->src_table, (struct prefix *)src_p); + return route_node_get(srn->src_table, (const struct prefix *)src_p); } -static struct route_node *srcdest_srcnode_lookup(struct route_node *rn, - struct prefix_ipv6 *src_p) +static struct route_node *srcdest_srcnode_lookup( + struct route_node *rn, + const struct prefix_ipv6 *src_p) { struct srcdest_rnode *srn; @@ -180,7 +181,7 @@ static struct route_node *srcdest_srcnode_lookup(struct route_node *rn, if (!srn->src_table) return NULL; - return route_node_lookup(srn->src_table, (struct prefix *)src_p); + return route_node_lookup(srn->src_table, (const struct prefix *)src_p); } /* ----- exported functions ----- */ @@ -233,25 +234,25 @@ struct route_node *srcdest_route_next(struct route_node *rn) } struct route_node *srcdest_rnode_get(struct route_table *table, - union prefixptr dst_pu, - struct prefix_ipv6 *src_p) + union prefixconstptr dst_pu, + const struct prefix_ipv6 *src_p) { - struct prefix_ipv6 *dst_p = dst_pu.p6; + const struct prefix_ipv6 *dst_p = dst_pu.p6; struct route_node *rn; - rn = route_node_get(table, (struct prefix *)dst_p); + rn = route_node_get(table, (const struct prefix *)dst_p); return srcdest_srcnode_get(rn, src_p); } struct route_node *srcdest_rnode_lookup(struct route_table *table, - union prefixptr dst_pu, - struct prefix_ipv6 *src_p) + union prefixconstptr dst_pu, + const struct prefix_ipv6 *src_p) { - struct prefix_ipv6 *dst_p = dst_pu.p6; + const struct prefix_ipv6 *dst_p = dst_pu.p6; struct route_node *rn; struct route_node *srn; - rn = route_node_lookup_maynull(table, (struct prefix *)dst_p); + rn = route_node_lookup_maynull(table, (const struct prefix *)dst_p); srn = srcdest_srcnode_lookup(rn, src_p); if (rn != NULL && rn == srn && !rn->info) { @@ -263,8 +264,8 @@ struct route_node *srcdest_rnode_lookup(struct route_table *table, return srn; } -void srcdest_rnode_prefixes(struct route_node *rn, struct prefix **p, - struct prefix **src_p) +void srcdest_rnode_prefixes(struct route_node *rn, const struct prefix **p, + const struct prefix **src_p) { if (rnode_is_srcnode(rn)) { struct route_node *dst_rn = rn->table->info; @@ -282,7 +283,7 @@ void srcdest_rnode_prefixes(struct route_node *rn, struct prefix **p, const char *srcdest_rnode2str(struct route_node *rn, char *str, int size) { - struct prefix *dst_p, *src_p; + const struct prefix *dst_p, *src_p; char dst_buf[PREFIX_STRLEN], src_buf[PREFIX_STRLEN]; srcdest_rnode_prefixes(rn, &dst_p, &src_p); diff --git a/lib/srcdest_table.h b/lib/srcdest_table.h index 669068a79b..5f97f02bac 100644 --- a/lib/srcdest_table.h +++ b/lib/srcdest_table.h @@ -56,13 +56,14 @@ extern route_table_delegate_t _srcdest_srcnode_delegate; extern struct route_table *srcdest_table_init(void); extern struct route_node *srcdest_rnode_get(struct route_table *table, - union prefixptr dst_pu, - struct prefix_ipv6 *src_p); + union prefixconstptr dst_pu, + const struct prefix_ipv6 *src_p); extern struct route_node *srcdest_rnode_lookup(struct route_table *table, - union prefixptr dst_pu, - struct prefix_ipv6 *src_p); -extern void srcdest_rnode_prefixes(struct route_node *rn, struct prefix **p, - struct prefix **src_p); + union prefixconstptr dst_pu, + const struct prefix_ipv6 *src_p); +extern void srcdest_rnode_prefixes(struct route_node *rn, + const struct prefix **p, + const struct prefix **src_p); extern const char *srcdest_rnode2str(struct route_node *rn, char *str, int size); extern struct route_node *srcdest_route_next(struct route_node *rn); @@ -479,6 +479,8 @@ static int vty_command(struct vty *vty, char *buf) const char *protocolname; char *cp = NULL; + assert(vty); + /* * Log non empty command lines */ @@ -496,13 +498,13 @@ static int vty_command(struct vty *vty, char *buf) /* format the base vty info */ snprintf(vty_str, sizeof(vty_str), "vty[??]@%s", vty->address); - if (vty) - for (i = 0; i < vector_active(vtyvec); i++) - if (vty == vector_slot(vtyvec, i)) { - snprintf(vty_str, sizeof(vty_str), - "vty[%d]@%s", i, vty->address); - break; - } + + for (i = 0; i < vector_active(vtyvec); i++) + if (vty == vector_slot(vtyvec, i)) { + snprintf(vty_str, sizeof(vty_str), "vty[%d]@%s", + i, vty->address); + break; + } /* format the prompt */ snprintf(prompt_str, sizeof(prompt_str), cmd_prompt(vty->node), diff --git a/lib/workqueue.c b/lib/workqueue.c index 1af51c06c1..39dd142afb 100644 --- a/lib/workqueue.c +++ b/lib/workqueue.c @@ -245,10 +245,11 @@ int work_queue_run(struct thread *thread) char yielded = 0; wq = THREAD_ARG(thread); - wq->thread = NULL; assert(wq); + wq->thread = NULL; + /* calculate cycle granularity: * list iteration == 1 run * listnode processing == 1 cycle diff --git a/nhrpd/nhrp_event.c b/nhrpd/nhrp_event.c index e7adc971e5..7ca9731765 100644 --- a/nhrpd/nhrp_event.c +++ b/nhrpd/nhrp_event.c @@ -59,7 +59,7 @@ static void evmgr_recv_message(struct event_manager *evmgr, struct zbuf *zb) buf[len] = 0; debugf(NHRP_DEBUG_EVENT, "evmgr: msg: %s", buf); - if (sscanf(buf, "eventid=%d", &eventid) != 1) + if (sscanf(buf, "eventid=%" SCNu32, &eventid) != 1) continue; if (sscanf(buf, "result=%63s", result) != 1) continue; diff --git a/nhrpd/nhrp_packet.c b/nhrpd/nhrp_packet.c index c27ebe1d90..e62ee1ef72 100644 --- a/nhrpd/nhrp_packet.c +++ b/nhrpd/nhrp_packet.c @@ -164,7 +164,7 @@ struct nhrp_cie_header *nhrp_cie_pull(struct zbuf *zb, if (!cie) return NULL; - if (cie->nbma_address_len + cie->nbma_subaddress_len) { + if (cie->nbma_address_len + cie->nbma_subaddress_len > 0) { sockunion_set(nbma, afi2family(htons(hdr->afnum)), zbuf_pulln(zb, cie->nbma_address_len diff --git a/nhrpd/vici.c b/nhrpd/vici.c index 3bb0d8308e..eb3827a12f 100644 --- a/nhrpd/vici.c +++ b/nhrpd/vici.c @@ -306,7 +306,7 @@ static void vici_recv_message(struct vici_conn *vici, struct zbuf *msg) uint32_t msglen; uint8_t msgtype; struct blob name; - struct vici_message_ctx ctx; + struct vici_message_ctx ctx = { .nsections = 0 }; msglen = zbuf_get_be32(msg); msgtype = zbuf_get8(msg); diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c index c799a4b30f..d84fd26ac4 100644 --- a/ospfd/ospf_ase.c +++ b/ospfd/ospf_ase.c @@ -543,7 +543,7 @@ static int ospf_ase_route_match_same(struct route_table *rt, struct ospf_route *newor) { struct route_node *rn; - struct ospf_route * or ; + struct ospf_route *or; struct ospf_path *op; struct ospf_path *newop; struct listnode *n1; @@ -559,6 +559,9 @@ static int ospf_ase_route_match_same(struct route_table *rt, route_unlock_node(rn); or = rn->info; + + assert(or); + if (or->path_type != newor->path_type) return 0; @@ -577,6 +580,8 @@ static int ospf_ase_route_match_same(struct route_table *rt, return 0; } + assert(or->paths); + if (or->paths->count != newor->paths->count) return 0; diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index 820b892176..002c6bba8d 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -91,7 +91,7 @@ struct external_info *ospf_external_info_check(struct ospf *ospf, p.prefix = lsa->data->id; p.prefixlen = ip_masklen(al->mask); - for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { + for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { int redist_on = 0; redist_on = diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 729e508865..502f233036 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -1889,7 +1889,7 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, zlog_debug( "ospf_translated_nssa_refresh(): no Type-7 found for " "Type-5 LSA Id %s", - inet_ntoa(type5->data->id)); + type5 ? inet_ntoa(type5->data->id) : "(null)"); return NULL; } @@ -1899,7 +1899,7 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, zlog_debug( "ospf_translated_nssa_refresh(): No translated Type-5 " "found for Type-7 with Id %s", - inet_ntoa(type7->data->id)); + type7 ? inet_ntoa(type7->data->id) : "(null)"); return NULL; } @@ -1912,7 +1912,7 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, zlog_debug( "ospf_translated_nssa_refresh(): Could not translate " "Type-7 for %s to Type-5", - inet_ntoa(type7->data->id)); + type7 ? inet_ntoa(type7->data->id) : "(null)"); return NULL; } @@ -1921,7 +1921,7 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, zlog_debug( "ospf_translated_nssa_refresh(): Could not install " "translated LSA, Id %s", - inet_ntoa(type7->data->id)); + type7 ? inet_ntoa(type7->data->id) : "(null)"); return NULL; } diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c index 93267156f2..fa7dd04d19 100644 --- a/ospfd/ospf_ri.c +++ b/ospfd/ospf_ri.c @@ -1649,7 +1649,7 @@ DEFUN (pce_domain, if (!ospf_ri_enabled(vty)) return CMD_WARNING_CONFIG_FAILED; - if (sscanf(argv[idx_number]->arg, "%d", &as) != 1) { + if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) { vty_out(vty, "pce_domain: fscanf: %s\n", safe_strerror(errno)); return CMD_WARNING_CONFIG_FAILED; } @@ -1684,7 +1684,7 @@ DEFUN (no_pce_domain, uint32_t as; struct ospf_pce_info *pce = &OspfRI.pce_info; - if (sscanf(argv[idx_number]->arg, "%d", &as) != 1) { + if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) { vty_out(vty, "no_pce_domain: fscanf: %s\n", safe_strerror(errno)); return CMD_WARNING_CONFIG_FAILED; @@ -1718,7 +1718,7 @@ DEFUN (pce_neigbhor, if (!ospf_ri_enabled(vty)) return CMD_WARNING_CONFIG_FAILED; - if (sscanf(argv[idx_number]->arg, "%d", &as) != 1) { + if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) { vty_out(vty, "pce_neighbor: fscanf: %s\n", safe_strerror(errno)); return CMD_WARNING_CONFIG_FAILED; @@ -1754,7 +1754,7 @@ DEFUN (no_pce_neighbor, uint32_t as; struct ospf_pce_info *pce = &OspfRI.pce_info; - if (sscanf(argv[idx_number]->arg, "%d", &as) != 1) { + if (sscanf(argv[idx_number]->arg, "%" SCNu32, &as) != 1) { vty_out(vty, "no_pce_neighbor: fscanf: %s\n", safe_strerror(errno)); return CMD_WARNING_CONFIG_FAILED; diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index ddf9133ed9..fb9770d09a 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -2336,27 +2336,6 @@ DEFUN (no_ospf_timers_lsa_min_arrival, return CMD_SUCCESS; } -#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180708 -CPP_NOTICE("ospf: `timers lsa arrival (0-1000)` deprecated 2017/07/08") -#endif -ALIAS_HIDDEN(ospf_timers_lsa_min_arrival, ospf_timers_lsa_arrival_cmd, - "timers lsa arrival (0-1000)", - "adjust routing timers\n" - "throttling link state advertisement delays\n" - "ospf minimum arrival interval delay\n" - "delay (msec) between accepted lsas\n"); - -#if defined(VERSION_TYPE_DEV) && CONFDATE > 20180708 -CPP_NOTICE("ospf: `no timers lsa arrival (0-1000)` deprecated 2017/07/08") -#endif -ALIAS_HIDDEN(no_ospf_timers_lsa_min_arrival, no_ospf_timers_lsa_arrival_cmd, - "no timers lsa arrival (0-1000)", NO_STR - "adjust routing timers\n" - "throttling link state advertisement delays\n" - "ospf minimum arrival interval delay\n" - "delay (msec) between accepted lsas\n"); - - DEFUN (ospf_neighbor, ospf_neighbor_cmd, "neighbor A.B.C.D [priority (0-255) [poll-interval (1-65535)]]", @@ -4809,16 +4788,19 @@ static void show_ip_ospf_nbr_nbma_detail_sub(struct vty *vty, vty_out(vty, " Poll interval %d\n", nbr_nbma->v_poll); /* Show poll-interval timer. */ - if (use_json) { - long time_store; - time_store = monotime_until(&nbr_nbma->t_poll->u.sands, NULL) - / 1000LL; - json_object_int_add(json_sub, "pollIntervalTimerDueMsec", - time_store); - } else - vty_out(vty, " Poll timer due in %s\n", - ospf_timer_dump(nbr_nbma->t_poll, timebuf, - sizeof(timebuf))); + if (nbr_nbma->t_poll) { + if (use_json) { + long time_store; + time_store = monotime_until(&nbr_nbma->t_poll->u.sands, + NULL) / 1000LL; + json_object_int_add(json_sub, + "pollIntervalTimerDueMsec", + time_store); + } else + vty_out(vty, " Poll timer due in %s\n", + ospf_timer_dump(nbr_nbma->t_poll, timebuf, + sizeof(timebuf))); + } /* Show poll-interval timer thread. */ if (use_json) { @@ -10658,8 +10640,6 @@ void ospf_vty_init(void) install_element(OSPF_NODE, &no_ospf_timers_min_ls_interval_cmd); install_element(OSPF_NODE, &ospf_timers_lsa_min_arrival_cmd); install_element(OSPF_NODE, &no_ospf_timers_lsa_min_arrival_cmd); - install_element(OSPF_NODE, &ospf_timers_lsa_arrival_cmd); - install_element(OSPF_NODE, &no_ospf_timers_lsa_arrival_cmd); /* refresh timer commands */ install_element(OSPF_NODE, &ospf_refresh_timer_cmd); diff --git a/pimd/mtracebis_netlink.c b/pimd/mtracebis_netlink.c index a66da87e1b..b4bf6bada3 100644 --- a/pimd/mtracebis_netlink.c +++ b/pimd/mtracebis_netlink.c @@ -489,7 +489,6 @@ int rtnl_listen(struct rtnl_handle *rtnl, rtnl_filter_t handler, void *jarg) int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler, void *jarg) { - int status; struct sockaddr_nl nladdr; char buf[8192]; struct nlmsghdr *h = (void *)buf; @@ -500,37 +499,43 @@ int rtnl_from_file(FILE *rtnl, rtnl_filter_t handler, void *jarg) nladdr.nl_groups = 0; while (1) { - int err, len; - int l; + int err; + size_t l, rl, arl; - status = fread(&buf, 1, sizeof(*h), rtnl); + rl = sizeof(*h); + arl = fread(&buf, 1, rl, rtnl); - if (status < 0) { - if (errno == EINTR) - continue; - perror("rtnl_from_file: fread"); + if (arl != rl) { + if (arl == 0) + return 0; + + if (ferror(rtnl)) + fprintf(stderr, "%s: header read failed\n", + __func__); + else + fprintf(stderr, "%s: truncated header\n", + __func__); return -1; } - if (status == 0) - return 0; - len = h->nlmsg_len; - l = len - sizeof(*h); + l = h->nlmsg_len > rl ? h->nlmsg_len - rl : 0; - if (l < 0 || len > (int)sizeof(buf)) { - fprintf(stderr, "!!!malformed message: len=%d @%lu\n", - len, ftell(rtnl)); + if (l == 0 || (l + (size_t)NLMSG_HDRLEN) > sizeof(buf)) { + fprintf(stderr, "%s: malformed message: len=%zu @%lu\n", + __func__, (size_t)h->nlmsg_len, ftell(rtnl)); return -1; } - status = fread(NLMSG_DATA(h), 1, NLMSG_ALIGN(l), rtnl); + rl = NLMSG_ALIGN(l); + arl = fread(NLMSG_DATA(h), 1, rl, rtnl); - if (status < 0) { - perror("rtnl_from_file: fread"); - return -1; - } - if (status < l) { - fprintf(stderr, "rtnl-from_file: truncated message\n"); + if (arl != rl) { + if (ferror(rtnl)) + fprintf(stderr, "%s: msg read failed\n", + __func__); + else + fprintf(stderr, "%s: truncated message\n", + __func__); return -1; } diff --git a/pimd/pim_br.c b/pimd/pim_br.c index f297b0591d..6184ea12c4 100644 --- a/pimd/pim_br.c +++ b/pimd/pim_br.c @@ -64,10 +64,6 @@ void pim_br_set_pmbr(struct prefix_sg *sg, struct in_addr br) if (!pim_br) { pim_br = XCALLOC(MTYPE_PIM_BR, sizeof(*pim_br)); - if (!pim_br) { - zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_br)); - return; - } pim_br->sg = *sg; @@ -100,9 +96,4 @@ void pim_br_clear_pmbr(struct prefix_sg *sg) void pim_br_init(void) { pim_br_list = list_new(); - if (!pim_br_list) { - zlog_err("%s: Failure to create pim_br_list", - __PRETTY_FUNCTION__); - return; - } } diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 123c47568c..ae2daf40aa 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -2038,7 +2038,7 @@ static void pim_show_state(struct pim_instance *pim, struct vty *vty, } else { vty_out(vty, "%-9d %-15s %-15s %-7s ", c_oil->installed, src_str, grp_str, - ifp_in->name); + in_ifname); } for (oif_vif_index = 0; oif_vif_index < MAXVIFS; diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c index 5c4d99ad4d..e075ff5ac2 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -75,36 +75,6 @@ void pim_if_terminate(struct pim_instance *pim) return; } -static void *if_list_clean(struct pim_interface *pim_ifp) -{ - struct pim_ifchannel *ch; - - if (pim_ifp->igmp_join_list) - list_delete_and_null(&pim_ifp->igmp_join_list); - - if (pim_ifp->igmp_socket_list) - list_delete_and_null(&pim_ifp->igmp_socket_list); - - if (pim_ifp->pim_neighbor_list) - list_delete_and_null(&pim_ifp->pim_neighbor_list); - - if (pim_ifp->upstream_switch_list) - list_delete_and_null(&pim_ifp->upstream_switch_list); - - if (pim_ifp->sec_addr_list) - list_delete_and_null(&pim_ifp->sec_addr_list); - - while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) { - ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb); - - pim_ifchannel_delete(ch); - } - - XFREE(MTYPE_PIM_INTERFACE, pim_ifp); - - return 0; -} - static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr) { XFREE(MTYPE_PIM_SEC_ADDR, sec_addr); @@ -145,10 +115,6 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) zassert(!ifp->info); pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp)); - if (!pim_ifp) { - zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_ifp)); - return 0; - } pim_ifp->options = 0; pim_ifp->pim = pim_get_pim_instance(ifp->vrf_id); @@ -186,38 +152,18 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim) /* list of struct igmp_sock */ pim_ifp->igmp_socket_list = list_new(); - if (!pim_ifp->igmp_socket_list) { - zlog_err("%s: failure: igmp_socket_list=list_new()", - __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } pim_ifp->igmp_socket_list->del = (void (*)(void *))igmp_sock_free; /* list of struct pim_neighbor */ pim_ifp->pim_neighbor_list = list_new(); - if (!pim_ifp->pim_neighbor_list) { - zlog_err("%s: failure: pim_neighbor_list=list_new()", - __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } pim_ifp->pim_neighbor_list->del = (void (*)(void *))pim_neighbor_free; pim_ifp->upstream_switch_list = list_new(); - if (!pim_ifp->upstream_switch_list) { - zlog_err("%s: failure: upstream_switch_list=list_new()", - __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } pim_ifp->upstream_switch_list->del = (void (*)(void *))pim_jp_agg_group_list_free; pim_ifp->upstream_switch_list->cmp = pim_jp_agg_group_list_cmp; pim_ifp->sec_addr_list = list_new(); - if (!pim_ifp->sec_addr_list) { - zlog_err("%s: failure: secondary addresslist", - __PRETTY_FUNCTION__); - return if_list_clean(pim_ifp); - } pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free; pim_ifp->sec_addr_list->cmp = (int (*)(void *, void *))pim_sec_addr_comp; @@ -404,8 +350,6 @@ static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct prefix *addr) } sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr)); - if (!sec_addr) - return changed; changed = 1; sec_addr->addr = *addr; @@ -1286,20 +1230,6 @@ static struct igmp_join *igmp_join_new(struct interface *ifp, } ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij)); - if (!ij) { - char group_str[INET_ADDRSTRLEN]; - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<grp?>", group_addr, group_str, - sizeof(group_str)); - pim_inet4_dump("<src?>", source_addr, source_str, - sizeof(source_str)); - zlog_err( - "%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s", - __PRETTY_FUNCTION__, sizeof(*ij), group_str, source_str, - ifp->name); - close(join_fd); - return 0; - } ij->sock_fd = join_fd; ij->group_addr = group_addr; @@ -1325,9 +1255,6 @@ ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr, if (!pim_ifp->igmp_join_list) { pim_ifp->igmp_join_list = list_new(); - if (!pim_ifp->igmp_join_list) { - return ferr_cfg_invalid("Insufficient memory"); - } pim_ifp->igmp_join_list->del = (void (*)(void *))igmp_join_free; } diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 6c347a430f..eb3307589e 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -519,12 +519,6 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, pim_ifp = ifp->info; ch = XCALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch)); - if (!ch) { - zlog_warn( - "%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s", - __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name); - return NULL; - } ch->flags = 0; if ((source_flags & PIM_ENCODE_RPT_BIT) diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 92993ff1b9..b46f1b5e9d 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -860,18 +860,8 @@ static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr, } igmp = XCALLOC(MTYPE_PIM_IGMP_SOCKET, sizeof(*igmp)); - if (!igmp) { - zlog_warn("%s %s: XCALLOC() failure", __FILE__, - __PRETTY_FUNCTION__); - return 0; - } igmp->igmp_group_list = list_new(); - if (!igmp->igmp_group_list) { - zlog_err("%s %s: failure: igmp_group_list = list_new()", - __FILE__, __PRETTY_FUNCTION__); - return 0; - } igmp->igmp_group_list->del = (void (*)(void *))igmp_group_free; snprintf(hash_name, 64, "IGMP %s hash", ifp->name); @@ -1129,19 +1119,8 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp, */ group = XCALLOC(MTYPE_PIM_IGMP_GROUP, sizeof(*group)); - if (!group) { - zlog_warn("%s %s: XCALLOC() failure", __FILE__, - __PRETTY_FUNCTION__); - return NULL; /* error, not found, could not create */ - } group->group_source_list = list_new(); - if (!group->group_source_list) { - zlog_warn("%s %s: list_new() failure", __FILE__, - __PRETTY_FUNCTION__); - XFREE(MTYPE_PIM_IGMP_GROUP, group); /* discard group */ - return NULL; /* error, not found, could not initialize */ - } group->group_source_list->del = (void (*)(void *))igmp_source_free; group->t_group_timer = NULL; diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c index 5ccad39b33..b32d71cc0d 100644 --- a/pimd/pim_igmpv3.c +++ b/pimd/pim_igmpv3.c @@ -457,11 +457,6 @@ struct igmp_source *source_new(struct igmp_group *group, } src = XCALLOC(MTYPE_PIM_IGMP_GROUP_SOURCE, sizeof(*src)); - if (!src) { - zlog_warn("%s %s: XCALLOC() failure", __FILE__, - __PRETTY_FUNCTION__); - return 0; /* error, not found, could not create */ - } src->t_source_timer = NULL; src->source_group = group; /* back pointer */ diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c index cb70ee7904..5121dc94ca 100644 --- a/pimd/pim_instance.c +++ b/pimd/pim_instance.c @@ -69,8 +69,6 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf) char hash_name[64]; pim = XCALLOC(MTYPE_PIM_PIM_INSTANCE, sizeof(struct pim_instance)); - if (!pim) - return NULL; pim_if_init(pim); @@ -102,12 +100,6 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf) } pim->static_routes = list_new(); - if (!pim->static_routes) { - zlog_err("%s %s: failure: static_routes=list_new()", __FILE__, - __PRETTY_FUNCTION__); - pim_instance_terminate(pim); - return NULL; - } pim->static_routes->del = (void (*)(void *))pim_static_route_free; pim->send_v6_secondary = 1; diff --git a/pimd/pim_jp_agg.c b/pimd/pim_jp_agg.c index e87dfbca95..c5f5b9c5e0 100644 --- a/pimd/pim_jp_agg.c +++ b/pimd/pim_jp_agg.c @@ -329,7 +329,6 @@ void pim_jp_agg_single_upstream_send(struct pim_rpf *rpf, if (first) { groups = list_new(); - jag.sources = list_new(); listnode_add(groups, &jag); diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 8462a4fdf8..dd30678405 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -152,13 +152,13 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp, struct pim_rpf *rpg; struct prefix_sg sg; - rpg = RP(pim_ifp->pim, msg->im_dst); + rpg = pim_ifp ? RP(pim_ifp->pim, msg->im_dst) : NULL; /* * If the incoming interface is unknown OR * the Interface type is SSM we don't need to * do anything here */ - if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp) + if (!rpg || (pim_rpf_addr_is_inaddr_none(rpg)) || (!(PIM_I_am_DR(pim_ifp)))) { if (PIM_DEBUG_MROUTE_DETAIL) zlog_debug( @@ -278,7 +278,7 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp, pim_ifp = up->rpf.source_nexthop.interface->info; - rpg = RP(pim_ifp->pim, sg.grp); + rpg = pim_ifp ? RP(pim_ifp->pim, sg.grp) : NULL; if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp) || (!(PIM_I_am_DR(pim_ifp)))) { diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index e798d70a51..951e743494 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -240,11 +240,6 @@ static struct pim_msdp_sa *pim_msdp_sa_new(struct pim_instance *pim, struct pim_msdp_sa *sa; sa = XCALLOC(MTYPE_PIM_MSDP_SA, sizeof(*sa)); - if (!sa) { - zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, - sizeof(*sa)); - return NULL; - } sa->pim = pim; sa->sg = *sg; @@ -1069,11 +1064,6 @@ static enum pim_msdp_err pim_msdp_peer_new(struct pim_instance *pim, pim_msdp_enable(pim); mp = XCALLOC(MTYPE_PIM_MSDP_PEER, sizeof(*mp)); - if (!mp) { - zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, - sizeof(*mp)); - return PIM_MSDP_ERR_OOM; - } mp->pim = pim; mp->peer = peer_addr; @@ -1277,11 +1267,6 @@ static struct pim_msdp_mg *pim_msdp_mg_new(const char *mesh_group_name) struct pim_msdp_mg *mg; mg = XCALLOC(MTYPE_PIM_MSDP_MG, sizeof(*mg)); - if (!mg) { - zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, - sizeof(*mg)); - return NULL; - } mg->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name); mg->mbr_list = list_new(); @@ -1395,13 +1380,6 @@ enum pim_msdp_err pim_msdp_mg_mbr_add(struct pim_instance *pim, } mbr = XCALLOC(MTYPE_PIM_MSDP_MG_MBR, sizeof(*mbr)); - if (!mbr) { - zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, - sizeof(*mbr)); - /* if there are no references to the mg free it */ - pim_msdp_mg_free(pim, mg); - return PIM_MSDP_ERR_OOM; - } mbr->mbr_ip = mbr_ip; listnode_add_sort(mg->mbr_list, mbr); diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index 20a942b4fd..2730f5e7aa 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -305,11 +305,6 @@ pim_neighbor_new(struct interface *ifp, struct in_addr source_addr, zassert(pim_ifp); neigh = XCALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh)); - if (!neigh) { - zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, - sizeof(*neigh)); - return 0; - } neigh->creation = pim_time_monotonic_sec(); neigh->source_addr = source_addr; diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c index d0fa90f0db..ac49373da0 100644 --- a/pimd/pim_nht.c +++ b/pimd/pim_nht.c @@ -92,10 +92,6 @@ static struct pim_nexthop_cache *pim_nexthop_cache_add(struct pim_instance *pim, pnc = XCALLOC(MTYPE_PIM_NEXTHOP_CACHE, sizeof(struct pim_nexthop_cache)); - if (!pnc) { - zlog_err("%s: NHT PIM XCALLOC failure ", __PRETTY_FUNCTION__); - return NULL; - } pnc->rpf.rpf_addr.family = rpf_addr->rpf_addr.family; pnc->rpf.rpf_addr.prefixlen = rpf_addr->rpf_addr.prefixlen; pnc->rpf.rpf_addr.u.prefix4.s_addr = @@ -140,14 +136,6 @@ int pim_find_or_track_nexthop(struct pim_instance *pim, struct prefix *addr, pnc = pim_nexthop_cache_find(pim, &rpf); if (!pnc) { pnc = pim_nexthop_cache_add(pim, &rpf); - if (!pnc) { - char rpf_str[PREFIX_STRLEN]; - pim_addr_dump("<nht-pnc?>", addr, rpf_str, - sizeof(rpf_str)); - zlog_warn("%s: pnc node allocation failed. addr %s ", - __PRETTY_FUNCTION__, rpf_str); - return 0; - } pim_sendmsg_zebra_rnh(pim, zclient, pnc, ZEBRA_NEXTHOP_REGISTER); if (PIM_DEBUG_PIM_NHT) { diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index d49484f869..f0f336fb73 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -107,11 +107,6 @@ void pim_oil_init(struct pim_instance *pim) pim_oil_equal, hash_name); pim->channel_oil_list = list_new(); - if (!pim->channel_oil_list) { - zlog_err("%s %s: failure: channel_oil_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return; - } pim->channel_oil_list->del = (void (*)(void *))pim_channel_oil_free; pim->channel_oil_list->cmp = (int (*)(void *, void *))pim_channel_oil_compare; @@ -182,10 +177,6 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim, } c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil)); - if (!c_oil) { - zlog_err("PIM XCALLOC(%zu) failure", sizeof(*c_oil)); - return NULL; - } c_oil->oil.mfcc_mcastgrp = sg->grp; c_oil->oil.mfcc_origin = sg->src; diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index a8cf58cd36..7e053d2aa0 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -115,13 +115,6 @@ void pim_rp_init(struct pim_instance *pim) rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); - if (!rp_info) { - zlog_err("Unable to alloc rp_info"); - route_table_finish(pim->rp_table); - list_delete_and_null(&pim->rp_list); - return; - } - if (!str2prefix("224.0.0.0/4", &rp_info->group)) { zlog_err("Unable to convert 224.0.0.0/4 to prefix"); list_delete_and_null(&pim->rp_list); @@ -365,8 +358,6 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, struct route_node *rn; rp_info = XCALLOC(MTYPE_PIM_RP, sizeof(*rp_info)); - if (!rp_info) - return PIM_MALLOC_FAIL; if (group_range == NULL) result = str2prefix("224.0.0.0/4", &rp_info->group); @@ -534,12 +525,6 @@ int pim_rp_new(struct pim_instance *pim, const char *rp, listnode_add_sort(pim->rp_list, rp_info); rn = route_node_get(pim->rp_table, &rp_info->group); - if (!rn) { - char buf[PREFIX_STRLEN]; - zlog_err("Failure to get route node for pim->rp_table: %s", - prefix2str(&rp_info->group, buf, sizeof(buf))); - return PIM_MALLOC_FAIL; - } rn->info = rp_info; if (PIM_DEBUG_TRACE) { diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c index 8e7da0f121..bdf303d5c5 100644 --- a/pimd/pim_ssmpingd.c +++ b/pimd/pim_ssmpingd.c @@ -348,12 +348,6 @@ static struct ssmpingd_sock *ssmpingd_new(struct pim_instance *pim, if (!pim->ssmpingd_list) { pim->ssmpingd_list = list_new(); - if (!pim->ssmpingd_list) { - zlog_err( - "%s %s: failure: qpim_ssmpingd_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return 0; - } pim->ssmpingd_list->del = (void (*)(void *))ssmpingd_free; } @@ -369,15 +363,6 @@ static struct ssmpingd_sock *ssmpingd_new(struct pim_instance *pim, } ss = XCALLOC(MTYPE_PIM_SSMPINGD, sizeof(*ss)); - if (!ss) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<src?>", source_addr, source_str, - sizeof(source_str)); - zlog_err("%s: XCALLOC(%zu) failure for ssmpingd source %s", - __PRETTY_FUNCTION__, sizeof(*ss), source_str); - close(sock_fd); - return 0; - } ss->pim = pim; ss->sock_fd = sock_fd; diff --git a/pimd/pim_static.c b/pimd/pim_static.c index 3d44a01c78..9569b7dcac 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -39,14 +39,7 @@ void pim_static_route_free(struct static_route *s_route) static struct static_route *static_route_alloc() { - struct static_route *s_route; - - s_route = XCALLOC(MTYPE_PIM_STATIC_ROUTE, sizeof(*s_route)); - if (!s_route) { - zlog_err("PIM XCALLOC(%zu) failure", sizeof(*s_route)); - return 0; - } - return s_route; + return XCALLOC(MTYPE_PIM_STATIC_ROUTE, sizeof(struct static_route)); } static struct static_route *static_route_new(unsigned int iif, unsigned int oif, @@ -55,9 +48,6 @@ static struct static_route *static_route_new(unsigned int iif, unsigned int oif, { struct static_route *s_route; s_route = static_route_alloc(); - if (!s_route) { - return 0; - } s_route->group = group; s_route->source = source; diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c index eddec3c29e..80bda336df 100644 --- a/pimd/pim_tlv.c +++ b/pimd/pim_tlv.c @@ -757,12 +757,6 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr, */ if (!*hello_option_addr_list) { *hello_option_addr_list = list_new(); - if (!*hello_option_addr_list) { - zlog_err( - "%s %s: failure: hello_option_addr_list=list_new()", - __FILE__, __PRETTY_FUNCTION__); - return -2; - } (*hello_option_addr_list)->del = (void (*)(void *))prefix_free; } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index 9329d72ce0..e3488b6a66 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -603,11 +603,6 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, struct pim_upstream *up; up = XCALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up)); - if (!up) { - zlog_err("%s: PIM XCALLOC(%zu) failure", __PRETTY_FUNCTION__, - sizeof(*up)); - return NULL; - } up->sg = *sg; pim_str_sg_set(sg, up->sg_str); diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index cb384bfe1d..a58dfcdd5f 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -202,7 +202,7 @@ static int pim_zebra_if_state_up(int command, struct zclient *zclient, * If we have a pimreg device callback and it's for a specific * table set the master appropriately */ - if (sscanf(ifp->name, "pimreg%d", &table_id) == 1) { + if (sscanf(ifp->name, "pimreg%" SCNu32, &table_id) == 1) { struct vrf *vrf; RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { if ((table_id == vrf->data.l.table_id) diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index 064b78b260..e2be7050d7 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -10,41 +10,43 @@ #################### FRRouting (FRR) configure options ##################### # with-feature options -%{!?with_pam: %global with_pam 0 } -%{!?with_ospfclient: %global with_ospfclient 1 } -%{!?with_ospfapi: %global with_ospfapi 1 } -%{!?with_rtadv: %global with_rtadv 1 } -%{!?with_ldpd: %global with_ldpd 1 } -%{!?with_nhrpd: %global with_nhrpd 1 } -%{!?with_eigrpd: %global with_eigrpd 1 } %{!?with_babeld: %global with_babeld 1 } -%{!?with_shared: %global with_shared 1 } -%{!?with_multipath: %global with_multipath 256 } -%{!?frr_user: %global frr_user frr } -%{!?vty_group: %global vty_group frrvty } -%{!?with_fpm: %global with_fpm 1 } -%{!?with_watchfrr: %global with_watchfrr 1 } %{!?with_bgp_vnc: %global with_bgp_vnc 0 } +%{!?with_cumulus: %global with_cumulus 0 } +%{!?with_eigrpd: %global with_eigrpd 1 } +%{!?with_fpm: %global with_fpm 1 } +%{!?with_ldpd: %global with_ldpd 1 } +%{!?with_multipath: %global with_multipath 256 } +%{!?with_nhrpd: %global with_nhrpd 1 } +%{!?with_ospfapi: %global with_ospfapi 1 } +%{!?with_ospfclient: %global with_ospfclient 1 } +%{!?with_pam: %global with_pam 0 } +%{!?with_pbrd: %global with_pbrd 1 } %{!?with_pimd: %global with_pimd 1 } %{!?with_rpki: %global with_rpki 0 } -%{!?with_pbrd: %global with_pbrd 1 } +%{!?with_rtadv: %global with_rtadv 1 } +%{!?with_watchfrr: %global with_watchfrr 1 } + +# user and group +%{!?frr_user: %global frr_user frr } +%{!?vty_group: %global vty_group frrvty } # path defines -%define _sysconfdir /etc/frr -%define _sbindir /usr/lib/frr -%define zeb_src %{_builddir}/%{name}-%{frrversion} -%define zeb_rh_src %{zeb_src}/redhat -%define zeb_docs %{zeb_src}/doc -%define frr_tools %{zeb_src}/tools +%define configdir %{_sysconfdir}/%{name} +%define _sbindir /usr/lib/frr +%define zeb_src %{_builddir}/%{name}-%{frrversion} +%define zeb_rh_src %{zeb_src}/redhat +%define zeb_docs %{zeb_src}/doc +%define frr_tools %{zeb_src}/tools # defines for configure -%define _localstatedir /var/run/frr +%define rundir %{_localstatedir}/run/%{name} # define for sphinx-build binary %if 0%{?rhel} && 0%{?rhel} < 7 -%define sphinx sphinx-build2.7 + %define sphinx sphinx-build2.7 %else -%define sphinx sphinx-build + %define sphinx sphinx-build %endif ############################################################################ @@ -83,55 +85,52 @@ %{!?frr_gid: %global frr_gid 92 } %{!?vty_gid: %global vty_gid 85 } -%define daemon_list zebra ripd ospfd bgpd isisd ripngd ospf6d pbrd +%define daemon_list zebra ripd ospfd bgpd isisd ripngd ospf6d pbrd %if %{with_ldpd} -%define daemon_ldpd ldpd + %define daemon_ldpd ldpd %else -%define daemon_ldpd "" + %define daemon_ldpd "" %endif %if %{with_pimd} -%define daemon_pimd pimd + %define daemon_pimd pimd %else -%define daemon_pimd "" + %define daemon_pimd "" %endif %if %{with_pbrd} -%define daemon_pbrd pbrd + %define daemon_pbrd pbrd %else -%define daemon_pbrd "" + %define daemon_pbrd "" %endif %if %{with_nhrpd} -%define daemon_nhrpd nhrpd + %define daemon_nhrpd nhrpd %else -%define daemon_nhrpd "" + %define daemon_nhrpd "" %endif %if %{with_eigrpd} -%define daemon_eigrpd eigrpd + %define daemon_eigrpd eigrpd %else -%define daemon_eigrpd "" + %define daemon_eigrpd "" %endif %if %{with_babeld} -%define daemon_babeld babeld + %define daemon_babeld babeld %else -%define daemon_babeld "" + %define daemon_babeld "" %endif %if %{with_watchfrr} -%define daemon_watchfrr watchfrr + %define daemon_watchfrr watchfrr %else -%define daemon_watchfrr "" + %define daemon_watchfrr "" %endif %define all_daemons %{daemon_list} %{daemon_ldpd} %{daemon_pimd} %{daemon_nhrpd} %{daemon_eigrpd} %{daemon_babeld} %{daemon_watchfrr} %{daemon_pbrd} -# allow build dir to be kept -%{!?keep_build: %global keep_build 0 } - #release sub-revision (the two digits after the CONFDATE) %{!?release_rev: %global release_rev 01 } @@ -143,19 +142,27 @@ License: GPLv2+ Group: System Environment/Daemons Source0: https://github.com/FRRouting/frr/archive/%{name}-%{frrversion}.tar.gz URL: https://www.frrouting.org +Requires(pre): shadow-utils Requires(preun): info Requires(post): info -BuildRequires: gcc patch libcap-devel -BuildRequires: readline-devel ncurses-devel -BuildRequires: json-c-devel bison >= 2.7 flex make -BuildRequires: c-ares-devel texinfo +BuildRequires: bison >= 2.7 +BuildRequires: c-ares-devel +BuildRequires: flex +BuildRequires: gcc +BuildRequires: json-c-devel +BuildRequires: libcap-devel +BuildRequires: make +BuildRequires: ncurses-devel +BuildRequires: readline-devel +BuildRequires: texinfo %if 0%{?rhel} && 0%{?rhel} < 7 #python27-devel is available from ius community repo for RedHat/CentOS 6 -BuildRequires: python27-devel python27-sphinx +BuildRequires: python27-devel +BuildRequires: python27-sphinx %else -BuildRequires: python-devel >= 2.7 python-sphinx +BuildRequires: python-devel >= 2.7 +BuildRequires: python-sphinx %endif -Requires: json-c initscripts %if %{with_pam} BuildRequires: pam-devel %endif @@ -163,7 +170,8 @@ BuildRequires: pam-devel BuildRequires: librtr-devel >= 0.5 %endif %if "%{initsystem}" == "systemd" -BuildRequires: systemd systemd-devel +BuildRequires: systemd +BuildRequires: systemd-devel Requires(post): systemd Requires(preun): systemd Requires(postun): systemd @@ -172,12 +180,13 @@ Requires(post): chkconfig Requires(preun): chkconfig # Initscripts > 5.60 is required for IPv6 support Requires(pre): initscripts >= 5.60 +Requires: initscripts %endif Provides: routingdaemon = %{version}-%{release} -BuildRoot: %{_tmppath}/%{name}-%{version}-root Obsoletes: gated mrt zebra frr-sysvinit Conflicts: bird + %description FRRouting is a free software that manages TCP/IP based routing protocol. It takes multi-server and multi-thread approach to resolve @@ -188,6 +197,7 @@ NHRP, Babel, PBR and EIGRP. FRRouting is a fork of Quagga. + %package contrib Summary: contrib tools for frr Group: System Environment/Daemons @@ -195,6 +205,7 @@ Group: System Environment/Daemons %description contrib Contributed/3rd party tools which may be of use with frr. + %package pythontools Summary: python tools for frr BuildRequires: python @@ -204,6 +215,7 @@ Group: System Environment/Daemons %description pythontools Contributed python 2.7 tools which may be of use with frr. + %package devel Summary: Header and object files for frr development Group: System Environment/Daemons @@ -213,8 +225,10 @@ Requires: %{name} = %{version}-%{release} The frr-devel package contains the header and object files neccessary for developing OSPF-API and frr applications. + %prep -%setup -q -n frr-%{frrversion} +%setup -q -n frr-%{frrversion} + %build @@ -230,15 +244,11 @@ developing OSPF-API and frr applications. %configure \ --sbindir=%{_sbindir} \ - --sysconfdir=%{_sysconfdir} \ - --libdir=%{_libdir} \ - --libexecdir=%{_libexecdir} \ - --localstatedir=%{_localstatedir} \ + --sysconfdir=%{configdir} \ + --localstatedir=%{rundir} \ + --disable-static \ --disable-werror \ --enable-irdp \ -%if !%{with_shared} - --disable-shared \ -%endif %if %{with_multipath} --enable-multipath=%{with_multipath} \ %endif @@ -292,11 +302,11 @@ developing OSPF-API and frr applications. --with-libpam \ %endif %if 0%{?frr_user:1} - --enable-user=%frr_user \ - --enable-group=%frr_user \ + --enable-user=%{frr_user} \ + --enable-group=%{frr_user} \ %endif %if 0%{?vty_group:1} - --enable-vty-group=%vty_group \ + --enable-vty-group=%{vty_group} \ %endif %if %{with_fpm} --enable-fpm \ @@ -308,6 +318,9 @@ developing OSPF-API and frr applications. %else --disable-watchfrr \ %endif +%if %{with_cumulus} + --enable-cumulus \ +%endif %if %{with_bgp_vnc} --enable-bgp-vnc \ %else @@ -318,9 +331,10 @@ developing OSPF-API and frr applications. --enable-systemd \ %endif %if %{with_rpki} - --enable-rpki \ + --enable-rpki +%else + --disable-rpki %endif - --enable-poll make %{?_smp_mflags} MAKEINFO="makeinfo --no-split" SPHINXBUILD=%{sphinx} @@ -328,9 +342,10 @@ pushd doc make SPHINXBUILD=%{sphinx} info popd + %install -mkdir -p %{buildroot}/etc/{frr,sysconfig,logrotate.d,pam.d,default} \ - %{buildroot}/var/log/frr %{buildroot}%{_infodir} +mkdir -p %{buildroot}%{_sysconfdir}/{frr,sysconfig,logrotate.d,pam.d,default} \ + %{buildroot}%{_localstatedir}/log/frr %{buildroot}%{_infodir} make DESTDIR=%{buildroot} INSTALL="install -p" CP="cp -p" SPHINXBUILD=%{sphinx} install # Remove this file, as it is uninstalled and causes errors when building on RH9 @@ -339,53 +354,47 @@ rm -rf %{buildroot}/usr/share/info/dir # Remove debian init script if it was installed rm -f %{buildroot}%{_sbindir}/frr -# kill bogus libtool files for modules -rm -f %{buildroot}%{_libdir}/frr/modules/*.la +# kill bogus libtool files +rm -vf %{buildroot}%{_libdir}/frr/modules/*.la +rm -vf %{buildroot}%{_libdir}/*.la # install /etc sources %if "%{initsystem}" == "systemd" mkdir -p %{buildroot}%{_unitdir} -install -m644 %{zeb_rh_src}/frr.service \ - %{buildroot}%{_unitdir}/frr.service -install %{zeb_rh_src}/frr.init \ - %{buildroot}%{_sbindir}/frr +install -m644 %{zeb_rh_src}/frr.service %{buildroot}%{_unitdir}/frr.service +install %{zeb_rh_src}/frr.init %{buildroot}%{_sbindir}/frr %else -mkdir -p %{buildroot}/etc/rc.d/init.d -install %{zeb_rh_src}/frr.init \ - %{buildroot}%{_sbindir}/frr -ln -s %{_sbindir}/frr \ - %{buildroot}/etc/rc.d/init.d/frr +mkdir -p %{buildroot}%{_initddir} +install %{zeb_rh_src}/frr.init %{buildroot}%{_sbindir}/frr +ln -s %{_sbindir}/frr %{buildroot}%{_initddir}/frr %endif -install %{zeb_rh_src}/daemons %{buildroot}/etc/frr -install -m644 %{zeb_rh_src}/frr.pam \ - %{buildroot}/etc/pam.d/frr -install -m644 %{zeb_rh_src}/frr.logrotate \ - %{buildroot}/etc/logrotate.d/frr -install -d -m750 %{buildroot}/var/run/frr +install %{zeb_rh_src}/daemons %{buildroot}%{_sysconfdir}/frr +install -m644 %{zeb_rh_src}/frr.pam %{buildroot}%{_sysconfdir}/pam.d/frr +install -m644 %{zeb_rh_src}/frr.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/frr +install -d -m750 %{buildroot}%{rundir} + %pre # add vty_group %if 0%{?vty_group:1} -if getent group %vty_group > /dev/null ; then : ; else \ - /usr/sbin/groupadd -r -g %vty_gid %vty_group > /dev/null || : ; fi + getent group %{vty_group} >/dev/null || groupadd -r -g %{vty_gid} %{vty_group} %endif # add frr user and group %if 0%{?frr_user:1} -# Ensure that frr_gid gets correctly allocated -if getent group %frr_user >/dev/null; then : ; else \ - /usr/sbin/groupadd -g %frr_gid %frr_user > /dev/null || : ; \ -fi -if getent passwd %frr_user >/dev/null ; then : ; else \ - /usr/sbin/useradd -u %frr_uid -g %frr_gid \ - -M -r -s /sbin/nologin -c "FRRouting suite" \ - -d %_localstatedir %frr_user 2> /dev/null || : ; \ -fi -%if 0%{?vty_group:1} -/usr/sbin/usermod -a -G %vty_group %frr_user -%endif + # Ensure that frr_gid gets correctly allocated + getent group %{frr_user} >/dev/null || groupadd -g %{frr_gid} %{frr_user} + getent passwd %{frr_user} >/dev/null || \ + useradd -r -u %{frr_uid} -g %{frr_user} \ + -s /sbin/nologin -c "FRRouting suite" \ + -d %{rundir} %{frr_user} + + %if 0%{?vty_group:1} + usermod -a -G %{vty_group} %{frr_user} + %endif %endif +exit 0 %post @@ -395,9 +404,9 @@ fi zebra_spec_add_service () { # Add port /etc/services entry if it isn't already there - if [ -f /etc/services ] && \ - ! %__sed -e 's/#.*$//' /etc/services | %__grep -wq $1 ; then - echo "$1 $2 # $3" >> /etc/services + if [ -f %{_sysconfdir}/services ] && \ + ! %__sed -e 's/#.*$//' %{_sysconfdir}/services | %__grep -wq $1 ; then + echo "$1 $2 # $3" >> %{_sysconfdir}/services fi } @@ -408,86 +417,87 @@ zebra_spec_add_service ripngd 2603/tcp "RIPngd vty" zebra_spec_add_service ospfd 2604/tcp "OSPFd vty" zebra_spec_add_service bgpd 2605/tcp "BGPd vty" zebra_spec_add_service ospf6d 2606/tcp "OSPF6d vty" +zebra_spec_add_service isisd 2608/tcp "ISISd vty" %if %{with_ospfapi} -zebra_spec_add_service ospfapi 2607/tcp "OSPF-API" + zebra_spec_add_service ospfapi 2607/tcp "OSPF-API" %endif -zebra_spec_add_service isisd 2608/tcp "ISISd vty" %if %{with_babeld} -zebra_spec_add_service babeld 2609/tcp "BABELd vty" + zebra_spec_add_service babeld 2609/tcp "BABELd vty" %endif %if %{with_nhrpd} -zebra_spec_add_service nhrpd 2610/tcp "NHRPd vty" + zebra_spec_add_service nhrpd 2610/tcp "NHRPd vty" %endif %if %{with_pimd} -zebra_spec_add_service pimd 2611/tcp "PIMd vty" + zebra_spec_add_service pimd 2611/tcp "PIMd vty" %endif %if %{with_pbrd} -zebra_spec_add_service pbrd 2615/tcp "PBRd vty" + zebra_spec_add_service pbrd 2615/tcp "PBRd vty" %endif %if %{with_ldpd} -zebra_spec_add_service ldpd 2612/tcp "LDPd vty" + zebra_spec_add_service ldpd 2612/tcp "LDPd vty" %endif %if %{with_eigrpd} -zebra_spec_add_service eigrpd 2613/tcp "EIGRPd vty" + zebra_spec_add_service eigrpd 2613/tcp "EIGRPd vty" %endif %if "%{initsystem}" == "systemd" -for daemon in %all_daemons ; do - %systemd_post frr.service -done + for daemon in %all_daemons ; do + %systemd_post frr.service + done %else -/sbin/chkconfig --add frr + /sbin/chkconfig --add frr %endif # Fix bad path in previous config files # Config files won't get replaced by default, so we do this ugly hack to fix it -%__sed -i 's|/etc/init.d/|%{_sbindir}/|g' %{_sysconfdir}/daemons 2> /dev/null || true +%__sed -i 's|/etc/init.d/|%{_sbindir}/|g' %{configdir}/daemons 2> /dev/null || true # With systemd, watchfrr is mandatory. Fix config to make sure it's enabled if # we install or upgrade to a frr built with systemd %if "%{initsystem}" == "systemd" - %__sed -i 's|watchfrr_enable=no|watchfrr_enable=yes|g' %{_sysconfdir}/daemons 2> /dev/null || true + %__sed -i 's|watchfrr_enable=no|watchfrr_enable=yes|g' %{configdir}/daemons 2> /dev/null || true %endif /sbin/install-info %{_infodir}/frr.info.gz %{_infodir}/dir # Create dummy files if they don't exist so basic functions can be used. -if [ ! -e %{_sysconfdir}/zebra.conf ]; then - echo "hostname `hostname`" > %{_sysconfdir}/zebra.conf +if [ ! -e %{configdir}/zebra.conf ]; then + echo "hostname `hostname`" > %{configdir}/zebra.conf %if 0%{?frr_user:1} - chown %frr_user:%frr_user %{_sysconfdir}/zebra.conf* + chown %{frr_user}:%{frr_user} %{configdir}/zebra.conf* %endif - chmod 640 %{_sysconfdir}/zebra.conf* + chmod 640 %{configdir}/zebra.conf* fi for daemon in %{all_daemons} ; do if [ x"${daemon}" != x"" ] ; then - if [ ! -e %{_sysconfdir}/${daemon}.conf ]; then - touch %{_sysconfdir}/${daemon}.conf + if [ ! -e %{configdir}/${daemon}.conf ]; then + touch %{configdir}/${daemon}.conf %if 0%{?frr_user:1} - chown %frr_user:%frr_user %{_sysconfdir}/${daemon}.conf* + chown %{frr_user}:%{frr_user} %{configdir}/${daemon}.conf* %endif fi fi done %if 0%{?frr_user:1} - chown %frr_user:%frr_user %{_sysconfdir}/daemons + chown %{frr_user}:%{frr_user} %{configdir}/daemons %endif %if %{with_watchfrr} # No config for watchfrr - this is part of /etc/sysconfig/frr - rm -f %{_sysconfdir}/watchfrr.* + rm -f %{configdir}/watchfrr.* %endif -if [ ! -e %{_sysconfdir}/vtysh.conf ]; then - touch %{_sysconfdir}/vtysh.conf - chmod 640 %{_sysconfdir}/vtysh.conf +if [ ! -e %{configdir}/vtysh.conf ]; then + touch %{configdir}/vtysh.conf + chmod 640 %{configdir}/vtysh.conf %if 0%{?frr_user:1} -%if 0%{?vty_group:1} - chown %{frr_user}:%{vty_group} %{_sysconfdir}/vtysh.conf* -%endif + %if 0%{?vty_group:1} + chown %{frr_user}:%{vty_group} %{configdir}/vtysh.conf* + %endif %endif fi + %postun if [ "$1" -ge 1 ]; then # @@ -502,11 +512,12 @@ if [ "$1" -ge 1 ]; then ## ## init.d Version ## - /etc/rc.d/init.d/frr restart >/dev/null 2>&1 + service frr restart >/dev/null 2>&1 %endif : fi + %preun %if "%{initsystem}" == "systemd" ## @@ -520,33 +531,28 @@ fi ## init.d Version ## if [ $1 -eq 0 ] ; then - /etc/rc.d/init.d/frr stop >/dev/null 2>&1 + service frr stop >/dev/null 2>&1 /sbin/chkconfig --del frr fi %endif /sbin/install-info --delete %{_infodir}/frr.info.gz %{_infodir}/dir -%clean -%if !0%{?keep_build:1} -rm -rf %{buildroot} -%endif %files -%defattr(-,root,root) %doc */*.sample* AUTHORS COPYING %doc doc/mpls %doc ChangeLog NEWS README %if 0%{?frr_user:1} -%dir %attr(751,%frr_user,%frr_user) %{_sysconfdir} -%dir %attr(750,%frr_user,%frr_user) /var/log/frr -%dir %attr(751,%frr_user,%frr_user) /var/run/frr + %dir %attr(751,%{frr_user},%{frr_user}) %{configdir} + %dir %attr(750,%{frr_user},%{frr_user}) %{_localstatedir}/log/frr + %dir %attr(751,%{frr_user},%{frr_user}) %{rundir} %else -%dir %attr(750,root,root) %{_sysconfdir} -%dir %attr(750,root,root) /var/log/frr -%dir %attr(750,root,root) /var/run/frr + %dir %attr(750,root,root) %{configdir} + %dir %attr(750,root,root) %{_localstatedir}/log/frr + %dir %attr(750,root,root) %{rundir} %endif %if 0%{?vty_group:1} -%attr(750,%frr_user,%vty_group) %{_sysconfdir}/vtysh.conf.sample + %attr(750,%{frr_user},%{vty_group}) %{configdir}/vtysh.conf.sample %endif %{_infodir}/frr.info.gz %{_mandir}/man*/* @@ -579,63 +585,60 @@ rm -rf %{buildroot} %if %{with_babeld} %{_sbindir}/babeld %endif -%if %{with_shared} -%{_libdir}/lib*.so %{_libdir}/lib*.so.0 -%attr(755,root,root) %{_libdir}/lib*.so.0.* -%endif +%{_libdir}/lib*.so.0.* %if %{with_fpm} -%attr(755,root,root) %{_libdir}/frr/modules/zebra_fpm.so + %{_libdir}/frr/modules/zebra_fpm.so %endif %if %{with_rpki} -%attr(755,root,root) %{_libdir}/frr/modules/bgpd_rpki.so + %{_libdir}/frr/modules/bgpd_rpki.so %endif -%attr(755,root,root) %{_libdir}/frr/modules/zebra_irdp.so +%{_libdir}/frr/modules/zebra_irdp.so %{_bindir}/* -%config(noreplace) /etc/frr/[!v]*.conf* -%config(noreplace) %attr(750,%frr_user,%frr_user) /etc/frr/daemons +%config(noreplace) %{configdir}/[!v]*.conf* +%config(noreplace) %attr(750,%{frr_user},%{frr_user}) %{configdir}/daemons %if "%{initsystem}" == "systemd" %{_unitdir}/frr.service %else - /etc/rc.d/init.d/frr + %{_initddir}/frr %endif %{_sbindir}/frr -%config(noreplace) /etc/pam.d/frr -%config(noreplace) /etc/logrotate.d/frr +%config(noreplace) %{_sysconfdir}/pam.d/frr +%config(noreplace) %{_sysconfdir}/logrotate.d/frr %{_sbindir}/frr-reload + %files contrib -%defattr(-,root,root) %doc tools + %files pythontools -%defattr(-,root,root) %{_sbindir}/frr-reload.py %{_sbindir}/frr-reload.pyc %{_sbindir}/frr-reload.pyo + %files devel -%defattr(-,root,root) +%{_libdir}/lib*.so %if %{with_ospfclient} -%{_sbindir}/ospfclient -%endif -%{_libdir}/*.a -%{_libdir}/*.la -%dir %attr(755,root,root) %{_includedir}/%{name} -%{_includedir}/%name/*.h -%dir %attr(755,root,root) %{_includedir}/%{name}/ospfd -%{_includedir}/%name/ospfd/*.h + %{_sbindir}/ospfclient +%endif +%dir %{_includedir}/%{name} +%{_includedir}/%{name}/*.h +%dir %{_includedir}/%{name}/ospfd +%{_includedir}/%{name}/ospfd/*.h %if %{with_ospfapi} -%dir %attr(755,root,root) %{_includedir}/%{name}/ospfapi -%{_includedir}/%name/ospfapi/*.h + %dir %{_includedir}/%{name}/ospfapi + %{_includedir}/%{name}/ospfapi/*.h %endif %if %{with_eigrpd} -%dir %attr(755,root,root) %{_includedir}/%{name}/eigrpd -%{_includedir}/%name/eigrpd/*.h + %dir %{_includedir}/%{name}/eigrpd + %{_includedir}/%{name}/eigrpd/*.h %endif + %changelog -* Sun May 20 2018 Martin Winter <mwinter@opensourcerouting.org> - %{version} +* Sun May 20 2018 Martin Winter <mwinter@opensourcerouting.org> - Fixed RPKI RPM build * Sun Mar 4 2018 Martin Winter <mwinter@opensourcerouting.org> diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index d1057bf53e..c463630b12 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -492,7 +492,7 @@ static int ripng_enable_network_lookup_if(struct interface *ifp) for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, connected)) { struct prefix *p; - struct route_node *node; + struct route_node *n; p = connected->address; @@ -501,10 +501,10 @@ static int ripng_enable_network_lookup_if(struct interface *ifp) address.prefix = p->u.prefix6; address.prefixlen = IPV6_MAX_BITLEN; - node = route_node_match(ripng_enable_network, - (struct prefix *)&address); - if (node) { - route_unlock_node(node); + n = route_node_match(ripng_enable_network, + (struct prefix *)&address); + if (n) { + route_unlock_node(n); return 1; } } diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 840157516f..565e151c53 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -1516,9 +1516,10 @@ int ripng_write_rte(int num, struct stream *s, struct prefix_ipv6 *p, } /* Write routing table entry. */ - if (!nexthop) + if (!nexthop) { + assert(p); stream_write(s, (uint8_t *)&p->prefix, sizeof(struct in6_addr)); - else + } else stream_write(s, (uint8_t *)nexthop, sizeof(struct in6_addr)); stream_putw(s, tag); if (p) diff --git a/tests/.gitignore b/tests/.gitignore index 5b90b7046c..c8368b39b6 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -21,6 +21,7 @@ TAGS __pycache__ .pytest_cache /bgpd/test_aspath +/bgpd/test_bgp_table /bgpd/test_capability /bgpd/test_ecommunity /bgpd/test_mp_attr diff --git a/tests/Makefile.am b/tests/Makefile.am index 32d2db768a..a7dec67348 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -21,7 +21,8 @@ TESTS_BGPD = \ bgpd/test_peer_attr \ bgpd/test_ecommunity \ bgpd/test_mp_attr \ - bgpd/test_mpath + bgpd/test_mpath \ + bgpd/test_bgp_table else TESTS_BGPD = endif @@ -143,6 +144,7 @@ bgpd_test_peer_attr_SOURCES = bgpd/test_peer_attr.c bgpd_test_ecommunity_SOURCES = bgpd/test_ecommunity.c bgpd_test_mp_attr_SOURCES = bgpd/test_mp_attr.c bgpd_test_mpath_SOURCES = bgpd/test_mpath.c +bgpd_test_bgp_table_SOURCES = bgpd/test_bgp_table.c isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv.c nodist_isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv_tests.h BUILT_SOURCES=isisd/test_fuzz_isis_tlv_tests.h @@ -186,6 +188,7 @@ bgpd_test_peer_attr_LDADD = $(BGP_TEST_LDADD) bgpd_test_ecommunity_LDADD = $(BGP_TEST_LDADD) bgpd_test_mp_attr_LDADD = $(BGP_TEST_LDADD) bgpd_test_mpath_LDADD = $(BGP_TEST_LDADD) +bgpd_test_bgp_table_LDADD = $(BGP_TEST_LDADD) isisd_test_fuzz_isis_tlv_LDADD = $(ISISD_TEST_LDADD) isisd_test_isis_vertex_queue_LDADD = $(ISISD_TEST_LDADD) ospf6d_test_lsdb_LDADD = $(OSPF6_TEST_LDADD) diff --git a/tests/bgpd/test_bgp_table.c b/tests/bgpd/test_bgp_table.c new file mode 100644 index 0000000000..01ce7480d7 --- /dev/null +++ b/tests/bgpd/test_bgp_table.c @@ -0,0 +1,192 @@ +/* + * BGP Routing table range lookup test + * Copyright (C) 2012 OSR. + * Copyright (C) 2018 Marcel Röthke (marcel.roethke@haw-hamburg.de), for HAW + * Hamburg + * + * This file is part of FRRouting + * + * Quagga 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. + * + * Quagga 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 <zebra.h> + +#include "prefix.h" +#include "table.h" +#include "bgpd/bgp_table.h" +#include "linklist.h" + +/* + * test_node_t + * + * Information that is kept for each node in the radix tree. + */ +struct test_node_t { + + /* + * Human readable representation of the string. Allocated using + * malloc()/dup(). + */ + char *prefix_str; +}; + +/* + * add_node + * + * Add the given prefix (passed in as a string) to the given table. + */ +static void add_node(struct bgp_table *table, const char *prefix_str) +{ + struct prefix_ipv4 p; + struct test_node_t *node; + struct bgp_node *rn; + + assert(prefix_str); + + if (str2prefix_ipv4(prefix_str, &p) <= 0) + assert(0); + + rn = bgp_node_get(table, (struct prefix *)&p); + if (rn->info) { + assert(0); + return; + } + + node = malloc(sizeof(struct test_node_t)); + assert(node); + node->prefix_str = strdup(prefix_str); + assert(node->prefix_str); + rn->info = node; +} + +static void print_range_result(struct list *list) +{ + + struct listnode *listnode; + struct bgp_node *bnode; + + for (ALL_LIST_ELEMENTS_RO(list, listnode, bnode)) { + char buf[PREFIX2STR_BUFFER]; + + prefix2str(&bnode->p, buf, PREFIX2STR_BUFFER); + printf("%s\n", buf); + } +} + +static void check_lookup_result(struct list *list, va_list arglist) +{ + char *prefix_str; + unsigned int prefix_count = 0; + + printf("Searching results\n"); + while ((prefix_str = va_arg(arglist, char *))) { + struct listnode *listnode; + struct bgp_node *bnode; + struct prefix p; + bool found = false; + + prefix_count++; + printf("Searching for %s\n", prefix_str); + + if (str2prefix(prefix_str, &p) <= 0) + assert(0); + + for (ALL_LIST_ELEMENTS_RO(list, listnode, bnode)) { + if (prefix_same(&bnode->p, &p)) + found = true; + } + + assert(found); + } + + printf("Checking for unexpected result items\n"); + printf("Expecting %d found %d\n", prefix_count, listcount(list)); + assert(prefix_count == listcount(list)); +} + +static void do_test(struct bgp_table *table, const char *prefix, uint8_t maxlen, + ...) +{ + va_list arglist; + struct list *list = list_new(); + struct prefix p; + + list->del = (void (*)(void *))bgp_unlock_node; + + va_start(arglist, maxlen); + printf("\nDoing lookup for %s-%d\n", prefix, maxlen); + if (str2prefix(prefix, &p) <= 0) + assert(0); + bgp_table_range_lookup(table, &p, maxlen, list); + print_range_result(list); + + check_lookup_result(list, arglist); + + list_delete_and_null(&list); + + va_end(arglist); + + printf("Checks successfull\n"); +} + +/* + * test_range_lookup + */ +static void test_range_lookup(void) +{ + struct bgp_table *table = bgp_table_init(NULL, AFI_IP, SAFI_UNICAST); + + printf("Testing bgp_table_range_lookup\n"); + + printf("Setup bgp_table"); + const char *prefixes[] = {"1.16.0.0/16", "1.16.128.0/18", + "1.16.192.0/18", "1.16.64.0/19", + "1.16.160.0/19", "1.16.32.0/20", + "1.16.32.0/21", "16.0.0.0/16"}; + + int num_prefixes = sizeof(prefixes) / sizeof(prefixes[0]); + + for (int i = 0; i < num_prefixes; i++) + add_node(table, prefixes[i]); + + do_test(table, "1.16.0.0/17", 20, "1.16.64.0/19", "1.16.32.0/20", NULL); + do_test(table, "1.16.128.0/17", 20, "1.16.128.0/18", "1.16.192.0/18", + "1.16.160.0/19", NULL); + + do_test(table, "1.16.128.0/17", 20, "1.16.128.0/18", "1.16.192.0/18", + "1.16.160.0/19", NULL); + + do_test(table, "1.16.0.0/16", 18, "1.16.0.0/16", "1.16.128.0/18", + "1.16.192.0/18", NULL); + + do_test(table, "1.16.0.0/16", 21, "1.16.0.0/16", "1.16.128.0/18", + "1.16.192.0/18", "1.16.64.0/19", "1.16.160.0/19", + "1.16.32.0/20", "1.16.32.0/21", NULL); + + do_test(table, "1.17.0.0/16", 20, NULL); + + do_test(table, "128.0.0.0/8", 16, NULL); + + do_test(table, "16.0.0.0/8", 16, "16.0.0.0/16", NULL); + + do_test(table, "0.0.0.0/3", 21, "1.16.0.0/16", "1.16.128.0/18", + "1.16.192.0/18", "1.16.64.0/19", "1.16.160.0/19", + "1.16.32.0/20", "1.16.32.0/21", "16.0.0.0/16", NULL); +} + +int main(void) +{ + test_range_lookup(); +} diff --git a/tests/bgpd/test_bgp_table.py b/tests/bgpd/test_bgp_table.py new file mode 100644 index 0000000000..4423530fe0 --- /dev/null +++ b/tests/bgpd/test_bgp_table.py @@ -0,0 +1,7 @@ +import frrtest + +class TestTable(frrtest.TestMultiOut): + program = './test_bgp_table' + +for i in range(6): + TestTable.onesimple('Checks successfull') diff --git a/tests/lib/test_srcdest_table.c b/tests/lib/test_srcdest_table.c index 04e85435d1..53180564bd 100644 --- a/tests/lib/test_srcdest_table.c +++ b/tests/lib/test_srcdest_table.c @@ -228,7 +228,8 @@ static void test_dump(struct test_state *test) } static void test_failed(struct test_state *test, const char *message, - struct prefix_ipv6 *dst_p, struct prefix_ipv6 *src_p) + const struct prefix_ipv6 *dst_p, + const struct prefix_ipv6 *src_p) { char *route_id = format_srcdest(dst_p, src_p); @@ -250,7 +251,7 @@ static void test_state_verify(struct test_state *test) /* Verify that there are no elements in the table which have never * been added */ for (rn = route_top(test->table); rn; rn = srcdest_route_next(rn)) { - struct prefix_ipv6 *dst_p, *src_p; + const struct prefix_ipv6 *dst_p, *src_p; /* While we are iterating, we hold a lock on the current * route_node, @@ -288,10 +289,10 @@ static void test_state_verify(struct test_state *test) expected_lock++; if (rn->lock != expected_lock) { - struct prefix_ipv6 *dst_p, *src_p; + const struct prefix_ipv6 *dst_p, *src_p; srcdest_rnode_prefixes( - rn, (struct prefix **)&dst_p, - (struct prefix **)&src_p); + rn, (const struct prefix **)&dst_p, + (const struct prefix **)&src_p); test_failed( test, @@ -305,8 +306,8 @@ static void test_state_verify(struct test_state *test) assert(rn->info == (void *)0xdeadbeef); - srcdest_rnode_prefixes(rn, (struct prefix **)&dst_p, - (struct prefix **)&src_p); + srcdest_rnode_prefixes(rn, (const struct prefix **)&dst_p, + (const struct prefix **)&src_p); memcpy(&hash_entry[0], dst_p, sizeof(*dst_p)); if (src_p) memcpy(&hash_entry[1], src_p, sizeof(*src_p)); @@ -377,7 +378,7 @@ static void test_state_del_one_route(struct test_state *test, struct prng *prng) which_route = prng_rand(prng) % test->log->count; struct route_node *rn; - struct prefix *dst_p, *src_p; + const struct prefix *dst_p, *src_p; struct prefix_ipv6 dst6_p, src6_p; for (rn = route_top(test->table); rn; rn = srcdest_route_next(rn)) { diff --git a/zebra/connected.c b/zebra/connected.c index a9a4dfe08f..8869d34fd6 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -564,7 +564,7 @@ void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address, if (broad) { memset(&d, 0, sizeof(struct prefix)); d.family = AF_INET6; - IPV6_ADDR_COPY(&d.u.prefix, broad); + IPV6_ADDR_COPY(&d.u.prefix6, broad); d.prefixlen = prefixlen; ifc = connected_check_ptp(ifp, &p, &d); } else diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index d9c6631845..8703b01319 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -390,8 +390,8 @@ void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, } } -int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type, void *data, - unsigned int alen) +int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type, + const void *data, unsigned int alen) { int len; struct rtattr *rta; @@ -415,8 +415,8 @@ int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type, void *data, return 0; } -int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type, void *data, - unsigned int alen) +int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type, + const void *data, unsigned int alen) { unsigned int len; struct rtattr *subrta; @@ -829,9 +829,6 @@ int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), n->nlmsg_seq = ++nl->seq; n->nlmsg_pid = nl->snl.nl_pid; - /* Request an acknowledgement by setting NLM_F_ACK */ - n->nlmsg_flags |= NLM_F_ACK; - if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( "netlink_talk: %s type %s(%u), len=%d seq=%u flags 0x%x", @@ -942,12 +939,20 @@ void kernel_init(struct zebra_ns *zns) snprintf(zns->netlink.name, sizeof(zns->netlink.name), "netlink-listen (NS %u)", zns->ns_id); zns->netlink.sock = -1; - netlink_socket(&zns->netlink, groups, zns->ns_id); + if (netlink_socket(&zns->netlink, groups, zns->ns_id) < 0) { + zlog_err("Failure to create %s socket", + zns->netlink.name); + exit(-1); + } snprintf(zns->netlink_cmd.name, sizeof(zns->netlink_cmd.name), "netlink-cmd (NS %u)", zns->ns_id); zns->netlink_cmd.sock = -1; - netlink_socket(&zns->netlink_cmd, 0, zns->ns_id); + if (netlink_socket(&zns->netlink_cmd, 0, zns->ns_id) < 0) { + zlog_err("Failure to create %s socket", + zns->netlink_cmd.name); + exit(-1); + } /* * SOL_NETLINK is not available on all platforms yet @@ -969,23 +974,24 @@ void kernel_init(struct zebra_ns *zns) #endif /* Register kernel socket. */ - if (zns->netlink.sock > 0) { - /* Only want non-blocking on the netlink event socket */ - if (fcntl(zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0) - zlog_err("Can't set %s socket flags: %s", - zns->netlink.name, safe_strerror(errno)); - - /* Set receive buffer size if it's set from command line */ - if (nl_rcvbufsize) - netlink_recvbuf(&zns->netlink, nl_rcvbufsize); - - netlink_install_filter(zns->netlink.sock, - zns->netlink_cmd.snl.nl_pid); - zns->t_netlink = NULL; - - thread_add_read(zebrad.master, kernel_read, zns, - zns->netlink.sock, &zns->t_netlink); - } + if (fcntl(zns->netlink.sock, F_SETFL, O_NONBLOCK) < 0) + zlog_err("Can't set %s socket error: %s(%d)", + zns->netlink.name, safe_strerror(errno), errno); + + if (fcntl(zns->netlink_cmd.sock, F_SETFL, O_NONBLOCK) < 0) + zlog_err("Can't set %s socket error: %s(%d)", + zns->netlink_cmd.name, safe_strerror(errno), errno); + + /* Set receive buffer size if it's set from command line */ + if (nl_rcvbufsize) + netlink_recvbuf(&zns->netlink, nl_rcvbufsize); + + netlink_install_filter(zns->netlink.sock, + zns->netlink_cmd.snl.nl_pid); + zns->t_netlink = NULL; + + thread_add_read(zebrad.master, kernel_read, zns, + zns->netlink.sock, &zns->t_netlink); rt_netlink_init(); } diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index 3b4048ff69..80bb876e0b 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -29,9 +29,9 @@ extern void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, int len); extern int addattr_l(struct nlmsghdr *n, unsigned int maxlen, int type, - void *data, unsigned int alen); + const void *data, unsigned int alen); extern int rta_addattr_l(struct rtattr *rta, unsigned int maxlen, int type, - void *data, unsigned int alen); + const void *data, unsigned int alen); extern int addattr16(struct nlmsghdr *n, unsigned int maxlen, int type, uint16_t data); extern int addattr32(struct nlmsghdr *n, unsigned int maxlen, int type, diff --git a/zebra/redistribute.c b/zebra/redistribute.c index be53b74b3f..69c0ebb7ec 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -113,7 +113,7 @@ static void zebra_redistribute(struct zserv *client, int type, for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) RNODE_FOREACH_RE (rn, newre) { - struct prefix *dst_p, *src_p; + const struct prefix *dst_p, *src_p; char buf[PREFIX_STRLEN]; srcdest_rnode_prefixes(rn, &dst_p, &src_p); @@ -147,7 +147,7 @@ static void zebra_redistribute(struct zserv *client, int type, /* Either advertise a route for redistribution to registered clients or */ /* withdraw redistribution if add cannot be done for client */ -void redistribute_update(struct prefix *p, struct prefix *src_p, +void redistribute_update(const struct prefix *p, const struct prefix *src_p, struct route_entry *re, struct route_entry *prev_re) { struct listnode *node, *nnode; @@ -216,7 +216,7 @@ void redistribute_update(struct prefix *p, struct prefix *src_p, } } -void redistribute_delete(struct prefix *p, struct prefix *src_p, +void redistribute_delete(const struct prefix *p, const struct prefix *src_p, struct route_entry *re) { struct listnode *node, *nnode; @@ -274,7 +274,7 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS) __func__, zebra_route_string(client->proto), afi, zebra_route_string(type), zvrf_id(zvrf), instance); - if (afi == 0 || afi > AFI_MAX) { + if (afi == 0 || afi >= AFI_MAX) { zlog_warn("%s: Specified afi %d does not exist", __PRETTY_FUNCTION__, afi); return; @@ -320,7 +320,7 @@ void zebra_redistribute_delete(ZAPI_HANDLER_ARGS) STREAM_GETC(msg, type); STREAM_GETW(msg, instance); - if (afi == 0 || afi > AFI_MAX) { + if (afi == 0 || afi >= AFI_MAX) { zlog_warn("%s: Specified afi %d does not exist", __PRETTY_FUNCTION__, afi); return; diff --git a/zebra/redistribute.h b/zebra/redistribute.h index 9b4820acd4..a0fbd13cf9 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -36,9 +36,11 @@ extern void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS); extern void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS); /* ----------------- */ -extern void redistribute_update(struct prefix *, struct prefix *, +extern void redistribute_update(const struct prefix *p, + const struct prefix *src_p, struct route_entry *, struct route_entry *); -extern void redistribute_delete(struct prefix *, struct prefix *, +extern void redistribute_delete(const struct prefix *p, + const struct prefix *src_p, struct route_entry *); extern void zebra_interface_up_update(struct interface *); diff --git a/zebra/rib.h b/zebra/rib.h index 209f085ed1..6509cdaba7 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -289,7 +289,7 @@ extern int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate, extern int is_zebra_valid_kernel_table(uint32_t table_id); extern int is_zebra_main_routing_table(uint32_t table_id); -extern int zebra_check_addr(struct prefix *p); +extern int zebra_check_addr(const struct prefix *p); extern void rib_addnode(struct route_node *rn, struct route_entry *re, int process); diff --git a/zebra/rt.h b/zebra/rt.h index ad1fe9a1f5..57e62e4f6e 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -67,8 +67,8 @@ enum dp_req_result { * a re-add. */ extern enum dp_req_result kernel_route_rib(struct route_node *rn, - struct prefix *p, - struct prefix *src_p, + const struct prefix *p, + const struct prefix *src_p, struct route_entry *old, struct route_entry *new); @@ -77,7 +77,8 @@ extern enum dp_req_result kernel_route_rib(struct route_node *rn, * so let's separate it out and allow the result to * be passed back up. */ -extern void kernel_route_rib_pass_fail(struct route_node *rn, struct prefix *p, +extern void kernel_route_rib_pass_fail(struct route_node *rn, + const struct prefix *p, struct route_entry *re, enum dp_results res); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 9033491549..485abc3f12 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -483,7 +483,9 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, memcpy(&nh.gate, gate, sz); if (index) { - ifp = if_lookup_by_index(index, VRF_UNKNOWN); + ifp = if_lookup_by_index_per_ns( + zebra_ns_lookup(ns_id), + index); if (ifp) nh_vrf_id = ifp->vrf_id; } @@ -526,8 +528,9 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, * using the last one looked * up right now */ - ifp = if_lookup_by_index(index, - VRF_UNKNOWN); + ifp = if_lookup_by_index_per_ns( + zebra_ns_lookup(ns_id), + index); if (ifp) nh_vrf_id = ifp->vrf_id; else { @@ -1287,8 +1290,8 @@ _netlink_mpls_build_multipath(const char *routedesc, zebra_nhlfe_t *nhlfe, * @param zvrf: The vrf we are in * @param tableid: The table we are working on */ -static void _netlink_route_debug(int cmd, struct prefix *p, - int family, struct zebra_vrf *zvrf, +static void _netlink_route_debug(int cmd, const struct prefix *p, + int family, vrf_id_t vrfid, uint32_t tableid) { if (IS_ZEBRA_DEBUG_KERNEL) { @@ -1297,7 +1300,7 @@ static void _netlink_route_debug(int cmd, struct prefix *p, "netlink_route_multipath(): %s %s vrf %u(%u)", nl_msg_type_to_str(cmd), prefix2str(p, buf, sizeof(buf)), - zvrf_id(zvrf), tableid); + vrfid, tableid); } } @@ -1340,8 +1343,9 @@ static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, /* Routing table change via netlink interface. */ /* Update flag indicates whether this is a "replace" or not. */ -static int netlink_route_multipath(int cmd, struct prefix *p, - struct prefix *src_p, struct route_entry *re, +static int netlink_route_multipath(int cmd, const struct prefix *p, + const struct prefix *src_p, + struct route_entry *re, int update) { int bytelen; @@ -1416,7 +1420,7 @@ static int netlink_route_multipath(int cmd, struct prefix *p, addattr32(&req.n, sizeof req, RTA_TABLE, re->table); } - _netlink_route_debug(cmd, p, family, zvrf, re->table); + _netlink_route_debug(cmd, p, family, zvrf_id(zvrf), re->table); /* * If we are not updating the route and we have received @@ -1699,8 +1703,8 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in) } enum dp_req_result kernel_route_rib(struct route_node *rn, - struct prefix *p, - struct prefix *src_p, + const struct prefix *p, + const struct prefix *src_p, struct route_entry *old, struct route_entry *new) { diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index 441f518e91..cba0376300 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -386,8 +386,8 @@ static int kernel_rtm(int cmd, struct prefix *p, struct route_entry *re) } enum dp_req_result kernel_route_rib(struct route_node *rn, - struct prefix *p, - struct prefix *src_p, + const struct prefix *p, + const struct prefix *src_p, struct route_entry *old, struct route_entry *new) { diff --git a/zebra/rtadv.c b/zebra/rtadv.c index dc918b1a9b..49ffcdd490 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -518,7 +518,7 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len, /* Create entry for neighbor if not known. */ p.family = AF_INET6; - IPV6_ADDR_COPY(&p.u.prefix, &addr->sin6_addr); + IPV6_ADDR_COPY(&p.u.prefix6, &addr->sin6_addr); p.prefixlen = IPV6_MAX_PREFIXLEN; if (!nbr_connected_check(ifp, &p)) diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 6e0d86d668..c16fa70857 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -448,7 +448,7 @@ void nbr_connected_add_ipv6(struct interface *ifp, struct in6_addr *address) struct prefix p; p.family = AF_INET6; - IPV6_ADDR_COPY(&p.u.prefix, address); + IPV6_ADDR_COPY(&p.u.prefix6, address); p.prefixlen = IPV6_MAX_PREFIXLEN; ifc = listnode_head(ifp->nbr_connected); @@ -473,7 +473,7 @@ void nbr_connected_delete_ipv6(struct interface *ifp, struct in6_addr *address) struct prefix p; p.family = AF_INET6; - IPV6_ADDR_COPY(&p.u.prefix, address); + IPV6_ADDR_COPY(&p.u.prefix6, address); p.prefixlen = IPV6_MAX_PREFIXLEN; ifc = nbr_connected_check(ifp, &p); @@ -514,8 +514,9 @@ int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp) return zserv_send_message(client, s); } -int zsend_redistribute_route(int cmd, struct zserv *client, struct prefix *p, - struct prefix *src_p, struct route_entry *re) +int zsend_redistribute_route(int cmd, struct zserv *client, + const struct prefix *p, + const struct prefix *src_p, struct route_entry *re) { struct zapi_route api; struct zapi_nexthop *api_nh; @@ -677,22 +678,28 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client, return zserv_send_message(client, s); } -int zsend_route_notify_owner(struct route_entry *re, struct prefix *p, - enum zapi_route_notify_owner note) +/* + * Common utility send route notification, called from a path using a + * route_entry and from a path using a dataplane context. + */ +static int route_notify_internal(const struct prefix *p, int type, + uint16_t instance, vrf_id_t vrf_id, + uint32_t table_id, + enum zapi_route_notify_owner note) { struct zserv *client; struct stream *s; uint8_t blen; - client = zserv_find_client(re->type, re->instance); + client = zserv_find_client(type, instance); if (!client || !client->notify_owner) { if (IS_ZEBRA_DEBUG_PACKET) { char buff[PREFIX_STRLEN]; zlog_debug( "Not Notifying Owner: %u about prefix %s(%u) %d vrf: %u", - re->type, prefix2str(p, buff, sizeof(buff)), - re->table, note, re->vrf_id); + type, prefix2str(p, buff, sizeof(buff)), + table_id, note, vrf_id); } return 0; } @@ -701,14 +708,14 @@ int zsend_route_notify_owner(struct route_entry *re, struct prefix *p, char buff[PREFIX_STRLEN]; zlog_debug("Notifying Owner: %u about prefix %s(%u) %d vrf: %u", - re->type, prefix2str(p, buff, sizeof(buff)), - re->table, note, re->vrf_id); + type, prefix2str(p, buff, sizeof(buff)), + table_id, note, vrf_id); } s = stream_new(ZEBRA_MAX_PACKET_SIZ); stream_reset(s); - zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, re->vrf_id); + zclient_create_header(s, ZEBRA_ROUTE_NOTIFY_OWNER, vrf_id); stream_put(s, ¬e, sizeof(note)); @@ -718,13 +725,20 @@ int zsend_route_notify_owner(struct route_entry *re, struct prefix *p, stream_putc(s, p->prefixlen); stream_put(s, &p->u.prefix, blen); - stream_putl(s, re->table); + stream_putl(s, table_id); stream_putw_at(s, 0, stream_get_endp(s)); return zserv_send_message(client, s); } +int zsend_route_notify_owner(struct route_entry *re, const struct prefix *p, + enum zapi_route_notify_owner note) +{ + return (route_notify_internal(p, re->type, re->instance, re->vrf_id, + re->table, note)); +} + void zsend_rule_notify_owner(struct zebra_pbr_rule *rule, enum zapi_rule_notify_owner note) { @@ -2820,7 +2834,9 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS) STREAM_GETL(s, ifindex); if (ifindex) { - zpr.ifp = if_lookup_by_index(ifindex, VRF_UNKNOWN); + zpr.ifp = if_lookup_by_index_per_ns( + zvrf->zns, + ifindex); if (!zpr.ifp) { zlog_debug("Failed to lookup ifindex: %u", ifindex); diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h index f27897580a..8289e33c6a 100644 --- a/zebra/zapi_msg.h +++ b/zebra/zapi_msg.h @@ -56,7 +56,8 @@ extern void nbr_connected_delete_ipv6(struct interface *ifp, extern int zsend_interface_update(int cmd, struct zserv *client, struct interface *ifp); extern int zsend_redistribute_route(int cmd, struct zserv *zclient, - struct prefix *p, struct prefix *src_p, + const struct prefix *p, + const struct prefix *src_p, struct route_entry *re); extern int zsend_router_id_update(struct zserv *zclient, struct prefix *p, vrf_id_t vrf_id); @@ -65,7 +66,8 @@ extern int zsend_interface_vrf_update(struct zserv *zclient, extern int zsend_interface_link_params(struct zserv *zclient, struct interface *ifp); extern int zsend_pw_update(struct zserv *client, struct zebra_pw *pw); -extern int zsend_route_notify_owner(struct route_entry *re, struct prefix *p, +extern int zsend_route_notify_owner(struct route_entry *re, + const struct prefix *p, enum zapi_route_notify_owner note); extern void zsend_rule_notify_owner(struct zebra_pbr_rule *rule, diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index fe0837a63a..cfe208d35b 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -38,6 +38,7 @@ #include "zebra/rib.h" #include "zebra/rt.h" +#include "zebra/interface.h" #include "zebra/zserv.h" #include "zebra/redistribute.h" #include "zebra/debug.h" @@ -704,6 +705,7 @@ static int nhlfe_nexthop_active(zebra_nhlfe_t *nhlfe) { struct nexthop *nexthop; struct interface *ifp; + struct zebra_ns *zns; nexthop = nhlfe->nexthop; if (!nexthop) // unexpected @@ -721,7 +723,8 @@ static int nhlfe_nexthop_active(zebra_nhlfe_t *nhlfe) * which will not be in the default * VRF. So let's look in all of them */ - ifp = if_lookup_by_index(nexthop->ifindex, VRF_UNKNOWN); + zns = zebra_ns_lookup(NS_DEFAULT); + ifp = if_lookup_by_index_per_ns(zns, nexthop->ifindex); if (ifp && if_is_operative(ifp)) SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); else @@ -2752,10 +2755,13 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf, switch (nexthop->type) { case NEXTHOP_TYPE_IFINDEX: { + struct zebra_ns *zns; struct interface *ifp; - ifp = if_lookup_by_index( - nexthop->ifindex, VRF_UNKNOWN); + zns = zebra_ns_lookup(NS_DEFAULT); + ifp = if_lookup_by_index_per_ns( + zns, + nexthop->ifindex); vty_out(vty, "%15s", ifp->name); break; } diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c index d0ea661403..60b72298a1 100644 --- a/zebra/zebra_netns_notify.c +++ b/zebra/zebra_netns_notify.c @@ -80,6 +80,8 @@ static void zebra_ns_notify_create_context_from_entry_name(const char *name) ns_id = zebra_ns_id_get(netnspath); if (zserv_privs.change(ZPRIVS_LOWER)) zlog_err("Can't lower privileges"); + if (ns_id == NS_UNKNOWN) + return; ns_id_external = ns_map_nsid_with_external(ns_id, true); /* if VRF with NS ID already present */ vrf = vrf_lookup_by_id((vrf_id_t)ns_id_external); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 8935956b25..9bf6bfa22f 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -156,7 +156,7 @@ int is_zebra_main_routing_table(uint32_t table_id) return 0; } -int zebra_check_addr(struct prefix *p) +int zebra_check_addr(const struct prefix *p) { if (p->family == AF_INET) { uint32_t addr; @@ -325,7 +325,7 @@ struct nexthop *route_entry_nexthop_blackhole_add(struct route_entry *re, return nexthop; } -static void nexthop_set_resolved(afi_t afi, struct nexthop *newhop, +static void nexthop_set_resolved(afi_t afi, const struct nexthop *newhop, struct nexthop *nexthop) { struct nexthop *resolved_hop; @@ -843,7 +843,7 @@ static unsigned nexthop_active_check(struct route_node *rn, route_map_result_t ret = RMAP_MATCH; int family; char buf[SRCDEST2STR_BUFFER]; - struct prefix *p, *src_p; + const struct prefix *p, *src_p; srcdest_rnode_prefixes(rn, &p, &src_p); if (rn->p.family == AF_INET) @@ -1012,7 +1012,7 @@ int zebra_rib_labeled_unicast(struct route_entry *re) return 1; } -void kernel_route_rib_pass_fail(struct route_node *rn, struct prefix *p, +void kernel_route_rib_pass_fail(struct route_node *rn, const struct prefix *p, struct route_entry *re, enum dp_results res) { @@ -1085,7 +1085,7 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re, { struct nexthop *nexthop; rib_table_info_t *info = srcdest_rnode_table_info(rn); - struct prefix *p, *src_p; + const struct prefix *p, *src_p; struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id); srcdest_rnode_prefixes(rn, &p, &src_p); @@ -1143,7 +1143,7 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re) { struct nexthop *nexthop; rib_table_info_t *info = srcdest_rnode_table_info(rn); - struct prefix *p, *src_p; + const struct prefix *p, *src_p; struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id); srcdest_rnode_prefixes(rn, &p, &src_p); @@ -1194,7 +1194,8 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re) } if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) { - struct prefix *p, *src_p; + const struct prefix *p, *src_p; + srcdest_rnode_prefixes(rn, &p, &src_p); redistribute_delete(p, src_p, re); @@ -1536,7 +1537,8 @@ static void rib_process(struct route_node *rn) char buf[SRCDEST2STR_BUFFER]; rib_dest_t *dest; struct zebra_vrf *zvrf = NULL; - struct prefix *p, *src_p; + const struct prefix *p, *src_p; + srcdest_rnode_prefixes(rn, &p, &src_p); vrf_id_t vrf_id = VRF_UNKNOWN; diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index ce51f54a65..bf6718164f 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -1337,7 +1337,8 @@ void zebra_route_map_write_delay_timer(struct vty *vty) } route_map_result_t zebra_route_map_check(int family, int rib_type, - uint8_t instance, struct prefix *p, + uint8_t instance, + const struct prefix *p, struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag) { @@ -1358,7 +1359,8 @@ route_map_result_t zebra_route_map_check(int family, int rib_type, rmap = route_map_lookup_by_name( proto_rm[family][ZEBRA_ROUTE_MAX]); if (rmap) { - ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); + ret = route_map_apply(rmap, (struct prefix *)p, + RMAP_ZEBRA, &nh_obj); } return (ret); diff --git a/zebra/zebra_routemap.h b/zebra/zebra_routemap.h index 20d425a2bc..688c8b7203 100644 --- a/zebra/zebra_routemap.h +++ b/zebra/zebra_routemap.h @@ -40,7 +40,7 @@ zebra_import_table_route_map_check(int family, int rib_type, uint8_t instance, const char *rmap_name); extern route_map_result_t zebra_route_map_check(int family, int rib_type, uint8_t instance, - struct prefix *p, struct nexthop *nexthop, + const struct prefix *p, struct nexthop *nexthop, vrf_id_t vrf_id, route_tag_t tag); extern route_map_result_t zebra_nht_route_map_check(int family, int client_proto, struct prefix *p, diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index 67b2954f35..76346f6b66 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -37,8 +37,9 @@ #include "zebra/zebra_memory.h" /* Install static route into rib. */ -void static_install_route(afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, struct static_route *si) +void static_install_route(afi_t afi, safi_t safi, const struct prefix *p, + const struct prefix_ipv6 *src_p, + struct static_route *si) { struct route_entry *re; struct route_node *rn; @@ -292,8 +293,9 @@ static int static_nexthop_same(struct nexthop *nexthop, struct static_route *si) } /* Uninstall static route from RIB. */ -void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, struct static_route *si) +void static_uninstall_route(afi_t afi, safi_t safi, const struct prefix *p, + const struct prefix_ipv6 *src_p, + struct static_route *si) { struct route_node *rn; struct route_entry *re; @@ -610,7 +612,7 @@ static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi, struct route_table *stable; struct route_node *rn; struct static_route *si; - struct prefix *p, *src_pp; + const struct prefix *p, *src_pp; struct prefix_ipv6 *src_p; struct vrf *vrf; diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h index 7dc47d6190..0be434fff2 100644 --- a/zebra/zebra_static.h +++ b/zebra/zebra_static.h @@ -82,11 +82,12 @@ struct static_route { uint32_t table_id; }; -extern void static_install_route(afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, +extern void static_install_route(afi_t afi, safi_t safi, const struct prefix *p, + const struct prefix_ipv6 *src_p, struct static_route *si); -extern void static_uninstall_route(afi_t afi, safi_t safi, struct prefix *p, - struct prefix_ipv6 *src_p, +extern void static_uninstall_route(afi_t afi, safi_t safi, + const struct prefix *p, + const struct prefix_ipv6 *src_p, struct static_route *si); extern int static_add_route(afi_t, safi_t safi, uint8_t type, struct prefix *p, diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index d443f725b0..3c21c3c1e5 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -134,14 +134,6 @@ static int zebra_vrf_enable(struct vrf *vrf) zvrf->import_check_table[afi] = table; } - static_fixup_vrf_ids(zvrf); - - /* - * We may have static routes that are now possible to - * insert into the appropriate tables - */ - static_config_install_delayed_routes(zvrf); - /* Kick off any VxLAN-EVPN processing. */ zebra_vxlan_vrf_enable(zvrf); diff --git a/zebra/zserv.c b/zebra/zserv.c index b297f75ed9..b08da9cebd 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -69,7 +69,7 @@ extern struct zebra_privs_t zserv_privs; * Client thread events. * * These are used almost exclusively by client threads to drive their own event - * loops. The only exception is in zebra_client_create(), which pushes an + * loops. The only exception is in zserv_client_create(), which pushes an * initial ZSERV_CLIENT_READ event to start the API handler loop. */ enum zserv_client_event { @@ -618,14 +618,6 @@ static int zserv_handle_client_close(struct thread *thread) { struct zserv *client = THREAD_ARG(thread); - /* - * Ensure these have been nulled. This does not equate to the - * associated task(s) being scheduled or unscheduled on the client - * pthread's threadmaster. - */ - assert(!client->t_read); - assert(!client->t_write); - /* synchronously stop thread */ frr_pthread_stop(client->pthread, NULL); @@ -1033,7 +1025,7 @@ void zserv_read_file(char *input) struct zserv *client = NULL; struct thread t; - zebra_client_create(-1); + zserv_client_create(-1); frr_pthread_stop(client->pthread, NULL); frr_pthread_destroy(client->pthread); |
