aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/af_inet.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/af_inet.c')
-rw-r--r--net/ipv4/af_inet.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 4f8cd4fc451d..4049906010f7 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1273,16 +1273,17 @@ out:
1273} 1273}
1274 1274
1275static struct sk_buff *inet_gso_segment(struct sk_buff *skb, 1275static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
1276 netdev_features_t features) 1276 netdev_features_t features)
1277{ 1277{
1278 struct sk_buff *segs = ERR_PTR(-EINVAL); 1278 struct sk_buff *segs = ERR_PTR(-EINVAL);
1279 const struct net_offload *ops; 1279 const struct net_offload *ops;
1280 unsigned int offset = 0;
1280 struct iphdr *iph; 1281 struct iphdr *iph;
1282 bool tunnel;
1281 int proto; 1283 int proto;
1284 int nhoff;
1282 int ihl; 1285 int ihl;
1283 int id; 1286 int id;
1284 unsigned int offset = 0;
1285 bool tunnel;
1286 1287
1287 if (unlikely(skb_shinfo(skb)->gso_type & 1288 if (unlikely(skb_shinfo(skb)->gso_type &
1288 ~(SKB_GSO_TCPV4 | 1289 ~(SKB_GSO_TCPV4 |
@@ -1290,12 +1291,15 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
1290 SKB_GSO_DODGY | 1291 SKB_GSO_DODGY |
1291 SKB_GSO_TCP_ECN | 1292 SKB_GSO_TCP_ECN |
1292 SKB_GSO_GRE | 1293 SKB_GSO_GRE |
1294 SKB_GSO_IPIP |
1293 SKB_GSO_TCPV6 | 1295 SKB_GSO_TCPV6 |
1294 SKB_GSO_UDP_TUNNEL | 1296 SKB_GSO_UDP_TUNNEL |
1295 SKB_GSO_MPLS | 1297 SKB_GSO_MPLS |
1296 0))) 1298 0)))
1297 goto out; 1299 goto out;
1298 1300
1301 skb_reset_network_header(skb);
1302 nhoff = skb_network_header(skb) - skb_mac_header(skb);
1299 if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) 1303 if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
1300 goto out; 1304 goto out;
1301 1305
@@ -1312,7 +1316,10 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
1312 goto out; 1316 goto out;
1313 __skb_pull(skb, ihl); 1317 __skb_pull(skb, ihl);
1314 1318
1315 tunnel = !!skb->encapsulation; 1319 tunnel = SKB_GSO_CB(skb)->encap_level > 0;
1320 if (tunnel)
1321 features = skb->dev->hw_enc_features & netif_skb_features(skb);
1322 SKB_GSO_CB(skb)->encap_level += ihl;
1316 1323
1317 skb_reset_transport_header(skb); 1324 skb_reset_transport_header(skb);
1318 1325
@@ -1327,18 +1334,23 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
1327 1334
1328 skb = segs; 1335 skb = segs;
1329 do { 1336 do {
1330 iph = ip_hdr(skb); 1337 iph = (struct iphdr *)(skb_mac_header(skb) + nhoff);
1331 if (!tunnel && proto == IPPROTO_UDP) { 1338 if (!tunnel && proto == IPPROTO_UDP) {
1332 iph->id = htons(id); 1339 iph->id = htons(id);
1333 iph->frag_off = htons(offset >> 3); 1340 iph->frag_off = htons(offset >> 3);
1334 if (skb->next != NULL) 1341 if (skb->next != NULL)
1335 iph->frag_off |= htons(IP_MF); 1342 iph->frag_off |= htons(IP_MF);
1336 offset += (skb->len - skb->mac_len - iph->ihl * 4); 1343 offset += skb->len - nhoff - ihl;
1337 } else { 1344 } else {
1338 iph->id = htons(id++); 1345 iph->id = htons(id++);
1339 } 1346 }
1340 iph->tot_len = htons(skb->len - skb->mac_len); 1347 iph->tot_len = htons(skb->len - nhoff);
1341 ip_send_check(iph); 1348 ip_send_check(iph);
1349 if (tunnel) {
1350 skb_reset_inner_headers(skb);
1351 skb->encapsulation = 1;
1352 }
1353 skb->network_header = (u8 *)iph - skb->head;
1342 } while ((skb = skb->next)); 1354 } while ((skb = skb->next));
1343 1355
1344out: 1356out:
@@ -1645,6 +1657,13 @@ static struct packet_offload ip_packet_offload __read_mostly = {
1645 }, 1657 },
1646}; 1658};
1647 1659
1660static const struct net_offload ipip_offload = {
1661 .callbacks = {
1662 .gso_send_check = inet_gso_send_check,
1663 .gso_segment = inet_gso_segment,
1664 },
1665};
1666
1648static int __init ipv4_offload_init(void) 1667static int __init ipv4_offload_init(void)
1649{ 1668{
1650 /* 1669 /*
@@ -1656,6 +1675,7 @@ static int __init ipv4_offload_init(void)
1656 pr_crit("%s: Cannot add TCP protocol offload\n", __func__); 1675 pr_crit("%s: Cannot add TCP protocol offload\n", __func__);
1657 1676
1658 dev_add_offload(&ip_packet_offload); 1677 dev_add_offload(&ip_packet_offload);
1678 inet_add_offload(&ipip_offload, IPPROTO_IPIP);
1659 return 0; 1679 return 0;
1660} 1680}
1661 1681