diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-23 22:19:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-23 22:19:54 -0400 |
commit | 2242d5eff17cf91110a3c44747f9f2e1a938cbda (patch) | |
tree | a6459b4d1aeb7f6f08dea3db2e2780f6276abdb0 /net | |
parent | 5579a782ad7ffa162b1060993e4a298dd50e7a33 (diff) | |
parent | fd6149d332973bafa50f03ddb0ea9513e67f4517 (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.c | 2 | ||||
-rw-r--r-- | net/bridge/br_if.c | 14 | ||||
-rw-r--r-- | net/core/dev.c | 135 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 25 | ||||
-rw-r--r-- | net/sctp/input.c | 2 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 54 | ||||
-rw-r--r-- | net/sctp/sm_statetable.c | 4 |
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) | |||
347 | void br_features_recompute(struct net_bridge *br) | 347 | void 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; | 363 | done: |
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 | ||
3950 | unsigned 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 | } | ||
3988 | EXPORT_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 | */ |
4711 | int netdev_compute_features(unsigned long all, unsigned long one) | 4723 | unsigned 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 | } |
4745 | EXPORT_SYMBOL(netdev_compute_features); | 4752 | EXPORT_SYMBOL(netdev_increment_features); |
4746 | 4753 | ||
4747 | static struct hlist_head *netdev_create_hash(void) | 4754 | static 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 | */ | ||
365 | static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp, | 376 | static 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) | |||
369 | void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, | 369 | void 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 | */ | ||
2619 | sctp_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 */ |