diff options
146 files changed, 1942 insertions, 1217 deletions
diff --git a/Makefile.am b/Makefile.am index c56a551aa5..7f7d7d6236 100644 --- a/Makefile.am +++ b/Makefile.am @@ -226,8 +226,8 @@ noinst_HEADERS += defaults.h clean-local: clean-python .PHONY: clean-python clean-python: - find -name __pycache__ -o -name .pytest_cache | xargs rm -rf - find -name "*.pyc" -o -name "*_clippy.c" | xargs rm -f + find . -name __pycache__ -o -name .pytest_cache | xargs rm -rf + find . -name "*.pyc" -o -name "*_clippy.c" | xargs rm -f redistclean: $(MAKE) distclean CONFIG_CLEAN_FILES="$(filter-out $(EXTRA_DIST), $(CONFIG_CLEAN_FILES))" diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c index a8698bfce3..79242f5b85 100644 --- a/babeld/babel_interface.c +++ b/babeld/babel_interface.c @@ -1262,7 +1262,7 @@ DEFUN (show_babel_parameters, } void -babel_if_init () +babel_if_init(void) { /* initialize interface list */ hook_register_prio(if_add, 0, babel_if_new_hook); diff --git a/babeld/babeld.c b/babeld/babeld.c index 702c1fbabb..39451b435a 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -307,7 +307,7 @@ babel_initial_noise(void) /* Delete all the added babel routes, make babeld only speak to zebra. */ static void -babel_clean_routing_process() +babel_clean_routing_process(void) { flush_all_routes(); babel_interface_close_all(); diff --git a/babeld/message.c b/babeld/message.c index f85a08ac3a..794b6e9976 100644 --- a/babeld/message.c +++ b/babeld/message.c @@ -1430,7 +1430,7 @@ send_wildcard_retraction(struct interface *ifp) } void -update_myseqno() +update_myseqno(void) { myseqno = seqno_plus(myseqno, 1); } diff --git a/babeld/neighbour.c b/babeld/neighbour.c index 83f05bb5cf..d962a0961c 100644 --- a/babeld/neighbour.c +++ b/babeld/neighbour.c @@ -234,7 +234,7 @@ neighbour_txcost(struct neighbour *neigh) } unsigned -check_neighbours() +check_neighbours(void) { struct neighbour *neigh; int changed, rc; diff --git a/babeld/resend.c b/babeld/resend.c index 8949075f67..f08897fbd1 100644 --- a/babeld/resend.c +++ b/babeld/resend.c @@ -238,7 +238,7 @@ satisfy_request(const unsigned char *prefix, unsigned char plen, } void -expire_resend() +expire_resend(void) { struct resend *current, *previous; int recompute = 0; @@ -267,7 +267,7 @@ expire_resend() } void -recompute_resend_time() +recompute_resend_time(void) { struct resend *request; struct timeval resend = {0, 0}; @@ -286,7 +286,7 @@ recompute_resend_time() } void -do_resend() +do_resend(void) { struct resend *resend; diff --git a/babeld/route.c b/babeld/route.c index 76f038cda5..ab104aa2b1 100644 --- a/babeld/route.c +++ b/babeld/route.c @@ -248,7 +248,7 @@ flush_route(struct babel_route *route) } void -flush_all_routes() +flush_all_routes(void) { int i; diff --git a/babeld/source.c b/babeld/source.c index ed165b41b4..2c303b624f 100644 --- a/babeld/source.c +++ b/babeld/source.c @@ -135,7 +135,7 @@ update_source(struct source *src, } void -expire_sources() +expire_sources(void) { struct source *src; diff --git a/babeld/util.c b/babeld/util.c index 880cda2fce..c6606e4f0e 100644 --- a/babeld/util.c +++ b/babeld/util.c @@ -441,7 +441,7 @@ uchar_to_in6addr(struct in6_addr *dest, const unsigned char *src) } int -daemonise() +daemonise(void) { int rc; diff --git a/babeld/xroute.c b/babeld/xroute.c index 88e9479e4b..61ea5a1ac1 100644 --- a/babeld/xroute.c +++ b/babeld/xroute.c @@ -169,7 +169,7 @@ add_xroute(unsigned char prefix[16], unsigned char plen, /* Returns an overestimate of the number of xroutes. */ int -xroutes_estimate() +xroutes_estimate(void) { return numxroutes; } diff --git a/bgpd/bgp_clist.h b/bgpd/bgp_clist.h index 9cf8a14a6a..75a31611ba 100644 --- a/bgpd/bgp_clist.h +++ b/bgpd/bgp_clist.h @@ -173,7 +173,7 @@ lcommunity_list_match_delete(struct lcommunity *lcom, static inline uint32_t bgp_clist_hash_key(char *name) { - return jhash(name, sizeof(name), 0xdeadbeaf); + return jhash(name, strlen(name), 0xdeadbeaf); } #endif /* _QUAGGA_BGP_CLIST_H */ diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 7f6d34808f..c74d7829bd 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -887,17 +887,26 @@ static void add_mac_mobility_to_attr(uint32_t seq_num, struct attr *attr) /* Install EVPN route into zebra. */ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p, - struct in_addr remote_vtep_ip, uint8_t flags, - uint32_t seq) + struct prefix_evpn *p, struct bgp_path_info *pi) { int ret; + uint8_t flags; - if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) - ret = bgp_zebra_send_remote_macip(bgp, vpn, p, remote_vtep_ip, - 1, flags, seq); - else + if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) { + flags = 0; + if (pi->attr->sticky) + SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); + if (pi->attr->default_gw) + SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); + if (is_evpn_prefix_ipaddr_v6(p) && + pi->attr->router_flag) + SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); + ret = bgp_zebra_send_remote_macip( + bgp, vpn, p, pi->attr->nexthop, 1, flags, + mac_mobility_seqnum(pi->attr)); + } else { ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, 1); + } return ret; } @@ -1121,11 +1130,9 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, { struct bgp_path_info *old_select, *new_select; struct bgp_path_info_pair old_and_new; - struct prefix_evpn *evp; afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; int ret = 0; - uint8_t flags = 0; /* Compute the best path. */ bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new, @@ -1133,7 +1140,6 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, old_select = old_and_new.old; new_select = old_and_new.new; - evp = (struct prefix_evpn *)&rn->p; /* If the best path hasn't changed - see if there is still something to * update * to zebra RIB. @@ -1144,20 +1150,10 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR) && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED) && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) { - if (bgp_zebra_has_route_changed(rn, old_select)) { - if (old_select->attr->sticky) - SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); - if (old_select->attr->default_gw) - SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); - if (is_evpn_prefix_ipaddr_v6(evp) && - old_select->attr->router_flag) - SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); - + if (bgp_zebra_has_route_changed(rn, old_select)) ret = evpn_zebra_install( bgp, vpn, (struct prefix_evpn *)&rn->p, - old_select->attr->nexthop, flags, - mac_mobility_seqnum(old_select->attr)); - } + old_select); UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG); bgp_zebra_clear_route_change_flags(rn); return ret; @@ -1182,18 +1178,9 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, if (new_select && new_select->type == ZEBRA_ROUTE_BGP && new_select->sub_type == BGP_ROUTE_IMPORTED) { - flags = 0; - if (new_select->attr->sticky) - SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); - if (new_select->attr->default_gw) - SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); - if (is_evpn_prefix_ipaddr_v6(evp) && - new_select->attr->router_flag) - SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); - ret = evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p, - new_select->attr->nexthop, flags, - mac_mobility_seqnum(new_select->attr)); + new_select); + /* If an old best existed and it was a "local" route, the only * reason * it would be supplanted is due to MAC mobility procedures. So, @@ -1698,6 +1685,27 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, return route_change; } +static void evpn_zebra_reinstall_best_route(struct bgp *bgp, + struct bgpevpn *vpn, struct bgp_node *rn) +{ + struct bgp_path_info *tmp_ri; + struct bgp_path_info *curr_select = NULL; + + for (tmp_ri = bgp_node_get_bgp_path_info(rn); + tmp_ri; tmp_ri = tmp_ri->next) { + if (CHECK_FLAG(tmp_ri->flags, BGP_PATH_SELECTED)) { + curr_select = tmp_ri; + break; + } + } + + if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP + && curr_select->sub_type == BGP_ROUTE_IMPORTED) + evpn_zebra_install(bgp, vpn, + (struct prefix_evpn *)&rn->p, + curr_select); +} + /* * If the local route was not selected evict it and tell zebra to re-add * the best remote dest. @@ -1717,9 +1725,6 @@ static void evpn_cleanup_local_non_best_route(struct bgp *bgp, struct bgp_node *rn, struct bgp_path_info *local_pi) { - struct bgp_path_info *tmp_pi; - struct bgp_path_info *curr_select = NULL; - uint8_t flags = 0; char buf[PREFIX_STRLEN]; /* local path was not picked as the winner; kick it out */ @@ -1731,24 +1736,7 @@ static void evpn_cleanup_local_non_best_route(struct bgp *bgp, bgp_path_info_reap(rn, local_pi); /* tell zebra to re-add the best remote path */ - for (tmp_pi = bgp_node_get_bgp_path_info(rn); - tmp_pi; tmp_pi = tmp_pi->next) { - if (CHECK_FLAG(tmp_pi->flags, BGP_PATH_SELECTED)) { - curr_select = tmp_pi; - break; - } - } - if (curr_select && - curr_select->type == ZEBRA_ROUTE_BGP - && curr_select->sub_type == BGP_ROUTE_IMPORTED) { - if (curr_select->attr->sticky) - SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY); - if (curr_select->attr->default_gw) - SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); - evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p, - curr_select->attr->nexthop, flags, - mac_mobility_seqnum(curr_select->attr)); - } + evpn_zebra_reinstall_best_route(bgp, vpn, rn); } /* @@ -5324,10 +5312,11 @@ int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp) * Handle del of a local MACIP. */ int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac, - struct ipaddr *ip) + struct ipaddr *ip, int state) { struct bgpevpn *vpn; struct prefix_evpn p; + struct bgp_node *rn; /* Lookup VNI hash - should exist. */ vpn = bgp_evpn_lookup_vni(bgp, vni); @@ -5338,9 +5327,16 @@ int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac, return -1; } - /* Remove EVPN type-2 route and schedule for processing. */ build_evpn_type2_prefix(&p, mac, ip); - delete_evpn_route(bgp, vpn, &p); + if (state == ZEBRA_NEIGH_ACTIVE) { + /* Remove EVPN type-2 route and schedule for processing. */ + delete_evpn_route(bgp, vpn, &p); + } else { + /* Re-instate the current remote best path if any */ + rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p); + if (rn) + evpn_zebra_reinstall_best_route(bgp, vpn, rn); + } return 0; } diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index 8728fdcab7..5c3d4ce3aa 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -129,7 +129,8 @@ extern int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi, struct prefix *p, struct bgp_path_info *ri); extern int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp); extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, - struct ethaddr *mac, struct ipaddr *ip); + struct ethaddr *mac, struct ipaddr *ip, + int state); extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac, struct ipaddr *ip, uint8_t flags, uint32_t seq); diff --git a/bgpd/bgp_keepalives.c b/bgpd/bgp_keepalives.c index 87e3ff2495..910c8a7372 100644 --- a/bgpd/bgp_keepalives.c +++ b/bgpd/bgp_keepalives.c @@ -288,7 +288,7 @@ void bgp_keepalives_off(struct peer *peer) pthread_mutex_unlock(peerhash_mtx); } -void bgp_keepalives_wake() +void bgp_keepalives_wake(void) { pthread_mutex_lock(peerhash_mtx); { diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index e15b8f4ec3..4153da5a64 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -670,8 +670,7 @@ static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen, listener->fd = sock; /* this socket needs a change of ns. record bgp back pointer */ - if (bgp->vrf_id != VRF_DEFAULT && vrf_is_mapped_on_netns( - vrf_lookup_by_id(bgp->vrf_id))) + if (bgp->vrf_id != VRF_DEFAULT && vrf_is_backend_netns()) listener->bgp = bgp; memcpy(&listener->su, sa, salen); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 6bce7261ae..07077dfe1f 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -5081,6 +5081,9 @@ void bgp_static_delete(struct bgp *bgp) bgp_static = bgp_node_get_bgp_static_info( rm); + if (!bgp_static) + continue; + bgp_static_withdraw_safi( bgp, &rm->p, AFI_IP, safi, (struct prefix_rd *)&rn->p); @@ -5257,8 +5260,6 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty, if (!bgp_node_has_bgp_path_info_data(prn)) bgp_node_set_bgp_table_info(prn, bgp_table_init(bgp, afi, safi)); - else - bgp_unlock_node(prn); table = bgp_node_get_bgp_table_info(prn); rn = bgp_node_get(table, &p); diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index ca6bb5ab82..cbbf8b2302 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -65,7 +65,7 @@ /******************** * PUBLIC FUNCTIONS ********************/ -struct bpacket *bpacket_alloc() +struct bpacket *bpacket_alloc(void) { struct bpacket *pkt; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index c6e48cc160..2da19b28db 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -22,6 +22,7 @@ #include "command.h" #include "lib/json.h" +#include "lib/zclient.h" #include "prefix.h" #include "plist.h" #include "buffer.h" @@ -897,7 +898,7 @@ DEFUN_HIDDEN (no_bgp_local_mac, return CMD_WARNING; } - rv = bgp_evpn_local_macip_del(bgp, vni, &mac, &ip); + rv = bgp_evpn_local_macip_del(bgp, vni, &mac, &ip, ZEBRA_NEIGH_ACTIVE); if (rv < 0) { vty_out(vty, "Internal error\n"); return CMD_WARNING; diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 3c4b219466..17de943381 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -2480,6 +2480,7 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient, char buf1[INET6_ADDRSTRLEN]; uint8_t flags = 0; uint32_t seqnum = 0; + int state = 0; memset(&ip, 0, sizeof(ip)); s = zclient->ibuf; @@ -2503,6 +2504,8 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient, if (command == ZEBRA_MACIP_ADD) { flags = stream_getc(s); seqnum = stream_getl(s); + } else { + state = stream_getl(s); } bgp = bgp_lookup_by_vrf_id(vrf_id); @@ -2510,16 +2513,17 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient, return 0; if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%u:Recv MACIP %s flags 0x%x MAC %s IP %s VNI %u seq %u", + zlog_debug("%u:Recv MACIP %s flags 0x%x MAC %s IP %s VNI %u seq %u state %d", vrf_id, (command == ZEBRA_MACIP_ADD) ? "Add" : "Del", flags, prefix_mac2str(&mac, buf, sizeof(buf)), - ipaddr2str(&ip, buf1, sizeof(buf1)), vni, seqnum); + ipaddr2str(&ip, buf1, sizeof(buf1)), vni, seqnum, + state); if (command == ZEBRA_MACIP_ADD) return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, flags, seqnum); else - return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip); + return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip, state); } static void bgp_zebra_process_local_ip_prefix(int cmd, struct zclient *zclient, diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 5b8ceb0541..0b6e05fff6 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -7839,7 +7839,7 @@ static const struct cmd_variable_handler bgp_viewvrf_var_handlers[] = { struct frr_pthread *bgp_pth_io; struct frr_pthread *bgp_pth_ka; -static void bgp_pthreads_init() +static void bgp_pthreads_init(void) { assert(!bgp_pth_io); assert(!bgp_pth_ka); @@ -7858,7 +7858,7 @@ static void bgp_pthreads_init() bgp_pth_ka = frr_pthread_new(&ka, "BGP Keepalives thread", "bgpd_ka"); } -void bgp_pthreads_run() +void bgp_pthreads_run(void) { frr_pthread_run(bgp_pth_io, NULL); frr_pthread_run(bgp_pth_ka, NULL); @@ -7868,7 +7868,7 @@ void bgp_pthreads_run() frr_pthread_wait_running(bgp_pth_ka); } -void bgp_pthreads_finish() +void bgp_pthreads_finish(void) { frr_pthread_stop_all(); frr_pthread_finish(); diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index e4e6760612..05e057f07f 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.c +++ b/bgpd/rfapi/bgp_rfapi_cfg.c @@ -575,7 +575,7 @@ static struct rfapi_l2_group_cfg *rfapi_l2_group_lookup_byname(struct bgp *bgp, return NULL; } -static struct rfapi_l2_group_cfg *rfapi_l2_group_new() +static struct rfapi_l2_group_cfg *rfapi_l2_group_new(void) { struct rfapi_l2_group_cfg *rfg; @@ -1396,7 +1396,7 @@ DEFUN (vnc_export_mode, return CMD_SUCCESS; } -static struct rfapi_rfg_name *rfgn_new() +static struct rfapi_rfg_name *rfgn_new(void) { return XCALLOC(MTYPE_RFAPI_RFG_NAME, sizeof(struct rfapi_rfg_name)); } diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index 904d43c65a..6b37073e0e 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -123,7 +123,7 @@ void rfapiDebugBacktrace(void) * Count remote routes and compare with actively-maintained values. * Abort if they disagree. */ -void rfapiCheckRouteCount() +void rfapiCheckRouteCount(void) { struct bgp *bgp = bgp_get_default(); struct rfapi *h; diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c index 520cc141c0..8e8acbfb91 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -222,7 +222,7 @@ void rfapiRibCheckCounts( assert(t_ri_active + t_ri_deleted + t_ri_pend + offset == alloc_count); } -static struct rfapi_info *rfapi_info_new() +static struct rfapi_info *rfapi_info_new(void) { return XCALLOC(MTYPE_RFAPI_INFO, sizeof(struct rfapi_info)); } diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index 04ddff934d..ea82c254bc 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -4964,7 +4964,7 @@ DEFUN (clear_vrf_all, return vnc_clear_vrf(vty, NULL, arg_vrf, NULL, NULL); } -void rfapi_vty_init() +void rfapi_vty_init(void) { install_element(ENABLE_NODE, &add_vnc_prefix_cost_life_lnh_cmd); install_element(ENABLE_NODE, &add_vnc_prefix_life_cost_lnh_cmd); diff --git a/bgpd/rfp-example/librfp/rfp_example.c b/bgpd/rfp-example/librfp/rfp_example.c index e8f670cf12..060fc76550 100644 --- a/bgpd/rfp-example/librfp/rfp_example.c +++ b/bgpd/rfp-example/librfp/rfp_example.c @@ -107,7 +107,7 @@ DEFUN (rfp_full_table_download, return CMD_SUCCESS; } -static void rfp_vty_install() +static void rfp_vty_install(void) { static int installed = 0; if (installed) /* do this only once */ diff --git a/bgpd/rfp-example/rfptest/rfptest.c b/bgpd/rfp-example/rfptest/rfptest.c index 48df6c0cc7..1036829b89 100644 --- a/bgpd/rfp-example/rfptest/rfptest.c +++ b/bgpd/rfp-example/rfptest/rfptest.c @@ -26,7 +26,7 @@ #include <stdio.h> #include <stdlib.h> #include "rfptest.h" -int main() +int main(void) { printf("Your test code goes here.\n"); exit(1); diff --git a/configure.ac b/configure.ac index 7f08e8e764..afdc6336b0 100755 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ ## AC_PREREQ([2.60]) -AC_INIT([frr], [6.1-dev], [https://github.com/frrouting/frr/issues]) +AC_INIT([frr], [7.1-dev], [https://github.com/frrouting/frr/issues]) PACKAGE_URL="https://frrouting.org/" AC_SUBST([PACKAGE_URL]) PACKAGE_FULLNAME="FRRouting" @@ -346,7 +346,7 @@ AM_CONDITIONAL([STATIC_BIN], [test "x$enable_static_bin" = "xyes"]) dnl $AR and $RANLIB are set by LT_INIT above AC_MSG_CHECKING([whether $AR supports D option]) -if $AR crD conftest.a; then +if $AR crD conftest.a >/dev/null 2>/dev/null; then AC_MSG_RESULT([yes]) dnl ARFLAGS is for automake, AR_FLAGS for libtool m-( ARFLAGS="crD" @@ -360,7 +360,7 @@ AC_SUBST([ARFLAGS]) AC_SUBST([AR_FLAGS]) AC_MSG_CHECKING([whether $RANLIB supports D option]) -if $RANLIB -D conftest.a; then +if $RANLIB -D conftest.a >/dev/null 2>/dev/null; then AC_MSG_RESULT([yes]) RANLIB="$RANLIB -D" else @@ -817,15 +817,17 @@ fi AM_CONDITIONAL([GIT_VERSION], [test "x$with_pkg_git_version" = "xyes"]) AC_CHECK_TOOL([OBJCOPY], [objcopy], [:]) -AC_CACHE_CHECK([for .interp value to use], [frr_cv_interp], [ - frr_cv_interp="" - AC_LINK_IFELSE([AC_LANG_SOURCE([[int main() { return 0; }]])], [ - if $OBJCOPY -j.interp -Obinary conftest conftest.interp; then - frr_cv_interp="`xargs -0 echo < conftest.interp`" - fi - test -f conftest.interp && rm conftest.interp +if test "x${OBJCOPY}" != "x:"; then + AC_CACHE_CHECK([for .interp value to use], [frr_cv_interp], [ + frr_cv_interp="" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main() { return 0; }]])], [ + if $OBJCOPY -j.interp -Obinary conftest conftest.interp; then + frr_cv_interp="`xargs -0 echo < conftest.interp`" + fi + test -f conftest.interp && rm conftest.interp + ]) ]) -]) +fi if test -n "$frr_cv_interp"; then AC_DEFINE_UNQUOTED([INTERP], ["$frr_cv_interp"], [.interp value]) fi @@ -1608,6 +1610,24 @@ AC_CHECK_MEMBER([struct lyd_node.priv], [], [ ]) ], [[#include <libyang/libyang.h>]]) +ac_ld_flag_save="$LDFLAGS" +LDFLAGS="$LDFLAGS $libyang_LIBS" +AC_CHECK_FUNC([ly_register_types], [ + libyang_ext_builtin=true + AC_DEFINE([LIBYANG_EXT_BUILTIN], [1], [have ly_register_types()]) +], [ + libyang_ext_builtin=false + AC_MSG_WARN([===== old libyang (before 0.16.74) detected =====]) + AC_MSG_WARN([The available version of libyang does not seem to support]) + AC_MSG_WARN([built-in YANG extension modules. This will cause "make check"]) + AC_MSG_WARN([to fail and may create installation and version mismatch issues.]) + AC_MSG_WARN([Support for the old mechanism will be removed at some point.]) + AC_MSG_WARN([Please update libyang to version 0.16.74 or newer.]) + AC_MSG_WARN([===== old libyang (before 0.16.74) detected =====]) +]) +AM_CONDITIONAL([LIBYANG_EXT_BUILTIN], [$libyang_ext_builtin]) +LDFLAGS="$ac_ld_flag_save" + dnl --------------- dnl configuration rollbacks dnl --------------- diff --git a/doc/developer/building-libyang.rst b/doc/developer/building-libyang.rst index 005b6ba786..c45c294b75 100644 --- a/doc/developer/building-libyang.rst +++ b/doc/developer/building-libyang.rst @@ -4,6 +4,13 @@ The libyang library can be installed from third-party packages available `here Note: the libyang dev/devel packages need to be installed in addition to the libyang core package in order to build FRR successfully. +.. warning:: + libyang ABI version 0.16.74 or newer will be required to build FRR in the + near future since it significantly eases build and installation + considerations. "0.16-r3" is equal to 0.16.105 and will work, "0.16-r2" + is equal to 0.16.52 and will stop working. The CI artifacts will be + updated shortly. + For example, for CentOS 7.x: .. code-block:: shell @@ -21,6 +28,14 @@ or Ubuntu 18.04: sudo apt install libpcre3-dev sudo dpkg -i libyang-dev_0.16.46_amd64.deb libyang_0.16.46_amd64.deb +.. note:: + For Debian-based systems, the official libyang package requires recent + versions of swig (3.0.12) and debhelper (11) which are only available in + Debian buster (10). However, libyang packages built on Debian buster can + be installed on both Debian jessie (8) and Debian stretch (9), as well as + various Ubuntu systems. The python3-yang package will not work, but the + other packages (libyang-dev is the one needed for FRR) will. + Alternatively, libyang can be built and installed manually by following the steps below: diff --git a/doc/developer/zebra.rst b/doc/developer/zebra.rst index f771d48235..74a8605bf2 100644 --- a/doc/developer/zebra.rst +++ b/doc/developer/zebra.rst @@ -241,7 +241,7 @@ Zebra Protocol Commands +------------------------------------+-------+ | ZEBRA_INTERFACE_DISABLE_RADV | 42 | +------------------------------------+-------+ -| ZEBRA_IPV3_NEXTHOP_LOOKUP_MRIB | 44 | +| ZEBRA_IPV3_NEXTHOP_LOOKUP_MRIB | 43 | +------------------------------------+-------+ | ZEBRA_INTERFACE_LINK_PARAMS | 44 | +------------------------------------+-------+ @@ -279,9 +279,9 @@ Zebra Protocol Commands +------------------------------------+-------+ | ZEBRA_VNI_DEL | 61 | +------------------------------------+-------+ -| ZEBRA_L2VNI_ADD | 63 | +| ZEBRA_L3VNI_ADD | 62 | +------------------------------------+-------+ -| ZEBRA_L2VNI_DEL | 64 | +| ZEBRA_L3VNI_DEL | 63 | +------------------------------------+-------+ | ZEBRA_REMOTE_VTEP_ADD | 64 | +------------------------------------+-------+ diff --git a/doc/user/installation.rst b/doc/user/installation.rst index ebca53ea32..4e1582ccd8 100644 --- a/doc/user/installation.rst +++ b/doc/user/installation.rst @@ -335,6 +335,9 @@ options to the configuration script. Look for libyang plugins in `dir` [`prefix`/lib/frr/libyang_plugins]. Note that the FRR libyang plugins will be installed here. + This option is meaningless with libyang 0.16.74 or newer and will be + removed once support for older libyang versions is dropped. + When it's desired to run FRR without installing it in the system, it's possible to configure it as follows to look for YANG modules and libyang plugins in the compile directory: diff --git a/eigrpd/eigrp_dump.c b/eigrpd/eigrp_dump.c index c975c0abc7..876e1cac07 100644 --- a/eigrpd/eigrp_dump.c +++ b/eigrpd/eigrp_dump.c @@ -605,7 +605,7 @@ static struct cmd_node eigrp_debug_node = { }; /* Initialize debug commands. */ -void eigrp_debug_init() +void eigrp_debug_init(void) { install_node(&eigrp_debug_node, config_write_debug); diff --git a/eigrpd/eigrp_interface.c b/eigrpd/eigrp_interface.c index e450c7d999..e6cfe1deea 100644 --- a/eigrpd/eigrp_interface.c +++ b/eigrpd/eigrp_interface.c @@ -122,7 +122,7 @@ int eigrp_if_delete_hook(struct interface *ifp) struct list *eigrp_iflist; -void eigrp_if_init() +void eigrp_if_init(void) { /* Initialize Zebra interface data structure. */ // hook_register_prio(if_add, 0, eigrp_if_new); diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c index f3b583abdd..ee0476b28d 100644 --- a/eigrpd/eigrp_packet.c +++ b/eigrpd/eigrp_packet.c @@ -1101,7 +1101,7 @@ struct eigrp_packet *eigrp_packet_duplicate(struct eigrp_packet *old, return new; } -static struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new() +static struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new(void) { struct TLV_IPv4_Internal_type *new; @@ -1327,7 +1327,7 @@ uint16_t eigrp_add_authTLV_SHA256_to_stream(struct stream *s, return 0; } -struct TLV_MD5_Authentication_Type *eigrp_authTLV_MD5_new() +struct TLV_MD5_Authentication_Type *eigrp_authTLV_MD5_new(void) { struct TLV_MD5_Authentication_Type *new; @@ -1342,7 +1342,7 @@ void eigrp_authTLV_MD5_free(struct TLV_MD5_Authentication_Type *authTLV) XFREE(MTYPE_EIGRP_AUTH_TLV, authTLV); } -struct TLV_SHA256_Authentication_Type *eigrp_authTLV_SHA256_new() +struct TLV_SHA256_Authentication_Type *eigrp_authTLV_SHA256_new(void) { struct TLV_SHA256_Authentication_Type *new; @@ -1363,7 +1363,7 @@ void eigrp_IPv4_InternalTLV_free( XFREE(MTYPE_EIGRP_IPV4_INT_TLV, IPv4_InternalTLV); } -struct TLV_Sequence_Type *eigrp_SequenceTLV_new() +struct TLV_Sequence_Type *eigrp_SequenceTLV_new(void) { struct TLV_Sequence_Type *new; diff --git a/eigrpd/eigrp_topology.c b/eigrpd/eigrp_topology.c index 0cb4e0e9f4..2d0ebf1bc5 100644 --- a/eigrpd/eigrp_topology.c +++ b/eigrpd/eigrp_topology.c @@ -61,7 +61,7 @@ static int eigrp_nexthop_entry_cmp(struct eigrp_nexthop_entry *, * del - assigned function executed before deleting topology node by list * function */ -struct route_table *eigrp_topology_new() +struct route_table *eigrp_topology_new(void) { return route_table_init(); } @@ -70,7 +70,7 @@ struct route_table *eigrp_topology_new() * Returns new created toplogy node * cmp - assigned function for comparing topology entry */ -struct eigrp_prefix_entry *eigrp_prefix_entry_new() +struct eigrp_prefix_entry *eigrp_prefix_entry_new(void) { struct eigrp_prefix_entry *new; new = XCALLOC(MTYPE_EIGRP_PREFIX_ENTRY, @@ -102,7 +102,7 @@ static int eigrp_nexthop_entry_cmp(struct eigrp_nexthop_entry *entry1, * Returns new topology entry */ -struct eigrp_nexthop_entry *eigrp_nexthop_entry_new() +struct eigrp_nexthop_entry *eigrp_nexthop_entry_new(void) { struct eigrp_nexthop_entry *new; diff --git a/eigrpd/eigrpd.c b/eigrpd/eigrpd.c index 5541ec15f3..69d947e59f 100644 --- a/eigrpd/eigrpd.c +++ b/eigrpd/eigrpd.c @@ -122,7 +122,7 @@ void eigrp_router_id_update(struct eigrp *eigrp) } } -void eigrp_master_init() +void eigrp_master_init(void) { struct timeval tv; diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h new file mode 100644 index 0000000000..a924606f36 --- /dev/null +++ b/include/linux/if_addr.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_IF_ADDR_H +#define __LINUX_IF_ADDR_H + +#include <linux/types.h> +#include <linux/netlink.h> + +struct ifaddrmsg { + __u8 ifa_family; + __u8 ifa_prefixlen; /* The prefix length */ + __u8 ifa_flags; /* Flags */ + __u8 ifa_scope; /* Address scope */ + __u32 ifa_index; /* Link index */ +}; + +/* + * Important comment: + * IFA_ADDRESS is prefix address, rather than local interface address. + * It makes no difference for normally configured broadcast interfaces, + * but for point-to-point IFA_ADDRESS is DESTINATION address, + * local address is supplied in IFA_LOCAL attribute. + * + * IFA_FLAGS is a u32 attribute that extends the u8 field ifa_flags. + * If present, the value from struct ifaddrmsg will be ignored. + */ +enum { + IFA_UNSPEC, + IFA_ADDRESS, + IFA_LOCAL, + IFA_LABEL, + IFA_BROADCAST, + IFA_ANYCAST, + IFA_CACHEINFO, + IFA_MULTICAST, + IFA_FLAGS, + IFA_RT_PRIORITY, /* u32, priority/metric for prefix route */ + __IFA_MAX, +}; + +#define IFA_MAX (__IFA_MAX - 1) + +/* ifa_flags */ +#define IFA_F_SECONDARY 0x01 +#define IFA_F_TEMPORARY IFA_F_SECONDARY + +#define IFA_F_NODAD 0x02 +#define IFA_F_OPTIMISTIC 0x04 +#define IFA_F_DADFAILED 0x08 +#define IFA_F_HOMEADDRESS 0x10 +#define IFA_F_DEPRECATED 0x20 +#define IFA_F_TENTATIVE 0x40 +#define IFA_F_PERMANENT 0x80 +#define IFA_F_MANAGETEMPADDR 0x100 +#define IFA_F_NOPREFIXROUTE 0x200 +#define IFA_F_MCAUTOJOIN 0x400 +#define IFA_F_STABLE_PRIVACY 0x800 + +struct ifa_cacheinfo { + __u32 ifa_prefered; + __u32 ifa_valid; + __u32 cstamp; /* created timestamp, hundredths of seconds */ + __u32 tstamp; /* updated timestamp, hundredths of seconds */ +}; + +/* backwards compatibility for userspace */ +#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)))) +#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg)) + +#endif diff --git a/include/subdir.am b/include/subdir.am index 731785d4b4..0d7fed2852 100644 --- a/include/subdir.am +++ b/include/subdir.am @@ -1,4 +1,5 @@ noinst_HEADERS += \ + include/linux/if_addr.h \ include/linux/if_bridge.h \ include/linux/if_link.h \ include/linux/lwtunnel.h \ diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 81b4b397ec..36d4a0d7c0 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -69,7 +69,7 @@ int isis_interface_config_write(struct vty *); int isis_if_new_hook(struct interface *); int isis_if_delete_hook(struct interface *); -struct isis_circuit *isis_circuit_new() +struct isis_circuit *isis_circuit_new(void) { struct isis_circuit *circuit; int i; @@ -1393,7 +1393,7 @@ int isis_if_delete_hook(struct interface *ifp) return 0; } -void isis_circuit_init() +void isis_circuit_init(void) { /* Initialize Zebra interface data structure */ hook_register_prio(if_add, 0, isis_if_new_hook); diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index b6f751463a..1f28309105 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -1471,7 +1471,7 @@ DEFUN (show_isis_topology, return CMD_SUCCESS; } -void isis_spf_cmds_init() +void isis_spf_cmds_init(void) { install_element(VIEW_NODE, &show_isis_topology_cmd); } diff --git a/isisd/isis_te.c b/isisd/isis_te.c index a69c95cadf..23a1f10a18 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -68,7 +68,7 @@ const char *mode2text[] = {"Disable", "Area", "AS", "Emulate"}; *------------------------------------------------------------------------*/ /* Create new MPLS TE Circuit context */ -struct mpls_te_circuit *mpls_te_circuit_new() +struct mpls_te_circuit *mpls_te_circuit_new(void) { struct mpls_te_circuit *mtc; diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 958f8c2281..d03c1dde08 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -219,11 +219,11 @@ static int isis_zebra_if_address_del(int command, struct zclient *client, } static int isis_zebra_link_params(int command, struct zclient *zclient, - zebra_size_t length) + zebra_size_t length, vrf_id_t vrf_id) { struct interface *ifp; - ifp = zebra_interface_link_params_read(zclient->ibuf); + ifp = zebra_interface_link_params_read(zclient->ibuf, vrf_id); if (ifp == NULL) return 0; diff --git a/isisd/isisd.c b/isisd/isisd.c index 419127c34e..13cd510dd1 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -2161,7 +2161,7 @@ int isis_config_write(struct vty *vty) struct cmd_node router_node = {ROUTER_NODE, "%s(config-router)# ", 1}; -void isis_init() +void isis_init(void) { /* Install IS-IS top node */ install_node(&router_node, isis_config_write); diff --git a/ldpd/labelmapping.c b/ldpd/labelmapping.c index 944f93331f..5e1b422a41 100644 --- a/ldpd/labelmapping.c +++ b/ldpd/labelmapping.c @@ -37,7 +37,7 @@ enqueue_pdu(struct nbr *nbr, uint16_t type, struct ibuf *buf, uint16_t size) struct ldp_hdr *ldp_hdr; ldp_hdr = ibuf_seek(buf, 0, sizeof(struct ldp_hdr)); - ldp_hdr->length = htons(size); + ldp_hdr->length = htons(size - LDP_HDR_DEAD_LEN); evbuf_enqueue(&nbr->tcp->wbuf, buf); } @@ -65,7 +65,7 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh) /* real size will be set up later */ err |= gen_ldp_hdr(buf, 0); - size = LDP_HDR_PDU_LEN; + size = LDP_HDR_SIZE; first = 0; } diff --git a/ldpd/socket.c b/ldpd/socket.c index 78a07b1ed4..b31db2c7bc 100644 --- a/ldpd/socket.c +++ b/ldpd/socket.c @@ -276,6 +276,7 @@ sock_set_bindany(int fd, int enable) return (-1); } } + return (0); #else log_warnx( "%s: missing SO_BINDANY, IP_FREEBIND and IP_BINDANY, unable to bind to a nonlocal IP address", diff --git a/lib/command.c b/lib/command.c index d1dafa3a1a..06879f6854 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1535,67 +1535,11 @@ DEFUN (config_end, "end", "End current mode and change to enable mode.\n") { - switch (vty->node) { - case VIEW_NODE: - case ENABLE_NODE: - /* Nothing to do. */ - break; - case CONFIG_NODE: - case INTERFACE_NODE: - case PW_NODE: - case LOGICALROUTER_NODE: - case VRF_NODE: - case NH_GROUP_NODE: - case ZEBRA_NODE: - case RIP_NODE: - case RIPNG_NODE: - case EIGRP_NODE: - case BABEL_NODE: - case BGP_NODE: - case BGP_VRF_POLICY_NODE: - case BGP_VNC_DEFAULTS_NODE: - case BGP_VNC_NVE_GROUP_NODE: - case BGP_VNC_L2_GROUP_NODE: - case BGP_VPNV4_NODE: - case BGP_VPNV6_NODE: - case BGP_FLOWSPECV4_NODE: - case BGP_FLOWSPECV6_NODE: - case BGP_IPV4_NODE: - case BGP_IPV4M_NODE: - case BGP_IPV4L_NODE: - case BGP_IPV6_NODE: - case BGP_IPV6M_NODE: - case BGP_EVPN_NODE: - case BGP_EVPN_VNI_NODE: - case BGP_IPV6L_NODE: - case RMAP_NODE: - case PBRMAP_NODE: - case OSPF_NODE: - case OSPF6_NODE: - case LDP_NODE: - case LDP_IPV4_NODE: - case LDP_IPV6_NODE: - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - case LDP_L2VPN_NODE: - case LDP_PSEUDOWIRE_NODE: - case ISIS_NODE: - case OPENFABRIC_NODE: - case KEYCHAIN_NODE: - case KEYCHAIN_KEY_NODE: - case VTY_NODE: - case LINK_PARAMS_NODE: - case BFD_NODE: - case BFD_PEER_NODE: + if (vty->config) { vty_config_exit(vty); vty->node = ENABLE_NODE; - break; - default: - break; } - vty->xpath_index = 0; - return CMD_SUCCESS; } @@ -2571,8 +2515,6 @@ DEFUN (config_log_syslog, { int idx_log_levels = 2; - disable_log_file(); - if (argc == 3) { int level; if ((level = level_match(argv[idx_log_levels]->arg)) @@ -2939,7 +2881,7 @@ void cmd_init(int terminal) #endif } -void cmd_terminate() +void cmd_terminate(void) { struct cmd_node *cmd_node; diff --git a/lib/filter.c b/lib/filter.c index 1aae58b61c..317c1b68b7 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -2212,14 +2212,14 @@ static void access_list_init_ipv6(void) install_element(CONFIG_NODE, &no_ipv6_access_list_remark_comment_cmd); } -void access_list_init() +void access_list_init(void) { access_list_init_ipv4(); access_list_init_ipv6(); access_list_init_mac(); } -void access_list_reset() +void access_list_reset(void) { access_list_reset_ipv4(); access_list_reset_ipv6(); diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c index d5a2007c4d..fe18eb1051 100644 --- a/lib/frr_pthread.c +++ b/lib/frr_pthread.c @@ -47,7 +47,7 @@ static struct list *frr_pthread_list; /* ------------------------------------------------------------------------ */ -void frr_pthread_init() +void frr_pthread_init(void) { pthread_mutex_lock(&frr_pthread_list_mtx); { @@ -57,7 +57,7 @@ void frr_pthread_init() pthread_mutex_unlock(&frr_pthread_list_mtx); } -void frr_pthread_finish() +void frr_pthread_finish(void) { pthread_mutex_lock(&frr_pthread_list_mtx); { @@ -124,7 +124,7 @@ int frr_pthread_set_name(struct frr_pthread *fpt) #ifdef HAVE_PTHREAD_SETNAME_NP # ifdef GNU_LINUX ret = pthread_setname_np(fpt->thread, fpt->os_name); -# else /* NetBSD */ +# elif defined(__NetBSD__) ret = pthread_setname_np(fpt->thread, fpt->os_name, NULL); # endif #elif defined(HAVE_PTHREAD_SET_NAME_NP) @@ -178,7 +178,7 @@ int frr_pthread_stop(struct frr_pthread *fpt, void **result) return ret; } -void frr_pthread_stop_all() +void frr_pthread_stop_all(void) { pthread_mutex_lock(&frr_pthread_list_mtx); { diff --git a/lib/graph.c b/lib/graph.c index 4bc3eb82b8..128e45c570 100644 --- a/lib/graph.c +++ b/lib/graph.c @@ -27,7 +27,7 @@ DEFINE_MTYPE_STATIC(LIB, GRAPH, "Graph") DEFINE_MTYPE_STATIC(LIB, GRAPH_NODE, "Graph Node") -struct graph *graph_new() +struct graph *graph_new(void) { struct graph *graph = XCALLOC(MTYPE_GRAPH, sizeof(struct graph)); graph->nodes = vector_init(VECTOR_MIN_SIZE); diff --git a/lib/hash.c b/lib/hash.c index 641c751368..6c3c953e97 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -445,7 +445,7 @@ DEFUN_NOSH(show_hash_stats, return CMD_SUCCESS; } -void hash_cmd_init() +void hash_cmd_init(void) { install_element(ENABLE_NODE, &show_hash_stats_cmd); } @@ -341,6 +341,8 @@ DECLARE_QOBJ_TYPE(interface) DECLARE_HOOK(if_add, (struct interface * ifp), (ifp)) DECLARE_KOOH(if_del, (struct interface * ifp), (ifp)) +#define METRIC_MAX (~0) + /* Connected address structure. */ struct connected { /* Attached interface. */ @@ -388,6 +390,13 @@ struct connected { /* Label for Linux 2.2.X and upper. */ char *label; + + /* + * Used for setting the connected route's cost. If the metric + * here is set to METRIC_MAX the connected route falls back to + * "struct interface" + */ + uint32_t metric; }; /* Nbr Connected address structure. */ diff --git a/lib/if_rmap.c b/lib/if_rmap.c index 108ab7ec6b..69da695dcb 100644 --- a/lib/if_rmap.c +++ b/lib/if_rmap.c @@ -287,7 +287,7 @@ int config_write_if_rmap(struct vty *vty) return write; } -void if_rmap_reset() +void if_rmap_reset(void) { hash_clean(ifrmaphash, (void (*)(void *))if_rmap_free); } diff --git a/lib/keychain.c b/lib/keychain.c index 601b44a4f1..9aa3ef695f 100644 --- a/lib/keychain.c +++ b/lib/keychain.c @@ -1040,7 +1040,7 @@ static int keychain_config_write(struct vty *vty) return 0; } -void keychain_init() +void keychain_init(void) { keychain_list = list_new(); @@ -375,13 +375,8 @@ static void md5_calc(const uint8_t *b64, md5_ctxt *ctxt) } /* From RFC 2104 */ -void hmac_md5(text, text_len, key, key_len, - digest) unsigned char *text; /* pointer to data stream */ -int text_len; /* length of data stream */ -unsigned char *key; /* pointer to authentication key */ -int key_len; /* length of authentication key */ -uint8_t *digest; /* caller digest to be filled in */ - +void hmac_md5(unsigned char *text, int text_len, unsigned char *key, + int key_len, uint8_t *digest) { MD5_CTX context; unsigned char k_ipad[65]; /* inner padding - diff --git a/lib/plist.c b/lib/plist.c index ee68fbc0f1..41c8e4f8c0 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -2111,7 +2111,7 @@ static void prefix_list_init_ipv6(void) install_element(ENABLE_NODE, &clear_ipv6_prefix_list_cmd); } -void prefix_list_init() +void prefix_list_init(void) { cmd_variable_handler_register(plist_var_handlers); @@ -2119,7 +2119,7 @@ void prefix_list_init() prefix_list_init_ipv6(); } -void prefix_list_reset() +void prefix_list_reset(void) { prefix_list_reset_afi(AFI_IP, 0); prefix_list_reset_afi(AFI_IP6, 0); diff --git a/lib/prefix.c b/lib/prefix.c index 0203301562..07eb1785b7 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -820,7 +820,7 @@ const char *prefix_family_str(const struct prefix *p) } /* Allocate new prefix_ipv4 structure. */ -struct prefix_ipv4 *prefix_ipv4_new() +struct prefix_ipv4 *prefix_ipv4_new(void) { struct prefix_ipv4 *p; @@ -1359,7 +1359,7 @@ const char *prefix2str(union prefixconstptr pu, char *str, int size) return str; } -struct prefix *prefix_new() +struct prefix *prefix_new(void) { struct prefix *p; diff --git a/lib/skiplist.c b/lib/skiplist.c index 3933429c3b..dda442580a 100644 --- a/lib/skiplist.c +++ b/lib/skiplist.c @@ -88,7 +88,7 @@ static struct skiplist *skiplist_last_created; /* debugging hack */ #endif -static int randomLevel() +static int randomLevel(void) { register int level = 0; register int b; diff --git a/lib/thread.c b/lib/thread.c index 867ca2dc60..ae8e375a27 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -400,7 +400,7 @@ static void cancelreq_del(void *cr) } /* initializer, only ever called once */ -static void initializer() +static void initializer(void) { pthread_key_create(&thread_current, NULL); } @@ -716,13 +716,6 @@ int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname, return CMD_SUCCESS; } -int vrf_is_mapped_on_netns(struct vrf *vrf) -{ - if (!vrf || vrf->data.l.netns_name[0] == '\0') - return 0; - return 1; -} - /* vrf CLI commands */ DEFUN_NOSH(vrf_exit, vrf_exit_cmd, @@ -953,7 +946,7 @@ int vrf_bind(vrf_id_t vrf_id, int fd, char *name) if (fd < 0 || name == NULL) return fd; - if (vrf_is_mapped_on_netns(vrf_lookup_by_id(vrf_id))) + if (vrf_is_backend_netns()) return fd; #ifdef SO_BINDTODEVICE ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)+1); @@ -240,9 +240,6 @@ extern void vrf_set_default_name(const char *default_name, bool force); extern const char *vrf_get_default_name(void); #define VRF_DEFAULT_NAME vrf_get_default_name() -/* VRF is mapped on netns or not ? */ -int vrf_is_mapped_on_netns(struct vrf *vrf); - /* VRF switch from NETNS */ extern int vrf_switch_to_netns(vrf_id_t vrf_id); extern int vrf_switchback_to_initial(void); @@ -775,61 +775,11 @@ static void vty_end_config(struct vty *vty) { vty_out(vty, "\n"); - switch (vty->node) { - case VIEW_NODE: - case ENABLE_NODE: - /* Nothing to do. */ - break; - case CONFIG_NODE: - case INTERFACE_NODE: - case PW_NODE: - case ZEBRA_NODE: - case RIP_NODE: - case RIPNG_NODE: - case EIGRP_NODE: - case BGP_NODE: - case BGP_VPNV4_NODE: - case BGP_VPNV6_NODE: - case BGP_VRF_POLICY_NODE: - case BGP_VNC_DEFAULTS_NODE: - case BGP_VNC_NVE_GROUP_NODE: - case BGP_VNC_L2_GROUP_NODE: - case BGP_IPV4_NODE: - case BGP_IPV4M_NODE: - case BGP_IPV4L_NODE: - case BGP_IPV6_NODE: - case BGP_IPV6M_NODE: - case BGP_EVPN_NODE: - case BGP_IPV6L_NODE: - case RMAP_NODE: - case PBRMAP_NODE: - case OSPF_NODE: - case OSPF6_NODE: - case LDP_NODE: - case LDP_IPV4_NODE: - case LDP_IPV6_NODE: - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - case LDP_L2VPN_NODE: - case LDP_PSEUDOWIRE_NODE: - case ISIS_NODE: - case OPENFABRIC_NODE: - case KEYCHAIN_NODE: - case KEYCHAIN_KEY_NODE: - case VTY_NODE: - case BGP_EVPN_VNI_NODE: - case BFD_NODE: - case BFD_PEER_NODE: + if (vty->config) { vty_config_exit(vty); vty->node = ENABLE_NODE; - break; - default: - /* Unknown node, we have to ignore it. */ - break; } - vty->xpath_index = 0; - vty_prompt(vty); vty->cp = 0; } @@ -1190,44 +1140,11 @@ static void vty_stop_input(struct vty *vty) vty_clear_buf(vty); vty_out(vty, "\n"); - switch (vty->node) { - case VIEW_NODE: - case ENABLE_NODE: - /* Nothing to do. */ - break; - case CONFIG_NODE: - case INTERFACE_NODE: - case PW_NODE: - case ZEBRA_NODE: - case RIP_NODE: - case RIPNG_NODE: - case EIGRP_NODE: - case BGP_NODE: - case RMAP_NODE: - case PBRMAP_NODE: - case OSPF_NODE: - case OSPF6_NODE: - case LDP_NODE: - case LDP_IPV4_NODE: - case LDP_IPV6_NODE: - case LDP_IPV4_IFACE_NODE: - case LDP_IPV6_IFACE_NODE: - case LDP_L2VPN_NODE: - case LDP_PSEUDOWIRE_NODE: - case ISIS_NODE: - case OPENFABRIC_NODE: - case KEYCHAIN_NODE: - case KEYCHAIN_KEY_NODE: - case VTY_NODE: - case BFD_NODE: - case BFD_PEER_NODE: + if (vty->config) { vty_config_exit(vty); vty->node = ENABLE_NODE; - break; - default: - /* Unknown node, we have to ignore it. */ - break; } + vty_prompt(vty); /* Set history pointer to the latest one. */ @@ -1688,7 +1605,7 @@ static int vty_flush(struct thread *thread) } /* Allocate new vty struct. */ -struct vty *vty_new() +struct vty *vty_new(void) { struct vty *new = XCALLOC(MTYPE_VTY, sizeof(struct vty)); @@ -2696,6 +2613,7 @@ int vty_config_enter(struct vty *vty, bool private_config, bool exclusive) vty->node = CONFIG_NODE; vty->config = true; vty->private_config = private_config; + vty->xpath_index = 0; if (private_config) { vty->candidate_config = nb_config_dup(running_config); @@ -2733,6 +2651,8 @@ void vty_config_exit(struct vty *vty) nb_config_free(vty->candidate_config_base); vty->candidate_config_base = NULL; } + + vty->config = false; } int vty_config_exclusive_lock(struct vty *vty) @@ -3115,7 +3035,7 @@ struct cmd_node vty_node = { }; /* Reset all VTY status. */ -void vty_reset() +void vty_reset(void) { unsigned int i; struct vty *vty; @@ -3180,7 +3100,7 @@ static void vty_save_cwd(void) strcpy(vty_cwd, cwd); } -char *vty_get_cwd() +char *vty_get_cwd(void) { return vty_cwd; } @@ -3195,7 +3115,7 @@ int vty_shell_serv(struct vty *vty) return vty->type == VTY_SHELL_SERV ? 1 : 0; } -void vty_init_vtysh() +void vty_init_vtysh(void) { vtyvec = vector_init(VECTOR_MIN_SIZE); } diff --git a/lib/yang.c b/lib/yang.c index 71b41c35d8..f62a8163f9 100644 --- a/lib/yang.c +++ b/lib/yang.c @@ -26,6 +26,8 @@ #include "yang_translator.h" #include "northbound.h" +#include <libyang/user_types.h> + DEFINE_MTYPE(LIB, YANG_MODULE, "YANG module") DEFINE_MTYPE(LIB, YANG_DATA, "YANG data structure") @@ -639,8 +641,18 @@ static void ly_log_cb(LY_LOG_LEVEL level, const char *msg, const char *path) zlog(priority, "libyang: %s", msg); } +#if CONFDATE > 20190401 +CPP_NOTICE("lib/yang: time to remove non-LIBYANG_EXT_BUILTIN support") +#endif + +#ifdef LIBYANG_EXT_BUILTIN +extern struct lytype_plugin_list frr_user_types[]; +#endif + void yang_init(void) { +#ifndef LIBYANG_EXT_BUILTIN +CPP_NOTICE("lib/yang: deprecated libyang <0.16.74 extension loading in use!") static char ly_plugin_dir[PATH_MAX]; const char *const *ly_loaded_plugins; const char *ly_plugin; @@ -650,11 +662,20 @@ void yang_init(void) snprintf(ly_plugin_dir, sizeof(ly_plugin_dir), "%s=%s", "LIBYANG_USER_TYPES_PLUGINS_DIR", LIBYANG_PLUGINS_PATH); putenv(ly_plugin_dir); +#endif /* Initialize libyang global parameters that affect all containers. */ ly_set_log_clb(ly_log_cb, 1); ly_log_options(LY_LOLOG | LY_LOSTORE); +#ifdef LIBYANG_EXT_BUILTIN + if (ly_register_types(frr_user_types, "frr_user_types")) { + flog_err(EC_LIB_LIBYANG_PLUGIN_LOAD, + "ly_register_types() failed"); + exit(1); + } +#endif + /* Initialize libyang container for native models. */ ly_native_ctx = ly_ctx_new(YANG_MODELS_PATH, LY_CTX_DISABLE_SEARCHDIR_CWD); @@ -665,6 +686,7 @@ void yang_init(void) ly_ctx_set_module_imp_clb(ly_native_ctx, yang_module_imp_clb, NULL); ly_ctx_set_priv_dup_clb(ly_native_ctx, ly_dup_cb); +#ifndef LIBYANG_EXT_BUILTIN /* Detect if the required libyang plugin(s) were loaded successfully. */ ly_loaded_plugins = ly_get_loaded_plugins(); for (size_t i = 0; (ly_plugin = ly_loaded_plugins[i]); i++) { @@ -678,6 +700,7 @@ void yang_init(void) "%s: failed to load frr_user_types.so", __func__); exit(1); } +#endif yang_translator_init(); } diff --git a/lib/zclient.c b/lib/zclient.c index cc936d47d7..0e58d97174 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -457,8 +457,7 @@ void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id) vrf_id); /* If default information is needed. */ - if (vrf_bitmap_check(zclient->default_information[afi], - VRF_DEFAULT)) + if (vrf_bitmap_check(zclient->default_information[afi], vrf_id)) zebra_redistribute_default_send( ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, afi, vrf_id); @@ -525,8 +524,7 @@ void zclient_send_dereg_requests(struct zclient *zclient, vrf_id_t vrf_id) i, 0, vrf_id); /* If default information is needed. */ - if (vrf_bitmap_check(zclient->default_information[afi], - VRF_DEFAULT)) + if (vrf_bitmap_check(zclient->default_information[afi], vrf_id)) zebra_redistribute_default_send( ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, afi, vrf_id); @@ -756,10 +754,24 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api) stream_reset(s); zclient_create_header(s, cmd, api->vrf_id); + if (api->type >= ZEBRA_ROUTE_MAX) { + flog_err(EC_LIB_ZAPI_ENCODE, + "%s: Specified route type (%u) is not a legal value\n", + __PRETTY_FUNCTION__, api->type); + return -1; + } stream_putc(s, api->type); + stream_putw(s, api->instance); stream_putl(s, api->flags); stream_putc(s, api->message); + + if (api->safi < SAFI_UNICAST || api->safi >= SAFI_MAX) { + flog_err(EC_LIB_ZAPI_ENCODE, + "%s: Specified route SAFI (%u) is not a legal value\n", + __PRETTY_FUNCTION__, api->safi); + return -1; + } stream_putc(s, api->safi); /* Put prefix information. */ @@ -875,7 +887,7 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api) /* Type, flags, message. */ STREAM_GETC(s, api->type); - if (api->type > ZEBRA_ROUTE_MAX) { + if (api->type >= ZEBRA_ROUTE_MAX) { flog_err(EC_LIB_ZAPI_ENCODE, "%s: Specified route type: %d is not a legal value\n", __PRETTY_FUNCTION__, api->type); @@ -886,6 +898,12 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api) STREAM_GETL(s, api->flags); STREAM_GETC(s, api->message); STREAM_GETC(s, api->safi); + if (api->safi < SAFI_UNICAST || api->safi >= SAFI_MAX) { + flog_err(EC_LIB_ZAPI_ENCODE, + "%s: Specified route SAFI (%u) is not a legal value\n", + __PRETTY_FUNCTION__, api->safi); + return -1; + } /* Prefix. */ STREAM_GETC(s, api->prefix.family); @@ -1497,7 +1515,8 @@ static void link_params_set_value(struct stream *s, struct if_link_params *iflp) iflp->use_bw = stream_getf(s); } -struct interface *zebra_interface_link_params_read(struct stream *s) +struct interface *zebra_interface_link_params_read(struct stream *s, + vrf_id_t vrf_id) { struct if_link_params *iflp; ifindex_t ifindex; @@ -1506,7 +1525,7 @@ struct interface *zebra_interface_link_params_read(struct stream *s) ifindex = stream_getl(s); - struct interface *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT); + struct interface *ifp = if_lookup_by_index(ifindex, vrf_id); if (ifp == NULL) { flog_err(EC_LIB_ZAPI_ENCODE, @@ -2372,8 +2391,12 @@ static void zclient_capability_decode(int command, struct zclient *zclient, { struct zclient_capabilities cap; struct stream *s = zclient->ibuf; + int vrf_backend; uint8_t mpls_enabled; + STREAM_GETL(s, vrf_backend); + vrf_configure_backend(vrf_backend); + memset(&cap, 0, sizeof(cap)); STREAM_GETC(s, mpls_enabled); cap.mpls_enabled = !!mpls_enabled; @@ -2583,7 +2606,7 @@ static int zclient_read(struct thread *thread) case ZEBRA_INTERFACE_LINK_PARAMS: if (zclient->interface_link_params) (*zclient->interface_link_params)(command, zclient, - length); + length, vrf_id); break; case ZEBRA_FEC_UPDATE: if (zclient_debug) diff --git a/lib/zclient.h b/lib/zclient.h index 401d6c400a..8a3423cdd8 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -229,7 +229,7 @@ struct zclient { int (*interface_address_add)(int, struct zclient *, uint16_t, vrf_id_t); int (*interface_address_delete)(int, struct zclient *, uint16_t, vrf_id_t); - int (*interface_link_params)(int, struct zclient *, uint16_t); + int (*interface_link_params)(int, struct zclient *, uint16_t, vrf_id_t); int (*interface_bfd_dest_update)(int, struct zclient *, uint16_t, vrf_id_t); int (*interface_nbr_address_add)(int, struct zclient *, uint16_t, @@ -426,6 +426,8 @@ enum zapi_iptable_notify_owner { #define ZEBRA_MACIP_TYPE_ROUTER_FLAG 0x04 /* Router Flag - proxy NA */ #define ZEBRA_MACIP_TYPE_OVERRIDE_FLAG 0x08 /* Override Flag */ +enum zebra_neigh_state { ZEBRA_NEIGH_INACTIVE = 0, ZEBRA_NEIGH_ACTIVE = 1 }; + struct zclient_options { bool receive_notify; }; @@ -564,7 +566,8 @@ extern struct interface *zebra_interface_vrf_update_read(struct stream *s, extern void zebra_interface_if_set_value(struct stream *, struct interface *); extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid); -extern struct interface *zebra_interface_link_params_read(struct stream *); +extern struct interface *zebra_interface_link_params_read(struct stream *s, + vrf_id_t vrf_id); extern size_t zebra_interface_link_params_write(struct stream *, struct interface *); extern int zclient_send_get_label_chunk( diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index dc7a3f6d45..671267aa05 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -1897,7 +1897,7 @@ int config_write_ospf6_debug_asbr(struct vty *vty) return 0; } -void install_element_ospf6_debug_asbr() +void install_element_ospf6_debug_asbr(void) { install_element(ENABLE_NODE, &debug_ospf6_asbr_cmd); install_element(ENABLE_NODE, &no_debug_ospf6_asbr_cmd); diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 2bfa4201cb..dd08144daa 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -246,6 +246,7 @@ void ospf6_interface_delete(struct ospf6_interface *oi) THREAD_OFF(oi->thread_send_hello); THREAD_OFF(oi->thread_send_lsupdate); THREAD_OFF(oi->thread_send_lsack); + THREAD_OFF(oi->thread_sso); ospf6_lsdb_remove_all(oi->lsdb); ospf6_lsdb_remove_all(oi->lsupdate_list); @@ -291,6 +292,7 @@ void ospf6_interface_disable(struct ospf6_interface *oi) THREAD_OFF(oi->thread_send_hello); THREAD_OFF(oi->thread_send_lsupdate); THREAD_OFF(oi->thread_send_lsack); + THREAD_OFF(oi->thread_sso); THREAD_OFF(oi->thread_network_lsa); THREAD_OFF(oi->thread_link_lsa); @@ -381,9 +383,9 @@ void ospf6_interface_state_update(struct interface *ifp) if (if_is_operative(ifp) && (ospf6_interface_get_linklocal_address(oi->interface) || if_is_loopback(oi->interface))) - thread_add_event(master, interface_up, oi, 0, NULL); + thread_execute(master, interface_up, oi, 0); else - thread_add_event(master, interface_down, oi, 0, NULL); + thread_execute(master, interface_down, oi, 0); return; } @@ -679,6 +681,12 @@ int interface_up(struct thread *thread) oi = (struct ospf6_interface *)THREAD_ARG(thread); assert(oi && oi->interface); + /* + * Remove old pointer. If this thread wasn't a timer this + * operation won't make a difference, because it is already NULL. + */ + oi->thread_sso = NULL; + if (IS_OSPF6_DEBUG_INTERFACE) zlog_debug("Interface Event %s: [InterfaceUp]", oi->interface->name); @@ -721,6 +729,22 @@ int interface_up(struct thread *thread) return 0; } +#ifdef __FreeBSD__ + /* + * XXX: Schedule IPv6 group join for later, otherwise we might + * lose the multicast group registration caused by IPv6 group + * leave race. + */ + if (oi->sso_try_cnt == 0) { + oi->sso_try_cnt++; + zlog_info("Scheduling %s for sso", oi->interface->name); + thread_add_timer(master, interface_up, oi, + OSPF6_INTERFACE_SSO_RETRY_INT, + &oi->thread_sso); + return 0; + } +#endif /* __FreeBSD__ */ + /* Join AllSPFRouters */ if (ospf6_sso(oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP) < 0) { @@ -729,7 +753,8 @@ int interface_up(struct thread *thread) "Scheduling %s for sso retry, trial count: %d", oi->interface->name, oi->sso_try_cnt); thread_add_timer(master, interface_up, oi, - OSPF6_INTERFACE_SSO_RETRY_INT, NULL); + OSPF6_INTERFACE_SSO_RETRY_INT, + &oi->thread_sso); } return 0; } @@ -830,6 +855,9 @@ int interface_down(struct thread *thread) /* Stop Hellos */ THREAD_OFF(oi->thread_send_hello); + /* Stop trying to set socket options. */ + THREAD_OFF(oi->thread_sso); + /* Leave AllSPFRouters */ if (oi->state > OSPF6_INTERFACE_DOWN) ospf6_sso(oi->interface->ifindex, &allspfrouters6, @@ -1602,6 +1630,7 @@ DEFUN (ipv6_ospf6_passive, SET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE); THREAD_OFF(oi->thread_send_hello); + THREAD_OFF(oi->thread_sso); for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) { THREAD_OFF(on->inactivity_timer); @@ -1631,7 +1660,7 @@ DEFUN (no_ipv6_ospf6_passive, UNSET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE); THREAD_OFF(oi->thread_send_hello); - oi->thread_send_hello = NULL; + THREAD_OFF(oi->thread_sso); thread_add_event(master, ospf6_hello_send, oi, 0, &oi->thread_send_hello); @@ -1791,8 +1820,8 @@ DEFUN (ipv6_ospf6_network, } /* Reset the interface */ - thread_add_event(master, interface_down, oi, 0, NULL); - thread_add_event(master, interface_up, oi, 0, NULL); + thread_execute(master, interface_down, oi, 0); + thread_execute(master, interface_up, oi, 0); return CMD_SUCCESS; } @@ -1825,8 +1854,8 @@ DEFUN (no_ipv6_ospf6_network, oi->type = type; /* Reset the interface */ - thread_add_event(master, interface_down, oi, 0, NULL); - thread_add_event(master, interface_up, oi, 0, NULL); + thread_execute(master, interface_down, oi, 0); + thread_execute(master, interface_up, oi, 0); return CMD_SUCCESS; } @@ -1969,8 +1998,8 @@ static void ospf6_interface_clear(struct vty *vty, struct interface *ifp) zlog_debug("Interface %s: clear by reset", ifp->name); /* Reset the interface */ - thread_add_event(master, interface_down, oi, 0, NULL); - thread_add_event(master, interface_up, oi, 0, NULL); + thread_execute(master, interface_down, oi, 0); + thread_execute(master, interface_up, oi, 0); } /* Clear interface */ diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index 8fd43f099a..e0c39a29b4 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -80,6 +80,7 @@ struct ospf6_interface { /* Interface socket setting trial counter, resets on success */ uint8_t sso_try_cnt; + struct thread *thread_sso; /* OSPF6 Interface flag */ char flag; diff --git a/ospfd/ospf_api.c b/ospfd/ospf_api.c index b1175a2f68..a3b337a0c0 100644 --- a/ospfd/ospf_api.c +++ b/ospfd/ospf_api.c @@ -300,7 +300,7 @@ uint32_t msg_get_seq(struct msg *msg) * ----------------------------------------------------------- */ -struct msg_fifo *msg_fifo_new() +struct msg_fifo *msg_fifo_new(void) { return XCALLOC(MTYPE_OSPF_API_FIFO, sizeof(struct msg_fifo)); } diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index f1477ba14d..ce1604a5b1 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -1182,7 +1182,7 @@ int ospf_vls_in_area(struct ospf_area *area) } -struct crypt_key *ospf_crypt_key_new() +struct crypt_key *ospf_crypt_key_new(void) { return XCALLOC(MTYPE_OSPF_CRYPT_KEY, sizeof(struct crypt_key)); } @@ -1230,7 +1230,7 @@ uint8_t ospf_default_iftype(struct interface *ifp) return OSPF_IFTYPE_BROADCAST; } -void ospf_if_init() +void ospf_if_init(void) { /* Initialize Zebra interface data structure. */ hook_register_prio(if_add, 0, ospf_if_new_hook); diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 288ce43f79..c9710e9165 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -150,7 +150,7 @@ int ospf_lsa_checksum_valid(struct lsa_header *lsa) /* Create OSPF LSA. */ -struct ospf_lsa *ospf_lsa_new() +struct ospf_lsa *ospf_lsa_new(void) { struct ospf_lsa *new; @@ -2249,6 +2249,22 @@ void ospf_external_lsa_refresh_default(struct ospf *ospf) } } +void ospf_default_originate_lsa_update(struct ospf *ospf) +{ + struct prefix_ipv4 p; + struct ospf_lsa *lsa; + + p.family = AF_INET; + p.prefixlen = 0; + p.prefix.s_addr = 0; + + lsa = ospf_external_info_find_lsa(ospf, &p); + if (lsa && IS_LSA_MAXAGE(lsa)) { + ospf_discard_from_db(ospf, lsa->lsdb, lsa); + ospf_lsdb_delete(lsa->lsdb, lsa); + } +} + void ospf_external_lsa_refresh_type(struct ospf *ospf, uint8_t type, unsigned short instance, int force) { diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h index ba4c4c1cac..4b4d760f44 100644 --- a/ospfd/ospf_lsa.h +++ b/ospfd/ospf_lsa.h @@ -296,6 +296,7 @@ extern int ospf_lsa_maxage_walker(struct thread *); extern struct ospf_lsa *ospf_lsa_refresh(struct ospf *, struct ospf_lsa *); extern void ospf_external_lsa_refresh_default(struct ospf *); +extern void ospf_default_originate_lsa_update(struct ospf *ospf); extern void ospf_external_lsa_refresh_type(struct ospf *, uint8_t, unsigned short, int); diff --git a/ospfd/ospf_lsdb.c b/ospfd/ospf_lsdb.c index f39bea9768..2e850c4e26 100644 --- a/ospfd/ospf_lsdb.c +++ b/ospfd/ospf_lsdb.c @@ -31,7 +31,7 @@ #include "ospfd/ospf_lsa.h" #include "ospfd/ospf_lsdb.h" -struct ospf_lsdb *ospf_lsdb_new() +struct ospf_lsdb *ospf_lsdb_new(void) { struct ospf_lsdb *new; diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 3bb3b79a6a..136683b074 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -148,7 +148,7 @@ void ospf_packet_free(struct ospf_packet *op) XFREE(MTYPE_OSPF_PACKET, op); } -struct ospf_fifo *ospf_fifo_new() +struct ospf_fifo *ospf_fifo_new(void) { struct ospf_fifo *new; diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c index 72f6dbe08e..4a0d4add15 100644 --- a/ospfd/ospf_ri.c +++ b/ospfd/ospf_ri.c @@ -146,7 +146,7 @@ static int ospf_router_info_register(uint8_t scope) return rc; } -static int ospf_router_info_unregister() +static int ospf_router_info_unregister(void) { if ((OspfRI.scope != OSPF_OPAQUE_AS_LSA) diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c index 7ee91b5b6c..da83c1ddaf 100644 --- a/ospfd/ospf_route.c +++ b/ospfd/ospf_route.c @@ -39,7 +39,7 @@ #include "ospfd/ospf_zebra.h" #include "ospfd/ospf_dump.h" -struct ospf_route *ospf_route_new() +struct ospf_route *ospf_route_new(void) { struct ospf_route *new; @@ -51,7 +51,7 @@ struct ospf_route *ospf_route_new() return new; } -void ospf_route_free(struct ospf_route * or) +void ospf_route_free(struct ospf_route *or) { if (or->paths) list_delete(& or->paths); @@ -59,7 +59,7 @@ void ospf_route_free(struct ospf_route * or) XFREE(MTYPE_OSPF_ROUTE, or); } -struct ospf_path *ospf_path_new() +struct ospf_path *ospf_path_new(void) { struct ospf_path *new; diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index 3efc219fcb..bd8cbee11a 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -150,7 +150,7 @@ static int ospf_mpls_te_register(enum inter_as_mode mode) return rc; } -static int ospf_mpls_te_unregister() +static int ospf_mpls_te_unregister(void) { uint8_t scope; diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 3ab9c018ea..c1dc1f0d6f 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -1205,14 +1205,17 @@ DEFUN (no_ospf_area_vlink, return CMD_WARNING_CONFIG_FAILED; } + vl_data = ospf_vl_lookup(ospf, area, vl_config.vl_peer); + if (!vl_data) { + vty_out(vty, "Virtual link does not exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (argc <= 5) { /* Basic VLink no command */ /* Thats all folks! - BUGS B. strikes again!!!*/ - if ((vl_data = ospf_vl_lookup(ospf, area, vl_config.vl_peer))) - ospf_vl_delete(ospf, vl_data); - + ospf_vl_delete(ospf, vl_data); ospf_area_check_free(ospf, vl_config.area_id); - return CMD_SUCCESS; } diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 79ddb192c1..a86800f901 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -340,11 +340,11 @@ static int ospf_interface_address_delete(int command, struct zclient *zclient, } static int ospf_interface_link_params(int command, struct zclient *zclient, - zebra_size_t length) + zebra_size_t length, vrf_id_t vrf_id) { struct interface *ifp; - ifp = zebra_interface_link_params_read(zclient->ibuf); + ifp = zebra_interface_link_params_read(zclient->ibuf, vrf_id); if (ifp == NULL) return 0; @@ -869,6 +869,9 @@ int ospf_redistribute_default_unset(struct ospf *ospf) ospf_asbr_status_update(ospf, --ospf->redistribute); + /* clean up maxage default originate external lsa */ + ospf_default_originate_lsa_update(ospf); + return CMD_SUCCESS; } diff --git a/pimd/pim_signals.c b/pimd/pim_signals.c index 0e9b09bf84..38387d38c3 100644 --- a/pimd/pim_signals.c +++ b/pimd/pim_signals.c @@ -33,26 +33,26 @@ * Signal handlers */ -static void pim_sighup() +static void pim_sighup(void) { zlog_info("SIGHUP received, ignoring"); } -static void pim_sigint() +static void pim_sigint(void) { zlog_notice("Terminating on signal SIGINT"); pim_terminate(); exit(1); } -static void pim_sigterm() +static void pim_sigterm(void) { zlog_notice("Terminating on signal SIGTERM"); pim_terminate(); exit(1); } -static void pim_sigusr1() +static void pim_sigusr1(void) { zlog_rotate(); } diff --git a/pimd/pim_static.c b/pimd/pim_static.c index 9569b7dcac..442b22e06f 100644 --- a/pimd/pim_static.c +++ b/pimd/pim_static.c @@ -37,12 +37,12 @@ void pim_static_route_free(struct static_route *s_route) XFREE(MTYPE_PIM_STATIC_ROUTE, s_route); } -static struct static_route *static_route_alloc() +static struct static_route *static_route_alloc(void) { return XCALLOC(MTYPE_PIM_STATIC_ROUTE, sizeof(struct static_route)); } -static struct static_route *static_route_new(unsigned int iif, unsigned int oif, +static struct static_route *static_route_new(ifindex_t iif, ifindex_t oif, struct in_addr group, struct in_addr source) { @@ -76,7 +76,7 @@ int pim_static_add(struct pim_instance *pim, struct interface *iif, ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0; ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0; - if (!iif_index || !oif_index) { + if (!iif_index || !oif_index || iif_index == -1 || oif_index == -1) { zlog_warn( "%s %s: Unable to add static route: Invalid interface index(iif=%d,oif=%d)", __FILE__, __PRETTY_FUNCTION__, iif_index, oif_index); diff --git a/pimd/pim_time.c b/pimd/pim_time.c index 23c85c2fa8..f12f767537 100644 --- a/pimd/pim_time.c +++ b/pimd/pim_time.c @@ -47,7 +47,7 @@ static int gettime_monotonic(struct timeval *tv) pim_time_monotonic_sec(): number of seconds since some unspecified starting point */ -int64_t pim_time_monotonic_sec() +int64_t pim_time_monotonic_sec(void) { struct timeval now_tv; @@ -65,7 +65,7 @@ int64_t pim_time_monotonic_sec() pim_time_monotonic_dsec(): number of deciseconds since some unspecified starting point */ -int64_t pim_time_monotonic_dsec() +int64_t pim_time_monotonic_dsec(void) { struct timeval now_tv; int64_t now_dsec; diff --git a/pimd/pimd.c b/pimd/pimd.c index b993bcdc03..656b000579 100644 --- a/pimd/pimd.c +++ b/pimd/pimd.c @@ -67,7 +67,7 @@ void pim_prefix_list_update(struct prefix_list *plist) } } -static void pim_free() +static void pim_free(void) { pim_route_map_terminate(); @@ -123,7 +123,7 @@ void pim_init(void) pim_cmd_init(); } -void pim_terminate() +void pim_terminate(void) { struct zclient *zclient; diff --git a/python/clidef.py b/python/clidef.py index a140ce3d54..f8d96115bd 100644 --- a/python/clidef.py +++ b/python/clidef.py @@ -41,7 +41,7 @@ class RenderHandler(object): class StringHandler(RenderHandler): argtype = 'const char *' decl = Template('const char *$varname = NULL;') - code = Template('$varname = argv[_i]->arg;') + code = Template('$varname = (argv[_i]->type == WORD_TKN) ? argv[_i]->text : argv[_i]->arg;') drop_str = True canfail = False diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 96b1cd8938..9575f6b8a8 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -563,7 +563,7 @@ int rip_if_down(struct interface *ifp) } /* Needed for stop RIP process. */ -void rip_if_down_all() +void rip_if_down_all(void) { struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); struct interface *ifp; @@ -964,7 +964,7 @@ void rip_enable_apply(struct interface *ifp) } /* Apply network configuration to all interface. */ -void rip_enable_apply_all() +void rip_enable_apply_all(void) { struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); struct interface *ifp; @@ -1029,7 +1029,7 @@ int rip_neighbor_delete(struct prefix_ipv4 *p) } /* Clear all network and neighbor configuration. */ -void rip_clean_network() +void rip_clean_network(void) { unsigned int i; char *str; diff --git a/ripd/rip_offset.c b/ripd/rip_offset.c index 418ec3fc7b..ca273c53b2 100644 --- a/ripd/rip_offset.c +++ b/ripd/rip_offset.c @@ -152,14 +152,14 @@ static int offset_list_cmp(struct rip_offset_list *o1, return strcmp(o1->ifname, o2->ifname); } -void rip_offset_init() +void rip_offset_init(void) { rip_offset_list_master = list_new(); rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp; rip_offset_list_master->del = (void (*)(void *))offset_list_del; } -void rip_offset_clean() +void rip_offset_clean(void) { list_delete(&rip_offset_list_master); diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c index b34f944c9e..3216b8f89f 100644 --- a/ripd/rip_routemap.c +++ b/ripd/rip_routemap.c @@ -518,7 +518,7 @@ static struct route_map_rule_cmd route_set_tag_cmd = { #define SET_STR "Set values in destination routing protocol\n" /* Route-map init */ -void rip_route_map_init() +void rip_route_map_init(void) { route_map_init(); diff --git a/ripngd/ripng_debug.c b/ripngd/ripng_debug.c index c56ff12627..fe63d8fdea 100644 --- a/ripngd/ripng_debug.c +++ b/ripngd/ripng_debug.c @@ -207,7 +207,7 @@ static int config_write_debug(struct vty *vty) return write; } -void ripng_debug_init() +void ripng_debug_init(void) { ripng_debug_event = 0; ripng_debug_packet = 0; diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index 4d14fbab64..e5dc6e6af6 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -739,7 +739,7 @@ static void ripng_enable_apply_all(void) } /* Clear all network and neighbor configuration */ -void ripng_clean_network() +void ripng_clean_network(void) { unsigned int i; char *str; @@ -930,7 +930,7 @@ static struct cmd_node interface_node = { }; /* Initialization of interface. */ -void ripng_if_init() +void ripng_if_init(void) { /* Interface initialize. */ hook_register_prio(if_add, 0, ripng_if_new_hook); diff --git a/ripngd/ripng_peer.c b/ripngd/ripng_peer.c index 6b2a183539..756162d65c 100644 --- a/ripngd/ripng_peer.c +++ b/ripngd/ripng_peer.c @@ -183,7 +183,7 @@ static int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2) return memcmp(&p1->addr, &p2->addr, sizeof(struct in6_addr)); } -void ripng_peer_init() +void ripng_peer_init(void) { peer_list = list_new(); peer_list->cmp = (int (*)(void *, void *))ripng_peer_list_cmp; diff --git a/ripngd/ripng_routemap.c b/ripngd/ripng_routemap.c index 9a9e346a59..0604e272cd 100644 --- a/ripngd/ripng_routemap.c +++ b/ripngd/ripng_routemap.c @@ -337,7 +337,7 @@ static struct route_map_rule_cmd route_set_tag_cmd = { #define MATCH_STR "Match values from routing table\n" #define SET_STR "Set values in destination routing protocol\n" -void ripng_route_map_init() +void ripng_route_map_init(void) { route_map_init(); diff --git a/ripngd/ripng_zebra.c b/ripngd/ripng_zebra.c index e3f42edf51..28a57f25d0 100644 --- a/ripngd/ripng_zebra.c +++ b/ripngd/ripng_zebra.c @@ -161,7 +161,7 @@ int ripng_redistribute_check(int type) return vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT); } -void ripng_redistribute_clean() +void ripng_redistribute_clean(void) { for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) { if (!vrf_bitmap_check(zclient->redist[AFI_IP6][i], VRF_DEFAULT)) diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index ae8e8ab7d9..0022c726c5 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -76,7 +76,7 @@ int ripng_route_rte(struct ripng_info *rinfo) } /* Allocate new ripng information. */ -struct ripng_info *ripng_info_new() +struct ripng_info *ripng_info_new(void) { struct ripng_info *new; @@ -2401,7 +2401,7 @@ static void ripng_distribute_update_all_wrapper(struct access_list *notused) } /* delete all the added ripng routes. */ -void ripng_clean() +void ripng_clean(void) { int i; struct agg_node *rp; @@ -2542,7 +2542,7 @@ static void ripng_routemap_update(const char *unused) } /* Initialize ripng structure and set commands. */ -void ripng_init() +void ripng_init(void) { /* Install RIPNG_NODE. */ install_node(&cmd_ripng_node, ripng_config_write); diff --git a/staticd/static_vty.c b/staticd/static_vty.c index ae0026cc97..f09c304359 100644 --- a/staticd/static_vty.c +++ b/staticd/static_vty.c @@ -775,7 +775,7 @@ DEFPY(ip_route_blackhole, "Table to configure\n" "The table number to configure\n") { - if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) { + if (table_str && vrf && !vrf_is_backend_netns()) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -814,7 +814,7 @@ DEFPY(ip_route_blackhole_vrf, VTY_DECLVAR_CONTEXT(vrf, vrf); struct static_vrf *svrf = vrf->info; - if (table_str && !vrf_is_mapped_on_netns(vrf)) { + if (table_str && !vrf_is_backend_netns()) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -880,7 +880,7 @@ DEFPY(ip_route_address_interface, return CMD_WARNING_CONFIG_FAILED; } - if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) { + if (table_str && vrf && !vrf_is_backend_netns()) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -938,7 +938,7 @@ DEFPY(ip_route_address_interface_vrf, struct static_vrf *svrf = vrf->info; struct static_vrf *nh_svrf; - if (table_str && !vrf_is_mapped_on_netns(vrf)) { + if (table_str && !vrf_is_backend_netns()) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -999,7 +999,7 @@ DEFPY(ip_route, struct static_vrf *nh_svrf; const char *flag = NULL; - if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) { + if (table_str && vrf && !vrf_is_backend_netns()) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1065,7 +1065,7 @@ DEFPY(ip_route_vrf, struct static_vrf *nh_svrf; const char *flag = NULL; - if (table_str && !vrf_is_mapped_on_netns(vrf)) { + if (table_str && !vrf_is_backend_netns()) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1119,7 +1119,7 @@ DEFPY(ipv6_route_blackhole, "Table to configure\n" "The table number to configure\n") { - if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) { + if (table_str && vrf && !vrf_is_backend_netns()) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1158,7 +1158,7 @@ DEFPY(ipv6_route_blackhole_vrf, VTY_DECLVAR_CONTEXT(vrf, vrf); struct static_vrf *svrf = vrf->info; - if (table_str && !vrf_is_mapped_on_netns(vrf)) { + if (table_str && !vrf_is_backend_netns()) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1213,7 +1213,7 @@ DEFPY(ipv6_route_address_interface, struct static_vrf *nh_svrf; const char *flag = NULL; - if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) { + if (table_str && vrf && !vrf_is_backend_netns()) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1282,7 +1282,7 @@ DEFPY(ipv6_route_address_interface_vrf, struct static_vrf *nh_svrf; const char *flag = NULL; - if (table_str && !vrf_is_mapped_on_netns(vrf)) { + if (table_str && !vrf_is_backend_netns()) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1343,7 +1343,7 @@ DEFPY(ipv6_route, struct static_vrf *nh_svrf; const char *flag = NULL; - if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) { + if (table_str && vrf && !vrf_is_backend_netns()) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; @@ -1409,7 +1409,7 @@ DEFPY(ipv6_route_vrf, struct static_vrf *nh_svrf; const char *flag = NULL; - if (table_str && !vrf_is_mapped_on_netns(vrf)) { + if (table_str && !vrf_is_backend_netns()) { vty_out(vty, "%% table param only available when running on netns-based vrfs\n"); return CMD_WARNING_CONFIG_FAILED; diff --git a/tests/bgpd/test_aspath.c b/tests/bgpd/test_aspath.c index d2d960f278..b2612892f9 100644 --- a/tests/bgpd/test_aspath.c +++ b/tests/bgpd/test_aspath.c @@ -1074,7 +1074,7 @@ static int validate(struct aspath *as, const struct test_spec *sp) return fails; } -static void empty_get_test() +static void empty_get_test(void) { struct aspath *as = aspath_empty_get(); struct test_spec sp = {"", "", 0, 0, 0, 0, 0, 0}; @@ -1219,7 +1219,7 @@ static void aggregate_test(struct tests *t) } /* cmp_left tests */ -static void cmp_test() +static void cmp_test(void) { unsigned int i; #define CMP_TESTS_MAX (sizeof(left_compare) / sizeof(struct compare_tests)) diff --git a/tests/helpers/c/main.c b/tests/helpers/c/main.c index 768cf296ad..11db2dabc3 100644 --- a/tests/helpers/c/main.c +++ b/tests/helpers/c/main.c @@ -26,7 +26,7 @@ #include "memory.h" #include "memory_vty.h" -extern void test_init(); +extern void test_init(void); struct thread_master *master; @@ -56,12 +56,12 @@ static int test_timer(struct thread *thread) return 0; } -static void test_timer_init() +static void test_timer_init(void) { thread_add_timer(master, test_timer, &timer_count, 10, NULL); } -static void test_vty_init() +static void test_vty_init(void) { install_element(VIEW_NODE, &daemon_exit_cmd); } diff --git a/tests/lib/test_heavy.c b/tests/lib/test_heavy.c index e2a0a2d49a..afc7a08e66 100644 --- a/tests/lib/test_heavy.c +++ b/tests/lib/test_heavy.c @@ -92,12 +92,12 @@ DEFUN (clear_foo, return CMD_SUCCESS; } -static void slow_vty_init() +static void slow_vty_init(void) { install_element(VIEW_NODE, &clear_foo_cmd); } -void test_init() +void test_init(void) { slow_vty_init(); } diff --git a/tests/lib/test_heavy_thread.c b/tests/lib/test_heavy_thread.c index b3c6e4c2f7..d516ed0de0 100644 --- a/tests/lib/test_heavy_thread.c +++ b/tests/lib/test_heavy_thread.c @@ -122,7 +122,7 @@ DEFUN (clear_foo, return CMD_SUCCESS; } -void test_init() +void test_init(void) { install_element(VIEW_NODE, &clear_foo_cmd); } diff --git a/tests/lib/test_heavy_wq.c b/tests/lib/test_heavy_wq.c index 00ddc836d7..442b8c8380 100644 --- a/tests/lib/test_heavy_wq.c +++ b/tests/lib/test_heavy_wq.c @@ -139,7 +139,7 @@ DEFUN (clear_foo, return CMD_SUCCESS; } -static int heavy_wq_init() +static int heavy_wq_init(void) { heavy_wq = work_queue_new(master, "heavy_work_queue"); @@ -152,7 +152,7 @@ static int heavy_wq_init() return 0; } -void test_init() +void test_init(void) { install_element(VIEW_NODE, &clear_foo_cmd); heavy_wq_init(); diff --git a/tests/lib/test_table.c b/tests/lib/test_table.c index 2c2a010533..2b65040627 100644 --- a/tests/lib/test_table.c +++ b/tests/lib/test_table.c @@ -402,7 +402,7 @@ static void verify_prefix_iter_cmp(const char *p1, const char *p2, * * Tests comparision of prefixes according to order of iteration. */ -static void test_prefix_iter_cmp() +static void test_prefix_iter_cmp(void) { printf("\n\nTesting route_table_prefix_iter_cmp()\n"); diff --git a/tests/topotests/bfd-topo1/test_bfd_topo1.py b/tests/topotests/bfd-topo1/test_bfd_topo1.py index 91904c6aae..4fd4f97436 100644 --- a/tests/topotests/bfd-topo1/test_bfd_topo1.py +++ b/tests/topotests/bfd-topo1/test_bfd_topo1.py @@ -138,7 +138,7 @@ def test_bgp_convergence(): expected = json.loads(open(ref_file).read()) test_func = partial(topotest.router_json_cmp, router, 'show ip bgp summary json', expected) - _, res = topotest.run_and_expect(test_func, None, count=20, wait=0.5) + _, res = topotest.run_and_expect(test_func, None, count=125, wait=1.0) assertmsg = '{}: bgp did not converge'.format(router.name) assert res is None, assertmsg diff --git a/tools/start-stop-daemon.c b/tools/start-stop-daemon.c index f2a1e9434b..5903f8732f 100644 --- a/tools/start-stop-daemon.c +++ b/tools/start-stop-daemon.c @@ -280,7 +280,7 @@ static void add_namespace(const char *path) #endif #ifdef HAVE_LXC -static void set_namespaces() +static void set_namespaces(void) { struct namespace *namespace; int fd; @@ -294,7 +294,7 @@ static void set_namespaces() } } #else -static void set_namespaces() +static void set_namespaces(void) { if (!LIST_EMPTY(&namespace_head)) fatal("LCX namespaces not supported"); diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index 2b48f1f360..332fd248ca 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -248,8 +248,7 @@ foreach (sort keys %live) { # Output install_element print <<EOF; -void -vtysh_init_cmd () +void vtysh_init_cmd(void) { EOF diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 6cf45789dd..340c9be601 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -3464,7 +3464,7 @@ static const struct cmd_variable_handler vtysh_var_handler[] = { .completions = vtysh_autocomplete}, {.completions = NULL}}; -void vtysh_uninit() +void vtysh_uninit(void) { if (vty->of != stdout) fclose(vty->of); diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index fe12f82ef2..91e49c45c1 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -516,7 +516,7 @@ int vtysh_read_config(const char *config_default_dir) * be edited by hand. So, we handle only "write terminal" case here and * integrate vtysh specific conf with conf from daemons. */ -void vtysh_config_write() +void vtysh_config_write(void) { char line[81]; @@ -539,7 +539,7 @@ void vtysh_config_write() user_config_write(); } -void vtysh_config_init() +void vtysh_config_init(void) { config_top = list_new(); config_top->del = (void (*)(void *))line_del; diff --git a/vtysh/vtysh_user.c b/vtysh/vtysh_user.c index e575b71549..dcf8ca0470 100644 --- a/vtysh/vtysh_user.c +++ b/vtysh/vtysh_user.c @@ -122,7 +122,7 @@ static struct vtysh_user *user_lookup(const char *name) return NULL; } -void user_config_write() +void user_config_write(void) { struct listnode *node, *nnode; struct vtysh_user *user; diff --git a/yang/libyang_plugins/subdir.am b/yang/libyang_plugins/subdir.am index 956d22587c..7164789083 100644 --- a/yang/libyang_plugins/subdir.am +++ b/yang/libyang_plugins/subdir.am @@ -1,7 +1,12 @@ # # libyang user types # + +if LIBYANG_EXT_BUILTIN +lib_libfrr_la_SOURCES += yang/libyang_plugins/frr_user_types.c +else libyang_plugins_LTLIBRARIES += yang/libyang_plugins/frr_user_types.la +endif yang_libyang_plugins_frr_user_types_la_CFLAGS = $(WERROR) yang_libyang_plugins_frr_user_types_la_LDFLAGS = -avoid-version -module -shared -export-dynamic diff --git a/zebra/connected.c b/zebra/connected.c index ab66eb3324..c449855f6d 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -209,6 +209,7 @@ void connected_up(struct interface *ifp, struct connected *ifc) .ifindex = ifp->ifindex, .vrf_id = ifp->vrf_id, }; + uint32_t metric; if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL)) return; @@ -243,11 +244,13 @@ void connected_up(struct interface *ifp, struct connected *ifc) break; } + metric = (ifc->metric < (uint32_t)METRIC_MAX) ? + ifc->metric : ifp->metric; rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, &p, - NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0); + NULL, &nh, RT_TABLE_MAIN, metric, 0, 0, 0); rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, &p, - NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0); + NULL, &nh, RT_TABLE_MAIN, metric, 0, 0, 0); if (IS_ZEBRA_DEBUG_RIB_DETAILED) { char buf[PREFIX_STRLEN]; @@ -276,7 +279,7 @@ void connected_up(struct interface *ifp, struct connected *ifc) /* Add connected IPv4 route to the interface. */ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr, uint16_t prefixlen, struct in_addr *broad, - const char *label) + const char *label, uint32_t metric) { struct prefix_ipv4 *p; struct connected *ifc; @@ -288,6 +291,7 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr, ifc = connected_new(); ifc->ifp = ifp; ifc->flags = flags; + ifc->metric = metric; /* If we get a notification from the kernel, * we can safely assume the address is known to the kernel */ SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); @@ -500,7 +504,7 @@ void connected_delete_ipv4(struct interface *ifp, int flags, /* Add connected IPv6 route to the interface. */ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr, struct in6_addr *broad, uint16_t prefixlen, - const char *label) + const char *label, uint32_t metric) { struct prefix_ipv6 *p; struct connected *ifc; @@ -512,6 +516,7 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr, ifc = connected_new(); ifc->ifp = ifp; ifc->flags = flags; + ifc->metric = metric; /* If we get a notification from the kernel, * we can safely assume the address is known to the kernel */ SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED); diff --git a/zebra/connected.h b/zebra/connected.h index 415ecfd965..faba30b0d5 100644 --- a/zebra/connected.h +++ b/zebra/connected.h @@ -36,7 +36,8 @@ extern struct connected *connected_check_ptp(struct interface *ifp, extern void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr, uint16_t prefixlen, - struct in_addr *broad, const char *label); + struct in_addr *broad, const char *label, + uint32_t metric); extern void connected_delete_ipv4(struct interface *ifp, int flags, struct in_addr *addr, uint16_t prefixlen, @@ -49,7 +50,8 @@ extern void connected_down(struct interface *ifp, struct connected *ifc); extern void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *address, struct in6_addr *broad, - uint16_t prefixlen, const char *label); + uint16_t prefixlen, const char *label, + uint32_t metric); extern void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address, struct in6_addr *broad, uint16_t prefixlen); diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c index df79d285a3..debc151d75 100644 --- a/zebra/if_ioctl.c +++ b/zebra/if_ioctl.c @@ -236,7 +236,8 @@ static int if_getaddrs(void) } connected_add_ipv4(ifp, flags, &addr->sin_addr, - prefixlen, dest_pnt, NULL); + prefixlen, dest_pnt, NULL, + METRIC_MAX); } if (ifap->ifa_addr->sa_family == AF_INET6) { struct sockaddr_in6 *addr; @@ -258,7 +259,7 @@ static int if_getaddrs(void) #endif connected_add_ipv6(ifp, flags, &addr->sin6_addr, NULL, - prefixlen, NULL); + prefixlen, NULL, METRIC_MAX); } } diff --git a/zebra/if_ioctl_solaris.c b/zebra/if_ioctl_solaris.c index 0206d4938e..2c29930c3f 100644 --- a/zebra/if_ioctl_solaris.c +++ b/zebra/if_ioctl_solaris.c @@ -302,10 +302,11 @@ static int if_get_addr(struct interface *ifp, struct sockaddr *addr, /* Set address to the interface. */ if (af == AF_INET) connected_add_ipv4(ifp, flags, &SIN(addr)->sin_addr, prefixlen, - (struct in_addr *)dest_pnt, label); + (struct in_addr *)dest_pnt, label, + METRIC_MAX); else if (af == AF_INET6) connected_add_ipv6(ifp, flags, &SIN6(addr)->sin6_addr, NULL, - prefixlen, label); + prefixlen, label, METRIC_MAX); return 0; } diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 4e49c1fc58..47087d4ce0 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -731,6 +731,7 @@ static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family, /* Form the request, specifying filter (rtattr) if needed. */ memset(&req, 0, sizeof(req)); req.n.nlmsg_type = type; + req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req.ifm.ifi_family = family; @@ -923,6 +924,7 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) uint8_t flags = 0; char *label = NULL; struct zebra_ns *zns; + uint32_t metric = METRIC_MAX; zns = zebra_ns_lookup(ns_id); ifa = NLMSG_DATA(h); @@ -1031,6 +1033,9 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (label && strcmp(ifp->name, label) == 0) label = NULL; + if (tb[IFA_RT_PRIORITY]) + metric = *(uint32_t *)RTA_DATA(tb[IFA_RT_PRIORITY]); + /* Register interface address to the interface. */ if (ifa->ifa_family == AF_INET) { if (ifa->ifa_prefixlen > IPV4_MAX_BITLEN) { @@ -1043,7 +1048,8 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (h->nlmsg_type == RTM_NEWADDR) connected_add_ipv4(ifp, flags, (struct in_addr *)addr, ifa->ifa_prefixlen, - (struct in_addr *)broad, label); + (struct in_addr *)broad, label, + metric); else connected_delete_ipv4( ifp, flags, (struct in_addr *)addr, @@ -1069,7 +1075,8 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) connected_add_ipv6(ifp, flags, (struct in6_addr *)addr, (struct in6_addr *)broad, - ifa->ifa_prefixlen, label); + ifa->ifa_prefixlen, label, + metric); } else connected_delete_ipv6(ifp, (struct in6_addr *)addr, (struct in6_addr *)broad, diff --git a/zebra/irdp_interface.c b/zebra/irdp_interface.c index 3e50550dd2..ffc49d2c13 100644 --- a/zebra/irdp_interface.c +++ b/zebra/irdp_interface.c @@ -706,7 +706,7 @@ DEFUN (ip_irdp_debug_disable, return CMD_SUCCESS; } -void irdp_if_init() +void irdp_if_init(void) { hook_register(zebra_if_config_wr, irdp_config_write); hook_register(if_del, irdp_if_delete); diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 360f596b8f..c88bfbb101 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -1032,7 +1032,6 @@ int netlink_request(struct nlsock *nl, struct nlmsghdr *n) } /* Fill common fields for all requests. */ - n->nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; n->nlmsg_pid = nl->snl.nl_pid; n->nlmsg_seq = ++nl->seq; diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 84b06e579f..acd7f911dc 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -236,6 +236,7 @@ size_t _rta_get(caddr_t sap, void *destp, size_t destlen, bool checkaf); size_t rta_get(caddr_t sap, void *dest, size_t destlen); size_t rta_getattr(caddr_t sap, void *destp, size_t destlen); size_t rta_getsdlname(caddr_t sap, void *dest, short *destlen); +const char *rtatostr(unsigned int flags, char *buf, size_t buflen); /* Supported address family check. */ static inline int af_check(int family) @@ -273,7 +274,7 @@ size_t _rta_get(caddr_t sap, void *destp, size_t destlen, bool checkaf) if (sa->sa_family == AF_LINK) { sdl = (struct sockaddr_dl *)sa; if (sdl->sdl_index == 0 || sdl->sdl_nlen == 0) - copylen = sizeof(*sdl) - sizeof(sdl->sdl_data); + copylen = destlen; } if (copylen > destlen) { @@ -329,6 +330,85 @@ size_t rta_getsdlname(caddr_t sap, void *destp, short *destlen) return tlen; } +const char *rtatostr(unsigned int flags, char *buf, size_t buflen) +{ + const char *flagstr, *bufstart; + int bit, wlen; + char ustr[32]; + + /* Hold the pointer to the buffer beginning. */ + bufstart = buf; + + for (bit = 1; bit; bit <<= 1) { + if ((flags & bit) == 0) + continue; + + switch (bit) { + case RTA_DST: + flagstr = "DST"; + break; + case RTA_GATEWAY: + flagstr = "GATEWAY"; + break; + case RTA_NETMASK: + flagstr = "NETMASK"; + break; +#ifdef RTA_GENMASK + case RTA_GENMASK: + flagstr = "GENMASK"; + break; +#endif /* RTA_GENMASK */ + case RTA_IFP: + flagstr = "IFP"; + break; + case RTA_IFA: + flagstr = "IFA"; + break; +#ifdef RTA_AUTHOR + case RTA_AUTHOR: + flagstr = "AUTHOR"; + break; +#endif /* RTA_AUTHOR */ + case RTA_BRD: + flagstr = "BRD"; + break; +#ifdef RTA_SRC + case RTA_SRC: + flagstr = "SRC"; + break; +#endif /* RTA_SRC */ +#ifdef RTA_SRCMASK + case RTA_SRCMASK: + flagstr = "SRCMASK"; + break; +#endif /* RTA_SRCMASK */ +#ifdef RTA_LABEL + case RTA_LABEL: + flagstr = "LABEL"; + break; +#endif /* RTA_LABEL */ + + default: + snprintf(ustr, sizeof(ustr), "0x%x", bit); + flagstr = ustr; + break; + } + + wlen = snprintf(buf, buflen, "%s,", flagstr); + buf += wlen; + buflen -= wlen; + } + + /* Check for empty buffer. */ + if (bufstart != buf) + buf--; + + /* Remove the last comma. */ + *buf = 0; + + return bufstart; +} + /* Dump routing table flag for debug purpose. */ static void rtm_flag_dump(int flag) { @@ -443,6 +523,7 @@ int ifm_read(struct if_msghdr *ifm) short ifnlen = 0; int maskbit; caddr_t cp; + char fbuf[64]; /* terminate ifname at head (for strnlen) and tail (for safety) */ ifname[IFNAMSIZ - 1] = '\0'; @@ -488,8 +569,9 @@ int ifm_read(struct if_msghdr *ifm) } if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("%s: sdl ifname %s", __func__, - (ifnlen ? ifname : "(nil)")); + zlog_debug("%s: sdl ifname %s addrs {%s}", __func__, + (ifnlen ? ifname : "(nil)"), + rtatostr(ifm->ifm_addrs, fbuf, sizeof(fbuf))); /* * Look up on ifindex first, because ifindices are the primary handle @@ -687,6 +769,7 @@ static void ifam_read_mesg(struct ifa_msghdr *ifm, union sockunion *addr, union sockunion dst; union sockunion gateway; int maskbit; + char fbuf[64]; pnt = (caddr_t)(ifm + 1); end = ((caddr_t)ifm) + ifm->ifam_msglen; @@ -736,33 +819,35 @@ static void ifam_read_mesg(struct ifa_msghdr *ifm, union sockunion *addr, } if (IS_ZEBRA_DEBUG_KERNEL) { - int family = sockunion_family(addr); - switch (family) { + switch (sockunion_family(addr)) { case AF_INET: case AF_INET6: { char buf[4][INET6_ADDRSTRLEN]; + int masklen = + (sockunion_family(addr) == AF_INET) + ? ip_masklen(mask->sin.sin_addr) + : ip6_masklen(mask->sin6.sin6_addr); zlog_debug( - "%s: ifindex %d, ifname %s, ifam_addrs 0x%x, " + "%s: ifindex %d, ifname %s, ifam_addrs {%s}, " "ifam_flags 0x%x, addr %s/%d broad %s dst %s " "gateway %s", __func__, ifm->ifam_index, - (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs, + (ifnlen ? ifname : "(nil)"), + rtatostr(ifm->ifam_addrs, fbuf, sizeof(fbuf)), ifm->ifam_flags, - inet_ntop(family, &addr->sin.sin_addr, buf[0], - sizeof(buf[0])), - ip_masklen(mask->sin.sin_addr), - inet_ntop(family, &brd->sin.sin_addr, buf[1], - sizeof(buf[1])), - inet_ntop(family, &dst.sin.sin_addr, buf[2], - sizeof(buf[2])), - inet_ntop(family, &gateway.sin.sin_addr, buf[3], - sizeof(buf[3]))); + sockunion2str(addr, buf[0], sizeof(buf[0])), + masklen, + sockunion2str(brd, buf[1], sizeof(buf[1])), + sockunion2str(&dst, buf[2], sizeof(buf[2])), + sockunion2str(&gateway, buf[2], + sizeof(buf[2]))); } break; default: - zlog_debug("%s: ifindex %d, ifname %s, ifam_addrs 0x%x", + zlog_debug("%s: ifindex %d, ifname %s, ifam_addrs {%s}", __func__, ifm->ifam_index, (ifnlen ? ifname : "(nil)"), - ifm->ifam_addrs); + rtatostr(ifm->ifam_addrs, fbuf, + sizeof(fbuf))); break; } } @@ -821,7 +906,8 @@ int ifam_read(struct ifa_msghdr *ifam) connected_add_ipv4(ifp, flags, &addr.sin.sin_addr, ip_masklen(mask.sin.sin_addr), &brd.sin.sin_addr, - (isalias ? ifname : NULL)); + (isalias ? ifname : NULL), + METRIC_MAX); else connected_delete_ipv4(ifp, flags, &addr.sin.sin_addr, ip_masklen(mask.sin.sin_addr), @@ -838,7 +924,8 @@ int ifam_read(struct ifa_msghdr *ifam) connected_add_ipv6(ifp, flags, &addr.sin6.sin6_addr, NULL, ip6_masklen(mask.sin6.sin6_addr), - (isalias ? ifname : NULL)); + (isalias ? ifname : NULL), + METRIC_MAX); else connected_delete_ipv6(ifp, &addr.sin6.sin6_addr, NULL, ip6_masklen(mask.sin6.sin6_addr)); @@ -909,7 +996,7 @@ static int rtm_read_mesg(struct rt_msghdr *rtm, union sockunion *dest, pnt += rta_get(pnt, gate, sizeof(*gate)); break; case RTA_NETMASK: - pnt += rta_get(pnt, mask, sizeof(*mask)); + pnt += rta_getattr(pnt, mask, sizeof(*mask)); break; case RTA_IFP: pnt += rta_getsdlname(pnt, ifname, ifnlen); @@ -950,6 +1037,7 @@ void rtm_read(struct rt_msghdr *rtm) struct prefix p; ifindex_t ifindex = 0; afi_t afi; + char fbuf[64]; zebra_flags = 0; @@ -959,9 +1047,10 @@ void rtm_read(struct rt_msghdr *rtm) if (!(flags & RTF_DONE)) return; if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("%s: got rtm of type %d (%s)", __func__, + zlog_debug("%s: got rtm of type %d (%s) addrs {%s}", __func__, rtm->rtm_type, - lookup_msg(rtm_type_str, rtm->rtm_type, NULL)); + lookup_msg(rtm_type_str, rtm->rtm_type, NULL), + rtatostr(rtm->rtm_addrs, fbuf, sizeof(fbuf))); #ifdef RTF_CLONED /*bsdi, netbsd 1.6*/ if (flags & RTF_CLONED) @@ -1207,12 +1296,14 @@ int rtm_write(int message, union sockunion *dest, union sockunion *mask, /* For debug purpose. */ static void rtmsg_debug(struct rt_msghdr *rtm) { + char fbuf[64]; + zlog_debug("Kernel: Len: %d Type: %s", rtm->rtm_msglen, lookup_msg(rtm_type_str, rtm->rtm_type, NULL)); rtm_flag_dump(rtm->rtm_flags); zlog_debug("Kernel: message seq %d", rtm->rtm_seq); - zlog_debug("Kernel: pid %lld, rtm_addrs 0x%x", (long long)rtm->rtm_pid, - rtm->rtm_addrs); + zlog_debug("Kernel: pid %lld, rtm_addrs {%s}", (long long)rtm->rtm_pid, + rtatostr(rtm->rtm_addrs, fbuf, sizeof(fbuf))); } /* This is pretty gross, better suggestions welcome -- mhandler */ diff --git a/zebra/label_manager.c b/zebra/label_manager.c index bfad8ea643..13472059a0 100644 --- a/zebra/label_manager.c +++ b/zebra/label_manager.c @@ -480,7 +480,7 @@ int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start, } -void label_manager_close() +void label_manager_close(void) { list_delete(&lbl_mgr.lc_list); stream_free(obuf); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index b9c1f0aefd..c5769ae06f 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -405,7 +405,7 @@ void zebra_interface_up_update(struct interface *ifp) if (ifp->ptm_status || !ifp->ptm_enable) { for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) - if (client->ifinfo) { + if (vrf_bitmap_check(client->ifinfo, ifp->vrf_id)) { zsend_interface_update(ZEBRA_INTERFACE_UP, client, ifp); zsend_interface_link_params(client, ifp); @@ -439,7 +439,7 @@ void zebra_interface_add_update(struct interface *ifp) ifp->vrf_id); for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) - if (client->ifinfo) { + if (vrf_bitmap_check(client->ifinfo, ifp->vrf_id)) { client->ifadd_cnt++; zsend_interface_add(client, ifp); zsend_interface_link_params(client, ifp); @@ -812,6 +812,6 @@ void zebra_interface_parameters_update(struct interface *ifp) ifp->name, ifp->vrf_id); for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) - if (client->ifinfo) + if (vrf_bitmap_check(client->ifinfo, ifp->vrf_id)) zsend_interface_link_params(client, ifp); } diff --git a/zebra/rt.h b/zebra/rt.h index 0317dc85ba..0b14a3ef36 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -32,12 +32,15 @@ #include "zebra/zebra_dplane.h" /* - * Update or delete a prefix from the kernel, + * Update or delete a route or LSP from the kernel, * using info from a dataplane context. */ extern enum zebra_dplane_result kernel_route_update( struct zebra_dplane_ctx *ctx); +extern enum zebra_dplane_result kernel_lsp_update( + struct zebra_dplane_ctx *ctx); + extern int kernel_address_add_ipv4(struct interface *, struct connected *); extern int kernel_address_delete_ipv4(struct interface *, struct connected *); extern int kernel_address_add_ipv6(struct interface *, struct connected *); @@ -47,21 +50,6 @@ extern int kernel_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, extern int kernel_interface_set_master(struct interface *master, struct interface *slave); -extern enum zebra_dplane_result kernel_add_lsp(zebra_lsp_t *lsp); -extern enum zebra_dplane_result kernel_upd_lsp(zebra_lsp_t *lsp); -extern enum zebra_dplane_result kernel_del_lsp(zebra_lsp_t *lsp); - -/* - * Add the ability to pass back up the lsp install/delete - * success/failure. - * - * This functions goal is similiar to kernel_route_rib_pass_fail - * in that we are separating out the mechanics for - * the install/failure to set/unset flags and to notify - * as needed. - */ -extern void kernel_lsp_pass_fail(zebra_lsp_t *lsp, enum zebra_dplane_status res); - extern int mpls_kernel_init(void); extern uint32_t kernel_get_speed(struct interface *ifp); @@ -90,8 +78,13 @@ extern void kernel_terminate(struct zebra_ns *zns, bool complete); extern void macfdb_read(struct zebra_ns *zns); extern void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, struct interface *br_if); +extern void macfdb_read_specific_mac(struct zebra_ns *zns, + struct interface *br_if, + struct ethaddr *mac, vlanid_t vid); extern void neigh_read(struct zebra_ns *zns); extern void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *ifp); +extern void neigh_read_specific_ip(struct ipaddr *ip, + struct interface *vlan_if); extern void route_read(struct zebra_ns *zns); #endif /* _ZEBRA_RT_H */ diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index ae4bc52727..ce2d25862d 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -879,6 +879,7 @@ static int netlink_request_route(struct zebra_ns *zns, int family, int type) /* Form the request, specifying filter (rtattr) if needed. */ memset(&req, 0, sizeof(req)); req.n.nlmsg_type = type; + req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.rtm.rtm_family = family; @@ -2127,6 +2128,7 @@ static int netlink_request_macs(struct nlsock *netlink_cmd, int family, /* Form the request, specifying filter (rtattr) if needed. */ memset(&req, 0, sizeof(req)); req.n.nlmsg_type = type; + req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req.ifm.ifi_family = family; if (master_ifindex) @@ -2195,6 +2197,70 @@ int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, return ret; } + +/* Request for MAC FDB for a specific MAC address in VLAN from the kernel */ +static int netlink_request_specific_mac_in_bridge(struct zebra_ns *zns, + int family, + int type, + struct interface *br_if, + struct ethaddr *mac, + vlanid_t vid) +{ + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; + struct zebra_if *br_zif; + char buf[ETHER_ADDR_STRLEN]; + + memset(&req, 0, sizeof(req)); + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.n.nlmsg_type = type; /* RTM_GETNEIGH */ + req.n.nlmsg_flags = NLM_F_REQUEST; + req.ndm.ndm_family = family; /* AF_BRIDGE */ + /* req.ndm.ndm_state = NUD_REACHABLE; */ + + addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6); + + br_zif = (struct zebra_if *)br_if->info; + if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0) + addattr16(&req.n, sizeof(req), NDA_VLAN, vid); + + addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: Tx family %s IF %s(%u) MAC %s vid %u", + __PRETTY_FUNCTION__, + nl_family_to_str(req.ndm.ndm_family), br_if->name, + br_if->ifindex, + prefix_mac2str(mac, buf, sizeof(buf)), vid); + + return netlink_request(&zns->netlink_cmd, &req.n); +} + +int netlink_macfdb_read_specific_mac(struct zebra_ns *zns, + struct interface *br_if, + struct ethaddr *mac, vlanid_t vid) +{ + int ret = 0; + struct zebra_dplane_info dp_info; + + zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/); + + /* Get bridge FDB table for specific bridge - we do the VLAN filtering. + */ + ret = netlink_request_specific_mac_in_bridge(zns, AF_BRIDGE, + RTM_GETNEIGH, + br_if, mac, vid); + if (ret < 0) + return ret; + + ret = netlink_parse_info(netlink_macfdb_table, &zns->netlink_cmd, + &dp_info, 1, 0); + + return ret; +} static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid, struct ethaddr *mac, struct in_addr vtep_ip, int cmd, bool sticky) @@ -2454,6 +2520,7 @@ static int netlink_request_neigh(struct nlsock *netlink_cmd, int family, /* Form the request, specifying filter (rtattr) if needed. */ memset(&req, 0, sizeof(req)); req.n.nlmsg_type = type; + req.n.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); req.ndm.ndm_family = family; if (ifindex) @@ -2505,6 +2572,73 @@ int netlink_neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if) return ret; } +/* + * Request for a specific IP in VLAN (SVI) device from IP Neighbor table, + * read using netlink interface. + */ +static int netlink_request_specific_neigh_in_vlan(struct zebra_ns *zns, + int type, struct ipaddr *ip, + ifindex_t ifindex) +{ + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf[256]; + } req; + int ipa_len; + + /* Form the request, specifying filter (rtattr) if needed. */ + memset(&req, 0, sizeof(req)); + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)); + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = type; /* RTM_GETNEIGH */ + req.ndm.ndm_ifindex = ifindex; + + if (IS_IPADDR_V4(ip)) { + ipa_len = IPV4_MAX_BYTELEN; + req.ndm.ndm_family = AF_INET; + + } else { + ipa_len = IPV6_MAX_BYTELEN; + req.ndm.ndm_family = AF_INET6; + } + + addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len); + + return netlink_request(&zns->netlink_cmd, &req.n); +} + +int netlink_neigh_read_specific_ip(struct ipaddr *ip, + struct interface *vlan_if) +{ + int ret = 0; + struct zebra_ns *zns; + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(vlan_if->vrf_id); + char buf[INET6_ADDRSTRLEN]; + struct zebra_dplane_info dp_info; + + zns = zvrf->zns; + + zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/); + + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: neigh request IF %s(%u) IP %s vrf_id %u", + __PRETTY_FUNCTION__, vlan_if->name, + vlan_if->ifindex, + ipaddr2str(ip, buf, sizeof(buf)), + vlan_if->vrf_id); + + ret = netlink_request_specific_neigh_in_vlan(zns, RTM_GETNEIGH, ip, + vlan_if->ifindex); + if (ret < 0) + return ret; + + ret = netlink_parse_info(netlink_neigh_table, &zns->netlink_cmd, + &dp_info, 1, 0); + + return ret; +} + int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id) { int len; @@ -2616,16 +2750,16 @@ int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip) } /* - * MPLS label forwarding table change via netlink interface. + * MPLS label forwarding table change via netlink interface, using dataplane + * context information. */ -int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) +int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx) { mpls_lse_t lse; zebra_nhlfe_t *nhlfe; struct nexthop *nexthop = NULL; unsigned int nexthop_num; const char *routedesc; - struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); int route_type; struct { @@ -2634,14 +2768,14 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) char buf[NL_PKT_BUF_SIZE]; } req; - memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE); + memset(&req, 0, sizeof(req) - NL_PKT_BUF_SIZE); /* * Count # nexthops so we can decide whether to use singlepath * or multipath case. */ nexthop_num = 0; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + for (nhlfe = dplane_ctx_get_nhlfe(ctx); nhlfe; nhlfe = nhlfe->next) { nexthop = nhlfe->nexthop; if (!nexthop) continue; @@ -2650,8 +2784,7 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED) && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) nexthop_num++; - } else /* DEL */ - { + } else { /* DEL */ /* Count all installed NHLFEs */ if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED) && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) @@ -2659,13 +2792,14 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) } } - if ((nexthop_num == 0) || (!lsp->best_nhlfe && (cmd != RTM_DELROUTE))) + if ((nexthop_num == 0) || + (!dplane_ctx_get_best_nhlfe(ctx) && (cmd != RTM_DELROUTE))) return 0; req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; req.n.nlmsg_type = cmd; - req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; + req.n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid; req.r.rtm_family = AF_MPLS; req.r.rtm_table = RT_TABLE_MAIN; @@ -2678,23 +2812,26 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) req.n.nlmsg_flags |= NLM_F_REPLACE; /* set the protocol value if installing */ - route_type = re_type_from_lsp_type(lsp->best_nhlfe->type); + route_type = re_type_from_lsp_type( + dplane_ctx_get_best_nhlfe(ctx)->type); req.r.rtm_protocol = zebra2proto(route_type); } /* Fill destination */ - lse = mpls_lse_encode(lsp->ile.in_label, 0, 0, 1); - addattr_l(&req.n, sizeof req, RTA_DST, &lse, sizeof(mpls_lse_t)); + lse = mpls_lse_encode(dplane_ctx_get_in_label(ctx), 0, 0, 1); + addattr_l(&req.n, sizeof(req), RTA_DST, &lse, sizeof(mpls_lse_t)); /* Fill nexthops (paths) based on single-path or multipath. The paths * chosen depend on the operation. */ if (nexthop_num == 1) { routedesc = "single-path"; - _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); + _netlink_mpls_debug(cmd, dplane_ctx_get_in_label(ctx), + routedesc); nexthop_num = 0; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + for (nhlfe = dplane_ctx_get_nhlfe(ctx); + nhlfe; nhlfe = nhlfe->next) { nexthop = nhlfe->nexthop; if (!nexthop) continue; @@ -2709,15 +2846,16 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)))) { /* Add the gateway */ - _netlink_mpls_build_singlepath(routedesc, nhlfe, - &req.n, &req.r, - sizeof req, cmd); + _netlink_mpls_build_singlepath( + routedesc, nhlfe, + &req.n, &req.r, + sizeof(req), cmd); + nexthop_num++; break; } } - } else /* Multipath case */ - { + } else { /* Multipath case */ char buf[NL_PKT_BUF_SIZE]; struct rtattr *rta = (void *)buf; struct rtnexthop *rtnh; @@ -2728,10 +2866,12 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) rtnh = RTA_DATA(rta); routedesc = "multipath"; - _netlink_mpls_debug(cmd, lsp->ile.in_label, routedesc); + _netlink_mpls_debug(cmd, dplane_ctx_get_in_label(ctx), + routedesc); nexthop_num = 0; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + for (nhlfe = dplane_ctx_get_nhlfe(ctx); + nhlfe; nhlfe = nhlfe->next) { nexthop = nhlfe->nexthop; if (!nexthop) continue; @@ -2762,7 +2902,7 @@ int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp) } /* Talk to netlink socket. */ - return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + return netlink_talk_info(netlink_talk_filter, &req.n, + dplane_ctx_get_ns(ctx), 0); } #endif /* HAVE_NETLINK */ diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index cefd1996a9..473ad98a3f 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -24,6 +24,7 @@ #ifdef HAVE_NETLINK #include "zebra/zebra_mpls.h" +#include "zebra/zebra_dplane.h" #define NL_DEFAULT_ROUTE_METRIC 20 @@ -58,7 +59,8 @@ void rt_netlink_init(void); -extern int netlink_mpls_multipath(int cmd, zebra_lsp_t *lsp); +/* MPLS label forwarding table change, using dataplane context information. */ +extern int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx); extern int netlink_route_change(struct nlmsghdr *h, ns_id_t ns_id, int startup); extern int netlink_route_read(struct zebra_ns *zns); @@ -71,6 +73,11 @@ extern int netlink_macfdb_read_for_bridge(struct zebra_ns *zns, extern int netlink_neigh_read(struct zebra_ns *zns); extern int netlink_neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if); +extern int netlink_macfdb_read_specific_mac(struct zebra_ns *zns, + struct interface *br_if, + struct ethaddr *mac, uint16_t vid); +extern int netlink_neigh_read_specific_ip(struct ipaddr *ip, + struct interface *vlan_if); #endif /* HAVE_NETLINK */ diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index 29e9bf82f0..abcff22b6b 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -44,30 +44,6 @@ extern struct zebra_privs_t zserv_privs; -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN -/* Adjust netmask socket length. Return value is a adjusted sin_len - value. */ -static int sin_masklen(struct in_addr mask) -{ - char *p, *lim; - int len; - struct sockaddr_in sin; - - if (mask.s_addr == 0) - return sizeof(long); - - sin.sin_addr = mask; - len = sizeof(struct sockaddr_in); - - lim = (char *)&sin.sin_addr; - p = lim + sizeof(sin.sin_addr); - - while (*--p == 0 && p >= lim) - len--; - return len; -} -#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ - #ifdef __OpenBSD__ static int kernel_rtm_add_labels(struct mpls_label_stack *nh_label, struct sockaddr_mpls *smpls) @@ -89,30 +65,6 @@ static int kernel_rtm_add_labels(struct mpls_label_stack *nh_label, } #endif -#ifdef SIN6_LEN -/* Calculate sin6_len value for netmask socket value. */ -static int sin6_masklen(struct in6_addr mask) -{ - struct sockaddr_in6 sin6; - char *p, *lim; - int len; - - if (IN6_IS_ADDR_UNSPECIFIED(&mask)) - return sizeof(long); - - sin6.sin6_addr = mask; - len = sizeof(struct sockaddr_in6); - - lim = (char *)&sin6.sin6_addr; - p = lim + sizeof(sin6.sin6_addr); - - while (*--p == 0 && p >= lim) - len--; - - return len; -} -#endif /* SIN6_LEN */ - /* Interface between zebra message and rtm message. */ static int kernel_rtm(int cmd, const struct prefix *p, const struct nexthop_group *ng, uint32_t metric) @@ -128,11 +80,11 @@ static int kernel_rtm(int cmd, const struct prefix *p, ifindex_t ifindex = 0; bool gate = false; int error; + char gate_buf[INET6_BUFSIZ]; char prefix_buf[PREFIX_STRLEN]; enum blackhole_type bh_type = BLACKHOLE_UNSPEC; - if (IS_ZEBRA_DEBUG_RIB) - prefix2str(p, prefix_buf, sizeof(prefix_buf)); + prefix2str(p, prefix_buf, sizeof(prefix_buf)); /* * We only have the ability to ADD or DELETE at this point @@ -154,23 +106,21 @@ static int kernel_rtm(int cmd, const struct prefix *p, switch (p->family) { case AF_INET: sin_dest.sin.sin_family = AF_INET; -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_dest.sin.sin_len = sizeof(sin_dest); - sin_gate.sin.sin_len = sizeof(sin_gate); -#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ sin_dest.sin.sin_addr = p->u.prefix4; sin_gate.sin.sin_family = AF_INET; +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin_dest.sin.sin_len = sizeof(struct sockaddr_in); + sin_gate.sin.sin_len = sizeof(struct sockaddr_in); +#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ break; case AF_INET6: sin_dest.sin6.sin6_family = AF_INET6; -#ifdef SIN6_LEN - sin_dest.sin6.sin6_len = sizeof(sin_dest); -#endif /* SIN6_LEN */ sin_dest.sin6.sin6_addr = p->u.prefix6; sin_gate.sin6.sin6_family = AF_INET6; -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_gate.sin6.sin6_len = sizeof(sin_gate); -#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin_dest.sin6.sin6_len = sizeof(struct sockaddr_in6); + sin_gate.sin6.sin6_len = sizeof(struct sockaddr_in6); +#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ break; } @@ -185,13 +135,16 @@ static int kernel_rtm(int cmd, const struct prefix *p, smplsp = NULL; gate = false; - char gate_buf[INET_ADDRSTRLEN] = "NULL"; + snprintf(gate_buf, sizeof(gate_buf), "NULL"); switch (nexthop->type) { case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: sin_gate.sin.sin_addr = nexthop->gate.ipv4; sin_gate.sin.sin_family = AF_INET; +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin_gate.sin.sin_len = sizeof(struct sockaddr_in); +#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ ifindex = nexthop->ifindex; gate = true; break; @@ -199,6 +152,9 @@ static int kernel_rtm(int cmd, const struct prefix *p, case NEXTHOP_TYPE_IPV6_IFINDEX: sin_gate.sin6.sin6_addr = nexthop->gate.ipv6; sin_gate.sin6.sin6_family = AF_INET6; +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin_gate.sin6.sin6_len = sizeof(struct sockaddr_in6); +#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ ifindex = nexthop->ifindex; /* Under kame set interface index to link local address */ #ifdef KAME @@ -227,6 +183,10 @@ static int kernel_rtm(int cmd, const struct prefix *p, struct in_addr loopback; loopback.s_addr = htonl(INADDR_LOOPBACK); sin_gate.sin.sin_addr = loopback; +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin_gate.sin.sin_len = + sizeof(struct sockaddr_in); +#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ gate = true; } break; @@ -239,26 +199,26 @@ static int kernel_rtm(int cmd, const struct prefix *p, case AF_INET: masklen2ip(p->prefixlen, &sin_mask.sin.sin_addr); sin_mask.sin.sin_family = AF_INET; -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - sin_mask.sin.sin_len = sin_masklen( - sin_mask.sin.sin_addr); -#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin_mask.sin.sin_len = sizeof(struct sockaddr_in); +#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ break; case AF_INET6: masklen2ip6(p->prefixlen, &sin_mask.sin6.sin6_addr); sin_mask.sin6.sin6_family = AF_INET6; -#ifdef SIN6_LEN - sin_mask.sin6.sin6_len = sin6_masklen( - sin_mask.sin6.sin6_addr); -#endif /* SIN6_LEN */ +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN + sin_mask.sin6.sin6_len = sizeof(struct sockaddr_in6); +#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ break; } #ifdef __OpenBSD__ - if (nexthop->nh_label - && !kernel_rtm_add_labels(nexthop->nh_label, &smpls)) - continue; - smplsp = (union sockunion *)&smpls; + if (nexthop->nh_label) { + if (kernel_rtm_add_labels(nexthop->nh_label, + &smpls) != 0) + continue; + smplsp = (union sockunion *)&smpls; + } #endif error = rtm_write(cmd, &sin_dest, &sin_mask, gate ? &sin_gate : NULL, smplsp, @@ -266,13 +226,29 @@ static int kernel_rtm(int cmd, const struct prefix *p, if (IS_ZEBRA_DEBUG_KERNEL) { if (!gate) { - zlog_debug("%s: %s: attention! gate not found for re", - __func__, prefix_buf); - } else - inet_ntop(p->family == AFI_IP ? AF_INET - : AF_INET6, - &sin_gate.sin.sin_addr, - gate_buf, INET_ADDRSTRLEN); + zlog_debug( + "%s: %s: attention! gate not found for re", + __func__, prefix_buf); + } else { + switch (p->family) { + case AFI_IP: + inet_ntop(AF_INET, + &sin_gate.sin.sin_addr, + gate_buf, sizeof(gate_buf)); + break; + + case AFI_IP6: + inet_ntop(AF_INET6, + &sin_gate.sin6.sin6_addr, + gate_buf, sizeof(gate_buf)); + break; + + default: + snprintf(gate_buf, sizeof(gate_buf), + "(invalid-af)"); + break; + } + } } switch (error) { /* We only flag nexthops as being in FIB if @@ -301,12 +277,11 @@ static int kernel_rtm(int cmd, const struct prefix *p, /* Note any unexpected status returns */ default: - flog_err(EC_LIB_SYSTEM_CALL, - "%s: %s: rtm_write() unexpectedly returned %d for command %s", - __func__, - prefix2str(p, prefix_buf, - sizeof(prefix_buf)), - error, lookup_msg(rtm_type_str, cmd, NULL)); + flog_err( + EC_LIB_SYSTEM_CALL, + "%s: %s: rtm_write() unexpectedly returned %d for command %s", + __func__, prefix_buf, error, + lookup_msg(rtm_type_str, cmd, NULL)); break; } } /* for (ALL_NEXTHOPS(...))*/ @@ -314,9 +289,9 @@ static int kernel_rtm(int cmd, const struct prefix *p, /* If there was no useful nexthop, then complain. */ if (nexthop_num == 0) { if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("%s: No useful nexthops were found in RIB prefix %s", - __func__, prefix2str(p, prefix_buf, - sizeof(prefix_buf))); + zlog_debug( + "%s: No useful nexthops were found in RIB prefix %s", + __func__, prefix_buf); return 1; } diff --git a/zebra/rtread_getmsg.c b/zebra/rtread_getmsg.c index c1bd68f9dc..725bb63a0d 100644 --- a/zebra/rtread_getmsg.c +++ b/zebra/rtread_getmsg.c @@ -261,6 +261,11 @@ void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, { } +void macfdb_read_specific_mac(struct zebra_ns *zns, struct interface *br_if, + struct ethaddr *mac, vlanid_t vid) +{ +} + void neigh_read(struct zebra_ns *zns) { } @@ -269,6 +274,10 @@ void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if) { } +void neigh_read_specific_ip(struct ipaddr *ip, struct interface *vlan_if) +{ +} + void kernel_read_pbr_rules(struct zebra_ns *zns) { } diff --git a/zebra/rtread_netlink.c b/zebra/rtread_netlink.c index e992046078..fbca47351d 100644 --- a/zebra/rtread_netlink.c +++ b/zebra/rtread_netlink.c @@ -45,6 +45,12 @@ void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, netlink_macfdb_read_for_bridge(zns, ifp, br_if); } +void macfdb_read_specific_mac(struct zebra_ns *zns, struct interface *br_if, + struct ethaddr *mac, vlanid_t vid) +{ +netlink_macfdb_read_specific_mac(zns, br_if, mac, vid); +} + void neigh_read(struct zebra_ns *zns) { netlink_neigh_read(zns); @@ -55,6 +61,11 @@ void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if) netlink_neigh_read_for_vlan(zns, vlan_if); } +void neigh_read_specific_ip(struct ipaddr *ip, struct interface *vlan_if) +{ + netlink_neigh_read_specific_ip(ip, vlan_if); +} + void kernel_read_pbr_rules(struct zebra_ns *zns) { netlink_rules_read(zns); diff --git a/zebra/rtread_sysctl.c b/zebra/rtread_sysctl.c index f88586a6ea..4150092d4a 100644 --- a/zebra/rtread_sysctl.c +++ b/zebra/rtread_sysctl.c @@ -88,6 +88,11 @@ void macfdb_read_for_bridge(struct zebra_ns *zns, struct interface *ifp, { } +void macfdb_read_specific_mac(struct zebra_ns *zns, struct interface *br_if, + struct ethaddr *mac, vlanid_t vid) +{ +} + void neigh_read(struct zebra_ns *zns) { } @@ -96,6 +101,10 @@ void neigh_read_for_vlan(struct zebra_ns *zns, struct interface *vlan_if) { } +void neigh_read_specific_ip(struct ipaddr *ip, struct interface *vlan_if) +{ +} + void kernel_read_pbr_rules(struct zebra_ns *zns) { } diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 15f9da0cba..b6d0948d35 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -209,7 +209,7 @@ int zsend_interface_link_params(struct zserv *client, struct interface *ifp) struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); /* Check this client need interface information. */ - if (!client->ifinfo) { + if (!vrf_bitmap_check(client->ifinfo, ifp->vrf_id)) { stream_free(s); return 0; } @@ -530,6 +530,7 @@ int zsend_redistribute_route(int cmd, struct zserv *client, memset(&api, 0, sizeof(api)); api.vrf_id = re->vrf_id; api.type = re->type; + api.safi = SAFI_UNICAST; api.instance = re->instance; api.flags = re->flags; @@ -1108,7 +1109,8 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf)); /* Anything not AF_INET/INET6 has been filtered out above */ if (!exist) - zebra_evaluate_rnh(zvrf, p.family, 1, type, &p); + zebra_evaluate_rnh(zvrf, family2afi(p.family), 1, type, + &p); } stream_failure: @@ -1324,6 +1326,7 @@ static void zread_interface_add(ZAPI_HANDLER_ARGS) continue; zsend_interface_add(client, ifp); + zsend_interface_link_params(client, ifp); zsend_interface_addresses(client, ifp); } } @@ -1394,147 +1397,150 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) else re->table = zvrf->table_id; + if (!CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP) + || api.nexthop_num == 0) { + char buf_prefix[PREFIX_STRLEN]; + + prefix2str(&api.prefix, buf_prefix, sizeof(buf_prefix)); + flog_warn(EC_ZEBRA_RX_ROUTE_NO_NEXTHOPS, + "%s: received a route without nexthops for prefix %s", + __func__, buf_prefix); + XFREE(MTYPE_RE, re); + return; + } + /* * TBD should _all_ of the nexthop add operations use * api_nh->vrf_id instead of re->vrf_id ? I only changed * for cases NEXTHOP_TYPE_IPV4 and NEXTHOP_TYPE_IPV6. */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) - for (i = 0; i < api.nexthop_num; i++) { - api_nh = &api.nexthops[i]; - ifindex_t ifindex = 0; - - if (IS_ZEBRA_DEBUG_RECV) - zlog_debug("nh type %d", api_nh->type); - - switch (api_nh->type) { - case NEXTHOP_TYPE_IFINDEX: - nexthop = route_entry_nexthop_ifindex_add( - re, api_nh->ifindex, api_nh->vrf_id); - break; - case NEXTHOP_TYPE_IPV4: - if (IS_ZEBRA_DEBUG_RECV) { - char nhbuf[INET6_ADDRSTRLEN] = {0}; - - inet_ntop(AF_INET, &api_nh->gate.ipv4, - nhbuf, INET6_ADDRSTRLEN); - zlog_debug("%s: nh=%s, vrf_id=%d", - __func__, nhbuf, - api_nh->vrf_id); - } - nexthop = route_entry_nexthop_ipv4_add( - re, &api_nh->gate.ipv4, NULL, - api_nh->vrf_id); - break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - - memset(&vtep_ip, 0, sizeof(struct ipaddr)); - if (CHECK_FLAG(api.flags, - ZEBRA_FLAG_EVPN_ROUTE)) { - ifindex = get_l3vni_svi_ifindex(vrf_id); - } else { - ifindex = api_nh->ifindex; - } - - if (IS_ZEBRA_DEBUG_RECV) { - char nhbuf[INET6_ADDRSTRLEN] = {0}; - - inet_ntop(AF_INET, &api_nh->gate.ipv4, - nhbuf, INET6_ADDRSTRLEN); - zlog_debug( - "%s: nh=%s, vrf_id=%d (re->vrf_id=%d), ifindex=%d", - __func__, nhbuf, api_nh->vrf_id, - re->vrf_id, ifindex); - } - nexthop = route_entry_nexthop_ipv4_ifindex_add( - re, &api_nh->gate.ipv4, NULL, ifindex, - api_nh->vrf_id); - - /* if this an EVPN route entry, - * program the nh as neigh - */ - if (CHECK_FLAG(api.flags, - ZEBRA_FLAG_EVPN_ROUTE)) { - SET_FLAG(nexthop->flags, - NEXTHOP_FLAG_EVPN_RVTEP); - vtep_ip.ipa_type = IPADDR_V4; - memcpy(&(vtep_ip.ipaddr_v4), - &(api_nh->gate.ipv4), - sizeof(struct in_addr)); - zebra_vxlan_evpn_vrf_route_add( - vrf_id, &api_nh->rmac, &vtep_ip, - &api.prefix); - } - break; - case NEXTHOP_TYPE_IPV6: - nexthop = route_entry_nexthop_ipv6_add( - re, &api_nh->gate.ipv6, api_nh->vrf_id); - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - memset(&vtep_ip, 0, sizeof(struct ipaddr)); - if (CHECK_FLAG(api.flags, - ZEBRA_FLAG_EVPN_ROUTE)) { - ifindex = get_l3vni_svi_ifindex(vrf_id); - } else { - ifindex = api_nh->ifindex; - } - - nexthop = route_entry_nexthop_ipv6_ifindex_add( - re, &api_nh->gate.ipv6, ifindex, - api_nh->vrf_id); - - /* if this an EVPN route entry, - * program the nh as neigh - */ - if (CHECK_FLAG(api.flags, - ZEBRA_FLAG_EVPN_ROUTE)) { - SET_FLAG(nexthop->flags, - NEXTHOP_FLAG_EVPN_RVTEP); - vtep_ip.ipa_type = IPADDR_V6; - memcpy(&vtep_ip.ipaddr_v6, - &(api_nh->gate.ipv6), - sizeof(struct in6_addr)); - zebra_vxlan_evpn_vrf_route_add( - vrf_id, &api_nh->rmac, &vtep_ip, - &api.prefix); - } - break; - case NEXTHOP_TYPE_BLACKHOLE: - nexthop = route_entry_nexthop_blackhole_add( - re, api_nh->bh_type); - break; + for (i = 0; i < api.nexthop_num; i++) { + api_nh = &api.nexthops[i]; + ifindex_t ifindex = 0; + + if (IS_ZEBRA_DEBUG_RECV) + zlog_debug("nh type %d", api_nh->type); + + switch (api_nh->type) { + case NEXTHOP_TYPE_IFINDEX: + nexthop = route_entry_nexthop_ifindex_add( + re, api_nh->ifindex, api_nh->vrf_id); + break; + case NEXTHOP_TYPE_IPV4: + if (IS_ZEBRA_DEBUG_RECV) { + char nhbuf[INET6_ADDRSTRLEN] = {0}; + + inet_ntop(AF_INET, &api_nh->gate.ipv4, nhbuf, + INET6_ADDRSTRLEN); + zlog_debug("%s: nh=%s, vrf_id=%d", __func__, + nhbuf, api_nh->vrf_id); } + nexthop = route_entry_nexthop_ipv4_add( + re, &api_nh->gate.ipv4, NULL, api_nh->vrf_id); + break; + case NEXTHOP_TYPE_IPV4_IFINDEX: - if (!nexthop) { - flog_warn( - EC_ZEBRA_NEXTHOP_CREATION_FAILED, - "%s: Nexthops Specified: %d but we failed to properly create one", - __PRETTY_FUNCTION__, api.nexthop_num); - nexthops_free(re->ng.nexthop); - XFREE(MTYPE_RE, re); - return; + memset(&vtep_ip, 0, sizeof(struct ipaddr)); + if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) { + ifindex = get_l3vni_svi_ifindex(vrf_id); + } else { + ifindex = api_nh->ifindex; } - /* MPLS labels for BGP-LU or Segment Routing */ - if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL) - && api_nh->type != NEXTHOP_TYPE_IFINDEX - && api_nh->type != NEXTHOP_TYPE_BLACKHOLE) { - enum lsp_types_t label_type; - - label_type = - lsp_type_from_re_type(client->proto); - - if (IS_ZEBRA_DEBUG_RECV) { - zlog_debug( - "%s: adding %d labels of type %d (1st=%u)", - __func__, api_nh->label_num, - label_type, api_nh->labels[0]); - } - - nexthop_add_labels(nexthop, label_type, - api_nh->label_num, - &api_nh->labels[0]); + + if (IS_ZEBRA_DEBUG_RECV) { + char nhbuf[INET6_ADDRSTRLEN] = {0}; + + inet_ntop(AF_INET, &api_nh->gate.ipv4, nhbuf, + INET6_ADDRSTRLEN); + zlog_debug( + "%s: nh=%s, vrf_id=%d (re->vrf_id=%d), ifindex=%d", + __func__, nhbuf, api_nh->vrf_id, + re->vrf_id, ifindex); + } + nexthop = route_entry_nexthop_ipv4_ifindex_add( + re, &api_nh->gate.ipv4, NULL, ifindex, + api_nh->vrf_id); + + /* if this an EVPN route entry, + * program the nh as neigh + */ + if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) { + SET_FLAG(nexthop->flags, + NEXTHOP_FLAG_EVPN_RVTEP); + vtep_ip.ipa_type = IPADDR_V4; + memcpy(&(vtep_ip.ipaddr_v4), + &(api_nh->gate.ipv4), + sizeof(struct in_addr)); + zebra_vxlan_evpn_vrf_route_add( + vrf_id, &api_nh->rmac, &vtep_ip, + &api.prefix); + } + break; + case NEXTHOP_TYPE_IPV6: + nexthop = route_entry_nexthop_ipv6_add( + re, &api_nh->gate.ipv6, api_nh->vrf_id); + break; + case NEXTHOP_TYPE_IPV6_IFINDEX: + memset(&vtep_ip, 0, sizeof(struct ipaddr)); + if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) { + ifindex = get_l3vni_svi_ifindex(vrf_id); + } else { + ifindex = api_nh->ifindex; + } + + nexthop = route_entry_nexthop_ipv6_ifindex_add( + re, &api_nh->gate.ipv6, ifindex, + api_nh->vrf_id); + + /* if this an EVPN route entry, + * program the nh as neigh + */ + if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) { + SET_FLAG(nexthop->flags, + NEXTHOP_FLAG_EVPN_RVTEP); + vtep_ip.ipa_type = IPADDR_V6; + memcpy(&vtep_ip.ipaddr_v6, &(api_nh->gate.ipv6), + sizeof(struct in6_addr)); + zebra_vxlan_evpn_vrf_route_add( + vrf_id, &api_nh->rmac, &vtep_ip, + &api.prefix); } + break; + case NEXTHOP_TYPE_BLACKHOLE: + nexthop = route_entry_nexthop_blackhole_add( + re, api_nh->bh_type); + break; + } + + if (!nexthop) { + flog_warn( + EC_ZEBRA_NEXTHOP_CREATION_FAILED, + "%s: Nexthops Specified: %d but we failed to properly create one", + __PRETTY_FUNCTION__, api.nexthop_num); + nexthops_free(re->ng.nexthop); + XFREE(MTYPE_RE, re); + return; } + /* MPLS labels for BGP-LU or Segment Routing */ + if (CHECK_FLAG(api.message, ZAPI_MESSAGE_LABEL) + && api_nh->type != NEXTHOP_TYPE_IFINDEX + && api_nh->type != NEXTHOP_TYPE_BLACKHOLE) { + enum lsp_types_t label_type; + + label_type = lsp_type_from_re_type(client->proto); + + if (IS_ZEBRA_DEBUG_RECV) { + zlog_debug( + "%s: adding %d labels of type %d (1st=%u)", + __func__, api_nh->label_num, label_type, + api_nh->labels[0]); + } + + nexthop_add_labels(nexthop, label_type, + api_nh->label_num, + &api_nh->labels[0]); + } + } if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE)) re->distance = api.distance; @@ -1656,6 +1662,7 @@ static void zsend_capabilities(struct zserv *client, struct zebra_vrf *zvrf) struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ); zclient_create_header(s, ZEBRA_CAPABILITIES, zvrf->vrf->vrf_id); + stream_putl(s, vrf_get_backend()); stream_putc(s, mpls_enabled); stream_putl(s, multipath_num); stream_putc(s, zebra_mlag_get_role()); @@ -1692,6 +1699,7 @@ static void zread_hello(ZAPI_HANDLER_ARGS) } zsend_capabilities(client, zvrf); + zebra_vrf_update_all(client); stream_failure: return; } diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index feede21cd9..6fbad2f71e 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -24,6 +24,7 @@ #include "lib/memory.h" #include "lib/queue.h" #include "lib/zebra.h" +#include "zebra/zebra_router.h" #include "zebra/zebra_memory.h" #include "zebra/zserv.h" #include "zebra/zebra_dplane.h" @@ -62,49 +63,25 @@ const uint32_t DPLANE_DEFAULT_NEW_WORK = 100; #endif /* DPLANE_DEBUG */ /* - * The context block used to exchange info about route updates across - * the boundary between the zebra main context (and pthread) and the - * dataplane layer (and pthread). + * Route information captured for route updates. */ -struct zebra_dplane_ctx { - - /* Operation code */ - enum dplane_op_e zd_op; - - /* Status on return */ - enum zebra_dplane_result zd_status; - - /* Dplane provider id */ - uint32_t zd_provider; - - /* Flags - used by providers, e.g. */ - int zd_flags; - - /* TODO -- internal/sub-operation status? */ - enum zebra_dplane_result zd_remote_status; - enum zebra_dplane_result zd_kernel_status; +struct dplane_route_info { /* Dest and (optional) source prefixes */ struct prefix zd_dest; struct prefix zd_src; - bool zd_is_update; - - uint32_t zd_seq; - uint32_t zd_old_seq; - vrf_id_t zd_vrf_id; - uint32_t zd_table_id; + afi_t zd_afi; + safi_t zd_safi; int zd_type; int zd_old_type; - afi_t zd_afi; - safi_t zd_safi; - route_tag_t zd_tag; route_tag_t zd_old_tag; uint32_t zd_metric; uint32_t zd_old_metric; + uint16_t zd_instance; uint16_t zd_old_instance; @@ -114,9 +91,6 @@ struct zebra_dplane_ctx { uint32_t zd_mtu; uint32_t zd_nexthop_mtu; - /* Namespace info */ - struct zebra_dplane_info zd_ns_info; - /* Nexthops */ struct nexthop_group zd_ng; @@ -125,6 +99,48 @@ struct zebra_dplane_ctx { /* TODO -- use fixed array of nexthops, to avoid mallocs? */ +}; + +/* + * The context block used to exchange info about route updates across + * the boundary between the zebra main context (and pthread) and the + * dataplane layer (and pthread). + */ +struct zebra_dplane_ctx { + + /* Operation code */ + enum dplane_op_e zd_op; + + /* Status on return */ + enum zebra_dplane_result zd_status; + + /* Dplane provider id */ + uint32_t zd_provider; + + /* Flags - used by providers, e.g. */ + int zd_flags; + + bool zd_is_update; + + uint32_t zd_seq; + uint32_t zd_old_seq; + + /* TODO -- internal/sub-operation status? */ + enum zebra_dplane_result zd_remote_status; + enum zebra_dplane_result zd_kernel_status; + + vrf_id_t zd_vrf_id; + uint32_t zd_table_id; + + /* Support info for either route or LSP update */ + union { + struct dplane_route_info rinfo; + zebra_lsp_t lsp; + } u; + + /* Namespace info, used especially for netlink kernel communication */ + struct zebra_dplane_info zd_ns_info; + /* Embedded list linkage */ TAILQ_ENTRY(zebra_dplane_ctx) zd_q_entries; }; @@ -218,6 +234,13 @@ static struct zebra_dplane_globals { _Atomic uint32_t dg_routes_queued; _Atomic uint32_t dg_routes_queued_max; _Atomic uint32_t dg_route_errors; + _Atomic uint32_t dg_other_errors; + + _Atomic uint32_t dg_lsps_in; + _Atomic uint32_t dg_lsps_queued; + _Atomic uint32_t dg_lsps_queued_max; + _Atomic uint32_t dg_lsp_errors; + _Atomic uint32_t dg_update_yields; /* Dataplane pthread */ @@ -251,6 +274,8 @@ static struct zebra_dplane_globals { static int dplane_thread_loop(struct thread *event); static void dplane_info_from_zns(struct zebra_dplane_info *ns_info, struct zebra_ns *zns); +static enum zebra_dplane_result lsp_update_internal(zebra_lsp_t *lsp, + enum dplane_op_e op); /* * Public APIs @@ -282,27 +307,68 @@ static struct zebra_dplane_ctx *dplane_ctx_alloc(void) */ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx) { - if (pctx) { - DPLANE_CTX_VALID(*pctx); + if (pctx == NULL) + return; - /* TODO -- just freeing memory, but would like to maintain - * a pool - */ + DPLANE_CTX_VALID(*pctx); - /* Free embedded nexthops */ - if ((*pctx)->zd_ng.nexthop) { + /* TODO -- just freeing memory, but would like to maintain + * a pool + */ + + /* Some internal allocations may need to be freed, depending on + * the type of info captured in the ctx. + */ + switch ((*pctx)->zd_op) { + case DPLANE_OP_ROUTE_INSTALL: + case DPLANE_OP_ROUTE_UPDATE: + case DPLANE_OP_ROUTE_DELETE: + + /* Free allocated nexthops */ + if ((*pctx)->u.rinfo.zd_ng.nexthop) { /* This deals with recursive nexthops too */ - nexthops_free((*pctx)->zd_ng.nexthop); + nexthops_free((*pctx)->u.rinfo.zd_ng.nexthop); + + (*pctx)->u.rinfo.zd_ng.nexthop = NULL; } - if ((*pctx)->zd_old_ng.nexthop) { + if ((*pctx)->u.rinfo.zd_old_ng.nexthop) { /* This deals with recursive nexthops too */ - nexthops_free((*pctx)->zd_old_ng.nexthop); + nexthops_free((*pctx)->u.rinfo.zd_old_ng.nexthop); + + (*pctx)->u.rinfo.zd_old_ng.nexthop = NULL; } - XFREE(MTYPE_DP_CTX, *pctx); - *pctx = NULL; + break; + + case DPLANE_OP_LSP_INSTALL: + case DPLANE_OP_LSP_UPDATE: + case DPLANE_OP_LSP_DELETE: + { + zebra_nhlfe_t *nhlfe, *next; + + /* Free allocated NHLFEs */ + for (nhlfe = (*pctx)->u.lsp.nhlfe_list; nhlfe; nhlfe = next) { + next = nhlfe->next; + + zebra_mpls_nhlfe_del(nhlfe); + } + + /* Clear pointers in lsp struct, in case we're cacheing + * free context structs. + */ + (*pctx)->u.lsp.nhlfe_list = NULL; + (*pctx)->u.lsp.best_nhlfe = NULL; + + break; + } + + case DPLANE_OP_NONE: + break; } + + XFREE(MTYPE_DP_CTX, *pctx); + *pctx = NULL; } /* @@ -414,6 +480,16 @@ const char *dplane_op2str(enum dplane_op_e op) ret = "ROUTE_DELETE"; break; + case DPLANE_OP_LSP_INSTALL: + ret = "LSP_INSTALL"; + break; + case DPLANE_OP_LSP_UPDATE: + ret = "LSP_UPDATE"; + break; + case DPLANE_OP_LSP_DELETE: + ret = "LSP_DELETE"; + break; + }; return ret; @@ -442,7 +518,7 @@ const struct prefix *dplane_ctx_get_dest(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return &(ctx->zd_dest); + return &(ctx->u.rinfo.zd_dest); } /* Source prefix is a little special - return NULL for "no src prefix" */ @@ -450,11 +526,11 @@ const struct prefix *dplane_ctx_get_src(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - if (ctx->zd_src.prefixlen == 0 && - IN6_IS_ADDR_UNSPECIFIED(&(ctx->zd_src.u.prefix6))) { + if (ctx->u.rinfo.zd_src.prefixlen == 0 && + IN6_IS_ADDR_UNSPECIFIED(&(ctx->u.rinfo.zd_src.u.prefix6))) { return NULL; } else { - return &(ctx->zd_src); + return &(ctx->u.rinfo.zd_src); } } @@ -490,28 +566,28 @@ int dplane_ctx_get_type(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_type; + return ctx->u.rinfo.zd_type; } int dplane_ctx_get_old_type(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_old_type; + return ctx->u.rinfo.zd_old_type; } afi_t dplane_ctx_get_afi(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_afi; + return ctx->u.rinfo.zd_afi; } safi_t dplane_ctx_get_safi(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_safi; + return ctx->u.rinfo.zd_safi; } uint32_t dplane_ctx_get_table(const struct zebra_dplane_ctx *ctx) @@ -525,70 +601,70 @@ route_tag_t dplane_ctx_get_tag(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_tag; + return ctx->u.rinfo.zd_tag; } route_tag_t dplane_ctx_get_old_tag(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_old_tag; + return ctx->u.rinfo.zd_old_tag; } uint16_t dplane_ctx_get_instance(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_instance; + return ctx->u.rinfo.zd_instance; } uint16_t dplane_ctx_get_old_instance(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_old_instance; + return ctx->u.rinfo.zd_old_instance; } uint32_t dplane_ctx_get_metric(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_metric; + return ctx->u.rinfo.zd_metric; } uint32_t dplane_ctx_get_old_metric(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_old_metric; + return ctx->u.rinfo.zd_old_metric; } uint32_t dplane_ctx_get_mtu(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_mtu; + return ctx->u.rinfo.zd_mtu; } uint32_t dplane_ctx_get_nh_mtu(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_nexthop_mtu; + return ctx->u.rinfo.zd_nexthop_mtu; } uint8_t dplane_ctx_get_distance(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_distance; + return ctx->u.rinfo.zd_distance; } uint8_t dplane_ctx_get_old_distance(const struct zebra_dplane_ctx *ctx) { DPLANE_CTX_VALID(ctx); - return ctx->zd_old_distance; + return ctx->u.rinfo.zd_old_distance; } const struct nexthop_group *dplane_ctx_get_ng( @@ -596,7 +672,7 @@ const struct nexthop_group *dplane_ctx_get_ng( { DPLANE_CTX_VALID(ctx); - return &(ctx->zd_ng); + return &(ctx->u.rinfo.zd_ng); } const struct nexthop_group *dplane_ctx_get_old_ng( @@ -604,7 +680,7 @@ const struct nexthop_group *dplane_ctx_get_old_ng( { DPLANE_CTX_VALID(ctx); - return &(ctx->zd_old_ng); + return &(ctx->u.rinfo.zd_old_ng); } const struct zebra_dplane_info *dplane_ctx_get_ns( @@ -615,6 +691,50 @@ const struct zebra_dplane_info *dplane_ctx_get_ns( return &(ctx->zd_ns_info); } +/* Accessors for LSP information */ + +mpls_label_t dplane_ctx_get_in_label(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.lsp.ile.in_label; +} + +uint8_t dplane_ctx_get_addr_family(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.lsp.addr_family; +} + +uint32_t dplane_ctx_get_lsp_flags(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.lsp.flags; +} + +zebra_nhlfe_t *dplane_ctx_get_nhlfe(struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.lsp.nhlfe_list; +} + +zebra_nhlfe_t *dplane_ctx_get_best_nhlfe(struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.lsp.best_nhlfe; +} + +uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->u.lsp.num_ecmp; +} + /* * End of dplane context accessors */ @@ -652,6 +772,28 @@ uint32_t dplane_get_in_queue_len(void) } /* + * Common dataplane context init with zebra namespace info. + */ +static int dplane_ctx_ns_init(struct zebra_dplane_ctx *ctx, + struct zebra_ns *zns, + bool is_update) +{ + dplane_info_from_zns(&(ctx->zd_ns_info), zns); + +#if defined(HAVE_NETLINK) + /* Increment message counter after copying to context struct - may need + * two messages in some 'update' cases. + */ + if (is_update) + zns->netlink_dplane.seq += 2; + else + zns->netlink_dplane.seq++; +#endif /* HAVE_NETLINK */ + + return AOK; +} + +/* * Initialize a context block for a route update from zebra data structs. */ static int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, @@ -673,67 +815,56 @@ static int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, ctx->zd_op = op; ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; - ctx->zd_type = re->type; - ctx->zd_old_type = re->type; + ctx->u.rinfo.zd_type = re->type; + ctx->u.rinfo.zd_old_type = re->type; /* Prefixes: dest, and optional source */ srcdest_rnode_prefixes(rn, &p, &src_p); - prefix_copy(&(ctx->zd_dest), p); + prefix_copy(&(ctx->u.rinfo.zd_dest), p); if (src_p) - prefix_copy(&(ctx->zd_src), src_p); + prefix_copy(&(ctx->u.rinfo.zd_src), src_p); else - memset(&(ctx->zd_src), 0, sizeof(ctx->zd_src)); + memset(&(ctx->u.rinfo.zd_src), 0, sizeof(ctx->u.rinfo.zd_src)); ctx->zd_table_id = re->table; - ctx->zd_metric = re->metric; - ctx->zd_old_metric = re->metric; + ctx->u.rinfo.zd_metric = re->metric; + ctx->u.rinfo.zd_old_metric = re->metric; ctx->zd_vrf_id = re->vrf_id; - ctx->zd_mtu = re->mtu; - ctx->zd_nexthop_mtu = re->nexthop_mtu; - ctx->zd_instance = re->instance; - ctx->zd_tag = re->tag; - ctx->zd_old_tag = re->tag; - ctx->zd_distance = re->distance; + ctx->u.rinfo.zd_mtu = re->mtu; + ctx->u.rinfo.zd_nexthop_mtu = re->nexthop_mtu; + ctx->u.rinfo.zd_instance = re->instance; + ctx->u.rinfo.zd_tag = re->tag; + ctx->u.rinfo.zd_old_tag = re->tag; + ctx->u.rinfo.zd_distance = re->distance; table = srcdest_rnode_table(rn); info = table->info; - ctx->zd_afi = info->afi; - ctx->zd_safi = info->safi; + ctx->u.rinfo.zd_afi = info->afi; + ctx->u.rinfo.zd_safi = info->safi; /* Extract ns info - can't use pointers to 'core' structs */ zvrf = vrf_info_lookup(re->vrf_id); zns = zvrf->zns; - /* Internal copy helper */ - dplane_info_from_zns(&(ctx->zd_ns_info), zns); - -#if defined(HAVE_NETLINK) - /* Increment message counter after copying to context struct - may need - * two messages in some 'update' cases. - */ - if (op == DPLANE_OP_ROUTE_UPDATE) - zns->netlink_dplane.seq += 2; - else - zns->netlink_dplane.seq++; -#endif /* NETLINK*/ + dplane_ctx_ns_init(ctx, zns, (op == DPLANE_OP_ROUTE_UPDATE)); /* Copy nexthops; recursive info is included too */ - copy_nexthops(&(ctx->zd_ng.nexthop), re->ng.nexthop, NULL); + copy_nexthops(&(ctx->u.rinfo.zd_ng.nexthop), re->ng.nexthop, NULL); /* TODO -- maybe use array of nexthops to avoid allocs? */ /* Ensure that the dplane's nexthops flags are clear. */ - for (ALL_NEXTHOPS(ctx->zd_ng, nexthop)) + for (ALL_NEXTHOPS(ctx->u.rinfo.zd_ng, nexthop)) UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); /* Trying out the sequence number idea, so we can try to detect * when a result is stale. */ - re->dplane_sequence++; + re->dplane_sequence = zebra_router_get_next_sequence(); ctx->zd_seq = re->dplane_sequence; ret = AOK; @@ -743,15 +874,79 @@ done: } /* + * Capture information for an LSP update in a dplane context. + */ +static int dplane_ctx_lsp_init(struct zebra_dplane_ctx *ctx, + enum dplane_op_e op, + zebra_lsp_t *lsp) +{ + int ret = AOK; + zebra_nhlfe_t *nhlfe, *new_nhlfe; + + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) + zlog_debug("init dplane ctx %s: in-label %u ecmp# %d", + dplane_op2str(op), lsp->ile.in_label, + lsp->num_ecmp); + + ctx->zd_op = op; + ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS; + + /* Capture namespace info */ + dplane_ctx_ns_init(ctx, zebra_ns_lookup(NS_DEFAULT), + (op == DPLANE_OP_LSP_UPDATE)); + + memset(&ctx->u.lsp, 0, sizeof(ctx->u.lsp)); + + ctx->u.lsp.ile = lsp->ile; + ctx->u.lsp.addr_family = lsp->addr_family; + ctx->u.lsp.num_ecmp = lsp->num_ecmp; + ctx->u.lsp.flags = lsp->flags; + + /* Copy source LSP's nhlfes, and capture 'best' nhlfe */ + for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + /* Not sure if this is meaningful... */ + if (nhlfe->nexthop == NULL) + continue; + + new_nhlfe = + zebra_mpls_lsp_add_nhlfe( + &(ctx->u.lsp), + nhlfe->type, + nhlfe->nexthop->type, + &(nhlfe->nexthop->gate), + nhlfe->nexthop->ifindex, + nhlfe->nexthop->nh_label->label[0]); + + if (new_nhlfe == NULL || new_nhlfe->nexthop == NULL) { + ret = ENOMEM; + break; + } + + /* Need to copy flags too */ + new_nhlfe->flags = nhlfe->flags; + new_nhlfe->nexthop->flags = nhlfe->nexthop->flags; + + if (nhlfe == lsp->best_nhlfe) + ctx->u.lsp.best_nhlfe = new_nhlfe; + } + + /* On error the ctx will be cleaned-up, so we don't need to + * deal with any allocated nhlfe or nexthop structs here. + */ + + return ret; +} + +/* * Enqueue a new route update, - * and ensure an event is active for the dataplane thread. + * and ensure an event is active for the dataplane pthread. */ static int dplane_route_enqueue(struct zebra_dplane_ctx *ctx) { int ret = EINVAL; uint32_t high, curr; - /* Enqueue for processing by the dataplane thread */ + /* Enqueue for processing by the dataplane pthread */ DPLANE_LOCK(); { TAILQ_INSERT_TAIL(&zdplane_info.dg_route_ctx_q, ctx, @@ -818,20 +1013,21 @@ dplane_route_update_internal(struct route_node *rn, old_re && (old_re != re)) { ctx->zd_is_update = true; - old_re->dplane_sequence++; + old_re->dplane_sequence = + zebra_router_get_next_sequence(); ctx->zd_old_seq = old_re->dplane_sequence; - ctx->zd_old_tag = old_re->tag; - ctx->zd_old_type = old_re->type; - ctx->zd_old_instance = old_re->instance; - ctx->zd_old_distance = old_re->distance; - ctx->zd_old_metric = old_re->metric; + ctx->u.rinfo.zd_old_tag = old_re->tag; + ctx->u.rinfo.zd_old_type = old_re->type; + ctx->u.rinfo.zd_old_instance = old_re->instance; + ctx->u.rinfo.zd_old_distance = old_re->distance; + ctx->u.rinfo.zd_old_metric = old_re->metric; #ifndef HAVE_NETLINK /* For bsd, capture previous re's nexthops too, sigh. * We'll need these to do per-nexthop deletes. */ - copy_nexthops(&(ctx->zd_old_ng.nexthop), + copy_nexthops(&(ctx->u.rinfo.zd_old_ng.nexthop), old_re->ng.nexthop, NULL); #endif /* !HAVE_NETLINK */ } @@ -847,10 +1043,11 @@ done: if (ret == AOK) result = ZEBRA_DPLANE_REQUEST_QUEUED; - else if (ctx) { + else { atomic_fetch_add_explicit(&zdplane_info.dg_route_errors, 1, memory_order_relaxed); - dplane_ctx_free(&ctx); + if (ctx) + dplane_ctx_free(&ctx); } return result; @@ -911,11 +1108,85 @@ done: } /* + * Enqueue LSP add for the dataplane. + */ +enum zebra_dplane_result dplane_lsp_add(zebra_lsp_t *lsp) +{ + enum zebra_dplane_result ret = + lsp_update_internal(lsp, DPLANE_OP_LSP_INSTALL); + + return ret; +} + +/* + * Enqueue LSP update for the dataplane. + */ +enum zebra_dplane_result dplane_lsp_update(zebra_lsp_t *lsp) +{ + enum zebra_dplane_result ret = + lsp_update_internal(lsp, DPLANE_OP_LSP_UPDATE); + + return ret; +} + +/* + * Enqueue LSP delete for the dataplane. + */ +enum zebra_dplane_result dplane_lsp_delete(zebra_lsp_t *lsp) +{ + enum zebra_dplane_result ret = + lsp_update_internal(lsp, DPLANE_OP_LSP_DELETE); + + return ret; +} + +/* + * Common internal LSP update utility + */ +static enum zebra_dplane_result lsp_update_internal(zebra_lsp_t *lsp, + enum dplane_op_e op) +{ + enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; + int ret = EINVAL; + struct zebra_dplane_ctx *ctx = NULL; + + /* Obtain context block */ + ctx = dplane_ctx_alloc(); + if (ctx == NULL) { + ret = ENOMEM; + goto done; + } + + ret = dplane_ctx_lsp_init(ctx, op, lsp); + if (ret != AOK) + goto done; + + ret = dplane_route_enqueue(ctx); + +done: + /* Update counter */ + atomic_fetch_add_explicit(&zdplane_info.dg_lsps_in, 1, + memory_order_relaxed); + + if (ret == AOK) + result = ZEBRA_DPLANE_REQUEST_QUEUED; + else { + atomic_fetch_add_explicit(&zdplane_info.dg_lsp_errors, 1, + memory_order_relaxed); + if (ctx) + dplane_ctx_free(&ctx); + } + + return result; +} + +/* * Handler for 'show dplane' */ int dplane_show_helper(struct vty *vty, bool detailed) { - uint64_t queued, queue_max, limit, errs, incoming, yields; + uint64_t queued, queue_max, limit, errs, incoming, yields, + other_errs; /* Using atomics because counters are being changed in different * pthread contexts. @@ -932,14 +1203,17 @@ int dplane_show_helper(struct vty *vty, bool detailed) memory_order_relaxed); yields = atomic_load_explicit(&zdplane_info.dg_update_yields, memory_order_relaxed); + other_errs = atomic_load_explicit(&zdplane_info.dg_other_errors, + memory_order_relaxed); vty_out(vty, "Zebra dataplane:\nRoute updates: %"PRIu64"\n", incoming); vty_out(vty, "Route update errors: %"PRIu64"\n", errs); + vty_out(vty, "Other errors : %"PRIu64"\n", other_errs); vty_out(vty, "Route update queue limit: %"PRIu64"\n", limit); vty_out(vty, "Route update queue depth: %"PRIu64"\n", queued); vty_out(vty, "Route update queue max: %"PRIu64"\n", queue_max); - vty_out(vty, "Route update yields: %"PRIu64"\n", yields); + vty_out(vty, "Dplane update yields: %"PRIu64"\n", yields); return CMD_SUCCESS; } @@ -1219,6 +1493,55 @@ int dplane_provider_work_ready(void) */ /* + * Handler for kernel LSP updates + */ +static enum zebra_dplane_result +kernel_dplane_lsp_update(struct zebra_dplane_ctx *ctx) +{ + enum zebra_dplane_result res; + + /* Call into the synchronous kernel-facing code here */ + res = kernel_lsp_update(ctx); + + if (res != ZEBRA_DPLANE_REQUEST_SUCCESS) + atomic_fetch_add_explicit( + &zdplane_info.dg_lsp_errors, 1, + memory_order_relaxed); + + return res; +} + +/* + * Handler for kernel route updates + */ +static enum zebra_dplane_result +kernel_dplane_route_update(struct zebra_dplane_ctx *ctx) +{ + enum zebra_dplane_result res; + + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { + char dest_str[PREFIX_STRLEN]; + + prefix2str(dplane_ctx_get_dest(ctx), + dest_str, sizeof(dest_str)); + + zlog_debug("%u:%s Dplane route update ctx %p op %s", + dplane_ctx_get_vrf(ctx), dest_str, + ctx, dplane_op2str(dplane_ctx_get_op(ctx))); + } + + /* Call into the synchronous kernel-facing code here */ + res = kernel_route_update(ctx); + + if (res != ZEBRA_DPLANE_REQUEST_SUCCESS) + atomic_fetch_add_explicit( + &zdplane_info.dg_route_errors, 1, + memory_order_relaxed); + + return res; +} + +/* * Kernel provider callback */ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov) @@ -1239,25 +1562,30 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov) if (ctx == NULL) break; - if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { - char dest_str[PREFIX_STRLEN]; - - prefix2str(dplane_ctx_get_dest(ctx), - dest_str, sizeof(dest_str)); + /* Dispatch to appropriate kernel-facing apis */ + switch (dplane_ctx_get_op(ctx)) { - zlog_debug("%u:%s Dplane route update ctx %p op %s", - dplane_ctx_get_vrf(ctx), dest_str, - ctx, dplane_op2str(dplane_ctx_get_op(ctx))); - } + case DPLANE_OP_ROUTE_INSTALL: + case DPLANE_OP_ROUTE_UPDATE: + case DPLANE_OP_ROUTE_DELETE: + res = kernel_dplane_route_update(ctx); + break; - /* Call into the synchronous kernel-facing code here */ - res = kernel_route_update(ctx); + case DPLANE_OP_LSP_INSTALL: + case DPLANE_OP_LSP_UPDATE: + case DPLANE_OP_LSP_DELETE: + res = kernel_dplane_lsp_update(ctx); + break; - if (res != ZEBRA_DPLANE_REQUEST_SUCCESS) + default: atomic_fetch_add_explicit( - &zdplane_info.dg_route_errors, 1, + &zdplane_info.dg_other_errors, 1, memory_order_relaxed); + res = ZEBRA_DPLANE_REQUEST_FAILURE; + break; + } + dplane_ctx_set_status(ctx, res); dplane_provider_enqueue_out_ctx(prov, ctx); diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 1c053b85bf..562a8499a2 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -28,6 +28,7 @@ #include "zebra/zebra_ns.h" #include "zebra/rib.h" #include "zebra/zserv.h" +#include "zebra/zebra_mpls.h" /* Key netlink info from zebra ns */ struct zebra_dplane_info { @@ -101,6 +102,10 @@ enum dplane_op_e { DPLANE_OP_ROUTE_UPDATE, DPLANE_OP_ROUTE_DELETE, + /* LSP update */ + DPLANE_OP_LSP_INSTALL, + DPLANE_OP_LSP_UPDATE, + DPLANE_OP_LSP_DELETE }; /* @@ -167,6 +172,8 @@ bool dplane_ctx_is_update(const struct zebra_dplane_ctx *ctx); uint32_t dplane_ctx_get_seq(const struct zebra_dplane_ctx *ctx); uint32_t dplane_ctx_get_old_seq(const struct zebra_dplane_ctx *ctx); vrf_id_t dplane_ctx_get_vrf(const struct zebra_dplane_ctx *ctx); + +/* Accessors for route update information */ int dplane_ctx_get_type(const struct zebra_dplane_ctx *ctx); int dplane_ctx_get_old_type(const struct zebra_dplane_ctx *ctx); afi_t dplane_ctx_get_afi(const struct zebra_dplane_ctx *ctx); @@ -188,6 +195,15 @@ const struct nexthop_group *dplane_ctx_get_ng( const struct nexthop_group *dplane_ctx_get_old_ng( const struct zebra_dplane_ctx *ctx); +/* Accessors for LSP information */ +mpls_label_t dplane_ctx_get_in_label(const struct zebra_dplane_ctx *ctx); +uint8_t dplane_ctx_get_addr_family(const struct zebra_dplane_ctx *ctx); +uint32_t dplane_ctx_get_lsp_flags(const struct zebra_dplane_ctx *ctx); +zebra_nhlfe_t *dplane_ctx_get_nhlfe(struct zebra_dplane_ctx *ctx); +zebra_nhlfe_t *dplane_ctx_get_best_nhlfe(struct zebra_dplane_ctx *ctx); +uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx); + +/* Namespace info - esp. for netlink communication */ const struct zebra_dplane_info *dplane_ctx_get_ns( const struct zebra_dplane_ctx *ctx); @@ -209,6 +225,13 @@ enum zebra_dplane_result dplane_route_update(struct route_node *rn, enum zebra_dplane_result dplane_route_delete(struct route_node *rn, struct route_entry *re); +/* + * Enqueue LSP change operations for the dataplane. + */ +enum zebra_dplane_result dplane_lsp_add(zebra_lsp_t *lsp); +enum zebra_dplane_result dplane_lsp_update(zebra_lsp_t *lsp); +enum zebra_dplane_result dplane_lsp_delete(zebra_lsp_t *lsp); + /* Retrieve the limit on the number of pending, unprocessed updates. */ uint32_t dplane_get_in_queue_limit(void); diff --git a/zebra/zebra_errors.c b/zebra/zebra_errors.c index d7c17829cd..cb5f30df1f 100644 --- a/zebra/zebra_errors.c +++ b/zebra/zebra_errors.c @@ -505,6 +505,15 @@ static struct log_ref ferr_zebra_err[] = { "Check configuration values for correctness. If they are correct, report this as a bug.", }, { + .code = EC_ZEBRA_RX_ROUTE_NO_NEXTHOPS, + .title = + "Zebra received an installation request for a route without nexthops", + .description = + "Zebra received a message from a client requesting a route installation, but the route is invalid since it doesn't have any nexthop address or interface.", + .suggestion = + "This is a bug; please report it.", + }, + { .code = EC_ZEBRA_RX_SRCDEST_WRONG_AFI, .title = "Zebra received sourcedest route install without IPv6 address family", diff --git a/zebra/zebra_errors.h b/zebra/zebra_errors.h index c3cdc4ed42..0af5f8a551 100644 --- a/zebra/zebra_errors.h +++ b/zebra/zebra_errors.h @@ -96,6 +96,7 @@ enum zebra_log_refs { EC_ZEBRA_VRF_NOT_FOUND, EC_ZEBRA_MORE_NH_THAN_MULTIPATH, EC_ZEBRA_NEXTHOP_CREATION_FAILED, + EC_ZEBRA_RX_ROUTE_NO_NEXTHOPS, EC_ZEBRA_RX_SRCDEST_WRONG_AFI, EC_ZEBRA_PSEUDOWIRE_EXISTS, EC_ZEBRA_PSEUDOWIRE_UNINSTALL_NOT_FOUND, diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index c0764cd4b8..c255c68866 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -862,7 +862,7 @@ static void lsp_uninstall_from_kernel(struct hash_backet *backet, void *ctxt) lsp = (zebra_lsp_t *)backet->data; if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) - (void)kernel_del_lsp(lsp); + (void)dplane_lsp_delete(lsp); } /* @@ -887,6 +887,7 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data) zebra_nhlfe_t *oldbest, *newbest; char buf[BUFSIZ], buf2[BUFSIZ]; struct zebra_vrf *zvrf = vrf_info_lookup(VRF_DEFAULT); + enum zebra_dplane_result res; lsp = (zebra_lsp_t *)data; if (!lsp) // unexpected @@ -916,13 +917,20 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data) if (newbest) { UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); - switch (kernel_add_lsp(lsp)) { + + switch (dplane_lsp_add(lsp)) { case ZEBRA_DPLANE_REQUEST_QUEUED: - flog_err( - EC_ZEBRA_DP_INVALID_RC, - "No current DataPlane interfaces can return this, please fix"); + /* Set 'installed' flag so we will know + * that an install is in-flight. + */ + SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + + zvrf->lsp_installs_queued++; break; case ZEBRA_DPLANE_REQUEST_FAILURE: + flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE, + "LSP Install Failure: %u", + lsp->ile.in_label); break; case ZEBRA_DPLANE_REQUEST_SUCCESS: zvrf->lsp_installs++; @@ -932,14 +940,22 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data) } else { /* Installed, may need an update and/or delete. */ if (!newbest) { + res = dplane_lsp_delete(lsp); - switch (kernel_del_lsp(lsp)) { + /* We do some of the lsp cleanup immediately for + * deletes. + */ + UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + clear_nhlfe_installed(lsp); + + switch (res) { case ZEBRA_DPLANE_REQUEST_QUEUED: - flog_err( - EC_ZEBRA_DP_INVALID_RC, - "No current DataPlane interfaces can return this, please fix"); + zvrf->lsp_removals_queued++; break; case ZEBRA_DPLANE_REQUEST_FAILURE: + flog_warn(EC_ZEBRA_LSP_DELETE_FAILURE, + "LSP Deletion Failure: %u", + lsp->ile.in_label); break; case ZEBRA_DPLANE_REQUEST_SUCCESS: zvrf->lsp_removals++; @@ -950,7 +966,10 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data) struct nexthop *nexthop; UNSET_FLAG(lsp->flags, LSP_FLAG_CHANGED); - UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + + /* We leave the INSTALLED flag set here + * so we know an update in in-flight. + */ /* * Any NHLFE that was installed but is not @@ -973,13 +992,14 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data) } } - switch (kernel_upd_lsp(lsp)) { + switch (dplane_lsp_update(lsp)) { case ZEBRA_DPLANE_REQUEST_QUEUED: - flog_err( - EC_ZEBRA_DP_INVALID_RC, - "No current DataPlane interfaces can return this, please fix"); + zvrf->lsp_installs_queued++; break; case ZEBRA_DPLANE_REQUEST_FAILURE: + flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE, + "LSP Update Failure: %u", + lsp->ile.in_label); break; case ZEBRA_DPLANE_REQUEST_SUCCESS: zvrf->lsp_installs++; @@ -1716,43 +1736,84 @@ static int mpls_processq_init(struct zebra_t *zebra) /* Public functions */ -void kernel_lsp_pass_fail(zebra_lsp_t *lsp, enum zebra_dplane_status res) +/* + * Process LSP update results from zebra dataplane. + */ +void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx) { - struct nexthop *nexthop; + struct zebra_vrf *zvrf; + zebra_ile_t tmp_ile; + struct hash *lsp_table; + zebra_lsp_t *lsp; zebra_nhlfe_t *nhlfe; + struct nexthop *nexthop; + enum dplane_op_e op; + enum zebra_dplane_result status; + + op = dplane_ctx_get_op(ctx); + status = dplane_ctx_get_status(ctx); + + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) + zlog_debug("LSP dplane ctx %p, op %s, in-label %u, result %s", + ctx, dplane_op2str(op), + dplane_ctx_get_in_label(ctx), + dplane_res2str(status)); + + switch (op) { + case DPLANE_OP_LSP_INSTALL: + case DPLANE_OP_LSP_UPDATE: + /* Look for zebra LSP object */ + zvrf = vrf_info_lookup(VRF_DEFAULT); + if (zvrf == NULL) + break; - if (!lsp) - return; + lsp_table = zvrf->lsp_table; - switch (res) { - case ZEBRA_DPLANE_INSTALL_FAILURE: - UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); - clear_nhlfe_installed(lsp); - flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE, - "LSP Install Failure: %u", lsp->ile.in_label); - break; - case ZEBRA_DPLANE_INSTALL_SUCCESS: - SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { - nexthop = nhlfe->nexthop; - if (!nexthop) - continue; + tmp_ile.in_label = dplane_ctx_get_in_label(ctx); + lsp = hash_lookup(lsp_table, &tmp_ile); + if (lsp == NULL) { + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("LSP ctx %p: in-label %u not found", + ctx, dplane_ctx_get_in_label(ctx)); + break; + } - SET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + /* TODO -- Confirm that this result is still 'current' */ + + if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) { + /* Update zebra object */ + SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + for (nhlfe = lsp->nhlfe_list; nhlfe; + nhlfe = nhlfe->next) { + nexthop = nhlfe->nexthop; + if (!nexthop) + continue; + + SET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED); + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + } + } else { + UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); + clear_nhlfe_installed(lsp); + flog_warn(EC_ZEBRA_LSP_INSTALL_FAILURE, + "LSP Install Failure: in-label %u", + lsp->ile.in_label); } + break; - case ZEBRA_DPLANE_DELETE_SUCCESS: - UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED); - clear_nhlfe_installed(lsp); - break; - case ZEBRA_DPLANE_DELETE_FAILURE: + + case DPLANE_OP_LSP_DELETE: flog_warn(EC_ZEBRA_LSP_DELETE_FAILURE, - "LSP Deletion Failure: %u", lsp->ile.in_label); + "LSP Deletion Failure: in-label %u", + dplane_ctx_get_in_label(ctx)); break; - case ZEBRA_DPLANE_STATUS_NONE: + + default: break; - } + + } /* Switch */ + + dplane_ctx_fini(&ctx); } /* @@ -1808,6 +1869,29 @@ int zebra_mpls_lsp_uninstall(struct zebra_vrf *zvrf, struct route_node *rn, } /* + * Add an NHLFE to an LSP, return the newly-added object + */ +zebra_nhlfe_t *zebra_mpls_lsp_add_nhlfe(zebra_lsp_t *lsp, + enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, + union g_addr *gate, + ifindex_t ifindex, + mpls_label_t out_label) +{ + /* Just a public pass-through to the internal implementation */ + return nhlfe_add(lsp, lsp_type, gtype, gate, ifindex, out_label); +} + +/* + * Free an allocated NHLFE + */ +void zebra_mpls_nhlfe_del(zebra_nhlfe_t *nhlfe) +{ + /* Just a pass-through to the internal implementation */ + nhlfe_del(nhlfe); +} + +/* * Registration from a client for the label binding for a FEC. If a binding * already exists, it is informed to the client. * NOTE: If there is a manually configured label binding, that is used. diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index c250fc4058..fb32adde31 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -191,6 +191,17 @@ int zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn, int zebra_mpls_lsp_uninstall(struct zebra_vrf *zvrf, struct route_node *rn, struct route_entry *re); +/* Add an NHLFE to an LSP, return the newly-added object */ +zebra_nhlfe_t *zebra_mpls_lsp_add_nhlfe(zebra_lsp_t *lsp, + enum lsp_types_t lsp_type, + enum nexthop_types_t gtype, + union g_addr *gate, + ifindex_t ifindex, + mpls_label_t out_label); + +/* Free an allocated NHLFE */ +void zebra_mpls_nhlfe_del(zebra_nhlfe_t *nhlfe); + int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p, uint32_t label, uint32_t label_index, struct zserv *client); @@ -331,6 +342,14 @@ int zebra_mpls_static_lsp_del(struct zebra_vrf *zvrf, mpls_label_t in_label, ifindex_t ifindex); /* + * Process LSP update results from zebra dataplane. + */ +/* Forward ref of dplane update context type */ +struct zebra_dplane_ctx; + +void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx); + +/* * Schedule all MPLS label forwarding entries for processing. * Called upon changes that may affect one or more of them such as * interface or nexthop state changes. diff --git a/zebra/zebra_mpls_netlink.c b/zebra/zebra_mpls_netlink.c index c4ab316d0b..d8b5ef4ce1 100644 --- a/zebra/zebra_mpls_netlink.c +++ b/zebra/zebra_mpls_netlink.c @@ -22,84 +22,43 @@ #ifdef HAVE_NETLINK +#include "zebra/debug.h" #include "zebra/rt.h" #include "zebra/rt_netlink.h" #include "zebra/zebra_mpls.h" /* - * Install Label Forwarding entry into the kernel. + * LSP forwarding update using dataplane context information. */ -enum zebra_dplane_result kernel_add_lsp(zebra_lsp_t *lsp) +enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx) { - int ret; + int cmd, ret = -1; - if (!lsp || !lsp->best_nhlfe) { // unexpected - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_INSTALL_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } + /* Call to netlink layer based on type of update */ + if (dplane_ctx_get_op(ctx) == DPLANE_OP_LSP_DELETE) { + cmd = RTM_DELROUTE; + } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_LSP_INSTALL || + dplane_ctx_get_op(ctx) == DPLANE_OP_LSP_UPDATE) { - ret = netlink_mpls_multipath(RTM_NEWROUTE, lsp); + /* Validate */ + if (dplane_ctx_get_best_nhlfe(ctx) == NULL) { + if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_MPLS) + zlog_debug("LSP in-label %u: update fails, no best NHLFE", + dplane_ctx_get_in_label(ctx)); + goto done; + } - kernel_lsp_pass_fail(lsp, - (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS - : ZEBRA_DPLANE_INSTALL_FAILURE); + cmd = RTM_NEWROUTE; + } else + /* Invalid op? */ + goto done; - return ZEBRA_DPLANE_REQUEST_SUCCESS; -} - -/* - * Update Label Forwarding entry in the kernel. This means that the Label - * forwarding entry is already installed and needs an update - either a new - * path is to be added, an installed path has changed (e.g., outgoing label) - * or an installed path (but not all paths) has to be removed. - * TODO: Performs a DEL followed by ADD now, need to change to REPLACE. Note - * that REPLACE was originally implemented for IPv4 nexthops but removed as - * it was not functioning when moving from swap to PHP as that was signaled - * through the metric field (before kernel-MPLS). This shouldn't be an issue - * any longer, so REPLACE can be reintroduced. - */ -enum zebra_dplane_result kernel_upd_lsp(zebra_lsp_t *lsp) -{ - int ret; - - if (!lsp || !lsp->best_nhlfe) { // unexpected - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_INSTALL_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } - - ret = netlink_mpls_multipath(RTM_NEWROUTE, lsp); - - kernel_lsp_pass_fail(lsp, - (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS - : ZEBRA_DPLANE_INSTALL_FAILURE); - - return ZEBRA_DPLANE_REQUEST_SUCCESS; -} - -/* - * Delete Label Forwarding entry from the kernel. - */ -enum zebra_dplane_result kernel_del_lsp(zebra_lsp_t *lsp) -{ - int ret; - - if (!lsp) { // unexpected - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_DELETE_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } - - if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) { - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_DELETE_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } - - ret = netlink_mpls_multipath(RTM_DELROUTE, lsp); + ret = netlink_mpls_multipath(cmd, ctx); - kernel_lsp_pass_fail(lsp, - (!ret) ? ZEBRA_DPLANE_DELETE_SUCCESS - : ZEBRA_DPLANE_DELETE_FAILURE); +done: - return ZEBRA_DPLANE_REQUEST_SUCCESS; + return (ret == 0 ? + ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE); } int mpls_kernel_init(void) diff --git a/zebra/zebra_mpls_null.c b/zebra/zebra_mpls_null.c index 02ec506d84..409432c4fb 100644 --- a/zebra/zebra_mpls_null.c +++ b/zebra/zebra_mpls_null.c @@ -24,24 +24,14 @@ #if !defined(HAVE_NETLINK) && !defined(OPEN_BSD) -enum zebra_dplane_result kernel_add_lsp(zebra_lsp_t *lsp) -{ - return ZEBRA_DPLANE_REQUEST_SUCCESS; -} - -enum zebra_dplane_result kernel_upd_lsp(zebra_lsp_t *lsp) -{ - return ZEBRA_DPLANE_REQUEST_SUCCESS; -} - -enum zebra_dplane_result kernel_del_lsp(zebra_lsp_t *lsp) -{ - return ZEBRA_DPLANE_REQUEST_SUCCESS; -} - int mpls_kernel_init(void) { return -1; }; +enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx) +{ + return ZEBRA_DPLANE_REQUEST_FAILURE; +} + #endif /* !defined(HAVE_NETLINK) && !defined(OPEN_BSD) */ diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c index 60f944b844..da76c6ebf9 100644 --- a/zebra/zebra_mpls_openbsd.c +++ b/zebra/zebra_mpls_openbsd.c @@ -236,13 +236,28 @@ static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label, return ret; } -static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp) +static int kernel_lsp_cmd(struct zebra_dplane_ctx *ctx) { zebra_nhlfe_t *nhlfe; struct nexthop *nexthop = NULL; unsigned int nexthop_num = 0; + int action; - for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe->next) { + switch (dplane_ctx_get_op(ctx)) { + case DPLANE_OP_LSP_DELETE: + action = RTM_DELETE; + break; + case DPLANE_OP_LSP_INSTALL: + action = RTM_ADD; + break; + case DPLANE_OP_LSP_UPDATE: + action = RTM_CHANGE; + break; + default: + return -1; + } + + for (nhlfe = dplane_ctx_get_nhlfe(ctx); nhlfe; nhlfe = nhlfe->next) { nexthop = nhlfe->nexthop; if (!nexthop) continue; @@ -269,12 +284,16 @@ static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp) switch (NHLFE_FAMILY(nhlfe)) { case AF_INET: - kernel_send_rtmsg_v4(action, lsp->ile.in_label, - nhlfe); + kernel_send_rtmsg_v4( + action, + dplane_ctx_get_in_label(ctx), + nhlfe); break; case AF_INET6: - kernel_send_rtmsg_v6(action, lsp->ile.in_label, - nhlfe); + kernel_send_rtmsg_v6( + action, + dplane_ctx_get_in_label(ctx), + nhlfe); break; default: break; @@ -285,62 +304,14 @@ static int kernel_lsp_cmd(int action, zebra_lsp_t *lsp) return (0); } -enum zebra_dplane_result kernel_add_lsp(zebra_lsp_t *lsp) +enum zebra_dplane_result kernel_lsp_update(struct zebra_dplane_ctx *ctx) { int ret; - if (!lsp || !lsp->best_nhlfe) { // unexpected - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_INSTALL_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } - - ret = kernel_lsp_cmd(RTM_ADD, lsp); - - kernel_lsp_pass_fail(lsp, - (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS - : ZEBRA_DPLANE_INSTALL_FAILURE); - - return ZEBRA_DPLANE_REQUEST_SUCCESS; -} - -enum zebra_dplane_result kernel_upd_lsp(zebra_lsp_t *lsp) -{ - int ret; - - if (!lsp || !lsp->best_nhlfe) { // unexpected - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_INSTALL_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } - - ret = kernel_lsp_cmd(RTM_CHANGE, lsp); - - kernel_lsp_pass_fail(lsp, - (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS - : ZEBRA_DPLANE_INSTALL_FAILURE); - return ZEBRA_DPLANE_REQUEST_SUCCESS; -} - -enum zebra_dplane_result kernel_del_lsp(zebra_lsp_t *lsp) -{ - int ret; - - if (!lsp) { // unexpected - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_DELETE_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } - - if (!CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED)) { - kernel_lsp_pass_fail(lsp, ZEBRA_DPLANE_DELETE_FAILURE); - return ZEBRA_DPLANE_REQUEST_FAILURE; - } - - ret = kernel_lsp_cmd(RTM_DELETE, lsp); - - kernel_lsp_pass_fail(lsp, - (!ret) ? ZEBRA_DPLANE_DELETE_SUCCESS - : ZEBRA_DPLANE_DELETE_FAILURE); + ret = kernel_lsp_cmd(ctx); - return ZEBRA_DPLANE_REQUEST_SUCCESS; + return (ret == 0 ? + ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE); } static int kmpw_install(struct zebra_pw *pw) diff --git a/zebra/zebra_ptm_redistribute.c b/zebra/zebra_ptm_redistribute.c index 420105198b..3acbe3bf2c 100644 --- a/zebra/zebra_ptm_redistribute.c +++ b/zebra/zebra_ptm_redistribute.c @@ -37,7 +37,7 @@ static int zsend_interface_bfd_update(int cmd, struct zserv *client, struct stream *s; /* Check this client need interface information. */ - if (!client->ifinfo) + if (!vrf_bitmap_check(client->ifinfo, ifp->vrf_id)) return 0; s = stream_new(ZEBRA_MAX_PACKET_SIZ); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 7e4ac1ddd2..0dc8a05e9c 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1811,7 +1811,7 @@ done: /* * Route-update results processing after async dataplane update. */ -static void rib_process_after(struct zebra_dplane_ctx *ctx) +static void rib_process_result(struct zebra_dplane_ctx *ctx) { struct route_table *table = NULL; struct zebra_vrf *zvrf = NULL; @@ -1931,8 +1931,6 @@ static void rib_process_after(struct zebra_dplane_ctx *ctx) } switch (op) { - case DPLANE_OP_NONE: - break; case DPLANE_OP_ROUTE_INSTALL: case DPLANE_OP_ROUTE_UPDATE: if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) { @@ -2015,6 +2013,8 @@ static void rib_process_after(struct zebra_dplane_ctx *ctx) dest_str, sizeof(dest_str))); } break; + default: + break; } done: @@ -2090,11 +2090,11 @@ static void do_nht_processing(void) zvrf_name(zvrf)); zvrf->flags &= ~ZEBRA_VRF_RIB_SCHEDULED; - zebra_evaluate_rnh(zvrf, AF_INET, 0, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(zvrf, AF_INET, 0, RNH_IMPORT_CHECK_TYPE, + zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_IMPORT_CHECK_TYPE, NULL); - zebra_evaluate_rnh(zvrf, AF_INET6, 0, RNH_NEXTHOP_TYPE, NULL); - zebra_evaluate_rnh(zvrf, AF_INET6, 0, RNH_IMPORT_CHECK_TYPE, + zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_IMPORT_CHECK_TYPE, NULL); } @@ -3191,7 +3191,8 @@ void rib_close_table(struct route_table *table) } /* - * + * Handle results from the dataplane system. Dequeue update context + * structs, dispatch to appropriate internal handlers. */ static int rib_process_dplane_results(struct thread *thread) { @@ -3200,13 +3201,15 @@ static int rib_process_dplane_results(struct thread *thread) /* Dequeue a list of completed updates with one lock/unlock cycle */ + /* TODO -- dequeue a list with one lock/unlock cycle? */ + do { TAILQ_INIT(&ctxlist); /* Take lock controlling queue of results */ pthread_mutex_lock(&dplane_mutex); { - /* Dequeue context block */ + /* Dequeue list of context structs */ dplane_ctx_list_append(&ctxlist, &rib_dplane_q); } pthread_mutex_unlock(&dplane_mutex); @@ -3219,7 +3222,24 @@ static int rib_process_dplane_results(struct thread *thread) break; while (ctx) { - rib_process_after(ctx); + switch (dplane_ctx_get_op(ctx)) { + case DPLANE_OP_ROUTE_INSTALL: + case DPLANE_OP_ROUTE_UPDATE: + case DPLANE_OP_ROUTE_DELETE: + rib_process_result(ctx); + break; + + case DPLANE_OP_LSP_INSTALL: + case DPLANE_OP_LSP_UPDATE: + case DPLANE_OP_LSP_DELETE: + zebra_mpls_lsp_dplane_result(ctx); + break; + + default: + /* Don't expect this: just return the struct? */ + dplane_ctx_fini(&ctx); + break; + } /* Dispatch by op code */ ctx = dplane_ctx_dequeue(&ctxlist); } diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index c3781888b1..317a7cdeca 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -54,16 +54,6 @@ static void free_state(vrf_id_t vrf_id, struct route_entry *re, struct route_node *rn); static void copy_state(struct rnh *rnh, struct route_entry *re, struct route_node *rn); -#define lookup_rnh_table(v, f) \ - ({ \ - struct zebra_vrf *zvrf; \ - struct route_table *t = NULL; \ - zvrf = zebra_vrf_lookup_by_id(v); \ - if (zvrf) \ - t = zvrf->rnh_table[family2afi(f)]; \ - t; \ - }) - static int compare_state(struct route_entry *r1, struct route_entry *r2); static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, vrf_id_t vrf_id); @@ -78,7 +68,7 @@ void zebra_rnh_init(void) hook_register(zserv_client_close, zebra_client_cleanup_rnh); } -static inline struct route_table *get_rnh_table(vrf_id_t vrfid, int family, +static inline struct route_table *get_rnh_table(vrf_id_t vrfid, afi_t afi, rnh_type_t type) { struct zebra_vrf *zvrf; @@ -88,10 +78,10 @@ static inline struct route_table *get_rnh_table(vrf_id_t vrfid, int family, if (zvrf) switch (type) { case RNH_NEXTHOP_TYPE: - t = zvrf->rnh_table[family2afi(family)]; + t = zvrf->rnh_table[afi]; break; case RNH_IMPORT_CHECK_TYPE: - t = zvrf->import_check_table[family2afi(family)]; + t = zvrf->import_check_table[afi]; break; } @@ -116,7 +106,7 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type, prefix2str(p, buf, sizeof(buf)); zlog_debug("%u: Add RNH %s type %d", vrfid, buf, type); } - table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); + table = get_rnh_table(vrfid, family2afi(PREFIX_FAMILY(p)), type); if (!table) { prefix2str(p, buf, sizeof(buf)); flog_warn(EC_ZEBRA_RNH_NO_TABLE, @@ -153,7 +143,7 @@ struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type) struct route_table *table; struct route_node *rn; - table = get_rnh_table(vrfid, PREFIX_FAMILY(p), type); + table = get_rnh_table(vrfid, family2afi(PREFIX_FAMILY(p)), type); if (!table) return NULL; @@ -278,7 +268,8 @@ void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw) if (rnh && !listnode_lookup(rnh->zebra_pseudowire_list, pw)) { listnode_add(rnh->zebra_pseudowire_list, pw); pw->rnh = rnh; - zebra_evaluate_rnh(zvrf, pw->af, 1, RNH_NEXTHOP_TYPE, &nh); + zebra_evaluate_rnh(zvrf, family2afi(pw->af), 1, + RNH_NEXTHOP_TYPE, &nh); } } @@ -299,22 +290,19 @@ void zebra_deregister_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw) /* Apply the NHT route-map for a client to the route (and nexthops) * resolving a NH. */ -static int zebra_rnh_apply_nht_rmap(int family, struct zebra_vrf *zvrf, +static int zebra_rnh_apply_nht_rmap(afi_t afi, struct zebra_vrf *zvrf, struct route_node *prn, struct route_entry *re, int proto) { int at_least_one = 0; - int rmap_family; /* Route map has diff AF family enum */ struct nexthop *nexthop; int ret; - rmap_family = (family == AF_INET) ? AFI_IP : AFI_IP6; - if (prn && re) { for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) { ret = zebra_nht_route_map_check( - rmap_family, proto, &prn->p, zvrf, re, nexthop); + afi, proto, &prn->p, zvrf, re, nexthop); if (ret != RMAP_DENYMATCH) { SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); at_least_one++; /* at least one valid NH */ @@ -331,7 +319,7 @@ static int zebra_rnh_apply_nht_rmap(int family, struct zebra_vrf *zvrf, * for BGP route for import. */ static struct route_entry * -zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, int family, +zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, afi_t afi, struct route_node *nrn, struct rnh *rnh, struct route_node **prn) { @@ -341,7 +329,7 @@ zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, int family, *prn = NULL; - route_table = zvrf->table[family2afi(family)][SAFI_UNICAST]; + route_table = zvrf->table[afi][SAFI_UNICAST]; if (!route_table) // unexpected return NULL; @@ -373,7 +361,7 @@ zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, int family, * See if a tracked route entry for import (by BGP) has undergone any * change, and if so, notify the client. */ -static void zebra_rnh_eval_import_check_entry(vrf_id_t vrfid, int family, +static void zebra_rnh_eval_import_check_entry(vrf_id_t vrfid, afi_t afi, int force, struct route_node *nrn, struct rnh *rnh, struct route_entry *re) @@ -413,9 +401,11 @@ static void zebra_rnh_eval_import_check_entry(vrf_id_t vrfid, int family, /* * Notify clients registered for this nexthop about a change. */ -static void zebra_rnh_notify_protocol_clients( - struct zebra_vrf *zvrf, int family, struct route_node *nrn, - struct rnh *rnh, struct route_node *prn, struct route_entry *re) +static void zebra_rnh_notify_protocol_clients(struct zebra_vrf *zvrf, afi_t afi, + struct route_node *nrn, + struct rnh *rnh, + struct route_node *prn, + struct route_entry *re) { struct listnode *node; struct zserv *client; @@ -441,7 +431,7 @@ static void zebra_rnh_notify_protocol_clients( * nexthop to see if it is filtered or not. */ num_resolving_nh = zebra_rnh_apply_nht_rmap( - family, zvrf, prn, re, client->proto); + afi, zvrf, prn, re, client->proto); if (num_resolving_nh) rnh->filtered[client->proto] = 0; else @@ -468,8 +458,7 @@ static void zebra_rnh_notify_protocol_clients( } } -static void zebra_rnh_process_pbr_tables(int family, - struct route_node *nrn, +static void zebra_rnh_process_pbr_tables(afi_t afi, struct route_node *nrn, struct rnh *rnh, struct route_node *prn, struct route_entry *re) @@ -479,10 +468,6 @@ static void zebra_rnh_process_pbr_tables(int family, struct route_node *o_rn; struct listnode *node; struct zserv *client; - afi_t afi = AFI_IP; - - if (family == AF_INET6) - afi = AFI_IP6; /* * We are only concerned about nexthops that change for @@ -537,7 +522,7 @@ static bool rnh_nexthop_valid(const struct nexthop *nh) * nexthop. */ static struct route_entry * -zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, int family, +zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, struct route_node *nrn, struct rnh *rnh, struct route_node **prn) { @@ -548,7 +533,7 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, int family, *prn = NULL; - route_table = zvrf->table[family2afi(family)][SAFI_UNICAST]; + route_table = zvrf->table[afi][SAFI_UNICAST]; if (!route_table) return NULL; @@ -635,7 +620,7 @@ static void zebra_rnh_process_pseudowires(vrf_id_t vrfid, struct rnh *rnh) * take appropriate action; this involves notifying any clients and/or * scheduling dependent static routes for processing. */ -static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, int family, +static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi, int force, struct route_node *nrn, struct rnh *rnh, struct route_node *prn, @@ -665,10 +650,10 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, int family, * rnh->state. */ /* Notify registered protocol clients. */ - zebra_rnh_notify_protocol_clients(zvrf, family, nrn, rnh, prn, + zebra_rnh_notify_protocol_clients(zvrf, afi, nrn, rnh, prn, rnh->state); - zebra_rnh_process_pbr_tables(family, nrn, rnh, prn, rnh->state); + zebra_rnh_process_pbr_tables(afi, nrn, rnh, prn, rnh->state); /* Process pseudowires attached to this nexthop */ zebra_rnh_process_pseudowires(zvrf->vrf->vrf_id, rnh); @@ -676,7 +661,7 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, int family, } /* Evaluate one tracked entry */ -static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, int family, +static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi, int force, rnh_type_t type, struct route_node *nrn) { @@ -695,11 +680,9 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, int family, /* Identify route entry (RE) resolving this tracked entry. */ if (type == RNH_IMPORT_CHECK_TYPE) - re = zebra_rnh_resolve_import_entry(zvrf, family, nrn, rnh, - &prn); + re = zebra_rnh_resolve_import_entry(zvrf, afi, nrn, rnh, &prn); else - re = zebra_rnh_resolve_nexthop_entry(zvrf, family, nrn, rnh, - &prn); + re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh, &prn); /* If the entry cannot be resolved and that is also the existing state, * there is nothing further to do. @@ -709,10 +692,10 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, int family, /* Process based on type of entry. */ if (type == RNH_IMPORT_CHECK_TYPE) - zebra_rnh_eval_import_check_entry(zvrf->vrf->vrf_id, family, - force, nrn, rnh, re); + zebra_rnh_eval_import_check_entry(zvrf->vrf->vrf_id, afi, force, + nrn, rnh, re); else - zebra_rnh_eval_nexthop_entry(zvrf, family, force, nrn, rnh, prn, + zebra_rnh_eval_nexthop_entry(zvrf, afi, force, nrn, rnh, prn, re); } @@ -725,7 +708,7 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, int family, * we can have a situation where one re entry * covers multiple nexthops we are interested in. */ -static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, int family, +static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi, rnh_type_t type, struct route_node *nrn) { struct rnh *rnh; @@ -736,10 +719,10 @@ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, int family, /* Identify route entry (RIB) resolving this tracked entry. */ if (type == RNH_IMPORT_CHECK_TYPE) - re = zebra_rnh_resolve_import_entry(zvrf, family, nrn, rnh, + re = zebra_rnh_resolve_import_entry(zvrf, afi, nrn, rnh, &prn); else - re = zebra_rnh_resolve_nexthop_entry(zvrf, family, nrn, rnh, + re = zebra_rnh_resolve_nexthop_entry(zvrf, afi, nrn, rnh, &prn); if (re) { @@ -751,13 +734,13 @@ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, int family, /* Evaluate all tracked entries (nexthops or routes for import into BGP) * of a particular VRF and address-family or a specific prefix. */ -void zebra_evaluate_rnh(struct zebra_vrf *zvrf, int family, int force, +void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force, rnh_type_t type, struct prefix *p) { struct route_table *rnh_table; struct route_node *nrn; - rnh_table = get_rnh_table(zvrf->vrf->vrf_id, family, type); + rnh_table = get_rnh_table(zvrf->vrf->vrf_id, afi, type); if (!rnh_table) // unexpected return; @@ -765,8 +748,7 @@ void zebra_evaluate_rnh(struct zebra_vrf *zvrf, int family, int force, /* Evaluating a specific entry, make sure it exists. */ nrn = route_node_lookup(rnh_table, p); if (nrn && nrn->info) - zebra_rnh_evaluate_entry(zvrf, family, force, type, - nrn); + zebra_rnh_evaluate_entry(zvrf, afi, force, type, nrn); if (nrn) route_unlock_node(nrn); @@ -775,27 +757,26 @@ void zebra_evaluate_rnh(struct zebra_vrf *zvrf, int family, int force, nrn = route_top(rnh_table); while (nrn) { if (nrn->info) - zebra_rnh_evaluate_entry(zvrf, family, force, - type, nrn); + zebra_rnh_evaluate_entry(zvrf, afi, force, type, + nrn); nrn = route_next(nrn); /* this will also unlock nrn */ } nrn = route_top(rnh_table); while (nrn) { if (nrn->info) - zebra_rnh_clear_nhc_flag(zvrf, family, type, - nrn); + zebra_rnh_clear_nhc_flag(zvrf, afi, type, nrn); nrn = route_next(nrn); /* this will also unlock nrn */ } } } -void zebra_print_rnh_table(vrf_id_t vrfid, int af, struct vty *vty, +void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty, rnh_type_t type) { struct route_table *table; struct route_node *rn; - table = get_rnh_table(vrfid, af, type); + table = get_rnh_table(vrfid, afi, type); if (!table) { zlog_debug("print_rnhs: rnh table not found\n"); return; @@ -1032,7 +1013,7 @@ static void print_rnh(struct route_node *rn, struct vty *vty) vty_out(vty, "\n"); } -static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, int family, +static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi, struct zserv *client, rnh_type_t type) { struct route_table *ntable; @@ -1040,11 +1021,11 @@ static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, int family, struct rnh *rnh; if (IS_ZEBRA_DEBUG_NHT) - zlog_debug("%u: Client %s RNH cleanup for family %d type %d", - vrf_id, zebra_route_string(client->proto), family, - type); + zlog_debug("%u: Client %s RNH cleanup for family %s type %d", + vrf_id, zebra_route_string(client->proto), + afi2str(afi), type); - ntable = get_rnh_table(vrf_id, family, type); + ntable = get_rnh_table(vrf_id, afi, type); if (!ntable) { zlog_debug("cleanup_rnh_client: rnh table not found\n"); return -1; @@ -1069,14 +1050,14 @@ static int zebra_client_cleanup_rnh(struct zserv *client) RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { zvrf = vrf->info; if (zvrf) { - zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET, client, + zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP, client, RNH_NEXTHOP_TYPE); - zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET6, - client, RNH_NEXTHOP_TYPE); - zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET, client, + zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6, client, + RNH_NEXTHOP_TYPE); + zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP, client, + RNH_IMPORT_CHECK_TYPE); + zebra_cleanup_rnh_client(zvrf_id(zvrf), AFI_IP6, client, RNH_IMPORT_CHECK_TYPE); - zebra_cleanup_rnh_client(zvrf_id(zvrf), AF_INET6, - client, RNH_IMPORT_CHECK_TYPE); if (client->proto == ZEBRA_ROUTE_LDP) { hash_iterate(zvrf->lsp_table, mpls_ldp_lsp_uninstall_all, diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index ed1fe9b756..00ee60dc1a 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -78,9 +78,9 @@ extern void zebra_register_rnh_pseudowire(vrf_id_t, struct zebra_pw *); extern void zebra_deregister_rnh_pseudowire(vrf_id_t, struct zebra_pw *); extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, rnh_type_t type); -extern void zebra_evaluate_rnh(struct zebra_vrf *zvrf, int family, int force, +extern void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force, rnh_type_t type, struct prefix *p); -extern void zebra_print_rnh_table(vrf_id_t vrfid, int family, struct vty *vty, +extern void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty, rnh_type_t); extern char *rnh_str(struct rnh *rnh, char *buf, int size); #endif /*_ZEBRA_RNH_H */ diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index c9918a7887..6d52e5f9e6 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -389,7 +389,7 @@ static int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype, route_map_lookup_by_name(NHT_RM_NAME(zvrf, afi, rtype)); if (NHT_RM_MAP(zvrf, afi, rtype)) - zebra_evaluate_rnh(zvrf, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -409,7 +409,7 @@ static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype, zvrf->vrf->vrf_id, rtype); NHT_RM_MAP(zvrf, afi, rtype) = NULL; - zebra_evaluate_rnh(zvrf, AF_INET, 1, RNH_NEXTHOP_TYPE, + zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL); } XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype)); @@ -1556,7 +1556,7 @@ static void zebra_nht_rm_update(const char *rmap) afi_ip = 1; zebra_evaluate_rnh( - zvrf, AF_INET, 1, + zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL); } } @@ -1582,7 +1582,7 @@ static void zebra_nht_rm_update(const char *rmap) afi_ipv6 = 1; zebra_evaluate_rnh( - zvrf, AF_INET, 1, + zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL); } } @@ -1713,7 +1713,7 @@ zebra_import_table_route_map_check(int family, int re_type, uint8_t instance, return (ret); } -route_map_result_t zebra_nht_route_map_check(int family, int client_proto, +route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto, const struct prefix *p, struct zebra_vrf *zvrf, struct route_entry *re, @@ -1731,9 +1731,9 @@ route_map_result_t zebra_nht_route_map_check(int family, int client_proto, nh_obj.tag = re->tag; if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX) - rmap = NHT_RM_MAP(zvrf, family, client_proto); - if (!rmap && NHT_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX)) - rmap = NHT_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX); + rmap = NHT_RM_MAP(zvrf, afi, client_proto); + if (!rmap && NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX)) + rmap = NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX); if (rmap) ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); @@ -1831,7 +1831,7 @@ void zebra_routemap_config_write_protocol(struct vty *vty, zebra_rmap_update_timer); } -void zebra_route_map_init() +void zebra_route_map_init(void) { install_element(CONFIG_NODE, &ip_protocol_cmd); install_element(CONFIG_NODE, &no_ip_protocol_cmd); diff --git a/zebra/zebra_routemap.h b/zebra/zebra_routemap.h index a8579e7c6e..abd2ad78f7 100644 --- a/zebra/zebra_routemap.h +++ b/zebra/zebra_routemap.h @@ -44,7 +44,7 @@ zebra_route_map_check(int family, int rib_type, uint8_t instance, const struct prefix *p, struct nexthop *nexthop, struct zebra_vrf *zvrf, route_tag_t tag); extern route_map_result_t -zebra_nht_route_map_check(int family, int client_proto, const struct prefix *p, +zebra_nht_route_map_check(afi_t afi, int client_proto, const struct prefix *p, struct zebra_vrf *zvrf, struct route_entry *, struct nexthop *nexthop); diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c index f0cc8d4fd7..3e94d6bca8 100644 --- a/zebra/zebra_router.c +++ b/zebra/zebra_router.c @@ -21,6 +21,9 @@ */ #include "zebra.h" +#include <pthread.h> +#include "lib/frratomic.h" + #include "zebra_router.h" #include "zebra_memory.h" #include "zebra_pbr.h" @@ -169,6 +172,13 @@ static void zebra_router_free_table(struct zebra_router_table *zrt) XFREE(MTYPE_ZEBRA_NS, zrt); } +uint32_t zebra_router_get_next_sequence(void) +{ + return 1 + + atomic_fetch_add_explicit(&zrouter.sequence_num, 1, + memory_order_relaxed); +} + void zebra_router_terminate(void) { struct zebra_router_table *zrt, *tmp; @@ -194,6 +204,8 @@ void zebra_router_terminate(void) void zebra_router_init(void) { + zrouter.sequence_num = 0; + zebra_vxlan_init(); zebra_mlag_init(); diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h index 1e0788d1ba..f63dcd984e 100644 --- a/zebra/zebra_router.h +++ b/zebra/zebra_router.h @@ -62,6 +62,9 @@ struct zebra_router { #if defined(HAVE_RTADV) struct rtadv rtadv; #endif /* HAVE_RTADV */ + + /* A sequence number used for tracking routes */ + _Atomic uint32_t sequence_num; }; extern struct zebra_router zrouter; @@ -83,4 +86,6 @@ extern unsigned long zebra_router_score_proto(uint8_t proto, extern void zebra_router_sweep_route(void); extern void zebra_router_show_table_summary(struct vty *vty); + +extern uint32_t zebra_router_get_next_sequence(void); #endif diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index c28025403b..2473299d17 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -137,12 +137,14 @@ struct zebra_vrf { */ enum vxlan_flood_control vxlan_flood_ctrl; - /* Route Installs */ + /* Install stats */ uint64_t installs; uint64_t removals; uint64_t installs_queued; uint64_t removals_queued; uint64_t neigh_updates; + uint64_t lsp_installs_queued; + uint64_t lsp_removals_queued; uint64_t lsp_installs; uint64_t lsp_removals; }; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index b18f0e943c..902c726511 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -389,11 +389,9 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) json_object_boolean_true_add(json_route, "selected"); - if (re->type != ZEBRA_ROUTE_CONNECT) { - json_object_int_add(json_route, "distance", - re->distance); - json_object_int_add(json_route, "metric", re->metric); - } + json_object_int_add(json_route, "distance", + re->distance); + json_object_int_add(json_route, "metric", re->metric); if (re->tag) json_object_int_add(json_route, "tag", re->tag); @@ -602,7 +600,9 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, srcdest_rnode2str(rn, buf, sizeof buf)); /* Distance and metric display. */ - if (re->type != ZEBRA_ROUTE_CONNECT) + if (((re->type == ZEBRA_ROUTE_CONNECT) && + (re->distance || re->metric)) || + (re->type != ZEBRA_ROUTE_CONNECT)) len += vty_out(vty, " [%u/%u]", re->distance, re->metric); } else { @@ -930,21 +930,35 @@ DEFPY (show_route_table_vrf, return CMD_SUCCESS; } -DEFUN (show_ip_nht, +DEFPY (show_ip_nht, show_ip_nht_cmd, - "show ip nht [vrf NAME]", + "show <ip$ipv4|ipv6$ipv6> nht [vrf NAME$vrf_name|vrf all$vrf_all]", SHOW_STR IP_STR + IP6_STR "IP nexthop tracking table\n" - VRF_CMD_HELP_STR) + VRF_CMD_HELP_STR + VRF_ALL_CMD_HELP_STR) { - int idx_vrf = 4; + afi_t afi = ipv4 ? AFI_IP : AFI_IP6; vrf_id_t vrf_id = VRF_DEFAULT; - if (argc == 5) - VRF_GET_ID(vrf_id, argv[idx_vrf]->arg, false); + if (vrf_all) { + struct vrf *vrf; + struct zebra_vrf *zvrf; - zebra_print_rnh_table(vrf_id, AF_INET, vty, RNH_NEXTHOP_TYPE); + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) + if ((zvrf = vrf->info) != NULL) { + vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf)); + zebra_print_rnh_table(zvrf_id(zvrf), afi, vty, + RNH_NEXTHOP_TYPE); + } + return CMD_SUCCESS; + } + if (vrf_name) + VRF_GET_ID(vrf_id, vrf_name, false); + + zebra_print_rnh_table(vrf_id, afi, vty, RNH_NEXTHOP_TYPE); return CMD_SUCCESS; } @@ -969,9 +983,8 @@ DEFPY (show_ip_import_check, if ((zvrf = vrf->info) != NULL) { vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf)); - zebra_print_rnh_table(zvrf_id(zvrf), - afi, vty, - RNH_NEXTHOP_TYPE); + zebra_print_rnh_table(zvrf_id(zvrf), afi, vty, + RNH_IMPORT_CHECK_TYPE); } return CMD_SUCCESS; } @@ -982,67 +995,6 @@ DEFPY (show_ip_import_check, return CMD_SUCCESS; } -DEFUN (show_ip_nht_vrf_all, - show_ip_nht_vrf_all_cmd, - "show ip nht vrf all", - SHOW_STR - IP_STR - "IP nexthop tracking table\n" - VRF_ALL_CMD_HELP_STR) -{ - struct vrf *vrf; - struct zebra_vrf *zvrf; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) { - vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf)); - zebra_print_rnh_table(zvrf_id(zvrf), AF_INET, vty, - RNH_NEXTHOP_TYPE); - } - - return CMD_SUCCESS; -} - -DEFUN (show_ipv6_nht, - show_ipv6_nht_cmd, - "show ipv6 nht [vrf NAME]", - SHOW_STR - IPV6_STR - "IPv6 nexthop tracking table\n" - VRF_CMD_HELP_STR) -{ - int idx_vrf = 4; - vrf_id_t vrf_id = VRF_DEFAULT; - - if (argc == 5) - VRF_GET_ID(vrf_id, argv[idx_vrf]->arg, false); - - zebra_print_rnh_table(vrf_id, AF_INET6, vty, RNH_NEXTHOP_TYPE); - return CMD_SUCCESS; -} - - -DEFUN (show_ipv6_nht_vrf_all, - show_ipv6_nht_vrf_all_cmd, - "show ipv6 nht vrf all", - SHOW_STR - IP_STR - "IPv6 nexthop tracking table\n" - VRF_ALL_CMD_HELP_STR) -{ - struct vrf *vrf; - struct zebra_vrf *zvrf; - - RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) - if ((zvrf = vrf->info) != NULL) { - vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf)); - zebra_print_rnh_table(zvrf_id(zvrf), AF_INET6, vty, - RNH_NEXTHOP_TYPE); - } - - return CMD_SUCCESS; -} - DEFUN (ip_nht_default_route, ip_nht_default_route_cmd, "ip nht resolve-via-default", @@ -1060,7 +1012,7 @@ DEFUN (ip_nht_default_route, zebra_rnh_ip_default_route = 1; - zebra_evaluate_rnh(zvrf, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -1081,7 +1033,7 @@ DEFUN (no_ip_nht_default_route, return CMD_SUCCESS; zebra_rnh_ip_default_route = 0; - zebra_evaluate_rnh(zvrf, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -1101,7 +1053,7 @@ DEFUN (ipv6_nht_default_route, return CMD_SUCCESS; zebra_rnh_ipv6_default_route = 1; - zebra_evaluate_rnh(zvrf, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP6, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -1123,7 +1075,7 @@ DEFUN (no_ipv6_nht_default_route, return CMD_SUCCESS; zebra_rnh_ipv6_default_route = 0; - zebra_evaluate_rnh(zvrf, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AFI_IP6, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -2955,9 +2907,6 @@ void zebra_vty_init(void) install_element(VIEW_NODE, &show_route_summary_cmd); install_element(VIEW_NODE, &show_ip_nht_cmd); install_element(VIEW_NODE, &show_ip_import_check_cmd); - install_element(VIEW_NODE, &show_ip_nht_vrf_all_cmd); - install_element(VIEW_NODE, &show_ipv6_nht_cmd); - install_element(VIEW_NODE, &show_ipv6_nht_vrf_all_cmd); install_element(VIEW_NODE, &show_ip_rpf_cmd); install_element(VIEW_NODE, &show_ip_rpf_addr_cmd); diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 86a7812780..45e6caebbe 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -81,7 +81,7 @@ static void zvni_print_hash(struct hash_backet *backet, void *ctxt[]); static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, struct ipaddr *ip, uint8_t flags, - uint32_t seq, uint16_t cmd); + uint32_t seq, int state, uint16_t cmd); static unsigned int neigh_hash_keymake(void *p); static void *zvni_neigh_alloc(void *p); static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip, @@ -97,7 +97,7 @@ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip, uint8_t flags, uint32_t seq); static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip, struct ethaddr *macaddr, - uint8_t flags); + uint8_t flags, int state); static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n); static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n); static zebra_vni_t *zvni_from_svi(struct interface *ifp, @@ -163,7 +163,7 @@ static zebra_vni_t *zvni_add(vni_t vni); static int zvni_del(zebra_vni_t *zvni); static int zvni_send_add_to_client(zebra_vni_t *zvni); static int zvni_send_del_to_client(vni_t vni); -static void zvni_build_hash_table(); +static void zvni_build_hash_table(void); static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep); static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip); static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip); @@ -2046,7 +2046,7 @@ static void zvni_print_hash_detail(struct hash_backet *backet, void *data) */ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, struct ipaddr *ip, uint8_t flags, - uint32_t seq, uint16_t cmd) + uint32_t seq, int state, uint16_t cmd) { char buf[ETHER_ADDR_STRLEN]; char buf2[INET6_ADDRSTRLEN]; @@ -2080,6 +2080,8 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, if (cmd == ZEBRA_MACIP_ADD) { stream_putc(s, flags); /* sticky mac/gateway mac */ stream_putl(s, seq); /* sequence number */ + } else { + stream_putl(s, state); /* state - active/inactive */ } @@ -2218,7 +2220,7 @@ static void zvni_neigh_del_hash_entry(struct hash_backet *backet, void *arg) && IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) { if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL)) zvni_neigh_send_del_to_client(wctx->zvni->vni, &n->ip, - &n->emac, 0); + &n->emac, 0, n->state); if (wctx->uninstall) zvni_neigh_uninstall(wctx->zvni, n); @@ -2354,7 +2356,7 @@ static void zvni_process_neigh_on_local_mac_del(zebra_vni_t *zvni, ZEBRA_NEIGH_SET_INACTIVE(n); n->loc_seq = 0; zvni_neigh_send_del_to_client(zvni->vni, &n->ip, - &n->emac, 0); + &n->emac, 0, ZEBRA_NEIGH_ACTIVE); } } } @@ -2385,7 +2387,7 @@ static void zvni_process_neigh_on_remote_mac_add(zebra_vni_t *zvni, ZEBRA_NEIGH_SET_INACTIVE(n); n->loc_seq = 0; zvni_neigh_send_del_to_client(zvni->vni, &n->ip, - &n->emac, 0); + &n->emac, 0, ZEBRA_NEIGH_ACTIVE); } } } @@ -2418,17 +2420,18 @@ static int zvni_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip, SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags, - seq, ZEBRA_MACIP_ADD); + seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD); } /* * Inform BGP about local neighbor deletion. */ static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip, - struct ethaddr *macaddr, uint8_t flags) + struct ethaddr *macaddr, uint8_t flags, + int state) { return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags, - 0, ZEBRA_MACIP_DEL); + 0, state, ZEBRA_MACIP_DEL); } /* @@ -2749,7 +2752,7 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni, /* Remove neighbor from BGP. */ zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, - ZEBRA_MACIP_TYPE_GW); + ZEBRA_MACIP_TYPE_GW, ZEBRA_NEIGH_ACTIVE); /* Delete this neighbor entry. */ zvni_neigh_del(zvni, n); @@ -2963,7 +2966,7 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni, */ if (IS_ZEBRA_NEIGH_ACTIVE(n)) zvni_neigh_send_del_to_client(zvni->vni, &n->ip, - &n->emac, 0); + &n->emac, 0, n->state); old_zmac = zvni_mac_lookup(zvni, &n->emac); if (old_zmac) { old_mac_seq = CHECK_FLAG(old_zmac->flags, @@ -3319,7 +3322,7 @@ static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr, SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags, - seq, ZEBRA_MACIP_ADD); + seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD); } /* @@ -3328,7 +3331,7 @@ static int zvni_mac_send_add_to_client(vni_t vni, struct ethaddr *macaddr, static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr) { return zvni_macip_send_msg_to_client(vni, macaddr, NULL, 0 /* flags */, - 0 /* seq */, ZEBRA_MACIP_DEL); + 0 /* seq */, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_DEL); } /* @@ -3841,7 +3844,7 @@ static int zvni_send_del_to_client(vni_t vni) * Build the VNI hash table by going over the VxLAN interfaces. This * is called when EVPN (advertise-all-vni) is enabled. */ -static void zvni_build_hash_table() +static void zvni_build_hash_table(void) { struct zebra_ns *zns; struct route_node *rn; @@ -5255,7 +5258,7 @@ static void process_remote_macip_add(vni_t vni, IS_ZEBRA_NEIGH_ACTIVE(n)) zvni_neigh_send_del_to_client( zvni->vni, &n->ip, - &n->emac, 0); + &n->emac, 0, n->state); /* update neigh list for macs */ old_mac = zvni_mac_lookup(zvni, &n->emac); @@ -5337,6 +5340,9 @@ static void process_remote_macip_del(vni_t vni, zebra_neigh_t *n = NULL; struct interface *ifp = NULL; struct zebra_if *zif = NULL; + struct zebra_ns *zns; + struct zebra_l2info_vxlan *vxl; + struct zebra_vrf *zvrf; char buf[ETHER_ADDR_STRLEN]; char buf1[INET6_ADDRSTRLEN]; @@ -5360,6 +5366,8 @@ static void process_remote_macip_del(vni_t vni, vni); return; } + zns = zebra_ns_lookup(NS_DEFAULT); + vxl = &zif->l2info.vxl; /* The remote VTEP specified is normally expected to exist, but * it is possible that the peer may delete the VTEP before deleting @@ -5386,9 +5394,10 @@ static void process_remote_macip_del(vni_t vni, if (!mac && !n) return; + zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id); + /* Ignore the delete if this mac is a gateway mac-ip */ - if (mac - && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) && CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) { zlog_warn( "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC", @@ -5402,6 +5411,23 @@ static void process_remote_macip_del(vni_t vni, /* Uninstall remote neighbor or MAC. */ if (n) { + if (zvrf->dad_freeze && + CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE) && + CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE) && + (memcmp(n->emac.octet, macaddr->octet, ETH_ALEN) == 0)) { + struct interface *vlan_if; + + vlan_if = zvni_map_to_svi(vxl->access_vlan, + zif->brslave_info.br_if); + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry", + __PRETTY_FUNCTION__, + ipaddr2str(ipaddr, buf1, + sizeof(buf1)), n->flags, + vlan_if->name); + neigh_read_specific_ip(ipaddr, vlan_if); + } + /* When the MAC changes for an IP, it is possible the * client may update the new MAC before trying to delete the * "old" neighbor (as these are two different MACIP routes). @@ -5414,6 +5440,25 @@ static void process_remote_macip_del(vni_t vni, zvni_deref_ip2mac(zvni, mac); } } else { + /* DAD: when MAC is freeze state as remote learn event, + * remote mac-ip delete event is received will result in freeze + * entry removal, first fetch kernel for the same entry present + * as LOCAL and reachable, avoid deleting this entry instead + * use kerenel local entry to update during unfreeze time. + */ + if (zvrf->dad_freeze && + CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) && + CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry", + __PRETTY_FUNCTION__, + prefix_mac2str(macaddr, buf, + sizeof(buf)), + mac->flags); + macfdb_read_specific_mac(zns, zif->brslave_info.br_if, + macaddr, vxl->access_vlan); + } + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { zvni_process_neigh_on_remote_mac_del(zvni, mac); /* @@ -7032,8 +7077,8 @@ int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp, } /* Remove neighbor from BGP. */ - if (IS_ZEBRA_NEIGH_ACTIVE(n)) - zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, 0); + zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, + 0, n->state); /* Delete this neighbor entry. */ zvni_neigh_del(zvni, n); diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index c50664a28b..c25e7357ed 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -37,7 +37,7 @@ /* Is EVPN enabled? */ #define EVPN_ENABLED(zvrf) (zvrf)->advertise_all_vni -static inline int is_evpn_enabled() +static inline int is_evpn_enabled(void) { struct zebra_vrf *zvrf = NULL; zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); @@ -45,7 +45,7 @@ static inline int is_evpn_enabled() } static inline int -is_vxlan_flooding_head_end() +is_vxlan_flooding_head_end(void) { struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); diff --git a/zebra/zebra_vxlan_private.h b/zebra/zebra_vxlan_private.h index 3be7dc012a..cae0d62bb3 100644 --- a/zebra/zebra_vxlan_private.h +++ b/zebra/zebra_vxlan_private.h @@ -313,11 +313,9 @@ struct rmac_walk_ctx { struct json_object *json; }; -enum zebra_neigh_state { ZEBRA_NEIGH_INACTIVE = 0, ZEBRA_NEIGH_ACTIVE = 1 }; +#define IS_ZEBRA_NEIGH_ACTIVE(n) (n->state == ZEBRA_NEIGH_ACTIVE) -#define IS_ZEBRA_NEIGH_ACTIVE(n) n->state == ZEBRA_NEIGH_ACTIVE - -#define IS_ZEBRA_NEIGH_INACTIVE(n) n->state == ZEBRA_NEIGH_INACTIVE +#define IS_ZEBRA_NEIGH_INACTIVE(n) (n->state == ZEBRA_NEIGH_INACTIVE) #define ZEBRA_NEIGH_SET_ACTIVE(n) n->state = ZEBRA_NEIGH_ACTIVE diff --git a/zebra/zserv.c b/zebra/zserv.c index 502186d226..766dd54fb3 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -723,8 +723,6 @@ static struct zserv *zserv_client_create(int sock) frr_pthread_new(&zclient_pthr_attrs, "Zebra API client thread", "zebra_apic"); - zebra_vrf_update_all(client); - /* start read loop */ zserv_client_event(client, ZSERV_CLIENT_READ); |
