32
32
#include <linux/slab.h>
33
33
#include <linux/tcp.h> /* for tcphdr */
34
34
#include <net/ip.h>
35
+ #include <net/gue.h>
35
36
#include <net/tcp.h> /* for csum_tcpudp_magic */
36
37
#include <net/udp.h>
37
38
#include <net/icmp.h> /* for icmp_send */
@@ -382,6 +383,10 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
382
383
mtu = dst_mtu (& rt -> dst );
383
384
} else {
384
385
mtu = dst_mtu (& rt -> dst ) - sizeof (struct iphdr );
386
+ if (!dest )
387
+ goto err_put ;
388
+ if (dest -> tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE )
389
+ mtu -= sizeof (struct udphdr ) + sizeof (struct guehdr );
385
390
if (mtu < 68 ) {
386
391
IP_VS_DBG_RL ("%s(): mtu less than 68\n" , __func__ );
387
392
goto err_put ;
@@ -533,6 +538,10 @@ __ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
533
538
mtu = dst_mtu (& rt -> dst );
534
539
else {
535
540
mtu = dst_mtu (& rt -> dst ) - sizeof (struct ipv6hdr );
541
+ if (!dest )
542
+ goto err_put ;
543
+ if (dest -> tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE )
544
+ mtu -= sizeof (struct udphdr ) + sizeof (struct guehdr );
536
545
if (mtu < IPV6_MIN_MTU ) {
537
546
IP_VS_DBG_RL ("%s(): mtu less than %d\n" , __func__ ,
538
547
IPV6_MIN_MTU );
@@ -989,6 +998,41 @@ static inline int __tun_gso_type_mask(int encaps_af, int orig_af)
989
998
}
990
999
}
991
1000
1001
+ static int
1002
+ ipvs_gue_encap (struct net * net , struct sk_buff * skb ,
1003
+ struct ip_vs_conn * cp , __u8 * next_protocol )
1004
+ {
1005
+ __be16 dport ;
1006
+ __be16 sport = udp_flow_src_port (net , skb , 0 , 0 , false);
1007
+ struct udphdr * udph ; /* Our new UDP header */
1008
+ struct guehdr * gueh ; /* Our new GUE header */
1009
+
1010
+ skb_push (skb , sizeof (struct guehdr ));
1011
+
1012
+ gueh = (struct guehdr * )skb -> data ;
1013
+
1014
+ gueh -> control = 0 ;
1015
+ gueh -> version = 0 ;
1016
+ gueh -> hlen = 0 ;
1017
+ gueh -> flags = 0 ;
1018
+ gueh -> proto_ctype = * next_protocol ;
1019
+
1020
+ skb_push (skb , sizeof (struct udphdr ));
1021
+ skb_reset_transport_header (skb );
1022
+
1023
+ udph = udp_hdr (skb );
1024
+
1025
+ dport = cp -> dest -> tun_port ;
1026
+ udph -> dest = dport ;
1027
+ udph -> source = sport ;
1028
+ udph -> len = htons (skb -> len );
1029
+ udph -> check = 0 ;
1030
+
1031
+ * next_protocol = IPPROTO_UDP ;
1032
+
1033
+ return 0 ;
1034
+ }
1035
+
992
1036
/*
993
1037
* IP Tunneling transmitter
994
1038
*
@@ -1025,6 +1069,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
1025
1069
struct iphdr * iph ; /* Our new IP header */
1026
1070
unsigned int max_headroom ; /* The extra header space needed */
1027
1071
int ret , local ;
1072
+ int tun_type , gso_type ;
1028
1073
1029
1074
EnterFunction (10 );
1030
1075
@@ -1046,6 +1091,11 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
1046
1091
*/
1047
1092
max_headroom = LL_RESERVED_SPACE (tdev ) + sizeof (struct iphdr );
1048
1093
1094
+ tun_type = cp -> dest -> tun_type ;
1095
+
1096
+ if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE )
1097
+ max_headroom += sizeof (struct udphdr ) + sizeof (struct guehdr );
1098
+
1049
1099
/* We only care about the df field if sysctl_pmtu_disc(ipvs) is set */
1050
1100
dfp = sysctl_pmtu_disc (ipvs ) ? & df : NULL ;
1051
1101
skb = ip_vs_prepare_tunneled_skb (skb , cp -> af , max_headroom ,
@@ -1054,11 +1104,20 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
1054
1104
if (IS_ERR (skb ))
1055
1105
goto tx_error ;
1056
1106
1057
- if (iptunnel_handle_offloads (skb , __tun_gso_type_mask (AF_INET , cp -> af )))
1107
+ gso_type = __tun_gso_type_mask (AF_INET , cp -> af );
1108
+ if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE )
1109
+ gso_type |= SKB_GSO_UDP_TUNNEL ;
1110
+
1111
+ if (iptunnel_handle_offloads (skb , gso_type ))
1058
1112
goto tx_error ;
1059
1113
1060
1114
skb -> transport_header = skb -> network_header ;
1061
1115
1116
+ skb_set_inner_ipproto (skb , next_protocol );
1117
+
1118
+ if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE )
1119
+ ipvs_gue_encap (net , skb , cp , & next_protocol );
1120
+
1062
1121
skb_push (skb , sizeof (struct iphdr ));
1063
1122
skb_reset_network_header (skb );
1064
1123
memset (& (IPCB (skb )-> opt ), 0 , sizeof (IPCB (skb )-> opt ));
@@ -1102,6 +1161,8 @@ int
1102
1161
ip_vs_tunnel_xmit_v6 (struct sk_buff * skb , struct ip_vs_conn * cp ,
1103
1162
struct ip_vs_protocol * pp , struct ip_vs_iphdr * ipvsh )
1104
1163
{
1164
+ struct netns_ipvs * ipvs = cp -> ipvs ;
1165
+ struct net * net = ipvs -> net ;
1105
1166
struct rt6_info * rt ; /* Route to the other host */
1106
1167
struct in6_addr saddr ; /* Source for tunnel */
1107
1168
struct net_device * tdev ; /* Device to other host */
@@ -1112,10 +1173,11 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
1112
1173
struct ipv6hdr * iph ; /* Our new IP header */
1113
1174
unsigned int max_headroom ; /* The extra header space needed */
1114
1175
int ret , local ;
1176
+ int tun_type , gso_type ;
1115
1177
1116
1178
EnterFunction (10 );
1117
1179
1118
- local = __ip_vs_get_out_rt_v6 (cp -> ipvs , cp -> af , skb , cp -> dest ,
1180
+ local = __ip_vs_get_out_rt_v6 (ipvs , cp -> af , skb , cp -> dest ,
1119
1181
& cp -> daddr .in6 ,
1120
1182
& saddr , ipvsh , 1 ,
1121
1183
IP_VS_RT_MODE_LOCAL |
@@ -1134,17 +1196,31 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
1134
1196
*/
1135
1197
max_headroom = LL_RESERVED_SPACE (tdev ) + sizeof (struct ipv6hdr );
1136
1198
1199
+ tun_type = cp -> dest -> tun_type ;
1200
+
1201
+ if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE )
1202
+ max_headroom += sizeof (struct udphdr ) + sizeof (struct guehdr );
1203
+
1137
1204
skb = ip_vs_prepare_tunneled_skb (skb , cp -> af , max_headroom ,
1138
1205
& next_protocol , & payload_len ,
1139
1206
& dsfield , & ttl , NULL );
1140
1207
if (IS_ERR (skb ))
1141
1208
goto tx_error ;
1142
1209
1143
- if (iptunnel_handle_offloads (skb , __tun_gso_type_mask (AF_INET6 , cp -> af )))
1210
+ gso_type = __tun_gso_type_mask (AF_INET6 , cp -> af );
1211
+ if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE )
1212
+ gso_type |= SKB_GSO_UDP_TUNNEL ;
1213
+
1214
+ if (iptunnel_handle_offloads (skb , gso_type ))
1144
1215
goto tx_error ;
1145
1216
1146
1217
skb -> transport_header = skb -> network_header ;
1147
1218
1219
+ skb_set_inner_ipproto (skb , next_protocol );
1220
+
1221
+ if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GUE )
1222
+ ipvs_gue_encap (net , skb , cp , & next_protocol );
1223
+
1148
1224
skb_push (skb , sizeof (struct ipv6hdr ));
1149
1225
skb_reset_network_header (skb );
1150
1226
memset (& (IPCB (skb )-> opt ), 0 , sizeof (IPCB (skb )-> opt ));
@@ -1167,7 +1243,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
1167
1243
1168
1244
ret = ip_vs_tunnel_xmit_prepare (skb , cp );
1169
1245
if (ret == NF_ACCEPT )
1170
- ip6_local_out (cp -> ipvs -> net , skb -> sk , skb );
1246
+ ip6_local_out (net , skb -> sk , skb );
1171
1247
else if (ret == NF_DROP )
1172
1248
kfree_skb (skb );
1173
1249
0 commit comments