net/ethtool/cabletest.c

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

File Facts

System
Linux kernel
Corpus path
net/ethtool/cabletest.c
Extension
.c
Size
10514 bytes
Lines
451
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

if (cfg->pair > ETHTOOL_A_CABLE_PAIR_D) {
			NL_SET_ERR_MSG_ATTR(
				info->extack,
				tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_PAIR],
				"invalid pair parameter");
			return -EINVAL;
		}
	}

	if (cfg->first > MAX_CABLE_LENGTH_CM) {
		NL_SET_ERR_MSG_ATTR(info->extack,
				    tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_FIRST],
				    "invalid first parameter");
		return -EINVAL;
	}

	if (cfg->last > MAX_CABLE_LENGTH_CM) {
		NL_SET_ERR_MSG_ATTR(info->extack,
				    tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_LAST],
				    "invalid last parameter");
		return -EINVAL;
	}

	if (cfg->first > cfg->last) {
		NL_SET_ERR_MSG(info->extack, "invalid first/last parameter");
		return -EINVAL;
	}

	if (!cfg->step) {
		NL_SET_ERR_MSG_ATTR(info->extack,
				    tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP],
				    "invalid step parameter");
		return -EINVAL;
	}

	if (cfg->step > (cfg->last - cfg->first)) {
		NL_SET_ERR_MSG_ATTR(info->extack,
				    tb[ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP],
				    "step parameter too big");
		return -EINVAL;
	}

	return 0;
}

int ethnl_act_cable_test_tdr(struct sk_buff *skb, struct genl_info *info)
{
	struct ethnl_req_info req_info = {};
	const struct ethtool_phy_ops *ops;
	struct nlattr **tb = info->attrs;
	struct phy_device *phydev;
	struct phy_tdr_config cfg;
	struct net_device *dev;
	int ret;

	ret = ethnl_parse_header_dev_get(&req_info,
					 tb[ETHTOOL_A_CABLE_TEST_TDR_HEADER],
					 genl_info_net(info), info->extack,
					 true);
	if (ret < 0)
		return ret;

	dev = req_info.dev;

	ret = ethnl_act_cable_test_tdr_cfg(tb[ETHTOOL_A_CABLE_TEST_TDR_CFG],
					   info, &cfg);
	if (ret)
		goto out_dev_put;

	netdev_lock_ops_compat(dev);
	phydev = ethnl_req_get_phydev(&req_info, tb,
				      ETHTOOL_A_CABLE_TEST_TDR_HEADER,
				      info->extack);
	if (IS_ERR_OR_NULL(phydev)) {
		ret = -EOPNOTSUPP;
		goto out_unlock;
	}

	ops = ethtool_phy_ops;
	if (!ops || !ops->start_cable_test_tdr) {
		ret = -EOPNOTSUPP;
		goto out_unlock;
	}

	ret = ethnl_ops_begin(dev);
	if (ret < 0)
		goto out_unlock;

	ret = ops->start_cable_test_tdr(phydev, info->extack, &cfg);

Annotation

Implementation Notes