From 7da2bc4a2fa433f428a6aa059ab9ebd105d00d38 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Tue, 20 Jun 2006 01:10:04 -0700 Subject: [PATCH] Network patches from DaveM for the 2.6.17 queue --- queue-2.6.17/ethtool-fix-ufo-typo.patch | 39 +++++++ .../ipv6-sum-real-space-for-rtas.patch | 93 ++++++++++++++++ ...nt-typing-in-struct-sadb_x_kmprivate.patch | 31 ++++++ ...ctp-packets-with-broadcast-addresses.patch | 103 ++++++++++++++++++ ...tp-when-a-gap-ack-consumes-rx-buffer.patch | 55 ++++++++++ ...on-max_retrans-setting-in-setsockopt.patch | 62 +++++++++++ ...r-the-chunk-when-processing-its-sack.patch | 26 +++++ ...nly-1-window-update-sack-per-message.patch | 85 +++++++++++++++ queue-2.6.17/series | 8 ++ 9 files changed, 502 insertions(+) create mode 100644 queue-2.6.17/ethtool-fix-ufo-typo.patch create mode 100644 queue-2.6.17/ipv6-sum-real-space-for-rtas.patch create mode 100644 queue-2.6.17/pfkeyv2-fix-inconsistent-typing-in-struct-sadb_x_kmprivate.patch create mode 100644 queue-2.6.17/reject-sctp-packets-with-broadcast-addresses.patch create mode 100644 queue-2.6.17/sctp-fix-persistent-slowdown-in-sctp-when-a-gap-ack-consumes-rx-buffer.patch create mode 100644 queue-2.6.17/sctp-limit-association-max_retrans-setting-in-setsockopt.patch create mode 100644 queue-2.6.17/sctp-reset-rtt_in_progress-for-the-chunk-when-processing-its-sack.patch create mode 100644 queue-2.6.17/sctp-send-only-1-window-update-sack-per-message.patch diff --git a/queue-2.6.17/ethtool-fix-ufo-typo.patch b/queue-2.6.17/ethtool-fix-ufo-typo.patch new file mode 100644 index 00000000000..77d9d8115dd --- /dev/null +++ b/queue-2.6.17/ethtool-fix-ufo-typo.patch @@ -0,0 +1,39 @@ +From stable-bounces@linux.kernel.org Tue Jun 20 00:09:54 2006 +Date: Tue, 20 Jun 2006 00:09:30 -0700 (PDT) +From: David Miller +To: stable@kernel.org +Cc: +Subject: ETHTOOL: Fix UFO typo + +From: Herbert Xu + +The function ethtool_get_ufo was referring to ETHTOOL_GTSO instead of +ETHTOOL_GUFO. + +Signed-off-by: Herbert Xu +Signed-off-by: David S. Miller +Signed-off-by: Chris Wright +--- + + net/core/ethtool.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- linux-2.6.17.1.orig/net/core/ethtool.c ++++ linux-2.6.17.1/net/core/ethtool.c +@@ -591,7 +591,7 @@ static int ethtool_set_tso(struct net_de + + static int ethtool_get_ufo(struct net_device *dev, char __user *useraddr) + { +- struct ethtool_value edata = { ETHTOOL_GTSO }; ++ struct ethtool_value edata = { ETHTOOL_GUFO }; + + if (!dev->ethtool_ops->get_ufo) + return -EOPNOTSUPP; +@@ -600,6 +600,7 @@ static int ethtool_get_ufo(struct net_de + return -EFAULT; + return 0; + } ++ + static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr) + { + struct ethtool_value edata; diff --git a/queue-2.6.17/ipv6-sum-real-space-for-rtas.patch b/queue-2.6.17/ipv6-sum-real-space-for-rtas.patch new file mode 100644 index 00000000000..816d85dff67 --- /dev/null +++ b/queue-2.6.17/ipv6-sum-real-space-for-rtas.patch @@ -0,0 +1,93 @@ +From stable-bounces@linux.kernel.org Tue Jun 20 00:03:17 2006 +Date: Tue, 20 Jun 2006 00:02:51 -0700 (PDT) +From: David Miller +To: stable@kernel.org +Cc: +Subject: IPV6: Sum real space for RTAs. + +From: YOSHIFUJI Hideaki + +This patch fixes RTNLGRP_IPV6_IFINFO netlink notifications. Issue +pointed out by Patrick McHardy . + +Signed-off-by: YOSHIFUJI Hideaki +Acked-by: Patrick McHardy +Signed-off-by: David S. Miller +Signed-off-by: Chris Wright +--- + + net/ipv6/addrconf.c | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +--- linux-2.6.17.1.orig/net/ipv6/addrconf.c ++++ linux-2.6.17.1/net/ipv6/addrconf.c +@@ -2860,6 +2860,11 @@ inet6_rtm_newaddr(struct sk_buff *skb, s + return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen); + } + ++/* Maximum length of ifa_cacheinfo attributes */ ++#define INET6_IFADDR_RTA_SPACE \ ++ RTA_SPACE(16) /* IFA_ADDRESS */ + \ ++ RTA_SPACE(sizeof(struct ifa_cacheinfo)) /* CACHEINFO */ ++ + static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, + u32 pid, u32 seq, int event, unsigned int flags) + { +@@ -3092,7 +3097,7 @@ static int inet6_dump_ifacaddr(struct sk + static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) + { + struct sk_buff *skb; +- int size = NLMSG_SPACE(sizeof(struct ifaddrmsg)+128); ++ int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE); + + skb = alloc_skb(size, GFP_ATOMIC); + if (!skb) { +@@ -3142,6 +3147,17 @@ static void inline ipv6_store_devconf(st + #endif + } + ++/* Maximum length of ifinfomsg attributes */ ++#define INET6_IFINFO_RTA_SPACE \ ++ RTA_SPACE(IFNAMSIZ) /* IFNAME */ + \ ++ RTA_SPACE(MAX_ADDR_LEN) /* ADDRESS */ + \ ++ RTA_SPACE(sizeof(u32)) /* MTU */ + \ ++ RTA_SPACE(sizeof(int)) /* LINK */ + \ ++ RTA_SPACE(0) /* PROTINFO */ + \ ++ RTA_SPACE(sizeof(u32)) /* FLAGS */ + \ ++ RTA_SPACE(sizeof(struct ifla_cacheinfo)) /* CACHEINFO */ + \ ++ RTA_SPACE(sizeof(__s32[DEVCONF_MAX])) /* CONF */ ++ + static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, + u32 pid, u32 seq, int event, unsigned int flags) + { +@@ -3235,8 +3251,7 @@ static int inet6_dump_ifinfo(struct sk_b + void inet6_ifinfo_notify(int event, struct inet6_dev *idev) + { + struct sk_buff *skb; +- /* 128 bytes ?? */ +- int size = NLMSG_SPACE(sizeof(struct ifinfomsg)+128); ++ int size = NLMSG_SPACE(sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE); + + skb = alloc_skb(size, GFP_ATOMIC); + if (!skb) { +@@ -3252,6 +3267,11 @@ void inet6_ifinfo_notify(int event, stru + netlink_broadcast(rtnl, skb, 0, RTNLGRP_IPV6_IFINFO, GFP_ATOMIC); + } + ++/* Maximum length of prefix_cacheinfo attributes */ ++#define INET6_PREFIX_RTA_SPACE \ ++ RTA_SPACE(sizeof(((struct prefix_info *)NULL)->prefix)) /* ADDRESS */ + \ ++ RTA_SPACE(sizeof(struct prefix_cacheinfo)) /* CACHEINFO */ ++ + static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, + struct prefix_info *pinfo, u32 pid, u32 seq, + int event, unsigned int flags) +@@ -3296,7 +3316,7 @@ static void inet6_prefix_notify(int even + struct prefix_info *pinfo) + { + struct sk_buff *skb; +- int size = NLMSG_SPACE(sizeof(struct prefixmsg)+128); ++ int size = NLMSG_SPACE(sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE); + + skb = alloc_skb(size, GFP_ATOMIC); + if (!skb) { diff --git a/queue-2.6.17/pfkeyv2-fix-inconsistent-typing-in-struct-sadb_x_kmprivate.patch b/queue-2.6.17/pfkeyv2-fix-inconsistent-typing-in-struct-sadb_x_kmprivate.patch new file mode 100644 index 00000000000..f99486898d1 --- /dev/null +++ b/queue-2.6.17/pfkeyv2-fix-inconsistent-typing-in-struct-sadb_x_kmprivate.patch @@ -0,0 +1,31 @@ +From stable-bounces@linux.kernel.org Tue Jun 20 00:03:59 2006 +Date: Tue, 20 Jun 2006 00:03:34 -0700 (PDT) +From: David Miller +To: stable@kernel.org +Cc: +Subject: PFKEYV2: Fix inconsistent typing in struct sadb_x_kmprivate. + +From: Tushar Gohad + +Fixes inconsistent use of "uint32_t" vs. "u_int32_t". +Fix pfkeyv2 userspace builds. + +Signed-off-by: Tushar Gohad +Signed-off-by: David S. Miller +Signed-off-by: Chris Wright +--- + + include/linux/pfkeyv2.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- linux-2.6.17.1.orig/include/linux/pfkeyv2.h ++++ linux-2.6.17.1/include/linux/pfkeyv2.h +@@ -159,7 +159,7 @@ struct sadb_spirange { + struct sadb_x_kmprivate { + uint16_t sadb_x_kmprivate_len; + uint16_t sadb_x_kmprivate_exttype; +- u_int32_t sadb_x_kmprivate_reserved; ++ uint32_t sadb_x_kmprivate_reserved; + } __attribute__((packed)); + /* sizeof(struct sadb_x_kmprivate) == 8 */ + diff --git a/queue-2.6.17/reject-sctp-packets-with-broadcast-addresses.patch b/queue-2.6.17/reject-sctp-packets-with-broadcast-addresses.patch new file mode 100644 index 00000000000..cd0fd492174 --- /dev/null +++ b/queue-2.6.17/reject-sctp-packets-with-broadcast-addresses.patch @@ -0,0 +1,103 @@ +From stable-bounces@linux.kernel.org Tue Jun 20 00:05:17 2006 +Date: Tue, 20 Jun 2006 00:04:53 -0700 (PDT) +From: David Miller +To: stable@kernel.org +Cc: +Subject: [SCTP]: Reject sctp packets with broadcast addresses. + +From: Vlad Yasevich + +Make SCTP handle broadcast properly + +Signed-off-by: Vlad Yasevich +Signed-off-by: Sridhar Samudrala +Signed-off-by: David S. Miller +Signed-off-by: Chris Wright +--- + + include/net/sctp/structs.h | 3 ++- + net/sctp/input.c | 3 ++- + net/sctp/ipv6.c | 6 ++++-- + net/sctp/protocol.c | 8 +++++++- + net/sctp/socket.c | 2 +- + 5 files changed, 16 insertions(+), 6 deletions(-) + +--- linux-2.6.17.1.orig/include/net/sctp/structs.h ++++ linux-2.6.17.1/include/net/sctp/structs.h +@@ -555,7 +555,8 @@ struct sctp_af { + int (*to_addr_param) (const union sctp_addr *, + union sctp_addr_param *); + int (*addr_valid) (union sctp_addr *, +- struct sctp_sock *); ++ struct sctp_sock *, ++ const struct sk_buff *); + sctp_scope_t (*scope) (union sctp_addr *); + void (*inaddr_any) (union sctp_addr *, unsigned short); + int (*is_any) (const union sctp_addr *); +--- linux-2.6.17.1.orig/net/sctp/input.c ++++ linux-2.6.17.1/net/sctp/input.c +@@ -170,7 +170,8 @@ int sctp_rcv(struct sk_buff *skb) + * IP broadcast addresses cannot be used in an SCTP transport + * address." + */ +- if (!af->addr_valid(&src, NULL) || !af->addr_valid(&dest, NULL)) ++ if (!af->addr_valid(&src, NULL, skb) || ++ !af->addr_valid(&dest, NULL, skb)) + goto discard_it; + + asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport); +--- linux-2.6.17.1.orig/net/sctp/ipv6.c ++++ linux-2.6.17.1/net/sctp/ipv6.c +@@ -523,7 +523,9 @@ static int sctp_v6_available(union sctp_ + * Return 0 - If the address is a non-unicast or an illegal address. + * Return 1 - If the address is a unicast. + */ +-static int sctp_v6_addr_valid(union sctp_addr *addr, struct sctp_sock *sp) ++static int sctp_v6_addr_valid(union sctp_addr *addr, ++ struct sctp_sock *sp, ++ const struct sk_buff *skb) + { + int ret = ipv6_addr_type(&addr->v6.sin6_addr); + +@@ -537,7 +539,7 @@ static int sctp_v6_addr_valid(union sctp + if (sp && ipv6_only_sock(sctp_opt2sk(sp))) + return 0; + sctp_v6_map_v4(addr); +- return sctp_get_af_specific(AF_INET)->addr_valid(addr, sp); ++ return sctp_get_af_specific(AF_INET)->addr_valid(addr, sp, skb); + } + + /* Is this a non-unicast address */ +--- linux-2.6.17.1.orig/net/sctp/protocol.c ++++ linux-2.6.17.1/net/sctp/protocol.c +@@ -365,12 +365,18 @@ static int sctp_v4_is_any(const union sc + * Return 0 - If the address is a non-unicast or an illegal address. + * Return 1 - If the address is a unicast. + */ +-static int sctp_v4_addr_valid(union sctp_addr *addr, struct sctp_sock *sp) ++static int sctp_v4_addr_valid(union sctp_addr *addr, ++ struct sctp_sock *sp, ++ const struct sk_buff *skb) + { + /* Is this a non-unicast address or a unusable SCTP address? */ + if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr)) + return 0; + ++ /* Is this a broadcast address? */ ++ if (skb && ((struct rtable *)skb->dst)->rt_flags & RTCF_BROADCAST) ++ return 0; ++ + return 1; + } + +--- linux-2.6.17.1.orig/net/sctp/socket.c ++++ linux-2.6.17.1/net/sctp/socket.c +@@ -172,7 +172,7 @@ static inline int sctp_verify_addr(struc + return -EINVAL; + + /* Is this a valid SCTP address? */ +- if (!af->addr_valid(addr, sctp_sk(sk))) ++ if (!af->addr_valid(addr, sctp_sk(sk), NULL)) + return -EINVAL; + + if (!sctp_sk(sk)->pf->send_verify(sctp_sk(sk), (addr))) diff --git a/queue-2.6.17/sctp-fix-persistent-slowdown-in-sctp-when-a-gap-ack-consumes-rx-buffer.patch b/queue-2.6.17/sctp-fix-persistent-slowdown-in-sctp-when-a-gap-ack-consumes-rx-buffer.patch new file mode 100644 index 00000000000..fdea08bf346 --- /dev/null +++ b/queue-2.6.17/sctp-fix-persistent-slowdown-in-sctp-when-a-gap-ack-consumes-rx-buffer.patch @@ -0,0 +1,55 @@ +From stable-bounces@linux.kernel.org Tue Jun 20 00:09:44 2006 +Date: Tue, 20 Jun 2006 00:09:03 -0700 (PDT) +From: David Miller +To: stable@kernel.org +Cc: +Subject: SCTP: Fix persistent slowdown in sctp when a gap ack consumes rx buffer. + +From: Neil Horman + +In the event that our entire receive buffer is full with a series of +chunks that represent a single gap-ack, and then we accept a chunk +(or chunks) that fill in the gap between the ctsn and the first gap, +we renege chunks from the end of the buffer, which effectively does +nothing but move our gap to the end of our received tsn stream. This +does little but move our missing tsns down stream a little, and, if the +sender is sending sufficiently large retransmit frames, the result is a +perpetual slowdown which can never be recovered from, since the only +chunk that can be accepted to allow progress in the tsn stream necessitates +that a new gap be created to make room for it. This leads to a constant +need for retransmits, and subsequent receiver stalls. The fix I've come up +with is to deliver the frame without reneging if we have a full receive +buffer and the receiving sockets sk_receive_queue is empty(indicating that +the receive buffer is being blocked by a missing tsn). + +Signed-off-by: Neil Horman +Signed-off-by: Sridhar Samudrala +Signed-off-by: David S. Miller +Signed-off-by: Chris Wright +--- + + net/sctp/sm_statefuns.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- linux-2.6.17.1.orig/net/sctp/sm_statefuns.c ++++ linux-2.6.17.1/net/sctp/sm_statefuns.c +@@ -5293,10 +5293,18 @@ static int sctp_eat_data(const struct sc + * seems a bit troublesome in that frag_point varies based on + * PMTU. In cases, such as loopback, this might be a rather + * large spill over. ++ * NOTE: If we have a full receive buffer here, we only renege if ++ * our receiver can still make progress without the tsn being ++ * received. We do this because in the event that the associations ++ * receive queue is empty we are filling a leading gap, and since ++ * reneging moves the gap to the end of the tsn stream, we are likely ++ * to stall again very shortly. Avoiding the renege when we fill a ++ * leading gap is a good heuristic for avoiding such steady state ++ * stalls. + */ + if (!asoc->rwnd || asoc->rwnd_over || + (datalen > asoc->rwnd + asoc->frag_point) || +- rcvbuf_over) { ++ (rcvbuf_over && (!skb_queue_len(&sk->sk_receive_queue)))) { + + /* If this is the next TSN, consider reneging to make + * room. Note: Playing nice with a confused sender. A diff --git a/queue-2.6.17/sctp-limit-association-max_retrans-setting-in-setsockopt.patch b/queue-2.6.17/sctp-limit-association-max_retrans-setting-in-setsockopt.patch new file mode 100644 index 00000000000..39b88002e53 --- /dev/null +++ b/queue-2.6.17/sctp-limit-association-max_retrans-setting-in-setsockopt.patch @@ -0,0 +1,62 @@ +From stable-bounces@linux.kernel.org Tue Jun 20 00:04:43 2006 +Date: Tue, 20 Jun 2006 00:04:18 -0700 (PDT) +From: David Miller +To: stable@kernel.org +Cc: +Subject: SCTP: Limit association max_retrans setting in setsockopt. + +From: Vlad Yasevich + +When using ASSOCINFO socket option, we need to limit the number of +maximum association retransmissions to be no greater than the sum +of all the path retransmissions. This is specified in Section 7.1.2 +of the SCTP socket API draft. +However, we only do this if the association has multiple paths. If +there is only one path, the protocol stack will use the +assoc_max_retrans setting when trying to retransmit packets. + +Signed-off-by: Vlad Yasevich +Signed-off-by: Sridhar Samudrala +Signed-off-by: David S. Miller +Signed-off-by: Chris Wright +--- + + net/sctp/socket.c | 26 +++++++++++++++++++++++++- + 1 file changed, 25 insertions(+), 1 deletion(-) + +--- linux-2.6.17.1.orig/net/sctp/socket.c ++++ linux-2.6.17.1/net/sctp/socket.c +@@ -2530,8 +2530,32 @@ static int sctp_setsockopt_associnfo(str + + /* Set the values to the specific association */ + if (asoc) { +- if (assocparams.sasoc_asocmaxrxt != 0) ++ if (assocparams.sasoc_asocmaxrxt != 0) { ++ __u32 path_sum = 0; ++ int paths = 0; ++ struct list_head *pos; ++ struct sctp_transport *peer_addr; ++ ++ list_for_each(pos, &asoc->peer.transport_addr_list) { ++ peer_addr = list_entry(pos, ++ struct sctp_transport, ++ transports); ++ path_sum += peer_addr->pathmaxrxt; ++ paths++; ++ } ++ ++ /* Only validate asocmaxrxt if we have more then ++ * one path/transport. We do this because path ++ * retransmissions are only counted when we have more ++ * then one path. ++ */ ++ if (paths > 1 && ++ assocparams.sasoc_asocmaxrxt > path_sum) ++ return -EINVAL; ++ + asoc->max_retrans = assocparams.sasoc_asocmaxrxt; ++ } ++ + if (assocparams.sasoc_cookie_life != 0) { + asoc->cookie_life.tv_sec = + assocparams.sasoc_cookie_life / 1000; diff --git a/queue-2.6.17/sctp-reset-rtt_in_progress-for-the-chunk-when-processing-its-sack.patch b/queue-2.6.17/sctp-reset-rtt_in_progress-for-the-chunk-when-processing-its-sack.patch new file mode 100644 index 00000000000..f901e314ba8 --- /dev/null +++ b/queue-2.6.17/sctp-reset-rtt_in_progress-for-the-chunk-when-processing-its-sack.patch @@ -0,0 +1,26 @@ +From stable-bounces@linux.kernel.org Tue Jun 20 00:06:54 2006 +Date: Tue, 20 Jun 2006 00:06:27 -0700 (PDT) +From: David Miller +To: stable@kernel.org +Cc: +Subject: SCTP: Reset rtt_in_progress for the chunk when processing its sack. + +Signed-off-by: Vlad Yasevich +Signed-off-by: Sridhar Samudrala +Signed-off-by: David S. Miller +Signed-off-by: Chris Wright +--- + + net/sctp/outqueue.c | 1 + + 1 file changed, 1 insertion(+) + +--- linux-2.6.17.1.orig/net/sctp/outqueue.c ++++ linux-2.6.17.1/net/sctp/outqueue.c +@@ -1262,6 +1262,7 @@ static void sctp_check_transmitted(struc + if (!tchunk->tsn_gap_acked && + !tchunk->resent && + tchunk->rtt_in_progress) { ++ tchunk->rtt_in_progress = 0; + rtt = jiffies - tchunk->sent_at; + sctp_transport_update_rto(transport, + rtt); diff --git a/queue-2.6.17/sctp-send-only-1-window-update-sack-per-message.patch b/queue-2.6.17/sctp-send-only-1-window-update-sack-per-message.patch new file mode 100644 index 00000000000..2dc49b407b7 --- /dev/null +++ b/queue-2.6.17/sctp-send-only-1-window-update-sack-per-message.patch @@ -0,0 +1,85 @@ +From stable-bounces@linux.kernel.org Tue Jun 20 00:08:57 2006 +Date: Tue, 20 Jun 2006 00:08:29 -0700 (PDT) +From: David Miller +To: stable@kernel.org +Cc: +Subject: SCTP: Send only 1 window update SACK per message. + +From: Tsutomu Fujii + +Right now, every time we increase our rwnd by more then MTU bytes, we +trigger a SACK. When processing large messages, this will generate a +SACK for almost every other SCTP fragment. However since we are freeing +the entire message at the same time, we might as well collapse the SACK +generation to 1. + +Signed-off-by: Tsutomu Fujii +Signed-off-by: Vlad Yasevich +Signed-off-by: Sridhar Samudrala +Signed-off-by: David S. Miller +Signed-off-by: Chris Wright +--- + + net/sctp/ulpevent.c | 30 ++++++++++++++++++++++++++++-- + 1 file changed, 28 insertions(+), 2 deletions(-) + +--- linux-2.6.17.1.orig/net/sctp/ulpevent.c ++++ linux-2.6.17.1/net/sctp/ulpevent.c +@@ -51,6 +51,8 @@ + static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, + struct sctp_association *asoc); + static void sctp_ulpevent_release_data(struct sctp_ulpevent *event); ++static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event); ++ + + /* Initialize an ULP event from an given skb. */ + SCTP_STATIC void sctp_ulpevent_init(struct sctp_ulpevent *event, int msg_flags) +@@ -883,6 +885,7 @@ static void sctp_ulpevent_receive_data(s + static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) + { + struct sk_buff *skb, *frag; ++ unsigned int len; + + /* Current stack structures assume that the rcv buffer is + * per socket. For UDP style sockets this is not true as +@@ -892,7 +895,30 @@ static void sctp_ulpevent_release_data(s + */ + + skb = sctp_event2skb(event); +- sctp_assoc_rwnd_increase(event->asoc, skb_headlen(skb)); ++ len = skb->len; ++ ++ if (!skb->data_len) ++ goto done; ++ ++ /* Don't forget the fragments. */ ++ for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) { ++ /* NOTE: skb_shinfos are recursive. Although IP returns ++ * skb's with only 1 level of fragments, SCTP reassembly can ++ * increase the levels. ++ */ ++ sctp_ulpevent_release_frag_data(sctp_skb2event(frag)); ++ } ++ ++done: ++ sctp_assoc_rwnd_increase(event->asoc, len); ++ sctp_ulpevent_release_owner(event); ++} ++ ++static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event) ++{ ++ struct sk_buff *skb, *frag; ++ ++ skb = sctp_event2skb(event); + + if (!skb->data_len) + goto done; +@@ -903,7 +929,7 @@ static void sctp_ulpevent_release_data(s + * skb's with only 1 level of fragments, SCTP reassembly can + * increase the levels. + */ +- sctp_ulpevent_release_data(sctp_skb2event(frag)); ++ sctp_ulpevent_release_frag_data(sctp_skb2event(frag)); + } + + done: diff --git a/queue-2.6.17/series b/queue-2.6.17/series index 18951cdb999..739856dfe7e 100644 --- a/queue-2.6.17/series +++ b/queue-2.6.17/series @@ -1,2 +1,10 @@ usb-whiteheat-fix-firmware-spurious-errors.patch serial-parport_serial-should-depend-on-serial_8250_pci.patch +ipv6-sum-real-space-for-rtas.patch +pfkeyv2-fix-inconsistent-typing-in-struct-sadb_x_kmprivate.patch +sctp-limit-association-max_retrans-setting-in-setsockopt.patch +reject-sctp-packets-with-broadcast-addresses.patch +sctp-reset-rtt_in_progress-for-the-chunk-when-processing-its-sack.patch +sctp-send-only-1-window-update-sack-per-message.patch +sctp-fix-persistent-slowdown-in-sctp-when-a-gap-ack-consumes-rx-buffer.patch +ethtool-fix-ufo-typo.patch -- 2.47.2