diff options
-rw-r--r-- | Documentation/networking/ip-sysctl.txt | 17 | ||||
-rw-r--r-- | drivers/net/tg3.c | 30 | ||||
-rw-r--r-- | drivers/net/tg3.h | 1 | ||||
-rw-r--r-- | include/net/sctp/structs.h | 2 | ||||
-rw-r--r-- | include/net/sock.h | 8 | ||||
-rw-r--r-- | lib/ts_bm.c | 40 | ||||
-rw-r--r-- | net/802/psnap.c | 2 | ||||
-rw-r--r-- | net/Kconfig | 7 | ||||
-rw-r--r-- | net/ipv4/icmp.c | 3 | ||||
-rw-r--r-- | net/ipv4/multipath_wrandom.c | 8 | ||||
-rw-r--r-- | net/ipv6/addrconf.c | 6 | ||||
-rw-r--r-- | net/ipv6/af_inet6.c | 6 | ||||
-rw-r--r-- | net/sctp/output.c | 2 | ||||
-rw-r--r-- | net/sctp/outqueue.c | 12 |
14 files changed, 97 insertions, 47 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 2b7cf19a06ad..26364d06ae92 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt | |||
@@ -427,6 +427,23 @@ icmp_ignore_bogus_error_responses - BOOLEAN | |||
427 | will avoid log file clutter. | 427 | will avoid log file clutter. |
428 | Default: FALSE | 428 | Default: FALSE |
429 | 429 | ||
430 | icmp_errors_use_inbound_ifaddr - BOOLEAN | ||
431 | |||
432 | If zero, icmp error messages are sent with the primary address of | ||
433 | the exiting interface. | ||
434 | |||
435 | If non-zero, the message will be sent with the primary address of | ||
436 | the interface that received the packet that caused the icmp error. | ||
437 | This is the behaviour network many administrators will expect from | ||
438 | a router. And it can make debugging complicated network layouts | ||
439 | much easier. | ||
440 | |||
441 | Note that if no primary address exists for the interface selected, | ||
442 | then the primary address of the first non-loopback interface that | ||
443 | has one will be used regarldess of this setting. | ||
444 | |||
445 | Default: 0 | ||
446 | |||
430 | igmp_max_memberships - INTEGER | 447 | igmp_max_memberships - INTEGER |
431 | Change the maximum number of multicast groups we can subscribe to. | 448 | Change the maximum number of multicast groups we can subscribe to. |
432 | Default: 20 | 449 | Default: 20 |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index f2d1dafde087..e7dc653d5bd6 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -69,8 +69,8 @@ | |||
69 | 69 | ||
70 | #define DRV_MODULE_NAME "tg3" | 70 | #define DRV_MODULE_NAME "tg3" |
71 | #define PFX DRV_MODULE_NAME ": " | 71 | #define PFX DRV_MODULE_NAME ": " |
72 | #define DRV_MODULE_VERSION "3.48" | 72 | #define DRV_MODULE_VERSION "3.49" |
73 | #define DRV_MODULE_RELDATE "Jan 16, 2006" | 73 | #define DRV_MODULE_RELDATE "Feb 2, 2006" |
74 | 74 | ||
75 | #define TG3_DEF_MAC_MODE 0 | 75 | #define TG3_DEF_MAC_MODE 0 |
76 | #define TG3_DEF_RX_MODE 0 | 76 | #define TG3_DEF_RX_MODE 0 |
@@ -3482,6 +3482,17 @@ static void tg3_reset_task(void *_data) | |||
3482 | struct tg3 *tp = _data; | 3482 | struct tg3 *tp = _data; |
3483 | unsigned int restart_timer; | 3483 | unsigned int restart_timer; |
3484 | 3484 | ||
3485 | tg3_full_lock(tp, 0); | ||
3486 | tp->tg3_flags |= TG3_FLAG_IN_RESET_TASK; | ||
3487 | |||
3488 | if (!netif_running(tp->dev)) { | ||
3489 | tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK; | ||
3490 | tg3_full_unlock(tp); | ||
3491 | return; | ||
3492 | } | ||
3493 | |||
3494 | tg3_full_unlock(tp); | ||
3495 | |||
3485 | tg3_netif_stop(tp); | 3496 | tg3_netif_stop(tp); |
3486 | 3497 | ||
3487 | tg3_full_lock(tp, 1); | 3498 | tg3_full_lock(tp, 1); |
@@ -3494,10 +3505,12 @@ static void tg3_reset_task(void *_data) | |||
3494 | 3505 | ||
3495 | tg3_netif_start(tp); | 3506 | tg3_netif_start(tp); |
3496 | 3507 | ||
3497 | tg3_full_unlock(tp); | ||
3498 | |||
3499 | if (restart_timer) | 3508 | if (restart_timer) |
3500 | mod_timer(&tp->timer, jiffies + 1); | 3509 | mod_timer(&tp->timer, jiffies + 1); |
3510 | |||
3511 | tp->tg3_flags &= ~TG3_FLAG_IN_RESET_TASK; | ||
3512 | |||
3513 | tg3_full_unlock(tp); | ||
3501 | } | 3514 | } |
3502 | 3515 | ||
3503 | static void tg3_tx_timeout(struct net_device *dev) | 3516 | static void tg3_tx_timeout(struct net_device *dev) |
@@ -6786,6 +6799,13 @@ static int tg3_close(struct net_device *dev) | |||
6786 | { | 6799 | { |
6787 | struct tg3 *tp = netdev_priv(dev); | 6800 | struct tg3 *tp = netdev_priv(dev); |
6788 | 6801 | ||
6802 | /* Calling flush_scheduled_work() may deadlock because | ||
6803 | * linkwatch_event() may be on the workqueue and it will try to get | ||
6804 | * the rtnl_lock which we are holding. | ||
6805 | */ | ||
6806 | while (tp->tg3_flags & TG3_FLAG_IN_RESET_TASK) | ||
6807 | msleep(1); | ||
6808 | |||
6789 | netif_stop_queue(dev); | 6809 | netif_stop_queue(dev); |
6790 | 6810 | ||
6791 | del_timer_sync(&tp->timer); | 6811 | del_timer_sync(&tp->timer); |
@@ -10880,6 +10900,7 @@ static void __devexit tg3_remove_one(struct pci_dev *pdev) | |||
10880 | if (dev) { | 10900 | if (dev) { |
10881 | struct tg3 *tp = netdev_priv(dev); | 10901 | struct tg3 *tp = netdev_priv(dev); |
10882 | 10902 | ||
10903 | flush_scheduled_work(); | ||
10883 | unregister_netdev(dev); | 10904 | unregister_netdev(dev); |
10884 | if (tp->regs) { | 10905 | if (tp->regs) { |
10885 | iounmap(tp->regs); | 10906 | iounmap(tp->regs); |
@@ -10901,6 +10922,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state) | |||
10901 | if (!netif_running(dev)) | 10922 | if (!netif_running(dev)) |
10902 | return 0; | 10923 | return 0; |
10903 | 10924 | ||
10925 | flush_scheduled_work(); | ||
10904 | tg3_netif_stop(tp); | 10926 | tg3_netif_stop(tp); |
10905 | 10927 | ||
10906 | del_timer_sync(&tp->timer); | 10928 | del_timer_sync(&tp->timer); |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index e8243305f0e8..7f4b7f6ac40d 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
@@ -2162,6 +2162,7 @@ struct tg3 { | |||
2162 | #define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 | 2162 | #define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 |
2163 | #define TG3_FLAG_10_100_ONLY 0x01000000 | 2163 | #define TG3_FLAG_10_100_ONLY 0x01000000 |
2164 | #define TG3_FLAG_PAUSE_AUTONEG 0x02000000 | 2164 | #define TG3_FLAG_PAUSE_AUTONEG 0x02000000 |
2165 | #define TG3_FLAG_IN_RESET_TASK 0x04000000 | ||
2165 | #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 | 2166 | #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 |
2166 | #define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 | 2167 | #define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 |
2167 | #define TG3_FLAG_SPLIT_MODE 0x40000000 | 2168 | #define TG3_FLAG_SPLIT_MODE 0x40000000 |
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 8c522ae031bb..072f407848a6 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
@@ -700,7 +700,7 @@ struct sctp_chunk { | |||
700 | __u8 ecn_ce_done; /* Have we processed the ECN CE bit? */ | 700 | __u8 ecn_ce_done; /* Have we processed the ECN CE bit? */ |
701 | __u8 pdiscard; /* Discard the whole packet now? */ | 701 | __u8 pdiscard; /* Discard the whole packet now? */ |
702 | __u8 tsn_gap_acked; /* Is this chunk acked by a GAP ACK? */ | 702 | __u8 tsn_gap_acked; /* Is this chunk acked by a GAP ACK? */ |
703 | __u8 fast_retransmit; /* Is this chunk fast retransmitted? */ | 703 | __s8 fast_retransmit; /* Is this chunk fast retransmitted? */ |
704 | __u8 tsn_missing_report; /* Data chunk missing counter. */ | 704 | __u8 tsn_missing_report; /* Data chunk missing counter. */ |
705 | }; | 705 | }; |
706 | 706 | ||
diff --git a/include/net/sock.h b/include/net/sock.h index 1806e5b61419..30758035d616 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -1354,12 +1354,12 @@ extern int sock_get_timestamp(struct sock *, struct timeval __user *); | |||
1354 | * Enable debug/info messages | 1354 | * Enable debug/info messages |
1355 | */ | 1355 | */ |
1356 | 1356 | ||
1357 | #if 0 | 1357 | #ifdef CONFIG_NETDEBUG |
1358 | #define NETDEBUG(fmt, args...) do { } while (0) | ||
1359 | #define LIMIT_NETDEBUG(fmt, args...) do { } while(0) | ||
1360 | #else | ||
1361 | #define NETDEBUG(fmt, args...) printk(fmt,##args) | 1358 | #define NETDEBUG(fmt, args...) printk(fmt,##args) |
1362 | #define LIMIT_NETDEBUG(fmt, args...) do { if (net_ratelimit()) printk(fmt,##args); } while(0) | 1359 | #define LIMIT_NETDEBUG(fmt, args...) do { if (net_ratelimit()) printk(fmt,##args); } while(0) |
1360 | #else | ||
1361 | #define NETDEBUG(fmt, args...) do { } while (0) | ||
1362 | #define LIMIT_NETDEBUG(fmt, args...) do { } while(0) | ||
1363 | #endif | 1363 | #endif |
1364 | 1364 | ||
1365 | /* | 1365 | /* |
diff --git a/lib/ts_bm.c b/lib/ts_bm.c index 8a8b3a16133e..c4c1ac5fbd1a 100644 --- a/lib/ts_bm.c +++ b/lib/ts_bm.c | |||
@@ -94,10 +94,28 @@ next: bs = bm->bad_shift[text[shift-i]]; | |||
94 | return UINT_MAX; | 94 | return UINT_MAX; |
95 | } | 95 | } |
96 | 96 | ||
97 | static int subpattern(u8 *pattern, int i, int j, int g) | ||
98 | { | ||
99 | int x = i+g-1, y = j+g-1, ret = 0; | ||
100 | |||
101 | while(pattern[x--] == pattern[y--]) { | ||
102 | if (y < 0) { | ||
103 | ret = 1; | ||
104 | break; | ||
105 | } | ||
106 | if (--g == 0) { | ||
107 | ret = pattern[i-1] != pattern[j-1]; | ||
108 | break; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | return ret; | ||
113 | } | ||
114 | |||
97 | static void compute_prefix_tbl(struct ts_bm *bm, const u8 *pattern, | 115 | static void compute_prefix_tbl(struct ts_bm *bm, const u8 *pattern, |
98 | unsigned int len) | 116 | unsigned int len) |
99 | { | 117 | { |
100 | int i, j, ended, l[ASIZE]; | 118 | int i, j, g; |
101 | 119 | ||
102 | for (i = 0; i < ASIZE; i++) | 120 | for (i = 0; i < ASIZE; i++) |
103 | bm->bad_shift[i] = len; | 121 | bm->bad_shift[i] = len; |
@@ -106,23 +124,15 @@ static void compute_prefix_tbl(struct ts_bm *bm, const u8 *pattern, | |||
106 | 124 | ||
107 | /* Compute the good shift array, used to match reocurrences | 125 | /* Compute the good shift array, used to match reocurrences |
108 | * of a subpattern */ | 126 | * of a subpattern */ |
109 | for (i = 1; i < bm->patlen; i++) { | ||
110 | for (j = 0; j < bm->patlen && bm->pattern[bm->patlen - 1 - j] | ||
111 | == bm->pattern[bm->patlen - 1 - i - j]; j++); | ||
112 | l[i] = j; | ||
113 | } | ||
114 | |||
115 | bm->good_shift[0] = 1; | 127 | bm->good_shift[0] = 1; |
116 | for (i = 1; i < bm->patlen; i++) | 128 | for (i = 1; i < bm->patlen; i++) |
117 | bm->good_shift[i] = bm->patlen; | 129 | bm->good_shift[i] = bm->patlen; |
118 | for (i = bm->patlen - 1; i > 0; i--) | 130 | for (i = bm->patlen-1, g = 1; i > 0; g++, i--) { |
119 | bm->good_shift[l[i]] = i; | 131 | for (j = i-1; j >= 1-g ; j--) |
120 | ended = 0; | 132 | if (subpattern(bm->pattern, i, j, g)) { |
121 | for (i = 0; i < bm->patlen; i++) { | 133 | bm->good_shift[g] = bm->patlen-j-g; |
122 | if (l[i] == bm->patlen - 1 - i) | 134 | break; |
123 | ended = i; | 135 | } |
124 | if (ended) | ||
125 | bm->good_shift[i] = ended; | ||
126 | } | 136 | } |
127 | } | 137 | } |
128 | 138 | ||
diff --git a/net/802/psnap.c b/net/802/psnap.c index 4d638944d933..34e42968b477 100644 --- a/net/802/psnap.c +++ b/net/802/psnap.c | |||
@@ -59,8 +59,10 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev, | |||
59 | proto = find_snap_client(skb->h.raw); | 59 | proto = find_snap_client(skb->h.raw); |
60 | if (proto) { | 60 | if (proto) { |
61 | /* Pass the frame on. */ | 61 | /* Pass the frame on. */ |
62 | u8 *hdr = skb->data; | ||
62 | skb->h.raw += 5; | 63 | skb->h.raw += 5; |
63 | skb_pull(skb, 5); | 64 | skb_pull(skb, 5); |
65 | skb_postpull_rcsum(skb, hdr, 5); | ||
64 | rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev); | 66 | rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev); |
65 | } else { | 67 | } else { |
66 | skb->sk = NULL; | 68 | skb->sk = NULL; |
diff --git a/net/Kconfig b/net/Kconfig index bc603d9aea56..5126f58d9c44 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -27,6 +27,13 @@ if NET | |||
27 | 27 | ||
28 | menu "Networking options" | 28 | menu "Networking options" |
29 | 29 | ||
30 | config NETDEBUG | ||
31 | bool "Network packet debugging" | ||
32 | help | ||
33 | You can say Y here if you want to get additional messages useful in | ||
34 | debugging bad packets, but can overwhelm logs under denial of service | ||
35 | attacks. | ||
36 | |||
30 | source "net/packet/Kconfig" | 37 | source "net/packet/Kconfig" |
31 | source "net/unix/Kconfig" | 38 | source "net/unix/Kconfig" |
32 | source "net/xfrm/Kconfig" | 39 | source "net/xfrm/Kconfig" |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 105039eb7629..6bc0887b0834 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -385,7 +385,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) | |||
385 | u32 daddr; | 385 | u32 daddr; |
386 | 386 | ||
387 | if (ip_options_echo(&icmp_param->replyopts, skb)) | 387 | if (ip_options_echo(&icmp_param->replyopts, skb)) |
388 | goto out; | 388 | return; |
389 | 389 | ||
390 | if (icmp_xmit_lock()) | 390 | if (icmp_xmit_lock()) |
391 | return; | 391 | return; |
@@ -416,7 +416,6 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) | |||
416 | ip_rt_put(rt); | 416 | ip_rt_put(rt); |
417 | out_unlock: | 417 | out_unlock: |
418 | icmp_xmit_unlock(); | 418 | icmp_xmit_unlock(); |
419 | out:; | ||
420 | } | 419 | } |
421 | 420 | ||
422 | 421 | ||
diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c index d34a9fa608e0..342d0b9098f5 100644 --- a/net/ipv4/multipath_wrandom.c +++ b/net/ipv4/multipath_wrandom.c | |||
@@ -228,7 +228,7 @@ static void wrandom_set_nhinfo(__u32 network, | |||
228 | struct multipath_dest *d, *target_dest = NULL; | 228 | struct multipath_dest *d, *target_dest = NULL; |
229 | 229 | ||
230 | /* store the weight information for a certain route */ | 230 | /* store the weight information for a certain route */ |
231 | spin_lock(&state[state_idx].lock); | 231 | spin_lock_bh(&state[state_idx].lock); |
232 | 232 | ||
233 | /* find state entry for gateway or add one if necessary */ | 233 | /* find state entry for gateway or add one if necessary */ |
234 | list_for_each_entry_rcu(r, &state[state_idx].head, list) { | 234 | list_for_each_entry_rcu(r, &state[state_idx].head, list) { |
@@ -276,7 +276,7 @@ static void wrandom_set_nhinfo(__u32 network, | |||
276 | * we are finished | 276 | * we are finished |
277 | */ | 277 | */ |
278 | 278 | ||
279 | spin_unlock(&state[state_idx].lock); | 279 | spin_unlock_bh(&state[state_idx].lock); |
280 | } | 280 | } |
281 | 281 | ||
282 | static void __multipath_free(struct rcu_head *head) | 282 | static void __multipath_free(struct rcu_head *head) |
@@ -302,7 +302,7 @@ static void wrandom_flush(void) | |||
302 | for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) { | 302 | for (i = 0; i < MULTIPATH_STATE_SIZE; ++i) { |
303 | struct multipath_route *r; | 303 | struct multipath_route *r; |
304 | 304 | ||
305 | spin_lock(&state[i].lock); | 305 | spin_lock_bh(&state[i].lock); |
306 | list_for_each_entry_rcu(r, &state[i].head, list) { | 306 | list_for_each_entry_rcu(r, &state[i].head, list) { |
307 | struct multipath_dest *d; | 307 | struct multipath_dest *d; |
308 | list_for_each_entry_rcu(d, &r->dests, list) { | 308 | list_for_each_entry_rcu(d, &r->dests, list) { |
@@ -315,7 +315,7 @@ static void wrandom_flush(void) | |||
315 | __multipath_free); | 315 | __multipath_free); |
316 | } | 316 | } |
317 | 317 | ||
318 | spin_unlock(&state[i].lock); | 318 | spin_unlock_bh(&state[i].lock); |
319 | } | 319 | } |
320 | } | 320 | } |
321 | 321 | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index d328d5986143..1db50487916b 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -3321,9 +3321,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
3321 | 3321 | ||
3322 | switch (event) { | 3322 | switch (event) { |
3323 | case RTM_NEWADDR: | 3323 | case RTM_NEWADDR: |
3324 | dst_hold(&ifp->rt->u.dst); | 3324 | ip6_ins_rt(ifp->rt, NULL, NULL, NULL); |
3325 | if (ip6_ins_rt(ifp->rt, NULL, NULL, NULL)) | ||
3326 | dst_release(&ifp->rt->u.dst); | ||
3327 | if (ifp->idev->cnf.forwarding) | 3325 | if (ifp->idev->cnf.forwarding) |
3328 | addrconf_join_anycast(ifp); | 3326 | addrconf_join_anycast(ifp); |
3329 | break; | 3327 | break; |
@@ -3334,8 +3332,6 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
3334 | dst_hold(&ifp->rt->u.dst); | 3332 | dst_hold(&ifp->rt->u.dst); |
3335 | if (ip6_del_rt(ifp->rt, NULL, NULL, NULL)) | 3333 | if (ip6_del_rt(ifp->rt, NULL, NULL, NULL)) |
3336 | dst_free(&ifp->rt->u.dst); | 3334 | dst_free(&ifp->rt->u.dst); |
3337 | else | ||
3338 | dst_release(&ifp->rt->u.dst); | ||
3339 | break; | 3335 | break; |
3340 | } | 3336 | } |
3341 | } | 3337 | } |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 064ffab82a9f..6c9711ac1c03 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -369,12 +369,6 @@ int inet6_destroy_sock(struct sock *sk) | |||
369 | struct sk_buff *skb; | 369 | struct sk_buff *skb; |
370 | struct ipv6_txoptions *opt; | 370 | struct ipv6_txoptions *opt; |
371 | 371 | ||
372 | /* | ||
373 | * Release destination entry | ||
374 | */ | ||
375 | |||
376 | sk_dst_reset(sk); | ||
377 | |||
378 | /* Release rx options */ | 372 | /* Release rx options */ |
379 | 373 | ||
380 | if ((skb = xchg(&np->pktoptions, NULL)) != NULL) | 374 | if ((skb = xchg(&np->pktoptions, NULL)) != NULL) |
diff --git a/net/sctp/output.c b/net/sctp/output.c index a40991ef72c9..437cba7260a4 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -608,7 +608,7 @@ static sctp_xmit_t sctp_packet_append_data(struct sctp_packet *packet, | |||
608 | * When a Fast Retransmit is being performed the sender SHOULD | 608 | * When a Fast Retransmit is being performed the sender SHOULD |
609 | * ignore the value of cwnd and SHOULD NOT delay retransmission. | 609 | * ignore the value of cwnd and SHOULD NOT delay retransmission. |
610 | */ | 610 | */ |
611 | if (!chunk->fast_retransmit) | 611 | if (chunk->fast_retransmit <= 0) |
612 | if (transport->flight_size >= transport->cwnd) { | 612 | if (transport->flight_size >= transport->cwnd) { |
613 | retval = SCTP_XMIT_RWND_FULL; | 613 | retval = SCTP_XMIT_RWND_FULL; |
614 | goto finish; | 614 | goto finish; |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index efb72faba20c..f148f9576dd2 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -406,7 +406,7 @@ void sctp_retransmit_mark(struct sctp_outq *q, | |||
406 | * chunks that are not yet acked should be added to the | 406 | * chunks that are not yet acked should be added to the |
407 | * retransmit queue. | 407 | * retransmit queue. |
408 | */ | 408 | */ |
409 | if ((fast_retransmit && chunk->fast_retransmit) || | 409 | if ((fast_retransmit && (chunk->fast_retransmit > 0)) || |
410 | (!fast_retransmit && !chunk->tsn_gap_acked)) { | 410 | (!fast_retransmit && !chunk->tsn_gap_acked)) { |
411 | /* RFC 2960 6.2.1 Processing a Received SACK | 411 | /* RFC 2960 6.2.1 Processing a Received SACK |
412 | * | 412 | * |
@@ -603,7 +603,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
603 | /* Mark the chunk as ineligible for fast retransmit | 603 | /* Mark the chunk as ineligible for fast retransmit |
604 | * after it is retransmitted. | 604 | * after it is retransmitted. |
605 | */ | 605 | */ |
606 | chunk->fast_retransmit = 0; | 606 | if (chunk->fast_retransmit > 0) |
607 | chunk->fast_retransmit = -1; | ||
607 | 608 | ||
608 | *start_timer = 1; | 609 | *start_timer = 1; |
609 | q->empty = 0; | 610 | q->empty = 0; |
@@ -621,7 +622,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
621 | list_for_each(lchunk1, lqueue) { | 622 | list_for_each(lchunk1, lqueue) { |
622 | chunk1 = list_entry(lchunk1, struct sctp_chunk, | 623 | chunk1 = list_entry(lchunk1, struct sctp_chunk, |
623 | transmitted_list); | 624 | transmitted_list); |
624 | chunk1->fast_retransmit = 0; | 625 | if (chunk1->fast_retransmit > 0) |
626 | chunk1->fast_retransmit = -1; | ||
625 | } | 627 | } |
626 | } | 628 | } |
627 | } | 629 | } |
@@ -1562,11 +1564,11 @@ static void sctp_mark_missing(struct sctp_outq *q, | |||
1562 | /* | 1564 | /* |
1563 | * M4) If any DATA chunk is found to have a | 1565 | * M4) If any DATA chunk is found to have a |
1564 | * 'TSN.Missing.Report' | 1566 | * 'TSN.Missing.Report' |
1565 | * value larger than or equal to 4, mark that chunk for | 1567 | * value larger than or equal to 3, mark that chunk for |
1566 | * retransmission and start the fast retransmit procedure. | 1568 | * retransmission and start the fast retransmit procedure. |
1567 | */ | 1569 | */ |
1568 | 1570 | ||
1569 | if (chunk->tsn_missing_report >= 4) { | 1571 | if (chunk->tsn_missing_report >= 3) { |
1570 | chunk->fast_retransmit = 1; | 1572 | chunk->fast_retransmit = 1; |
1571 | do_fast_retransmit = 1; | 1573 | do_fast_retransmit = 1; |
1572 | } | 1574 | } |