diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-09-14 08:57:30 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-14 08:57:30 -0400 |
commit | dbaa9a9d2b37d838125fb7f2b9fdc5dc5fa4eaa9 (patch) | |
tree | 8641efeba632bddfa0e486b41a5f19578b1a1a31 /net/dccp | |
parent | 142e27fc8a3619471669d6241784eec9167c47d1 (diff) | |
parent | 2f4ba45a75d6383b4a1201169a808ffea416ffa0 (diff) |
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'net/dccp')
-rw-r--r-- | net/dccp/ccids/ccid3.c | 321 | ||||
-rw-r--r-- | net/dccp/ccids/ccid3.h | 16 | ||||
-rw-r--r-- | net/dccp/ccids/lib/packet_history.h | 3 | ||||
-rw-r--r-- | net/dccp/dccp.h | 16 | ||||
-rw-r--r-- | net/dccp/input.c | 4 | ||||
-rw-r--r-- | net/dccp/ipv4.c | 5 | ||||
-rw-r--r-- | net/dccp/minisocks.c | 1 | ||||
-rw-r--r-- | net/dccp/options.c | 90 | ||||
-rw-r--r-- | net/dccp/output.c | 3 |
9 files changed, 239 insertions, 220 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 7bf3b3a91e9..38aa8498611 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -43,12 +43,22 @@ #include "ccid3.h" /* - * Reason for maths with 10 here is to avoid 32 bit overflow when a is big. + * Reason for maths here is to avoid 32 bit overflow when a is big. + * With this we get close to the limit. */ static inline u32 usecs_div(const u32 a, const u32 b) { - const u32 tmp = a * (USEC_PER_SEC / 10); - return b > 20 ? tmp / (b / 10) : tmp; + const u32 div = a < (UINT_MAX / (USEC_PER_SEC / 10)) ? 10 : + a < (UINT_MAX / (USEC_PER_SEC / 50)) ? 50 : + a < (UINT_MAX / (USEC_PER_SEC / 100)) ? 100 : + a < (UINT_MAX / (USEC_PER_SEC / 500)) ? 500 : + a < (UINT_MAX / (USEC_PER_SEC / 1000)) ? 1000 : + a < (UINT_MAX / (USEC_PER_SEC / 5000)) ? 5000 : + a < (UINT_MAX / (USEC_PER_SEC / 10000)) ? 10000 : + a < (UINT_MAX / (USEC_PER_SEC / 50000)) ? 50000 : + 100000; + const u32 tmp = a * (USEC_PER_SEC / div); + return (b >= 2 * div) ? tmp / (b / div) : tmp; } static int ccid3_debug; @@ -68,13 +78,11 @@ static struct dccp_li_hist *ccid3_li_hist; static int ccid3_init(struct sock *sk) { - ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); return 0; } static void ccid3_exit(struct sock *sk) { - ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); } /* TFRC sender states */ @@ -102,8 +110,7 @@ static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state) static inline void ccid3_hc_tx_set_state(struct sock *sk, enum ccid3_hc_tx_states state) { - struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; + struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); enum ccid3_hc_tx_states oldstate = hctx->ccid3hctx_state; ccid3_pr_debug("%s(%p) %-8.8s -> %s\n", @@ -144,8 +151,7 @@ static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx) */ static void ccid3_hc_tx_update_x(struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; + struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); /* To avoid large error in calcX */ if (hctx->ccid3hctx_p >= TFRC_SMALLEST_P) { @@ -159,7 +165,7 @@ static void ccid3_hc_tx_update_x(struct sock *sk) } else { struct timeval now; - do_gettimeofday(&now); + dccp_timestamp(sk, &now); if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >= hctx->ccid3hctx_rtt) { hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv, @@ -174,9 +180,8 @@ static void ccid3_hc_tx_update_x(struct sock *sk) static void ccid3_hc_tx_no_feedback_timer(unsigned long data) { struct sock *sk = (struct sock *)data; - struct dccp_sock *dp = dccp_sk(sk); unsigned long next_tmout = 0; - struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; + struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); bh_lock_sock(sk); if (sock_owned_by_user(sk)) { @@ -274,20 +279,20 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb, int len) { struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; + struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); struct dccp_tx_hist_entry *new_packet; struct timeval now; long delay; int rc = -ENOTCONN; - /* Check if pure ACK or Terminating*/ + BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM); + /* Check if pure ACK or Terminating*/ /* * XXX: We only call this function for DATA and DATAACK, on, these * packets can have zero length, but why the comment about "pure ACK"? */ - if (hctx == NULL || len == 0 || - hctx->ccid3hctx_state == TFRC_SSTATE_TERM) + if (unlikely(len == 0)) goto out; /* See if last packet allocated was not sent */ @@ -297,23 +302,20 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, SLAB_ATOMIC); rc = -ENOBUFS; - if (new_packet == NULL) { - ccid3_pr_debug("%s, sk=%p, not enough mem to add " - "to history, send refused\n", - dccp_role(sk), sk); + if (unlikely(new_packet == NULL)) { + LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, not enough " + "mem to add to history, send refused\n", + __FUNCTION__, dccp_role(sk), sk); goto out; } dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet); } - do_gettimeofday(&now); + dccp_timestamp(sk, &now); switch (hctx->ccid3hctx_state) { case TFRC_SSTATE_NO_SENT: - ccid3_pr_debug("%s, sk=%p, first packet(%llu)\n", - dccp_role(sk), sk, dp->dccps_gss); - hctx->ccid3hctx_no_feedback_timer.function = ccid3_hc_tx_no_feedback_timer; hctx->ccid3hctx_no_feedback_timer.data = (unsigned long)sk; sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, @@ -321,7 +323,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, hctx->ccid3hctx_last_win_count = 0; hctx->ccid3hctx_t_last_win_count = now; ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); - hctx->ccid3hctx_t_ipi = TFRC_INITIAL_TIMEOUT; + hctx->ccid3hctx_t_ipi = TFRC_INITIAL_IPI; /* Set nominal send time for initial packet */ hctx->ccid3hctx_t_nom = now; @@ -334,7 +336,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, case TFRC_SSTATE_FBACK: delay = (timeval_delta(&now, &hctx->ccid3hctx_t_nom) - hctx->ccid3hctx_delta); - ccid3_pr_debug("send_packet delay=%ld\n", delay); delay /= -1000; /* divide by -1000 is to convert to ms and get sign right */ rc = delay > 0 ? delay : 0; @@ -348,29 +349,25 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, } /* Can we send? if so add options and add to packet history */ - if (rc == 0) + if (rc == 0) { + dp->dccps_hc_tx_insert_options = 1; new_packet->dccphtx_ccval = DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count; + } out: return rc; } static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) { - struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; + const struct dccp_sock *dp = dccp_sk(sk); + struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); struct timeval now; - BUG_ON(hctx == NULL); - - if (hctx->ccid3hctx_state == TFRC_SSTATE_TERM) { - ccid3_pr_debug("%s, sk=%p, while state is TFRC_SSTATE_TERM!\n", - dccp_role(sk), sk); - return; - } + BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM); - do_gettimeofday(&now); + dccp_timestamp(sk, &now); /* check if we have sent a data packet */ if (len > 0) { @@ -378,14 +375,14 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) struct dccp_tx_hist_entry *packet; packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); - if (packet == NULL) { - printk(KERN_CRIT "%s: packet doesn't exists in " - "history!\n", __FUNCTION__); + if (unlikely(packet == NULL)) { + LIMIT_NETDEBUG(KERN_WARNING "%s: packet doesn't " + "exists in history!\n", __FUNCTION__); return; } - if (packet->dccphtx_sent) { - printk(KERN_CRIT "%s: no unsent packet in history!\n", - __FUNCTION__); + if (unlikely(packet->dccphtx_sent)) { + LIMIT_NETDEBUG(KERN_WARNING "%s: no unsent packet in " + "history!\n", __FUNCTION__); return; } packet->dccphtx_tstamp = now; @@ -445,24 +442,18 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) { - struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; + const struct dccp_sock *dp = dccp_sk(sk); + struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); struct ccid3_options_received *opt_recv; struct dccp_tx_hist_entry *packet; + struct timeval now; unsigned long next_tmout; u32 t_elapsed; u32 pinv; u32 x_recv; u32 r_sample; - if (hctx == NULL) - return; - - if (hctx->ccid3hctx_state == TFRC_SSTATE_TERM) { - ccid3_pr_debug("%s, sk=%p, received a packet when " - "terminating!\n", dccp_role(sk), sk); - return; - } + BUG_ON(hctx == NULL || hctx->ccid3hctx_state == TFRC_SSTATE_TERM); /* we are only interested in ACKs */ if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK || @@ -471,7 +462,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) opt_recv = &hctx->ccid3hctx_options_received; - t_elapsed = dp->dccps_options_received.dccpor_elapsed_time; + t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10; x_recv = opt_recv->ccid3or_receive_rate; pinv = opt_recv->ccid3or_loss_event_rate; @@ -486,19 +477,24 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) /* get t_recvdata from history */ packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist, DCCP_SKB_CB(skb)->dccpd_ack_seq); - if (packet == NULL) { - ccid3_pr_debug("%s, sk=%p, seqno %llu(%s) does't " - "exist in history!\n", - dccp_role(sk), sk, - DCCP_SKB_CB(skb)->dccpd_ack_seq, - dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); + if (unlikely(packet == NULL)) { + LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, seqno " + "%llu(%s) does't exist in history!\n", + __FUNCTION__, dccp_role(sk), sk, + (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, + dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); return; } /* Update RTT */ - r_sample = timeval_now_delta(&packet->dccphtx_tstamp); - /* FIXME: */ - // r_sample -= usecs_to_jiffies(t_elapsed * 10); + dccp_timestamp(sk, &now); + r_sample = timeval_delta(&now, &packet->dccphtx_tstamp); + if (unlikely(r_sample <= t_elapsed)) + LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, " + "t_elapsed=%uus\n", + __FUNCTION__, r_sample, t_elapsed); + else + r_sample -= t_elapsed; /* Update RTT estimate by * If (No feedback recv) @@ -591,11 +587,11 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) static void ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb) { - const struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; + const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); + + BUG_ON(hctx == NULL); - if (hctx == NULL || !(sk->sk_state == DCCP_OPEN || - sk->sk_state == DCCP_PARTOPEN)) + if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)) return; DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count; @@ -606,12 +602,11 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, unsigned char *value) { int rc = 0; - struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; + const struct dccp_sock *dp = dccp_sk(sk); + struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); struct ccid3_options_received *opt_recv; - if (hctx == NULL) - return 0; + BUG_ON(hctx == NULL); opt_recv = &hctx->ccid3hctx_options_received; @@ -625,10 +620,10 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, switch (option) { case TFRC_OPT_LOSS_EVENT_RATE: - if (len != 4) { - ccid3_pr_debug("%s, sk=%p, invalid len for " - "TFRC_OPT_LOSS_EVENT_RATE\n", - dccp_role(sk), sk); + if (unlikely(len != 4)) { + LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid " + "len for TFRC_OPT_LOSS_EVENT_RATE\n", + __FUNCTION__, dccp_role(sk), sk); rc = -EINVAL; } else { opt_recv->ccid3or_loss_event_rate = ntohl(*(u32 *)value); @@ -646,10 +641,10 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, opt_recv->ccid3or_loss_intervals_len); break; case TFRC_OPT_RECEIVE_RATE: - if (len != 4) { - ccid3_pr_debug("%s, sk=%p, invalid len for " - "TFRC_OPT_RECEIVE_RATE\n", - dccp_role(sk), sk); + if (unlikely(len != 4)) { + LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, invalid " + "len for TFRC_OPT_RECEIVE_RATE\n", + __FUNCTION__, dccp_role(sk), sk); rc = -EINVAL; } else { opt_recv->ccid3or_receive_rate = ntohl(*(u32 *)value); @@ -668,13 +663,11 @@ static int ccid3_hc_tx_init(struct sock *sk) struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hctx; - ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); - - hctx = dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx), - gfp_any()); - if (hctx == NULL) + dp->dccps_hc_tx_ccid_private = kmalloc(sizeof(*hctx), gfp_any()); + if (dp->dccps_hc_tx_ccid_private == NULL) return -ENOMEM; + hctx = ccid3_hc_tx_sk(sk); memset(hctx, 0, sizeof(*hctx)); if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && @@ -696,9 +689,8 @@ static int ccid3_hc_tx_init(struct sock *sk) static void ccid3_hc_tx_exit(struct sock *sk) { struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; + struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); - ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); BUG_ON(hctx == NULL); ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM); @@ -738,8 +730,7 @@ static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state) static inline void ccid3_hc_rx_set_state(struct sock *sk, enum ccid3_hc_rx_states state) { - struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; + struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); enum ccid3_hc_rx_states oldstate = hcrx->ccid3hcrx_state; ccid3_pr_debug("%s(%p) %-8.8s -> %s\n", @@ -751,14 +742,14 @@ static inline void ccid3_hc_rx_set_state(struct sock *sk, static void ccid3_hc_rx_send_feedback(struct sock *sk) { + struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; struct dccp_rx_hist_entry *packet; struct timeval now; ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); - do_gettimeofday(&now); + dccp_timestamp(sk, &now); switch (hcrx->ccid3hcrx_state) { case TFRC_RSTATE_NO_DATA: @@ -767,11 +758,8 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) case TFRC_RSTATE_DATA: { const u32 delta = timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_feedback); - - hcrx->ccid3hcrx_x_recv = (hcrx->ccid3hcrx_bytes_recv * - USEC_PER_SEC); - if (likely(delta > 1)) - hcrx->ccid3hcrx_x_recv /= delta; + hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, + delta); } break; default: @@ -782,10 +770,10 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) } packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist); - if (packet == NULL) { - printk(KERN_CRIT "%s: %s, sk=%p, no data packet in history!\n", - __FUNCTION__, dccp_role(sk), sk); - dump_stack(); + if (unlikely(packet == NULL)) { + LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, no data packet " + "in history!\n", + __FUNCTION__, dccp_role(sk), sk); return; } @@ -801,17 +789,18 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) hcrx->ccid3hcrx_pinv = ~0; else hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p; + dp->dccps_hc_rx_insert_options = 1; dccp_send_ack(sk); } static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) { - const struct dccp_sock *dp = dccp_sk(sk); + const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); u32 x_recv, pinv; - struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; - if (hcrx == NULL || !(sk->sk_state == DCCP_OPEN || - sk->sk_state == DCCP_PARTOPEN)) + BUG_ON(hcrx == NULL); + + if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)) return; DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter; @@ -837,8 +826,7 @@ static void ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) static u32 ccid3_hc_rx_calc_first_li(struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; + struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); struct dccp_rx_hist_entry *entry, *next, *tail = NULL; u32 rtt, delta, x_recv, fval, p, tmp2; struct timeval tstamp = { 0, }; @@ -869,17 +857,17 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk) } } - if (step == 0) { - printk(KERN_CRIT "%s: %s, sk=%p, packet history contains no " - "data packets!\n", - __FUNCTION__, dccp_role(sk), sk); + if (unlikely(step == 0)) { + LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, packet history " + "contains no data packets!\n", + __FUNCTION__, dccp_role(sk), sk); return ~0; } - if (interval == 0) { - ccid3_pr_debug("%s, sk=%p, Could not find a win_count " - "interval > 0. Defaulting to 1\n", - dccp_role(sk), sk); + if (unlikely(interval == 0)) { + LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Could not find a " + "win_count interval > 0. Defaulting to 1\n", + __FUNCTION__, dccp_role(sk), sk); interval = 1; } found: @@ -889,10 +877,9 @@ found: if (rtt == 0) rtt = 1; - delta = timeval_now_delta(&hcrx->ccid3hcrx_tstamp_last_feedback); - x_recv = hcrx->ccid3hcrx_bytes_recv * USEC_PER_SEC; - if (likely(delta > 1)) - x_recv /= delta; + dccp_timestamp(sk, &tstamp); + delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); + x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta); tmp1 = (u64)x_recv * (u64)rtt; do_div(tmp1,10000000); @@ -911,8 +898,7 @@ found: static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) { - struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; + struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); if (seq_loss != DCCP_MAX_SEQNO + 1 && list_empty(&hcrx->ccid3hcrx_li_hist)) { @@ -924,14 +910,14 @@ static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) if (li_tail == NULL) return; li_tail->dccplih_interval = ccid3_hc_rx_calc_first_li(sk); - } - /* FIXME: find end of interval */ + } else + LIMIT_NETDEBUG(KERN_WARNING "%s: FIXME: find end of " + "interval\n", __FUNCTION__); } static void ccid3_hc_rx_detect_loss(struct sock *sk) { - struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; + struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); u8 win_loss; const u64 seq_loss = dccp_rx_hist_detect_loss(&hcrx->ccid3hcrx_hist, &hcrx->ccid3hcrx_li_hist, @@ -942,22 +928,19 @@ static void ccid3_hc_rx_detect_loss(struct sock *sk) static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) { - struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; + struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); const struct dccp_options_received *opt_recv; struct dccp_rx_hist_entry *packet; struct timeval now; u8 win_count; - u32 p_prev; + u32 p_prev, r_sample, t_elapsed; int ins; - if (hcrx == NULL) - return; - - BUG_ON(!(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA || + BUG_ON(hcrx == NULL || + !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA || hcrx->ccid3hcrx_state == TFRC_RSTATE_DATA)); - opt_recv = &dp->dccps_options_received; + opt_recv = &dccp_sk(sk)->dccps_options_received; switch (DCCP_SKB_CB(skb)->dccpd_type) { case DCCP_PKT_ACK: @@ -967,10 +950,24 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) if (opt_recv->dccpor_timestamp_echo == 0) break; p_prev = hcrx->ccid3hcrx_rtt; - do_gettimeofday(&now); - hcrx->ccid3hcrx_rtt = timeval_usecs(&now) - - (opt_recv->dccpor_timestamp_echo - - opt_recv->dccpor_elapsed_time) * 10; + dccp_timestamp(sk, &now); + timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10); + r_sample = timeval_usecs(&now); + t_elapsed = opt_recv->dccpor_elapsed_time * 10; + + if (unlikely(r_sample <= t_elapsed)) + LIMIT_NETDEBUG(KERN_WARNING "%s: r_sample=%uus, " + "t_elapsed=%uus\n", + __FUNCTION__, r_sample, t_elapsed); + else + r_sample -= t_elapsed; + + if (hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA) + hcrx->ccid3hcrx_rtt = r_sample; + else + hcrx->ccid3hcrx_rtt = (hcrx->ccid3hcrx_rtt * 9) / 10 + + r_sample / 10; + if (p_prev != hcrx->ccid3hcrx_rtt) ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n", dccp_role(sk), hcrx->ccid3hcrx_rtt, @@ -978,19 +975,16 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) break; case DCCP_PKT_DATA: break; - default: - ccid3_pr_debug("%s, sk=%p, not DATA/DATAACK/ACK packet(%s)\n", - dccp_role(sk), sk, - dccp_packet_name(DCCP_SKB_CB(skb)->dccpd_type)); + default: /* We're not interested in other packet types, move along */ return; } - packet = dccp_rx_hist_entry_new(ccid3_rx_hist, opt_recv->dccpor_ndp, + packet = dccp_rx_hist_entry_new(ccid3_rx_hist, sk, opt_recv->dccpor_ndp, skb, SLAB_ATOMIC); - if (packet == NULL) { - ccid3_pr_debug("%s, sk=%p, Not enough mem to add rx packet " - "to history (consider it lost)!", - dccp_role(sk), sk); + if (unlikely(packet == NULL)) { + LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, Not enough mem to " + "add rx packet to history, consider it lost!\n", + __FUNCTION__, dccp_role(sk), sk); return; } @@ -1017,7 +1011,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) if (ins != 0) break; - do_gettimeofday(&now); + dccp_timestamp(sk, &now); if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >= hcrx->ccid3hcrx_rtt) { hcrx->ccid3hcrx_tstamp_last_ack = now; @@ -1056,11 +1050,11 @@ static int ccid3_hc_rx_init(struct sock *sk) ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); - hcrx = dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx), - gfp_any()); - if (hcrx == NULL) + dp->dccps_hc_rx_ccid_private = kmalloc(sizeof(*hcrx), gfp_any()); + if (dp->dccps_hc_rx_ccid_private == NULL) return -ENOMEM; + hcrx = ccid3_hc_rx_sk(sk); memset(hcrx, 0, sizeof(*hcrx)); if (dp->dccps_packet_size >= TFRC_MIN_PACKET_SIZE && @@ -1072,23 +1066,18 @@ static int ccid3_hc_rx_init(struct sock *sk) hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA; INIT_LIST_HEAD(&hcrx->ccid3hcrx_hist); INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist); - /* - * XXX this seems to be paranoid, need to think more about this, for - * now start with something different than zero. -acme - */ - hcrx->ccid3hcrx_rtt = USEC_PER_SEC / 5; + dccp_timestamp(sk, &hcrx->ccid3hcrx_tstamp_last_ack); + hcrx->ccid3hcrx_tstamp_last_feedback = hcrx->ccid3hcrx_tstamp_last_ack; + hcrx->ccid3hcrx_rtt = 5000; /* XXX 5ms for now... */ return 0; } static void ccid3_hc_rx_exit(struct sock *sk) { + struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); struct dccp_sock *dp = dccp_sk(sk); - struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; - ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); - - if (hcrx == NULL) - return; + BUG_ON(hcrx == NULL); ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM); @@ -1104,12 +1093,14 @@ static void ccid3_hc_rx_exit(struct sock *sk) static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info) { - const struct dccp_sock *dp = dccp_sk(sk); - const struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; + const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); - if (hcrx == NULL) + /* Listen socks doesn't have a private CCID block */ + if (sk->sk_state == DCCP_LISTEN) return; + BUG_ON(hcrx == NULL); + info->tcpi_ca_state = hcrx->ccid3hcrx_state; info->tcpi_options |= TCPI_OPT_TIMESTAMPS; info->tcpi_rcv_rtt = hcrx->ccid3hcrx_rtt; @@ -1117,12 +1108,14 @@ static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info) static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info) { - const struct dccp_sock *dp = dccp_sk(sk); - const struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; + const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); - if (hctx == NULL) + /* Listen socks doesn't have a private CCID block */ + if (sk->sk_state == DCCP_LISTEN) return; + BUG_ON(hctx == NULL); + info->tcpi_rto = hctx->ccid3hctx_t_rto; info->tcpi_rtt = hctx->ccid3hctx_rtt; } diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index ee8cbace663..eb248778eea 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -48,6 +48,8 @@ /* Two seconds as per CCID3 spec */ #define TFRC_INITIAL_TIMEOUT (2 * USEC_PER_SEC) +#define TFRC_INITIAL_IPI (USEC_PER_SEC / 4) + /* In usecs - half the scheduling granularity as per RFC3448 4.6 */ #define TFRC_OPSYS_HALF_TIME_GRAN (USEC_PER_SEC / (2 * HZ)) @@ -115,7 +117,7 @@ struct ccid3_hc_rx_sock { u64 ccid3hcrx_seqno_last_counter:48, ccid3hcrx_state:8, ccid3hcrx_last_counter:4; - unsigned long ccid3hcrx_rtt; + u32 ccid3hcrx_rtt; u32 ccid3hcrx_p; u32 ccid3hcrx_bytes_recv; struct timeval ccid3hcrx_tstamp_last_feedback; @@ -128,10 +130,14 @@ struct ccid3_hc_rx_sock { u32 ccid3hcrx_x_recv; }; -#define ccid3_hc_tx_field(s,field) (s->dccps_hc_tx_ccid_private == NULL ? 0 : \ - ((struct ccid3_hc_tx_sock *)s->dccps_hc_tx_ccid_private)->ccid3hctx_##field) +static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) +{ + return dccp_sk(sk)->dccps_hc_tx_ccid_private; +} -#define ccid3_hc_rx_field(s,field) (s->dccps_hc_rx_ccid_private == NULL ? 0 : \ - ((struct ccid3_hc_rx_sock *)s->dccps_hc_rx_ccid_private)->ccid3hcrx_##field) +static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk) +{ + return dccp_sk(sk)->dccps_hc_rx_ccid_private; +} #endif /* _DCCP_CCID3_H_ */ diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h index fb90a91aa93..b375ebdb7dc 100644 --- a/net/dccp/ccids/lib/packet_history.h +++ b/net/dccp/ccids/lib/packet_history.h @@ -134,6 +134,7 @@ static inline struct dccp_tx_hist_entry * static inline struct dccp_rx_hist_entry * dccp_rx_hist_entry_new(struct dccp_rx_hist *hist, + const struct sock *sk, const u32 ndp, const struct sk_buff *skb, const unsigned int __nocast prio) @@ -148,7 +149,7 @@ static inline struct dccp_rx_hist_entry * entry->dccphrx_ccval = dh->dccph_ccval; entry->dccphrx_type = dh->dccph_type; entry->dccphrx_ndp = ndp; - do_gettimeofday(&(entry->dccphrx_tstamp)); + dccp_timestamp(sk, &entry->dccphrx_tstamp); } return entry; diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index 33456c0d593..95c4630b3b1 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h @@ -426,10 +426,13 @@ extern struct dccp_ackpkts * dccp_ackpkts_alloc(unsigned int len, const unsigned int __nocast priority); extern void dccp_ackpkts_free(struct dccp_ackpkts *ap); -extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state); +extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk, + u64 ackno, u8 state); extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap, struct sock *sk, u64 ackno); +extern void dccp_timestamp(const struct sock *sk, struct timeval *tv); + static inline suseconds_t timeval_usecs(const struct timeval *tv) { return tv->tv_sec * USEC_PER_SEC + tv->tv_usec; @@ -468,17 +471,6 @@ static inline void timeval_sub_usecs(struct timeval *tv, } } -/* - * Returns the difference in usecs between timeval - * passed in and current time - */ -static inline suseconds_t timeval_now_delta(const struct timeval *tv) -{ - struct timeval now; - do_gettimeofday(&now); - return timeval_delta(&now, tv); -} - #ifdef CONFIG_IP_DCCP_DEBUG extern void dccp_ackvector_print(const u64 ackno, const unsigned char *vector, int len); diff --git a/net/dccp/input.c b/net/dccp/input.c index ef29cef1daf..c60bc3433f5 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -170,7 +170,7 @@ int dccp_rcv_established(struct sock *sk, struct sk_buff *skb, if (dp->dccps_options.dccpo_send_ack_vector) { struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; - if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, + if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_ACKPKTS_STATE_RECEIVED)) { LIMIT_NETDEBUG(KERN_WARNING "DCCP: acknowledgeable " @@ -498,7 +498,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, * DCCP_ACKPKTS_STATE_ECN_MARKED */ if (dp->dccps_options.dccpo_send_ack_vector) { - if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, + if (dccp_ackpkts_add(dp->dccps_hc_rx_ackpkts, sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_ACKPKTS_STATE_RECEIVED)) goto discard; diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 3fc75dbee4b..2afaa464e7f 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -641,16 +641,12 @@ int dccp_v4_send_reset(struct sock *sk, enum dccp_reset_codes code) skb = dccp_make_reset(sk, sk->sk_dst_cache, code); if (skb != NULL) { - const struct dccp_sock *dp = dccp_sk(sk); const struct inet_sock *inet = inet_sk(sk); err = ip_build_and_send_pkt(skb, sk, inet->saddr, inet->daddr, NULL); if (err == NET_XMIT_CN) err = 0; - - ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); - ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); } return err; @@ -1243,6 +1239,7 @@ static int dccp_v4_init_sock(struct sock *sk) static int dccp_ctl_socket_init = 1; dccp_options_init(&dp->dccps_options); + do_gettimeofday(&dp->dccps_epoch); if (dp->dccps_options.dccpo_send_ack_vector) { dp->dccps_hc_rx_ackpkts = diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index ce5dff4ac22..18461bc04cb 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c @@ -96,6 +96,7 @@ struct sock *dccp_create_openreq_child(struct sock *sk, newdp->dccps_hc_rx_ackpkts = NULL; newdp->dccps_role = DCCP_ROLE_SERVER; newicsk->icsk_rto = DCCP_TIMEOUT_INIT; + do_gettimeofday(&newdp->dccps_epoch); if (newdp->dccps_options.dccpo_send_ack_vector) { newdp->dccps_hc_rx_ackpkts = diff --git a/net/dccp/options.c b/net/dccp/options.c index 382c5894acb..d4c4242d8dd 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -72,6 +72,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) struct dccp_options_received *opt_recv = &dp->dccps_options_received; unsigned char opt, len; unsigned char *value; + u32 elapsed_time; memset(opt_recv, 0, sizeof(*opt_recv)); @@ -139,7 +140,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) opt_recv->dccpor_timestamp = ntohl(*(u32 *)value); dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; - do_gettimeofday(&dp->dccps_timestamp_time); + dccp_timestamp(sk, &dp->dccps_timestamp_time); dccp_pr_debug("%sTIMESTAMP=%u, ackno=%llu\n", debug_prefix, opt_recv->dccpor_timestamp, @@ -159,18 +160,18 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) (unsigned long long) DCCP_SKB_CB(skb)->dccpd_ack_seq); - if (len > 4) { - if (len == 6) - opt_recv->dccpor_elapsed_time = - ntohs(*(u16 *)(value + 4)); - else - opt_recv->dccpor_elapsed_time = - ntohl(*(u32 *)(value + 4)); - dccp_pr_debug("%sTIMESTAMP_ECHO ELAPSED_TIME=%d\n", - debug_prefix, - opt_recv->dccpor_elapsed_time); - } + if (len == 4) + break; + + if (len == 6) + elapsed_time = ntohs(*(u16 *)(value + 4)); + else + elapsed_time = ntohl(*(u32 *)(value + 4)); + + /* Give precedence to the biggest ELAPSED_TIME */ + if (elapsed_time > opt_recv->dccpor_elapsed_time) + opt_recv->dccpor_elapsed_time = elapsed_time; break; case DCCPO_ELAPSED_TIME: if (len != 2 && len != 4) @@ -180,14 +181,15 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) continue; if (len == 2) - opt_recv->dccpor_elapsed_time = - ntohs(*(u16 *)value); + elapsed_time = ntohs(*(u16 *)value); else - opt_recv->dccpor_elapsed_time = - ntohl(*(u32 *)value); + elapsed_time = ntohl(*(u32 *)value); + + if (elapsed_time > opt_recv->dccpor_elapsed_time) + opt_recv->dccpor_elapsed_time = elapsed_time; dccp_pr_debug("%sELAPSED_TIME=%d\n", debug_prefix, - opt_recv->dccpor_elapsed_time); + elapsed_time); break; /* * From draft-ietf-dccp-spec-11.txt: @@ -359,9 +361,13 @@ static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb) #endif struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; int len = ap->dccpap_buf_vector_len + 2; - const u32 elapsed_time = timeval_now_delta(&ap->dccpap_time) / 10; + struct timeval now; + u32 elapsed_time; unsigned char *to, *from; + dccp_timestamp(sk, &now); + elapsed_time = timeval_delta(&now, &ap->dccpap_time) / 10; + if (elapsed_time != 0) dccp_insert_option_elapsed_time(sk, skb, elapsed_time); @@ -426,13 +432,29 @@ static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb) (unsigned long long) ap->dccpap_ack_ackno); } +void dccp_timestamp(const struct sock *sk, struct timeval *tv) +{ + const struct dccp_sock *dp = dccp_sk(sk); + + do_gettimeofday(tv); + tv->tv_sec -= dp->dccps_epoch.tv_sec; + tv->tv_usec -= dp->dccps_epoch.tv_usec; + + while (tv->tv_usec < 0) { + tv->tv_sec--; + tv->tv_usec += USEC_PER_SEC; + } +} + +EXPORT_SYMBOL_GPL(dccp_timestamp); + void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb) { struct timeval tv; u32 now; - do_gettimeofday(&tv); - now = (tv.tv_sec * USEC_PER_SEC + tv.tv_usec) / 10; + dccp_timestamp(sk, &tv); + now = timeval_usecs(&tv) / 10; /* yes this will overflow but that is the point as we want a * 10 usec 32 bit timer which mean it wraps every 11.9 hours */ @@ -450,13 +472,17 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk, const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? "CLIENT TX opt: " : "server TX opt: "; #endif + struct timeval now; u32 tstamp_echo; - const u32 elapsed_time = - timeval_now_delta(&dp->dccps_timestamp_time) / 10; - const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time); - const int len = 6 + elapsed_time_len; + u32 elapsed_time; + int len, elapsed_time_len; unsigned char *to; + dccp_timestamp(sk, &now); + elapsed_time = timeval_delta(&now, &dp->dccps_timestamp_time) / 10; + elapsed_time_len = dccp_elapsed_time_len(elapsed_time); + len = 6 + elapsed_time_len; + if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert " "timestamp echo!\n"); @@ -505,13 +531,18 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb) (dp->dccps_hc_rx_ackpkts->dccpap_buf_ackno != DCCP_MAX_SEQNO + 1)) dccp_insert_option_ack_vector(sk, skb); - if (dp->dccps_timestamp_echo != 0) dccp_insert_option_timestamp_echo(sk, skb); } - ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb); - ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb); + if (dp->dccps_hc_rx_insert_options) { + ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb); + dp->dccps_hc_rx_insert_options = 0; + } + if (dp->dccps_hc_tx_insert_options) { + ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb); + dp->dccps_hc_tx_insert_options = 0; + } /* XXX: insert other options when appropriate */ @@ -616,7 +647,8 @@ static inline int dccp_ackpkts_set_buf_head_state(struct dccp_ackpkts *ap, /* * Implements the draft-ietf-dccp-spec-11.txt Appendix A */ -int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state) +int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk, + u64 ackno, u8 state) { /* * Check at the right places if the buffer is full, if it is, tell the @@ -697,7 +729,7 @@ int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state) } ap->dccpap_buf_ackno = ackno; - do_gettimeofday(&ap->dccpap_time); + dccp_timestamp(sk, &ap->dccpap_time); out: dccp_pr_debug(""); dccp_ackpkts_print(ap); diff --git a/net/dccp/output.c b/net/dccp/output.c index 28de157a432..ea6d0e91e51 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -522,7 +522,4 @@ void dccp_send_close(struct sock *sk, const int active) dccp_transmit_skb(sk, skb_clone(skb, prio)); } else dccp_transmit_skb(sk, skb); - - ccid_hc_rx_exit(dp->dccps_hc_rx_ccid, sk); - ccid_hc_tx_exit(dp->dccps_hc_tx_ccid, sk); } |