aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bluetooth/af_bluetooth.c6
-rw-r--r--net/bluetooth/hci_core.c4
-rw-r--r--net/bluetooth/hci_sock.c12
-rw-r--r--net/bluetooth/rfcomm/Makefile2
-rw-r--r--net/bluetooth/rfcomm/core.c43
-rw-r--r--net/bluetooth/rfcomm/crc.c71
-rw-r--r--net/core/dev.c14
-rw-r--r--net/core/ethtool.c53
-rw-r--r--net/core/skbuff.c75
-rw-r--r--net/ipv4/ip_output.c83
-rw-r--r--net/ipv6/ip6_output.c71
-rw-r--r--net/ipv6/mcast.c2
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
311extern int hci_sock_init(void);
312extern int hci_sock_cleanup(void);
313
314extern int bt_sysfs_init(void);
315extern int bt_sysfs_cleanup(void);
316
317static int __init bt_init(void) 311static 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
90void hci_notify(struct hci_dev *hdev, int event) 90static 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
1350void hci_rx_task(unsigned long arg) 1350static 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
5obj-$(CONFIG_BT_RFCOMM) += rfcomm.o 5obj-$(CONFIG_BT_RFCOMM) += rfcomm.o
6 6
7rfcomm-y := core.o sock.o crc.o 7rfcomm-y := core.o sock.o
8rfcomm-$(CONFIG_BT_RFCOMM_TTY) += tty.o 8rfcomm-$(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 */
137static 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 */
31unsigned 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
96u32 ethtool_op_get_ufo(struct net_device *dev)
97{
98 return (dev->features & NETIF_F_UFO) != 0;
99}
100
101int 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
98static int ethtool_get_settings(struct net_device *dev, void __user *useraddr) 112static 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
591static 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}
602static 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
572static int ethtool_self_test(struct net_device *dev, char __user *useraddr) 617static 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);
882EXPORT_SYMBOL(ethtool_op_set_tso); 933EXPORT_SYMBOL(ethtool_op_set_tso);
883EXPORT_SYMBOL(ethtool_op_set_tx_csum); 934EXPORT_SYMBOL(ethtool_op_set_tx_csum);
884EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum); 935EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum);
936EXPORT_SYMBOL(ethtool_op_set_ufo);
937EXPORT_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;
179out: 181out:
180 return skb; 182 return skb;
181nodata: 183nodata:
@@ -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 */
1712int 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
1699void __init skb_init(void) 1773void __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);
1747EXPORT_SYMBOL(skb_seq_read); 1821EXPORT_SYMBOL(skb_seq_read);
1748EXPORT_SYMBOL(skb_abort_seq_read); 1822EXPORT_SYMBOL(skb_abort_seq_read);
1749EXPORT_SYMBOL(skb_find_text); 1823EXPORT_SYMBOL(skb_find_text);
1824EXPORT_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
692inline 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
148int ip6_output(struct sk_buff *skb) 148int 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}
772inline 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
772int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, 832int 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)