Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| networking:receivesidescaling [2014/07/13 20:45] – AdrianChadd | networking:receivesidescaling [2021/04/25 04:44] (current) – Sapell namespace correctly KubilayKocak | ||
|---|---|---|---|
| Line 19: | Line 19: | ||
| Robert' | Robert' | ||
| - | My code to make it usable by mortals and implement the missing pieces | + | I'm committing things |
| + | |||
| + | I do development in this branch - but right now everything | ||
| * https:// | * https:// | ||
| Line 55: | Line 57: | ||
| Here's the list of things to do for basic RSS support. | Here's the list of things to do for basic RSS support. | ||
| - | |||
| - | * For NICs that hash on RX we can certainly use their RSS hash; but for NICs that don't, we may want to set the flowid on packet reception to a software calculated RSS value. | ||
| - | * .. which will be amusing, as currently the flowid tag isn't set on mbufs _also with_ the flowtype value; making it difficult to know whether the NIC is actually setting an RSS hash or some arbitrary flowid value. | ||
| - | * .. So, we likely need to populate the flowtype value in the ethernet driver, complete with whether it's a 2-tuple or a 4-tuple value, and whether it's for IPv4 or IPv6. | ||
| - | * Investigate / handle RSS for IP fragments - what CPU does the defrag/ | ||
| - | * Modify (some) drivers to use the RSS routines to pin the transmit/ | ||
| - | * .. and make sure it's all correctly pinned. | ||
| - | * UDP RSS? What's required? (see below) | ||
| * RSS Rebalancing - re-assigning the bucket -> queue -> CPU mapping to deal with slightly different CPU / queue loads (ie, " | * RSS Rebalancing - re-assigning the bucket -> queue -> CPU mapping to deal with slightly different CPU / queue loads (ie, " | ||
| Line 68: | Line 62: | ||
| * .. and some notification mechanism for userland is required. | * .. and some notification mechanism for userland is required. | ||
| - | * Figure out what' | + | * See if it' |
| + | |||
| + | ===== Current work ===== | ||
| + | |||
| + | ==== General work ==== | ||
| + | |||
| + | The current RSS work aims to finish up RSS awareness in the UDP path and tidy up the immediate loose ends around | ||
| + | |||
| + | * Convert UDP code to initialise 2-tuple or 4-tuple hashing based on whether 4-tuple UDP is enabled | ||
| + | * Add RSS calculation to the IPv6 fragment reassembly code - again depending upon whether 2-tuple or 4-tuple is configured for the packet type (eg if it' | ||
| + | * If it's easy, re-injected re-assembled IPv6 fragments back into the correct netisr queue - the new RSS hash value / type will direct it to the correct CPU. | ||
| + | * Handle IPv4 tunnel decapsulated frames (gif, gre, ipip, ipsec) | ||
| + | * Handle IPv6 tunnel decapsulated frames (gif, gre, ipip, ipsec) | ||
| + | * Look at what was done for IPv4 netisr receive (ie, calling into the RSS code to see if frames | ||
| + | * IPv6 UDP receive works - but IPv6 UDP send has very simplistic locking. In order for it to scale it should do something similar to what the IPv4 UDP send path does (ie, optimise for local bind() sockets, so it doesn' | ||
| + | |||
| + | ==== FreeBSD-12 work ==== | ||
| + | |||
| + | TODO list for %%FreeBSD%%-12: | ||
| + | |||
| + | * add support to configure per-device RSS keys on the fly; | ||
| + | * configure per-device RSS bucket mappings on the fly; | ||
| + | * configure per-device RSS hash configurations on the fly; | ||
| + | * configure per-bucket CPU set mappings on the fly; | ||
| + | * split the RSS driver side, the RSS packet input side and the RSS stack side of things up into separate options; | ||
| + | * UDP IPv6 RSS support would be nice (it works, but i need to test/ | ||
| + | * work on scaling linearly on incoming /and/ outgoing connections. Right now incoming connections are easy, but outgoing connections aren't so easy; | ||
| + | * allow the system TCP/UDP hash type to be set at boot time - right now it's 4-tuple for TCP, 2-tuple for UDP, but some NICs (eg the 40G Intel ixl hardware) can only hash UDPv4 as 4-tuple; it doesn' | ||
| + | * remove the requirement that the RSS CPU/hash bucket mapping is a power of two; allow it to be an arbitrary configuration. | ||
| + | |||
| + | And: | ||
| + | |||
| + | * it'd be nice if this were better documented; | ||
| + | * it'd be nice if we had easy examples of this stuff working, complete with library bits in base. | ||
| ===== Completed work ===== | ===== Completed work ===== | ||
| + | * (done) For NICs that hash on RX we can certainly use their RSS hash; but for NICs that don't, we may want to set the flowid on packet reception to a software calculated RSS value. | ||
| + | * .. which will be amusing, as currently the flowid tag isn't set on mbufs _also with_ the flowtype value; making it difficult to know whether the NIC is actually setting an RSS hash or some arbitrary flowid value. | ||
| + | * (done - ixgbe, igb) .. So, we likely need to populate the flowtype value in the ethernet driver, complete with whether it's a 2-tuple or a 4-tuple value, and whether it's for IPv4 or IPv6. | ||
| + | * (done - ipv4) Investigate / handle RSS for IP fragments - what CPU does the defrag/ | ||
| + | * .. will likely have to do a software calculation of the frame once it finishes ip_reass() | ||
| + | * (done - ixgbe, igb) Modify (some) drivers to use the RSS routines to pin the transmit/ | ||
| + | * .. and make sure it's all correctly pinned. | ||
| + | * (done, ipv4) UDP RSS? What's required? (see below) | ||
| + | * (done, ipv4) Reinject completed IPv4/IPv6 fragments into netisr but destined for the correct RSS bucket / queue / CPU. | ||
| + | |||
| + | * (done) Figure out what's going on with ixgbe(4) and UDPv4 receive on fragmented (> 1 MTU) frames. Testing showed that the RX path was stamping these large UDP frames with a hashtype of straight IPv4 rather than UDP IPv4. It may be that hardware LRO is enabled and it's coalescing things for us, but returning it as an IPv4 frame. Perhaps a higher / varied traffic load would run the LRO buffers out and and would start to see some frames returned with UDP IPv4 (first fragment) and some with stright IPv4 (subsequent fragments.) | ||
| + | * What's happening: ixgbe, igb and cxgbe treat fragmented frames as 2-tuple IPv4 or IPv6 - including the first frame in the fragment. So the RSS hash needs to be re-calculated and re-injected where appropriate. | ||
| * (Done - adrian) add support for multiple listener sockets on the same listen address/ | * (Done - adrian) add support for multiple listener sockets on the same listen address/ | ||
| * (Done - adrian) .. and then modify the pcbgroups / pcb lookup routines to terminate an incoming socket on a CPU local pcbgroup entry if one exists, before defaulting to a wildcard entry | * (Done - adrian) .. and then modify the pcbgroups / pcb lookup routines to terminate an incoming socket on a CPU local pcbgroup entry if one exists, before defaulting to a wildcard entry | ||
| Line 82: | Line 121: | ||
| * .. ie, that the RSS hash for the transmit direction and receive direction of a flow come out to the same value | * .. ie, that the RSS hash for the transmit direction and receive direction of a flow come out to the same value | ||
| * IPv6 RSS? What's required? (done - adrian) | * IPv6 RSS? What's required? (done - adrian) | ||
| + | * (Done - adrian) Add RSS calculation to the IPv4 fragment reassembly code - again depending upon whether 2-tuple or 4-tuple is configured for the packet type (eg if it's UDPv4 but only 2-tuple for UDP is available, then only do the software hash for the 2-tuple data.) | ||
| + | * (Done - adrian) If it's easy, re-injected re-assembled IPv4 fragments back into the correct netisr queue - the new RSS hash value / type will direct it to the correct CPU. | ||
| + | * (Done - adrian) UDP IPv4 and IPv6 RSS aware receive distribution to RSS aware sockets; | ||
| + | * (Done - adrian) UDP IPv4 and IPv6 RSS software hash for outbound UDP frames; | ||
| + | * (Done - tiwei) RSS software hash for IPv6 packet receive path | ||
| ===== Later work ===== | ===== Later work ===== | ||
| Line 165: | Line 209: | ||
| This is especially a problem with UDP. | This is especially a problem with UDP. | ||
| + | |||
| + | For the IPv4 path, it's handled via ip_reass() in sys/ | ||
| + | |||
| + | For the IPv6 path, IPv6 fragments are a different IPv6 protocol. They' | ||
| + | |||
| + | So, once the fragments have been received and reassembled a 2-tuple or 4-tuple RSS hash is required. This depends upon the protocol type (TCP, UDP, other) and whether TCP/UDP hashing is enabled in RSS. | ||
| + | |||
| + | The easiest solution would be to just recalculate the hash on the completed frame. The more complicated solution is to check if the hash type has changed (eg IPv4 TCP frame, which the hardware stamped with a 2-tuple hash type) and if it still has the correct hash type, treat it as valid. | ||
| + | |||
| + | Another amusing thing is where to reinject the completed packet. The destination RSS bucket is likely different to the CPU which reassembled the frames. Somehow it needs to be re-injected into the correct netisr queue and handled appropriately. | ||
| + | |||
| + | ---- | ||
| + | |||
| + | {{tag> | ||