neightbl_dump_info() calls neightbl_fill_info() in each loop to render the default parms. If there are many devices and neightbl_fill_param_info() failed, neightbl_fill_info() is called again when the dump resumes: # ynl --family rt-neigh --dump getneightbl --output-json | jq '.[] | {name: .name, ifindex: .parms.ifindex}' ... { "name": "ndisc_cache", "ifindex": null } ... { "name": "ndisc_cache", "ifindex": 6 } { "name": "ndisc_cache", "ifindex": null } { "name": "ndisc_cache", "ifindex": 5 } Let's skip neightbl_fill_info() if it is already called in neightbl_dump_info(). Note that we cannot use !neigh_skip instead of !default_skip because default_skip == 1 && neigh_skip == 0 could be true if the first neightbl_fill_param_info() fails. Fixes: c7fb64db001f ("[NETLINK]: Neighbour table configuration and statistics via rtnetlink") Signed-off-by: Kuniyuki Iwashima --- Cc: Thomas Graf --- net/core/neighbour.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index b90957b630ce..15eedaef6578 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2587,9 +2587,10 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) { const struct nlmsghdr *nlh = cb->nlh; struct net *net = sock_net(skb->sk); + int default_skip = cb->args[2]; + int neigh_skip = cb->args[1]; int family, tidx, nidx = 0; int tbl_skip = cb->args[0]; - int neigh_skip = cb->args[1]; struct neigh_table *tbl; if (cb->strict_check) { @@ -2613,12 +2614,13 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) if (tidx < tbl_skip || (family && tbl->family != family)) continue; - if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid, + if (!default_skip && + neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid, nlh->nlmsg_seq, RTM_NEWNEIGHTBL, NLM_F_MULTI) < 0) break; - nidx = 0; + default_skip = 1; p = list_first_entry(&tbl->parms_list, struct neigh_parms, list); list_for_each_entry_continue_rcu(p, &tbl->parms_list, list) { @@ -2642,12 +2644,15 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) } neigh_skip = 0; + nidx = 0; + default_skip = 0; } out: rcu_read_unlock(); cb->args[0] = tidx; cb->args[1] = nidx; + cb->args[2] = default_skip; return skb->len; } -- 2.55.0.1003.g10538fe699-goog