aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/output.c')
-rw-r--r--net/dccp/output.c53
1 files changed, 31 insertions, 22 deletions
diff --git a/net/dccp/output.c b/net/dccp/output.c
index fe20068c5d8e..d06945c7d3df 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -53,8 +53,11 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
53 dccp_packet_hdr_len(dcb->dccpd_type); 53 dccp_packet_hdr_len(dcb->dccpd_type);
54 int err, set_ack = 1; 54 int err, set_ack = 1;
55 u64 ackno = dp->dccps_gsr; 55 u64 ackno = dp->dccps_gsr;
56 56 /*
57 dccp_inc_seqno(&dp->dccps_gss); 57 * Increment GSS here already in case the option code needs it.
58 * Update GSS for real only if option processing below succeeds.
59 */
60 dcb->dccpd_seq = ADD48(dp->dccps_gss, 1);
58 61
59 switch (dcb->dccpd_type) { 62 switch (dcb->dccpd_type) {
60 case DCCP_PKT_DATA: 63 case DCCP_PKT_DATA:
@@ -66,6 +69,9 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
66 69
67 case DCCP_PKT_REQUEST: 70 case DCCP_PKT_REQUEST:
68 set_ack = 0; 71 set_ack = 0;
72 /* Use ISS on the first (non-retransmitted) Request. */
73 if (icsk->icsk_retransmits == 0)
74 dcb->dccpd_seq = dp->dccps_iss;
69 /* fall through */ 75 /* fall through */
70 76
71 case DCCP_PKT_SYNC: 77 case DCCP_PKT_SYNC:
@@ -84,8 +90,6 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
84 break; 90 break;
85 } 91 }
86 92
87 dcb->dccpd_seq = dp->dccps_gss;
88
89 if (dccp_insert_options(sk, skb)) { 93 if (dccp_insert_options(sk, skb)) {
90 kfree_skb(skb); 94 kfree_skb(skb);
91 return -EPROTO; 95 return -EPROTO;
@@ -103,7 +107,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
103 /* XXX For now we're using only 48 bits sequence numbers */ 107 /* XXX For now we're using only 48 bits sequence numbers */
104 dh->dccph_x = 1; 108 dh->dccph_x = 1;
105 109
106 dp->dccps_awh = dp->dccps_gss; 110 dccp_update_gss(sk, dcb->dccpd_seq);
107 dccp_hdr_set_seq(dh, dp->dccps_gss); 111 dccp_hdr_set_seq(dh, dp->dccps_gss);
108 if (set_ack) 112 if (set_ack)
109 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), ackno); 113 dccp_hdr_set_ack(dccp_hdr_ack_bits(skb), ackno);
@@ -112,6 +116,11 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
112 case DCCP_PKT_REQUEST: 116 case DCCP_PKT_REQUEST:
113 dccp_hdr_request(skb)->dccph_req_service = 117 dccp_hdr_request(skb)->dccph_req_service =
114 dp->dccps_service; 118 dp->dccps_service;
119 /*
120 * Limit Ack window to ISS <= P.ackno <= GSS, so that
121 * only Responses to Requests we sent are considered.
122 */
123 dp->dccps_awl = dp->dccps_iss;
115 break; 124 break;
116 case DCCP_PKT_RESET: 125 case DCCP_PKT_RESET:
117 dccp_hdr_reset(skb)->dccph_reset_code = 126 dccp_hdr_reset(skb)->dccph_reset_code =
@@ -284,14 +293,26 @@ void dccp_write_xmit(struct sock *sk, int block)
284 } 293 }
285} 294}
286 295
287int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb) 296/**
297 * dccp_retransmit_skb - Retransmit Request, Close, or CloseReq packets
298 * There are only four retransmittable packet types in DCCP:
299 * - Request in client-REQUEST state (sec. 8.1.1),
300 * - CloseReq in server-CLOSEREQ state (sec. 8.3),
301 * - Close in node-CLOSING state (sec. 8.3),
302 * - Acks in client-PARTOPEN state (sec. 8.1.5, handled by dccp_delack_timer()).
303 * This function expects sk->sk_send_head to contain the original skb.
304 */
305int dccp_retransmit_skb(struct sock *sk)
288{ 306{
307 WARN_ON(sk->sk_send_head == NULL);
308
289 if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk) != 0) 309 if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk) != 0)
290 return -EHOSTUNREACH; /* Routing failure or similar. */ 310 return -EHOSTUNREACH; /* Routing failure or similar. */
291 311
292 return dccp_transmit_skb(sk, (skb_cloned(skb) ? 312 /* this count is used to distinguish original and retransmitted skb */
293 pskb_copy(skb, GFP_ATOMIC): 313 inet_csk(sk)->icsk_retransmits++;
294 skb_clone(skb, GFP_ATOMIC))); 314
315 return dccp_transmit_skb(sk, skb_clone(sk->sk_send_head, GFP_ATOMIC));
295} 316}
296 317
297struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst, 318struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
@@ -437,19 +458,7 @@ static inline void dccp_connect_init(struct sock *sk)
437 458
438 dccp_sync_mss(sk, dst_mtu(dst)); 459 dccp_sync_mss(sk, dst_mtu(dst));
439 460
440 /* 461 /* Initialise GAR as per 8.5; AWL/AWH are set in dccp_transmit_skb() */
441 * SWL and AWL are initially adjusted so that they are not less than
442 * the initial Sequence Numbers received and sent, respectively:
443 * SWL := max(GSR + 1 - floor(W/4), ISR),
444 * AWL := max(GSS - W' + 1, ISS).
445 * These adjustments MUST be applied only at the beginning of the
446 * connection.
447 */
448 dccp_update_gss(sk, dp->dccps_iss);
449 dccp_set_seqno(&dp->dccps_awl, max48(dp->dccps_awl, dp->dccps_iss));
450
451 /* S.GAR - greatest valid acknowledgement number received on a non-Sync;
452 * initialized to S.ISS (sec. 8.5) */
453 dp->dccps_gar = dp->dccps_iss; 462 dp->dccps_gar = dp->dccps_iss;
454 463
455 icsk->icsk_retransmits = 0; 464 icsk->icsk_retransmits = 0;