From 815059466cdfb022ff5beec55f7ffee649db7600 Mon Sep 17 00:00:00 2001 From: Stephen Worley Date: Thu, 1 Aug 2019 14:53:06 -0400 Subject: [PATCH] zebra: Move the supports_nh bool to a better place Move the supports_nh bool indicating whether the kernel we are using supports nexthop objects into the netlink kernel interface itself. Since only linux and netlink support nexthop object APIs for now this is fine. Signed-off-by: Stephen Worley --- zebra/if_netlink.c | 10 +--------- zebra/rt_netlink.c | 17 ++++++++++++++++- zebra/zebra_dplane.c | 17 +++++------------ zebra/zebra_nhg.c | 44 ++++++++++++++++++++++++++------------------ zebra/zebra_ns.h | 1 - 5 files changed, 48 insertions(+), 41 deletions(-) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 44249d7dd1..c09007bcb1 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -1482,15 +1482,7 @@ void interface_list(struct zebra_ns *zns) * so we need to get the nexthop info * from the kernel before we can do that */ - - if (netlink_nexthop_read(zns)) { - /* If the nexthop read fails, assume the kernel - * cannot handle nexthop objects. - */ - zlog_debug("Nexthop objects disabled on this kernel"); - zns->supports_nh = false; - } else - zns->supports_nh = true; + netlink_nexthop_read(zns); interface_addr_lookup_netlink(zns); } diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 6e791b1336..840354a8bc 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -74,6 +74,8 @@ static vlanid_t filter_vlan = 0; +static bool supports_nh = false; + struct gw_family_t { uint16_t filler; uint16_t family; @@ -1644,7 +1646,7 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx) RTA_PAYLOAD(rta)); } - if (dplane_ctx_get_nhe_id(ctx)) { + if (supports_nh) { /* Kernel supports nexthop objects */ addattr32(&req.n, sizeof(req), RTA_NH_ID, dplane_ctx_get_nhe_id(ctx)); @@ -1938,6 +1940,10 @@ static int netlink_nexthop(int cmd, struct zebra_dplane_ctx *ctx) char buf[NL_PKT_BUF_SIZE]; } req; + /* Nothing to do if the kernel doesn't support nexthop objects */ + if (!supports_nh) + return 0; + memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg)); @@ -2424,6 +2430,15 @@ int netlink_nexthop_read(struct zebra_ns *zns) return ret; ret = netlink_parse_info(netlink_nexthop_change, &zns->netlink_cmd, &dp_info, 0, 1); + + if (!ret) + /* If we succesfully read in nexthop objects, + * this kernel must support them. + */ + supports_nh = true; + else if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("Nexthop objects not supported on this kernel"); + return ret; } diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index e2c7bd7635..04aca1ac7e 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -1526,7 +1526,7 @@ static int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, dplane_ctx_ns_init(ctx, zns, (op == DPLANE_OP_ROUTE_UPDATE)); #ifdef HAVE_NETLINK - if (re->nhe_id && zns->supports_nh) { + if (re->nhe_id) { struct nhg_hash_entry *nhe = zebra_nhg_resolve(zebra_nhg_lookup_id(re->nhe_id)); @@ -1594,11 +1594,6 @@ static int dplane_ctx_nexthop_init(struct zebra_dplane_ctx *ctx, zns = ((struct zebra_vrf *)vrf_info_lookup(nhe->vrf_id))->zns; - if (!zns->supports_nh) { - ret = EOPNOTSUPP; - goto done; - } - /* * TODO: Might not need to mark this as an update, since * it probably won't require two messages @@ -1896,12 +1891,8 @@ done: if (ret == AOK) result = ZEBRA_DPLANE_REQUEST_QUEUED; else { - if (ret == EOPNOTSUPP) - result = ZEBRA_DPLANE_REQUEST_SUCCESS; - else - atomic_fetch_add_explicit( - &zdplane_info.dg_nexthop_errors, 1, - memory_order_relaxed); + atomic_fetch_add_explicit(&zdplane_info.dg_nexthop_errors, 1, + memory_order_relaxed); if (ctx) dplane_ctx_free(&ctx); } @@ -2078,6 +2069,8 @@ enum zebra_dplane_result dplane_nexthop_add(struct nhg_hash_entry *nhe) /* * Enqueue a nexthop update for the dataplane. + * + * Might not need this func since zebra's nexthop objects should be immutable? */ enum zebra_dplane_result dplane_nexthop_update(struct nhg_hash_entry *nhe) { diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 2027f98f6f..9e54753bf0 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -553,6 +553,29 @@ static enum nhg_ctx_op_e nhg_ctx_get_op(const struct nhg_ctx *ctx) return ctx->op; } +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) +{ + struct nhg_ctx *ctx = NULL; + + ctx = nhg_ctx_new(); + + ctx->id = id; + ctx->vrf_id = vrf_id; + ctx->afi = afi; + ctx->type = type; + ctx->count = count; + + if (count) + /* Copy over the array */ + memcpy(&ctx->u.grp, grp, count * sizeof(struct nh_grp)); + else if (nh) + ctx->u.nh = *nh; + + return ctx; +} + static bool zebra_nhg_contains_dup(struct nhg_hash_entry *nhe) { struct nhg_connected *rb_node_dep = NULL; @@ -717,7 +740,7 @@ static int nhg_ctx_process_del(struct nhg_ctx *ctx) EC_ZEBRA_BAD_NHG_MESSAGE, "Kernel delete message received for nexthop group ID (%u) that we do not have in our ID table", ctx->id); - return 0; + return -1; } zebra_nhg_handle_kernel_state_change(nhe, true); @@ -786,20 +809,7 @@ int zebra_nhg_kernel_find(uint32_t id, struct nexthop *nh, struct nh_grp *grp, */ id_counter = id; - ctx = nhg_ctx_new(); - - ctx->id = id; - ctx->vrf_id = vrf_id; - ctx->afi = afi; - ctx->type = type; - ctx->count = count; - - if (count) - /* Copy over the array */ - memcpy(&ctx->u.grp, grp, count * sizeof(struct nh_grp)); - else - ctx->u.nh = *nh; - + ctx = nhg_ctx_init(id, nh, grp, vrf_id, afi, type, count); nhg_ctx_set_op(ctx, NHG_CTX_OP_NEW); /* Under statup conditions, we need to handle them immediately @@ -822,9 +832,7 @@ int zebra_nhg_kernel_del(uint32_t id) { struct nhg_ctx *ctx = NULL; - ctx = nhg_ctx_new(); - - ctx->id = id; + ctx = nhg_ctx_init(id, NULL, NULL, 0, 0, 0, 0); nhg_ctx_set_op(ctx, NHG_CTX_OP_DEL); diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h index 11aa1b74c9..dc79a83db0 100644 --- a/zebra/zebra_ns.h +++ b/zebra/zebra_ns.h @@ -54,7 +54,6 @@ struct zebra_ns { struct nlsock netlink_cmd; /* command channel */ struct nlsock netlink_dplane; /* dataplane channel */ struct thread *t_netlink; - bool supports_nh; /* Does kernel support nexthop objects? */ #endif struct route_table *if_table;