^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #ifndef _NET_ETHTOOL_NETLINK_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #define _NET_ETHTOOL_NETLINK_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/ethtool_netlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/netdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <net/genetlink.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <net/sock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) struct ethnl_req_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) const struct nlattr *nest, struct net *net,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) struct netlink_ext_ack *extack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) bool require_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) int ethnl_fill_reply_header(struct sk_buff *skb, struct net_device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) u16 attrtype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct sk_buff *ethnl_reply_init(size_t payload, struct net_device *dev, u8 cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) u16 hdr_attrtype, struct genl_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) void **ehdrp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) void *ethnl_dump_put(struct sk_buff *skb, struct netlink_callback *cb, u8 cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) void *ethnl_bcastmsg_put(struct sk_buff *skb, u8 cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int ethnl_multicast(struct sk_buff *skb, struct net_device *dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * ethnl_strz_size() - calculate attribute length for fixed size string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * @s: ETH_GSTRING_LEN sized string (may not be null terminated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * Return: total length of an attribute with null terminated string from @s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static inline int ethnl_strz_size(const char *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return nla_total_size(strnlen(s, ETH_GSTRING_LEN) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * ethnl_put_strz() - put string attribute with fixed size string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * @skb: skb with the message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * @attrype: attribute type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * @s: ETH_GSTRING_LEN sized string (may not be null terminated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * Puts an attribute with null terminated string from @s into the message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * Return: 0 on success, negative error code on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static inline int ethnl_put_strz(struct sk_buff *skb, u16 attrtype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) const char *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) unsigned int len = strnlen(s, ETH_GSTRING_LEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct nlattr *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) attr = nla_reserve(skb, attrtype, len + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (!attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return -EMSGSIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) memcpy(nla_data(attr), s, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) ((char *)nla_data(attr))[len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * ethnl_update_u32() - update u32 value from NLA_U32 attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * @dst: value to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * @attr: netlink attribute with new value or null
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * @mod: pointer to bool for modification tracking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * Copy the u32 value from NLA_U32 netlink attribute @attr into variable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * pointed to by @dst; do nothing if @attr is null. Bool pointed to by @mod
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * is set to true if this function changed the value of *dst, otherwise it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * is left as is.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static inline void ethnl_update_u32(u32 *dst, const struct nlattr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) bool *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (!attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) val = nla_get_u32(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (*dst == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) *dst = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) *mod = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * ethnl_update_u8() - update u8 value from NLA_U8 attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * @dst: value to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * @attr: netlink attribute with new value or null
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * @mod: pointer to bool for modification tracking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * Copy the u8 value from NLA_U8 netlink attribute @attr into variable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * pointed to by @dst; do nothing if @attr is null. Bool pointed to by @mod
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * is set to true if this function changed the value of *dst, otherwise it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * is left as is.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static inline void ethnl_update_u8(u8 *dst, const struct nlattr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) bool *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (!attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) val = nla_get_u8(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (*dst == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) *dst = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) *mod = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * ethnl_update_bool32() - update u32 used as bool from NLA_U8 attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * @dst: value to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * @attr: netlink attribute with new value or null
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * @mod: pointer to bool for modification tracking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * Use the u8 value from NLA_U8 netlink attribute @attr to set u32 variable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * pointed to by @dst to 0 (if zero) or 1 (if not); do nothing if @attr is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * null. Bool pointed to by @mod is set to true if this function changed the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * logical value of *dst, otherwise it is left as is.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static inline void ethnl_update_bool32(u32 *dst, const struct nlattr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) bool *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) u8 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (!attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) val = !!nla_get_u8(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (!!*dst == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) *dst = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) *mod = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * ethnl_update_binary() - update binary data from NLA_BINARY atribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * @dst: value to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * @len: destination buffer length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * @attr: netlink attribute with new value or null
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * @mod: pointer to bool for modification tracking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * Use the u8 value from NLA_U8 netlink attribute @attr to rewrite data block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * of length @len at @dst by attribute payload; do nothing if @attr is null.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * Bool pointed to by @mod is set to true if this function changed the logical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * value of *dst, otherwise it is left as is.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static inline void ethnl_update_binary(void *dst, unsigned int len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) const struct nlattr *attr, bool *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (!attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (nla_len(attr) < len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) len = nla_len(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (!memcmp(dst, nla_data(attr), len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) memcpy(dst, nla_data(attr), len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) *mod = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * ethnl_update_bitfield32() - update u32 value from NLA_BITFIELD32 attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * @dst: value to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * @attr: netlink attribute with new value or null
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * @mod: pointer to bool for modification tracking
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * Update bits in u32 value which are set in attribute's mask to values from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * attribute's value. Do nothing if @attr is null or the value wouldn't change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * otherwise, set bool pointed to by @mod to true.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static inline void ethnl_update_bitfield32(u32 *dst, const struct nlattr *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) bool *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct nla_bitfield32 change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) u32 newval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (!attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) change = nla_get_bitfield32(attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) newval = (*dst & ~change.selector) | (change.value & change.selector);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (*dst == newval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) *dst = newval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) *mod = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * ethnl_reply_header_size() - total size of reply header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * This is an upper estimate so that we do not need to hold RTNL lock longer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * than necessary (to prevent rename between size estimate and composing the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * message). Accounts only for device ifindex and name as those are the only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * attributes ethnl_fill_reply_header() puts into the reply header.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static inline unsigned int ethnl_reply_header_size(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return nla_total_size(nla_total_size(sizeof(u32)) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) nla_total_size(IFNAMSIZ));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /* GET request handling */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* Unified processing of GET requests uses two data structures: request info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * and reply data. Request info holds information parsed from client request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * and its stays constant through all request processing. Reply data holds data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * retrieved from ethtool_ops callbacks or other internal sources which is used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * to compose the reply. When processing a dump request, request info is filled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * only once (when the request message is parsed) but reply data is filled for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * each reply message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * Both structures consist of part common for all request types (struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * ethnl_req_info and struct ethnl_reply_data defined below) and optional
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * parts specific for each request type. Common part always starts at offset 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * struct ethnl_req_info - base type of request information for GET requests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * @dev: network device the request is for (may be null)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * @flags: request flags common for all request types
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * This is a common base for request specific structures holding data from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * parsed userspace request. These always embed struct ethnl_req_info at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * zero offset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct ethnl_req_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) u32 flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) * struct ethnl_reply_data - base type of reply data for GET requests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * @dev: device for current reply message; in single shot requests it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * equal to ðnl_req_info.dev; in dumps it's different for each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * reply message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * This is a common base for request specific structures holding data for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * kernel reply message. These always embed struct ethnl_reply_data at zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * offset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct ethnl_reply_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct net_device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) static inline int ethnl_ops_begin(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (dev && dev->reg_state == NETREG_UNREGISTERING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (dev && dev->ethtool_ops->begin)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) return dev->ethtool_ops->begin(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static inline void ethnl_ops_complete(struct net_device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (dev && dev->ethtool_ops->complete)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) dev->ethtool_ops->complete(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * struct ethnl_request_ops - unified handling of GET requests
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * @request_cmd: command id for request (GET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * @reply_cmd: command id for reply (GET_REPLY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * @hdr_attr: attribute type for request header
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * @req_info_size: size of request info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) * @reply_data_size: size of reply data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * @allow_nodev_do: allow non-dump request with no device identification
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * @parse_request:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * Parse request except common header (struct ethnl_req_info). Common
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * header is already filled on entry, the rest up to @repdata_offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * is zero initialized. This callback should only modify type specific
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * request info by parsed attributes from request message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * @prepare_data:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * Retrieve and prepare data needed to compose a reply message. Calls to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * ethtool_ops handlers are limited to this callback. Common reply data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * (struct ethnl_reply_data) is filled on entry, type specific part after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * it is zero initialized. This callback should only modify the type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * specific part of reply data. Device identification from struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * ethnl_reply_data is to be used as for dump requests, it iterates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * through network devices while dev member of struct ethnl_req_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * points to the device from client request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * @reply_size:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) * Estimate reply message size. Returned value must be sufficient for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * message payload without common reply header. The callback may returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * estimate higher than actual message size if exact calculation would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * not be worth the saved memory space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * @fill_reply:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * Fill reply message payload (except for common header) from reply data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * The callback must not generate more payload than previously called
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * ->reply_size() estimated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * @cleanup_data:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * Optional cleanup called when reply data is no longer needed. Can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * used e.g. to free any additional data structures outside the main
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * structure which were allocated by ->prepare_data(). When processing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * dump requests, ->cleanup() is called for each message.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * Description of variable parts of GET request handling when using the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * unified infrastructure. When used, a pointer to an instance of this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * structure is to be added to ðnl_default_requests array and generic
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * handlers ethnl_default_doit(), ethnl_default_dumpit(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * ethnl_default_start() and ethnl_default_done() used in @ethtool_genl_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * ethnl_default_notify() can be used in @ethnl_notify_handlers to send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * notifications of the corresponding type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct ethnl_request_ops {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) u8 request_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) u8 reply_cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) u16 hdr_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) unsigned int req_info_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) unsigned int reply_data_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) bool allow_nodev_do;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) int (*parse_request)(struct ethnl_req_info *req_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) struct nlattr **tb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) struct netlink_ext_ack *extack);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int (*prepare_data)(const struct ethnl_req_info *req_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct ethnl_reply_data *reply_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct genl_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) int (*reply_size)(const struct ethnl_req_info *req_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) const struct ethnl_reply_data *reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) int (*fill_reply)(struct sk_buff *skb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) const struct ethnl_req_info *req_info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) const struct ethnl_reply_data *reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) void (*cleanup_data)(struct ethnl_reply_data *reply_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) /* request handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) extern const struct ethnl_request_ops ethnl_strset_request_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) extern const struct ethnl_request_ops ethnl_linkinfo_request_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) extern const struct ethnl_request_ops ethnl_linkmodes_request_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) extern const struct ethnl_request_ops ethnl_linkstate_request_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) extern const struct ethnl_request_ops ethnl_debug_request_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) extern const struct ethnl_request_ops ethnl_wol_request_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) extern const struct ethnl_request_ops ethnl_features_request_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) extern const struct ethnl_request_ops ethnl_privflags_request_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) extern const struct ethnl_request_ops ethnl_rings_request_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) extern const struct ethnl_request_ops ethnl_channels_request_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) extern const struct ethnl_request_ops ethnl_coalesce_request_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) extern const struct ethnl_request_ops ethnl_pause_request_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) extern const struct ethnl_request_ops ethnl_eee_request_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) extern const struct ethnl_request_ops ethnl_tsinfo_request_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_FLAGS + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) extern const struct nla_policy ethnl_strset_get_policy[ETHTOOL_A_STRSET_COUNTS_ONLY + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) extern const struct nla_policy ethnl_linkinfo_get_policy[ETHTOOL_A_LINKINFO_HEADER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) extern const struct nla_policy ethnl_linkinfo_set_policy[ETHTOOL_A_LINKINFO_TP_MDIX_CTRL + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) extern const struct nla_policy ethnl_linkmodes_get_policy[ETHTOOL_A_LINKMODES_HEADER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) extern const struct nla_policy ethnl_linkmodes_set_policy[ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) extern const struct nla_policy ethnl_linkstate_get_policy[ETHTOOL_A_LINKSTATE_HEADER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) extern const struct nla_policy ethnl_debug_get_policy[ETHTOOL_A_DEBUG_HEADER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) extern const struct nla_policy ethnl_debug_set_policy[ETHTOOL_A_DEBUG_MSGMASK + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) extern const struct nla_policy ethnl_wol_get_policy[ETHTOOL_A_WOL_HEADER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) extern const struct nla_policy ethnl_wol_set_policy[ETHTOOL_A_WOL_SOPASS + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) extern const struct nla_policy ethnl_features_get_policy[ETHTOOL_A_FEATURES_HEADER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) extern const struct nla_policy ethnl_features_set_policy[ETHTOOL_A_FEATURES_WANTED + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) extern const struct nla_policy ethnl_privflags_get_policy[ETHTOOL_A_PRIVFLAGS_HEADER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) extern const struct nla_policy ethnl_privflags_set_policy[ETHTOOL_A_PRIVFLAGS_FLAGS + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) extern const struct nla_policy ethnl_rings_get_policy[ETHTOOL_A_RINGS_HEADER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) extern const struct nla_policy ethnl_rings_set_policy[ETHTOOL_A_RINGS_TX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) extern const struct nla_policy ethnl_channels_get_policy[ETHTOOL_A_CHANNELS_HEADER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) extern const struct nla_policy ethnl_channels_set_policy[ETHTOOL_A_CHANNELS_COMBINED_COUNT + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) extern const struct nla_policy ethnl_coalesce_get_policy[ETHTOOL_A_COALESCE_HEADER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) extern const struct nla_policy ethnl_coalesce_set_policy[ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) extern const struct nla_policy ethnl_pause_get_policy[ETHTOOL_A_PAUSE_HEADER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) extern const struct nla_policy ethnl_pause_set_policy[ETHTOOL_A_PAUSE_TX + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) extern const struct nla_policy ethnl_eee_get_policy[ETHTOOL_A_EEE_HEADER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) extern const struct nla_policy ethnl_eee_set_policy[ETHTOOL_A_EEE_TX_LPI_TIMER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) extern const struct nla_policy ethnl_tsinfo_get_policy[ETHTOOL_A_TSINFO_HEADER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) extern const struct nla_policy ethnl_cable_test_act_policy[ETHTOOL_A_CABLE_TEST_HEADER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) extern const struct nla_policy ethnl_cable_test_tdr_act_policy[ETHTOOL_A_CABLE_TEST_TDR_CFG + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) extern const struct nla_policy ethnl_tunnel_info_get_policy[ETHTOOL_A_TUNNEL_INFO_HEADER + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int ethnl_set_linkinfo(struct sk_buff *skb, struct genl_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) int ethnl_set_linkmodes(struct sk_buff *skb, struct genl_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) int ethnl_set_debug(struct sk_buff *skb, struct genl_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) int ethnl_set_wol(struct sk_buff *skb, struct genl_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int ethnl_set_features(struct sk_buff *skb, struct genl_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) int ethnl_set_privflags(struct sk_buff *skb, struct genl_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) int ethnl_set_rings(struct sk_buff *skb, struct genl_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) int ethnl_set_channels(struct sk_buff *skb, struct genl_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) int ethnl_set_pause(struct sk_buff *skb, struct genl_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) int ethnl_set_eee(struct sk_buff *skb, struct genl_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) int ethnl_act_cable_test_tdr(struct sk_buff *skb, struct genl_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) int ethnl_tunnel_info_doit(struct sk_buff *skb, struct genl_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) int ethnl_tunnel_info_start(struct netlink_callback *cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) int ethnl_tunnel_info_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) #endif /* _NET_ETHTOOL_NETLINK_H */