net/ethtool/features.c

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

File Facts

System
Linux kernel
Corpus path
net/ethtool/features.c
Extension
.c
Size
9182 bytes
Lines
298
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 features_req_info {
	struct ethnl_req_info	base;
};

struct features_reply_data {
	struct ethnl_reply_data	base;
	u32			hw[ETHTOOL_DEV_FEATURE_WORDS];
	u32			wanted[ETHTOOL_DEV_FEATURE_WORDS];
	u32			active[ETHTOOL_DEV_FEATURE_WORDS];
	u32			nochange[ETHTOOL_DEV_FEATURE_WORDS];
	u32			all[ETHTOOL_DEV_FEATURE_WORDS];
};

#define FEATURES_REPDATA(__reply_base) \
	container_of(__reply_base, struct features_reply_data, base)

const struct nla_policy ethnl_features_get_policy[] = {
	[ETHTOOL_A_FEATURES_HEADER]	=
		NLA_POLICY_NESTED(ethnl_header_policy),
};

static void ethnl_features_to_bitmap32(u32 *dest, netdev_features_t src)
{
	unsigned int i;

	for (i = 0; i < ETHTOOL_DEV_FEATURE_WORDS; i++)
		dest[i] = src >> (32 * i);
}

static int features_prepare_data(const struct ethnl_req_info *req_base,
				 struct ethnl_reply_data *reply_base,
				 const struct genl_info *info)
{
	struct features_reply_data *data = FEATURES_REPDATA(reply_base);
	struct net_device *dev = reply_base->dev;
	netdev_features_t all_features;

	ethnl_features_to_bitmap32(data->hw, dev->hw_features);
	ethnl_features_to_bitmap32(data->wanted, dev->wanted_features);
	ethnl_features_to_bitmap32(data->active, dev->features);
	ethnl_features_to_bitmap32(data->nochange, NETIF_F_NEVER_CHANGE);
	all_features = GENMASK_ULL(NETDEV_FEATURE_COUNT - 1, 0);
	ethnl_features_to_bitmap32(data->all, all_features);

	return 0;
}

static int features_reply_size(const struct ethnl_req_info *req_base,
			       const struct ethnl_reply_data *reply_base)
{
	const struct features_reply_data *data = FEATURES_REPDATA(reply_base);
	bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
	unsigned int len = 0;
	int ret;

	ret = ethnl_bitset32_size(data->hw, data->all, NETDEV_FEATURE_COUNT,
				  netdev_features_strings, compact);
	if (ret < 0)
		return ret;
	len += ret;
	ret = ethnl_bitset32_size(data->wanted, NULL, NETDEV_FEATURE_COUNT,
				  netdev_features_strings, compact);
	if (ret < 0)
		return ret;
	len += ret;
	ret = ethnl_bitset32_size(data->active, NULL, NETDEV_FEATURE_COUNT,
				  netdev_features_strings, compact);
	if (ret < 0)
		return ret;
	len += ret;
	ret = ethnl_bitset32_size(data->nochange, NULL, NETDEV_FEATURE_COUNT,
				  netdev_features_strings, compact);
	if (ret < 0)
		return ret;
	len += ret;

	return len;
}

static int features_fill_reply(struct sk_buff *skb,
			       const struct ethnl_req_info *req_base,
			       const struct ethnl_reply_data *reply_base)
{
	const struct features_reply_data *data = FEATURES_REPDATA(reply_base);
	bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
	int ret;

	ret = ethnl_put_bitset32(skb, ETHTOOL_A_FEATURES_HW, data->hw,
				 data->all, NETDEV_FEATURE_COUNT,
				 netdev_features_strings, compact);

Annotation

Implementation Notes