aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-10-23 22:19:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-23 22:19:54 -0400
commit2242d5eff17cf91110a3c44747f9f2e1a938cbda (patch)
treea6459b4d1aeb7f6f08dea3db2e2780f6276abdb0 /net
parent5579a782ad7ffa162b1060993e4a298dd50e7a33 (diff)
parentfd6149d332973bafa50f03ddb0ea9513e67f4517 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (29 commits) tcp: Restore ordering of TCP options for the sake of inter-operability net: Fix disjunct computation of netdev features sctp: Fix to handle SHUTDOWN in SHUTDOWN_RECEIVED state sctp: Fix to handle SHUTDOWN in SHUTDOWN-PENDING state sctp: Add check for the TSN field of the SHUTDOWN chunk sctp: Drop ICMP packet too big message with MTU larger than current PMTU p54: enable 2.4/5GHz spectrum by eeprom bits. orinoco: reduce stack usage in firmware download path ath5k: fix suspend-related oops on rmmod [netdrvr] fec_mpc52xx: Implement polling, to make netconsole work. qlge: Fix MSI/legacy single interrupt bug. smc911x: Make the driver safer on SMP smc911x: Add IRQ polarity configuration smc911x: Allow Kconfig dependency on ARM sis190: add identifier for Atheros AR8021 PHY 8139x: reduce message severity on driver overlap igb: add IGB_DCA instead of selecting INTEL_IOATDMA igb: fix tx data corruption with transition to L0s on 82575 ehea: Fix memory hotplug support netdev: DM9000: remove BLACKFIN hacking in DM9000 netdev driver ...
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_device.c2
-rw-r--r--net/bridge/br_if.c14
-rw-r--r--net/core/dev.c135
-rw-r--r--net/ipv4/tcp_output.c25
-rw-r--r--net/sctp/input.c2
-rw-r--r--net/sctp/sm_statefuns.c54
-rw-r--r--net/sctp/sm_statetable.c4
7 files changed, 157 insertions, 79 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 22ba8632196f..6c023f0f8252 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -179,5 +179,5 @@ void br_dev_setup(struct net_device *dev)
179 179
180 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | 180 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
181 NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX | 181 NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX |
182 NETIF_F_NETNS_LOCAL; 182 NETIF_F_NETNS_LOCAL | NETIF_F_GSO;
183} 183}
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 573e20f7dba4..0a09ccf68c1c 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -347,15 +347,21 @@ int br_min_mtu(const struct net_bridge *br)
347void br_features_recompute(struct net_bridge *br) 347void br_features_recompute(struct net_bridge *br)
348{ 348{
349 struct net_bridge_port *p; 349 struct net_bridge_port *p;
350 unsigned long features; 350 unsigned long features, mask;
351 351
352 features = br->feature_mask; 352 features = mask = br->feature_mask;
353 if (list_empty(&br->port_list))
354 goto done;
355
356 features &= ~NETIF_F_ONE_FOR_ALL;
353 357
354 list_for_each_entry(p, &br->port_list, list) { 358 list_for_each_entry(p, &br->port_list, list) {
355 features = netdev_compute_features(features, p->dev->features); 359 features = netdev_increment_features(features,
360 p->dev->features, mask);
356 } 361 }
357 362
358 br->dev->features = features; 363done:
364 br->dev->features = netdev_fix_features(features, NULL);
359} 365}
360 366
361/* called with RTNL */ 367/* called with RTNL */
diff --git a/net/core/dev.c b/net/core/dev.c
index b8a4fd0806af..d9038e328cc1 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3947,6 +3947,46 @@ static void netdev_init_queue_locks(struct net_device *dev)
3947 __netdev_init_queue_locks_one(dev, &dev->rx_queue, NULL); 3947 __netdev_init_queue_locks_one(dev, &dev->rx_queue, NULL);
3948} 3948}
3949 3949
3950unsigned long netdev_fix_features(unsigned long features, const char *name)
3951{
3952 /* Fix illegal SG+CSUM combinations. */
3953 if ((features & NETIF_F_SG) &&
3954 !(features & NETIF_F_ALL_CSUM)) {
3955 if (name)
3956 printk(KERN_NOTICE "%s: Dropping NETIF_F_SG since no "
3957 "checksum feature.\n", name);
3958 features &= ~NETIF_F_SG;
3959 }
3960
3961 /* TSO requires that SG is present as well. */
3962 if ((features & NETIF_F_TSO) && !(features & NETIF_F_SG)) {
3963 if (name)
3964 printk(KERN_NOTICE "%s: Dropping NETIF_F_TSO since no "
3965 "SG feature.\n", name);
3966 features &= ~NETIF_F_TSO;
3967 }
3968
3969 if (features & NETIF_F_UFO) {
3970 if (!(features & NETIF_F_GEN_CSUM)) {
3971 if (name)
3972 printk(KERN_ERR "%s: Dropping NETIF_F_UFO "
3973 "since no NETIF_F_HW_CSUM feature.\n",
3974 name);
3975 features &= ~NETIF_F_UFO;
3976 }
3977
3978 if (!(features & NETIF_F_SG)) {
3979 if (name)
3980 printk(KERN_ERR "%s: Dropping NETIF_F_UFO "
3981 "since no NETIF_F_SG feature.\n", name);
3982 features &= ~NETIF_F_UFO;
3983 }
3984 }
3985
3986 return features;
3987}
3988EXPORT_SYMBOL(netdev_fix_features);
3989
3950/** 3990/**
3951 * register_netdevice - register a network device 3991 * register_netdevice - register a network device
3952 * @dev: device to register 3992 * @dev: device to register
@@ -4032,36 +4072,7 @@ int register_netdevice(struct net_device *dev)
4032 dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM); 4072 dev->features &= ~(NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM|NETIF_F_HW_CSUM);
4033 } 4073 }
4034 4074
4035 4075 dev->features = netdev_fix_features(dev->features, dev->name);
4036 /* Fix illegal SG+CSUM combinations. */
4037 if ((dev->features & NETIF_F_SG) &&
4038 !(dev->features & NETIF_F_ALL_CSUM)) {
4039 printk(KERN_NOTICE "%s: Dropping NETIF_F_SG since no checksum feature.\n",
4040 dev->name);
4041 dev->features &= ~NETIF_F_SG;
4042 }
4043
4044 /* TSO requires that SG is present as well. */
4045 if ((dev->features & NETIF_F_TSO) &&
4046 !(dev->features & NETIF_F_SG)) {
4047 printk(KERN_NOTICE "%s: Dropping NETIF_F_TSO since no SG feature.\n",
4048 dev->name);
4049 dev->features &= ~NETIF_F_TSO;
4050 }
4051 if (dev->features & NETIF_F_UFO) {
4052 if (!(dev->features & NETIF_F_HW_CSUM)) {
4053 printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no "
4054 "NETIF_F_HW_CSUM feature.\n",
4055 dev->name);
4056 dev->features &= ~NETIF_F_UFO;
4057 }
4058 if (!(dev->features & NETIF_F_SG)) {
4059 printk(KERN_ERR "%s: Dropping NETIF_F_UFO since no "
4060 "NETIF_F_SG feature.\n",
4061 dev->name);
4062 dev->features &= ~NETIF_F_UFO;
4063 }
4064 }
4065 4076
4066 /* Enable software GSO if SG is supported. */ 4077 /* Enable software GSO if SG is supported. */
4067 if (dev->features & NETIF_F_SG) 4078 if (dev->features & NETIF_F_SG)
@@ -4700,49 +4711,45 @@ static int __init netdev_dma_register(void) { return -ENODEV; }
4700#endif /* CONFIG_NET_DMA */ 4711#endif /* CONFIG_NET_DMA */
4701 4712
4702/** 4713/**
4703 * netdev_compute_feature - compute conjunction of two feature sets 4714 * netdev_increment_features - increment feature set by one
4704 * @all: first feature set 4715 * @all: current feature set
4705 * @one: second feature set 4716 * @one: new feature set
4717 * @mask: mask feature set
4706 * 4718 *
4707 * Computes a new feature set after adding a device with feature set 4719 * Computes a new feature set after adding a device with feature set
4708 * @one to the master device with current feature set @all. Returns 4720 * @one to the master device with current feature set @all. Will not
4709 * the new feature set. 4721 * enable anything that is off in @mask. Returns the new feature set.
4710 */ 4722 */
4711int netdev_compute_features(unsigned long all, unsigned long one) 4723unsigned long netdev_increment_features(unsigned long all, unsigned long one,
4712{ 4724 unsigned long mask)
4713 /* if device needs checksumming, downgrade to hw checksumming */ 4725{
4714 if (all & NETIF_F_NO_CSUM && !(one & NETIF_F_NO_CSUM)) 4726 /* If device needs checksumming, downgrade to it. */
4715 all ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM; 4727 if (all & NETIF_F_NO_CSUM && !(one & NETIF_F_NO_CSUM))
4716 4728 all ^= NETIF_F_NO_CSUM | (one & NETIF_F_ALL_CSUM);
4717 /* if device can't do all checksum, downgrade to ipv4/ipv6 */ 4729 else if (mask & NETIF_F_ALL_CSUM) {
4718 if (all & NETIF_F_HW_CSUM && !(one & NETIF_F_HW_CSUM)) 4730 /* If one device supports v4/v6 checksumming, set for all. */
4719 all ^= NETIF_F_HW_CSUM 4731 if (one & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM) &&
4720 | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; 4732 !(all & NETIF_F_GEN_CSUM)) {
4721 4733 all &= ~NETIF_F_ALL_CSUM;
4722 if (one & NETIF_F_GSO) 4734 all |= one & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM);
4723 one |= NETIF_F_GSO_SOFTWARE; 4735 }
4724 one |= NETIF_F_GSO;
4725
4726 /*
4727 * If even one device supports a GSO protocol with software fallback,
4728 * enable it for all.
4729 */
4730 all |= one & NETIF_F_GSO_SOFTWARE;
4731 4736
4732 /* If even one device supports robust GSO, enable it for all. */ 4737 /* If one device supports hw checksumming, set for all. */
4733 if (one & NETIF_F_GSO_ROBUST) 4738 if (one & NETIF_F_GEN_CSUM && !(all & NETIF_F_GEN_CSUM)) {
4734 all |= NETIF_F_GSO_ROBUST; 4739 all &= ~NETIF_F_ALL_CSUM;
4740 all |= NETIF_F_HW_CSUM;
4741 }
4742 }
4735 4743
4736 all &= one | NETIF_F_LLTX; 4744 one |= NETIF_F_ALL_CSUM;
4737 4745
4738 if (!(all & NETIF_F_ALL_CSUM)) 4746 one |= all & NETIF_F_ONE_FOR_ALL;
4739 all &= ~NETIF_F_SG; 4747 all &= one | NETIF_F_LLTX | NETIF_F_GSO;
4740 if (!(all & NETIF_F_SG)) 4748 all |= one & mask & NETIF_F_ONE_FOR_ALL;
4741 all &= ~NETIF_F_GSO_MASK;
4742 4749
4743 return all; 4750 return all;
4744} 4751}
4745EXPORT_SYMBOL(netdev_compute_features); 4752EXPORT_SYMBOL(netdev_increment_features);
4746 4753
4747static struct hlist_head *netdev_create_hash(void) 4754static struct hlist_head *netdev_create_hash(void)
4748{ 4755{
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 990a58493235..e4c5ac9fe89b 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -362,6 +362,17 @@ struct tcp_out_options {
362 __u32 tsval, tsecr; /* need to include OPTION_TS */ 362 __u32 tsval, tsecr; /* need to include OPTION_TS */
363}; 363};
364 364
365/* Beware: Something in the Internet is very sensitive to the ordering of
366 * TCP options, we learned this through the hard way, so be careful here.
367 * Luckily we can at least blame others for their non-compliance but from
368 * inter-operatibility perspective it seems that we're somewhat stuck with
369 * the ordering which we have been using if we want to keep working with
370 * those broken things (not that it currently hurts anybody as there isn't
371 * particular reason why the ordering would need to be changed).
372 *
373 * At least SACK_PERM as the first option is known to lead to a disaster
374 * (but it may well be that other scenarios fail similarly).
375 */
365static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, 376static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
366 const struct tcp_out_options *opts, 377 const struct tcp_out_options *opts,
367 __u8 **md5_hash) { 378 __u8 **md5_hash) {
@@ -376,6 +387,12 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
376 *md5_hash = NULL; 387 *md5_hash = NULL;
377 } 388 }
378 389
390 if (unlikely(opts->mss)) {
391 *ptr++ = htonl((TCPOPT_MSS << 24) |
392 (TCPOLEN_MSS << 16) |
393 opts->mss);
394 }
395
379 if (likely(OPTION_TS & opts->options)) { 396 if (likely(OPTION_TS & opts->options)) {
380 if (unlikely(OPTION_SACK_ADVERTISE & opts->options)) { 397 if (unlikely(OPTION_SACK_ADVERTISE & opts->options)) {
381 *ptr++ = htonl((TCPOPT_SACK_PERM << 24) | 398 *ptr++ = htonl((TCPOPT_SACK_PERM << 24) |
@@ -392,12 +409,6 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
392 *ptr++ = htonl(opts->tsecr); 409 *ptr++ = htonl(opts->tsecr);
393 } 410 }
394 411
395 if (unlikely(opts->mss)) {
396 *ptr++ = htonl((TCPOPT_MSS << 24) |
397 (TCPOLEN_MSS << 16) |
398 opts->mss);
399 }
400
401 if (unlikely(OPTION_SACK_ADVERTISE & opts->options && 412 if (unlikely(OPTION_SACK_ADVERTISE & opts->options &&
402 !(OPTION_TS & opts->options))) { 413 !(OPTION_TS & opts->options))) {
403 *ptr++ = htonl((TCPOPT_NOP << 24) | 414 *ptr++ = htonl((TCPOPT_NOP << 24) |
@@ -432,7 +443,7 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
432 443
433 if (tp->rx_opt.dsack) { 444 if (tp->rx_opt.dsack) {
434 tp->rx_opt.dsack = 0; 445 tp->rx_opt.dsack = 0;
435 tp->rx_opt.eff_sacks--; 446 tp->rx_opt.eff_sacks = tp->rx_opt.num_sacks;
436 } 447 }
437 } 448 }
438} 449}
diff --git a/net/sctp/input.c b/net/sctp/input.c
index a49fa80b57b9..bf612d954d41 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -369,7 +369,7 @@ static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb)
369void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, 369void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
370 struct sctp_transport *t, __u32 pmtu) 370 struct sctp_transport *t, __u32 pmtu)
371{ 371{
372 if (!t || (t->pathmtu == pmtu)) 372 if (!t || (t->pathmtu <= pmtu))
373 return; 373 return;
374 374
375 if (sock_owned_by_user(sk)) { 375 if (sock_owned_by_user(sk)) {
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index d4c3fbc4671e..a6a0ea71ae93 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -2544,6 +2544,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
2544 sctp_shutdownhdr_t *sdh; 2544 sctp_shutdownhdr_t *sdh;
2545 sctp_disposition_t disposition; 2545 sctp_disposition_t disposition;
2546 struct sctp_ulpevent *ev; 2546 struct sctp_ulpevent *ev;
2547 __u32 ctsn;
2547 2548
2548 if (!sctp_vtag_verify(chunk, asoc)) 2549 if (!sctp_vtag_verify(chunk, asoc))
2549 return sctp_sf_pdiscard(ep, asoc, type, arg, commands); 2550 return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -2558,6 +2559,14 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
2558 sdh = (sctp_shutdownhdr_t *)chunk->skb->data; 2559 sdh = (sctp_shutdownhdr_t *)chunk->skb->data;
2559 skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t)); 2560 skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t));
2560 chunk->subh.shutdown_hdr = sdh; 2561 chunk->subh.shutdown_hdr = sdh;
2562 ctsn = ntohl(sdh->cum_tsn_ack);
2563
2564 /* If Cumulative TSN Ack beyond the max tsn currently
2565 * send, terminating the association and respond to the
2566 * sender with an ABORT.
2567 */
2568 if (!TSN_lt(ctsn, asoc->next_tsn))
2569 return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands);
2561 2570
2562 /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT 2571 /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT
2563 * When a peer sends a SHUTDOWN, SCTP delivers this notification to 2572 * When a peer sends a SHUTDOWN, SCTP delivers this notification to
@@ -2599,6 +2608,51 @@ out:
2599 return disposition; 2608 return disposition;
2600} 2609}
2601 2610
2611/*
2612 * sctp_sf_do_9_2_shut_ctsn
2613 *
2614 * Once an endpoint has reached the SHUTDOWN-RECEIVED state,
2615 * it MUST NOT send a SHUTDOWN in response to a ULP request.
2616 * The Cumulative TSN Ack of the received SHUTDOWN chunk
2617 * MUST be processed.
2618 */
2619sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(const struct sctp_endpoint *ep,
2620 const struct sctp_association *asoc,
2621 const sctp_subtype_t type,
2622 void *arg,
2623 sctp_cmd_seq_t *commands)
2624{
2625 struct sctp_chunk *chunk = arg;
2626 sctp_shutdownhdr_t *sdh;
2627
2628 if (!sctp_vtag_verify(chunk, asoc))
2629 return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
2630
2631 /* Make sure that the SHUTDOWN chunk has a valid length. */
2632 if (!sctp_chunk_length_valid(chunk,
2633 sizeof(struct sctp_shutdown_chunk_t)))
2634 return sctp_sf_violation_chunklen(ep, asoc, type, arg,
2635 commands);
2636
2637 sdh = (sctp_shutdownhdr_t *)chunk->skb->data;
2638
2639 /* If Cumulative TSN Ack beyond the max tsn currently
2640 * send, terminating the association and respond to the
2641 * sender with an ABORT.
2642 */
2643 if (!TSN_lt(ntohl(sdh->cum_tsn_ack), asoc->next_tsn))
2644 return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands);
2645
2646 /* verify, by checking the Cumulative TSN Ack field of the
2647 * chunk, that all its outstanding DATA chunks have been
2648 * received by the SHUTDOWN sender.
2649 */
2650 sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN,
2651 SCTP_BE32(sdh->cum_tsn_ack));
2652
2653 return SCTP_DISPOSITION_CONSUME;
2654}
2655
2602/* RFC 2960 9.2 2656/* RFC 2960 9.2
2603 * If an endpoint is in SHUTDOWN-ACK-SENT state and receives an INIT chunk 2657 * If an endpoint is in SHUTDOWN-ACK-SENT state and receives an INIT chunk
2604 * (e.g., if the SHUTDOWN COMPLETE was lost) with source and destination 2658 * (e.g., if the SHUTDOWN COMPLETE was lost) with source and destination
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index dd4ddc40c0ad..5c8186d88c61 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -266,11 +266,11 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
266 /* SCTP_STATE_ESTABLISHED */ \ 266 /* SCTP_STATE_ESTABLISHED */ \
267 TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown), \ 267 TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown), \
268 /* SCTP_STATE_SHUTDOWN_PENDING */ \ 268 /* SCTP_STATE_SHUTDOWN_PENDING */ \
269 TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ 269 TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown), \
270 /* SCTP_STATE_SHUTDOWN_SENT */ \ 270 /* SCTP_STATE_SHUTDOWN_SENT */ \
271 TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown_ack), \ 271 TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown_ack), \
272 /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ 272 /* SCTP_STATE_SHUTDOWN_RECEIVED */ \
273 TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ 273 TYPE_SCTP_FUNC(sctp_sf_do_9_2_shut_ctsn), \
274 /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ 274 /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
275 TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ 275 TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
276} /* TYPE_SCTP_SHUTDOWN */ 276} /* TYPE_SCTP_SHUTDOWN */