diff options
author | Eric Dumazet <edumazet@google.com> | 2014-03-05 21:19:34 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-03-07 14:37:55 -0500 |
commit | 31c70d5956fc3d1abf83e9ab5e1d8237dea59498 (patch) | |
tree | 7a63e4de80e41654006eb1bc2e61033ac4c2f47a /net/l2tp | |
parent | 219626924222b6b41bf2264896b34a6abaaeecf0 (diff) |
l2tp: keep original skb ownership
There is no reason to orphan skb in l2tp.
This breaks things like per socket memory limits, TCP Small queues...
Fix this before more people copy/paste it.
This is very similar to commit 8f646c922d550
("vxlan: keep original skb ownership")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: James Chapman <jchapman@katalix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/l2tp')
-rw-r--r-- | net/l2tp/l2tp_core.c | 23 |
1 files changed, 2 insertions, 21 deletions
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index e5dc42f0e527..9958c31c2c54 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
@@ -1108,6 +1108,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, | |||
1108 | struct flowi *fl, size_t data_len) | 1108 | struct flowi *fl, size_t data_len) |
1109 | { | 1109 | { |
1110 | struct l2tp_tunnel *tunnel = session->tunnel; | 1110 | struct l2tp_tunnel *tunnel = session->tunnel; |
1111 | struct sock *sk = tunnel->sock; | ||
1111 | unsigned int len = skb->len; | 1112 | unsigned int len = skb->len; |
1112 | int error; | 1113 | int error; |
1113 | 1114 | ||
@@ -1131,7 +1132,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, | |||
1131 | /* Queue the packet to IP for output */ | 1132 | /* Queue the packet to IP for output */ |
1132 | skb->local_df = 1; | 1133 | skb->local_df = 1; |
1133 | #if IS_ENABLED(CONFIG_IPV6) | 1134 | #if IS_ENABLED(CONFIG_IPV6) |
1134 | if (skb->sk->sk_family == PF_INET6 && !tunnel->v4mapped) | 1135 | if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) |
1135 | error = inet6_csk_xmit(skb, NULL); | 1136 | error = inet6_csk_xmit(skb, NULL); |
1136 | else | 1137 | else |
1137 | #endif | 1138 | #endif |
@@ -1151,23 +1152,6 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, | |||
1151 | return 0; | 1152 | return 0; |
1152 | } | 1153 | } |
1153 | 1154 | ||
1154 | /* Automatically called when the skb is freed. | ||
1155 | */ | ||
1156 | static void l2tp_sock_wfree(struct sk_buff *skb) | ||
1157 | { | ||
1158 | sock_put(skb->sk); | ||
1159 | } | ||
1160 | |||
1161 | /* For data skbs that we transmit, we associate with the tunnel socket | ||
1162 | * but don't do accounting. | ||
1163 | */ | ||
1164 | static inline void l2tp_skb_set_owner_w(struct sk_buff *skb, struct sock *sk) | ||
1165 | { | ||
1166 | sock_hold(sk); | ||
1167 | skb->sk = sk; | ||
1168 | skb->destructor = l2tp_sock_wfree; | ||
1169 | } | ||
1170 | |||
1171 | #if IS_ENABLED(CONFIG_IPV6) | 1155 | #if IS_ENABLED(CONFIG_IPV6) |
1172 | static void l2tp_xmit_ipv6_csum(struct sock *sk, struct sk_buff *skb, | 1156 | static void l2tp_xmit_ipv6_csum(struct sock *sk, struct sk_buff *skb, |
1173 | int udp_len) | 1157 | int udp_len) |
@@ -1221,7 +1205,6 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len | |||
1221 | return NET_XMIT_DROP; | 1205 | return NET_XMIT_DROP; |
1222 | } | 1206 | } |
1223 | 1207 | ||
1224 | skb_orphan(skb); | ||
1225 | /* Setup L2TP header */ | 1208 | /* Setup L2TP header */ |
1226 | session->build_header(session, __skb_push(skb, hdr_len)); | 1209 | session->build_header(session, __skb_push(skb, hdr_len)); |
1227 | 1210 | ||
@@ -1287,8 +1270,6 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len | |||
1287 | break; | 1270 | break; |
1288 | } | 1271 | } |
1289 | 1272 | ||
1290 | l2tp_skb_set_owner_w(skb, sk); | ||
1291 | |||
1292 | l2tp_xmit_core(session, skb, fl, data_len); | 1273 | l2tp_xmit_core(session, skb, fl, data_len); |
1293 | out_unlock: | 1274 | out_unlock: |
1294 | bh_unlock_sock(sk); | 1275 | bh_unlock_sock(sk); |