net/netfilter/nft_bitwise.c

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

File Facts

System
Linux kernel
Corpus path
net/netfilter/nft_bitwise.c
Extension
.c
Size
13288 bytes
Lines
555
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_bitwise {
	u8			sreg;
	u8			sreg2;
	u8			dreg;
	enum nft_bitwise_ops	op:8;
	u8			len;
	struct nft_data		mask;
	struct nft_data		xor;
	struct nft_data		data;
};

static void nft_bitwise_eval_mask_xor(u32 *dst, const u32 *src,
				      const struct nft_bitwise *priv)
{
	unsigned int i;

	for (i = 0; i < DIV_ROUND_UP(priv->len, sizeof(u32)); i++)
		dst[i] = (src[i] & priv->mask.data[i]) ^ priv->xor.data[i];
}

static void nft_bitwise_eval_lshift(u32 *dst, const u32 *src,
				    const struct nft_bitwise *priv)
{
	u32 shift = priv->data.data[0];
	unsigned int i;
	u32 carry = 0;

	for (i = DIV_ROUND_UP(priv->len, sizeof(u32)); i > 0; i--) {
		u32 tmp_src = src[i - 1];

		dst[i - 1] = (tmp_src << shift) | carry;
		carry = tmp_src >> (BITS_PER_TYPE(u32) - shift);
	}
}

static void nft_bitwise_eval_rshift(u32 *dst, const u32 *src,
				    const struct nft_bitwise *priv)
{
	u32 shift = priv->data.data[0];
	unsigned int i;
	u32 carry = 0;

	for (i = 0; i < DIV_ROUND_UP(priv->len, sizeof(u32)); i++) {
		u32 tmp_src = src[i];

		dst[i] = carry | (tmp_src >> shift);
		carry = tmp_src << (BITS_PER_TYPE(u32) - shift);
	}
}

static void nft_bitwise_eval_and(u32 *dst, const u32 *src, const u32 *src2,
				 const struct nft_bitwise *priv)
{
	unsigned int i, n;

	for (i = 0, n = DIV_ROUND_UP(priv->len, sizeof(u32)); i < n; i++)
		dst[i] = src[i] & src2[i];
}

static void nft_bitwise_eval_or(u32 *dst, const u32 *src, const u32 *src2,
				const struct nft_bitwise *priv)
{
	unsigned int i, n;

	for (i = 0, n = DIV_ROUND_UP(priv->len, sizeof(u32)); i < n; i++)
		dst[i] = src[i] | src2[i];
}

static void nft_bitwise_eval_xor(u32 *dst, const u32 *src, const u32 *src2,
				 const struct nft_bitwise *priv)
{
	unsigned int i, n;

	for (i = 0, n = DIV_ROUND_UP(priv->len, sizeof(u32)); i < n; i++)
		dst[i] = src[i] ^ src2[i];
}

void nft_bitwise_eval(const struct nft_expr *expr,
		      struct nft_regs *regs, const struct nft_pktinfo *pkt)
{
	const struct nft_bitwise *priv = nft_expr_priv(expr);
	const u32 *src = &regs->data[priv->sreg], *src2;
	u32 *dst = &regs->data[priv->dreg];

	if (priv->op == NFT_BITWISE_MASK_XOR) {
		nft_bitwise_eval_mask_xor(dst, src, priv);
		return;
	}
	if (priv->op == NFT_BITWISE_LSHIFT) {
		nft_bitwise_eval_lshift(dst, src, priv);

Annotation

Implementation Notes