Blame view
net/mpls/mpls_gso.c
2.5 KB
0d89d2035 MPLS: Add limited... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
/* * MPLS GSO Support * * Authors: Simon Horman (horms@verge.net.au) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * Based on: GSO portions of net/ipv4/gre.c */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/err.h> #include <linux/module.h> #include <linux/netdev_features.h> #include <linux/netdevice.h> #include <linux/skbuff.h> static struct sk_buff *mpls_gso_segment(struct sk_buff *skb, netdev_features_t features) { struct sk_buff *segs = ERR_PTR(-EINVAL); |
48d2ab609 net: mpls: Fixups... |
26 |
u16 mac_offset = skb->mac_header; |
0d89d2035 MPLS: Add limited... |
27 |
netdev_features_t mpls_features; |
48d2ab609 net: mpls: Fixups... |
28 |
u16 mac_len = skb->mac_len; |
0d89d2035 MPLS: Add limited... |
29 |
__be16 mpls_protocol; |
48d2ab609 net: mpls: Fixups... |
30 31 32 33 34 35 |
unsigned int mpls_hlen; skb_reset_network_header(skb); mpls_hlen = skb_inner_network_header(skb) - skb_network_header(skb); if (unlikely(!pskb_may_pull(skb, mpls_hlen))) goto out; |
0d89d2035 MPLS: Add limited... |
36 |
|
0d89d2035 MPLS: Add limited... |
37 38 39 |
/* Setup inner SKB. */ mpls_protocol = skb->protocol; skb->protocol = skb->inner_protocol; |
48d2ab609 net: mpls: Fixups... |
40 41 42 43 |
__skb_pull(skb, mpls_hlen); skb->mac_len = 0; skb_reset_mac_header(skb); |
0d89d2035 MPLS: Add limited... |
44 45 |
/* Segment inner packet. */ |
1e16aa3dd net: gso: use fea... |
46 |
mpls_features = skb->dev->mpls_features & features; |
0d89d2035 MPLS: Add limited... |
47 |
segs = skb_mac_gso_segment(skb, mpls_features); |
48d2ab609 net: mpls: Fixups... |
48 49 50 51 52 53 54 55 56 57 58 |
if (IS_ERR_OR_NULL(segs)) { skb_gso_error_unwind(skb, mpls_protocol, mpls_hlen, mac_offset, mac_len); goto out; } skb = segs; mpls_hlen += mac_len; do { skb->mac_len = mac_len; skb->protocol = mpls_protocol; |
0d89d2035 MPLS: Add limited... |
59 |
|
48d2ab609 net: mpls: Fixups... |
60 |
skb_reset_inner_network_header(skb); |
0d89d2035 MPLS: Add limited... |
61 |
|
48d2ab609 net: mpls: Fixups... |
62 |
__skb_push(skb, mpls_hlen); |
0d89d2035 MPLS: Add limited... |
63 |
|
48d2ab609 net: mpls: Fixups... |
64 65 66 |
skb_reset_mac_header(skb); skb_set_network_header(skb, mac_len); } while ((skb = skb->next)); |
5c7cdf339 gso: Remove arbit... |
67 |
|
48d2ab609 net: mpls: Fixups... |
68 |
out: |
0d89d2035 MPLS: Add limited... |
69 70 |
return segs; } |
207895fd3 net: mark some po... |
71 |
static struct packet_offload mpls_mc_offload __read_mostly = { |
0d89d2035 MPLS: Add limited... |
72 |
.type = cpu_to_be16(ETH_P_MPLS_MC), |
bdef7de4b net: Add priority... |
73 |
.priority = 15, |
0d89d2035 MPLS: Add limited... |
74 |
.callbacks = { |
0d89d2035 MPLS: Add limited... |
75 76 77 |
.gso_segment = mpls_gso_segment, }, }; |
207895fd3 net: mark some po... |
78 |
static struct packet_offload mpls_uc_offload __read_mostly = { |
0d89d2035 MPLS: Add limited... |
79 |
.type = cpu_to_be16(ETH_P_MPLS_UC), |
bdef7de4b net: Add priority... |
80 |
.priority = 15, |
0d89d2035 MPLS: Add limited... |
81 |
.callbacks = { |
0d89d2035 MPLS: Add limited... |
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
.gso_segment = mpls_gso_segment, }, }; static int __init mpls_gso_init(void) { pr_info("MPLS GSO support "); dev_add_offload(&mpls_uc_offload); dev_add_offload(&mpls_mc_offload); return 0; } static void __exit mpls_gso_exit(void) { dev_remove_offload(&mpls_uc_offload); dev_remove_offload(&mpls_mc_offload); } module_init(mpls_gso_init); module_exit(mpls_gso_exit); MODULE_DESCRIPTION("MPLS GSO support"); MODULE_AUTHOR("Simon Horman (horms@verge.net.au)"); MODULE_LICENSE("GPL"); |