net/ethtool/tunnels.c

Source file repositories/reference/linux-study-clean/net/ethtool/tunnels.c

File Facts

System
Linux kernel
Corpus path
net/ethtool/tunnels.c
Extension
.c
Size
6847 bytes
Lines
282
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 ethnl_tunnel_info_dump_ctx {
	struct ethnl_req_info	req_info;
	unsigned long		ifindex;
};

int ethnl_tunnel_info_start(struct netlink_callback *cb)
{
	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
	struct ethnl_tunnel_info_dump_ctx *ctx = (void *)cb->ctx;
	struct nlattr **tb = info->info.attrs;
	int ret;

	BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));

	memset(ctx, 0, sizeof(*ctx));

	ret = ethnl_parse_header_dev_get(&ctx->req_info,
					 tb[ETHTOOL_A_TUNNEL_INFO_HEADER],
					 sock_net(cb->skb->sk), cb->extack,
					 false);
	if (ctx->req_info.dev) {
		ethnl_parse_header_dev_put(&ctx->req_info);
		ctx->req_info.dev = NULL;
	}

	return ret;
}

int ethnl_tunnel_info_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
{
	struct ethnl_tunnel_info_dump_ctx *ctx = (void *)cb->ctx;
	struct net *net = sock_net(skb->sk);
	struct net_device *dev;
	int ret = 0;
	void *ehdr;

	rtnl_lock();
	for_each_netdev_dump(net, dev, ctx->ifindex) {
		ehdr = ethnl_dump_put(skb, cb,
				      ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY);
		if (!ehdr) {
			ret = -EMSGSIZE;
			break;
		}

		ret = ethnl_fill_reply_header(skb, dev,
					      ETHTOOL_A_TUNNEL_INFO_HEADER);
		if (ret < 0) {
			genlmsg_cancel(skb, ehdr);
			break;
		}

		ctx->req_info.dev = dev;
		ret = ethnl_tunnel_info_fill_reply(&ctx->req_info, skb);
		ctx->req_info.dev = NULL;
		if (ret < 0) {
			genlmsg_cancel(skb, ehdr);
			if (ret == -EOPNOTSUPP)
				continue;
			break;
		}
		genlmsg_end(skb, ehdr);
	}
	rtnl_unlock();

	if (ret == -EMSGSIZE && skb->len)
		return skb->len;
	return ret;
}

Annotation

Implementation Notes