This is an old revision of the document!
Network RSS
What is RSS?
In this context, it's “Receive Side Scaling”. It started at Microsoft.
Start here: http://msdn.microsoft.com/en-us/library/windows/hardware/ff570736(v=vs.85).aspx
Then, read this: http://msdn.microsoft.com/en-us/library/windows/hardware/ff567236(v=vs.85).aspx
The basic idea is to keep the code and data for each given TCP and UDP flow on a CPU, which aims to:
- Reduce lock contention (as multiple CPUs aren't competing for the same resource);
- Keep things more hot in the local CPU cache;
- .. eventually, keep it local to a CPU socket and memory.
Where's the code?
Robert's initial RSS work and the PCBGROUPS work is in -HEAD.
My code to make it usable by mortals and implement the missing pieces is here:
TODO list
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/assembly? How's it end up on the right CPU?
- Modify (some) drivers to use the RSS routines to pin the transmit/receive paths to the correct RSS CPU ID
- .. and make sure it's all correctly pinned.
- UDP RSS? What's required?
- IPv6 RSS? What's required?
- RSS Rebalancing - re-assigning the bucket → queue → CPU mapping to deal with slightly different CPU / queue loads (ie, “rebalancing” the load between each bucket so each CPU gets an even set of load)
- .. some driver hooks are required to inform the drivers to reprogram their RSS configuration
- .. and some notification mechanism for userland is required.
Completed work
- (Done - adrian) add support for multiple listener sockets on the same listen address/port
- (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) Investigate a userland API to query the local CPU needed for a given socket, so applications can migrate fds to the right thread if required (eg for outbound connections)
- (Done - rwatson) Integrate Robert's existing work into HEAD
- (Done - adrian) Allow swi's to be CPU pinned, for TCP timers to correctly run on the right CPU
- (Done - adrian) Store the TCP hashtype in the inpcb
- (Done - adrian) Map TCP timers to the RSS selected CPU
- (Done - adrian) Ensure that the RSS used is the receive hash from the hardware - and that for software calculation of the RSS hash, the source/destination tuples are used in the right order
- .. ie, that the RSS hash for the transmit direction and receive direction of a flow come out to the same value
Later work
What isn't required for basic RSS but would be nice:
- Merge in the GSOC support for policies per FD/socket for RSS (GSoC project from Takuya Asada?) (URL?)
- RSS-ised TCP syncache?
- There's some lock contention between the if_transmit() thread(s), TX interrupt and deferred TX taskqueue. An interrupt can come in and schedule the swi during if_transmit() and deferred TX taskqueue. Keep an eye on that over time.
- .. maybe do a trylock and schedule a deferred TX taskqueue to handle the TX completion, at least so the swi doesn't preempt an existing running task?
- .. maybe temporarily disable scheduling the swi if the TX lock is held?
- How should multi-CPU-socket and multi-CPU-NIC RSS work? Ideally each CPU local to a NIC would have a separate PCBGROUPs table (or part of one) and separate RSS, so the traffic can be kept local to that CPU socket.
Drivers
- Work is being done using igb(4), as that's what AdrianChadd has on hand.
TODO - hopefully at least ixgbe and cxgbe