0001
0002
0003 #include <net/xdp_sock_drv.h>
0004
0005 #include "netlink.h"
0006 #include "common.h"
0007
0008 struct channels_req_info {
0009 struct ethnl_req_info base;
0010 };
0011
0012 struct channels_reply_data {
0013 struct ethnl_reply_data base;
0014 struct ethtool_channels channels;
0015 };
0016
0017 #define CHANNELS_REPDATA(__reply_base) \
0018 container_of(__reply_base, struct channels_reply_data, base)
0019
0020 const struct nla_policy ethnl_channels_get_policy[] = {
0021 [ETHTOOL_A_CHANNELS_HEADER] =
0022 NLA_POLICY_NESTED(ethnl_header_policy),
0023 };
0024
0025 static int channels_prepare_data(const struct ethnl_req_info *req_base,
0026 struct ethnl_reply_data *reply_base,
0027 struct genl_info *info)
0028 {
0029 struct channels_reply_data *data = CHANNELS_REPDATA(reply_base);
0030 struct net_device *dev = reply_base->dev;
0031 int ret;
0032
0033 if (!dev->ethtool_ops->get_channels)
0034 return -EOPNOTSUPP;
0035 ret = ethnl_ops_begin(dev);
0036 if (ret < 0)
0037 return ret;
0038 dev->ethtool_ops->get_channels(dev, &data->channels);
0039 ethnl_ops_complete(dev);
0040
0041 return 0;
0042 }
0043
0044 static int channels_reply_size(const struct ethnl_req_info *req_base,
0045 const struct ethnl_reply_data *reply_base)
0046 {
0047 return nla_total_size(sizeof(u32)) +
0048 nla_total_size(sizeof(u32)) +
0049 nla_total_size(sizeof(u32)) +
0050 nla_total_size(sizeof(u32)) +
0051 nla_total_size(sizeof(u32)) +
0052 nla_total_size(sizeof(u32)) +
0053 nla_total_size(sizeof(u32)) +
0054 nla_total_size(sizeof(u32));
0055 }
0056
0057 static int channels_fill_reply(struct sk_buff *skb,
0058 const struct ethnl_req_info *req_base,
0059 const struct ethnl_reply_data *reply_base)
0060 {
0061 const struct channels_reply_data *data = CHANNELS_REPDATA(reply_base);
0062 const struct ethtool_channels *channels = &data->channels;
0063
0064 if ((channels->max_rx &&
0065 (nla_put_u32(skb, ETHTOOL_A_CHANNELS_RX_MAX,
0066 channels->max_rx) ||
0067 nla_put_u32(skb, ETHTOOL_A_CHANNELS_RX_COUNT,
0068 channels->rx_count))) ||
0069 (channels->max_tx &&
0070 (nla_put_u32(skb, ETHTOOL_A_CHANNELS_TX_MAX,
0071 channels->max_tx) ||
0072 nla_put_u32(skb, ETHTOOL_A_CHANNELS_TX_COUNT,
0073 channels->tx_count))) ||
0074 (channels->max_other &&
0075 (nla_put_u32(skb, ETHTOOL_A_CHANNELS_OTHER_MAX,
0076 channels->max_other) ||
0077 nla_put_u32(skb, ETHTOOL_A_CHANNELS_OTHER_COUNT,
0078 channels->other_count))) ||
0079 (channels->max_combined &&
0080 (nla_put_u32(skb, ETHTOOL_A_CHANNELS_COMBINED_MAX,
0081 channels->max_combined) ||
0082 nla_put_u32(skb, ETHTOOL_A_CHANNELS_COMBINED_COUNT,
0083 channels->combined_count))))
0084 return -EMSGSIZE;
0085
0086 return 0;
0087 }
0088
0089 const struct ethnl_request_ops ethnl_channels_request_ops = {
0090 .request_cmd = ETHTOOL_MSG_CHANNELS_GET,
0091 .reply_cmd = ETHTOOL_MSG_CHANNELS_GET_REPLY,
0092 .hdr_attr = ETHTOOL_A_CHANNELS_HEADER,
0093 .req_info_size = sizeof(struct channels_req_info),
0094 .reply_data_size = sizeof(struct channels_reply_data),
0095
0096 .prepare_data = channels_prepare_data,
0097 .reply_size = channels_reply_size,
0098 .fill_reply = channels_fill_reply,
0099 };
0100
0101
0102
0103 const struct nla_policy ethnl_channels_set_policy[] = {
0104 [ETHTOOL_A_CHANNELS_HEADER] =
0105 NLA_POLICY_NESTED(ethnl_header_policy),
0106 [ETHTOOL_A_CHANNELS_RX_COUNT] = { .type = NLA_U32 },
0107 [ETHTOOL_A_CHANNELS_TX_COUNT] = { .type = NLA_U32 },
0108 [ETHTOOL_A_CHANNELS_OTHER_COUNT] = { .type = NLA_U32 },
0109 [ETHTOOL_A_CHANNELS_COMBINED_COUNT] = { .type = NLA_U32 },
0110 };
0111
0112 int ethnl_set_channels(struct sk_buff *skb, struct genl_info *info)
0113 {
0114 unsigned int from_channel, old_total, i;
0115 bool mod = false, mod_combined = false;
0116 struct ethtool_channels channels = {};
0117 struct ethnl_req_info req_info = {};
0118 struct nlattr **tb = info->attrs;
0119 u32 err_attr, max_rx_in_use = 0;
0120 const struct ethtool_ops *ops;
0121 struct net_device *dev;
0122 int ret;
0123
0124 ret = ethnl_parse_header_dev_get(&req_info,
0125 tb[ETHTOOL_A_CHANNELS_HEADER],
0126 genl_info_net(info), info->extack,
0127 true);
0128 if (ret < 0)
0129 return ret;
0130 dev = req_info.dev;
0131 ops = dev->ethtool_ops;
0132 ret = -EOPNOTSUPP;
0133 if (!ops->get_channels || !ops->set_channels)
0134 goto out_dev;
0135
0136 rtnl_lock();
0137 ret = ethnl_ops_begin(dev);
0138 if (ret < 0)
0139 goto out_rtnl;
0140 ops->get_channels(dev, &channels);
0141 old_total = channels.combined_count +
0142 max(channels.rx_count, channels.tx_count);
0143
0144 ethnl_update_u32(&channels.rx_count, tb[ETHTOOL_A_CHANNELS_RX_COUNT],
0145 &mod);
0146 ethnl_update_u32(&channels.tx_count, tb[ETHTOOL_A_CHANNELS_TX_COUNT],
0147 &mod);
0148 ethnl_update_u32(&channels.other_count,
0149 tb[ETHTOOL_A_CHANNELS_OTHER_COUNT], &mod);
0150 ethnl_update_u32(&channels.combined_count,
0151 tb[ETHTOOL_A_CHANNELS_COMBINED_COUNT], &mod_combined);
0152 mod |= mod_combined;
0153 ret = 0;
0154 if (!mod)
0155 goto out_ops;
0156
0157
0158 if (channels.rx_count > channels.max_rx)
0159 err_attr = ETHTOOL_A_CHANNELS_RX_COUNT;
0160 else if (channels.tx_count > channels.max_tx)
0161 err_attr = ETHTOOL_A_CHANNELS_TX_COUNT;
0162 else if (channels.other_count > channels.max_other)
0163 err_attr = ETHTOOL_A_CHANNELS_OTHER_COUNT;
0164 else if (channels.combined_count > channels.max_combined)
0165 err_attr = ETHTOOL_A_CHANNELS_COMBINED_COUNT;
0166 else
0167 err_attr = 0;
0168 if (err_attr) {
0169 ret = -EINVAL;
0170 NL_SET_ERR_MSG_ATTR(info->extack, tb[err_attr],
0171 "requested channel count exceeds maximum");
0172 goto out_ops;
0173 }
0174
0175
0176 if (!channels.combined_count && !channels.rx_count)
0177 err_attr = ETHTOOL_A_CHANNELS_RX_COUNT;
0178 else if (!channels.combined_count && !channels.tx_count)
0179 err_attr = ETHTOOL_A_CHANNELS_TX_COUNT;
0180 else
0181 err_attr = 0;
0182 if (err_attr) {
0183 if (mod_combined)
0184 err_attr = ETHTOOL_A_CHANNELS_COMBINED_COUNT;
0185 ret = -EINVAL;
0186 NL_SET_ERR_MSG_ATTR(info->extack, tb[err_attr],
0187 "requested channel counts would result in no RX or TX channel being configured");
0188 goto out_ops;
0189 }
0190
0191
0192
0193
0194 if (netif_is_rxfh_configured(dev) &&
0195 !ethtool_get_max_rxfh_channel(dev, &max_rx_in_use) &&
0196 (channels.combined_count + channels.rx_count) <= max_rx_in_use) {
0197 ret = -EINVAL;
0198 GENL_SET_ERR_MSG(info, "requested channel counts are too low for existing indirection table settings");
0199 goto out_ops;
0200 }
0201
0202
0203 from_channel = channels.combined_count +
0204 min(channels.rx_count, channels.tx_count);
0205 for (i = from_channel; i < old_total; i++)
0206 if (xsk_get_pool_from_qid(dev, i)) {
0207 ret = -EINVAL;
0208 GENL_SET_ERR_MSG(info, "requested channel counts are too low for existing zerocopy AF_XDP sockets");
0209 goto out_ops;
0210 }
0211
0212 ret = dev->ethtool_ops->set_channels(dev, &channels);
0213 if (ret < 0)
0214 goto out_ops;
0215 ethtool_notify(dev, ETHTOOL_MSG_CHANNELS_NTF, NULL);
0216
0217 out_ops:
0218 ethnl_ops_complete(dev);
0219 out_rtnl:
0220 rtnl_unlock();
0221 out_dev:
0222 ethnl_parse_header_dev_put(&req_info);
0223 return ret;
0224 }