倉庫指標
- Star
- (27,997 star)
- PR 合併指標
- (平均合併 8天) (30 天內合併 378 個 PR)
描述
Title: UDP Proxy Filter ephemeral ports management
Description:
Background: According to [1], a way to overcome the known ephemeral ports exhaustion problem is to use the REUSEADDR option together with bind and connect. This allows to extend the limited 2-tuple port range to 4-tuple. This, however, can lead to multiple sockets with the same 4-tuple to be created, resulting with a newer socket "overshadowing" previous ones.
Proposed Solution: While [1] proposes several solutions, I would like to propose a different one which seems simpler. The idea is to let envoy manage a set of configurable ephemeral ports ranges as follows:
- The UDP proxy filter configuration is added with an ephemeral port ranges entry (e.g. 1024-5,000, 10,000-50,000)
- The filter manages a <host addr, port queue> map.
- As soon as the socket is created in UdpActiveSession::writeUpstream we use the host addr to look up the associated port queue from the map and pop a "free" port. The port is placed back in the queue when the session ends.
- Getting a port we set the SO_REUSEADDR socket option and bind to the port.
- In case we are out of ports we fail the request increasing e.g. upstream_cx_overflow
Some more details:
- Having a <host addr, port queue> map to manage the ports assumes that the same host addr does not appear in more than one cluster.
- In order to have a lockless data structure the idea is to split the range between the different filter workers. For simplicity, say that our range is 10,000-50,000 and we have 8 workers, the worker with index 1 will use the range 10,000-14,999, the worker with index 2 15,000-19,999 and so on...
A PoC implementation seems to do the job. Before submitting a PR I would like to know if there is an elegant way to get the index and concurrency at the filter level (e.g. via the context) without adding them to the filter factory (which seems wrong).
Relevant Links: