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/29 08:20] – AdrianChadd | networking:receivesidescaling [2021/04/25 04:44] (current) – Sapell namespace correctly KubilayKocak | ||
|---|---|---|---|
| Line 21: | Line 21: | ||
| I'm committing things to -HEAD as they get tested. | I'm committing things to -HEAD as they get tested. | ||
| - | My development | + | I do development |
| * https:// | * https:// | ||
| Line 57: | 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/ | ||
| - | * .. will likely have to do a software calculation of the frame once it finishes ip_reass() | ||
| - | * 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 71: | Line 62: | ||
| * .. and some notification mechanism for userland is required. | * .. and some notification mechanism for userland is required. | ||
| - | * Reinject completed IPv4/IPv6 fragments into netisr but destined for the correct | + | * See if it's worth modifying the driver transmit behaviour so if the transmit CPU isn' |
| - | * 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.) | + | ===== Current work ===== |
| - | ===== Current | + | ==== General |
| The current RSS work aims to finish up RSS awareness in the UDP path and tidy up the immediate loose ends around IPv4 and IPv6 fragment handling. | The current RSS work aims to finish up RSS awareness in the UDP path and tidy up the immediate loose ends around IPv4 and IPv6 fragment handling. | ||
| - | * UDP IPv4 and IPv6 RSS aware receive distribution to RSS aware sockets; | ||
| - | * UDP IPv4 and IPv6 RSS software hash for outbound UDP frames; | ||
| * Convert UDP code to initialise 2-tuple or 4-tuple hashing based on whether 4-tuple UDP is enabled or not; | * Convert UDP code to initialise 2-tuple or 4-tuple hashing based on whether 4-tuple UDP is enabled or not; | ||
| - | * Add RSS calculation to the IPv4 and IPv6 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.) | + | * 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's UDPv4 but only 2-tuple for UDP is available, then only do the software hash for the 2-tuple data.) |
| - | * If it's easy, re-injected re-assembled | + | * 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 needed their RSS hash recalculated based on what the hardware provided) and do the same for IPv6. | ||
| + | * 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 97: | 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 190: | Line 219: | ||
| 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. | 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> | ||