diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/802/tr.c | 22 | ||||
| -rw-r--r-- | net/core/dev.c | 9 | ||||
| -rw-r--r-- | net/core/netpoll.c | 63 | ||||
| -rw-r--r-- | net/decnet/dn_neigh.c | 2 | ||||
| -rw-r--r-- | net/ipv4/icmp.c | 12 | ||||
| -rw-r--r-- | net/ipv4/ipcomp.c | 2 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ipt_ECN.c | 17 | ||||
| -rw-r--r-- | net/ipv4/netfilter/ipt_TCPMSS.c | 7 | ||||
| -rw-r--r-- | net/ipv4/tcp_output.c | 53 | ||||
| -rw-r--r-- | net/ipv6/ip6_input.c | 9 | ||||
| -rw-r--r-- | net/ipv6/ipcomp6.c | 2 | ||||
| -rw-r--r-- | net/ipv6/raw.c | 2 | ||||
| -rw-r--r-- | net/sunrpc/xdr.c | 1 |
13 files changed, 115 insertions, 86 deletions
diff --git a/net/802/tr.c b/net/802/tr.c index a755e880f4ba..1bb7dc1b85cd 100644 --- a/net/802/tr.c +++ b/net/802/tr.c | |||
| @@ -251,10 +251,11 @@ void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,struct net_device * | |||
| 251 | unsigned int hash; | 251 | unsigned int hash; |
| 252 | struct rif_cache *entry; | 252 | struct rif_cache *entry; |
| 253 | unsigned char *olddata; | 253 | unsigned char *olddata; |
| 254 | unsigned long flags; | ||
| 254 | static const unsigned char mcast_func_addr[] | 255 | static const unsigned char mcast_func_addr[] |
| 255 | = {0xC0,0x00,0x00,0x04,0x00,0x00}; | 256 | = {0xC0,0x00,0x00,0x04,0x00,0x00}; |
| 256 | 257 | ||
| 257 | spin_lock_bh(&rif_lock); | 258 | spin_lock_irqsave(&rif_lock, flags); |
| 258 | 259 | ||
| 259 | /* | 260 | /* |
| 260 | * Broadcasts are single route as stated in RFC 1042 | 261 | * Broadcasts are single route as stated in RFC 1042 |
| @@ -323,7 +324,7 @@ printk("source routing for %02X:%02X:%02X:%02X:%02X:%02X\n",trh->daddr[0], | |||
| 323 | else | 324 | else |
| 324 | slack = 18 - ((ntohs(trh->rcf) & TR_RCF_LEN_MASK)>>8); | 325 | slack = 18 - ((ntohs(trh->rcf) & TR_RCF_LEN_MASK)>>8); |
| 325 | olddata = skb->data; | 326 | olddata = skb->data; |
| 326 | spin_unlock_bh(&rif_lock); | 327 | spin_unlock_irqrestore(&rif_lock, flags); |
| 327 | 328 | ||
| 328 | skb_pull(skb, slack); | 329 | skb_pull(skb, slack); |
| 329 | memmove(skb->data, olddata, sizeof(struct trh_hdr) - slack); | 330 | memmove(skb->data, olddata, sizeof(struct trh_hdr) - slack); |
| @@ -337,10 +338,11 @@ printk("source routing for %02X:%02X:%02X:%02X:%02X:%02X\n",trh->daddr[0], | |||
| 337 | static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev) | 338 | static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev) |
| 338 | { | 339 | { |
| 339 | unsigned int hash, rii_p = 0; | 340 | unsigned int hash, rii_p = 0; |
| 341 | unsigned long flags; | ||
| 340 | struct rif_cache *entry; | 342 | struct rif_cache *entry; |
| 341 | 343 | ||
| 342 | 344 | ||
| 343 | spin_lock_bh(&rif_lock); | 345 | spin_lock_irqsave(&rif_lock, flags); |
| 344 | 346 | ||
| 345 | /* | 347 | /* |
| 346 | * Firstly see if the entry exists | 348 | * Firstly see if the entry exists |
| @@ -378,7 +380,7 @@ printk("adding rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n", | |||
| 378 | if(!entry) | 380 | if(!entry) |
| 379 | { | 381 | { |
| 380 | printk(KERN_DEBUG "tr.c: Couldn't malloc rif cache entry !\n"); | 382 | printk(KERN_DEBUG "tr.c: Couldn't malloc rif cache entry !\n"); |
| 381 | spin_unlock_bh(&rif_lock); | 383 | spin_unlock_irqrestore(&rif_lock, flags); |
| 382 | return; | 384 | return; |
| 383 | } | 385 | } |
| 384 | 386 | ||
| @@ -420,7 +422,7 @@ printk("updating rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n", | |||
| 420 | } | 422 | } |
| 421 | entry->last_used=jiffies; | 423 | entry->last_used=jiffies; |
| 422 | } | 424 | } |
| 423 | spin_unlock_bh(&rif_lock); | 425 | spin_unlock_irqrestore(&rif_lock, flags); |
| 424 | } | 426 | } |
| 425 | 427 | ||
| 426 | /* | 428 | /* |
| @@ -430,9 +432,9 @@ printk("updating rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n", | |||
| 430 | static void rif_check_expire(unsigned long dummy) | 432 | static void rif_check_expire(unsigned long dummy) |
| 431 | { | 433 | { |
| 432 | int i; | 434 | int i; |
| 433 | unsigned long next_interval = jiffies + sysctl_tr_rif_timeout/2; | 435 | unsigned long flags, next_interval = jiffies + sysctl_tr_rif_timeout/2; |
| 434 | 436 | ||
| 435 | spin_lock_bh(&rif_lock); | 437 | spin_lock_irqsave(&rif_lock, flags); |
| 436 | 438 | ||
| 437 | for(i =0; i < RIF_TABLE_SIZE; i++) { | 439 | for(i =0; i < RIF_TABLE_SIZE; i++) { |
| 438 | struct rif_cache *entry, **pentry; | 440 | struct rif_cache *entry, **pentry; |
| @@ -454,7 +456,7 @@ static void rif_check_expire(unsigned long dummy) | |||
| 454 | } | 456 | } |
| 455 | } | 457 | } |
| 456 | 458 | ||
| 457 | spin_unlock_bh(&rif_lock); | 459 | spin_unlock_irqrestore(&rif_lock, flags); |
| 458 | 460 | ||
| 459 | mod_timer(&rif_timer, next_interval); | 461 | mod_timer(&rif_timer, next_interval); |
| 460 | 462 | ||
| @@ -485,7 +487,7 @@ static struct rif_cache *rif_get_idx(loff_t pos) | |||
| 485 | 487 | ||
| 486 | static void *rif_seq_start(struct seq_file *seq, loff_t *pos) | 488 | static void *rif_seq_start(struct seq_file *seq, loff_t *pos) |
| 487 | { | 489 | { |
| 488 | spin_lock_bh(&rif_lock); | 490 | spin_lock_irq(&rif_lock); |
| 489 | 491 | ||
| 490 | return *pos ? rif_get_idx(*pos - 1) : SEQ_START_TOKEN; | 492 | return *pos ? rif_get_idx(*pos - 1) : SEQ_START_TOKEN; |
| 491 | } | 493 | } |
| @@ -516,7 +518,7 @@ static void *rif_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
| 516 | 518 | ||
| 517 | static void rif_seq_stop(struct seq_file *seq, void *v) | 519 | static void rif_seq_stop(struct seq_file *seq, void *v) |
| 518 | { | 520 | { |
| 519 | spin_unlock_bh(&rif_lock); | 521 | spin_unlock_irq(&rif_lock); |
| 520 | } | 522 | } |
| 521 | 523 | ||
| 522 | static int rif_seq_show(struct seq_file *seq, void *v) | 524 | static int rif_seq_show(struct seq_file *seq, void *v) |
diff --git a/net/core/dev.c b/net/core/dev.c index 52a3bf7ae177..faf59b02c4bf 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -1696,7 +1696,8 @@ static void net_rx_action(struct softirq_action *h) | |||
| 1696 | struct softnet_data *queue = &__get_cpu_var(softnet_data); | 1696 | struct softnet_data *queue = &__get_cpu_var(softnet_data); |
| 1697 | unsigned long start_time = jiffies; | 1697 | unsigned long start_time = jiffies; |
| 1698 | int budget = netdev_budget; | 1698 | int budget = netdev_budget; |
| 1699 | 1699 | void *have; | |
| 1700 | |||
| 1700 | local_irq_disable(); | 1701 | local_irq_disable(); |
| 1701 | 1702 | ||
| 1702 | while (!list_empty(&queue->poll_list)) { | 1703 | while (!list_empty(&queue->poll_list)) { |
| @@ -1709,10 +1710,10 @@ static void net_rx_action(struct softirq_action *h) | |||
| 1709 | 1710 | ||
| 1710 | dev = list_entry(queue->poll_list.next, | 1711 | dev = list_entry(queue->poll_list.next, |
| 1711 | struct net_device, poll_list); | 1712 | struct net_device, poll_list); |
| 1712 | netpoll_poll_lock(dev); | 1713 | have = netpoll_poll_lock(dev); |
| 1713 | 1714 | ||
| 1714 | if (dev->quota <= 0 || dev->poll(dev, &budget)) { | 1715 | if (dev->quota <= 0 || dev->poll(dev, &budget)) { |
| 1715 | netpoll_poll_unlock(dev); | 1716 | netpoll_poll_unlock(have); |
| 1716 | local_irq_disable(); | 1717 | local_irq_disable(); |
| 1717 | list_del(&dev->poll_list); | 1718 | list_del(&dev->poll_list); |
| 1718 | list_add_tail(&dev->poll_list, &queue->poll_list); | 1719 | list_add_tail(&dev->poll_list, &queue->poll_list); |
| @@ -1721,7 +1722,7 @@ static void net_rx_action(struct softirq_action *h) | |||
| 1721 | else | 1722 | else |
| 1722 | dev->quota = dev->weight; | 1723 | dev->quota = dev->weight; |
| 1723 | } else { | 1724 | } else { |
| 1724 | netpoll_poll_unlock(dev); | 1725 | netpoll_poll_unlock(have); |
| 1725 | dev_put(dev); | 1726 | dev_put(dev); |
| 1726 | local_irq_disable(); | 1727 | local_irq_disable(); |
| 1727 | } | 1728 | } |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index c327c9edadc5..a1a9a7abff50 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #define MAX_UDP_CHUNK 1460 | 33 | #define MAX_UDP_CHUNK 1460 |
| 34 | #define MAX_SKBS 32 | 34 | #define MAX_SKBS 32 |
| 35 | #define MAX_QUEUE_DEPTH (MAX_SKBS / 2) | 35 | #define MAX_QUEUE_DEPTH (MAX_SKBS / 2) |
| 36 | #define MAX_RETRIES 20000 | ||
| 36 | 37 | ||
| 37 | static DEFINE_SPINLOCK(skb_list_lock); | 38 | static DEFINE_SPINLOCK(skb_list_lock); |
| 38 | static int nr_skbs; | 39 | static int nr_skbs; |
| @@ -248,14 +249,14 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) | |||
| 248 | int status; | 249 | int status; |
| 249 | struct netpoll_info *npinfo; | 250 | struct netpoll_info *npinfo; |
| 250 | 251 | ||
| 251 | repeat: | 252 | if (!np || !np->dev || !netif_running(np->dev)) { |
| 252 | if(!np || !np->dev || !netif_running(np->dev)) { | ||
| 253 | __kfree_skb(skb); | 253 | __kfree_skb(skb); |
| 254 | return; | 254 | return; |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | /* avoid recursion */ | ||
| 258 | npinfo = np->dev->npinfo; | 257 | npinfo = np->dev->npinfo; |
| 258 | |||
| 259 | /* avoid recursion */ | ||
| 259 | if (npinfo->poll_owner == smp_processor_id() || | 260 | if (npinfo->poll_owner == smp_processor_id() || |
| 260 | np->dev->xmit_lock_owner == smp_processor_id()) { | 261 | np->dev->xmit_lock_owner == smp_processor_id()) { |
| 261 | if (np->drop) | 262 | if (np->drop) |
| @@ -265,30 +266,37 @@ repeat: | |||
| 265 | return; | 266 | return; |
| 266 | } | 267 | } |
| 267 | 268 | ||
| 268 | spin_lock(&np->dev->xmit_lock); | 269 | do { |
| 269 | np->dev->xmit_lock_owner = smp_processor_id(); | 270 | npinfo->tries--; |
| 271 | spin_lock(&np->dev->xmit_lock); | ||
| 272 | np->dev->xmit_lock_owner = smp_processor_id(); | ||
| 270 | 273 | ||
| 271 | /* | 274 | /* |
| 272 | * network drivers do not expect to be called if the queue is | 275 | * network drivers do not expect to be called if the queue is |
| 273 | * stopped. | 276 | * stopped. |
| 274 | */ | 277 | */ |
| 275 | if (netif_queue_stopped(np->dev)) { | 278 | if (netif_queue_stopped(np->dev)) { |
| 279 | np->dev->xmit_lock_owner = -1; | ||
| 280 | spin_unlock(&np->dev->xmit_lock); | ||
| 281 | netpoll_poll(np); | ||
| 282 | udelay(50); | ||
| 283 | continue; | ||
| 284 | } | ||
| 285 | |||
| 286 | status = np->dev->hard_start_xmit(skb, np->dev); | ||
| 276 | np->dev->xmit_lock_owner = -1; | 287 | np->dev->xmit_lock_owner = -1; |
| 277 | spin_unlock(&np->dev->xmit_lock); | 288 | spin_unlock(&np->dev->xmit_lock); |
| 278 | 289 | ||
| 279 | netpoll_poll(np); | 290 | /* success */ |
| 280 | goto repeat; | 291 | if(!status) { |
| 281 | } | 292 | npinfo->tries = MAX_RETRIES; /* reset */ |
| 282 | 293 | return; | |
| 283 | status = np->dev->hard_start_xmit(skb, np->dev); | 294 | } |
| 284 | np->dev->xmit_lock_owner = -1; | ||
| 285 | spin_unlock(&np->dev->xmit_lock); | ||
| 286 | 295 | ||
| 287 | /* transmit busy */ | 296 | /* transmit busy */ |
| 288 | if(status) { | ||
| 289 | netpoll_poll(np); | 297 | netpoll_poll(np); |
| 290 | goto repeat; | 298 | udelay(50); |
| 291 | } | 299 | } while (npinfo->tries > 0); |
| 292 | } | 300 | } |
| 293 | 301 | ||
| 294 | void netpoll_send_udp(struct netpoll *np, const char *msg, int len) | 302 | void netpoll_send_udp(struct netpoll *np, const char *msg, int len) |
| @@ -349,15 +357,11 @@ static void arp_reply(struct sk_buff *skb) | |||
| 349 | unsigned char *arp_ptr; | 357 | unsigned char *arp_ptr; |
| 350 | int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; | 358 | int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; |
| 351 | u32 sip, tip; | 359 | u32 sip, tip; |
| 352 | unsigned long flags; | ||
| 353 | struct sk_buff *send_skb; | 360 | struct sk_buff *send_skb; |
| 354 | struct netpoll *np = NULL; | 361 | struct netpoll *np = NULL; |
| 355 | 362 | ||
| 356 | spin_lock_irqsave(&npinfo->rx_lock, flags); | ||
| 357 | if (npinfo->rx_np && npinfo->rx_np->dev == skb->dev) | 363 | if (npinfo->rx_np && npinfo->rx_np->dev == skb->dev) |
| 358 | np = npinfo->rx_np; | 364 | np = npinfo->rx_np; |
| 359 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | ||
| 360 | |||
| 361 | if (!np) | 365 | if (!np) |
| 362 | return; | 366 | return; |
| 363 | 367 | ||
| @@ -639,9 +643,11 @@ int netpoll_setup(struct netpoll *np) | |||
| 639 | if (!npinfo) | 643 | if (!npinfo) |
| 640 | goto release; | 644 | goto release; |
| 641 | 645 | ||
| 646 | npinfo->rx_flags = 0; | ||
| 642 | npinfo->rx_np = NULL; | 647 | npinfo->rx_np = NULL; |
| 643 | npinfo->poll_lock = SPIN_LOCK_UNLOCKED; | 648 | npinfo->poll_lock = SPIN_LOCK_UNLOCKED; |
| 644 | npinfo->poll_owner = -1; | 649 | npinfo->poll_owner = -1; |
| 650 | npinfo->tries = MAX_RETRIES; | ||
| 645 | npinfo->rx_lock = SPIN_LOCK_UNLOCKED; | 651 | npinfo->rx_lock = SPIN_LOCK_UNLOCKED; |
| 646 | } else | 652 | } else |
| 647 | npinfo = ndev->npinfo; | 653 | npinfo = ndev->npinfo; |
| @@ -718,9 +724,16 @@ int netpoll_setup(struct netpoll *np) | |||
| 718 | npinfo->rx_np = np; | 724 | npinfo->rx_np = np; |
| 719 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | 725 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); |
| 720 | } | 726 | } |
| 727 | |||
| 728 | /* fill up the skb queue */ | ||
| 729 | refill_skbs(); | ||
| 730 | |||
| 721 | /* last thing to do is link it to the net device structure */ | 731 | /* last thing to do is link it to the net device structure */ |
| 722 | ndev->npinfo = npinfo; | 732 | ndev->npinfo = npinfo; |
| 723 | 733 | ||
| 734 | /* avoid racing with NAPI reading npinfo */ | ||
| 735 | synchronize_rcu(); | ||
| 736 | |||
| 724 | return 0; | 737 | return 0; |
| 725 | 738 | ||
| 726 | release: | 739 | release: |
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index f32dba9e26fe..8d0cc3cf3e49 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c | |||
| @@ -148,12 +148,12 @@ static int dn_neigh_construct(struct neighbour *neigh) | |||
| 148 | 148 | ||
| 149 | __neigh_parms_put(neigh->parms); | 149 | __neigh_parms_put(neigh->parms); |
| 150 | neigh->parms = neigh_parms_clone(parms); | 150 | neigh->parms = neigh_parms_clone(parms); |
| 151 | rcu_read_unlock(); | ||
| 152 | 151 | ||
| 153 | if (dn_db->use_long) | 152 | if (dn_db->use_long) |
| 154 | neigh->ops = &dn_long_ops; | 153 | neigh->ops = &dn_long_ops; |
| 155 | else | 154 | else |
| 156 | neigh->ops = &dn_short_ops; | 155 | neigh->ops = &dn_short_ops; |
| 156 | rcu_read_unlock(); | ||
| 157 | 157 | ||
| 158 | if (dn->flags & DN_NDFLAG_P3) | 158 | if (dn->flags & DN_NDFLAG_P3) |
| 159 | neigh->ops = &dn_phase3_ops; | 159 | neigh->ops = &dn_phase3_ops; |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 3d78464f64ea..badfc5849973 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
| @@ -349,12 +349,12 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param, | |||
| 349 | { | 349 | { |
| 350 | struct sk_buff *skb; | 350 | struct sk_buff *skb; |
| 351 | 351 | ||
| 352 | ip_append_data(icmp_socket->sk, icmp_glue_bits, icmp_param, | 352 | if (ip_append_data(icmp_socket->sk, icmp_glue_bits, icmp_param, |
| 353 | icmp_param->data_len+icmp_param->head_len, | 353 | icmp_param->data_len+icmp_param->head_len, |
| 354 | icmp_param->head_len, | 354 | icmp_param->head_len, |
| 355 | ipc, rt, MSG_DONTWAIT); | 355 | ipc, rt, MSG_DONTWAIT) < 0) |
| 356 | 356 | ip_flush_pending_frames(icmp_socket->sk); | |
| 357 | if ((skb = skb_peek(&icmp_socket->sk->sk_write_queue)) != NULL) { | 357 | else if ((skb = skb_peek(&icmp_socket->sk->sk_write_queue)) != NULL) { |
| 358 | struct icmphdr *icmph = skb->h.icmph; | 358 | struct icmphdr *icmph = skb->h.icmph; |
| 359 | unsigned int csum = 0; | 359 | unsigned int csum = 0; |
| 360 | struct sk_buff *skb1; | 360 | struct sk_buff *skb1; |
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 2065944fd9e5..7ded6e60f43a 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c | |||
| @@ -358,7 +358,7 @@ static struct crypto_tfm **ipcomp_alloc_tfms(const char *alg_name) | |||
| 358 | int cpu; | 358 | int cpu; |
| 359 | 359 | ||
| 360 | /* This can be any valid CPU ID so we don't need locking. */ | 360 | /* This can be any valid CPU ID so we don't need locking. */ |
| 361 | cpu = smp_processor_id(); | 361 | cpu = raw_smp_processor_id(); |
| 362 | 362 | ||
| 363 | list_for_each_entry(pos, &ipcomp_tfms_list, list) { | 363 | list_for_each_entry(pos, &ipcomp_tfms_list, list) { |
| 364 | struct crypto_tfm *tfm; | 364 | struct crypto_tfm *tfm; |
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c index ada9911118e9..94a0ce1c1c9d 100644 --- a/net/ipv4/netfilter/ipt_ECN.c +++ b/net/ipv4/netfilter/ipt_ECN.c | |||
| @@ -61,16 +61,20 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo, int inward) | |||
| 61 | if (!tcph) | 61 | if (!tcph) |
| 62 | return 0; | 62 | return 0; |
| 63 | 63 | ||
| 64 | if (!(einfo->operation & IPT_ECN_OP_SET_ECE | 64 | if ((!(einfo->operation & IPT_ECN_OP_SET_ECE) || |
| 65 | || tcph->ece == einfo->proto.tcp.ece) | 65 | tcph->ece == einfo->proto.tcp.ece) && |
| 66 | && (!(einfo->operation & IPT_ECN_OP_SET_CWR | 66 | ((!(einfo->operation & IPT_ECN_OP_SET_CWR) || |
| 67 | || tcph->cwr == einfo->proto.tcp.cwr))) | 67 | tcph->cwr == einfo->proto.tcp.cwr))) |
| 68 | return 1; | 68 | return 1; |
| 69 | 69 | ||
| 70 | if (!skb_ip_make_writable(pskb, (*pskb)->nh.iph->ihl*4+sizeof(*tcph))) | 70 | if (!skb_ip_make_writable(pskb, (*pskb)->nh.iph->ihl*4+sizeof(*tcph))) |
| 71 | return 0; | 71 | return 0; |
| 72 | tcph = (void *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl*4; | 72 | tcph = (void *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl*4; |
| 73 | 73 | ||
| 74 | if ((*pskb)->ip_summed == CHECKSUM_HW && | ||
| 75 | skb_checksum_help(*pskb, inward)) | ||
| 76 | return 0; | ||
| 77 | |||
| 74 | diffs[0] = ((u_int16_t *)tcph)[6]; | 78 | diffs[0] = ((u_int16_t *)tcph)[6]; |
| 75 | if (einfo->operation & IPT_ECN_OP_SET_ECE) | 79 | if (einfo->operation & IPT_ECN_OP_SET_ECE) |
| 76 | tcph->ece = einfo->proto.tcp.ece; | 80 | tcph->ece = einfo->proto.tcp.ece; |
| @@ -79,13 +83,10 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo, int inward) | |||
| 79 | diffs[1] = ((u_int16_t *)tcph)[6]; | 83 | diffs[1] = ((u_int16_t *)tcph)[6]; |
| 80 | diffs[0] = diffs[0] ^ 0xFFFF; | 84 | diffs[0] = diffs[0] ^ 0xFFFF; |
| 81 | 85 | ||
| 82 | if ((*pskb)->ip_summed != CHECKSUM_HW) | 86 | if ((*pskb)->ip_summed != CHECKSUM_UNNECESSARY) |
| 83 | tcph->check = csum_fold(csum_partial((char *)diffs, | 87 | tcph->check = csum_fold(csum_partial((char *)diffs, |
| 84 | sizeof(diffs), | 88 | sizeof(diffs), |
| 85 | tcph->check^0xFFFF)); | 89 | tcph->check^0xFFFF)); |
| 86 | else | ||
| 87 | if (skb_checksum_help(*pskb, inward)) | ||
| 88 | return 0; | ||
| 89 | (*pskb)->nfcache |= NFC_ALTERED; | 90 | (*pskb)->nfcache |= NFC_ALTERED; |
| 90 | return 1; | 91 | return 1; |
| 91 | } | 92 | } |
diff --git a/net/ipv4/netfilter/ipt_TCPMSS.c b/net/ipv4/netfilter/ipt_TCPMSS.c index 1049050b2bfb..7b84a254440e 100644 --- a/net/ipv4/netfilter/ipt_TCPMSS.c +++ b/net/ipv4/netfilter/ipt_TCPMSS.c | |||
| @@ -61,6 +61,10 @@ ipt_tcpmss_target(struct sk_buff **pskb, | |||
| 61 | if (!skb_ip_make_writable(pskb, (*pskb)->len)) | 61 | if (!skb_ip_make_writable(pskb, (*pskb)->len)) |
| 62 | return NF_DROP; | 62 | return NF_DROP; |
| 63 | 63 | ||
| 64 | if ((*pskb)->ip_summed == CHECKSUM_HW && | ||
| 65 | skb_checksum_help(*pskb, out == NULL)) | ||
| 66 | return NF_DROP; | ||
| 67 | |||
| 64 | iph = (*pskb)->nh.iph; | 68 | iph = (*pskb)->nh.iph; |
| 65 | tcplen = (*pskb)->len - iph->ihl*4; | 69 | tcplen = (*pskb)->len - iph->ihl*4; |
| 66 | 70 | ||
| @@ -186,9 +190,6 @@ ipt_tcpmss_target(struct sk_buff **pskb, | |||
| 186 | newmss); | 190 | newmss); |
| 187 | 191 | ||
| 188 | retmodified: | 192 | retmodified: |
| 189 | /* We never hw checksum SYN packets. */ | ||
| 190 | BUG_ON((*pskb)->ip_summed == CHECKSUM_HW); | ||
| 191 | |||
| 192 | (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED; | 193 | (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED; |
| 193 | return IPT_CONTINUE; | 194 | return IPT_CONTINUE; |
| 194 | } | 195 | } |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 7d076f0db100..566045e58437 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
| @@ -861,7 +861,8 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len, | |||
| 861 | u16 flags; | 861 | u16 flags; |
| 862 | 862 | ||
| 863 | /* All of a TSO frame must be composed of paged data. */ | 863 | /* All of a TSO frame must be composed of paged data. */ |
| 864 | BUG_ON(skb->len != skb->data_len); | 864 | if (skb->len != skb->data_len) |
| 865 | return tcp_fragment(sk, skb, len, mss_now); | ||
| 865 | 866 | ||
| 866 | buff = sk_stream_alloc_pskb(sk, 0, 0, GFP_ATOMIC); | 867 | buff = sk_stream_alloc_pskb(sk, 0, 0, GFP_ATOMIC); |
| 867 | if (unlikely(buff == NULL)) | 868 | if (unlikely(buff == NULL)) |
| @@ -974,6 +975,8 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) | |||
| 974 | 975 | ||
| 975 | sent_pkts = 0; | 976 | sent_pkts = 0; |
| 976 | while ((skb = sk->sk_send_head)) { | 977 | while ((skb = sk->sk_send_head)) { |
| 978 | unsigned int limit; | ||
| 979 | |||
| 977 | tso_segs = tcp_init_tso_segs(sk, skb, mss_now); | 980 | tso_segs = tcp_init_tso_segs(sk, skb, mss_now); |
| 978 | BUG_ON(!tso_segs); | 981 | BUG_ON(!tso_segs); |
| 979 | 982 | ||
| @@ -994,9 +997,10 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) | |||
| 994 | break; | 997 | break; |
| 995 | } | 998 | } |
| 996 | 999 | ||
| 1000 | limit = mss_now; | ||
| 997 | if (tso_segs > 1) { | 1001 | if (tso_segs > 1) { |
| 998 | u32 limit = tcp_window_allows(tp, skb, | 1002 | limit = tcp_window_allows(tp, skb, |
| 999 | mss_now, cwnd_quota); | 1003 | mss_now, cwnd_quota); |
| 1000 | 1004 | ||
| 1001 | if (skb->len < limit) { | 1005 | if (skb->len < limit) { |
| 1002 | unsigned int trim = skb->len % mss_now; | 1006 | unsigned int trim = skb->len % mss_now; |
| @@ -1004,15 +1008,12 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) | |||
| 1004 | if (trim) | 1008 | if (trim) |
| 1005 | limit = skb->len - trim; | 1009 | limit = skb->len - trim; |
| 1006 | } | 1010 | } |
| 1007 | if (skb->len > limit) { | ||
| 1008 | if (tso_fragment(sk, skb, limit, mss_now)) | ||
| 1009 | break; | ||
| 1010 | } | ||
| 1011 | } else if (unlikely(skb->len > mss_now)) { | ||
| 1012 | if (unlikely(tcp_fragment(sk, skb, mss_now, mss_now))) | ||
| 1013 | break; | ||
| 1014 | } | 1011 | } |
| 1015 | 1012 | ||
| 1013 | if (skb->len > limit && | ||
| 1014 | unlikely(tso_fragment(sk, skb, limit, mss_now))) | ||
| 1015 | break; | ||
| 1016 | |||
| 1016 | TCP_SKB_CB(skb)->when = tcp_time_stamp; | 1017 | TCP_SKB_CB(skb)->when = tcp_time_stamp; |
| 1017 | 1018 | ||
| 1018 | if (unlikely(tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)))) | 1019 | if (unlikely(tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)))) |
| @@ -1064,11 +1065,14 @@ void tcp_push_one(struct sock *sk, unsigned int mss_now) | |||
| 1064 | cwnd_quota = tcp_snd_test(sk, skb, mss_now, TCP_NAGLE_PUSH); | 1065 | cwnd_quota = tcp_snd_test(sk, skb, mss_now, TCP_NAGLE_PUSH); |
| 1065 | 1066 | ||
| 1066 | if (likely(cwnd_quota)) { | 1067 | if (likely(cwnd_quota)) { |
| 1068 | unsigned int limit; | ||
| 1069 | |||
| 1067 | BUG_ON(!tso_segs); | 1070 | BUG_ON(!tso_segs); |
| 1068 | 1071 | ||
| 1072 | limit = mss_now; | ||
| 1069 | if (tso_segs > 1) { | 1073 | if (tso_segs > 1) { |
| 1070 | u32 limit = tcp_window_allows(tp, skb, | 1074 | limit = tcp_window_allows(tp, skb, |
| 1071 | mss_now, cwnd_quota); | 1075 | mss_now, cwnd_quota); |
| 1072 | 1076 | ||
| 1073 | if (skb->len < limit) { | 1077 | if (skb->len < limit) { |
| 1074 | unsigned int trim = skb->len % mss_now; | 1078 | unsigned int trim = skb->len % mss_now; |
| @@ -1076,15 +1080,12 @@ void tcp_push_one(struct sock *sk, unsigned int mss_now) | |||
| 1076 | if (trim) | 1080 | if (trim) |
| 1077 | limit = skb->len - trim; | 1081 | limit = skb->len - trim; |
| 1078 | } | 1082 | } |
| 1079 | if (skb->len > limit) { | ||
| 1080 | if (unlikely(tso_fragment(sk, skb, limit, mss_now))) | ||
| 1081 | return; | ||
| 1082 | } | ||
| 1083 | } else if (unlikely(skb->len > mss_now)) { | ||
| 1084 | if (unlikely(tcp_fragment(sk, skb, mss_now, mss_now))) | ||
| 1085 | return; | ||
| 1086 | } | 1083 | } |
| 1087 | 1084 | ||
| 1085 | if (skb->len > limit && | ||
| 1086 | unlikely(tso_fragment(sk, skb, limit, mss_now))) | ||
| 1087 | return; | ||
| 1088 | |||
| 1088 | /* Send it out now. */ | 1089 | /* Send it out now. */ |
| 1089 | TCP_SKB_CB(skb)->when = tcp_time_stamp; | 1090 | TCP_SKB_CB(skb)->when = tcp_time_stamp; |
| 1090 | 1091 | ||
| @@ -1370,15 +1371,21 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
| 1370 | 1371 | ||
| 1371 | if (skb->len > cur_mss) { | 1372 | if (skb->len > cur_mss) { |
| 1372 | int old_factor = tcp_skb_pcount(skb); | 1373 | int old_factor = tcp_skb_pcount(skb); |
| 1373 | int new_factor; | 1374 | int diff; |
| 1374 | 1375 | ||
| 1375 | if (tcp_fragment(sk, skb, cur_mss, cur_mss)) | 1376 | if (tcp_fragment(sk, skb, cur_mss, cur_mss)) |
| 1376 | return -ENOMEM; /* We'll try again later. */ | 1377 | return -ENOMEM; /* We'll try again later. */ |
| 1377 | 1378 | ||
| 1378 | /* New SKB created, account for it. */ | 1379 | /* New SKB created, account for it. */ |
| 1379 | new_factor = tcp_skb_pcount(skb); | 1380 | diff = old_factor - tcp_skb_pcount(skb) - |
| 1380 | tp->packets_out -= old_factor - new_factor; | 1381 | tcp_skb_pcount(skb->next); |
| 1381 | tp->packets_out += tcp_skb_pcount(skb->next); | 1382 | tp->packets_out -= diff; |
| 1383 | |||
| 1384 | if (diff > 0) { | ||
| 1385 | tp->fackets_out -= diff; | ||
| 1386 | if ((int)tp->fackets_out < 0) | ||
| 1387 | tp->fackets_out = 0; | ||
| 1388 | } | ||
| 1382 | } | 1389 | } |
| 1383 | 1390 | ||
| 1384 | /* Collapse two adjacent packets if worthwhile and we can. */ | 1391 | /* Collapse two adjacent packets if worthwhile and we can. */ |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 866f10726c58..10fbb50daea4 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
| @@ -198,12 +198,13 @@ resubmit: | |||
| 198 | if (!raw_sk) { | 198 | if (!raw_sk) { |
| 199 | if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { | 199 | if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { |
| 200 | IP6_INC_STATS_BH(IPSTATS_MIB_INUNKNOWNPROTOS); | 200 | IP6_INC_STATS_BH(IPSTATS_MIB_INUNKNOWNPROTOS); |
| 201 | icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR, nhoff); | 201 | icmpv6_send(skb, ICMPV6_PARAMPROB, |
| 202 | ICMPV6_UNK_NEXTHDR, nhoff, | ||
| 203 | skb->dev); | ||
| 202 | } | 204 | } |
| 203 | } else { | 205 | } else |
| 204 | IP6_INC_STATS_BH(IPSTATS_MIB_INDELIVERS); | 206 | IP6_INC_STATS_BH(IPSTATS_MIB_INDELIVERS); |
| 205 | kfree_skb(skb); | 207 | kfree_skb(skb); |
| 206 | } | ||
| 207 | } | 208 | } |
| 208 | rcu_read_unlock(); | 209 | rcu_read_unlock(); |
| 209 | return 0; | 210 | return 0; |
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 423feb46ccc0..135383ef538f 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
| @@ -354,7 +354,7 @@ static struct crypto_tfm **ipcomp6_alloc_tfms(const char *alg_name) | |||
| 354 | int cpu; | 354 | int cpu; |
| 355 | 355 | ||
| 356 | /* This can be any valid CPU ID so we don't need locking. */ | 356 | /* This can be any valid CPU ID so we don't need locking. */ |
| 357 | cpu = smp_processor_id(); | 357 | cpu = raw_smp_processor_id(); |
| 358 | 358 | ||
| 359 | list_for_each_entry(pos, &ipcomp6_tfms_list, list) { | 359 | list_for_each_entry(pos, &ipcomp6_tfms_list, list) { |
| 360 | struct crypto_tfm *tfm; | 360 | struct crypto_tfm *tfm; |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index e2b848ec9851..1d4d75b34d32 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
| @@ -328,6 +328,8 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb) | |||
| 328 | 328 | ||
| 329 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) { | 329 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) { |
| 330 | if (skb->ip_summed == CHECKSUM_HW) { | 330 | if (skb->ip_summed == CHECKSUM_HW) { |
| 331 | skb_postpull_rcsum(skb, skb->nh.raw, | ||
| 332 | skb->h.raw - skb->nh.raw); | ||
| 331 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 333 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
| 332 | if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, | 334 | if (csum_ipv6_magic(&skb->nh.ipv6h->saddr, |
| 333 | &skb->nh.ipv6h->daddr, | 335 | &skb->nh.ipv6h->daddr, |
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 8a4d9c106af1..fde16f40a581 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
| @@ -993,6 +993,7 @@ xdr_xcode_array2(struct xdr_buf *buf, unsigned int base, | |||
| 993 | return -EINVAL; | 993 | return -EINVAL; |
| 994 | } else { | 994 | } else { |
| 995 | if (xdr_decode_word(buf, base, &desc->array_len) != 0 || | 995 | if (xdr_decode_word(buf, base, &desc->array_len) != 0 || |
| 996 | desc->array_len > desc->array_maxlen || | ||
| 996 | (unsigned long) base + 4 + desc->array_len * | 997 | (unsigned long) base + 4 + desc->array_len * |
| 997 | desc->elem_size > buf->len) | 998 | desc->elem_size > buf->len) |
| 998 | return -EINVAL; | 999 | return -EINVAL; |
