diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/af_bluetooth.c | 6 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 4 | ||||
-rw-r--r-- | net/bluetooth/hci_sock.c | 12 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/Makefile | 2 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/core.c | 43 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/crc.c | 71 | ||||
-rw-r--r-- | net/core/dev.c | 14 | ||||
-rw-r--r-- | net/core/ethtool.c | 53 | ||||
-rw-r--r-- | net/core/skbuff.c | 75 | ||||
-rw-r--r-- | net/ipv4/ip_output.c | 83 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 71 | ||||
-rw-r--r-- | net/ipv6/mcast.c | 2 |
12 files changed, 343 insertions, 93 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 12b43345b54f..03532062a46a 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -308,12 +308,6 @@ static struct net_proto_family bt_sock_family_ops = { | |||
308 | .create = bt_sock_create, | 308 | .create = bt_sock_create, |
309 | }; | 309 | }; |
310 | 310 | ||
311 | extern int hci_sock_init(void); | ||
312 | extern int hci_sock_cleanup(void); | ||
313 | |||
314 | extern int bt_sysfs_init(void); | ||
315 | extern int bt_sysfs_cleanup(void); | ||
316 | |||
317 | static int __init bt_init(void) | 311 | static int __init bt_init(void) |
318 | { | 312 | { |
319 | BT_INFO("Core ver %s", VERSION); | 313 | BT_INFO("Core ver %s", VERSION); |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 55dc42eac92c..cf0df1c8c933 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -87,7 +87,7 @@ int hci_unregister_notifier(struct notifier_block *nb) | |||
87 | return notifier_chain_unregister(&hci_notifier, nb); | 87 | return notifier_chain_unregister(&hci_notifier, nb); |
88 | } | 88 | } |
89 | 89 | ||
90 | void hci_notify(struct hci_dev *hdev, int event) | 90 | static void hci_notify(struct hci_dev *hdev, int event) |
91 | { | 91 | { |
92 | notifier_call_chain(&hci_notifier, event, hdev); | 92 | notifier_call_chain(&hci_notifier, event, hdev); |
93 | } | 93 | } |
@@ -1347,7 +1347,7 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
1347 | kfree_skb(skb); | 1347 | kfree_skb(skb); |
1348 | } | 1348 | } |
1349 | 1349 | ||
1350 | void hci_rx_task(unsigned long arg) | 1350 | static void hci_rx_task(unsigned long arg) |
1351 | { | 1351 | { |
1352 | struct hci_dev *hdev = (struct hci_dev *) arg; | 1352 | struct hci_dev *hdev = (struct hci_dev *) arg; |
1353 | struct sk_buff *skb; | 1353 | struct sk_buff *skb; |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 32ef7975a139..799e448750ad 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -66,20 +66,20 @@ static struct hci_sec_filter hci_sec_filter = { | |||
66 | /* Packet types */ | 66 | /* Packet types */ |
67 | 0x10, | 67 | 0x10, |
68 | /* Events */ | 68 | /* Events */ |
69 | { 0x1000d9fe, 0x0000300c }, | 69 | { 0x1000d9fe, 0x0000b00c }, |
70 | /* Commands */ | 70 | /* Commands */ |
71 | { | 71 | { |
72 | { 0x0 }, | 72 | { 0x0 }, |
73 | /* OGF_LINK_CTL */ | 73 | /* OGF_LINK_CTL */ |
74 | { 0xbe000006, 0x00000001, 0x0000, 0x00 }, | 74 | { 0xbe000006, 0x00000001, 0x000000, 0x00 }, |
75 | /* OGF_LINK_POLICY */ | 75 | /* OGF_LINK_POLICY */ |
76 | { 0x00005200, 0x00000000, 0x0000, 0x00 }, | 76 | { 0x00005200, 0x00000000, 0x000000, 0x00 }, |
77 | /* OGF_HOST_CTL */ | 77 | /* OGF_HOST_CTL */ |
78 | { 0xaab00200, 0x2b402aaa, 0x0154, 0x00 }, | 78 | { 0xaab00200, 0x2b402aaa, 0x020154, 0x00 }, |
79 | /* OGF_INFO_PARAM */ | 79 | /* OGF_INFO_PARAM */ |
80 | { 0x000002be, 0x00000000, 0x0000, 0x00 }, | 80 | { 0x000002be, 0x00000000, 0x000000, 0x00 }, |
81 | /* OGF_STATUS_PARAM */ | 81 | /* OGF_STATUS_PARAM */ |
82 | { 0x000000ea, 0x00000000, 0x0000, 0x00 } | 82 | { 0x000000ea, 0x00000000, 0x000000, 0x00 } |
83 | } | 83 | } |
84 | }; | 84 | }; |
85 | 85 | ||
diff --git a/net/bluetooth/rfcomm/Makefile b/net/bluetooth/rfcomm/Makefile index aecec45ec68d..fe07988a3705 100644 --- a/net/bluetooth/rfcomm/Makefile +++ b/net/bluetooth/rfcomm/Makefile | |||
@@ -4,5 +4,5 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_BT_RFCOMM) += rfcomm.o | 5 | obj-$(CONFIG_BT_RFCOMM) += rfcomm.o |
6 | 6 | ||
7 | rfcomm-y := core.o sock.o crc.o | 7 | rfcomm-y := core.o sock.o |
8 | rfcomm-$(CONFIG_BT_RFCOMM_TTY) += tty.o | 8 | rfcomm-$(CONFIG_BT_RFCOMM_TTY) += tty.o |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 35adce6482b6..c3d56ead840c 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -133,6 +133,49 @@ static inline void rfcomm_session_put(struct rfcomm_session *s) | |||
133 | 133 | ||
134 | /* ---- RFCOMM FCS computation ---- */ | 134 | /* ---- RFCOMM FCS computation ---- */ |
135 | 135 | ||
136 | /* reversed, 8-bit, poly=0x07 */ | ||
137 | static unsigned char rfcomm_crc_table[256] = { | ||
138 | 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, | ||
139 | 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b, | ||
140 | 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, | ||
141 | 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67, | ||
142 | |||
143 | 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, | ||
144 | 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43, | ||
145 | 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, | ||
146 | 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f, | ||
147 | |||
148 | 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, | ||
149 | 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b, | ||
150 | 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, | ||
151 | 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17, | ||
152 | |||
153 | 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, | ||
154 | 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33, | ||
155 | 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, | ||
156 | 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f, | ||
157 | |||
158 | 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, | ||
159 | 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b, | ||
160 | 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, | ||
161 | 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87, | ||
162 | |||
163 | 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, | ||
164 | 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3, | ||
165 | 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, | ||
166 | 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf, | ||
167 | |||
168 | 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, | ||
169 | 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb, | ||
170 | 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, | ||
171 | 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7, | ||
172 | |||
173 | 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, | ||
174 | 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3, | ||
175 | 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, | ||
176 | 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf | ||
177 | }; | ||
178 | |||
136 | /* CRC on 2 bytes */ | 179 | /* CRC on 2 bytes */ |
137 | #define __crc(data) (rfcomm_crc_table[rfcomm_crc_table[0xff ^ data[0]] ^ data[1]]) | 180 | #define __crc(data) (rfcomm_crc_table[rfcomm_crc_table[0xff ^ data[0]] ^ data[1]]) |
138 | 181 | ||
diff --git a/net/bluetooth/rfcomm/crc.c b/net/bluetooth/rfcomm/crc.c deleted file mode 100644 index 1011bc4a8692..000000000000 --- a/net/bluetooth/rfcomm/crc.c +++ /dev/null | |||
@@ -1,71 +0,0 @@ | |||
1 | /* | ||
2 | RFCOMM implementation for Linux Bluetooth stack (BlueZ). | ||
3 | Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com> | ||
4 | Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org> | ||
5 | |||
6 | This program is free software; you can redistribute it and/or modify | ||
7 | it under the terms of the GNU General Public License version 2 as | ||
8 | published by the Free Software Foundation; | ||
9 | |||
10 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
11 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
12 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. | ||
13 | IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY | ||
14 | CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES | ||
15 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
16 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
17 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
18 | |||
19 | ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, | ||
20 | COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS | ||
21 | SOFTWARE IS DISCLAIMED. | ||
22 | */ | ||
23 | |||
24 | /* | ||
25 | * RFCOMM FCS calculation. | ||
26 | * | ||
27 | * $Id: crc.c,v 1.2 2002/09/21 09:54:32 holtmann Exp $ | ||
28 | */ | ||
29 | |||
30 | /* reversed, 8-bit, poly=0x07 */ | ||
31 | unsigned char rfcomm_crc_table[256] = { | ||
32 | 0x00, 0x91, 0xe3, 0x72, 0x07, 0x96, 0xe4, 0x75, | ||
33 | 0x0e, 0x9f, 0xed, 0x7c, 0x09, 0x98, 0xea, 0x7b, | ||
34 | 0x1c, 0x8d, 0xff, 0x6e, 0x1b, 0x8a, 0xf8, 0x69, | ||
35 | 0x12, 0x83, 0xf1, 0x60, 0x15, 0x84, 0xf6, 0x67, | ||
36 | |||
37 | 0x38, 0xa9, 0xdb, 0x4a, 0x3f, 0xae, 0xdc, 0x4d, | ||
38 | 0x36, 0xa7, 0xd5, 0x44, 0x31, 0xa0, 0xd2, 0x43, | ||
39 | 0x24, 0xb5, 0xc7, 0x56, 0x23, 0xb2, 0xc0, 0x51, | ||
40 | 0x2a, 0xbb, 0xc9, 0x58, 0x2d, 0xbc, 0xce, 0x5f, | ||
41 | |||
42 | 0x70, 0xe1, 0x93, 0x02, 0x77, 0xe6, 0x94, 0x05, | ||
43 | 0x7e, 0xef, 0x9d, 0x0c, 0x79, 0xe8, 0x9a, 0x0b, | ||
44 | 0x6c, 0xfd, 0x8f, 0x1e, 0x6b, 0xfa, 0x88, 0x19, | ||
45 | 0x62, 0xf3, 0x81, 0x10, 0x65, 0xf4, 0x86, 0x17, | ||
46 | |||
47 | 0x48, 0xd9, 0xab, 0x3a, 0x4f, 0xde, 0xac, 0x3d, | ||
48 | 0x46, 0xd7, 0xa5, 0x34, 0x41, 0xd0, 0xa2, 0x33, | ||
49 | 0x54, 0xc5, 0xb7, 0x26, 0x53, 0xc2, 0xb0, 0x21, | ||
50 | 0x5a, 0xcb, 0xb9, 0x28, 0x5d, 0xcc, 0xbe, 0x2f, | ||
51 | |||
52 | 0xe0, 0x71, 0x03, 0x92, 0xe7, 0x76, 0x04, 0x95, | ||
53 | 0xee, 0x7f, 0x0d, 0x9c, 0xe9, 0x78, 0x0a, 0x9b, | ||
54 | 0xfc, 0x6d, 0x1f, 0x8e, 0xfb, 0x6a, 0x18, 0x89, | ||
55 | 0xf2, 0x63, 0x11, 0x80, 0xf5, 0x64, 0x16, 0x87, | ||
56 | |||
57 | 0xd8, 0x49, 0x3b, 0xaa, 0xdf, 0x4e, 0x3c, 0xad, | ||
58 | 0xd6, 0x47, 0x35, 0xa4, 0xd1, 0x40, 0x32, 0xa3, | ||
59 | 0xc4, 0x55, 0x27, 0xb6, 0xc3, 0x52, 0x20, 0xb1, | ||
60 | 0xca, 0x5b, 0x29, 0xb8, 0xcd, 0x5c, 0x2e, 0xbf, | ||
61 | |||
62 | 0x90, 0x01, 0x73, 0xe2, 0x97, 0x06, 0x74, 0xe5, | ||
63 | 0x9e, 0x0f, 0x7d, 0xec, 0x99, 0x08, 0x7a, 0xeb, | ||
64 | 0x8c, 0x1d, 0x6f, 0xfe, 0x8b, 0x1a, 0x68, 0xf9, | ||
65 | 0x82, 0x13, 0x61, 0xf0, 0x85, 0x14, 0x66, 0xf7, | ||
66 | |||
67 | 0xa8, 0x39, 0x4b, 0xda, 0xaf, 0x3e, 0x4c, 0xdd, | ||
68 | 0xa6, 0x37, 0x45, 0xd4, 0xa1, 0x30, 0x42, 0xd3, | ||
69 | 0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, | ||
70 | 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf | ||
71 | }; | ||
diff --git a/net/core/dev.c b/net/core/dev.c index a44eeef24edf..8d1541595277 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2717,6 +2717,20 @@ int register_netdevice(struct net_device *dev) | |||
2717 | dev->name); | 2717 | dev->name); |
2718 | dev->features &= ~NETIF_F_TSO; | 2718 | dev->features &= ~NETIF_F_TSO; |
2719 | } | 2719 | } |
2720 | if (dev->features & NETIF_F_UFO) { | ||
2721 | if (!(dev->features & NETIF_F_HW_CSUM)) { | ||
2722 | printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no " | ||
2723 | "NETIF_F_HW_CSUM feature.\n", | ||
2724 | dev->name); | ||
2725 | dev->features &= ~NETIF_F_UFO; | ||
2726 | } | ||
2727 | if (!(dev->features & NETIF_F_SG)) { | ||
2728 | printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no " | ||
2729 | "NETIF_F_SG feature.\n", | ||
2730 | dev->name); | ||
2731 | dev->features &= ~NETIF_F_UFO; | ||
2732 | } | ||
2733 | } | ||
2720 | 2734 | ||
2721 | /* | 2735 | /* |
2722 | * nil rebuild_header routine, | 2736 | * nil rebuild_header routine, |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 404b761e82ce..0350586e9195 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -93,6 +93,20 @@ int ethtool_op_get_perm_addr(struct net_device *dev, struct ethtool_perm_addr *a | |||
93 | } | 93 | } |
94 | 94 | ||
95 | 95 | ||
96 | u32 ethtool_op_get_ufo(struct net_device *dev) | ||
97 | { | ||
98 | return (dev->features & NETIF_F_UFO) != 0; | ||
99 | } | ||
100 | |||
101 | int ethtool_op_set_ufo(struct net_device *dev, u32 data) | ||
102 | { | ||
103 | if (data) | ||
104 | dev->features |= NETIF_F_UFO; | ||
105 | else | ||
106 | dev->features &= ~NETIF_F_UFO; | ||
107 | return 0; | ||
108 | } | ||
109 | |||
96 | /* Handlers for each ethtool command */ | 110 | /* Handlers for each ethtool command */ |
97 | 111 | ||
98 | static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) | 112 | static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) |
@@ -483,6 +497,11 @@ static int __ethtool_set_sg(struct net_device *dev, u32 data) | |||
483 | return err; | 497 | return err; |
484 | } | 498 | } |
485 | 499 | ||
500 | if (!data && dev->ethtool_ops->set_ufo) { | ||
501 | err = dev->ethtool_ops->set_ufo(dev, 0); | ||
502 | if (err) | ||
503 | return err; | ||
504 | } | ||
486 | return dev->ethtool_ops->set_sg(dev, data); | 505 | return dev->ethtool_ops->set_sg(dev, data); |
487 | } | 506 | } |
488 | 507 | ||
@@ -569,6 +588,32 @@ static int ethtool_set_tso(struct net_device *dev, char __user *useraddr) | |||
569 | return dev->ethtool_ops->set_tso(dev, edata.data); | 588 | return dev->ethtool_ops->set_tso(dev, edata.data); |
570 | } | 589 | } |
571 | 590 | ||
591 | static int ethtool_get_ufo(struct net_device *dev, char __user *useraddr) | ||
592 | { | ||
593 | struct ethtool_value edata = { ETHTOOL_GTSO }; | ||
594 | |||
595 | if (!dev->ethtool_ops->get_ufo) | ||
596 | return -EOPNOTSUPP; | ||
597 | edata.data = dev->ethtool_ops->get_ufo(dev); | ||
598 | if (copy_to_user(useraddr, &edata, sizeof(edata))) | ||
599 | return -EFAULT; | ||
600 | return 0; | ||
601 | } | ||
602 | static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr) | ||
603 | { | ||
604 | struct ethtool_value edata; | ||
605 | |||
606 | if (!dev->ethtool_ops->set_ufo) | ||
607 | return -EOPNOTSUPP; | ||
608 | if (copy_from_user(&edata, useraddr, sizeof(edata))) | ||
609 | return -EFAULT; | ||
610 | if (edata.data && !(dev->features & NETIF_F_SG)) | ||
611 | return -EINVAL; | ||
612 | if (edata.data && !(dev->features & NETIF_F_HW_CSUM)) | ||
613 | return -EINVAL; | ||
614 | return dev->ethtool_ops->set_ufo(dev, edata.data); | ||
615 | } | ||
616 | |||
572 | static int ethtool_self_test(struct net_device *dev, char __user *useraddr) | 617 | static int ethtool_self_test(struct net_device *dev, char __user *useraddr) |
573 | { | 618 | { |
574 | struct ethtool_test test; | 619 | struct ethtool_test test; |
@@ -854,6 +899,12 @@ int dev_ethtool(struct ifreq *ifr) | |||
854 | case ETHTOOL_GPERMADDR: | 899 | case ETHTOOL_GPERMADDR: |
855 | rc = ethtool_get_perm_addr(dev, useraddr); | 900 | rc = ethtool_get_perm_addr(dev, useraddr); |
856 | break; | 901 | break; |
902 | case ETHTOOL_GUFO: | ||
903 | rc = ethtool_get_ufo(dev, useraddr); | ||
904 | break; | ||
905 | case ETHTOOL_SUFO: | ||
906 | rc = ethtool_set_ufo(dev, useraddr); | ||
907 | break; | ||
857 | default: | 908 | default: |
858 | rc = -EOPNOTSUPP; | 909 | rc = -EOPNOTSUPP; |
859 | } | 910 | } |
@@ -882,3 +933,5 @@ EXPORT_SYMBOL(ethtool_op_set_sg); | |||
882 | EXPORT_SYMBOL(ethtool_op_set_tso); | 933 | EXPORT_SYMBOL(ethtool_op_set_tso); |
883 | EXPORT_SYMBOL(ethtool_op_set_tx_csum); | 934 | EXPORT_SYMBOL(ethtool_op_set_tx_csum); |
884 | EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); | 935 | EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); |
936 | EXPORT_SYMBOL(ethtool_op_set_ufo); | ||
937 | EXPORT_SYMBOL(ethtool_op_get_ufo); | ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index ef9d46b91eb9..95501e40100e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -176,6 +176,8 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, | |||
176 | skb_shinfo(skb)->tso_size = 0; | 176 | skb_shinfo(skb)->tso_size = 0; |
177 | skb_shinfo(skb)->tso_segs = 0; | 177 | skb_shinfo(skb)->tso_segs = 0; |
178 | skb_shinfo(skb)->frag_list = NULL; | 178 | skb_shinfo(skb)->frag_list = NULL; |
179 | skb_shinfo(skb)->ufo_size = 0; | ||
180 | skb_shinfo(skb)->ip6_frag_id = 0; | ||
179 | out: | 181 | out: |
180 | return skb; | 182 | return skb; |
181 | nodata: | 183 | nodata: |
@@ -1696,6 +1698,78 @@ unsigned int skb_find_text(struct sk_buff *skb, unsigned int from, | |||
1696 | return textsearch_find(config, state); | 1698 | return textsearch_find(config, state); |
1697 | } | 1699 | } |
1698 | 1700 | ||
1701 | /** | ||
1702 | * skb_append_datato_frags: - append the user data to a skb | ||
1703 | * @sk: sock structure | ||
1704 | * @skb: skb structure to be appened with user data. | ||
1705 | * @getfrag: call back function to be used for getting the user data | ||
1706 | * @from: pointer to user message iov | ||
1707 | * @length: length of the iov message | ||
1708 | * | ||
1709 | * Description: This procedure append the user data in the fragment part | ||
1710 | * of the skb if any page alloc fails user this procedure returns -ENOMEM | ||
1711 | */ | ||
1712 | int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, | ||
1713 | int getfrag(void *from, char *to, int offset, | ||
1714 | int len, int odd, struct sk_buff *skb), | ||
1715 | void *from, int length) | ||
1716 | { | ||
1717 | int frg_cnt = 0; | ||
1718 | skb_frag_t *frag = NULL; | ||
1719 | struct page *page = NULL; | ||
1720 | int copy, left; | ||
1721 | int offset = 0; | ||
1722 | int ret; | ||
1723 | |||
1724 | do { | ||
1725 | /* Return error if we don't have space for new frag */ | ||
1726 | frg_cnt = skb_shinfo(skb)->nr_frags; | ||
1727 | if (frg_cnt >= MAX_SKB_FRAGS) | ||
1728 | return -EFAULT; | ||
1729 | |||
1730 | /* allocate a new page for next frag */ | ||
1731 | page = alloc_pages(sk->sk_allocation, 0); | ||
1732 | |||
1733 | /* If alloc_page fails just return failure and caller will | ||
1734 | * free previous allocated pages by doing kfree_skb() | ||
1735 | */ | ||
1736 | if (page == NULL) | ||
1737 | return -ENOMEM; | ||
1738 | |||
1739 | /* initialize the next frag */ | ||
1740 | sk->sk_sndmsg_page = page; | ||
1741 | sk->sk_sndmsg_off = 0; | ||
1742 | skb_fill_page_desc(skb, frg_cnt, page, 0, 0); | ||
1743 | skb->truesize += PAGE_SIZE; | ||
1744 | atomic_add(PAGE_SIZE, &sk->sk_wmem_alloc); | ||
1745 | |||
1746 | /* get the new initialized frag */ | ||
1747 | frg_cnt = skb_shinfo(skb)->nr_frags; | ||
1748 | frag = &skb_shinfo(skb)->frags[frg_cnt - 1]; | ||
1749 | |||
1750 | /* copy the user data to page */ | ||
1751 | left = PAGE_SIZE - frag->page_offset; | ||
1752 | copy = (length > left)? left : length; | ||
1753 | |||
1754 | ret = getfrag(from, (page_address(frag->page) + | ||
1755 | frag->page_offset + frag->size), | ||
1756 | offset, copy, 0, skb); | ||
1757 | if (ret < 0) | ||
1758 | return -EFAULT; | ||
1759 | |||
1760 | /* copy was successful so update the size parameters */ | ||
1761 | sk->sk_sndmsg_off += copy; | ||
1762 | frag->size += copy; | ||
1763 | skb->len += copy; | ||
1764 | skb->data_len += copy; | ||
1765 | offset += copy; | ||
1766 | length -= copy; | ||
1767 | |||
1768 | } while (length > 0); | ||
1769 | |||
1770 | return 0; | ||
1771 | } | ||
1772 | |||
1699 | void __init skb_init(void) | 1773 | void __init skb_init(void) |
1700 | { | 1774 | { |
1701 | skbuff_head_cache = kmem_cache_create("skbuff_head_cache", | 1775 | skbuff_head_cache = kmem_cache_create("skbuff_head_cache", |
@@ -1747,3 +1821,4 @@ EXPORT_SYMBOL(skb_prepare_seq_read); | |||
1747 | EXPORT_SYMBOL(skb_seq_read); | 1821 | EXPORT_SYMBOL(skb_seq_read); |
1748 | EXPORT_SYMBOL(skb_abort_seq_read); | 1822 | EXPORT_SYMBOL(skb_abort_seq_read); |
1749 | EXPORT_SYMBOL(skb_find_text); | 1823 | EXPORT_SYMBOL(skb_find_text); |
1824 | EXPORT_SYMBOL(skb_append_datato_frags); | ||
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 87e350069abb..17758234a3e3 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -275,7 +275,8 @@ int ip_output(struct sk_buff *skb) | |||
275 | { | 275 | { |
276 | IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS); | 276 | IP_INC_STATS(IPSTATS_MIB_OUTREQUESTS); |
277 | 277 | ||
278 | if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->tso_size) | 278 | if (skb->len > dst_mtu(skb->dst) && |
279 | !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size)) | ||
279 | return ip_fragment(skb, ip_finish_output); | 280 | return ip_fragment(skb, ip_finish_output); |
280 | else | 281 | else |
281 | return ip_finish_output(skb); | 282 | return ip_finish_output(skb); |
@@ -688,6 +689,60 @@ csum_page(struct page *page, int offset, int copy) | |||
688 | return csum; | 689 | return csum; |
689 | } | 690 | } |
690 | 691 | ||
692 | inline int ip_ufo_append_data(struct sock *sk, | ||
693 | int getfrag(void *from, char *to, int offset, int len, | ||
694 | int odd, struct sk_buff *skb), | ||
695 | void *from, int length, int hh_len, int fragheaderlen, | ||
696 | int transhdrlen, int mtu,unsigned int flags) | ||
697 | { | ||
698 | struct sk_buff *skb; | ||
699 | int err; | ||
700 | |||
701 | /* There is support for UDP fragmentation offload by network | ||
702 | * device, so create one single skb packet containing complete | ||
703 | * udp datagram | ||
704 | */ | ||
705 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) { | ||
706 | skb = sock_alloc_send_skb(sk, | ||
707 | hh_len + fragheaderlen + transhdrlen + 20, | ||
708 | (flags & MSG_DONTWAIT), &err); | ||
709 | |||
710 | if (skb == NULL) | ||
711 | return err; | ||
712 | |||
713 | /* reserve space for Hardware header */ | ||
714 | skb_reserve(skb, hh_len); | ||
715 | |||
716 | /* create space for UDP/IP header */ | ||
717 | skb_put(skb,fragheaderlen + transhdrlen); | ||
718 | |||
719 | /* initialize network header pointer */ | ||
720 | skb->nh.raw = skb->data; | ||
721 | |||
722 | /* initialize protocol header pointer */ | ||
723 | skb->h.raw = skb->data + fragheaderlen; | ||
724 | |||
725 | skb->ip_summed = CHECKSUM_HW; | ||
726 | skb->csum = 0; | ||
727 | sk->sk_sndmsg_off = 0; | ||
728 | } | ||
729 | |||
730 | err = skb_append_datato_frags(sk,skb, getfrag, from, | ||
731 | (length - transhdrlen)); | ||
732 | if (!err) { | ||
733 | /* specify the length of each IP datagram fragment*/ | ||
734 | skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen); | ||
735 | __skb_queue_tail(&sk->sk_write_queue, skb); | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | /* There is not enough support do UFO , | ||
740 | * so follow normal path | ||
741 | */ | ||
742 | kfree_skb(skb); | ||
743 | return err; | ||
744 | } | ||
745 | |||
691 | /* | 746 | /* |
692 | * ip_append_data() and ip_append_page() can make one large IP datagram | 747 | * ip_append_data() and ip_append_page() can make one large IP datagram |
693 | * from many pieces of data. Each pieces will be holded on the socket | 748 | * from many pieces of data. Each pieces will be holded on the socket |
@@ -777,6 +832,15 @@ int ip_append_data(struct sock *sk, | |||
777 | csummode = CHECKSUM_HW; | 832 | csummode = CHECKSUM_HW; |
778 | 833 | ||
779 | inet->cork.length += length; | 834 | inet->cork.length += length; |
835 | if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) && | ||
836 | (rt->u.dst.dev->features & NETIF_F_UFO)) { | ||
837 | |||
838 | if(ip_ufo_append_data(sk, getfrag, from, length, hh_len, | ||
839 | fragheaderlen, transhdrlen, mtu, flags)) | ||
840 | goto error; | ||
841 | |||
842 | return 0; | ||
843 | } | ||
780 | 844 | ||
781 | /* So, what's going on in the loop below? | 845 | /* So, what's going on in the loop below? |
782 | * | 846 | * |
@@ -1008,14 +1072,23 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, | |||
1008 | return -EINVAL; | 1072 | return -EINVAL; |
1009 | 1073 | ||
1010 | inet->cork.length += size; | 1074 | inet->cork.length += size; |
1075 | if ((sk->sk_protocol == IPPROTO_UDP) && | ||
1076 | (rt->u.dst.dev->features & NETIF_F_UFO)) | ||
1077 | skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen); | ||
1078 | |||
1011 | 1079 | ||
1012 | while (size > 0) { | 1080 | while (size > 0) { |
1013 | int i; | 1081 | int i; |
1014 | 1082 | ||
1015 | /* Check if the remaining data fits into current packet. */ | 1083 | if (skb_shinfo(skb)->ufo_size) |
1016 | len = mtu - skb->len; | 1084 | len = size; |
1017 | if (len < size) | 1085 | else { |
1018 | len = maxfraglen - skb->len; | 1086 | |
1087 | /* Check if the remaining data fits into current packet. */ | ||
1088 | len = mtu - skb->len; | ||
1089 | if (len < size) | ||
1090 | len = maxfraglen - skb->len; | ||
1091 | } | ||
1019 | if (len <= 0) { | 1092 | if (len <= 0) { |
1020 | struct sk_buff *skb_prev; | 1093 | struct sk_buff *skb_prev; |
1021 | char *data; | 1094 | char *data; |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 563b442ffab8..614296a920c6 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -147,7 +147,8 @@ static int ip6_output2(struct sk_buff *skb) | |||
147 | 147 | ||
148 | int ip6_output(struct sk_buff *skb) | 148 | int ip6_output(struct sk_buff *skb) |
149 | { | 149 | { |
150 | if (skb->len > dst_mtu(skb->dst) || dst_allfrag(skb->dst)) | 150 | if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ufo_size) || |
151 | dst_allfrag(skb->dst)) | ||
151 | return ip6_fragment(skb, ip6_output2); | 152 | return ip6_fragment(skb, ip6_output2); |
152 | else | 153 | else |
153 | return ip6_output2(skb); | 154 | return ip6_output2(skb); |
@@ -768,6 +769,65 @@ out_err_release: | |||
768 | *dst = NULL; | 769 | *dst = NULL; |
769 | return err; | 770 | return err; |
770 | } | 771 | } |
772 | inline int ip6_ufo_append_data(struct sock *sk, | ||
773 | int getfrag(void *from, char *to, int offset, int len, | ||
774 | int odd, struct sk_buff *skb), | ||
775 | void *from, int length, int hh_len, int fragheaderlen, | ||
776 | int transhdrlen, int mtu,unsigned int flags) | ||
777 | |||
778 | { | ||
779 | struct sk_buff *skb; | ||
780 | int err; | ||
781 | |||
782 | /* There is support for UDP large send offload by network | ||
783 | * device, so create one single skb packet containing complete | ||
784 | * udp datagram | ||
785 | */ | ||
786 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) { | ||
787 | skb = sock_alloc_send_skb(sk, | ||
788 | hh_len + fragheaderlen + transhdrlen + 20, | ||
789 | (flags & MSG_DONTWAIT), &err); | ||
790 | if (skb == NULL) | ||
791 | return -ENOMEM; | ||
792 | |||
793 | /* reserve space for Hardware header */ | ||
794 | skb_reserve(skb, hh_len); | ||
795 | |||
796 | /* create space for UDP/IP header */ | ||
797 | skb_put(skb,fragheaderlen + transhdrlen); | ||
798 | |||
799 | /* initialize network header pointer */ | ||
800 | skb->nh.raw = skb->data; | ||
801 | |||
802 | /* initialize protocol header pointer */ | ||
803 | skb->h.raw = skb->data + fragheaderlen; | ||
804 | |||
805 | skb->ip_summed = CHECKSUM_HW; | ||
806 | skb->csum = 0; | ||
807 | sk->sk_sndmsg_off = 0; | ||
808 | } | ||
809 | |||
810 | err = skb_append_datato_frags(sk,skb, getfrag, from, | ||
811 | (length - transhdrlen)); | ||
812 | if (!err) { | ||
813 | struct frag_hdr fhdr; | ||
814 | |||
815 | /* specify the length of each IP datagram fragment*/ | ||
816 | skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen) - | ||
817 | sizeof(struct frag_hdr); | ||
818 | ipv6_select_ident(skb, &fhdr); | ||
819 | skb_shinfo(skb)->ip6_frag_id = fhdr.identification; | ||
820 | __skb_queue_tail(&sk->sk_write_queue, skb); | ||
821 | |||
822 | return 0; | ||
823 | } | ||
824 | /* There is not enough support do UPD LSO, | ||
825 | * so follow normal path | ||
826 | */ | ||
827 | kfree_skb(skb); | ||
828 | |||
829 | return err; | ||
830 | } | ||
771 | 831 | ||
772 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | 832 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, |
773 | int offset, int len, int odd, struct sk_buff *skb), | 833 | int offset, int len, int odd, struct sk_buff *skb), |
@@ -860,6 +920,15 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
860 | */ | 920 | */ |
861 | 921 | ||
862 | inet->cork.length += length; | 922 | inet->cork.length += length; |
923 | if (((length > mtu) && (sk->sk_protocol == IPPROTO_UDP)) && | ||
924 | (rt->u.dst.dev->features & NETIF_F_UFO)) { | ||
925 | |||
926 | if(ip6_ufo_append_data(sk, getfrag, from, length, hh_len, | ||
927 | fragheaderlen, transhdrlen, mtu, flags)) | ||
928 | goto error; | ||
929 | |||
930 | return 0; | ||
931 | } | ||
863 | 932 | ||
864 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) | 933 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) |
865 | goto alloc_new_skb; | 934 | goto alloc_new_skb; |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 39a96c768102..c4f2a0ef7489 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -164,7 +164,7 @@ static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, | |||
164 | #define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value)) | 164 | #define MLDV2_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value)) |
165 | #define MLDV2_EXP(thresh, nbmant, nbexp, value) \ | 165 | #define MLDV2_EXP(thresh, nbmant, nbexp, value) \ |
166 | ((value) < (thresh) ? (value) : \ | 166 | ((value) < (thresh) ? (value) : \ |
167 | ((MLDV2_MASK(value, nbmant) | (1<<(nbmant+nbexp))) << \ | 167 | ((MLDV2_MASK(value, nbmant) | (1<<(nbmant))) << \ |
168 | (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) | 168 | (MLDV2_MASK((value) >> (nbmant), nbexp) + (nbexp)))) |
169 | 169 | ||
170 | #define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value) | 170 | #define MLDV2_QQIC(value) MLDV2_EXP(0x80, 4, 3, value) |