]>
Commit | Line | Data |
---|---|---|
eb6eebd2 JG |
1 | #ifndef __NET_UDP_TUNNEL_WRAPPER_H |
2 | #define __NET_UDP_TUNNEL_WRAPPER_H | |
3 | ||
4 | #include <linux/version.h> | |
5 | #include <linux/kconfig.h> | |
6 | ||
e23775f2 PS |
7 | #include <net/dst_metadata.h> |
8 | #include <linux/netdev_features.h> | |
9 | #ifdef HAVE_UDP_TUNNEL_IPV6 | |
eb6eebd2 | 10 | #include_next <net/udp_tunnel.h> |
a42ec67e JG |
11 | |
12 | static inline struct sk_buff * | |
13 | rpl_udp_tunnel_handle_offloads(struct sk_buff *skb, bool udp_csum, | |
e23775f2 | 14 | int type, bool is_vxlan) |
a42ec67e JG |
15 | { |
16 | if (skb_is_gso(skb) && skb_is_encapsulated(skb)) { | |
17 | kfree_skb(skb); | |
18 | return ERR_PTR(-ENOSYS); | |
19 | } | |
20 | return udp_tunnel_handle_offloads(skb, udp_csum); | |
21 | } | |
22 | #define udp_tunnel_handle_offloads rpl_udp_tunnel_handle_offloads | |
23 | ||
eb6eebd2 JG |
24 | #else |
25 | ||
a42ec67e JG |
26 | #include <net/ip_tunnels.h> |
27 | #include <net/udp.h> | |
28 | ||
eb6eebd2 JG |
29 | struct udp_port_cfg { |
30 | u8 family; | |
31 | ||
32 | /* Used only for kernel-created sockets */ | |
33 | union { | |
34 | struct in_addr local_ip; | |
35 | #if IS_ENABLED(CONFIG_IPV6) | |
36 | struct in6_addr local_ip6; | |
37 | #endif | |
38 | }; | |
39 | ||
40 | union { | |
41 | struct in_addr peer_ip; | |
42 | #if IS_ENABLED(CONFIG_IPV6) | |
43 | struct in6_addr peer_ip6; | |
44 | #endif | |
45 | }; | |
46 | ||
47 | __be16 local_udp_port; | |
48 | __be16 peer_udp_port; | |
49 | unsigned int use_udp_checksums:1, | |
50 | use_udp6_tx_checksums:1, | |
e23775f2 PS |
51 | use_udp6_rx_checksums:1, |
52 | ipv6_v6only:1; | |
eb6eebd2 JG |
53 | }; |
54 | ||
4adb03cb | 55 | #define udp_sock_create rpl_udp_sock_create |
bedf02f4 AW |
56 | int rpl_udp_sock_create(struct net *net, struct udp_port_cfg *cfg, |
57 | struct socket **sockp); | |
eb6eebd2 | 58 | |
a42ec67e JG |
59 | typedef int (*udp_tunnel_encap_rcv_t)(struct sock *sk, struct sk_buff *skb); |
60 | typedef void (*udp_tunnel_encap_destroy_t)(struct sock *sk); | |
61 | ||
62 | struct udp_tunnel_sock_cfg { | |
63 | void *sk_user_data; /* user data used by encap_rcv call back */ | |
64 | /* Used for setting up udp_sock fields, see udp.h for details */ | |
65 | __u8 encap_type; | |
66 | udp_tunnel_encap_rcv_t encap_rcv; | |
67 | udp_tunnel_encap_destroy_t encap_destroy; | |
68 | }; | |
69 | ||
70 | /* Setup the given (UDP) sock to receive UDP encapsulated packets */ | |
bedf02f4 AW |
71 | #define setup_udp_tunnel_sock rpl_setup_udp_tunnel_sock |
72 | void rpl_setup_udp_tunnel_sock(struct net *net, struct socket *sock, | |
73 | struct udp_tunnel_sock_cfg *sock_cfg); | |
a42ec67e JG |
74 | |
75 | /* Transmit the skb using UDP encapsulation. */ | |
bedf02f4 | 76 | #define udp_tunnel_xmit_skb rpl_udp_tunnel_xmit_skb |
c0cddcec JS |
77 | int rpl_udp_tunnel_xmit_skb(struct rtable *rt, |
78 | struct sock *sk, struct sk_buff *skb, | |
bedf02f4 AW |
79 | __be32 src, __be32 dst, __u8 tos, __u8 ttl, |
80 | __be16 df, __be16 src_port, __be16 dst_port, | |
81 | bool xnet, bool nocheck); | |
7bdcee3e | 82 | |
a42ec67e | 83 | |
bedf02f4 AW |
84 | #define udp_tunnel_sock_release rpl_udp_tunnel_sock_release |
85 | void rpl_udp_tunnel_sock_release(struct socket *sock); | |
a42ec67e JG |
86 | |
87 | void ovs_udp_gso(struct sk_buff *skb); | |
88 | void ovs_udp_csum_gso(struct sk_buff *skb); | |
89 | ||
e23775f2 | 90 | #define udp_tunnel_encap_enable(sock) udp_encap_enable() |
a42ec67e JG |
91 | static inline struct sk_buff *udp_tunnel_handle_offloads(struct sk_buff *skb, |
92 | bool udp_csum, | |
e23775f2 | 93 | int type, |
a42ec67e JG |
94 | bool is_vxlan) |
95 | { | |
a42ec67e JG |
96 | void (*fix_segment)(struct sk_buff *); |
97 | ||
e23775f2 PS |
98 | if (skb_is_gso(skb) && skb_is_encapsulated(skb)) { |
99 | kfree_skb(skb); | |
100 | return ERR_PTR(-ENOSYS); | |
101 | } | |
102 | ||
103 | type |= udp_csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; | |
a42ec67e JG |
104 | if (!udp_csum) |
105 | fix_segment = ovs_udp_gso; | |
106 | else | |
107 | fix_segment = ovs_udp_csum_gso; | |
108 | ||
109 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) | |
110 | if (!is_vxlan) | |
111 | type = 0; | |
112 | #endif | |
113 | ||
114 | return ovs_iptunnel_handle_offloads(skb, udp_csum, type, fix_segment); | |
115 | } | |
116 | ||
e23775f2 PS |
117 | #if IS_ENABLED(CONFIG_IPV6) |
118 | #define udp_tunnel6_xmit_skb rpl_udp_tunnel6_xmit_skb | |
119 | int rpl_udp_tunnel6_xmit_skb(struct dst_entry *dst, struct sock *sk, | |
120 | struct sk_buff *skb, | |
121 | struct net_device *dev, struct in6_addr *saddr, | |
122 | struct in6_addr *daddr, | |
123 | __u8 prio, __u8 ttl, __be16 src_port, | |
124 | __be16 dst_port, bool nocheck); | |
125 | #endif | |
126 | ||
127 | static inline void udp_tunnel_gro_complete(struct sk_buff *skb, int nhoff) | |
128 | { | |
129 | struct udphdr *uh; | |
130 | ||
131 | uh = (struct udphdr *)(skb->data + nhoff - sizeof(struct udphdr)); | |
132 | skb_shinfo(skb)->gso_type |= uh->check ? | |
133 | SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; | |
134 | } | |
135 | #endif | |
136 | ||
137 | static inline void ovs_udp_tun_rx_dst(struct ip_tunnel_info *info, | |
138 | struct sk_buff *skb, | |
139 | unsigned short family, | |
140 | __be16 flags, __be64 tunnel_id, int md_size) | |
141 | { | |
142 | if (family == AF_INET) | |
143 | ovs_ip_tun_rx_dst(info, skb, flags, tunnel_id, md_size); | |
144 | ||
145 | info->key.tp_src = udp_hdr(skb)->source; | |
146 | info->key.tp_dst = udp_hdr(skb)->dest; | |
147 | if (udp_hdr(skb)->check) | |
148 | info->key.tun_flags |= TUNNEL_CSUM; | |
149 | } | |
a42ec67e | 150 | |
eb6eebd2 | 151 | #endif |