lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-ID: <20231008052101.144422-5-akihiko.odaki@daynix.com> Date: Sun, 8 Oct 2023 14:20:48 +0900 From: Akihiko Odaki <akihiko.odaki@...nix.com> To: Cc: Willem de Bruijn <willemdebruijn.kernel@...il.com>, Jason Wang <jasowang@...hat.com>, "Michael S. Tsirkin" <mst@...hat.com>, Xuan Zhuo Shuah Khan <"xuanzhuo@...ux.alibaba.comshuah"@kernel.org>, netdev@...r.kernel.org, linux-kernel@...r.kernel.org, kvm@...r.kernel.org, virtualization@...ts.linux-foundation.org, linux-kselftest@...r.kernel.org, bpf@...r.kernel.org, davem@...emloft.net, kuba@...nel.org, ast@...nel.org, daniel@...earbox.net, andrii@...nel.org, kafai@...com, songliubraving@...com, yhs@...com, john.fastabend@...il.com, kpsingh@...nel.org, rdunlap@...radead.org, willemb@...gle.com, gustavoars@...nel.org, herbert@...dor.apana.org.au, steffen.klassert@...unet.com, nogikh@...gle.com, pablo@...filter.org, decui@...rosoft.com, cai@....pw, jakub@...udflare.com, elver@...gle.com, pabeni@...hat.com, Yuri Benditovich <yuri.benditovich@...nix.com>, Akihiko Odaki <akihiko.odaki@...nix.com> Subject: [RFC PATCH 4/7] virtio_net: Add functions for hashing They are useful to implement VIRTIO_NET_F_RSS and VIRTIO_NET_F_HASH_REPORT. Signed-off-by: Akihiko Odaki <akihiko.odaki@...nix.com> --- include/linux/virtio_net.h | 157 +++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 7b4dd69555e4..f05781ddc261 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -7,6 +7,143 @@ #include <uapi/linux/udp.h> #include <uapi/linux/virtio_net.h> +struct virtio_net_hash { + u32 value; + u16 report; +}; + +struct virtio_net_toeplitz_state { + u32 hash; + u32 key_buffer; + const u32 *key; +}; + +#define VIRTIO_NET_SUPPORTED_HASH_TYPES (VIRTIO_NET_RSS_HASH_TYPE_IPv4 | \ + VIRTIO_NET_RSS_HASH_TYPE_TCPv4 | \ + VIRTIO_NET_RSS_HASH_TYPE_UDPv4 | \ + VIRTIO_NET_RSS_HASH_TYPE_IPv6 | \ + VIRTIO_NET_RSS_HASH_TYPE_TCPv6 | \ + VIRTIO_NET_RSS_HASH_TYPE_UDPv6) + +static inline void virtio_net_toeplitz(struct virtio_net_toeplitz_state *state, + const u32 *input, size_t len) +{ + u32 key; + + while (len) { + state->key++; + key = ntohl(*state->key); + + for (u32 bit = BIT(31); bit; bit >>= 1) { + if (*input & bit) + state->hash ^= state->key_buffer; + + state->key_buffer = + (state->key_buffer << 1) | !!(key & bit); + } + + input++; + len--; + } +} + +static inline u8 virtio_net_hash_key_length(u32 types) +{ + size_t len = 0; + + if (types & VIRTIO_NET_HASH_REPORT_IPv4) + len = max(len, + sizeof(struct flow_dissector_key_ipv4_addrs)); + + if (types & + (VIRTIO_NET_HASH_REPORT_TCPv4 | VIRTIO_NET_HASH_REPORT_UDPv4)) + len = max(len, + sizeof(struct flow_dissector_key_ipv4_addrs) + + sizeof(struct flow_dissector_key_ports)); + + if (types & VIRTIO_NET_HASH_REPORT_IPv6) + len = max(len, + sizeof(struct flow_dissector_key_ipv6_addrs)); + + if (types & + (VIRTIO_NET_HASH_REPORT_TCPv6 | VIRTIO_NET_HASH_REPORT_UDPv6)) + len = max(len, + sizeof(struct flow_dissector_key_ipv6_addrs) + + sizeof(struct flow_dissector_key_ports)); + + return 4 + len; +} + +static inline void virtio_net_hash(const struct sk_buff *skb, + u32 types, const u32 *key, + struct virtio_net_hash *hash) +{ + u16 report = VIRTIO_NET_HASH_REPORT_NONE; + struct virtio_net_toeplitz_state toeplitz_state = { + .key_buffer = ntohl(*key), + .key = key + }; + struct flow_keys flow; + + if (!skb_flow_dissect_flow_keys(skb, &flow, 0)) + return; + + switch (flow.basic.n_proto) { + case htons(ETH_P_IP): + if (flow.basic.ip_proto == IPPROTO_TCP && + (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv4)) { + report = VIRTIO_NET_HASH_REPORT_TCPv4; + virtio_net_toeplitz(&toeplitz_state, + (u32 *)&flow.addrs.v4addrs, + sizeof(flow.addrs.v4addrs) / 4); + virtio_net_toeplitz(&toeplitz_state, &flow.ports.ports, + 1); + } else if (flow.basic.ip_proto == IPPROTO_UDP && + (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv4)) { + report = VIRTIO_NET_HASH_REPORT_UDPv4; + virtio_net_toeplitz(&toeplitz_state, + (u32 *)&flow.addrs.v4addrs, + sizeof(flow.addrs.v4addrs) / 4); + virtio_net_toeplitz(&toeplitz_state, &flow.ports.ports, + 1); + } else if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv4) { + report = VIRTIO_NET_HASH_REPORT_IPv4; + virtio_net_toeplitz(&toeplitz_state, + (u32 *)&flow.addrs.v4addrs, + sizeof(flow.addrs.v4addrs) / 4); + } + break; + + case htons(ETH_P_IPV6): + if (flow.basic.ip_proto == IPPROTO_TCP && + (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv6)) { + report = VIRTIO_NET_HASH_REPORT_TCPv6; + virtio_net_toeplitz(&toeplitz_state, + (u32 *)&flow.addrs.v6addrs, + sizeof(flow.addrs.v6addrs) / 4); + virtio_net_toeplitz(&toeplitz_state, &flow.ports.ports, + 1); + } else if (flow.basic.ip_proto == IPPROTO_UDP && + (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv6)) { + report = VIRTIO_NET_HASH_REPORT_UDPv6; + virtio_net_toeplitz(&toeplitz_state, + (u32 *)&flow.addrs.v6addrs, + sizeof(flow.addrs.v6addrs) / 4); + virtio_net_toeplitz(&toeplitz_state, &flow.ports.ports, + 1); + } else if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv6) { + report = VIRTIO_NET_HASH_REPORT_IPv6; + virtio_net_toeplitz(&toeplitz_state, + (u32 *)&flow.addrs.v6addrs, + sizeof(flow.addrs.v6addrs) / 4); + } + break; + } + + hash->value = toeplitz_state.hash; + hash->report = report; +} + static inline bool virtio_net_hdr_match_proto(__be16 protocol, __u8 gso_type) { switch (gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { @@ -216,4 +353,24 @@ static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb, return 0; } +static inline int virtio_net_hdr_v1_hash_from_skb(const struct sk_buff *skb, + struct virtio_net_hdr_v1_hash *hdr, + bool has_data_valid, + int vlan_hlen, + const struct virtio_net_hash *hash) +{ + int ret; + + memset(hdr, 0, sizeof(*hdr)); + + ret = virtio_net_hdr_from_skb(skb, (struct virtio_net_hdr *)hdr, + true, has_data_valid, vlan_hlen); + if (!ret) { + hdr->hash_value = cpu_to_le32(hash->value); + hdr->hash_report = cpu_to_le16(hash->report); + } + + return ret; +} + #endif /* _LINUX_VIRTIO_NET_H */ -- 2.42.0
Powered by blists - more mailing lists