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;