Skip to content

Commit 6a93cc9

Browse files
azhou-niciradavem330
authored andcommitted
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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent fd38441 commit 6a93cc9

File tree

3 files changed

+151
-1
lines changed

3 files changed

+151
-1
lines changed

include/net/udp_tunnel.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
#ifndef __NET_UDP_TUNNEL_H
22
#define __NET_UDP_TUNNEL_H
33

4+
#include <net/ip_tunnels.h>
5+
#include <net/udp.h>
6+
7+
#if IS_ENABLED(CONFIG_IPV6)
8+
#include <net/ipv6.h>
9+
#include <net/addrconf.h>
10+
#endif
11+
412
struct udp_port_cfg {
513
u8 family;
614

@@ -53,4 +61,53 @@ static inline int udp_sock_create(struct net *net,
5361
return -EPFNOSUPPORT;
5462
}
5563

64+
typedef int (*udp_tunnel_encap_rcv_t)(struct sock *sk, struct sk_buff *skb);
65+
typedef void (*udp_tunnel_encap_destroy_t)(struct sock *sk);
66+
67+
struct udp_tunnel_sock_cfg {
68+
void *sk_user_data; /* user data used by encap_rcv call back */
69+
/* Used for setting up udp_sock fields, see udp.h for details */
70+
__u8 encap_type;
71+
udp_tunnel_encap_rcv_t encap_rcv;
72+
udp_tunnel_encap_destroy_t encap_destroy;
73+
};
74+
75+
/* Setup the given (UDP) sock to receive UDP encapsulated packets */
76+
void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
77+
struct udp_tunnel_sock_cfg *sock_cfg);
78+
79+
/* Transmit the skb using UDP encapsulation. */
80+
int udp_tunnel_xmit_skb(struct socket *sock, struct rtable *rt,
81+
struct sk_buff *skb, __be32 src, __be32 dst,
82+
__u8 tos, __u8 ttl, __be16 df, __be16 src_port,
83+
__be16 dst_port, bool xnet);
84+
85+
#if IS_ENABLED(CONFIG_IPV6)
86+
int udp_tunnel6_xmit_skb(struct socket *sock, struct dst_entry *dst,
87+
struct sk_buff *skb, struct net_device *dev,
88+
struct in6_addr *saddr, struct in6_addr *daddr,
89+
__u8 prio, __u8 ttl, __be16 src_port,
90+
__be16 dst_port);
91+
#endif
92+
93+
void udp_tunnel_sock_release(struct socket *sock);
94+
95+
static inline struct sk_buff *udp_tunnel_handle_offloads(struct sk_buff *skb,
96+
bool udp_csum)
97+
{
98+
int type = udp_csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;
99+
100+
return iptunnel_handle_offloads(skb, udp_csum, type);
101+
}
102+
103+
static inline void udp_tunnel_encap_enable(struct socket *sock)
104+
{
105+
#if IS_ENABLED(CONFIG_IPV6)
106+
if (sock->sk->sk_family == PF_INET6)
107+
ipv6_stub->udpv6_encap_enable();
108+
else
109+
#endif
110+
udp_encap_enable();
111+
}
112+
56113
#endif

net/ipv4/udp_tunnel.c

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
1212
struct socket **sockp)
1313
{
14-
int err = -EINVAL;
14+
int err;
1515
struct socket *sock = NULL;
1616
struct sockaddr_in udp_addr;
1717

@@ -54,4 +54,55 @@ int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
5454
}
5555
EXPORT_SYMBOL(udp_sock_create4);
5656

