This 1) concentrates previously scattered computation of p_inv into one function; 2) removes the `p' element of the CCID3 RX sock (it is redundant); 3) makes the tfrc_rx_info structure standalone, only used on demand. The reason for (2) is that the code essentially only uses p_inv = 1/p. It does not need p, since all the relevant information is already in p_inv. The motivation for (3) is that the embedded info structure will not be used often, so that the extra cost of keeping p in synch with p_inv (which has to be done at each packet reception) is overhead most of the time. Advantages that this buys: * the RX sock loses further weight; * computation of p_inv is no longer scattered in different places; * not having to keep p in sync with p_inv speeds up computation (important, as p_inv has to be recomputed for each new data packet); * several test cases can now be removed since all is in one function; * the send_feedback and packet_recv code becomes simpler. Committer note: Reorganized the struct a bit using pahole so that we can save 8 bytes on 64bit architectures, before it was 104 bytes, with my change it got down to 96. Signed-off-by: Gerrit Renker <gerrit@xxxxxxxxxxxxxx> Acked-by: Ian McDonald <ian.mcdonald@xxxxxxxxxxx> Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxxxxxxxxxx> --- net/dccp/ccids/ccid3.c | 57 +++++++++++++++++++++++++---------------------- net/dccp/ccids/ccid3.h | 21 +++++++---------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index e7d2b62..26e8870 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -726,6 +726,25 @@ static inline void ccid3_hc_rx_update_s(struct ccid3_hc_rx_sock *hcrx, int len) hcrx->ccid3hcrx_s = tfrc_ewma(hcrx->ccid3hcrx_s, len, 9); } +/* returns: 1 when p > p_prev (i.e. when feedback is required); 0 else */ +static int ccid3_hc_rx_update_p(struct ccid3_hc_rx_sock *hcrx) +{ + struct list_head *li_hist = &hcrx->ccid3hcrx_li_hist; + u32 pinv_prev = hcrx->ccid3hcrx_pinv; + + if (list_empty(li_hist)) /* only empty if no loss so far, i.e. p == 0 */ + return 0; + + hcrx->ccid3hcrx_pinv = dccp_li_hist_calc_i_mean(li_hist); + if (hcrx->ccid3hcrx_pinv == 0) { + DCCP_BUG("non-empty LI history and yet I_mean == 0!"); + return 0; + } + + /* exploit that p > p_prev <=> 1/p < 1/p_prev */ + return (hcrx->ccid3hcrx_pinv < pinv_prev); +} + static void ccid3_hc_rx_send_feedback(struct sock *sk) { struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); @@ -741,6 +760,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) switch (hcrx->ccid3hcrx_state) { case TFRC_RSTATE_NO_DATA: hcrx->ccid3hcrx_x_recv = 0; + hcrx->ccid3hcrx_pinv = ~0U; /* see RFC 4342, 8.5 */ break; case TFRC_RSTATE_DATA: delta = timeval_delta(&now, @@ -770,14 +790,6 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) DCCP_BUG_ON(delta < 0); hcrx->ccid3hcrx_elapsed_time = delta / 10; - if (hcrx->ccid3hcrx_p == 0) - hcrx->ccid3hcrx_pinv = ~0U; /* see RFC 4342, 8.5 */ - else if (hcrx->ccid3hcrx_p > 1000000) { - DCCP_WARN("p (%u) > 100%%\n", hcrx->ccid3hcrx_p); - hcrx->ccid3hcrx_pinv = 1; /* use 100% in this case */ - } else - hcrx->ccid3hcrx_pinv = 1000000 / hcrx->ccid3hcrx_p; - dp->dccps_hc_rx_insert_options = 1; dccp_send_ack(sk); } @@ -1016,7 +1028,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) const struct dccp_options_received *opt_recv; struct dccp_rx_hist_entry *packet; struct timeval now; - u32 p_prev, r_sample, rtt_prev; + u32 r_sample, rtt_prev; int loss, payload_size; BUG_ON(hcrx == NULL); @@ -1096,22 +1108,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) ccid3_pr_debug("%s(%p, state=%s), data loss! Reacting...\n", dccp_role(sk), sk, dccp_state_name(sk->sk_state)); - p_prev = hcrx->ccid3hcrx_p; - - /* Calculate loss event rate */ - if (!list_empty(&hcrx->ccid3hcrx_li_hist)) { - u32 i_mean = dccp_li_hist_calc_i_mean(&hcrx->ccid3hcrx_li_hist); - - /* Scaling up by 1000000 as fixed decimal */ - if (i_mean != 0) - hcrx->ccid3hcrx_p = 1000000 / i_mean; - } else - DCCP_BUG("empty loss history"); - - if (hcrx->ccid3hcrx_p > p_prev) { + if (ccid3_hc_rx_update_p(hcrx)) ccid3_hc_rx_send_feedback(sk); - return; - } } static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk) @@ -1165,6 +1163,11 @@ static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len, { const struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); const void *val; + struct tfrc_rx_info rx_info = { + .tfrcrx_x_recv = hcrx->ccid3hcrx_x_recv, + .tfrcrx_rtt = hcrx->ccid3hcrx_rtt, + .tfrcrx_p = scaled_div(1, hcrx->ccid3hcrx_pinv) + }; /* Listen socks doesn't have a private CCID block */ if (sk->sk_state == DCCP_LISTEN) @@ -1172,10 +1175,10 @@ static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len, switch (optname) { case DCCP_SOCKOPT_CCID_RX_INFO: - if (len < sizeof(hcrx->ccid3hcrx_tfrc)) + if (len < sizeof(rx_info)) return -EINVAL; - len = sizeof(hcrx->ccid3hcrx_tfrc); - val = &hcrx->ccid3hcrx_tfrc; + len = sizeof(rx_info); + val = &rx_info; break; default: return -ENOPROTOOPT; diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index fbef100..8099e23 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h @@ -127,39 +127,36 @@ enum ccid3_hc_rx_states { /** struct ccid3_hc_rx_sock - CCID3 receiver half-connection socket * - * @ccid3hcrx_x_recv - Receiver estimate of send rate (RFC 3448 4.3) - * @ccid3hcrx_rtt - Receiver estimate of rtt (non-standard) - * @ccid3hcrx_p - current loss event rate (RFC 3448 5.4) * @ccid3hcrx_seqno_nonloss - Last received non-loss sequence number * @ccid3hcrx_ccval_nonloss - Last received non-loss Window CCVal * @ccid3hcrx_ccval_last_counter - Tracks window counter (RFC 4342, 8.1) * @ccid3hcrx_state - receiver state, one of %ccid3_hc_rx_states + * @ccid3hcrx_s - Received packet size in bytes * @ccid3hcrx_bytes_recv - Total sum of DCCP payload bytes + * @ccid3hcrx_x_recv - Receiver estimate of send rate (RFC 3448, sec. 4.3) + * @ccid3hcrx_rtt - Receiver estimate of rtt (non-standard) + * @ccid3hcrx_pinv - Reciprocal of Loss Event Rate p (RFC 4342, sec. 8.5) * @ccid3hcrx_tstamp_last_feedback - Time at which last feedback was sent * @ccid3hcrx_tstamp_last_ack - Time at which last feedback was sent * @ccid3hcrx_hist - Packet history * @ccid3hcrx_li_hist - Loss Interval History - * @ccid3hcrx_s - Received packet size in bytes - * @ccid3hcrx_pinv - Inverse of Loss Event Rate (RFC 4342, sec. 8.5) * @ccid3hcrx_elapsed_time - Time since packet reception */ struct ccid3_hc_rx_sock { - struct tfrc_rx_info ccid3hcrx_tfrc; -#define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv -#define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt -#define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p u64 ccid3hcrx_seqno_nonloss:48, ccid3hcrx_ccval_nonloss:4, ccid3hcrx_ccval_last_counter:4; enum ccid3_hc_rx_states ccid3hcrx_state:8; u32 ccid3hcrx_bytes_recv; + u32 ccid3hcrx_x_recv; + u32 ccid3hcrx_rtt; + u32 ccid3hcrx_pinv; + u32 ccid3hcrx_elapsed_time; + u16 ccid3hcrx_s; struct timeval ccid3hcrx_tstamp_last_feedback; struct timeval ccid3hcrx_tstamp_last_ack; struct list_head ccid3hcrx_hist; struct list_head ccid3hcrx_li_hist; - u16 ccid3hcrx_s; - u32 ccid3hcrx_pinv; - u32 ccid3hcrx_elapsed_time; }; static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) -- 1.5.0.6 - To unsubscribe from this list: send the line "unsubscribe dccp" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html