aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp')
-rw-r--r--net/dccp/ccid.c4
-rw-r--r--net/dccp/ccids/ccid2.c109
-rw-r--r--net/dccp/ccids/ccid2.h25
-rw-r--r--net/dccp/input.c61
-rw-r--r--net/dccp/ipv4.c1
-rw-r--r--net/dccp/ipv6.c9
-rw-r--r--net/dccp/output.c14
7 files changed, 153 insertions, 70 deletions
diff --git a/net/dccp/ccid.c b/net/dccp/ccid.c
index 36479ca61e0..48b585a5cba 100644
--- a/net/dccp/ccid.c
+++ b/net/dccp/ccid.c
@@ -118,7 +118,7 @@ static int ccid_activate(struct ccid_operations *ccid_ops)
118 if (ccid_ops->ccid_hc_tx_slab == NULL) 118 if (ccid_ops->ccid_hc_tx_slab == NULL)
119 goto out_free_rx_slab; 119 goto out_free_rx_slab;
120 120
121 pr_info("CCID: Activated CCID %d (%s)\n", 121 pr_info("DCCP: Activated CCID %d (%s)\n",
122 ccid_ops->ccid_id, ccid_ops->ccid_name); 122 ccid_ops->ccid_id, ccid_ops->ccid_name);
123 err = 0; 123 err = 0;
124out: 124out:
@@ -136,7 +136,7 @@ static void ccid_deactivate(struct ccid_operations *ccid_ops)
136 ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab); 136 ccid_kmem_cache_destroy(ccid_ops->ccid_hc_rx_slab);
137 ccid_ops->ccid_hc_rx_slab = NULL; 137 ccid_ops->ccid_hc_rx_slab = NULL;
138 138
139 pr_info("CCID: Deactivated CCID %d (%s)\n", 139 pr_info("DCCP: Deactivated CCID %d (%s)\n",
140 ccid_ops->ccid_id, ccid_ops->ccid_name); 140 ccid_ops->ccid_id, ccid_ops->ccid_name);
141} 141}
142 142
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index fadecd20d75..0462040fc81 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -153,17 +153,93 @@ out:
153 sock_put(sk); 153 sock_put(sk);
154} 154}
155 155
156/*
157 * Congestion window validation (RFC 2861).
158 */
159static int ccid2_do_cwv = 1;
160module_param(ccid2_do_cwv, bool, 0644);
161MODULE_PARM_DESC(ccid2_do_cwv, "Perform RFC2861 Congestion Window Validation");
162
163/**
164 * ccid2_update_used_window - Track how much of cwnd is actually used
165 * This is done in addition to CWV. The sender needs to have an idea of how many
166 * packets may be in flight, to set the local Sequence Window value accordingly
167 * (RFC 4340, 7.5.2). The CWV mechanism is exploited to keep track of the
168 * maximum-used window. We use an EWMA low-pass filter to filter out noise.
169 */
170static void ccid2_update_used_window(struct ccid2_hc_tx_sock *hc, u32 new_wnd)
171{
172 hc->tx_expected_wnd = (3 * hc->tx_expected_wnd + new_wnd) / 4;
173}
174
175/* This borrows the code of tcp_cwnd_application_limited() */
176static void ccid2_cwnd_application_limited(struct sock *sk, const u32 now)
177{
178 struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
179 /* don't reduce cwnd below the initial window (IW) */
180 u32 init_win = rfc3390_bytes_to_packets(dccp_sk(sk)->dccps_mss_cache),
181 win_used = max(hc->tx_cwnd_used, init_win);
182
183 if (win_used < hc->tx_cwnd) {
184 hc->tx_ssthresh = max(hc->tx_ssthresh,
185 (hc->tx_cwnd >> 1) + (hc->tx_cwnd >> 2));
186 hc->tx_cwnd = (hc->tx_cwnd + win_used) >> 1;
187 }
188 hc->tx_cwnd_used = 0;
189 hc->tx_cwnd_stamp = now;
190}
191
192/* This borrows the code of tcp_cwnd_restart() */
193static void ccid2_cwnd_restart(struct sock *sk, const u32 now)
194{
195 struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
196 u32 cwnd = hc->tx_cwnd, restart_cwnd,
197 iwnd = rfc3390_bytes_to_packets(dccp_sk(sk)->dccps_mss_cache);
198
199 hc->tx_ssthresh = max(hc->tx_ssthresh, (cwnd >> 1) + (cwnd >> 2));
200
201 /* don't reduce cwnd below the initial window (IW) */
202 restart_cwnd = min(cwnd, iwnd);
203 cwnd >>= (now - hc->tx_lsndtime) / hc->tx_rto;
204 hc->tx_cwnd = max(cwnd, restart_cwnd);
205
206 hc->tx_cwnd_stamp = now;
207 hc->tx_cwnd_used = 0;
208}
209
156static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len) 210static void ccid2_hc_tx_packet_sent(struct sock *sk, unsigned int len)
157{ 211{
158 struct dccp_sock *dp = dccp_sk(sk); 212 struct dccp_sock *dp = dccp_sk(sk);
159 struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); 213 struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk);
214 const u32 now = ccid2_time_stamp;
160 struct ccid2_seq *next; 215 struct ccid2_seq *next;
161 216
162 hc->tx_pipe++; 217 /* slow-start after idle periods (RFC 2581, RFC 2861) */
218 if (ccid2_do_cwv && !hc->tx_pipe &&
219 (s32)(now - hc->tx_lsndtime) >= hc->tx_rto)
220 ccid2_cwnd_restart(sk, now);
221
222 hc->tx_lsndtime = now;
223 hc->tx_pipe += 1;
224
225 /* see whether cwnd was fully used (RFC 2861), update expected window */
226 if (ccid2_cwnd_network_limited(hc)) {
227 ccid2_update_used_window(hc, hc->tx_cwnd);
228 hc->tx_cwnd_used = 0;
229 hc->tx_cwnd_stamp = now;
230 } else {
231 if (hc->tx_pipe > hc->tx_cwnd_used)
232 hc->tx_cwnd_used = hc->tx_pipe;
233
234 ccid2_update_used_window(hc, hc->tx_cwnd_used);
235
236 if (ccid2_do_cwv && (s32)(now - hc->tx_cwnd_stamp) >= hc->tx_rto)
237 ccid2_cwnd_application_limited(sk, now);
238 }
163 239
164 hc->tx_seqh->ccid2s_seq = dp->dccps_gss; 240 hc->tx_seqh->ccid2s_seq = dp->dccps_gss;
165 hc->tx_seqh->ccid2s_acked = 0; 241 hc->tx_seqh->ccid2s_acked = 0;
166 hc->tx_seqh->ccid2s_sent = ccid2_time_stamp; 242 hc->tx_seqh->ccid2s_sent = now;
167 243
168 next = hc->tx_seqh->ccid2s_next; 244 next = hc->tx_seqh->ccid2s_next;
169 /* check if we need to alloc more space */ 245 /* check if we need to alloc more space */
@@ -583,15 +659,6 @@ done:
583 dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks); 659 dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks);
584} 660}
585 661
586/*
587 * Convert RFC 3390 larger initial window into an equivalent number of packets.
588 * This is based on the numbers specified in RFC 5681, 3.1.
589 */
590static inline u32 rfc3390_bytes_to_packets(const u32 smss)
591{
592 return smss <= 1095 ? 4 : (smss > 2190 ? 2 : 3);
593}
594
595static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk) 662static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
596{ 663{
597 struct ccid2_hc_tx_sock *hc = ccid_priv(ccid); 664 struct ccid2_hc_tx_sock *hc = ccid_priv(ccid);
@@ -603,6 +670,7 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
603 670
604 /* Use larger initial windows (RFC 4341, section 5). */ 671 /* Use larger initial windows (RFC 4341, section 5). */
605 hc->tx_cwnd = rfc3390_bytes_to_packets(dp->dccps_mss_cache); 672 hc->tx_cwnd = rfc3390_bytes_to_packets(dp->dccps_mss_cache);
673 hc->tx_expected_wnd = hc->tx_cwnd;
606 674
607 /* Make sure that Ack Ratio is enabled and within bounds. */ 675 /* Make sure that Ack Ratio is enabled and within bounds. */
608 max_ratio = DIV_ROUND_UP(hc->tx_cwnd, 2); 676 max_ratio = DIV_ROUND_UP(hc->tx_cwnd, 2);
@@ -615,7 +683,8 @@ static int ccid2_hc_tx_init(struct ccid *ccid, struct sock *sk)
615 683
616 hc->tx_rto = DCCP_TIMEOUT_INIT; 684 hc->tx_rto = DCCP_TIMEOUT_INIT;
617 hc->tx_rpdupack = -1; 685 hc->tx_rpdupack = -1;
618 hc->tx_last_cong = ccid2_time_stamp; 686 hc->tx_last_cong = hc->tx_lsndtime = hc->tx_cwnd_stamp = ccid2_time_stamp;
687 hc->tx_cwnd_used = 0;
619 setup_timer(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire, 688 setup_timer(&hc->tx_rtotimer, ccid2_hc_tx_rto_expire,
620 (unsigned long)sk); 689 (unsigned long)sk);
621 INIT_LIST_HEAD(&hc->tx_av_chunks); 690 INIT_LIST_HEAD(&hc->tx_av_chunks);
@@ -636,18 +705,14 @@ static void ccid2_hc_tx_exit(struct sock *sk)
636 705
637static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) 706static void ccid2_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
638{ 707{
639 const struct dccp_sock *dp = dccp_sk(sk);
640 struct ccid2_hc_rx_sock *hc = ccid2_hc_rx_sk(sk); 708 struct ccid2_hc_rx_sock *hc = ccid2_hc_rx_sk(sk);
641 709
642 switch (DCCP_SKB_CB(skb)->dccpd_type) { 710 if (!dccp_data_packet(skb))
643 case DCCP_PKT_DATA: 711 return;
644 case DCCP_PKT_DATAACK: 712
645 hc->rx_data++; 713 if (++hc->rx_num_data_pkts >= dccp_sk(sk)->dccps_r_ack_ratio) {
646 if (hc->rx_data >= dp->dccps_r_ack_ratio) { 714 dccp_send_ack(sk);
647 dccp_send_ack(sk); 715 hc->rx_num_data_pkts = 0;
648 hc->rx_data = 0;
649 }
650 break;
651 } 716 }
652} 717}
653 718
diff --git a/net/dccp/ccids/ccid2.h b/net/dccp/ccids/ccid2.h
index e9985dafc2c..f585d330e1e 100644
--- a/net/dccp/ccids/ccid2.h
+++ b/net/dccp/ccids/ccid2.h
@@ -53,6 +53,10 @@ struct ccid2_seq {
53 * @tx_rttvar: moving average/maximum of @mdev_max 53 * @tx_rttvar: moving average/maximum of @mdev_max
54 * @tx_rto: RTO value deriving from SRTT and RTTVAR (RFC 2988) 54 * @tx_rto: RTO value deriving from SRTT and RTTVAR (RFC 2988)
55 * @tx_rtt_seq: to decay RTTVAR at most once per flight 55 * @tx_rtt_seq: to decay RTTVAR at most once per flight
56 * @tx_cwnd_used: actually used cwnd, W_used of RFC 2861
57 * @tx_expected_wnd: moving average of @tx_cwnd_used
58 * @tx_cwnd_stamp: to track idle periods in CWV
59 * @tx_lsndtime: last time (in jiffies) a data packet was sent
56 * @tx_rpseq: last consecutive seqno 60 * @tx_rpseq: last consecutive seqno
57 * @tx_rpdupack: dupacks since rpseq 61 * @tx_rpdupack: dupacks since rpseq
58 * @tx_av_chunks: list of Ack Vectors received on current skb 62 * @tx_av_chunks: list of Ack Vectors received on current skb
@@ -76,6 +80,12 @@ struct ccid2_hc_tx_sock {
76 u64 tx_rtt_seq:48; 80 u64 tx_rtt_seq:48;
77 struct timer_list tx_rtotimer; 81 struct timer_list tx_rtotimer;
78 82
83 /* Congestion Window validation (optional, RFC 2861) */
84 u32 tx_cwnd_used,
85 tx_expected_wnd,
86 tx_cwnd_stamp,
87 tx_lsndtime;
88
79 u64 tx_rpseq; 89 u64 tx_rpseq;
80 int tx_rpdupack; 90 int tx_rpdupack;
81 u32 tx_last_cong; 91 u32 tx_last_cong;
@@ -88,8 +98,21 @@ static inline bool ccid2_cwnd_network_limited(struct ccid2_hc_tx_sock *hc)
88 return hc->tx_pipe >= hc->tx_cwnd; 98 return hc->tx_pipe >= hc->tx_cwnd;
89} 99}
90 100
101/*
102 * Convert RFC 3390 larger initial window into an equivalent number of packets.
103 * This is based on the numbers specified in RFC 5681, 3.1.
104 */
105static inline u32 rfc3390_bytes_to_packets(const u32 smss)
106{
107 return smss <= 1095 ? 4 : (smss > 2190 ? 2 : 3);
108}
109
110/**
111 * struct ccid2_hc_rx_sock - Receiving end of CCID-2 half-connection
112 * @rx_num_data_pkts: number of data packets received since last feedback
113 */
91struct ccid2_hc_rx_sock { 114struct ccid2_hc_rx_sock {
92 int rx_data; 115 u32 rx_num_data_pkts;
93}; 116};
94 117
95static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk) 118static inline struct ccid2_hc_tx_sock *ccid2_hc_tx_sk(const struct sock *sk)
diff --git a/net/dccp/input.c b/net/dccp/input.c
index 4222e7a654b..51d5fe5fffb 100644
--- a/net/dccp/input.c
+++ b/net/dccp/input.c
@@ -619,20 +619,31 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
619 return 1; 619 return 1;
620 } 620 }
621 621
622 if (sk->sk_state != DCCP_REQUESTING && sk->sk_state != DCCP_RESPOND) { 622 /* Step 6: Check sequence numbers (omitted in LISTEN/REQUEST state) */
623 if (dccp_check_seqno(sk, skb)) 623 if (sk->sk_state != DCCP_REQUESTING && dccp_check_seqno(sk, skb))
624 goto discard; 624 goto discard;
625
626 /*
627 * Step 8: Process options and mark acknowledgeable
628 */
629 if (dccp_parse_options(sk, NULL, skb))
630 return 1;
631 625
632 dccp_handle_ackvec_processing(sk, skb); 626 /*
633 dccp_deliver_input_to_ccids(sk, skb); 627 * Step 7: Check for unexpected packet types
628 * If (S.is_server and P.type == Response)
629 * or (S.is_client and P.type == Request)
630 * or (S.state == RESPOND and P.type == Data),
631 * Send Sync packet acknowledging P.seqno
632 * Drop packet and return
633 */
634 if ((dp->dccps_role != DCCP_ROLE_CLIENT &&
635 dh->dccph_type == DCCP_PKT_RESPONSE) ||
636 (dp->dccps_role == DCCP_ROLE_CLIENT &&
637 dh->dccph_type == DCCP_PKT_REQUEST) ||
638 (sk->sk_state == DCCP_RESPOND && dh->dccph_type == DCCP_PKT_DATA)) {
639 dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC);
640 goto discard;
634 } 641 }
635 642
643 /* Step 8: Process options */
644 if (dccp_parse_options(sk, NULL, skb))
645 return 1;
646
636 /* 647 /*
637 * Step 9: Process Reset 648 * Step 9: Process Reset
638 * If P.type == Reset, 649 * If P.type == Reset,
@@ -640,31 +651,15 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
640 * S.state := TIMEWAIT 651 * S.state := TIMEWAIT
641 * Set TIMEWAIT timer 652 * Set TIMEWAIT timer
642 * Drop packet and return 653 * Drop packet and return
643 */ 654 */
644 if (dh->dccph_type == DCCP_PKT_RESET) { 655 if (dh->dccph_type == DCCP_PKT_RESET) {
645 dccp_rcv_reset(sk, skb); 656 dccp_rcv_reset(sk, skb);
646 return 0; 657 return 0;
647 /* 658 } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) { /* Step 13 */
648 * Step 7: Check for unexpected packet types
649 * If (S.is_server and P.type == Response)
650 * or (S.is_client and P.type == Request)
651 * or (S.state == RESPOND and P.type == Data),
652 * Send Sync packet acknowledging P.seqno
653 * Drop packet and return
654 */
655 } else if ((dp->dccps_role != DCCP_ROLE_CLIENT &&
656 dh->dccph_type == DCCP_PKT_RESPONSE) ||
657 (dp->dccps_role == DCCP_ROLE_CLIENT &&
658 dh->dccph_type == DCCP_PKT_REQUEST) ||
659 (sk->sk_state == DCCP_RESPOND &&
660 dh->dccph_type == DCCP_PKT_DATA)) {
661 dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC);
662 goto discard;
663 } else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) {
664 if (dccp_rcv_closereq(sk, skb)) 659 if (dccp_rcv_closereq(sk, skb))
665 return 0; 660 return 0;
666 goto discard; 661 goto discard;
667 } else if (dh->dccph_type == DCCP_PKT_CLOSE) { 662 } else if (dh->dccph_type == DCCP_PKT_CLOSE) { /* Step 14 */
668 if (dccp_rcv_close(sk, skb)) 663 if (dccp_rcv_close(sk, skb))
669 return 0; 664 return 0;
670 goto discard; 665 goto discard;
@@ -679,8 +674,12 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
679 __kfree_skb(skb); 674 __kfree_skb(skb);
680 return 0; 675 return 0;
681 676
682 case DCCP_RESPOND:
683 case DCCP_PARTOPEN: 677 case DCCP_PARTOPEN:
678 /* Step 8: if using Ack Vectors, mark packet acknowledgeable */
679 dccp_handle_ackvec_processing(sk, skb);
680 dccp_deliver_input_to_ccids(sk, skb);
681 /* fall through */
682 case DCCP_RESPOND:
684 queued = dccp_rcv_respond_partopen_state_process(sk, skb, 683 queued = dccp_rcv_respond_partopen_state_process(sk, skb,
685 dh, len); 684 dh, len);
686 break; 685 break;
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 8c36adfd191..332639b56f4 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -26,6 +26,7 @@
26#include <net/timewait_sock.h> 26#include <net/timewait_sock.h>
27#include <net/tcp_states.h> 27#include <net/tcp_states.h>
28#include <net/xfrm.h> 28#include <net/xfrm.h>
29#include <net/secure_seq.h>
29 30
30#include "ackvec.h" 31#include "ackvec.h"
31#include "ccid.h" 32#include "ccid.h"
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 8dc4348774a..b74f76117dc 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -29,6 +29,7 @@
29#include <net/transp_v6.h> 29#include <net/transp_v6.h>
30#include <net/ip6_checksum.h> 30#include <net/ip6_checksum.h>
31#include <net/xfrm.h> 31#include <net/xfrm.h>
32#include <net/secure_seq.h>
32 33
33#include "dccp.h" 34#include "dccp.h"
34#include "ipv6.h" 35#include "ipv6.h"
@@ -69,13 +70,7 @@ static inline void dccp_v6_send_check(struct sock *sk, struct sk_buff *skb)
69 dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr); 70 dh->dccph_checksum = dccp_v6_csum_finish(skb, &np->saddr, &np->daddr);
70} 71}
71 72
72static inline __u32 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr, 73static inline __u64 dccp_v6_init_sequence(struct sk_buff *skb)
73 __be16 sport, __be16 dport )
74{
75 return secure_tcpv6_sequence_number(saddr, daddr, sport, dport);
76}
77
78static inline __u32 dccp_v6_init_sequence(struct sk_buff *skb)
79{ 74{
80 return secure_dccpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32, 75 return secure_dccpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32,
81 ipv6_hdr(skb)->saddr.s6_addr32, 76 ipv6_hdr(skb)->saddr.s6_addr32,
diff --git a/net/dccp/output.c b/net/dccp/output.c
index fab108e51e5..dede3edb884 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -27,11 +27,13 @@ static inline void dccp_event_ack_sent(struct sock *sk)
27 inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); 27 inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);
28} 28}
29 29
30static void dccp_skb_entail(struct sock *sk, struct sk_buff *skb) 30/* enqueue @skb on sk_send_head for retransmission, return clone to send now */
31static struct sk_buff *dccp_skb_entail(struct sock *sk, struct sk_buff *skb)
31{ 32{
32 skb_set_owner_w(skb, sk); 33 skb_set_owner_w(skb, sk);
33 WARN_ON(sk->sk_send_head); 34 WARN_ON(sk->sk_send_head);
34 sk->sk_send_head = skb; 35 sk->sk_send_head = skb;
36 return skb_clone(sk->sk_send_head, gfp_any());
35} 37}
36 38
37/* 39/*
@@ -552,8 +554,7 @@ int dccp_connect(struct sock *sk)
552 554
553 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST; 555 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_REQUEST;
554 556
555 dccp_skb_entail(sk, skb); 557 dccp_transmit_skb(sk, dccp_skb_entail(sk, skb));
556 dccp_transmit_skb(sk, skb_clone(skb, GFP_KERNEL));
557 DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS); 558 DCCP_INC_STATS(DCCP_MIB_ACTIVEOPENS);
558 559
559 /* Timer for repeating the REQUEST until an answer. */ 560 /* Timer for repeating the REQUEST until an answer. */
@@ -678,8 +679,7 @@ void dccp_send_close(struct sock *sk, const int active)
678 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_CLOSE; 679 DCCP_SKB_CB(skb)->dccpd_type = DCCP_PKT_CLOSE;
679 680
680 if (active) { 681 if (active) {
681 dccp_skb_entail(sk, skb); 682 skb = dccp_skb_entail(sk, skb);
682 dccp_transmit_skb(sk, skb_clone(skb, prio));
683 /* 683 /*
684 * Retransmission timer for active-close: RFC 4340, 8.3 requires 684 * Retransmission timer for active-close: RFC 4340, 8.3 requires
685 * to retransmit the Close/CloseReq until the CLOSING/CLOSEREQ 685 * to retransmit the Close/CloseReq until the CLOSING/CLOSEREQ
@@ -692,6 +692,6 @@ void dccp_send_close(struct sock *sk, const int active)
692 */ 692 */
693 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, 693 inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
694 DCCP_TIMEOUT_INIT, DCCP_RTO_MAX); 694 DCCP_TIMEOUT_INIT, DCCP_RTO_MAX);
695 } else 695 }
696 dccp_transmit_skb(sk, skb); 696 dccp_transmit_skb(sk, skb);
697} 697}