diff options
Diffstat (limited to 'net/dccp/ccids/ccid3.c')
| -rw-r--r-- | net/dccp/ccids/ccid3.c | 153 |
1 files changed, 121 insertions, 32 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index c39bff706cfc..090bc39e8199 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * net/dccp/ccids/ccid3.c | 2 | * net/dccp/ccids/ccid3.c |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. | 4 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. |
| 5 | * Copyright (c) 2005-6 Ian McDonald <imcdnzl@gmail.com> | 5 | * Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz> |
| 6 | * | 6 | * |
| 7 | * An implementation of the DCCP protocol | 7 | * An implementation of the DCCP protocol |
| 8 | * | 8 | * |
| @@ -342,6 +342,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, | |||
| 342 | new_packet->dccphtx_ccval = | 342 | new_packet->dccphtx_ccval = |
| 343 | DCCP_SKB_CB(skb)->dccpd_ccval = | 343 | DCCP_SKB_CB(skb)->dccpd_ccval = |
| 344 | hctx->ccid3hctx_last_win_count; | 344 | hctx->ccid3hctx_last_win_count; |
| 345 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, | ||
| 346 | hctx->ccid3hctx_t_ipi); | ||
| 345 | } | 347 | } |
| 346 | out: | 348 | out: |
| 347 | return rc; | 349 | return rc; |
| @@ -413,7 +415,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) | |||
| 413 | case TFRC_SSTATE_NO_FBACK: | 415 | case TFRC_SSTATE_NO_FBACK: |
| 414 | case TFRC_SSTATE_FBACK: | 416 | case TFRC_SSTATE_FBACK: |
| 415 | if (len > 0) { | 417 | if (len > 0) { |
| 416 | hctx->ccid3hctx_t_nom = now; | 418 | timeval_sub_usecs(&hctx->ccid3hctx_t_nom, |
| 419 | hctx->ccid3hctx_t_ipi); | ||
| 417 | ccid3_calc_new_t_ipi(hctx); | 420 | ccid3_calc_new_t_ipi(hctx); |
| 418 | ccid3_calc_new_delta(hctx); | 421 | ccid3_calc_new_delta(hctx); |
| 419 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, | 422 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, |
| @@ -757,8 +760,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) | |||
| 757 | } | 760 | } |
| 758 | 761 | ||
| 759 | hcrx->ccid3hcrx_tstamp_last_feedback = now; | 762 | hcrx->ccid3hcrx_tstamp_last_feedback = now; |
| 760 | hcrx->ccid3hcrx_last_counter = packet->dccphrx_ccval; | 763 | hcrx->ccid3hcrx_ccval_last_counter = packet->dccphrx_ccval; |
| 761 | hcrx->ccid3hcrx_seqno_last_counter = packet->dccphrx_seqno; | ||
| 762 | hcrx->ccid3hcrx_bytes_recv = 0; | 764 | hcrx->ccid3hcrx_bytes_recv = 0; |
| 763 | 765 | ||
| 764 | /* Convert to multiples of 10us */ | 766 | /* Convert to multiples of 10us */ |
| @@ -782,7 +784,7 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) | |||
| 782 | if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)) | 784 | if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)) |
| 783 | return 0; | 785 | return 0; |
| 784 | 786 | ||
| 785 | DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter; | 787 | DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_ccval_last_counter; |
| 786 | 788 | ||
| 787 | if (dccp_packet_without_ack(skb)) | 789 | if (dccp_packet_without_ack(skb)) |
| 788 | return 0; | 790 | return 0; |
| @@ -854,6 +856,11 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk) | |||
| 854 | interval = 1; | 856 | interval = 1; |
| 855 | } | 857 | } |
| 856 | found: | 858 | found: |
| 859 | if (!tail) { | ||
| 860 | LIMIT_NETDEBUG(KERN_WARNING "%s: tail is null\n", | ||
| 861 | __FUNCTION__); | ||
| 862 | return ~0; | ||
| 863 | } | ||
| 857 | rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval; | 864 | rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval; |
| 858 | ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n", | 865 | ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n", |
| 859 | dccp_role(sk), sk, rtt); | 866 | dccp_role(sk), sk, rtt); |
| @@ -864,9 +871,20 @@ found: | |||
| 864 | delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); | 871 | delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); |
| 865 | x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta); | 872 | x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta); |
| 866 | 873 | ||
| 874 | if (x_recv == 0) | ||
| 875 | x_recv = hcrx->ccid3hcrx_x_recv; | ||
| 876 | |||
| 867 | tmp1 = (u64)x_recv * (u64)rtt; | 877 | tmp1 = (u64)x_recv * (u64)rtt; |
| 868 | do_div(tmp1,10000000); | 878 | do_div(tmp1,10000000); |
| 869 | tmp2 = (u32)tmp1; | 879 | tmp2 = (u32)tmp1; |
| 880 | |||
| 881 | if (!tmp2) { | ||
| 882 | LIMIT_NETDEBUG(KERN_WARNING "tmp2 = 0 " | ||
| 883 | "%s: x_recv = %u, rtt =%u\n", | ||
| 884 | __FUNCTION__, x_recv, rtt); | ||
| 885 | return ~0; | ||
| 886 | } | ||
| 887 | |||
| 870 | fval = (hcrx->ccid3hcrx_s * 100000) / tmp2; | 888 | fval = (hcrx->ccid3hcrx_s * 100000) / tmp2; |
| 871 | /* do not alter order above or you will get overflow on 32 bit */ | 889 | /* do not alter order above or you will get overflow on 32 bit */ |
| 872 | p = tfrc_calc_x_reverse_lookup(fval); | 890 | p = tfrc_calc_x_reverse_lookup(fval); |
| @@ -882,31 +900,101 @@ found: | |||
| 882 | static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) | 900 | static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) |
| 883 | { | 901 | { |
| 884 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); | 902 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); |
| 903 | struct dccp_li_hist_entry *next, *head; | ||
| 904 | u64 seq_temp; | ||
| 885 | 905 | ||
| 886 | if (seq_loss != DCCP_MAX_SEQNO + 1 && | 906 | if (list_empty(&hcrx->ccid3hcrx_li_hist)) { |
| 887 | list_empty(&hcrx->ccid3hcrx_li_hist)) { | 907 | if (!dccp_li_hist_interval_new(ccid3_li_hist, |
| 888 | struct dccp_li_hist_entry *li_tail; | 908 | &hcrx->ccid3hcrx_li_hist, seq_loss, win_loss)) |
| 909 | return; | ||
| 889 | 910 | ||
| 890 | li_tail = dccp_li_hist_interval_new(ccid3_li_hist, | 911 | next = (struct dccp_li_hist_entry *) |
| 891 | &hcrx->ccid3hcrx_li_hist, | 912 | hcrx->ccid3hcrx_li_hist.next; |
| 892 | seq_loss, win_loss); | 913 | next->dccplih_interval = ccid3_hc_rx_calc_first_li(sk); |
| 893 | if (li_tail == NULL) | 914 | } else { |
| 915 | struct dccp_li_hist_entry *entry; | ||
| 916 | struct list_head *tail; | ||
| 917 | |||
| 918 | head = (struct dccp_li_hist_entry *) | ||
| 919 | hcrx->ccid3hcrx_li_hist.next; | ||
| 920 | /* FIXME win count check removed as was wrong */ | ||
| 921 | /* should make this check with receive history */ | ||
| 922 | /* and compare there as per section 10.2 of RFC4342 */ | ||
| 923 | |||
| 924 | /* new loss event detected */ | ||
| 925 | /* calculate last interval length */ | ||
| 926 | seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss); | ||
| 927 | entry = dccp_li_hist_entry_new(ccid3_li_hist, SLAB_ATOMIC); | ||
| 928 | |||
| 929 | if (entry == NULL) { | ||
| 930 | printk(KERN_CRIT "%s: out of memory\n",__FUNCTION__); | ||
| 931 | dump_stack(); | ||
| 894 | return; | 932 | return; |
| 895 | li_tail->dccplih_interval = ccid3_hc_rx_calc_first_li(sk); | 933 | } |
| 896 | } else | 934 | |
| 897 | LIMIT_NETDEBUG(KERN_WARNING "%s: FIXME: find end of " | 935 | list_add(&entry->dccplih_node, &hcrx->ccid3hcrx_li_hist); |
| 898 | "interval\n", __FUNCTION__); | 936 | |
| 937 | tail = hcrx->ccid3hcrx_li_hist.prev; | ||
| 938 | list_del(tail); | ||
| 939 | kmem_cache_free(ccid3_li_hist->dccplih_slab, tail); | ||
| 940 | |||
| 941 | /* Create the newest interval */ | ||
| 942 | entry->dccplih_seqno = seq_loss; | ||
| 943 | entry->dccplih_interval = seq_temp; | ||
| 944 | entry->dccplih_win_count = win_loss; | ||
| 945 | } | ||
| 899 | } | 946 | } |
| 900 | 947 | ||
| 901 | static void ccid3_hc_rx_detect_loss(struct sock *sk) | 948 | static int ccid3_hc_rx_detect_loss(struct sock *sk, |
| 949 | struct dccp_rx_hist_entry *packet) | ||
| 902 | { | 950 | { |
| 903 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); | 951 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); |
| 904 | u8 win_loss; | 952 | struct dccp_rx_hist_entry *rx_hist = dccp_rx_hist_head(&hcrx->ccid3hcrx_hist); |
| 905 | const u64 seq_loss = dccp_rx_hist_detect_loss(&hcrx->ccid3hcrx_hist, | 953 | u64 seqno = packet->dccphrx_seqno; |
| 906 | &hcrx->ccid3hcrx_li_hist, | 954 | u64 tmp_seqno; |
| 907 | &win_loss); | 955 | int loss = 0; |
| 956 | u8 ccval; | ||
| 957 | |||
| 958 | |||
| 959 | tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss; | ||
| 960 | |||
| 961 | if (!rx_hist || | ||
| 962 | follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) { | ||
| 963 | hcrx->ccid3hcrx_seqno_nonloss = seqno; | ||
| 964 | hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval; | ||
| 965 | goto detect_out; | ||
| 966 | } | ||
| 967 | |||
| 908 | 968 | ||
| 909 | ccid3_hc_rx_update_li(sk, seq_loss, win_loss); | 969 | while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno) |
| 970 | > TFRC_RECV_NUM_LATE_LOSS) { | ||
| 971 | loss = 1; | ||
| 972 | ccid3_hc_rx_update_li(sk, hcrx->ccid3hcrx_seqno_nonloss, | ||
| 973 | hcrx->ccid3hcrx_ccval_nonloss); | ||
| 974 | tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss; | ||
| 975 | dccp_inc_seqno(&tmp_seqno); | ||
| 976 | hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno; | ||
| 977 | dccp_inc_seqno(&tmp_seqno); | ||
| 978 | while (dccp_rx_hist_find_entry(&hcrx->ccid3hcrx_hist, | ||
| 979 | tmp_seqno, &ccval)) { | ||
| 980 | hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno; | ||
| 981 | hcrx->ccid3hcrx_ccval_nonloss = ccval; | ||
| 982 | dccp_inc_seqno(&tmp_seqno); | ||
| 983 | } | ||
| 984 | } | ||
| 985 | |||
| 986 | /* FIXME - this code could be simplified with above while */ | ||
| 987 | /* but works at moment */ | ||
| 988 | if (follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) { | ||
| 989 | hcrx->ccid3hcrx_seqno_nonloss = seqno; | ||
| 990 | hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval; | ||
| 991 | } | ||
| 992 | |||
| 993 | detect_out: | ||
| 994 | dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist, | ||
| 995 | &hcrx->ccid3hcrx_li_hist, packet, | ||
| 996 | hcrx->ccid3hcrx_seqno_nonloss); | ||
| 997 | return loss; | ||
| 910 | } | 998 | } |
| 911 | 999 | ||
| 912 | static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | 1000 | static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) |
| @@ -916,8 +1004,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 916 | struct dccp_rx_hist_entry *packet; | 1004 | struct dccp_rx_hist_entry *packet; |
| 917 | struct timeval now; | 1005 | struct timeval now; |
| 918 | u8 win_count; | 1006 | u8 win_count; |
| 919 | u32 p_prev, r_sample, t_elapsed; | 1007 | u32 p_prev, rtt_prev, r_sample, t_elapsed; |
| 920 | int ins; | 1008 | int loss; |
| 921 | 1009 | ||
| 922 | BUG_ON(hcrx == NULL || | 1010 | BUG_ON(hcrx == NULL || |
| 923 | !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA || | 1011 | !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA || |
| @@ -932,7 +1020,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 932 | case DCCP_PKT_DATAACK: | 1020 | case DCCP_PKT_DATAACK: |
| 933 | if (opt_recv->dccpor_timestamp_echo == 0) | 1021 | if (opt_recv->dccpor_timestamp_echo == 0) |
| 934 | break; | 1022 | break; |
| 935 | p_prev = hcrx->ccid3hcrx_rtt; | 1023 | rtt_prev = hcrx->ccid3hcrx_rtt; |
| 936 | dccp_timestamp(sk, &now); | 1024 | dccp_timestamp(sk, &now); |
| 937 | timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10); | 1025 | timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10); |
| 938 | r_sample = timeval_usecs(&now); | 1026 | r_sample = timeval_usecs(&now); |
| @@ -951,8 +1039,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 951 | hcrx->ccid3hcrx_rtt = (hcrx->ccid3hcrx_rtt * 9) / 10 + | 1039 | hcrx->ccid3hcrx_rtt = (hcrx->ccid3hcrx_rtt * 9) / 10 + |
| 952 | r_sample / 10; | 1040 | r_sample / 10; |
| 953 | 1041 | ||
| 954 | if (p_prev != hcrx->ccid3hcrx_rtt) | 1042 | if (rtt_prev != hcrx->ccid3hcrx_rtt) |
| 955 | ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n", | 1043 | ccid3_pr_debug("%s, New RTT=%uus, elapsed time=%u\n", |
| 956 | dccp_role(sk), hcrx->ccid3hcrx_rtt, | 1044 | dccp_role(sk), hcrx->ccid3hcrx_rtt, |
| 957 | opt_recv->dccpor_elapsed_time); | 1045 | opt_recv->dccpor_elapsed_time); |
| 958 | break; | 1046 | break; |
| @@ -973,8 +1061,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 973 | 1061 | ||
| 974 | win_count = packet->dccphrx_ccval; | 1062 | win_count = packet->dccphrx_ccval; |
| 975 | 1063 | ||
| 976 | ins = dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist, | 1064 | loss = ccid3_hc_rx_detect_loss(sk, packet); |
| 977 | &hcrx->ccid3hcrx_li_hist, packet); | ||
| 978 | 1065 | ||
| 979 | if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK) | 1066 | if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK) |
| 980 | return; | 1067 | return; |
| @@ -991,7 +1078,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 991 | case TFRC_RSTATE_DATA: | 1078 | case TFRC_RSTATE_DATA: |
| 992 | hcrx->ccid3hcrx_bytes_recv += skb->len - | 1079 | hcrx->ccid3hcrx_bytes_recv += skb->len - |
| 993 | dccp_hdr(skb)->dccph_doff * 4; | 1080 | dccp_hdr(skb)->dccph_doff * 4; |
| 994 | if (ins != 0) | 1081 | if (loss) |
| 995 | break; | 1082 | break; |
| 996 | 1083 | ||
| 997 | dccp_timestamp(sk, &now); | 1084 | dccp_timestamp(sk, &now); |
| @@ -1012,7 +1099,6 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 1012 | ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n", | 1099 | ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n", |
| 1013 | dccp_role(sk), sk, dccp_state_name(sk->sk_state)); | 1100 | dccp_role(sk), sk, dccp_state_name(sk->sk_state)); |
| 1014 | 1101 | ||
| 1015 | ccid3_hc_rx_detect_loss(sk); | ||
| 1016 | p_prev = hcrx->ccid3hcrx_p; | 1102 | p_prev = hcrx->ccid3hcrx_p; |
| 1017 | 1103 | ||
| 1018 | /* Calculate loss event rate */ | 1104 | /* Calculate loss event rate */ |
| @@ -1022,6 +1108,9 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
| 1022 | /* Scaling up by 1000000 as fixed decimal */ | 1108 | /* Scaling up by 1000000 as fixed decimal */ |
| 1023 | if (i_mean != 0) | 1109 | if (i_mean != 0) |
| 1024 | hcrx->ccid3hcrx_p = 1000000 / i_mean; | 1110 | hcrx->ccid3hcrx_p = 1000000 / i_mean; |
| 1111 | } else { | ||
| 1112 | printk(KERN_CRIT "%s: empty loss hist\n",__FUNCTION__); | ||
| 1113 | dump_stack(); | ||
| 1025 | } | 1114 | } |
| 1026 | 1115 | ||
| 1027 | if (hcrx->ccid3hcrx_p > p_prev) { | 1116 | if (hcrx->ccid3hcrx_p > p_prev) { |
| @@ -1230,7 +1319,7 @@ static __exit void ccid3_module_exit(void) | |||
| 1230 | } | 1319 | } |
| 1231 | module_exit(ccid3_module_exit); | 1320 | module_exit(ccid3_module_exit); |
| 1232 | 1321 | ||
| 1233 | MODULE_AUTHOR("Ian McDonald <iam4@cs.waikato.ac.nz>, " | 1322 | MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, " |
| 1234 | "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); | 1323 | "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); |
| 1235 | MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID"); | 1324 | MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID"); |
| 1236 | MODULE_LICENSE("GPL"); | 1325 | MODULE_LICENSE("GPL"); |
