Unverified Commit 27416dfc authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!14524 The bugfix for LPM trie

Merge Pull Request from: @ci-robot 
 
PR sync from: Tengda Wu <wutengda2@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/53RLNLHNDFQ4USKOEWX5M26K6EN3AS5W/ 
This is a small bugfix for bpf LPM trie.

Hou Tao (2):
  bpf: Handle BPF_EXIST and BPF_NOEXIST for LPM trie
  bpf: Handle in-place update for full LPM trie correctly


-- 
2.34.1
 
https://gitee.com/openeuler/kernel/issues/IBFB6E 
 
Link:https://gitee.com/openeuler/kernel/pulls/14524

 

Reviewed-by: default avatarXu Kuohai <xukuohai@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents 03d43e38 9d9f63c5
Loading
Loading
Loading
Loading
+30 −14
Original line number Diff line number Diff line
@@ -302,6 +302,16 @@ static struct lpm_trie_node *lpm_trie_node_alloc(const struct lpm_trie *trie,
	return node;
}

static int trie_check_add_elem(struct lpm_trie *trie, u64 flags)
{
	if (flags == BPF_EXIST)
		return -ENOENT;
	if (trie->n_entries == trie->map.max_entries)
		return -ENOSPC;
	trie->n_entries++;
	return 0;
}

/* Called from syscall or from eBPF program */
static long trie_update_elem(struct bpf_map *map,
			     void *_key, void *value, u64 flags)
@@ -325,20 +335,12 @@ static long trie_update_elem(struct bpf_map *map,
	spin_lock_irqsave(&trie->lock, irq_flags);

	/* Allocate and fill a new node */

	if (trie->n_entries == trie->map.max_entries) {
		ret = -ENOSPC;
		goto out;
	}

	new_node = lpm_trie_node_alloc(trie, value);
	if (!new_node) {
		ret = -ENOMEM;
		goto out;
	}

	trie->n_entries++;

	new_node->prefixlen = key->prefixlen;
	RCU_INIT_POINTER(new_node->child[0], NULL);
	RCU_INIT_POINTER(new_node->child[1], NULL);
@@ -368,6 +370,10 @@ static long trie_update_elem(struct bpf_map *map,
	 * simply assign the @new_node to that slot and be done.
	 */
	if (!node) {
		ret = trie_check_add_elem(trie, flags);
		if (ret)
			goto out;

		rcu_assign_pointer(*slot, new_node);
		goto out;
	}
@@ -376,18 +382,30 @@ static long trie_update_elem(struct bpf_map *map,
	 * which already has the correct data array set.
	 */
	if (node->prefixlen == matchlen) {
		if (!(node->flags & LPM_TREE_NODE_FLAG_IM)) {
			if (flags == BPF_NOEXIST) {
				ret = -EEXIST;
				goto out;
			}
		} else {
			ret = trie_check_add_elem(trie, flags);
			if (ret)
				goto out;
		}

		new_node->child[0] = node->child[0];
		new_node->child[1] = node->child[1];

		if (!(node->flags & LPM_TREE_NODE_FLAG_IM))
			trie->n_entries--;

		rcu_assign_pointer(*slot, new_node);
		free_node = node;

		goto out;
	}

	ret = trie_check_add_elem(trie, flags);
	if (ret)
		goto out;

	/* If the new node matches the prefix completely, it must be inserted
	 * as an ancestor. Simply insert it between @node and *@slot.
	 */
@@ -400,6 +418,7 @@ static long trie_update_elem(struct bpf_map *map,

	im_node = lpm_trie_node_alloc(trie, NULL);
	if (!im_node) {
		trie->n_entries--;
		ret = -ENOMEM;
		goto out;
	}
@@ -422,9 +441,6 @@ static long trie_update_elem(struct bpf_map *map,

out:
	if (ret) {
		if (new_node)
			trie->n_entries--;

		kfree(new_node);
		kfree(im_node);
	}