diff options
author | Lorenzo Colitti <lorenzo@google.com> | 2014-03-26 13:03:12 +0900 |
---|---|---|
committer | JP Abgrall <jpa@google.com> | 2014-05-16 20:58:31 +0000 |
commit | 6ba3a0e3b112bdb47858e97aa763706ba26ca5ea (patch) | |
tree | ab2763230c1d978e67819a152747cb06cfdf0337 /include | |
parent | 2cf4347e486ca01b5ca6429b50e79b93de07adf8 (diff) |
net: support marking accepting TCP sockets
When using mark-based routing, sockets returned from accept()
may need to be marked differently depending on the incoming
connection request.
This is the case, for example, if different socket marks identify
different networks: a listening socket may want to accept
connections from all networks, but each connection should be
marked with the network that the request came in on, so that
subsequent packets are sent on the correct network.
This patch adds a sysctl to mark TCP sockets based on the fwmark
of the incoming SYN packet. If enabled, and an unmarked socket
receives a SYN, then the SYN packet's fwmark is written to the
connection's inet_request_sock, and later written back to the
accepted socket when the connection is established. If the
socket already has a nonzero mark, then the behaviour is the same
as it is today, i.e., the listening socket's fwmark is used.
Black-box tested using user-mode linux:
- IPv4/IPv6 SYN+ACK, FIN, etc. packets are routed based on the
mark of the incoming SYN packet.
- The socket returned by accept() is marked with the mark of the
incoming SYN packet.
- Tested with syncookies=1 and syncookies=2.
Change-Id: I26bc1eceefd2c588d73b921865ab70e4645ade57
Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/net/inet_sock.h | 9 | ||||
-rw-r--r-- | include/net/netns/ipv4.h | 1 |
2 files changed, 10 insertions, 0 deletions
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 7235ae73a1e8..9528e10fa0b4 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -88,6 +88,7 @@ struct inet_request_sock { acked : 1, no_srccheck: 1; kmemcheck_bitfield_end(flags); + u32 ir_mark; struct ip_options_rcu *opt; }; @@ -96,6 +97,14 @@ static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk) return (struct inet_request_sock *)sk; } +static inline u32 inet_request_mark(struct sock *sk, struct sk_buff *skb) +{ + if (!sk->sk_mark && sock_net(sk)->ipv4.sysctl_tcp_fwmark_accept) + return skb->mark; + + return sk->sk_mark; +} + struct inet_cork { unsigned int flags; __be32 addr; diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 222461a7cc5d..0dd6f0b3eadb 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -65,6 +65,7 @@ struct netns_ipv4 { int sysctl_tcp_ecn; int sysctl_fwmark_reflect; + int sysctl_tcp_fwmark_accept; kgid_t sysctl_ping_group_range[2]; long sysctl_tcp_mem[3]; |