net/netfilter/nft_counter.c

Source file repositories/reference/linux-study-clean/net/netfilter/nft_counter.c

File Facts

System
Linux kernel
Corpus path
net/netfilter/nft_counter.c
Extension
.c
Size
8627 bytes
Lines
328
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

struct nft_counter {
	u64_stats_t	bytes;
	u64_stats_t	packets;
};

struct nft_counter_tot {
	s64		bytes;
	s64		packets;
};

struct nft_counter_percpu_priv {
	struct nft_counter __percpu *counter;
};

static DEFINE_PER_CPU(struct u64_stats_sync, nft_counter_sync);

/* control plane only: sync fetch+reset */
static DEFINE_SPINLOCK(nft_counter_lock);

static inline void nft_counter_do_eval(struct nft_counter_percpu_priv *priv,
				       struct nft_regs *regs,
				       const struct nft_pktinfo *pkt)
{
	struct u64_stats_sync *nft_sync;
	struct nft_counter *this_cpu;

	local_bh_disable();
	this_cpu = this_cpu_ptr(priv->counter);
	nft_sync = this_cpu_ptr(&nft_counter_sync);

	u64_stats_update_begin(nft_sync);
	u64_stats_add(&this_cpu->bytes, pkt->skb->len);
	u64_stats_inc(&this_cpu->packets);
	u64_stats_update_end(nft_sync);

	local_bh_enable();
}

static inline void nft_counter_obj_eval(struct nft_object *obj,
					struct nft_regs *regs,
					const struct nft_pktinfo *pkt)
{
	struct nft_counter_percpu_priv *priv = nft_obj_data(obj);

	nft_counter_do_eval(priv, regs, pkt);
}

static int nft_counter_do_init(const struct nlattr * const tb[],
			       struct nft_counter_percpu_priv *priv)
{
	struct nft_counter __percpu *cpu_stats;
	struct nft_counter *this_cpu;

	cpu_stats = alloc_percpu_gfp(struct nft_counter, GFP_KERNEL_ACCOUNT);
	if (cpu_stats == NULL)
		return -ENOMEM;

	this_cpu = raw_cpu_ptr(cpu_stats);
	if (tb[NFTA_COUNTER_PACKETS]) {
		u64_stats_set(&this_cpu->packets,
			      be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS])));
	}
	if (tb[NFTA_COUNTER_BYTES]) {
		u64_stats_set(&this_cpu->bytes,
			      be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES])));
	}

	priv->counter = cpu_stats;
	return 0;
}

static int nft_counter_obj_init(const struct nft_ctx *ctx,
				const struct nlattr * const tb[],
				struct nft_object *obj)
{
	struct nft_counter_percpu_priv *priv = nft_obj_data(obj);

	return nft_counter_do_init(tb, priv);
}

static void nft_counter_do_destroy(struct nft_counter_percpu_priv *priv)
{
	free_percpu(priv->counter);
}

static void nft_counter_obj_destroy(const struct nft_ctx *ctx,
				    struct nft_object *obj)
{
	struct nft_counter_percpu_priv *priv = nft_obj_data(obj);

Annotation

Implementation Notes