117 lines
3.6 KiB
Diff
117 lines
3.6 KiB
Diff
|
From 0dcfa1b0211fa50201d51d0f52869a8e2d93ba76 Mon Sep 17 00:00:00 2001
|
||
|
From: Phil Sutter <psutter@redhat.com>
|
||
|
Date: Mon, 7 Dec 2020 18:29:15 +0100
|
||
|
Subject: [PATCH] json: Fix seqnum_to_json() functionality
|
||
|
|
||
|
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1900565
|
||
|
Upstream Status: nftables commit 299ec575faa6b
|
||
|
|
||
|
commit 299ec575faa6b070940b483dc517ecd883b9f1a4
|
||
|
Author: Phil Sutter <phil@nwl.cc>
|
||
|
Date: Wed Dec 2 23:07:11 2020 +0100
|
||
|
|
||
|
json: Fix seqnum_to_json() functionality
|
||
|
|
||
|
Introduction of json_cmd_assoc_hash missed that by the time the hash
|
||
|
table insert happens, the struct cmd object's 'seqnum' field which is
|
||
|
used as key is not initialized yet. This doesn't happen until
|
||
|
nft_netlink() prepares the batch object which records the lowest seqnum.
|
||
|
Therefore push all json_cmd_assoc objects into a temporary list until
|
||
|
the first lookup happens. At this time, all referenced cmd objects have
|
||
|
their seqnum set and the list entries can be moved into the hash table
|
||
|
for fast lookups.
|
||
|
|
||
|
To expose such problems in the future, make json_events_cb() emit an
|
||
|
error message if the passed message has a handle but no assoc entry is
|
||
|
found for its seqnum.
|
||
|
|
||
|
Fixes: 389a0e1edc89a ("json: echo: Speedup seqnum_to_json()")
|
||
|
Cc: Derek Dai <daiderek@gmail.com>
|
||
|
Signed-off-by: Phil Sutter <phil@nwl.cc>
|
||
|
---
|
||
|
src/parser_json.c | 27 +++++++++++++++++++++++----
|
||
|
1 file changed, 23 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/src/parser_json.c b/src/parser_json.c
|
||
|
index 107dc38..785f0e7 100644
|
||
|
--- a/src/parser_json.c
|
||
|
+++ b/src/parser_json.c
|
||
|
@@ -3646,6 +3646,7 @@ static int json_verify_metainfo(struct json_ctx *ctx, json_t *root)
|
||
|
}
|
||
|
|
||
|
struct json_cmd_assoc {
|
||
|
+ struct json_cmd_assoc *next;
|
||
|
struct hlist_node hnode;
|
||
|
const struct cmd *cmd;
|
||
|
json_t *json;
|
||
|
@@ -3653,6 +3654,7 @@ struct json_cmd_assoc {
|
||
|
|
||
|
#define CMD_ASSOC_HSIZE 512
|
||
|
static struct hlist_head json_cmd_assoc_hash[CMD_ASSOC_HSIZE];
|
||
|
+static struct json_cmd_assoc *json_cmd_assoc_list;
|
||
|
|
||
|
static void json_cmd_assoc_free(void)
|
||
|
{
|
||
|
@@ -3660,6 +3662,12 @@ static void json_cmd_assoc_free(void)
|
||
|
struct hlist_node *pos, *n;
|
||
|
int i;
|
||
|
|
||
|
+ while (json_cmd_assoc_list) {
|
||
|
+ cur = json_cmd_assoc_list->next;
|
||
|
+ free(json_cmd_assoc_list);
|
||
|
+ json_cmd_assoc_list = cur;
|
||
|
+ }
|
||
|
+
|
||
|
for (i = 0; i < CMD_ASSOC_HSIZE; i++) {
|
||
|
hlist_for_each_entry_safe(cur, pos, n,
|
||
|
&json_cmd_assoc_hash[i], hnode)
|
||
|
@@ -3670,21 +3678,29 @@ static void json_cmd_assoc_free(void)
|
||
|
static void json_cmd_assoc_add(json_t *json, const struct cmd *cmd)
|
||
|
{
|
||
|
struct json_cmd_assoc *new = xzalloc(sizeof *new);
|
||
|
- int key = cmd->seqnum % CMD_ASSOC_HSIZE;
|
||
|
|
||
|
new->json = json;
|
||
|
new->cmd = cmd;
|
||
|
+ new->next = json_cmd_assoc_list;
|
||
|
|
||
|
- hlist_add_head(&new->hnode, &json_cmd_assoc_hash[key]);
|
||
|
+ json_cmd_assoc_list = new;
|
||
|
}
|
||
|
|
||
|
static json_t *seqnum_to_json(const uint32_t seqnum)
|
||
|
{
|
||
|
- int key = seqnum % CMD_ASSOC_HSIZE;
|
||
|
struct json_cmd_assoc *cur;
|
||
|
struct hlist_node *n;
|
||
|
+ int key;
|
||
|
|
||
|
+ while (json_cmd_assoc_list) {
|
||
|
+ cur = json_cmd_assoc_list;
|
||
|
+ json_cmd_assoc_list = cur->next;
|
||
|
|
||
|
+ key = cur->cmd->seqnum % CMD_ASSOC_HSIZE;
|
||
|
+ hlist_add_head(&cur->hnode, &json_cmd_assoc_hash[key]);
|
||
|
+ }
|
||
|
+
|
||
|
+ key = seqnum % CMD_ASSOC_HSIZE;
|
||
|
hlist_for_each_entry(cur, n, &json_cmd_assoc_hash[key], hnode) {
|
||
|
if (cur->cmd->seqnum == seqnum)
|
||
|
return cur->json;
|
||
|
@@ -3865,8 +3881,11 @@ int json_events_cb(const struct nlmsghdr *nlh, struct netlink_mon_handler *monh)
|
||
|
return MNL_CB_OK;
|
||
|
|
||
|
json = seqnum_to_json(nlh->nlmsg_seq);
|
||
|
- if (!json)
|
||
|
+ if (!json) {
|
||
|
+ json_echo_error(monh, "No JSON command found with seqnum %lu\n",
|
||
|
+ nlh->nlmsg_seq);
|
||
|
return MNL_CB_OK;
|
||
|
+ }
|
||
|
|
||
|
tmp = json_object_get(json, "add");
|
||
|
if (!tmp)
|
||
|
--
|
||
|
2.31.1
|
||
|
|