diff options
Diffstat (limited to 'zebra')
| -rw-r--r-- | zebra/connected.c | 4 | ||||
| -rw-r--r-- | zebra/interface.c | 10 | ||||
| -rw-r--r-- | zebra/redistribute.c | 8 | ||||
| -rw-r--r-- | zebra/rt_netlink.c | 16 | ||||
| -rw-r--r-- | zebra/sample_plugin.c | 134 | ||||
| -rw-r--r-- | zebra/zebra_dplane.c | 4 | ||||
| -rw-r--r-- | zebra/zebra_fpm.c | 21 | ||||
| -rw-r--r-- | zebra/zebra_mpls.c | 40 | ||||
| -rw-r--r-- | zebra/zebra_nhg.c | 116 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 21 | ||||
| -rw-r--r-- | zebra/zebra_vrf.c | 27 | ||||
| -rw-r--r-- | zebra/zebra_vrf.h | 10 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 12 | ||||
| -rw-r--r-- | zebra/zebra_vxlan.c | 61 |
14 files changed, 370 insertions, 114 deletions
diff --git a/zebra/connected.c b/zebra/connected.c index 75f4f53bc6..0ff474d787 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -65,7 +65,7 @@ static void connected_withdraw(struct connected *ifc) if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED)) { listnode_delete(ifc->ifp->connected, ifc); - connected_free(ifc); + connected_free(&ifc); } } @@ -177,7 +177,7 @@ static void connected_update(struct interface *ifp, struct connected *ifc) */ if (connected_same(current, ifc)) { /* nothing to do */ - connected_free(ifc); + connected_free(&ifc); return; } diff --git a/zebra/interface.c b/zebra/interface.c index daa93e36d1..eea80652e5 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -738,7 +738,7 @@ static void if_delete_connected(struct interface *ifp) ZEBRA_IFC_CONFIGURED)) { listnode_delete(ifp->connected, ifc); - connected_free(ifc); + connected_free(&ifc); } else last = node; } @@ -759,7 +759,7 @@ static void if_delete_connected(struct interface *ifp) last = node; else { listnode_delete(ifp->connected, ifc); - connected_free(ifc); + connected_free(&ifc); } } else { last = node; @@ -829,7 +829,7 @@ void if_delete_update(struct interface *ifp) if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("interface %s is being deleted from the system", ifp->name); - if_delete(ifp); + if_delete(&ifp); } } @@ -2878,7 +2878,7 @@ static int ip_address_uninstall(struct vty *vty, struct interface *ifp, if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { listnode_delete(ifp->connected, ifc); - connected_free(ifc); + connected_free(&ifc); return CMD_WARNING_CONFIG_FAILED; } @@ -3103,7 +3103,7 @@ static int ipv6_address_uninstall(struct vty *vty, struct interface *ifp, if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) || !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) { listnode_delete(ifp->connected, ifc); - connected_free(ifc); + connected_free(&ifc); return CMD_WARNING_CONFIG_FAILED; } diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 4e0163f8ac..98603c9693 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -718,8 +718,8 @@ int zebra_import_table(afi_t afi, vrf_id_t vrf_id, uint32_t table_id, if (afi >= AFI_MAX) return (-1); - table = zebra_vrf_table_with_table_id(afi, SAFI_UNICAST, vrf_id, - table_id); + table = zebra_vrf_get_table_with_table_id(afi, SAFI_UNICAST, vrf_id, + table_id); if (table == NULL) { return 0; } else if (IS_ZEBRA_DEBUG_RIB) { @@ -830,8 +830,8 @@ static void zebra_import_table_rm_update_vrf_afi(struct zebra_vrf *zvrf, if ((!rmap_name) || (strcmp(rmap_name, rmap) != 0)) return; - table = zebra_vrf_table_with_table_id(afi, SAFI_UNICAST, - zvrf->vrf->vrf_id, table_id); + table = zebra_vrf_get_table_with_table_id(afi, SAFI_UNICAST, + zvrf->vrf->vrf_id, table_id); if (!table) { if (IS_ZEBRA_DEBUG_RIB_DETAILED) zlog_debug("%s: Table id=%d not found", __func__, diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 640802fe31..c9a9a81b18 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -2246,6 +2246,7 @@ static struct nexthop netlink_nexthop_process_nh(struct rtattr **tb, enum nexthop_types_t type = 0; int if_index = 0; size_t sz = 0; + struct interface *ifp_lookup; if_index = *(int *)RTA_DATA(tb[NHA_OIF]); @@ -2280,9 +2281,13 @@ static struct nexthop netlink_nexthop_process_nh(struct rtattr **tb, if (if_index) nh.ifindex = if_index; - *ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), nh.ifindex); + ifp_lookup = + if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), nh.ifindex); + if (ifp) - nh.vrf_id = (*ifp)->vrf_id; + *ifp = ifp_lookup; + if (ifp_lookup) + nh.vrf_id = ifp_lookup->vrf_id; else { flog_warn( EC_ZEBRA_UNKNOWN_INTERFACE, @@ -2451,7 +2456,6 @@ int netlink_nexthop_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) return 0; } -#if 0 /* Force off kernel nexthop group installs for now */ /** * netlink_request_nexthop() - Request nextop information from the kernel * @zns: Zebra namespace @@ -2510,12 +2514,6 @@ int netlink_nexthop_read(struct zebra_ns *zns) return ret; } -#else -int netlink_nexthop_read(struct zebra_ns *zns) -{ - return 0; -} -#endif int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, diff --git a/zebra/sample_plugin.c b/zebra/sample_plugin.c new file mode 100644 index 0000000000..c96a86cc73 --- /dev/null +++ b/zebra/sample_plugin.c @@ -0,0 +1,134 @@ +/* + * Sample plugin for the FRR zebra dataplane. + * + * Copyright (c) 2019 Volta Networks, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Should be possible to build this plugin using this sort of command: + * + * gcc -I ~/work/frr/ -I ~/work/frr/lib -I ~/work/frr/zebra \ + * -g -O0 -o sample_plugin.so -shared -fPIC sample_plugin.c + * + * where 'frr' is a configured and built frr sandbox. + * + * Run zebra with '-M /path/to/sample_plugin.so' to load the module. + */ + +#include "config.h" /* Include this explicitly */ +#include "lib/zebra.h" +#include "lib/libfrr.h" +#include "zebra/zebra_dplane.h" +#include "zebra/debug.h" + +static const char *plugin_name = "SAMPLE"; + +static struct zebra_dplane_provider *prov_p; + +/* + * Startup/init callback, called from the dataplane. + */ +static int sample_start(struct zebra_dplane_provider *prov) +{ + /* Nothing special to do - we don't allocate anything. */ + return 0; +} + + +/* + * Shutdown/cleanup callback, called from the dataplane pthread. + */ +static int sample_fini(struct zebra_dplane_provider *prov, bool early) +{ + /* Nothing special to do. */ + return 0; +} + +/* + * Callback from the dataplane to process incoming work; this runs in the + * dplane pthread. + */ +static int sample_process(struct zebra_dplane_provider *prov) +{ + int counter, limit; + struct zebra_dplane_ctx *ctx; + + limit = dplane_provider_get_work_limit(prov_p); + + /* Respect the configured limit on the amount of work to do in + * any one call. + */ + for (counter = 0; counter < limit; counter++) { + ctx = dplane_provider_dequeue_in_ctx(prov_p); + if (!ctx) + break; + + /* Just set 'success' status and return to the dataplane */ + dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_SUCCESS); + dplane_provider_enqueue_out_ctx(prov_p, ctx); + } + + return 0; +} + +/* + * Init entry point called during zebra startup. This is registered during + * module init. + */ +static int init_sample_plugin(struct thread_master *tm) +{ + int ret; + struct zebra_dplane_provider *prov = NULL; + + /* Note that we don't use or store the thread_master 'tm'. We + * don't use the zebra main pthread: our plugin code will run in + * the zebra dataplane pthread context. + */ + + /* Register the plugin with the dataplane infrastructure. We + * register to be called before the kernel, and we register + * our init, process work, and shutdown callbacks. + */ + ret = dplane_provider_register(plugin_name, DPLANE_PRIO_PRE_KERNEL, + DPLANE_PROV_FLAGS_DEFAULT, + sample_start, + sample_process, + sample_fini, + NULL, + &prov_p); + + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("sample plugin register => %d", ret); + + return 0; +} + +/* + * Base FRR loadable module info: basic info including module entry-point. + */ +static int module_init(void) +{ + hook_register(frr_late_init, init_sample_plugin); + return 0; +} + +FRR_MODULE_SETUP( + .name = "dplane_sample", + .version = "0.0.1", + .description = "Dataplane Sample Plugin", + .init = module_init, + ) diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index a88b0a38da..7f993442a6 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -3752,7 +3752,9 @@ void zebra_dplane_shutdown(void) zdplane_info.dg_run = false; - THREAD_OFF(zdplane_info.dg_t_update); + if (zdplane_info.dg_t_update) + thread_cancel_async(zdplane_info.dg_t_update->master, + &zdplane_info.dg_t_update, NULL); frr_pthread_stop(zdplane_info.dg_pthread, NULL); diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index 5d88d4eeb4..fa48c03c71 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -498,6 +498,11 @@ static inline void zfpm_write_off(void) THREAD_WRITE_OFF(zfpm_g->t_write); } +static inline void zfpm_connect_off(void) +{ + THREAD_TIMER_OFF(zfpm_g->t_connect); +} + /* * zfpm_conn_up_thread_cb * @@ -731,7 +736,6 @@ static int zfpm_read_cb(struct thread *thread) fpm_msg_hdr_t *hdr; zfpm_g->stats.read_cb_calls++; - zfpm_g->t_read = NULL; /* * Check if async connect is now done. @@ -1157,7 +1161,6 @@ static int zfpm_write_cb(struct thread *thread) int num_writes; zfpm_g->stats.write_cb_calls++; - zfpm_g->t_write = NULL; /* * Check if async connect is now done. @@ -1241,7 +1244,6 @@ static int zfpm_connect_cb(struct thread *t) int sock, ret; struct sockaddr_in serv; - zfpm_g->t_connect = NULL; assert(zfpm_g->state == ZFPM_STATE_ACTIVE); sock = socket(AF_INET, SOCK_STREAM, 0); @@ -2029,11 +2031,24 @@ static int zfpm_init(struct thread_master *master) return 0; } +static int zfpm_fini(void) +{ + zfpm_write_off(); + zfpm_read_off(); + zfpm_connect_off(); + + zfpm_stop_stats_timer(); + + hook_unregister(rib_update, zfpm_trigger_update); + return 0; +} + static int zebra_fpm_module_init(void) { hook_register(rib_update, zfpm_trigger_update); hook_register(zebra_rmac_update, zfpm_trigger_rmac_update); hook_register(frr_late_init, zfpm_init); + hook_register(frr_early_fini, zfpm_fini); return 0; } diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index ef1bd02608..6942a37989 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -2565,6 +2565,16 @@ void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf, fec_print(rn->info, vty); } +static void mpls_zebra_nhg_update(struct route_entry *re, afi_t afi, + struct nexthop_group *new_grp) +{ + struct nhg_hash_entry *nhe; + + nhe = zebra_nhg_rib_find(0, new_grp, afi); + + zebra_nhg_re_update_ref(re, nhe); +} + static bool mpls_ftn_update_nexthop(int add, struct nexthop *nexthop, enum lsp_types_t type, mpls_label_t label) { @@ -2591,7 +2601,6 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type, struct route_entry *re; struct nexthop *nexthop; struct nexthop_group new_grp = {}; - struct nhg_hash_entry *nhe = NULL; bool found; afi_t afi = family2afi(prefix->family); @@ -2658,12 +2667,11 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type, } if (found) { - nhe = zebra_nhg_rib_find(0, &new_grp, afi); - - zebra_nhg_re_update_ref(re, nhe); - SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED); + + mpls_zebra_nhg_update(re, afi, &new_grp); + rib_queue_add(rn); } @@ -2680,10 +2688,11 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type, struct route_node *rn; struct route_entry *re; struct nexthop *nexthop; + struct nexthop_group new_grp = {}; + afi_t afi = family2afi(prefix->family); /* Lookup table. */ - table = zebra_vrf_table(family2afi(prefix->family), SAFI_UNICAST, - zvrf_id(zvrf)); + table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf_id(zvrf)); if (!table) return -1; @@ -2698,11 +2707,18 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type, if (re == NULL) return -1; - for (nexthop = re->ng->nexthop; nexthop; nexthop = nexthop->next) + nexthop_group_copy(&new_grp, re->ng); + + for (nexthop = new_grp.nexthop; nexthop; nexthop = nexthop->next) nexthop_del_labels(nexthop); SET_FLAG(re->status, ROUTE_ENTRY_CHANGED); SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED); + + mpls_zebra_nhg_update(re, afi, &new_grp); + + nexthops_free(new_grp.nexthop); + rib_queue_add(rn); return 0; @@ -2904,7 +2920,6 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf, update = 0; RNODE_FOREACH_RE (rn, re) { struct nexthop_group new_grp = {}; - struct nhg_hash_entry *nhe = NULL; nexthop_group_copy(&new_grp, re->ng); @@ -2920,11 +2935,8 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf, update = 1; } - if (CHECK_FLAG(re->status, - ROUTE_ENTRY_LABELS_CHANGED)) { - nhe = zebra_nhg_rib_find(0, &new_grp, afi); - zebra_nhg_re_update_ref(re, nhe); - } + if (CHECK_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED)) + mpls_zebra_nhg_update(re, afi, &new_grp); nexthops_free(new_grp.nexthop); } diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 2bb117b272..2d7521d8be 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -360,6 +360,8 @@ bool zebra_nhg_hash_equal(const void *arg1, const void *arg2) { const struct nhg_hash_entry *nhe1 = arg1; const struct nhg_hash_entry *nhe2 = arg2; + struct nexthop *nexthop1; + struct nexthop *nexthop2; /* No matter what if they equal IDs, assume equal */ if (nhe1->id && nhe2->id && (nhe1->id == nhe2->id)) @@ -371,12 +373,47 @@ bool zebra_nhg_hash_equal(const void *arg1, const void *arg2) if (nhe1->afi != nhe2->afi) return false; - if (nexthop_group_active_nexthop_num_no_recurse(nhe1->nhg) - != nexthop_group_active_nexthop_num_no_recurse(nhe2->nhg)) - return false; + /* Nexthops should be sorted */ + for (nexthop1 = nhe1->nhg->nexthop, nexthop2 = nhe2->nhg->nexthop; + nexthop1 || nexthop2; + nexthop1 = nexthop1->next, nexthop2 = nexthop2->next) { + if (nexthop1 && !nexthop2) + return false; - if (!nexthop_group_equal_no_recurse(nhe1->nhg, nhe2->nhg)) - return false; + if (!nexthop1 && nexthop2) + return false; + + /* + * We have to check the active flag of each individual one, + * not just the overall active_num. This solves the special case + * issue of a route with a nexthop group with one nexthop + * resolving to itself and thus marking it inactive. If we + * have two different routes each wanting to mark a different + * nexthop inactive, they need to hash to two different groups. + * + * If we just hashed on num_active, they would hash the same + * which is incorrect. + * + * ex) + * 1.1.1.0/24 + * -> 1.1.1.1 dummy1 (inactive) + * -> 1.1.2.1 dummy2 + * + * 1.1.2.0/24 + * -> 1.1.1.1 dummy1 + * -> 1.1.2.1 dummy2 (inactive) + * + * Without checking each individual one, they would hash to + * the same group and both have 1.1.1.1 dummy1 marked inactive. + * + */ + if (CHECK_FLAG(nexthop1->flags, NEXTHOP_FLAG_ACTIVE) + != CHECK_FLAG(nexthop2->flags, NEXTHOP_FLAG_ACTIVE)) + return false; + + if (!nexthop_same(nexthop1, nexthop2)) + return false; + } return true; } @@ -552,20 +589,6 @@ zebra_nhg_find_nexthop(uint32_t id, struct nexthop *nh, afi_t afi, int type) return nhe; } -static struct nhg_ctx *nhg_ctx_new() -{ - struct nhg_ctx *new = NULL; - - new = XCALLOC(MTYPE_NHG_CTX, sizeof(struct nhg_ctx)); - - return new; -} - -static void nhg_ctx_free(struct nhg_ctx *ctx) -{ - XFREE(MTYPE_NHG_CTX, ctx); -} - static uint32_t nhg_ctx_get_id(const struct nhg_ctx *ctx) { return ctx->id; @@ -621,6 +644,36 @@ static struct nh_grp *nhg_ctx_get_grp(struct nhg_ctx *ctx) return ctx->u.grp; } +static struct nhg_ctx *nhg_ctx_new() +{ + struct nhg_ctx *new = NULL; + + new = XCALLOC(MTYPE_NHG_CTX, sizeof(struct nhg_ctx)); + + return new; +} + +static void nhg_ctx_free(struct nhg_ctx **ctx) +{ + struct nexthop *nh; + + if (ctx == NULL) + return; + + assert((*ctx) != NULL); + + if (nhg_ctx_get_count(*ctx)) + goto done; + + nh = nhg_ctx_get_nh(*ctx); + + nexthop_del_labels(nh); + +done: + XFREE(MTYPE_NHG_CTX, *ctx); + *ctx = NULL; +} + static struct nhg_ctx *nhg_ctx_init(uint32_t id, struct nexthop *nh, struct nh_grp *grp, vrf_id_t vrf_id, afi_t afi, int type, uint8_t count) @@ -869,25 +922,14 @@ static int nhg_ctx_process_del(struct nhg_ctx *ctx) return 0; } -static void nhg_ctx_process_finish(struct nhg_ctx *ctx) +static void nhg_ctx_fini(struct nhg_ctx **ctx) { - struct nexthop *nh; - /* * Just freeing for now, maybe do something more in the future * based on flag. */ - if (nhg_ctx_get_count(ctx)) - goto done; - - nh = nhg_ctx_get_nh(ctx); - - nexthop_del_labels(nh); - -done: - if (ctx) - nhg_ctx_free(ctx); + nhg_ctx_free(ctx); } static int queue_add(struct nhg_ctx *ctx) @@ -942,7 +984,7 @@ int nhg_ctx_process(struct nhg_ctx *ctx) nhg_ctx_set_status(ctx, (ret ? NHG_CTX_FAILURE : NHG_CTX_SUCCESS)); - nhg_ctx_process_finish(ctx); + nhg_ctx_fini(&ctx); return ret; } @@ -971,7 +1013,7 @@ int zebra_nhg_kernel_find(uint32_t id, struct nexthop *nh, struct nh_grp *grp, return nhg_ctx_process(ctx); if (queue_add(ctx)) { - nhg_ctx_process_finish(ctx); + nhg_ctx_fini(&ctx); return -1; } @@ -988,7 +1030,7 @@ int zebra_nhg_kernel_del(uint32_t id) nhg_ctx_set_op(ctx, NHG_CTX_OP_DEL); if (queue_add(ctx)) { - nhg_ctx_process_finish(ctx); + nhg_ctx_fini(&ctx); return -1; } @@ -1001,6 +1043,9 @@ static struct nhg_hash_entry *depends_find(struct nexthop *nh, afi_t afi) struct nexthop *lookup = NULL; struct nhg_hash_entry *nhe = NULL; + if (!nh) + goto done; + copy_nexthops(&lookup, nh, NULL); /* Clear it, in case its a group */ @@ -1013,6 +1058,7 @@ static struct nhg_hash_entry *depends_find(struct nexthop *nh, afi_t afi) nexthops_free(lookup); +done: return nhe; } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index e0bf1a58f2..781963793e 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -570,14 +570,6 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re, nexthops_free(old->fib_ng.nexthop); old->fib_ng.nexthop = NULL; } - - if (!RIB_SYSTEM_ROUTE(old)) { - /* Clear old route's FIB flags */ - for (ALL_NEXTHOPS_PTR(old->ng, nexthop)) { - UNSET_FLAG(nexthop->flags, - NEXTHOP_FLAG_FIB); - } - } } if (zvrf) @@ -1575,10 +1567,9 @@ rib_find_rn_from_ctx(const struct zebra_dplane_ctx *ctx) /* Locate rn and re(s) from ctx */ - table = zebra_vrf_table_with_table_id(dplane_ctx_get_afi(ctx), - dplane_ctx_get_safi(ctx), - dplane_ctx_get_vrf(ctx), - dplane_ctx_get_table(ctx)); + table = zebra_vrf_lookup_table_with_table_id( + dplane_ctx_get_afi(ctx), dplane_ctx_get_safi(ctx), + dplane_ctx_get_vrf(ctx), dplane_ctx_get_table(ctx)); if (table == NULL) { if (IS_ZEBRA_DEBUG_DPLANE) { zlog_debug("Failed to find route for ctx: no table for afi %d, safi %d, vrf %u", @@ -2664,7 +2655,8 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p, assert(!src_p || !src_p->prefixlen || afi == AFI_IP6); /* Lookup table. */ - table = zebra_vrf_table_with_table_id(afi, safi, re->vrf_id, re->table); + table = zebra_vrf_get_table_with_table_id(afi, safi, re->vrf_id, + re->table); if (!table) { if (re->ng) nexthop_group_delete(&re->ng); @@ -2809,7 +2801,8 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, assert(!src_p || !src_p->prefixlen || afi == AFI_IP6); /* Lookup table. */ - table = zebra_vrf_table_with_table_id(afi, safi, vrf_id, table_id); + table = zebra_vrf_lookup_table_with_table_id(afi, safi, vrf_id, + table_id); if (!table) return; diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index f425c0e49e..c392303760 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -343,13 +343,12 @@ int zebra_vrf_has_config(struct zebra_vrf *zvrf) * - case VRF backend is default : on default VRF only * - case VRF backend is netns : on all VRFs */ -struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, - vrf_id_t vrf_id, - uint32_t table_id) +struct route_table *zebra_vrf_lookup_table_with_table_id(afi_t afi, safi_t safi, + vrf_id_t vrf_id, + uint32_t table_id) { struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id); struct other_route_table ort, *otable; - struct route_table *table; if (!zvrf) return NULL; @@ -364,9 +363,28 @@ struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, ort.safi = safi; ort.table_id = table_id; otable = otable_find(&zvrf->other_tables, &ort); + if (otable) return otable->table; + return NULL; +} + +struct route_table *zebra_vrf_get_table_with_table_id(afi_t afi, safi_t safi, + vrf_id_t vrf_id, + uint32_t table_id) +{ + struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id); + struct other_route_table *otable; + struct route_table *table; + + table = zebra_vrf_lookup_table_with_table_id(afi, safi, vrf_id, + table_id); + + if (table) + goto done; + + /* Create it as an `other` table */ table = zebra_router_get_table(zvrf, table_id, afi, safi); otable = XCALLOC(MTYPE_OTHER_TABLE, sizeof(*otable)); @@ -376,6 +394,7 @@ struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, otable->table = table; otable_add(&zvrf->other_tables, otable); +done: return table; } diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index 6c80f9bcb4..5448e17073 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -233,9 +233,13 @@ zvrf_other_table_compare_func(const struct other_route_table *a, DECLARE_RBTREE_UNIQ(otable, struct other_route_table, next, zvrf_other_table_compare_func) -struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, - vrf_id_t vrf_id, - uint32_t table_id); +extern struct route_table * +zebra_vrf_lookup_table_with_table_id(afi_t afi, safi_t safi, vrf_id_t vrf_id, + uint32_t table_id); +extern struct route_table *zebra_vrf_get_table_with_table_id(afi_t afi, + safi_t safi, + vrf_id_t vrf_id, + uint32_t table_id); extern void zebra_vrf_update_all(struct zserv *client); extern struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id); diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 9d17454730..12517f3135 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -1708,10 +1708,9 @@ DEFPY (show_route_summary, if ((zvrf = vrf->info) == NULL) continue; - table = zebra_vrf_table_with_table_id(afi, - SAFI_UNICAST, - zvrf->vrf->vrf_id, - table_id); + table = zebra_vrf_lookup_table_with_table_id( + afi, SAFI_UNICAST, zvrf->vrf->vrf_id, table_id); + if (!table) continue; @@ -1726,9 +1725,8 @@ DEFPY (show_route_summary, if (vrf_name) VRF_GET_ID(vrf_id, vrf_name, false); - table = zebra_vrf_table_with_table_id(afi, - SAFI_UNICAST, - vrf_id, table_id); + table = zebra_vrf_lookup_table_with_table_id(afi, SAFI_UNICAST, + vrf_id, table_id); if (!table) return CMD_SUCCESS; diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 2417b505ad..3efb407fae 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -4615,18 +4615,21 @@ static int zl3vni_remote_rmac_add(zebra_l3vni_t *zl3vni, struct ethaddr *rmac, { char buf[ETHER_ADDR_STRLEN]; char buf1[INET6_ADDRSTRLEN]; + char buf2[PREFIX_STRLEN]; zebra_mac_t *zrmac = NULL; zrmac = zl3vni_rmac_lookup(zl3vni, rmac); if (!zrmac) { + /* Create the RMAC entry, or update its vtep, if necessary. */ zrmac = zl3vni_rmac_add(zl3vni, rmac); if (!zrmac) { zlog_debug( - "Failed to add RMAC %s L3VNI %u Remote VTEP %s", + "Failed to add RMAC %s L3VNI %u Remote VTEP %s, prefix %s", prefix_mac2str(rmac, buf, sizeof(buf)), zl3vni->vni, - ipaddr2str(vtep_ip, buf1, sizeof(buf1))); + ipaddr2str(vtep_ip, buf1, sizeof(buf1)), + prefix2str(host_prefix, buf2, sizeof(buf2))); return -1; } memset(&zrmac->fwd_info, 0, sizeof(zrmac->fwd_info)); @@ -4638,6 +4641,21 @@ static int zl3vni_remote_rmac_add(zebra_l3vni_t *zl3vni, struct ethaddr *rmac, /* install rmac in kernel */ zl3vni_rmac_install(zl3vni, zrmac); + } else if (!IPV4_ADDR_SAME(&zrmac->fwd_info.r_vtep_ip, + &vtep_ip->ipaddr_v4)) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug( + "L3VNI %u Remote VTEP change(%s -> %s) for RMAC %s, prefix %s", + zl3vni->vni, + inet_ntoa(zrmac->fwd_info.r_vtep_ip), + ipaddr2str(vtep_ip, buf1, sizeof(buf1)), + prefix_mac2str(rmac, buf, sizeof(buf)), + prefix2str(host_prefix, buf2, sizeof(buf2))); + + zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4; + + /* install rmac in kernel */ + zl3vni_rmac_install(zl3vni, zrmac); } rb_find_or_add_host(&zrmac->host_rb, host_prefix); @@ -4786,24 +4804,39 @@ static int zl3vni_remote_nh_add(zebra_l3vni_t *zl3vni, struct ipaddr *vtep_ip, struct prefix *host_prefix) { char buf[ETHER_ADDR_STRLEN]; - char buf1[INET6_ADDRSTRLEN]; + char buf1[ETHER_ADDR_STRLEN]; + char buf2[INET6_ADDRSTRLEN]; + char buf3[PREFIX_STRLEN]; zebra_neigh_t *nh = NULL; + /* Create the next hop entry, or update its mac, if necessary. */ nh = zl3vni_nh_lookup(zl3vni, vtep_ip); if (!nh) { nh = zl3vni_nh_add(zl3vni, vtep_ip, rmac); if (!nh) { - zlog_debug( - "Failed to add NH as Neigh (IP %s MAC %s L3-VNI %u)", - ipaddr2str(vtep_ip, buf1, sizeof(buf1)), + "Failed to add NH %s as Neigh (RMAC %s L3-VNI %u prefix %s)", + ipaddr2str(vtep_ip, buf1, sizeof(buf2)), prefix_mac2str(rmac, buf, sizeof(buf)), - zl3vni->vni); + zl3vni->vni, + prefix2str(host_prefix, buf2, sizeof(buf2))); return -1; } /* install the nh neigh in kernel */ zl3vni_nh_install(zl3vni, nh); + } else if (memcmp(&nh->emac, rmac, ETH_ALEN) != 0) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("L3VNI %u RMAC change(%s --> %s) for nexthop %s, prefix %s", + zl3vni->vni, + prefix_mac2str(&nh->emac, buf, sizeof(buf)), + prefix_mac2str(rmac, buf1, sizeof(buf1)), + ipaddr2str(vtep_ip, buf2, sizeof(buf2)), + prefix2str(host_prefix, buf3, sizeof(buf3))); + + memcpy(&nh->emac, rmac, ETH_ALEN); + /* install (update) the nh neigh in kernel */ + zl3vni_nh_install(zl3vni, nh); } rb_find_or_add_host(&nh->host_rb, host_prefix); @@ -5775,12 +5808,14 @@ static void process_remote_macip_del(vni_t vni, 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); + 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 ? vlan_if->name : "Unknown"); + if (vlan_if) + neigh_read_specific_ip(ipaddr, vlan_if); } /* When the MAC changes for an IP, it is possible the |
