diff options
author | Tom Parkin <tparkin@katalix.com> | 2013-03-19 02:11:12 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-03-20 12:10:38 -0400 |
commit | 44046a593eb770dbecdabf1c82bcd252f2a8337b (patch) | |
tree | 1f8db140d6f920d0abad4a072c8f2d85a6e6ca9b | |
parent | f1e79e208076ffe7bad97158275f1c572c04f5c7 (diff) |
udp: add encap_destroy callback
Users of udp encapsulation currently have an encap_rcv callback which they can
use to hook into the udp receive path.
In situations where a encapsulation user allocates resources associated with a
udp encap socket, it may be convenient to be able to also hook the proto
.destroy operation. For example, if an encap user holds a reference to the
udp socket, the destroy hook might be used to relinquish this reference.
This patch adds a socket destroy hook into udp, which is set and enabled
in the same way as the existing encap_rcv hook.
Signed-off-by: Tom Parkin <tparkin@katalix.com>
Signed-off-by: James Chapman <jchapman@katalix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/udp.h | 1 | ||||
-rw-r--r-- | net/ipv4/udp.c | 7 | ||||
-rw-r--r-- | net/ipv6/udp.c | 8 |
3 files changed, 16 insertions, 0 deletions
diff --git a/include/linux/udp.h b/include/linux/udp.h index 9d81de123c90..42278bbf7a88 100644 --- a/include/linux/udp.h +++ b/include/linux/udp.h | |||
@@ -68,6 +68,7 @@ struct udp_sock { | |||
68 | * For encapsulation sockets. | 68 | * For encapsulation sockets. |
69 | */ | 69 | */ |
70 | int (*encap_rcv)(struct sock *sk, struct sk_buff *skb); | 70 | int (*encap_rcv)(struct sock *sk, struct sk_buff *skb); |
71 | void (*encap_destroy)(struct sock *sk); | ||
71 | }; | 72 | }; |
72 | 73 | ||
73 | static inline struct udp_sock *udp_sk(const struct sock *sk) | 74 | static inline struct udp_sock *udp_sk(const struct sock *sk) |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 265c42cf963c..0a073a263720 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1762,9 +1762,16 @@ int udp_rcv(struct sk_buff *skb) | |||
1762 | 1762 | ||
1763 | void udp_destroy_sock(struct sock *sk) | 1763 | void udp_destroy_sock(struct sock *sk) |
1764 | { | 1764 | { |
1765 | struct udp_sock *up = udp_sk(sk); | ||
1765 | bool slow = lock_sock_fast(sk); | 1766 | bool slow = lock_sock_fast(sk); |
1766 | udp_flush_pending_frames(sk); | 1767 | udp_flush_pending_frames(sk); |
1767 | unlock_sock_fast(sk, slow); | 1768 | unlock_sock_fast(sk, slow); |
1769 | if (static_key_false(&udp_encap_needed) && up->encap_type) { | ||
1770 | void (*encap_destroy)(struct sock *sk); | ||
1771 | encap_destroy = ACCESS_ONCE(up->encap_destroy); | ||
1772 | if (encap_destroy) | ||
1773 | encap_destroy(sk); | ||
1774 | } | ||
1768 | } | 1775 | } |
1769 | 1776 | ||
1770 | /* | 1777 | /* |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 599e1ba6d1ce..d8e5e852fc7a 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -1285,10 +1285,18 @@ do_confirm: | |||
1285 | 1285 | ||
1286 | void udpv6_destroy_sock(struct sock *sk) | 1286 | void udpv6_destroy_sock(struct sock *sk) |
1287 | { | 1287 | { |
1288 | struct udp_sock *up = udp_sk(sk); | ||
1288 | lock_sock(sk); | 1289 | lock_sock(sk); |
1289 | udp_v6_flush_pending_frames(sk); | 1290 | udp_v6_flush_pending_frames(sk); |
1290 | release_sock(sk); | 1291 | release_sock(sk); |
1291 | 1292 | ||
1293 | if (static_key_false(&udpv6_encap_needed) && up->encap_type) { | ||
1294 | void (*encap_destroy)(struct sock *sk); | ||
1295 | encap_destroy = ACCESS_ONCE(up->encap_destroy); | ||
1296 | if (encap_destroy) | ||
1297 | encap_destroy(sk); | ||
1298 | } | ||
1299 | |||
1292 | inet6_destroy_sock(sk); | 1300 | inet6_destroy_sock(sk); |
1293 | } | 1301 | } |
1294 | 1302 | ||