18024e028STom Herbert #ifndef __NET_UDP_TUNNEL_H 28024e028STom Herbert #define __NET_UDP_TUNNEL_H 38024e028STom Herbert 46a93cc90SAndy Zhou #include <net/ip_tunnels.h> 56a93cc90SAndy Zhou #include <net/udp.h> 66a93cc90SAndy Zhou 76a93cc90SAndy Zhou #if IS_ENABLED(CONFIG_IPV6) 86a93cc90SAndy Zhou #include <net/ipv6.h> 96a93cc90SAndy Zhou #include <net/addrconf.h> 106a93cc90SAndy Zhou #endif 116a93cc90SAndy Zhou 128024e028STom Herbert struct udp_port_cfg { 138024e028STom Herbert u8 family; 148024e028STom Herbert 158024e028STom Herbert /* Used only for kernel-created sockets */ 168024e028STom Herbert union { 178024e028STom Herbert struct in_addr local_ip; 188024e028STom Herbert #if IS_ENABLED(CONFIG_IPV6) 198024e028STom Herbert struct in6_addr local_ip6; 208024e028STom Herbert #endif 218024e028STom Herbert }; 228024e028STom Herbert 238024e028STom Herbert union { 248024e028STom Herbert struct in_addr peer_ip; 258024e028STom Herbert #if IS_ENABLED(CONFIG_IPV6) 268024e028STom Herbert struct in6_addr peer_ip6; 278024e028STom Herbert #endif 288024e028STom Herbert }; 298024e028STom Herbert 308024e028STom Herbert __be16 local_udp_port; 318024e028STom Herbert __be16 peer_udp_port; 328024e028STom Herbert unsigned int use_udp_checksums:1, 338024e028STom Herbert use_udp6_tx_checksums:1, 34a43a9ef6SJiri Benc use_udp6_rx_checksums:1, 35a43a9ef6SJiri Benc ipv6_v6only:1; 368024e028STom Herbert }; 378024e028STom Herbert 38fd384412SAndy Zhou int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg, 398024e028STom Herbert struct socket **sockp); 408024e028STom Herbert 41fd384412SAndy Zhou #if IS_ENABLED(CONFIG_IPV6) 42fd384412SAndy Zhou int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, 43fd384412SAndy Zhou struct socket **sockp); 44fd384412SAndy Zhou #else 45fd384412SAndy Zhou static inline int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, 46fd384412SAndy Zhou struct socket **sockp) 47fd384412SAndy Zhou { 48fd384412SAndy Zhou return 0; 49fd384412SAndy Zhou } 50fd384412SAndy Zhou #endif 51fd384412SAndy Zhou 52fd384412SAndy Zhou static inline int udp_sock_create(struct net *net, 53fd384412SAndy Zhou struct udp_port_cfg *cfg, 54fd384412SAndy Zhou struct socket **sockp) 55fd384412SAndy Zhou { 56fd384412SAndy Zhou if (cfg->family == AF_INET) 57fd384412SAndy Zhou return udp_sock_create4(net, cfg, sockp); 58fd384412SAndy Zhou 59fd384412SAndy Zhou if (cfg->family == AF_INET6) 60fd384412SAndy Zhou return udp_sock_create6(net, cfg, sockp); 61fd384412SAndy Zhou 62fd384412SAndy Zhou return -EPFNOSUPPORT; 63fd384412SAndy Zhou } 64fd384412SAndy Zhou 656a93cc90SAndy Zhou typedef int (*udp_tunnel_encap_rcv_t)(struct sock *sk, struct sk_buff *skb); 666a93cc90SAndy Zhou typedef void (*udp_tunnel_encap_destroy_t)(struct sock *sk); 676a93cc90SAndy Zhou 686a93cc90SAndy Zhou struct udp_tunnel_sock_cfg { 696a93cc90SAndy Zhou void *sk_user_data; /* user data used by encap_rcv call back */ 706a93cc90SAndy Zhou /* Used for setting up udp_sock fields, see udp.h for details */ 716a93cc90SAndy Zhou __u8 encap_type; 726a93cc90SAndy Zhou udp_tunnel_encap_rcv_t encap_rcv; 736a93cc90SAndy Zhou udp_tunnel_encap_destroy_t encap_destroy; 746a93cc90SAndy Zhou }; 756a93cc90SAndy Zhou 766a93cc90SAndy Zhou /* Setup the given (UDP) sock to receive UDP encapsulated packets */ 776a93cc90SAndy Zhou void setup_udp_tunnel_sock(struct net *net, struct socket *sock, 786a93cc90SAndy Zhou struct udp_tunnel_sock_cfg *sock_cfg); 796a93cc90SAndy Zhou 806a93cc90SAndy Zhou /* Transmit the skb using UDP encapsulation. */ 8179b16aadSDavid Miller int udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb, 82d998f8efSTom Herbert __be32 src, __be32 dst, __u8 tos, __u8 ttl, 83d998f8efSTom Herbert __be16 df, __be16 src_port, __be16 dst_port, 84d998f8efSTom Herbert bool xnet, bool nocheck); 856a93cc90SAndy Zhou 866a93cc90SAndy Zhou #if IS_ENABLED(CONFIG_IPV6) 8779b16aadSDavid Miller int udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk, 8879b16aadSDavid Miller struct sk_buff *skb, 89d998f8efSTom Herbert struct net_device *dev, struct in6_addr *saddr, 90d998f8efSTom Herbert struct in6_addr *daddr, 916a93cc90SAndy Zhou __u8 prio, __u8 ttl, __be16 src_port, 92d998f8efSTom Herbert __be16 dst_port, bool nocheck); 936a93cc90SAndy Zhou #endif 946a93cc90SAndy Zhou 956a93cc90SAndy Zhou void udp_tunnel_sock_release(struct socket *sock); 966a93cc90SAndy Zhou 97c29a70d2SPravin B Shelar struct metadata_dst *udp_tun_rx_dst(struct sk_buff *skb, unsigned short family, 98c29a70d2SPravin B Shelar __be16 flags, __be64 tunnel_id, 99c29a70d2SPravin B Shelar int md_size); 100c29a70d2SPravin B Shelar 1016a93cc90SAndy Zhou static inline struct sk_buff *udp_tunnel_handle_offloads(struct sk_buff *skb, 1026a93cc90SAndy Zhou bool udp_csum) 1036a93cc90SAndy Zhou { 1046a93cc90SAndy Zhou int type = udp_csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; 1056a93cc90SAndy Zhou 1066a93cc90SAndy Zhou return iptunnel_handle_offloads(skb, udp_csum, type); 1076a93cc90SAndy Zhou } 1086a93cc90SAndy Zhou 109cfdf1e1bSJesse Gross static inline void udp_tunnel_gro_complete(struct sk_buff *skb, int nhoff) 110cfdf1e1bSJesse Gross { 111cfdf1e1bSJesse Gross struct udphdr *uh; 112cfdf1e1bSJesse Gross 113cfdf1e1bSJesse Gross uh = (struct udphdr *)(skb->data + nhoff - sizeof(struct udphdr)); 114cfdf1e1bSJesse Gross skb_shinfo(skb)->gso_type |= uh->check ? 115cfdf1e1bSJesse Gross SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; 116cfdf1e1bSJesse Gross } 117cfdf1e1bSJesse Gross 1186a93cc90SAndy Zhou static inline void udp_tunnel_encap_enable(struct socket *sock) 1196a93cc90SAndy Zhou { 1206a93cc90SAndy Zhou #if IS_ENABLED(CONFIG_IPV6) 1216a93cc90SAndy Zhou if (sock->sk->sk_family == PF_INET6) 1226a93cc90SAndy Zhou ipv6_stub->udpv6_encap_enable(); 1236a93cc90SAndy Zhou else 1246a93cc90SAndy Zhou #endif 1256a93cc90SAndy Zhou udp_encap_enable(); 1266a93cc90SAndy Zhou } 1276a93cc90SAndy Zhou 1288024e028STom Herbert #endif 129