📄 ccid3.c
字号:
case TFRC_SSTATE_FBACK: if (len > 0) { hctx->ccid3hctx_t_nom = now; ccid3_calc_new_t_ipi(hctx); ccid3_calc_new_delta(hctx); timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); } break; default: printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); dump_stack(); break; }}static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb){ 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; 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 || DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK)) return; opt_recv = &hctx->ccid3hctx_options_received; t_elapsed = dp->dccps_options_received.dccpor_elapsed_time * 10; x_recv = opt_recv->ccid3or_receive_rate; pinv = opt_recv->ccid3or_loss_event_rate; switch (hctx->ccid3hctx_state) { case TFRC_SSTATE_NO_SENT: /* FIXME: what to do here? */ return; case TFRC_SSTATE_NO_FBACK: case TFRC_SSTATE_FBACK: /* Calculate new round trip sample by * R_sample = (now - t_recvdata) - t_delay */ /* get t_recvdata from history */ packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist, DCCP_SKB_CB(skb)->dccpd_ack_seq); 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 */ 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) * R = R_sample; * Else * R = q * R + (1 - q) * R_sample; * * q is a constant, RFC 3448 recomments 0.9 */ if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) { ccid3_hc_tx_set_state(sk, TFRC_SSTATE_FBACK); hctx->ccid3hctx_rtt = r_sample; } else hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 + r_sample / 10; ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, " "r_sample=%us\n", dccp_role(sk), sk, hctx->ccid3hctx_rtt, r_sample); /* Update timeout interval */ hctx->ccid3hctx_t_rto = max_t(u32, 4 * hctx->ccid3hctx_rtt, USEC_PER_SEC); /* Update receive rate */ hctx->ccid3hctx_x_recv = x_recv;/* X_recv in bytes per sec */ /* Update loss event rate */ if (pinv == ~0 || pinv == 0) hctx->ccid3hctx_p = 0; else { hctx->ccid3hctx_p = 1000000 / pinv; if (hctx->ccid3hctx_p < TFRC_SMALLEST_P) { hctx->ccid3hctx_p = TFRC_SMALLEST_P; ccid3_pr_debug("%s, sk=%p, Smallest p used!\n", dccp_role(sk), sk); } } /* unschedule no feedback timer */ sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); /* Update sending rate */ ccid3_hc_tx_update_x(sk); /* Update next send time */ timeval_sub_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); ccid3_calc_new_t_ipi(hctx); timeval_add_usecs(&hctx->ccid3hctx_t_nom, hctx->ccid3hctx_t_ipi); ccid3_calc_new_delta(hctx); /* remove all packets older than the one acked from history */ dccp_tx_hist_purge_older(ccid3_tx_hist, &hctx->ccid3hctx_hist, packet); /* * As we have calculated new ipi, delta, t_nom it is possible that * we now can send a packet, so wake up dccp_wait_for_ccids. */ sk->sk_write_space(sk); /* * Schedule no feedback timer to expire in * max(4 * R, 2 * s / X) */ next_tmout = max(hctx->ccid3hctx_t_rto, 2 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_x)); ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to " "expire in %lu jiffies (%luus)\n", dccp_role(sk), sk, usecs_to_jiffies(next_tmout), next_tmout); sk_reset_timer(sk, &hctx->ccid3hctx_no_feedback_timer, jiffies + max_t(u32, 1, usecs_to_jiffies(next_tmout))); /* set idle flag */ hctx->ccid3hctx_idle = 1; break; default: printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", __FUNCTION__, dccp_role(sk), sk, hctx->ccid3hctx_state); dump_stack(); break; }}static void ccid3_hc_tx_insert_options(struct sock *sk, struct sk_buff *skb){ const struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); BUG_ON(hctx == NULL); if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)) return; DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count;}static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, unsigned char len, u16 idx, unsigned char *value){ int rc = 0; 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; BUG_ON(hctx == NULL); opt_recv = &hctx->ccid3hctx_options_received; if (opt_recv->ccid3or_seqno != dp->dccps_gsr) { opt_recv->ccid3or_seqno = dp->dccps_gsr; opt_recv->ccid3or_loss_event_rate = ~0; opt_recv->ccid3or_loss_intervals_idx = 0; opt_recv->ccid3or_loss_intervals_len = 0; opt_recv->ccid3or_receive_rate = 0; } switch (option) { case TFRC_OPT_LOSS_EVENT_RATE: 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); ccid3_pr_debug("%s, sk=%p, LOSS_EVENT_RATE=%u\n", dccp_role(sk), sk, opt_recv->ccid3or_loss_event_rate); } break; case TFRC_OPT_LOSS_INTERVALS: opt_recv->ccid3or_loss_intervals_idx = idx; opt_recv->ccid3or_loss_intervals_len = len; ccid3_pr_debug("%s, sk=%p, LOSS_INTERVALS=(%u, %u)\n", dccp_role(sk), sk, opt_recv->ccid3or_loss_intervals_idx, opt_recv->ccid3or_loss_intervals_len); break; case TFRC_OPT_RECEIVE_RATE: 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); ccid3_pr_debug("%s, sk=%p, RECEIVE_RATE=%u\n", dccp_role(sk), sk, opt_recv->ccid3or_receive_rate); } break; } return rc;}static int ccid3_hc_tx_init(struct sock *sk){ struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hctx; 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 && dp->dccps_packet_size <= TFRC_MAX_PACKET_SIZE) hctx->ccid3hctx_s = dp->dccps_packet_size; else hctx->ccid3hctx_s = TFRC_STD_PACKET_SIZE; /* Set transmission rate to 1 packet per second */ hctx->ccid3hctx_x = hctx->ccid3hctx_s; hctx->ccid3hctx_t_rto = USEC_PER_SEC; hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; INIT_LIST_HEAD(&hctx->ccid3hctx_hist); init_timer(&hctx->ccid3hctx_no_feedback_timer); return 0;}static void ccid3_hc_tx_exit(struct sock *sk){ struct dccp_sock *dp = dccp_sk(sk); struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); BUG_ON(hctx == NULL); ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM); sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); /* Empty packet history */ dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist); kfree(dp->dccps_hc_tx_ccid_private); dp->dccps_hc_tx_ccid_private = NULL;}/* * RX Half Connection methods *//* TFRC receiver states */enum ccid3_hc_rx_states { TFRC_RSTATE_NO_DATA = 1, TFRC_RSTATE_DATA, TFRC_RSTATE_TERM = 127,};#ifdef CCID3_DEBUGstatic const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state){ static char *ccid3_rx_state_names[] = { [TFRC_RSTATE_NO_DATA] = "NO_DATA", [TFRC_RSTATE_DATA] = "DATA", [TFRC_RSTATE_TERM] = "TERM", }; return ccid3_rx_state_names[state];}#endifstatic inline void ccid3_hc_rx_set_state(struct sock *sk, enum ccid3_hc_rx_states state){ 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", dccp_role(sk), sk, ccid3_rx_state_name(oldstate), ccid3_rx_state_name(state)); WARN_ON(state == oldstate); hcrx->ccid3hcrx_state = state;}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 dccp_rx_hist_entry *packet; struct timeval now; ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); dccp_timestamp(sk, &now); switch (hcrx->ccid3hcrx_state) { case TFRC_RSTATE_NO_DATA: hcrx->ccid3hcrx_x_recv = 0; break; case TFRC_RSTATE_DATA: { const u32 delta = timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_feedback); hcrx->ccid3hcrx_x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta); } break; default: printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state); dump_stack(); return; } packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist); if (unlikely(packet == NULL)) { LIMIT_NETDEBUG(KERN_WARNING "%s: %s, sk=%p, no data packet " "in history!\n", __FUNCTION__, dccp_role(sk), sk); return; } hcrx->ccid3hcrx_tstamp_last_feedback = now; hcrx->ccid3hcrx_last_counter = packet->dccphrx_ccval; hcrx->ccid3hcrx_seqno_last_counter = packet->dccphrx_seqno; hcrx->ccid3hcrx_bytes_recv = 0; /* Convert to multiples of 10us */ hcrx->ccid3hcrx_elapsed_time = timeval_delta(&now, &packet->dccphrx_tstamp) / 10; if (hcrx->ccid3hcrx_p == 0) 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 ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); u32 x_recv, pinv; 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; if (dccp_packet_without_ack(skb)) return; if (hcrx->ccid3hcrx_elapsed_time != 0) dccp_insert_option_elapsed_time(sk, skb, hcrx->ccid3hcrx_elapsed_time); dccp_insert_option_timestamp(sk, skb); x_recv = htonl(hcrx->ccid3hcrx_x_recv); pinv = htonl(hcrx->ccid3hcrx_pinv); dccp_insert_option(sk, skb, TFRC_OPT_LOSS_EVENT_RATE, &pinv, sizeof(pinv)); dccp_insert_option(sk, skb, TFRC_OPT_RECEIVE_RATE, &x_recv, sizeof(x_recv));}/* calculate first loss interval * * returns estimated loss interval in usecs */static u32 ccid3_hc_rx_calc_first_li(struct sock *sk){ 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, }; int interval = 0; int win_count = 0; int step = 0; u64 tmp1; list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, dccphrx_node) { if (dccp_rx_hist_entry_data_packet(entry)) { tail = entry; switch (step) { case 0: tstamp = entry->dccphrx_tstamp; win_count = entry->dccphrx_ccval; step = 1; break; case 1: interval = win_count - entry->dccphrx_ccval;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -