net/xfrm/xfrm_interface_core.c

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

File Facts

System
Linux kernel
Corpus path
net/xfrm/xfrm_interface_core.c
Extension
.c
Size
29052 bytes
Lines
1242
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: operation-table or driver-model contract
Status
pattern 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

static const struct net_device_ops xfrmi_netdev_ops;

#define XFRMI_HASH_BITS	8
#define XFRMI_HASH_SIZE	BIT(XFRMI_HASH_BITS)

struct xfrmi_net {
	/* lists for storing interfaces in use */
	struct xfrm_if __rcu *xfrmi[XFRMI_HASH_SIZE];
	struct xfrm_if __rcu *collect_md_xfrmi;
};

static const struct nla_policy xfrm_lwt_policy[LWT_XFRM_MAX + 1] = {
	[LWT_XFRM_IF_ID]	= NLA_POLICY_MIN(NLA_U32, 1),
	[LWT_XFRM_LINK]		= NLA_POLICY_MIN(NLA_U32, 1),
};

static void xfrmi_destroy_state(struct lwtunnel_state *lwt)
{
}

static int xfrmi_build_state(struct net *net, struct nlattr *nla,
			     unsigned int family, const void *cfg,
			     struct lwtunnel_state **ts,
			     struct netlink_ext_ack *extack)
{
	struct nlattr *tb[LWT_XFRM_MAX + 1];
	struct lwtunnel_state *new_state;
	struct xfrm_md_info *info;
	int ret;

	ret = nla_parse_nested(tb, LWT_XFRM_MAX, nla, xfrm_lwt_policy, extack);
	if (ret < 0)
		return ret;

	if (!tb[LWT_XFRM_IF_ID]) {
		NL_SET_ERR_MSG(extack, "if_id must be set");
		return -EINVAL;
	}

	new_state = lwtunnel_state_alloc(sizeof(*info));
	if (!new_state) {
		NL_SET_ERR_MSG(extack, "failed to create encap info");
		return -ENOMEM;
	}

	new_state->type = LWTUNNEL_ENCAP_XFRM;

	info = lwt_xfrm_info(new_state);

	info->if_id = nla_get_u32(tb[LWT_XFRM_IF_ID]);

	if (tb[LWT_XFRM_LINK])
		info->link = nla_get_u32(tb[LWT_XFRM_LINK]);

	*ts = new_state;
	return 0;
}

static int xfrmi_fill_encap_info(struct sk_buff *skb,
				 struct lwtunnel_state *lwt)
{
	struct xfrm_md_info *info = lwt_xfrm_info(lwt);

	if (nla_put_u32(skb, LWT_XFRM_IF_ID, info->if_id) ||
	    (info->link && nla_put_u32(skb, LWT_XFRM_LINK, info->link)))
		return -EMSGSIZE;

	return 0;
}

static int xfrmi_encap_nlsize(struct lwtunnel_state *lwtstate)
{
	return nla_total_size(sizeof(u32)) + /* LWT_XFRM_IF_ID */
		nla_total_size(sizeof(u32)); /* LWT_XFRM_LINK */
}

static int xfrmi_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b)
{
	struct xfrm_md_info *a_info = lwt_xfrm_info(a);
	struct xfrm_md_info *b_info = lwt_xfrm_info(b);

	return memcmp(a_info, b_info, sizeof(*a_info));
}

static const struct lwtunnel_encap_ops xfrmi_encap_ops = {
	.build_state	= xfrmi_build_state,
	.destroy_state	= xfrmi_destroy_state,
	.fill_encap	= xfrmi_fill_encap_info,
	.get_encap_size = xfrmi_encap_nlsize,
	.cmp_encap	= xfrmi_encap_cmp,

Annotation

Implementation Notes