diff options
author | Andy Zhou <azhou@nicira.com> | 2014-09-17 04:31:17 +0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-19 23:57:15 +0400 |
commit | 6a93cc9052748c6355ec9d5b6c38b77f85f1cb0d (patch) | |
tree | 4855feb2fa46451d755bf841a3e463ba2a8053a0 /net/ipv4 | |
parent | fd384412e199b62c3ddaabd18dce86d0e164c5b9 (diff) | |
download | linux-6a93cc9052748c6355ec9d5b6c38b77f85f1cb0d.tar.xz |
udp-tunnel: Add a few more UDP tunnel APIs
Added a few more UDP tunnel APIs that can be shared by UDP based
tunnel protocol implementation. The main ones are highlighted below.
setup_udp_tunnel_sock() configures UDP listener socket for
receiving UDP encapsulated packets.
udp_tunnel_xmit_skb() and upd_tunnel6_xmit_skb() transmit skb
using UDP encapsulation.
udp_tunnel_sock_release() closes the UDP tunnel listener socket.
Signed-off-by: Andy Zhou <azhou@nicira.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/udp_tunnel.c | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/net/ipv4/udp_tunnel.c b/net/ipv4/udp_tunnel.c index 7fccf6c3417a..1671263e5fa0 100644 --- a/net/ipv4/udp_tunnel.c +++ b/net/ipv4/udp_tunnel.c @@ -11,7 +11,7 @@ int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg, struct socket **sockp) { - int err = -EINVAL; + int err; struct socket *sock = NULL; struct sockaddr_in udp_addr; @@ -54,4 +54,55 @@ error: } EXPORT_SYMBOL(udp_sock_create4); +void setup_udp_tunnel_sock(struct net *net, struct socket *sock, + struct udp_tunnel_sock_cfg *cfg) +{ + struct sock *sk = sock->sk; + + /* Disable multicast loopback */ + inet_sk(sk)->mc_loop = 0; + + /* Enable CHECKSUM_UNNECESSARY to CHECKSUM_COMPLETE conversion */ + udp_set_convert_csum(sk, true); + + rcu_assign_sk_user_data(sk, cfg->sk_user_data); + + udp_sk(sk)->encap_type = cfg->encap_type; + udp_sk(sk)->encap_rcv = cfg->encap_rcv; + udp_sk(sk)->encap_destroy = cfg->encap_destroy; + + udp_tunnel_encap_enable(sock); +} +EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock); + +int udp_tunnel_xmit_skb(struct socket *sock, struct rtable *rt, + struct sk_buff *skb, __be32 src, __be32 dst, + __u8 tos, __u8 ttl, __be16 df, __be16 src_port, + __be16 dst_port, bool xnet) +{ + struct udphdr *uh; + + __skb_push(skb, sizeof(*uh)); + skb_reset_transport_header(skb); + uh = udp_hdr(skb); + + uh->dest = dst_port; + uh->source = src_port; + uh->len = htons(skb->len); + + udp_set_csum(sock->sk->sk_no_check_tx, skb, src, dst, skb->len); + + return iptunnel_xmit(sock->sk, rt, skb, src, dst, IPPROTO_UDP, + tos, ttl, df, xnet); +} +EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb); + +void udp_tunnel_sock_release(struct socket *sock) +{ + rcu_assign_sk_user_data(sock->sk, NULL); + kernel_sock_shutdown(sock, SHUT_RDWR); + sk_release_kernel(sock->sk); +} +EXPORT_SYMBOL_GPL(udp_tunnel_sock_release); + MODULE_LICENSE("GPL"); |