1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <net/xdp_sock.h> 4 5 #include "netlink.h" 6 #include "common.h" 7 8 struct channels_req_info { 9 struct ethnl_req_info base; 10 }; 11 12 struct channels_reply_data { 13 struct ethnl_reply_data base; 14 struct ethtool_channels channels; 15 }; 16 17 #define CHANNELS_REPDATA(__reply_base) \ 18 container_of(__reply_base, struct channels_reply_data, base) 19 20 static const struct nla_policy 21 channels_get_policy[ETHTOOL_A_CHANNELS_MAX + 1] = { 22 [ETHTOOL_A_CHANNELS_UNSPEC] = { .type = NLA_REJECT }, 23 [ETHTOOL_A_CHANNELS_HEADER] = { .type = NLA_NESTED }, 24 [ETHTOOL_A_CHANNELS_RX_MAX] = { .type = NLA_REJECT }, 25 [ETHTOOL_A_CHANNELS_TX_MAX] = { .type = NLA_REJECT }, 26 [ETHTOOL_A_CHANNELS_OTHER_MAX] = { .type = NLA_REJECT }, 27 [ETHTOOL_A_CHANNELS_COMBINED_MAX] = { .type = NLA_REJECT }, 28 [ETHTOOL_A_CHANNELS_RX_COUNT] = { .type = NLA_REJECT }, 29 [ETHTOOL_A_CHANNELS_TX_COUNT] = { .type = NLA_REJECT }, 30 [ETHTOOL_A_CHANNELS_OTHER_COUNT] = { .type = NLA_REJECT }, 31 [ETHTOOL_A_CHANNELS_COMBINED_COUNT] = { .type = NLA_REJECT }, 32 }; 33 34 static int channels_prepare_data(const struct ethnl_req_info *req_base, 35 struct ethnl_reply_data *reply_base, 36 struct genl_info *info) 37 { 38 struct channels_reply_data *data = CHANNELS_REPDATA(reply_base); 39 struct net_device *dev = reply_base->dev; 40 int ret; 41 42 if (!dev->ethtool_ops->get_channels) 43 return -EOPNOTSUPP; 44 ret = ethnl_ops_begin(dev); 45 if (ret < 0) 46 return ret; 47 dev->ethtool_ops->get_channels(dev, &data->channels); 48 ethnl_ops_complete(dev); 49 50 return 0; 51 } 52 53 static int channels_reply_size(const struct ethnl_req_info *req_base, 54 const struct ethnl_reply_data *reply_base) 55 { 56 return nla_total_size(sizeof(u32)) + /* _CHANNELS_RX_MAX */ 57 nla_total_size(sizeof(u32)) + /* _CHANNELS_TX_MAX */ 58 nla_total_size(sizeof(u32)) + /* _CHANNELS_OTHER_MAX */ 59 nla_total_size(sizeof(u32)) + /* _CHANNELS_COMBINED_MAX */ 60 nla_total_size(sizeof(u32)) + /* _CHANNELS_RX_COUNT */ 61 nla_total_size(sizeof(u32)) + /* _CHANNELS_TX_COUNT */ 62 nla_total_size(sizeof(u32)) + /* _CHANNELS_OTHER_COUNT */ 63 nla_total_size(sizeof(u32)); /* _CHANNELS_COMBINED_COUNT */ 64 } 65 66 static int channels_fill_reply(struct sk_buff *skb, 67 const struct ethnl_req_info *req_base, 68 const struct ethnl_reply_data *reply_base) 69 { 70 const struct channels_reply_data *data = CHANNELS_REPDATA(reply_base); 71 const struct ethtool_channels *channels = &data->channels; 72 73 if ((channels->max_rx && 74 (nla_put_u32(skb, ETHTOOL_A_CHANNELS_RX_MAX, 75 channels->max_rx) || 76 nla_put_u32(skb, ETHTOOL_A_CHANNELS_RX_COUNT, 77 channels->rx_count))) || 78 (channels->max_tx && 79 (nla_put_u32(skb, ETHTOOL_A_CHANNELS_TX_MAX, 80 channels->max_tx) || 81 nla_put_u32(skb, ETHTOOL_A_CHANNELS_TX_COUNT, 82 channels->tx_count))) || 83 (channels->max_other && 84 (nla_put_u32(skb, ETHTOOL_A_CHANNELS_OTHER_MAX, 85 channels->max_other) || 86 nla_put_u32(skb, ETHTOOL_A_CHANNELS_OTHER_COUNT, 87 channels->other_count))) || 88 (channels->max_combined && 89 (nla_put_u32(skb, ETHTOOL_A_CHANNELS_COMBINED_MAX, 90 channels->max_combined) || 91 nla_put_u32(skb, ETHTOOL_A_CHANNELS_COMBINED_COUNT, 92 channels->combined_count)))) 93 return -EMSGSIZE; 94 95 return 0; 96 } 97 98 const struct ethnl_request_ops ethnl_channels_request_ops = { 99 .request_cmd = ETHTOOL_MSG_CHANNELS_GET, 100 .reply_cmd = ETHTOOL_MSG_CHANNELS_GET_REPLY, 101 .hdr_attr = ETHTOOL_A_CHANNELS_HEADER, 102 .max_attr = ETHTOOL_A_CHANNELS_MAX, 103 .req_info_size = sizeof(struct channels_req_info), 104 .reply_data_size = sizeof(struct channels_reply_data), 105 .request_policy = channels_get_policy, 106 107 .prepare_data = channels_prepare_data, 108 .reply_size = channels_reply_size, 109 .fill_reply = channels_fill_reply, 110 }; 111 112 /* CHANNELS_SET */ 113 114 static const struct nla_policy 115 channels_set_policy[ETHTOOL_A_CHANNELS_MAX + 1] = { 116 [ETHTOOL_A_CHANNELS_UNSPEC] = { .type = NLA_REJECT }, 117 [ETHTOOL_A_CHANNELS_HEADER] = { .type = NLA_NESTED }, 118 [ETHTOOL_A_CHANNELS_RX_MAX] = { .type = NLA_REJECT }, 119 [ETHTOOL_A_CHANNELS_TX_MAX] = { .type = NLA_REJECT }, 120 [ETHTOOL_A_CHANNELS_OTHER_MAX] = { .type = NLA_REJECT }, 121 [ETHTOOL_A_CHANNELS_COMBINED_MAX] = { .type = NLA_REJECT }, 122 [ETHTOOL_A_CHANNELS_RX_COUNT] = { .type = NLA_U32 }, 123 [ETHTOOL_A_CHANNELS_TX_COUNT] = { .type = NLA_U32 }, 124 [ETHTOOL_A_CHANNELS_OTHER_COUNT] = { .type = NLA_U32 }, 125 [ETHTOOL_A_CHANNELS_COMBINED_COUNT] = { .type = NLA_U32 }, 126 }; 127 128 int ethnl_set_channels(struct sk_buff *skb, struct genl_info *info) 129 { 130 struct nlattr *tb[ETHTOOL_A_CHANNELS_MAX + 1]; 131 unsigned int from_channel, old_total, i; 132 struct ethtool_channels channels = {}; 133 struct ethnl_req_info req_info = {}; 134 const struct nlattr *err_attr; 135 const struct ethtool_ops *ops; 136 struct net_device *dev; 137 u32 max_rx_in_use = 0; 138 bool mod = false; 139 int ret; 140 141 ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, 142 ETHTOOL_A_CHANNELS_MAX, channels_set_policy, 143 info->extack); 144 if (ret < 0) 145 return ret; 146 ret = ethnl_parse_header_dev_get(&req_info, 147 tb[ETHTOOL_A_CHANNELS_HEADER], 148 genl_info_net(info), info->extack, 149 true); 150 if (ret < 0) 151 return ret; 152 dev = req_info.dev; 153 ops = dev->ethtool_ops; 154 ret = -EOPNOTSUPP; 155 if (!ops->get_channels || !ops->set_channels) 156 goto out_dev; 157 158 rtnl_lock(); 159 ret = ethnl_ops_begin(dev); 160 if (ret < 0) 161 goto out_rtnl; 162 ops->get_channels(dev, &channels); 163 old_total = channels.combined_count + 164 max(channels.rx_count, channels.tx_count); 165 166 ethnl_update_u32(&channels.rx_count, tb[ETHTOOL_A_CHANNELS_RX_COUNT], 167 &mod); 168 ethnl_update_u32(&channels.tx_count, tb[ETHTOOL_A_CHANNELS_TX_COUNT], 169 &mod); 170 ethnl_update_u32(&channels.other_count, 171 tb[ETHTOOL_A_CHANNELS_OTHER_COUNT], &mod); 172 ethnl_update_u32(&channels.combined_count, 173 tb[ETHTOOL_A_CHANNELS_COMBINED_COUNT], &mod); 174 ret = 0; 175 if (!mod) 176 goto out_ops; 177 178 /* ensure new channel counts are within limits */ 179 if (channels.rx_count > channels.max_rx) 180 err_attr = tb[ETHTOOL_A_CHANNELS_RX_COUNT]; 181 else if (channels.tx_count > channels.max_tx) 182 err_attr = tb[ETHTOOL_A_CHANNELS_TX_COUNT]; 183 else if (channels.other_count > channels.max_other) 184 err_attr = tb[ETHTOOL_A_CHANNELS_OTHER_COUNT]; 185 else if (channels.combined_count > channels.max_combined) 186 err_attr = tb[ETHTOOL_A_CHANNELS_COMBINED_COUNT]; 187 else 188 err_attr = NULL; 189 if (err_attr) { 190 ret = -EINVAL; 191 NL_SET_ERR_MSG_ATTR(info->extack, err_attr, 192 "requested channel count exceeds maximum"); 193 goto out_ops; 194 } 195 196 /* ensure the new Rx count fits within the configured Rx flow 197 * indirection table settings 198 */ 199 if (netif_is_rxfh_configured(dev) && 200 !ethtool_get_max_rxfh_channel(dev, &max_rx_in_use) && 201 (channels.combined_count + channels.rx_count) <= max_rx_in_use) { 202 GENL_SET_ERR_MSG(info, "requested channel counts are too low for existing indirection table settings"); 203 return -EINVAL; 204 } 205 206 /* Disabling channels, query zero-copy AF_XDP sockets */ 207 from_channel = channels.combined_count + 208 min(channels.rx_count, channels.tx_count); 209 for (i = from_channel; i < old_total; i++) 210 if (xdp_get_umem_from_qid(dev, i)) { 211 GENL_SET_ERR_MSG(info, "requested channel counts are too low for existing zerocopy AF_XDP sockets"); 212 return -EINVAL; 213 } 214 215 ret = dev->ethtool_ops->set_channels(dev, &channels); 216 if (ret < 0) 217 goto out_ops; 218 ethtool_notify(dev, ETHTOOL_MSG_CHANNELS_NTF, NULL); 219 220 out_ops: 221 ethnl_ops_complete(dev); 222 out_rtnl: 223 rtnl_unlock(); 224 out_dev: 225 dev_put(dev); 226 return ret; 227 } 228