net/xfrm/xfrm_ipcomp.c

Source file repositories/reference/linux-study-clean/net/xfrm/xfrm_ipcomp.c

File Facts

System
Linux kernel
Corpus path
net/xfrm/xfrm_ipcomp.c
Extension
.c
Size
7815 bytes
Lines
369
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration 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 ipcomp_skb_cb {
	struct xfrm_skb_cb xfrm;
	struct acomp_req *req;
};

struct ipcomp_data {
	u16 threshold;
	struct crypto_acomp *tfm;
};

struct ipcomp_req_extra {
	struct xfrm_state *x;
	struct scatterlist sg[];
};

static inline struct ipcomp_skb_cb *ipcomp_cb(struct sk_buff *skb)
{
	struct ipcomp_skb_cb *cb = (void *)skb->cb;

	BUILD_BUG_ON(sizeof(*cb) > sizeof(skb->cb));
	return cb;
}

static int ipcomp_post_acomp(struct sk_buff *skb, int err, int hlen)
{
	struct acomp_req *req = ipcomp_cb(skb)->req;
	struct ipcomp_req_extra *extra;
	struct scatterlist *dsg;
	int len, dlen;

	if (unlikely(!req))
		return err;

	extra = acomp_request_extra(req);
	dsg = extra->sg;

	if (unlikely(err))
		goto out_free_req;

	dlen = req->dlen;

	pskb_trim_unique(skb, 0);
	__skb_put(skb, hlen);

	/* Only update truesize on input. */
	if (!hlen)
		skb->truesize += dlen;
	skb->data_len = dlen;
	skb->len += dlen;

	do {
		skb_frag_t *frag;
		struct page *page;

		frag = skb_shinfo(skb)->frags + skb_shinfo(skb)->nr_frags;
		page = sg_page(dsg);
		dsg = sg_next(dsg);

		len = PAGE_SIZE;
		if (dlen < len)
			len = dlen;

		skb_frag_fill_page_desc(frag, page, 0, len);

		skb_shinfo(skb)->nr_frags++;
	} while ((dlen -= len));

out_free_req:
	for (; dsg && sg_page(dsg); dsg = sg_next(dsg))
		__free_page(sg_page(dsg));

	acomp_request_free(req);
	return err;
}

static int ipcomp_input_done2(struct sk_buff *skb, int err)
{
	struct ip_comp_hdr *ipch = ip_comp_hdr(skb);
	const int plen = skb->len;

	skb->transport_header = skb->network_header + sizeof(*ipch);

	return ipcomp_post_acomp(skb, err, 0) ?:
	       skb->len < (plen + sizeof(ip_comp_hdr)) ? -EINVAL :
	       ipch->nexthdr;
}

static void ipcomp_input_done(void *data, int err)
{
	struct sk_buff *skb = data;

Annotation

Implementation Notes