29
29
#include <linux/tcp.h> /* for tcphdr */
30
30
#include <net/ip.h>
31
31
#include <net/gue.h>
32
+ #include <net/gre.h>
32
33
#include <net/tcp.h> /* for csum_tcpudp_magic */
33
34
#include <net/udp.h>
34
35
#include <net/icmp.h> /* for icmp_send */
@@ -388,6 +389,12 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
388
389
IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM ) &&
389
390
skb -> ip_summed == CHECKSUM_PARTIAL )
390
391
mtu -= GUE_PLEN_REMCSUM + GUE_LEN_PRIV ;
392
+ } else if (dest -> tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GRE ) {
393
+ __be16 tflags = 0 ;
394
+
395
+ if (dest -> tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_CSUM )
396
+ tflags |= TUNNEL_CSUM ;
397
+ mtu -= gre_calc_hlen (tflags );
391
398
}
392
399
if (mtu < 68 ) {
393
400
IP_VS_DBG_RL ("%s(): mtu less than 68\n" , __func__ );
@@ -548,6 +555,12 @@ __ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
548
555
IP_VS_TUNNEL_ENCAP_FLAG_REMCSUM ) &&
549
556
skb -> ip_summed == CHECKSUM_PARTIAL )
550
557
mtu -= GUE_PLEN_REMCSUM + GUE_LEN_PRIV ;
558
+ } else if (dest -> tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GRE ) {
559
+ __be16 tflags = 0 ;
560
+
561
+ if (dest -> tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_CSUM )
562
+ tflags |= TUNNEL_CSUM ;
563
+ mtu -= gre_calc_hlen (tflags );
551
564
}
552
565
if (mtu < IPV6_MIN_MTU ) {
553
566
IP_VS_DBG_RL ("%s(): mtu less than %d\n" , __func__ ,
@@ -1079,6 +1092,24 @@ ipvs_gue_encap(struct net *net, struct sk_buff *skb,
1079
1092
return 0 ;
1080
1093
}
1081
1094
1095
+ static void
1096
+ ipvs_gre_encap (struct net * net , struct sk_buff * skb ,
1097
+ struct ip_vs_conn * cp , __u8 * next_protocol )
1098
+ {
1099
+ __be16 proto = * next_protocol == IPPROTO_IPIP ?
1100
+ htons (ETH_P_IP ) : htons (ETH_P_IPV6 );
1101
+ __be16 tflags = 0 ;
1102
+ size_t hdrlen ;
1103
+
1104
+ if (cp -> dest -> tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_CSUM )
1105
+ tflags |= TUNNEL_CSUM ;
1106
+
1107
+ hdrlen = gre_calc_hlen (tflags );
1108
+ gre_build_header (skb , hdrlen , tflags , proto , 0 , 0 );
1109
+
1110
+ * next_protocol = IPPROTO_GRE ;
1111
+ }
1112
+
1082
1113
/*
1083
1114
* IP Tunneling transmitter
1084
1115
*
@@ -1151,6 +1182,15 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
1151
1182
gue_hdrlen = sizeof (struct guehdr ) + gue_optlen ;
1152
1183
1153
1184
max_headroom += sizeof (struct udphdr ) + gue_hdrlen ;
1185
+ } else if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GRE ) {
1186
+ size_t gre_hdrlen ;
1187
+ __be16 tflags = 0 ;
1188
+
1189
+ if (tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_CSUM )
1190
+ tflags |= TUNNEL_CSUM ;
1191
+ gre_hdrlen = gre_calc_hlen (tflags );
1192
+
1193
+ max_headroom += gre_hdrlen ;
1154
1194
}
1155
1195
1156
1196
/* We only care about the df field if sysctl_pmtu_disc(ipvs) is set */
@@ -1172,6 +1212,11 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
1172
1212
skb -> ip_summed == CHECKSUM_PARTIAL ) {
1173
1213
gso_type |= SKB_GSO_TUNNEL_REMCSUM ;
1174
1214
}
1215
+ } else if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GRE ) {
1216
+ if (tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_CSUM )
1217
+ gso_type |= SKB_GSO_GRE_CSUM ;
1218
+ else
1219
+ gso_type |= SKB_GSO_GRE ;
1175
1220
}
1176
1221
1177
1222
if (iptunnel_handle_offloads (skb , gso_type ))
@@ -1192,8 +1237,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
1192
1237
check = true;
1193
1238
1194
1239
udp_set_csum (!check , skb , saddr , cp -> daddr .ip , skb -> len );
1195
- }
1196
-
1240
+ } else if ( tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GRE )
1241
+ ipvs_gre_encap ( net , skb , cp , & next_protocol );
1197
1242
1198
1243
skb_push (skb , sizeof (struct iphdr ));
1199
1244
skb_reset_network_header (skb );
@@ -1287,6 +1332,15 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
1287
1332
gue_hdrlen = sizeof (struct guehdr ) + gue_optlen ;
1288
1333
1289
1334
max_headroom += sizeof (struct udphdr ) + gue_hdrlen ;
1335
+ } else if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GRE ) {
1336
+ size_t gre_hdrlen ;
1337
+ __be16 tflags = 0 ;
1338
+
1339
+ if (tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_CSUM )
1340
+ tflags |= TUNNEL_CSUM ;
1341
+ gre_hdrlen = gre_calc_hlen (tflags );
1342
+
1343
+ max_headroom += gre_hdrlen ;
1290
1344
}
1291
1345
1292
1346
skb = ip_vs_prepare_tunneled_skb (skb , cp -> af , max_headroom ,
@@ -1306,6 +1360,11 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
1306
1360
skb -> ip_summed == CHECKSUM_PARTIAL ) {
1307
1361
gso_type |= SKB_GSO_TUNNEL_REMCSUM ;
1308
1362
}
1363
+ } else if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GRE ) {
1364
+ if (tun_flags & IP_VS_TUNNEL_ENCAP_FLAG_CSUM )
1365
+ gso_type |= SKB_GSO_GRE_CSUM ;
1366
+ else
1367
+ gso_type |= SKB_GSO_GRE ;
1309
1368
}
1310
1369
1311
1370
if (iptunnel_handle_offloads (skb , gso_type ))
@@ -1326,7 +1385,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
1326
1385
check = true;
1327
1386
1328
1387
udp6_set_csum (!check , skb , & saddr , & cp -> daddr .in6 , skb -> len );
1329
- }
1388
+ } else if (tun_type == IP_VS_CONN_F_TUNNEL_TYPE_GRE )
1389
+ ipvs_gre_encap (net , skb , cp , & next_protocol );
1330
1390
1331
1391
skb_push (skb , sizeof (struct ipv6hdr ));
1332
1392
skb_reset_network_header (skb );
0 commit comments