1 // SPDX-License-Identifier: GPL-2.0-only
3 #include <net/xdp_sock_drv.h>
8 struct channels_req_info
{
9 struct ethnl_req_info base
;
12 struct channels_reply_data
{
13 struct ethnl_reply_data base
;
14 struct ethtool_channels channels
;
17 #define CHANNELS_REPDATA(__reply_base) \
18 container_of(__reply_base, struct channels_reply_data, base)
20 const struct nla_policy ethnl_channels_get_policy
[] = {
21 [ETHTOOL_A_CHANNELS_HEADER
] =
22 NLA_POLICY_NESTED(ethnl_header_policy
),
25 static int channels_prepare_data(const struct ethnl_req_info
*req_base
,
26 struct ethnl_reply_data
*reply_base
,
27 struct genl_info
*info
)
29 struct channels_reply_data
*data
= CHANNELS_REPDATA(reply_base
);
30 struct net_device
*dev
= reply_base
->dev
;
33 if (!dev
->ethtool_ops
->get_channels
)
35 ret
= ethnl_ops_begin(dev
);
38 dev
->ethtool_ops
->get_channels(dev
, &data
->channels
);
39 ethnl_ops_complete(dev
);
44 static int channels_reply_size(const struct ethnl_req_info
*req_base
,
45 const struct ethnl_reply_data
*reply_base
)
47 return nla_total_size(sizeof(u32
)) + /* _CHANNELS_RX_MAX */
48 nla_total_size(sizeof(u32
)) + /* _CHANNELS_TX_MAX */
49 nla_total_size(sizeof(u32
)) + /* _CHANNELS_OTHER_MAX */
50 nla_total_size(sizeof(u32
)) + /* _CHANNELS_COMBINED_MAX */
51 nla_total_size(sizeof(u32
)) + /* _CHANNELS_RX_COUNT */
52 nla_total_size(sizeof(u32
)) + /* _CHANNELS_TX_COUNT */
53 nla_total_size(sizeof(u32
)) + /* _CHANNELS_OTHER_COUNT */
54 nla_total_size(sizeof(u32
)); /* _CHANNELS_COMBINED_COUNT */
57 static int channels_fill_reply(struct sk_buff
*skb
,
58 const struct ethnl_req_info
*req_base
,
59 const struct ethnl_reply_data
*reply_base
)
61 const struct channels_reply_data
*data
= CHANNELS_REPDATA(reply_base
);
62 const struct ethtool_channels
*channels
= &data
->channels
;
64 if ((channels
->max_rx
&&
65 (nla_put_u32(skb
, ETHTOOL_A_CHANNELS_RX_MAX
,
67 nla_put_u32(skb
, ETHTOOL_A_CHANNELS_RX_COUNT
,
68 channels
->rx_count
))) ||
70 (nla_put_u32(skb
, ETHTOOL_A_CHANNELS_TX_MAX
,
72 nla_put_u32(skb
, ETHTOOL_A_CHANNELS_TX_COUNT
,
73 channels
->tx_count
))) ||
74 (channels
->max_other
&&
75 (nla_put_u32(skb
, ETHTOOL_A_CHANNELS_OTHER_MAX
,
76 channels
->max_other
) ||
77 nla_put_u32(skb
, ETHTOOL_A_CHANNELS_OTHER_COUNT
,
78 channels
->other_count
))) ||
79 (channels
->max_combined
&&
80 (nla_put_u32(skb
, ETHTOOL_A_CHANNELS_COMBINED_MAX
,
81 channels
->max_combined
) ||
82 nla_put_u32(skb
, ETHTOOL_A_CHANNELS_COMBINED_COUNT
,
83 channels
->combined_count
))))
89 const struct ethnl_request_ops ethnl_channels_request_ops
= {
90 .request_cmd
= ETHTOOL_MSG_CHANNELS_GET
,
91 .reply_cmd
= ETHTOOL_MSG_CHANNELS_GET_REPLY
,
92 .hdr_attr
= ETHTOOL_A_CHANNELS_HEADER
,
93 .req_info_size
= sizeof(struct channels_req_info
),
94 .reply_data_size
= sizeof(struct channels_reply_data
),
96 .prepare_data
= channels_prepare_data
,
97 .reply_size
= channels_reply_size
,
98 .fill_reply
= channels_fill_reply
,
103 const struct nla_policy ethnl_channels_set_policy
[] = {
104 [ETHTOOL_A_CHANNELS_HEADER
] =
105 NLA_POLICY_NESTED(ethnl_header_policy
),
106 [ETHTOOL_A_CHANNELS_RX_COUNT
] = { .type
= NLA_U32
},
107 [ETHTOOL_A_CHANNELS_TX_COUNT
] = { .type
= NLA_U32
},
108 [ETHTOOL_A_CHANNELS_OTHER_COUNT
] = { .type
= NLA_U32
},
109 [ETHTOOL_A_CHANNELS_COMBINED_COUNT
] = { .type
= NLA_U32
},
112 int ethnl_set_channels(struct sk_buff
*skb
, struct genl_info
*info
)
114 unsigned int from_channel
, old_total
, i
;
115 bool mod
= false, mod_combined
= false;
116 struct ethtool_channels channels
= {};
117 struct ethnl_req_info req_info
= {};
118 struct nlattr
**tb
= info
->attrs
;
119 const struct nlattr
*err_attr
;
120 const struct ethtool_ops
*ops
;
121 struct net_device
*dev
;
122 u32 max_rx_in_use
= 0;
125 ret
= ethnl_parse_header_dev_get(&req_info
,
126 tb
[ETHTOOL_A_CHANNELS_HEADER
],
127 genl_info_net(info
), info
->extack
,
132 ops
= dev
->ethtool_ops
;
134 if (!ops
->get_channels
|| !ops
->set_channels
)
138 ret
= ethnl_ops_begin(dev
);
141 ops
->get_channels(dev
, &channels
);
142 old_total
= channels
.combined_count
+
143 max(channels
.rx_count
, channels
.tx_count
);
145 ethnl_update_u32(&channels
.rx_count
, tb
[ETHTOOL_A_CHANNELS_RX_COUNT
],
147 ethnl_update_u32(&channels
.tx_count
, tb
[ETHTOOL_A_CHANNELS_TX_COUNT
],
149 ethnl_update_u32(&channels
.other_count
,
150 tb
[ETHTOOL_A_CHANNELS_OTHER_COUNT
], &mod
);
151 ethnl_update_u32(&channels
.combined_count
,
152 tb
[ETHTOOL_A_CHANNELS_COMBINED_COUNT
], &mod_combined
);
158 /* ensure new channel counts are within limits */
159 if (channels
.rx_count
> channels
.max_rx
)
160 err_attr
= tb
[ETHTOOL_A_CHANNELS_RX_COUNT
];
161 else if (channels
.tx_count
> channels
.max_tx
)
162 err_attr
= tb
[ETHTOOL_A_CHANNELS_TX_COUNT
];
163 else if (channels
.other_count
> channels
.max_other
)
164 err_attr
= tb
[ETHTOOL_A_CHANNELS_OTHER_COUNT
];
165 else if (channels
.combined_count
> channels
.max_combined
)
166 err_attr
= tb
[ETHTOOL_A_CHANNELS_COMBINED_COUNT
];
171 NL_SET_ERR_MSG_ATTR(info
->extack
, err_attr
,
172 "requested channel count exceeds maximum");
176 /* ensure there is at least one RX and one TX channel */
177 if (!channels
.combined_count
&& !channels
.rx_count
)
178 err_attr
= tb
[ETHTOOL_A_CHANNELS_RX_COUNT
];
179 else if (!channels
.combined_count
&& !channels
.tx_count
)
180 err_attr
= tb
[ETHTOOL_A_CHANNELS_TX_COUNT
];
185 err_attr
= tb
[ETHTOOL_A_CHANNELS_COMBINED_COUNT
];
187 NL_SET_ERR_MSG_ATTR(info
->extack
, err_attr
, "requested channel counts would result in no RX or TX channel being configured");
191 /* ensure the new Rx count fits within the configured Rx flow
192 * indirection table settings
194 if (netif_is_rxfh_configured(dev
) &&
195 !ethtool_get_max_rxfh_channel(dev
, &max_rx_in_use
) &&
196 (channels
.combined_count
+ channels
.rx_count
) <= max_rx_in_use
) {
198 GENL_SET_ERR_MSG(info
, "requested channel counts are too low for existing indirection table settings");
202 /* Disabling channels, query zero-copy AF_XDP sockets */
203 from_channel
= channels
.combined_count
+
204 min(channels
.rx_count
, channels
.tx_count
);
205 for (i
= from_channel
; i
< old_total
; i
++)
206 if (xsk_get_pool_from_qid(dev
, i
)) {
208 GENL_SET_ERR_MSG(info
, "requested channel counts are too low for existing zerocopy AF_XDP sockets");
212 ret
= dev
->ethtool_ops
->set_channels(dev
, &channels
);
215 ethtool_notify(dev
, ETHTOOL_MSG_CHANNELS_NTF
, NULL
);
218 ethnl_ops_complete(dev
);