57+
void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
58+
struct udp_tunnel_sock_cfg *cfg)
59+
{
60+
struct sock *sk = sock->sk;
61+
62+
/* Disable multicast loopback */
63+
inet_sk(sk)->mc_loop = 0;
64+
65+
/* Enable CHECKSUM_UNNECESSARY to CHECKSUM_COMPLETE conversion */
66+
udp_set_convert_csum(sk, true);
67+
68+
rcu_assign_sk_user_data(sk, cfg->sk_user_data);
69+
70+
udp_sk(sk)->encap_type = cfg->encap_type;
71+
udp_sk(sk)->encap_rcv = cfg->encap_rcv;
72+
udp_sk(sk)->encap_destroy = cfg->encap_destroy;
73+
74+
udp_tunnel_encap_enable(sock);
75+
}
76+
EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock);
77+
78+
int udp_tunnel_xmit_skb(struct socket *sock, struct rtable *rt,
79+
struct sk_buff *skb, __be32 src, __be32 dst,
80+
__u8 tos, __u8 ttl, __be16 df, __be16 src_port,
81+
__be16 dst_port, bool xnet)
82+
{
83+
struct udphdr *uh;
84+
85+
__skb_push(skb, sizeof(*uh));
86+
skb_reset_transport_header(skb);
87+
uh = udp_hdr(skb);
88+
89+
uh->dest = dst_port;
90+
uh->source = src_port;
91+
uh->len = htons(skb->len);
92+
93+
udp_set_csum(sock->sk->sk_no_check_tx, skb, src, dst, skb->len);
94+
95+
return iptunnel_xmit(sock->sk, rt, skb, src, dst, IPPROTO_UDP,
96+
tos, ttl, df, xnet);
97+
}
98+
EXPORT_SYMBOL_GPL(udp_tunnel_xmit_skb);
99+
100+
void udp_tunnel_sock_release(struct socket *sock)
101+
{
102+
rcu_assign_sk_user_data(sock->sk, NULL);
103+
kernel_sock_shutdown(sock, SHUT_RDWR);
104+
sk_release_kernel(sock->sk);
105+
}
106+
EXPORT_SYMBOL_GPL(udp_tunnel_sock_release);
107+
57108
MODULE_LICENSE("GPL");

net/ipv6/ip6_udp_tunnel.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,45 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg,
6161
return err;
6262
}
6363
EXPORT_SYMBOL_GPL(udp_sock_create6);
64+
65+
int udp_tunnel6_xmit_skb(struct socket *sock, struct dst_entry *dst,
66+
struct sk_buff *skb, struct net_device *dev,
67+
struct in6_addr *saddr, struct in6_addr *daddr,
68+
__u8 prio, __u8 ttl, __be16 src_port, __be16 dst_port)
69+
{
70+
struct udphdr *uh;
71+
struct ipv6hdr *ip6h;
72+
struct sock *sk = sock->sk;
73+
74+
__skb_push(skb, sizeof(*uh));
75+
skb_reset_transport_header(skb);
76+
uh = udp_hdr(skb);
77+
78+
uh->dest = dst_port;
79+
uh->source = src_port;
80+
81+
uh->len = htons(skb->len);
82+
uh->check = 0;
83+
84+
memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
85+
IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED
86+
| IPSKB_REROUTED);
87+
skb_dst_set(skb, dst);
88+
89+
udp6_set_csum(udp_get_no_check6_tx(sk), skb, &inet6_sk(sk)->saddr,
90+
&sk->sk_v6_daddr, skb->len);
91+
92+
__skb_push(skb, sizeof(*ip6h));
93+
skb_reset_network_header(skb);
94+
ip6h = ipv6_hdr(skb);
95+
ip6_flow_hdr(ip6h, prio, htonl(0));
96+
ip6h->payload_len = htons(skb->len);
97+
ip6h->nexthdr = IPPROTO_UDP;
98+
ip6h->hop_limit = ttl;
99+
ip6h->daddr = *daddr;
100+
ip6h->saddr = *saddr;
101+
102+
ip6tunnel_xmit(skb, dev);
103+
return 0;
104+
}
105+
EXPORT_SYMBOL_GPL(udp_tunnel6_xmit_skb);

0 commit comments

Comments
 (0)