diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/Kconfig | 1 | ||||
| -rw-r--r-- | net/Makefile | 1 | ||||
| -rw-r--r-- | net/core/dev.c | 4 | ||||
| -rw-r--r-- | net/core/ethtool.c | 1 | ||||
| -rw-r--r-- | net/ipv4/af_inet.c | 1 | ||||
| -rw-r--r-- | net/ipv4/tcp.c | 1 | ||||
| -rw-r--r-- | net/ipv4/udp.c | 2 | ||||
| -rw-r--r-- | net/ipv6/ip6_offload.c | 1 | ||||
| -rw-r--r-- | net/ipv6/udp_offload.c | 3 | ||||
| -rw-r--r-- | net/mpls/Kconfig | 9 | ||||
| -rw-r--r-- | net/mpls/Makefile | 4 | ||||
| -rw-r--r-- | net/mpls/mpls_gso.c | 108 |
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" | |||
| 218 | source "net/openvswitch/Kconfig" | 218 | source "net/openvswitch/Kconfig" |
| 219 | source "net/vmw_vsock/Kconfig" | 219 | source "net/vmw_vsock/Kconfig" |
| 220 | source "net/netlink/Kconfig" | 220 | source "net/netlink/Kconfig" |
| 221 | source "net/mpls/Kconfig" | ||
| 221 | 222 | ||
| 222 | config RPS | 223 | config 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/ | |||
| 70 | obj-$(CONFIG_NFC) += nfc/ | 70 | obj-$(CONFIG_NFC) += nfc/ |
| 71 | obj-$(CONFIG_OPENVSWITCH) += openvswitch/ | 71 | obj-$(CONFIG_OPENVSWITCH) += openvswitch/ |
| 72 | obj-$(CONFIG_VSOCKETS) += vmw_vsock/ | 72 | obj-$(CONFIG_VSOCKETS) += vmw_vsock/ |
| 73 | obj-$(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 | # | ||
| 4 | config 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 | # | ||
| 4 | obj-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 | |||
| 22 | static 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 | |||
| 62 | out: | ||
| 63 | return segs; | ||
| 64 | } | ||
| 65 | |||
| 66 | static int mpls_gso_send_check(struct sk_buff *skb) | ||
| 67 | { | ||
| 68 | return 0; | ||
| 69 | } | ||
| 70 | |||
| 71 | static 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 | |||
| 79 | static 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 | |||
| 87 | static 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 | |||
| 97 | static void __exit mpls_gso_exit(void) | ||
| 98 | { | ||
| 99 | dev_remove_offload(&mpls_uc_offload); | ||
| 100 | dev_remove_offload(&mpls_mc_offload); | ||
| 101 | } | ||
| 102 | |||
| 103 | module_init(mpls_gso_init); | ||
| 104 | module_exit(mpls_gso_exit); | ||
| 105 | |||
| 106 | MODULE_DESCRIPTION("MPLS GSO support"); | ||
| 107 | MODULE_AUTHOR("Simon Horman (horms@verge.net.au)"); | ||
| 108 | MODULE_LICENSE("GPL"); | ||
