aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/Kconfig1
-rw-r--r--net/Makefile1
-rw-r--r--net/core/dev.c4
-rw-r--r--net/core/ethtool.c1
-rw-r--r--net/ipv4/af_inet.c1
-rw-r--r--net/ipv4/tcp.c1
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/ipv6/ip6_offload.c1
-rw-r--r--net/ipv6/udp_offload.c3
-rw-r--r--net/mpls/Kconfig9
-rw-r--r--net/mpls/Makefile4
-rw-r--r--net/mpls/mpls_gso.c108
12 files changed, 134 insertions, 2 deletions
diff --git a/net/Kconfig b/net/Kconfig
index 08de901415ee..523e43e6da1b 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -218,6 +218,7 @@ source "net/batman-adv/Kconfig"
218source "net/openvswitch/Kconfig" 218source "net/openvswitch/Kconfig"
219source "net/vmw_vsock/Kconfig" 219source "net/vmw_vsock/Kconfig"
220source "net/netlink/Kconfig" 220source "net/netlink/Kconfig"
221source "net/mpls/Kconfig"
221 222
222config RPS 223config RPS
223 boolean 224 boolean
diff --git a/net/Makefile b/net/Makefile
index 091e7b04f301..9492e8cb64e9 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -70,3 +70,4 @@ obj-$(CONFIG_BATMAN_ADV) += batman-adv/
70obj-$(CONFIG_NFC) += nfc/ 70obj-$(CONFIG_NFC) += nfc/
71obj-$(CONFIG_OPENVSWITCH) += openvswitch/ 71obj-$(CONFIG_OPENVSWITCH) += openvswitch/
72obj-$(CONFIG_VSOCKETS) += vmw_vsock/ 72obj-$(CONFIG_VSOCKETS) += vmw_vsock/
73obj-$(CONFIG_NET_MPLS_GSO) += mpls/
diff --git a/net/core/dev.c b/net/core/dev.c
index 50c02ded1d69..2f09cb29cc95 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5277,6 +5277,10 @@ int register_netdevice(struct net_device *dev)
5277 */ 5277 */
5278 dev->hw_enc_features |= NETIF_F_SG; 5278 dev->hw_enc_features |= NETIF_F_SG;
5279 5279
5280 /* Make NETIF_F_SG inheritable to MPLS.
5281 */
5282 dev->mpls_features |= NETIF_F_SG;
5283
5280 ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev); 5284 ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev);
5281 ret = notifier_to_errno(ret); 5285 ret = notifier_to_errno(ret);
5282 if (ret) 5286 if (ret)
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 22efdaa76ebf..4e6f63ade741 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -82,6 +82,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN]
82 [NETIF_F_FSO_BIT] = "tx-fcoe-segmentation", 82 [NETIF_F_FSO_BIT] = "tx-fcoe-segmentation",
83 [NETIF_F_GSO_GRE_BIT] = "tx-gre-segmentation", 83 [NETIF_F_GSO_GRE_BIT] = "tx-gre-segmentation",
84 [NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation", 84 [NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation",
85 [NETIF_F_GSO_MPLS_BIT] = "tx-mpls-segmentation",
85 86
86 [NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc", 87 [NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc",
87 [NETIF_F_SCTP_CSUM_BIT] = "tx-checksum-sctp", 88 [NETIF_F_SCTP_CSUM_BIT] = "tx-checksum-sctp",
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index d01be2a3ae53..b05ae96aec44 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1295,6 +1295,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
1295 SKB_GSO_GRE | 1295 SKB_GSO_GRE |
1296 SKB_GSO_TCPV6 | 1296 SKB_GSO_TCPV6 |
1297 SKB_GSO_UDP_TUNNEL | 1297 SKB_GSO_UDP_TUNNEL |
1298 SKB_GSO_MPLS |
1298 0))) 1299 0)))
1299 goto out; 1300 goto out;
1300 1301
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index d87ce72ca8aa..ba4186e1dca9 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2917,6 +2917,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
2917 SKB_GSO_TCP_ECN | 2917 SKB_GSO_TCP_ECN |
2918 SKB_GSO_TCPV6 | 2918 SKB_GSO_TCPV6 |
2919 SKB_GSO_GRE | 2919 SKB_GSO_GRE |
2920 SKB_GSO_MPLS |
2920 SKB_GSO_UDP_TUNNEL | 2921 SKB_GSO_UDP_TUNNEL |
2921 0) || 2922 0) ||
2922 !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) 2923 !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))))
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 0bf5d399a03c..aa5eff46d137 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2381,7 +2381,7 @@ struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
2381 2381
2382 if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY | 2382 if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY |
2383 SKB_GSO_UDP_TUNNEL | 2383 SKB_GSO_UDP_TUNNEL |
2384 SKB_GSO_GRE) || 2384 SKB_GSO_GRE | SKB_GSO_MPLS) ||
2385 !(type & (SKB_GSO_UDP)))) 2385 !(type & (SKB_GSO_UDP))))
2386 goto out; 2386 goto out;
2387 2387
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index 71b766ee821d..a263b990ee11 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -98,6 +98,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
98 SKB_GSO_TCP_ECN | 98 SKB_GSO_TCP_ECN |
99 SKB_GSO_GRE | 99 SKB_GSO_GRE |
100 SKB_GSO_UDP_TUNNEL | 100 SKB_GSO_UDP_TUNNEL |
101 SKB_GSO_MPLS |
101 SKB_GSO_TCPV6 | 102 SKB_GSO_TCPV6 |
102 0))) 103 0)))
103 goto out; 104 goto out;
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index 3bb3a891a424..76d401a93c7a 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -63,7 +63,8 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
63 if (unlikely(type & ~(SKB_GSO_UDP | 63 if (unlikely(type & ~(SKB_GSO_UDP |
64 SKB_GSO_DODGY | 64 SKB_GSO_DODGY |
65 SKB_GSO_UDP_TUNNEL | 65 SKB_GSO_UDP_TUNNEL |
66 SKB_GSO_GRE) || 66 SKB_GSO_GRE |
67 SKB_GSO_MPLS) ||
67 !(type & (SKB_GSO_UDP)))) 68 !(type & (SKB_GSO_UDP))))
68 goto out; 69 goto out;
69 70
diff --git a/net/mpls/Kconfig b/net/mpls/Kconfig
new file mode 100644
index 000000000000..37421db88965
--- /dev/null
+++ b/net/mpls/Kconfig
@@ -0,0 +1,9 @@
1#
2# MPLS configuration
3#
4config NET_MPLS_GSO
5 tristate "MPLS: GSO support"
6 help
7 This is helper module to allow segmentation of non-MPLS GSO packets
8 that have had MPLS stack entries pushed onto them and thus
9 become MPLS GSO packets.
diff --git a/net/mpls/Makefile b/net/mpls/Makefile
new file mode 100644
index 000000000000..0a3c171be537
--- /dev/null
+++ b/net/mpls/Makefile
@@ -0,0 +1,4 @@
1#
2# Makefile for MPLS.
3#
4obj-y += mpls_gso.o
diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c
new file mode 100644
index 000000000000..1bec1219ab81
--- /dev/null
+++ b/net/mpls/mpls_gso.c
@@ -0,0 +1,108 @@
1/*
2 * MPLS GSO Support
3 *
4 * Authors: Simon Horman (horms@verge.net.au)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 * Based on: GSO portions of net/ipv4/gre.c
12 */
13
14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15
16#include <linux/err.h>
17#include <linux/module.h>
18#include <linux/netdev_features.h>
19#include <linux/netdevice.h>
20#include <linux/skbuff.h>
21
22static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
23 netdev_features_t features)
24{
25 struct sk_buff *segs = ERR_PTR(-EINVAL);
26 netdev_features_t mpls_features;
27 __be16 mpls_protocol;
28
29 if (unlikely(skb_shinfo(skb)->gso_type &
30 ~(SKB_GSO_TCPV4 |
31 SKB_GSO_TCPV6 |
32 SKB_GSO_UDP |
33 SKB_GSO_DODGY |
34 SKB_GSO_TCP_ECN |
35 SKB_GSO_GRE |
36 SKB_GSO_MPLS)))
37 goto out;
38
39 /* Setup inner SKB. */
40 mpls_protocol = skb->protocol;
41 skb->protocol = skb->inner_protocol;
42
43 /* Push back the mac header that skb_mac_gso_segment() has pulled.
44 * It will be re-pulled by the call to skb_mac_gso_segment() below
45 */
46 __skb_push(skb, skb->mac_len);
47
48 /* Segment inner packet. */
49 mpls_features = skb->dev->mpls_features & netif_skb_features(skb);
50 segs = skb_mac_gso_segment(skb, mpls_features);
51
52
53 /* Restore outer protocol. */
54 skb->protocol = mpls_protocol;
55
56 /* Re-pull the mac header that the call to skb_mac_gso_segment()
57 * above pulled. It will be re-pushed after returning
58 * skb_mac_gso_segment(), an indirect caller of this function.
59 */
60 __skb_push(skb, skb->data - skb_mac_header(skb));
61
62out:
63 return segs;
64}
65
66static int mpls_gso_send_check(struct sk_buff *skb)
67{
68 return 0;
69}
70
71static struct packet_offload mpls_mc_offload = {
72 .type = cpu_to_be16(ETH_P_MPLS_MC),
73 .callbacks = {
74 .gso_send_check = mpls_gso_send_check,
75 .gso_segment = mpls_gso_segment,
76 },
77};
78
79static struct packet_offload mpls_uc_offload = {
80 .type = cpu_to_be16(ETH_P_MPLS_UC),
81 .callbacks = {
82 .gso_send_check = mpls_gso_send_check,
83 .gso_segment = mpls_gso_segment,
84 },
85};
86
87static int __init mpls_gso_init(void)
88{
89 pr_info("MPLS GSO support\n");
90
91 dev_add_offload(&mpls_uc_offload);
92 dev_add_offload(&mpls_mc_offload);
93
94 return 0;
95}
96
97static void __exit mpls_gso_exit(void)
98{
99 dev_remove_offload(&mpls_uc_offload);
100 dev_remove_offload(&mpls_mc_offload);
101}
102
103module_init(mpls_gso_init);
104module_exit(mpls_gso_exit);
105
106MODULE_DESCRIPTION("MPLS GSO support");
107MODULE_AUTHOR("Simon Horman (horms@verge.net.au)");
108MODULE_LICENSE("GPL");