aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-09-22 03:23:13 -0400
committerDavid S. Miller <davem@davemloft.net>2011-09-22 03:23:13 -0400
commit8decf868790b48a727d7e7ca164f2bcd3c1389c0 (patch)
treeb759a5f861f842af7ea76f9011b579d06e9d5508 /net/core
parent3fc72370186be2f9d4d6ef06d99e1caa5d92c564 (diff)
parentd93dc5c4478c1fd5de85a3e8aece9aad7bbae044 (diff)
Merge branch 'master' of github.com:davem330/net
Conflicts: MAINTAINERS drivers/net/Kconfig drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c drivers/net/ethernet/broadcom/tg3.c drivers/net/wireless/iwlwifi/iwl-pci.c drivers/net/wireless/iwlwifi/iwl-trans-tx-pcie.c drivers/net/wireless/rt2x00/rt2800usb.c drivers/net/wireless/wl12xx/main.c
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c8
-rw-r--r--net/core/fib_rules.c4
-rw-r--r--net/core/flow.c36
-rw-r--r--net/core/neighbour.c8
-rw-r--r--net/core/netpoll.c4
-rw-r--r--net/core/skbuff.c22
6 files changed, 57 insertions, 25 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 4b9981caf06f..bf49a47ddfdb 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1517,6 +1517,14 @@ static inline bool is_skb_forwardable(struct net_device *dev,
1517 */ 1517 */
1518int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) 1518int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
1519{ 1519{
1520 if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
1521 if (skb_copy_ubufs(skb, GFP_ATOMIC)) {
1522 atomic_long_inc(&dev->rx_dropped);
1523 kfree_skb(skb);
1524 return NET_RX_DROP;
1525 }
1526 }
1527
1520 skb_orphan(skb); 1528 skb_orphan(skb);
1521 nf_reset(skb); 1529 nf_reset(skb);
1522 1530
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 67c5c288cd80..38be4744133f 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -384,8 +384,8 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
384 */ 384 */
385 list_for_each_entry(r, &ops->rules_list, list) { 385 list_for_each_entry(r, &ops->rules_list, list) {
386 if (r->action == FR_ACT_GOTO && 386 if (r->action == FR_ACT_GOTO &&
387 r->target == rule->pref) { 387 r->target == rule->pref &&
388 BUG_ON(rtnl_dereference(r->ctarget) != NULL); 388 rtnl_dereference(r->ctarget) == NULL) {
389 rcu_assign_pointer(r->ctarget, rule); 389 rcu_assign_pointer(r->ctarget, rule);
390 if (--ops->unresolved_rules == 0) 390 if (--ops->unresolved_rules == 0)
391 break; 391 break;
diff --git a/net/core/flow.c b/net/core/flow.c
index bf32c33cad3b..555a456efb07 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -30,6 +30,7 @@ struct flow_cache_entry {
30 struct hlist_node hlist; 30 struct hlist_node hlist;
31 struct list_head gc_list; 31 struct list_head gc_list;
32 } u; 32 } u;
33 struct net *net;
33 u16 family; 34 u16 family;
34 u8 dir; 35 u8 dir;
35 u32 genid; 36 u32 genid;
@@ -172,29 +173,26 @@ static void flow_new_hash_rnd(struct flow_cache *fc,
172 173
173static u32 flow_hash_code(struct flow_cache *fc, 174static u32 flow_hash_code(struct flow_cache *fc,
174 struct flow_cache_percpu *fcp, 175 struct flow_cache_percpu *fcp,
175 const struct flowi *key) 176 const struct flowi *key,
177 size_t keysize)
176{ 178{
177 const u32 *k = (const u32 *) key; 179 const u32 *k = (const u32 *) key;
180 const u32 length = keysize * sizeof(flow_compare_t) / sizeof(u32);
178 181
179 return jhash2(k, (sizeof(*key) / sizeof(u32)), fcp->hash_rnd) 182 return jhash2(k, length, fcp->hash_rnd)
180 & (flow_cache_hash_size(fc) - 1); 183 & (flow_cache_hash_size(fc) - 1);
181} 184}
182 185
183typedef unsigned long flow_compare_t;
184
185/* I hear what you're saying, use memcmp. But memcmp cannot make 186/* I hear what you're saying, use memcmp. But memcmp cannot make
186 * important assumptions that we can here, such as alignment and 187 * important assumptions that we can here, such as alignment.
187 * constant size.
188 */ 188 */
189static int flow_key_compare(const struct flowi *key1, const struct flowi *key2) 189static int flow_key_compare(const struct flowi *key1, const struct flowi *key2,
190 size_t keysize)
190{ 191{
191 const flow_compare_t *k1, *k1_lim, *k2; 192 const flow_compare_t *k1, *k1_lim, *k2;
192 const int n_elem = sizeof(struct flowi) / sizeof(flow_compare_t);
193
194 BUILD_BUG_ON(sizeof(struct flowi) % sizeof(flow_compare_t));
195 193
196 k1 = (const flow_compare_t *) key1; 194 k1 = (const flow_compare_t *) key1;
197 k1_lim = k1 + n_elem; 195 k1_lim = k1 + keysize;
198 196
199 k2 = (const flow_compare_t *) key2; 197 k2 = (const flow_compare_t *) key2;
200 198
@@ -215,6 +213,7 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
215 struct flow_cache_entry *fle, *tfle; 213 struct flow_cache_entry *fle, *tfle;
216 struct hlist_node *entry; 214 struct hlist_node *entry;
217 struct flow_cache_object *flo; 215 struct flow_cache_object *flo;
216 size_t keysize;
218 unsigned int hash; 217 unsigned int hash;
219 218
220 local_bh_disable(); 219 local_bh_disable();
@@ -222,6 +221,11 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
222 221
223 fle = NULL; 222 fle = NULL;
224 flo = NULL; 223 flo = NULL;
224
225 keysize = flow_key_size(family);
226 if (!keysize)
227 goto nocache;
228
225 /* Packet really early in init? Making flow_cache_init a 229 /* Packet really early in init? Making flow_cache_init a
226 * pre-smp initcall would solve this. --RR */ 230 * pre-smp initcall would solve this. --RR */
227 if (!fcp->hash_table) 231 if (!fcp->hash_table)
@@ -230,11 +234,12 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
230 if (fcp->hash_rnd_recalc) 234 if (fcp->hash_rnd_recalc)
231 flow_new_hash_rnd(fc, fcp); 235 flow_new_hash_rnd(fc, fcp);
232 236
233 hash = flow_hash_code(fc, fcp, key); 237 hash = flow_hash_code(fc, fcp, key, keysize);
234 hlist_for_each_entry(tfle, entry, &fcp->hash_table[hash], u.hlist) { 238 hlist_for_each_entry(tfle, entry, &fcp->hash_table[hash], u.hlist) {
235 if (tfle->family == family && 239 if (tfle->net == net &&
240 tfle->family == family &&
236 tfle->dir == dir && 241 tfle->dir == dir &&
237 flow_key_compare(key, &tfle->key) == 0) { 242 flow_key_compare(key, &tfle->key, keysize) == 0) {
238 fle = tfle; 243 fle = tfle;
239 break; 244 break;
240 } 245 }
@@ -246,9 +251,10 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
246 251
247 fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC); 252 fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC);
248 if (fle) { 253 if (fle) {
254 fle->net = net;
249 fle->family = family; 255 fle->family = family;
250 fle->dir = dir; 256 fle->dir = dir;
251 memcpy(&fle->key, key, sizeof(*key)); 257 memcpy(&fle->key, key, keysize * sizeof(flow_compare_t));
252 fle->object = NULL; 258 fle->object = NULL;
253 hlist_add_head(&fle->u.hlist, &fcp->hash_table[hash]); 259 hlist_add_head(&fle->u.hlist, &fcp->hash_table[hash]);
254 fcp->hash_count++; 260 fcp->hash_count++;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 4002261f20d1..43449649cf73 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -1331,11 +1331,15 @@ static void neigh_proxy_process(unsigned long arg)
1331 1331
1332 if (tdif <= 0) { 1332 if (tdif <= 0) {
1333 struct net_device *dev = skb->dev; 1333 struct net_device *dev = skb->dev;
1334
1334 __skb_unlink(skb, &tbl->proxy_queue); 1335 __skb_unlink(skb, &tbl->proxy_queue);
1335 if (tbl->proxy_redo && netif_running(dev)) 1336 if (tbl->proxy_redo && netif_running(dev)) {
1337 rcu_read_lock();
1336 tbl->proxy_redo(skb); 1338 tbl->proxy_redo(skb);
1337 else 1339 rcu_read_unlock();
1340 } else {
1338 kfree_skb(skb); 1341 kfree_skb(skb);
1342 }
1339 1343
1340 dev_put(dev); 1344 dev_put(dev);
1341 } else if (!sched_next || tdif < sched_next) 1345 } else if (!sched_next || tdif < sched_next)
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index d676a561d983..f57d94627a2a 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -558,13 +558,14 @@ int __netpoll_rx(struct sk_buff *skb)
558 if (skb_shared(skb)) 558 if (skb_shared(skb))
559 goto out; 559 goto out;
560 560
561 iph = (struct iphdr *)skb->data;
562 if (!pskb_may_pull(skb, sizeof(struct iphdr))) 561 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
563 goto out; 562 goto out;
563 iph = (struct iphdr *)skb->data;
564 if (iph->ihl < 5 || iph->version != 4) 564 if (iph->ihl < 5 || iph->version != 4)
565 goto out; 565 goto out;
566 if (!pskb_may_pull(skb, iph->ihl*4)) 566 if (!pskb_may_pull(skb, iph->ihl*4))
567 goto out; 567 goto out;
568 iph = (struct iphdr *)skb->data;
568 if (ip_fast_csum((u8 *)iph, iph->ihl) != 0) 569 if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
569 goto out; 570 goto out;
570 571
@@ -579,6 +580,7 @@ int __netpoll_rx(struct sk_buff *skb)
579 if (pskb_trim_rcsum(skb, len)) 580 if (pskb_trim_rcsum(skb, len))
580 goto out; 581 goto out;
581 582
583 iph = (struct iphdr *)skb->data;
582 if (iph->protocol != IPPROTO_UDP) 584 if (iph->protocol != IPPROTO_UDP)
583 goto out; 585 goto out;
584 586
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 296afd0aa8d2..5b2c5f1d4dba 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -613,8 +613,21 @@ struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src)
613} 613}
614EXPORT_SYMBOL_GPL(skb_morph); 614EXPORT_SYMBOL_GPL(skb_morph);
615 615
616/* skb frags copy userspace buffers to kernel */ 616/* skb_copy_ubufs - copy userspace skb frags buffers to kernel
617static int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask) 617 * @skb: the skb to modify
618 * @gfp_mask: allocation priority
619 *
620 * This must be called on SKBTX_DEV_ZEROCOPY skb.
621 * It will copy all frags into kernel and drop the reference
622 * to userspace pages.
623 *
624 * If this function is called from an interrupt gfp_mask() must be
625 * %GFP_ATOMIC.
626 *
627 * Returns 0 on success or a negative error code on failure
628 * to allocate kernel memory to copy to.
629 */
630int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask)
618{ 631{
619 int i; 632 int i;
620 int num_frags = skb_shinfo(skb)->nr_frags; 633 int num_frags = skb_shinfo(skb)->nr_frags;
@@ -654,6 +667,8 @@ static int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask)
654 skb_shinfo(skb)->frags[i - 1].page = head; 667 skb_shinfo(skb)->frags[i - 1].page = head;
655 head = (struct page *)head->private; 668 head = (struct page *)head->private;
656 } 669 }
670
671 skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
657 return 0; 672 return 0;
658} 673}
659 674
@@ -679,7 +694,6 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
679 if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) { 694 if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
680 if (skb_copy_ubufs(skb, gfp_mask)) 695 if (skb_copy_ubufs(skb, gfp_mask))
681 return NULL; 696 return NULL;
682 skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
683 } 697 }
684 698
685 n = skb + 1; 699 n = skb + 1;
@@ -805,7 +819,6 @@ struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask)
805 n = NULL; 819 n = NULL;
806 goto out; 820 goto out;
807 } 821 }
808 skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
809 } 822 }
810 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { 823 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
811 skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i]; 824 skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i];
@@ -898,7 +911,6 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
898 if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) { 911 if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
899 if (skb_copy_ubufs(skb, gfp_mask)) 912 if (skb_copy_ubufs(skb, gfp_mask))
900 goto nofrags; 913 goto nofrags;
901 skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
902 } 914 }
903 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) 915 for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
904 skb_frag_ref(skb, i); 916 skb_frag_ref(skb, i);