aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2006-08-29 16:17:25 -0400
committerJohn W. Linville <linville@tuxdriver.com>2006-08-29 16:17:25 -0400
commite4ac2663ea27d5dda88d97d117080995fcfcd6d5 (patch)
tree74eac23956a86546ed93eac973b0bc4744b97ccc /net
parent4c2be501b7e8695f8bdf4f7d5f51595ed55eea44 (diff)
parentd96299537e43681942ea272e00b0e529aa5b5fa4 (diff)
Merge branch 'from-linus' into upstream
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_forward.c10
-rw-r--r--net/dccp/ccids/ccid3.c153
-rw-r--r--net/dccp/ccids/ccid3.h9
-rw-r--r--net/dccp/ccids/lib/loss_interval.c36
-rw-r--r--net/dccp/ccids/lib/loss_interval.h9
-rw-r--r--net/dccp/ccids/lib/packet_history.c168
-rw-r--r--net/dccp/ccids/lib/packet_history.h17
-rw-r--r--net/dccp/ccids/lib/tfrc.h2
-rw-r--r--net/dccp/ccids/lib/tfrc_equation.c2
-rw-r--r--net/dccp/dccp.h10
-rw-r--r--net/dccp/options.c2
-rw-r--r--net/ipv4/netfilter/arp_tables.c3
-rw-r--r--net/ipv4/tcp_output.c1
-rw-r--r--net/ipv6/tcp_ipv6.c2
-rw-r--r--net/sctp/sm_make_chunk.c30
-rw-r--r--net/sctp/sm_statefuns.c20
-rw-r--r--net/sctp/socket.c10
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c3
-rw-r--r--net/sunrpc/clnt.c30
-rw-r--r--net/sunrpc/rpc_pipe.c55
20 files changed, 273 insertions, 299 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 6ccd32b30809..864fbbc7b24d 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -40,11 +40,15 @@ int br_dev_queue_push_xmit(struct sk_buff *skb)
40 else { 40 else {
41#ifdef CONFIG_BRIDGE_NETFILTER 41#ifdef CONFIG_BRIDGE_NETFILTER
42 /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */ 42 /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */
43 nf_bridge_maybe_copy_header(skb); 43 if (nf_bridge_maybe_copy_header(skb))
44 kfree_skb(skb);
45 else
44#endif 46#endif
45 skb_push(skb, ETH_HLEN); 47 {
48 skb_push(skb, ETH_HLEN);
46 49
47 dev_queue_xmit(skb); 50 dev_queue_xmit(skb);
51 }
48 } 52 }
49 53
50 return 0; 54 return 0;
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 }
346out: 348out:
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 }
856found: 858found:
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:
882static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) 900static 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
901static void ccid3_hc_rx_detect_loss(struct sock *sk) 948static 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
993detect_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
912static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) 1000static 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}
1231module_exit(ccid3_module_exit); 1320module_exit(ccid3_module_exit);
1232 1321
1233MODULE_AUTHOR("Ian McDonald <iam4@cs.waikato.ac.nz>, " 1322MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
1234 "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); 1323 "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
1235MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID"); 1324MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID");
1236MODULE_LICENSE("GPL"); 1325MODULE_LICENSE("GPL");
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 5ade4f668b22..0a2cb7536d26 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -1,13 +1,13 @@
1/* 1/*
2 * net/dccp/ccids/ccid3.h 2 * net/dccp/ccids/ccid3.h
3 * 3 *
4 * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. 4 * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand.
5 * 5 *
6 * An implementation of the DCCP protocol 6 * An implementation of the DCCP protocol
7 * 7 *
8 * This code has been developed by the University of Waikato WAND 8 * This code has been developed by the University of Waikato WAND
9 * research group. For further information please see http://www.wand.net.nz/ 9 * research group. For further information please see http://www.wand.net.nz/
10 * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz 10 * or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz
11 * 11 *
12 * This code also uses code from Lulea University, rereleased as GPL by its 12 * This code also uses code from Lulea University, rereleased as GPL by its
13 * authors: 13 * authors:
@@ -120,9 +120,10 @@ struct ccid3_hc_rx_sock {
120#define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv 120#define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv
121#define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt 121#define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt
122#define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p 122#define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p
123 u64 ccid3hcrx_seqno_last_counter:48, 123 u64 ccid3hcrx_seqno_nonloss:48,
124 ccid3hcrx_ccval_nonloss:4,
124 ccid3hcrx_state:8, 125 ccid3hcrx_state:8,
125 ccid3hcrx_last_counter:4; 126 ccid3hcrx_ccval_last_counter:4;
126 u32 ccid3hcrx_bytes_recv; 127 u32 ccid3hcrx_bytes_recv;
127 struct timeval ccid3hcrx_tstamp_last_feedback; 128 struct timeval ccid3hcrx_tstamp_last_feedback;
128 struct timeval ccid3hcrx_tstamp_last_ack; 129 struct timeval ccid3hcrx_tstamp_last_ack;
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index 5d7b7d864385..906c81ab9d4f 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -2,7 +2,7 @@
2 * net/dccp/ccids/lib/loss_interval.c 2 * net/dccp/ccids/lib/loss_interval.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 Ian McDonald <iam4@cs.waikato.ac.nz> 5 * Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
6 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> 6 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
@@ -12,6 +12,7 @@
12 */ 12 */
13 13
14#include <linux/module.h> 14#include <linux/module.h>
15#include <net/sock.h>
15 16
16#include "loss_interval.h" 17#include "loss_interval.h"
17 18
@@ -90,13 +91,13 @@ u32 dccp_li_hist_calc_i_mean(struct list_head *list)
90 u32 w_tot = 0; 91 u32 w_tot = 0;
91 92
92 list_for_each_entry_safe(li_entry, li_next, list, dccplih_node) { 93 list_for_each_entry_safe(li_entry, li_next, list, dccplih_node) {
93 if (i < DCCP_LI_HIST_IVAL_F_LENGTH) { 94 if (li_entry->dccplih_interval != ~0) {
94 i_tot0 += li_entry->dccplih_interval * dccp_li_hist_w[i]; 95 i_tot0 += li_entry->dccplih_interval * dccp_li_hist_w[i];
95 w_tot += dccp_li_hist_w[i]; 96 w_tot += dccp_li_hist_w[i];
97 if (i != 0)
98 i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1];
96 } 99 }
97 100
98 if (i != 0)
99 i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1];
100 101
101 if (++i > DCCP_LI_HIST_IVAL_F_LENGTH) 102 if (++i > DCCP_LI_HIST_IVAL_F_LENGTH)
102 break; 103 break;
@@ -107,37 +108,36 @@ u32 dccp_li_hist_calc_i_mean(struct list_head *list)
107 108
108 i_tot = max(i_tot0, i_tot1); 109 i_tot = max(i_tot0, i_tot1);
109 110
110 /* FIXME: Why do we do this? -Ian McDonald */ 111 if (!w_tot) {
111 if (i_tot * 4 < w_tot) 112 LIMIT_NETDEBUG(KERN_WARNING "%s: w_tot = 0\n", __FUNCTION__);
112 i_tot = w_tot * 4; 113 return 1;
114 }
113 115
114 return i_tot * 4 / w_tot; 116 return i_tot / w_tot;
115} 117}
116 118
117EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean); 119EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean);
118 120
119struct dccp_li_hist_entry *dccp_li_hist_interval_new(struct dccp_li_hist *hist, 121int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
120 struct list_head *list, 122 struct list_head *list, const u64 seq_loss, const u8 win_loss)
121 const u64 seq_loss,
122 const u8 win_loss)
123{ 123{
124 struct dccp_li_hist_entry *tail = NULL, *entry; 124 struct dccp_li_hist_entry *entry;
125 int i; 125 int i;
126 126
127 for (i = 0; i <= DCCP_LI_HIST_IVAL_F_LENGTH; ++i) { 127 for (i = 0; i < DCCP_LI_HIST_IVAL_F_LENGTH; i++) {
128 entry = dccp_li_hist_entry_new(hist, SLAB_ATOMIC); 128 entry = dccp_li_hist_entry_new(hist, SLAB_ATOMIC);
129 if (entry == NULL) { 129 if (entry == NULL) {
130 dccp_li_hist_purge(hist, list); 130 dccp_li_hist_purge(hist, list);
131 return NULL; 131 dump_stack();
132 return 0;
132 } 133 }
133 if (tail == NULL) 134 entry->dccplih_interval = ~0;
134 tail = entry;
135 list_add(&entry->dccplih_node, list); 135 list_add(&entry->dccplih_node, list);
136 } 136 }
137 137
138 entry->dccplih_seqno = seq_loss; 138 entry->dccplih_seqno = seq_loss;
139 entry->dccplih_win_count = win_loss; 139 entry->dccplih_win_count = win_loss;
140 return tail; 140 return 1;
141} 141}
142 142
143EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new); 143EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new);
diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h
index 43bf78269d1d..0ae85f0340b2 100644
--- a/net/dccp/ccids/lib/loss_interval.h
+++ b/net/dccp/ccids/lib/loss_interval.h
@@ -4,7 +4,7 @@
4 * net/dccp/ccids/lib/loss_interval.h 4 * net/dccp/ccids/lib/loss_interval.h
5 * 5 *
6 * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. 6 * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
7 * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> 7 * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
8 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> 8 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
@@ -52,9 +52,6 @@ extern void dccp_li_hist_purge(struct dccp_li_hist *hist,
52 52
53extern u32 dccp_li_hist_calc_i_mean(struct list_head *list); 53extern u32 dccp_li_hist_calc_i_mean(struct list_head *list);
54 54
55extern struct dccp_li_hist_entry * 55extern int dccp_li_hist_interval_new(struct dccp_li_hist *hist,
56 dccp_li_hist_interval_new(struct dccp_li_hist *hist, 56 struct list_head *list, const u64 seq_loss, const u8 win_loss);
57 struct list_head *list,
58 const u64 seq_loss,
59 const u8 win_loss);
60#endif /* _DCCP_LI_HIST_ */ 57#endif /* _DCCP_LI_HIST_ */
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c
index ad98d6a322eb..b876c9c81c65 100644
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -1,13 +1,13 @@
1/* 1/*
2 * net/dccp/packet_history.h 2 * net/dccp/packet_history.c
3 * 3 *
4 * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. 4 * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand.
5 * 5 *
6 * An implementation of the DCCP protocol 6 * An implementation of the DCCP protocol
7 * 7 *
8 * This code has been developed by the University of Waikato WAND 8 * This code has been developed by the University of Waikato WAND
9 * research group. For further information please see http://www.wand.net.nz/ 9 * research group. For further information please see http://www.wand.net.nz/
10 * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz 10 * or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz
11 * 11 *
12 * This code also uses code from Lulea University, rereleased as GPL by its 12 * This code also uses code from Lulea University, rereleased as GPL by its
13 * authors: 13 * authors:
@@ -112,64 +112,27 @@ struct dccp_rx_hist_entry *
112 112
113EXPORT_SYMBOL_GPL(dccp_rx_hist_find_data_packet); 113EXPORT_SYMBOL_GPL(dccp_rx_hist_find_data_packet);
114 114
115int dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, 115void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
116 struct list_head *rx_list, 116 struct list_head *rx_list,
117 struct list_head *li_list, 117 struct list_head *li_list,
118 struct dccp_rx_hist_entry *packet) 118 struct dccp_rx_hist_entry *packet,
119 u64 nonloss_seqno)
119{ 120{
120 struct dccp_rx_hist_entry *entry, *next, *iter; 121 struct dccp_rx_hist_entry *entry, *next;
121 u8 num_later = 0; 122 u8 num_later = 0;
122 123
123 iter = dccp_rx_hist_head(rx_list); 124 list_add(&packet->dccphrx_node, rx_list);
124 if (iter == NULL)
125 dccp_rx_hist_add_entry(rx_list, packet);
126 else {
127 const u64 seqno = packet->dccphrx_seqno;
128
129 if (after48(seqno, iter->dccphrx_seqno))
130 dccp_rx_hist_add_entry(rx_list, packet);
131 else {
132 if (dccp_rx_hist_entry_data_packet(iter))
133 num_later = 1;
134
135 list_for_each_entry_continue(iter, rx_list,
136 dccphrx_node) {
137 if (after48(seqno, iter->dccphrx_seqno)) {
138 dccp_rx_hist_add_entry(&iter->dccphrx_node,
139 packet);
140 goto trim_history;
141 }
142
143 if (dccp_rx_hist_entry_data_packet(iter))
144 num_later++;
145 125
146 if (num_later == TFRC_RECV_NUM_LATE_LOSS) {
147 dccp_rx_hist_entry_delete(hist, packet);
148 return 1;
149 }
150 }
151
152 if (num_later < TFRC_RECV_NUM_LATE_LOSS)
153 dccp_rx_hist_add_entry(rx_list, packet);
154 /*
155 * FIXME: else what? should we destroy the packet
156 * like above?
157 */
158 }
159 }
160
161trim_history:
162 /*
163 * Trim history (remove all packets after the NUM_LATE_LOSS + 1
164 * data packets)
165 */
166 num_later = TFRC_RECV_NUM_LATE_LOSS + 1; 126 num_later = TFRC_RECV_NUM_LATE_LOSS + 1;
167 127
168 if (!list_empty(li_list)) { 128 if (!list_empty(li_list)) {
169 list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) { 129 list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) {
170 if (num_later == 0) { 130 if (num_later == 0) {
171 list_del_init(&entry->dccphrx_node); 131 if (after48(nonloss_seqno,
172 dccp_rx_hist_entry_delete(hist, entry); 132 entry->dccphrx_seqno)) {
133 list_del_init(&entry->dccphrx_node);
134 dccp_rx_hist_entry_delete(hist, entry);
135 }
173 } else if (dccp_rx_hist_entry_data_packet(entry)) 136 } else if (dccp_rx_hist_entry_data_packet(entry))
174 --num_later; 137 --num_later;
175 } 138 }
@@ -217,94 +180,10 @@ trim_history:
217 --num_later; 180 --num_later;
218 } 181 }
219 } 182 }
220
221 return 0;
222} 183}
223 184
224EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet); 185EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet);
225 186
226u64 dccp_rx_hist_detect_loss(struct list_head *rx_list,
227 struct list_head *li_list, u8 *win_loss)
228{
229 struct dccp_rx_hist_entry *entry, *next, *packet;
230 struct dccp_rx_hist_entry *a_loss = NULL;
231 struct dccp_rx_hist_entry *b_loss = NULL;
232 u64 seq_loss = DCCP_MAX_SEQNO + 1;
233 u8 num_later = TFRC_RECV_NUM_LATE_LOSS;
234
235 list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) {
236 if (num_later == 0) {
237 b_loss = entry;
238 break;
239 } else if (dccp_rx_hist_entry_data_packet(entry))
240 --num_later;
241 }
242
243 if (b_loss == NULL)
244 goto out;
245
246 num_later = 1;
247 list_for_each_entry_safe_continue(entry, next, rx_list, dccphrx_node) {
248 if (num_later == 0) {
249 a_loss = entry;
250 break;
251 } else if (dccp_rx_hist_entry_data_packet(entry))
252 --num_later;
253 }
254
255 if (a_loss == NULL) {
256 if (list_empty(li_list)) {
257 /* no loss event have occured yet */
258 LIMIT_NETDEBUG("%s: TODO: find a lost data packet by "
259 "comparing to initial seqno\n",
260 __FUNCTION__);
261 goto out;
262 } else {
263 LIMIT_NETDEBUG("%s: Less than 4 data pkts in history!",
264 __FUNCTION__);
265 goto out;
266 }
267 }
268
269 /* Locate a lost data packet */
270 entry = packet = b_loss;
271 list_for_each_entry_safe_continue(entry, next, rx_list, dccphrx_node) {
272 u64 delta = dccp_delta_seqno(entry->dccphrx_seqno,
273 packet->dccphrx_seqno);
274
275 if (delta != 0) {
276 if (dccp_rx_hist_entry_data_packet(packet))
277 --delta;
278 /*
279 * FIXME: check this, probably this % usage is because
280 * in earlier drafts the ndp count was just 8 bits
281 * long, but now it cam be up to 24 bits long.
282 */
283#if 0
284 if (delta % DCCP_NDP_LIMIT !=
285 (packet->dccphrx_ndp -
286 entry->dccphrx_ndp) % DCCP_NDP_LIMIT)
287#endif
288 if (delta != packet->dccphrx_ndp - entry->dccphrx_ndp) {
289 seq_loss = entry->dccphrx_seqno;
290 dccp_inc_seqno(&seq_loss);
291 }
292 }
293 packet = entry;
294 if (packet == a_loss)
295 break;
296 }
297out:
298 if (seq_loss != DCCP_MAX_SEQNO + 1)
299 *win_loss = a_loss->dccphrx_ccval;
300 else
301 *win_loss = 0; /* Paranoia */
302
303 return seq_loss;
304}
305
306EXPORT_SYMBOL_GPL(dccp_rx_hist_detect_loss);
307
308struct dccp_tx_hist *dccp_tx_hist_new(const char *name) 187struct dccp_tx_hist *dccp_tx_hist_new(const char *name)
309{ 188{
310 struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); 189 struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
@@ -365,6 +244,25 @@ struct dccp_tx_hist_entry *
365 244
366EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry); 245EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry);
367 246
247int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
248 u8 *ccval)
249{
250 struct dccp_rx_hist_entry *packet = NULL, *entry;
251
252 list_for_each_entry(entry, list, dccphrx_node)
253 if (entry->dccphrx_seqno == seq) {
254 packet = entry;
255 break;
256 }
257
258 if (packet)
259 *ccval = packet->dccphrx_ccval;
260
261 return packet != NULL;
262}
263
264EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry);
265
368void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, 266void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
369 struct list_head *list, 267 struct list_head *list,
370 struct dccp_tx_hist_entry *packet) 268 struct dccp_tx_hist_entry *packet)
@@ -391,7 +289,7 @@ void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list)
391 289
392EXPORT_SYMBOL_GPL(dccp_tx_hist_purge); 290EXPORT_SYMBOL_GPL(dccp_tx_hist_purge);
393 291
394MODULE_AUTHOR("Ian McDonald <iam4@cs.waikato.ac.nz>, " 292MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, "
395 "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); 293 "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>");
396MODULE_DESCRIPTION("DCCP TFRC library"); 294MODULE_DESCRIPTION("DCCP TFRC library");
397MODULE_LICENSE("GPL"); 295MODULE_LICENSE("GPL");
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h
index 673c209e4e85..067cf1c85a37 100644
--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -1,13 +1,13 @@
1/* 1/*
2 * net/dccp/packet_history.h 2 * net/dccp/packet_history.h
3 * 3 *
4 * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. 4 * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand.
5 * 5 *
6 * An implementation of the DCCP protocol 6 * An implementation of the DCCP protocol
7 * 7 *
8 * This code has been developed by the University of Waikato WAND 8 * This code has been developed by the University of Waikato WAND
9 * research group. For further information please see http://www.wand.net.nz/ 9 * research group. For further information please see http://www.wand.net.nz/
10 * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz 10 * or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz
11 * 11 *
12 * This code also uses code from Lulea University, rereleased as GPL by its 12 * This code also uses code from Lulea University, rereleased as GPL by its
13 * authors: 13 * authors:
@@ -106,6 +106,8 @@ static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist,
106extern struct dccp_tx_hist_entry * 106extern struct dccp_tx_hist_entry *
107 dccp_tx_hist_find_entry(const struct list_head *list, 107 dccp_tx_hist_find_entry(const struct list_head *list,
108 const u64 seq); 108 const u64 seq);
109extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq,
110 u8 *ccval);
109 111
110static inline void dccp_tx_hist_add_entry(struct list_head *list, 112static inline void dccp_tx_hist_add_entry(struct list_head *list,
111 struct dccp_tx_hist_entry *entry) 113 struct dccp_tx_hist_entry *entry)
@@ -164,12 +166,6 @@ static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist *hist,
164extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist, 166extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist,
165 struct list_head *list); 167 struct list_head *list);
166 168
167static inline void dccp_rx_hist_add_entry(struct list_head *list,
168 struct dccp_rx_hist_entry *entry)
169{
170 list_add(&entry->dccphrx_node, list);
171}
172
173static inline struct dccp_rx_hist_entry * 169static inline struct dccp_rx_hist_entry *
174 dccp_rx_hist_head(struct list_head *list) 170 dccp_rx_hist_head(struct list_head *list)
175{ 171{
@@ -188,10 +184,11 @@ static inline int
188 entry->dccphrx_type == DCCP_PKT_DATAACK; 184 entry->dccphrx_type == DCCP_PKT_DATAACK;
189} 185}
190 186
191extern int dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, 187extern void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,
192 struct list_head *rx_list, 188 struct list_head *rx_list,
193 struct list_head *li_list, 189 struct list_head *li_list,
194 struct dccp_rx_hist_entry *packet); 190 struct dccp_rx_hist_entry *packet,
191 u64 nonloss_seqno);
195 192
196extern u64 dccp_rx_hist_detect_loss(struct list_head *rx_list, 193extern u64 dccp_rx_hist_detect_loss(struct list_head *rx_list,
197 struct list_head *li_list, u8 *win_loss); 194 struct list_head *li_list, u8 *win_loss);
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h
index 130c4c40cfe3..45f30f59ea2a 100644
--- a/net/dccp/ccids/lib/tfrc.h
+++ b/net/dccp/ccids/lib/tfrc.h
@@ -4,7 +4,7 @@
4 * net/dccp/ccids/lib/tfrc.h 4 * net/dccp/ccids/lib/tfrc.h
5 * 5 *
6 * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. 6 * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
7 * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> 7 * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
8 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> 8 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
9 * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon 9 * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
10 * 10 *
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c
index 4fd2ebebf5a0..44076e0c6591 100644
--- a/net/dccp/ccids/lib/tfrc_equation.c
+++ b/net/dccp/ccids/lib/tfrc_equation.c
@@ -2,7 +2,7 @@
2 * net/dccp/ccids/lib/tfrc_equation.c 2 * net/dccp/ccids/lib/tfrc_equation.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 Ian McDonald <iam4@cs.waikato.ac.nz> 5 * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
6 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> 6 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
7 * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon 7 * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
8 * 8 *
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index d00a2f4ee5dd..a5c5475724c0 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -5,7 +5,7 @@
5 * 5 *
6 * An implementation of the DCCP protocol 6 * An implementation of the DCCP protocol
7 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> 7 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
8 * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> 8 * Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz>
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as 11 * under the terms of the GNU General Public License version 2 as
@@ -81,6 +81,14 @@ static inline u64 max48(const u64 seq1, const u64 seq2)
81 return after48(seq1, seq2) ? seq1 : seq2; 81 return after48(seq1, seq2) ? seq1 : seq2;
82} 82}
83 83
84/* is seq1 next seqno after seq2 */
85static inline int follows48(const u64 seq1, const u64 seq2)
86{
87 int diff = (seq1 & 0xFFFF) - (seq2 & 0xFFFF);
88
89 return diff==1;
90}
91
84enum { 92enum {
85 DCCP_MIB_NUM = 0, 93 DCCP_MIB_NUM = 0,
86 DCCP_MIB_ACTIVEOPENS, /* ActiveOpens */ 94 DCCP_MIB_ACTIVEOPENS, /* ActiveOpens */
diff --git a/net/dccp/options.c b/net/dccp/options.c
index daf72bb671f0..07a34696ac97 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -4,7 +4,7 @@
4 * An implementation of the DCCP protocol 4 * An implementation of the DCCP protocol
5 * Copyright (c) 2005 Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org> 5 * Copyright (c) 2005 Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
6 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net> 6 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
7 * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> 7 * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index df4854cf598b..8d1d7a6e72a5 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -236,7 +236,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
236 struct arpt_entry *e, *back; 236 struct arpt_entry *e, *back;
237 const char *indev, *outdev; 237 const char *indev, *outdev;
238 void *table_base; 238 void *table_base;
239 struct xt_table_info *private = table->private; 239 struct xt_table_info *private;
240 240
241 /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ 241 /* ARP header, plus 2 device addresses, plus 2 IP addresses. */
242 if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) + 242 if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) +
@@ -248,6 +248,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb,
248 outdev = out ? out->name : nulldevname; 248 outdev = out ? out->name : nulldevname;
249 249
250 read_lock_bh(&table->lock); 250 read_lock_bh(&table->lock);
251 private = table->private;
251 table_base = (void *)private->entries[smp_processor_id()]; 252 table_base = (void *)private->entries[smp_processor_id()];
252 e = get_entry(table_base, private->hook_entry[hook]); 253 e = get_entry(table_base, private->hook_entry[hook]);
253 back = get_entry(table_base, private->underflow[hook]); 254 back = get_entry(table_base, private->underflow[hook]);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 507adefbc17c..b4f3ffe1b3b4 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -201,6 +201,7 @@ void tcp_select_initial_window(int __space, __u32 mss,
201 * See RFC1323 for an explanation of the limit to 14 201 * See RFC1323 for an explanation of the limit to 14
202 */ 202 */
203 space = max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max); 203 space = max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max);
204 space = min_t(u32, space, *window_clamp);
204 while (space > 65535 && (*rcv_wscale) < 14) { 205 while (space > 65535 && (*rcv_wscale) < 14) {
205 space >>= 1; 206 space >>= 1;
206 (*rcv_wscale)++; 207 (*rcv_wscale)++;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index b843a650be71..802a1a6b1037 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -944,7 +944,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
944 * comment in that function for the gory details. -acme 944 * comment in that function for the gory details. -acme
945 */ 945 */
946 946
947 sk->sk_gso_type = SKB_GSO_TCPV6; 947 newsk->sk_gso_type = SKB_GSO_TCPV6;
948 __ip6_dst_store(newsk, dst, NULL); 948 __ip6_dst_store(newsk, dst, NULL);
949 949
950 newtcp6sk = (struct tcp6_sock *)newsk; 950 newtcp6sk = (struct tcp6_sock *)newsk;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 4f11f5858209..17b509282cf2 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -806,38 +806,26 @@ no_mem:
806 806
807/* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error. */ 807/* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error. */
808struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc, 808struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc,
809 const struct sctp_chunk *chunk, 809 const struct msghdr *msg,
810 const struct msghdr *msg) 810 size_t paylen)
811{ 811{
812 struct sctp_chunk *retval; 812 struct sctp_chunk *retval;
813 void *payload = NULL, *payoff; 813 void *payload = NULL;
814 size_t paylen = 0; 814 int err;
815 struct iovec *iov = NULL;
816 int iovlen = 0;
817
818 if (msg) {
819 iov = msg->msg_iov;
820 iovlen = msg->msg_iovlen;
821 paylen = get_user_iov_size(iov, iovlen);
822 }
823 815
824 retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen); 816 retval = sctp_make_abort(asoc, NULL, sizeof(sctp_errhdr_t) + paylen);
825 if (!retval) 817 if (!retval)
826 goto err_chunk; 818 goto err_chunk;
827 819
828 if (paylen) { 820 if (paylen) {
829 /* Put the msg_iov together into payload. */ 821 /* Put the msg_iov together into payload. */
830 payload = kmalloc(paylen, GFP_ATOMIC); 822 payload = kmalloc(paylen, GFP_KERNEL);
831 if (!payload) 823 if (!payload)
832 goto err_payload; 824 goto err_payload;
833 payoff = payload;
834 825
835 for (; iovlen > 0; --iovlen) { 826 err = memcpy_fromiovec(payload, msg->msg_iov, paylen);
836 if (copy_from_user(payoff, iov->iov_base,iov->iov_len)) 827 if (err < 0)
837 goto err_copy; 828 goto err_copy;
838 payoff += iov->iov_len;
839 iov++;
840 }
841 } 829 }
842 830
843 sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen); 831 sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen);
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index ead3f1b0ea3d..5b5ae7958322 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -4031,18 +4031,12 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
4031 * from its upper layer, but retransmits data to the far end 4031 * from its upper layer, but retransmits data to the far end
4032 * if necessary to fill gaps. 4032 * if necessary to fill gaps.
4033 */ 4033 */
4034 struct msghdr *msg = arg; 4034 struct sctp_chunk *abort = arg;
4035 struct sctp_chunk *abort;
4036 sctp_disposition_t retval; 4035 sctp_disposition_t retval;
4037 4036
4038 retval = SCTP_DISPOSITION_CONSUME; 4037 retval = SCTP_DISPOSITION_CONSUME;
4039 4038
4040 /* Generate ABORT chunk to send the peer. */ 4039 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
4041 abort = sctp_make_abort_user(asoc, NULL, msg);
4042 if (!abort)
4043 retval = SCTP_DISPOSITION_NOMEM;
4044 else
4045 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
4046 4040
4047 /* Even if we can't send the ABORT due to low memory delete the 4041 /* Even if we can't send the ABORT due to low memory delete the
4048 * TCB. This is a departure from our typical NOMEM handling. 4042 * TCB. This is a departure from our typical NOMEM handling.
@@ -4166,8 +4160,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
4166 void *arg, 4160 void *arg,
4167 sctp_cmd_seq_t *commands) 4161 sctp_cmd_seq_t *commands)
4168{ 4162{
4169 struct msghdr *msg = arg; 4163 struct sctp_chunk *abort = arg;
4170 struct sctp_chunk *abort;
4171 sctp_disposition_t retval; 4164 sctp_disposition_t retval;
4172 4165
4173 /* Stop T1-init timer */ 4166 /* Stop T1-init timer */
@@ -4175,12 +4168,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
4175 SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); 4168 SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
4176 retval = SCTP_DISPOSITION_CONSUME; 4169 retval = SCTP_DISPOSITION_CONSUME;
4177 4170
4178 /* Generate ABORT chunk to send the peer */ 4171 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
4179 abort = sctp_make_abort_user(asoc, NULL, msg);
4180 if (!abort)
4181 retval = SCTP_DISPOSITION_NOMEM;
4182 else
4183 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
4184 4172
4185 sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, 4173 sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
4186 SCTP_STATE(SCTP_STATE_CLOSED)); 4174 SCTP_STATE(SCTP_STATE_CLOSED));
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 54722e622e6d..fde3f55bfd4b 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1520,8 +1520,16 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
1520 goto out_unlock; 1520 goto out_unlock;
1521 } 1521 }
1522 if (sinfo_flags & SCTP_ABORT) { 1522 if (sinfo_flags & SCTP_ABORT) {
1523 struct sctp_chunk *chunk;
1524
1525 chunk = sctp_make_abort_user(asoc, msg, msg_len);
1526 if (!chunk) {
1527 err = -ENOMEM;
1528 goto out_unlock;
1529 }
1530
1523 SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc); 1531 SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc);
1524 sctp_primitive_ABORT(asoc, msg); 1532 sctp_primitive_ABORT(asoc, chunk);
1525 err = 0; 1533 err = 0;
1526 goto out_unlock; 1534 goto out_unlock;
1527 } 1535 }
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 4a9aa9393b97..ef1cf5b476c8 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -718,8 +718,7 @@ gss_destroy(struct rpc_auth *auth)
718 auth, auth->au_flavor); 718 auth, auth->au_flavor);
719 719
720 gss_auth = container_of(auth, struct gss_auth, rpc_auth); 720 gss_auth = container_of(auth, struct gss_auth, rpc_auth);
721 rpc_unlink(gss_auth->path); 721 rpc_unlink(gss_auth->dentry);
722 dput(gss_auth->dentry);
723 gss_auth->dentry = NULL; 722 gss_auth->dentry = NULL;
724 gss_mech_put(gss_auth->mech); 723 gss_mech_put(gss_auth->mech);
725 724
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index d6409e757219..3e19d321067a 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -183,8 +183,7 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname,
183 183
184out_no_auth: 184out_no_auth:
185 if (!IS_ERR(clnt->cl_dentry)) { 185 if (!IS_ERR(clnt->cl_dentry)) {
186 rpc_rmdir(clnt->cl_pathname); 186 rpc_rmdir(clnt->cl_dentry);
187 dput(clnt->cl_dentry);
188 rpc_put_mount(); 187 rpc_put_mount();
189 } 188 }
190out_no_path: 189out_no_path:
@@ -251,10 +250,8 @@ rpc_clone_client(struct rpc_clnt *clnt)
251 new->cl_autobind = 0; 250 new->cl_autobind = 0;
252 new->cl_oneshot = 0; 251 new->cl_oneshot = 0;
253 new->cl_dead = 0; 252 new->cl_dead = 0;
254 if (!IS_ERR(new->cl_dentry)) { 253 if (!IS_ERR(new->cl_dentry))
255 dget(new->cl_dentry); 254 dget(new->cl_dentry);
256 rpc_get_mount();
257 }
258 rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); 255 rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
259 if (new->cl_auth) 256 if (new->cl_auth)
260 atomic_inc(&new->cl_auth->au_count); 257 atomic_inc(&new->cl_auth->au_count);
@@ -317,11 +314,15 @@ rpc_destroy_client(struct rpc_clnt *clnt)
317 clnt->cl_auth = NULL; 314 clnt->cl_auth = NULL;
318 } 315 }
319 if (clnt->cl_parent != clnt) { 316 if (clnt->cl_parent != clnt) {
317 if (!IS_ERR(clnt->cl_dentry))
318 dput(clnt->cl_dentry);
320 rpc_destroy_client(clnt->cl_parent); 319 rpc_destroy_client(clnt->cl_parent);
321 goto out_free; 320 goto out_free;
322 } 321 }
323 if (clnt->cl_pathname[0]) 322 if (!IS_ERR(clnt->cl_dentry)) {
324 rpc_rmdir(clnt->cl_pathname); 323 rpc_rmdir(clnt->cl_dentry);
324 rpc_put_mount();
325 }
325 if (clnt->cl_xprt) { 326 if (clnt->cl_xprt) {
326 xprt_destroy(clnt->cl_xprt); 327 xprt_destroy(clnt->cl_xprt);
327 clnt->cl_xprt = NULL; 328 clnt->cl_xprt = NULL;
@@ -331,10 +332,6 @@ rpc_destroy_client(struct rpc_clnt *clnt)
331out_free: 332out_free:
332 rpc_free_iostats(clnt->cl_metrics); 333 rpc_free_iostats(clnt->cl_metrics);
333 clnt->cl_metrics = NULL; 334 clnt->cl_metrics = NULL;
334 if (!IS_ERR(clnt->cl_dentry)) {
335 dput(clnt->cl_dentry);
336 rpc_put_mount();
337 }
338 kfree(clnt); 335 kfree(clnt);
339 return 0; 336 return 0;
340} 337}
@@ -1184,6 +1181,17 @@ call_verify(struct rpc_task *task)
1184 u32 *p = iov->iov_base, n; 1181 u32 *p = iov->iov_base, n;
1185 int error = -EACCES; 1182 int error = -EACCES;
1186 1183
1184 if ((task->tk_rqstp->rq_rcv_buf.len & 3) != 0) {
1185 /* RFC-1014 says that the representation of XDR data must be a
1186 * multiple of four bytes
1187 * - if it isn't pointer subtraction in the NFS client may give
1188 * undefined results
1189 */
1190 printk(KERN_WARNING
1191 "call_verify: XDR representation not a multiple of"
1192 " 4 bytes: 0x%x\n", task->tk_rqstp->rq_rcv_buf.len);
1193 goto out_eio;
1194 }
1187 if ((len -= 3) < 0) 1195 if ((len -= 3) < 0)
1188 goto out_overflow; 1196 goto out_overflow;
1189 p += 1; /* skip XID */ 1197 p += 1; /* skip XID */
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index a3bd2db2e024..0b1a1ac8a4bc 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -539,6 +539,7 @@ repeat:
539 rpc_close_pipes(dentry->d_inode); 539 rpc_close_pipes(dentry->d_inode);
540 simple_unlink(dir, dentry); 540 simple_unlink(dir, dentry);
541 } 541 }
542 inode_dir_notify(dir, DN_DELETE);
542 dput(dentry); 543 dput(dentry);
543 } while (n); 544 } while (n);
544 goto repeat; 545 goto repeat;
@@ -610,8 +611,8 @@ __rpc_rmdir(struct inode *dir, struct dentry *dentry)
610 int error; 611 int error;
611 612
612 shrink_dcache_parent(dentry); 613 shrink_dcache_parent(dentry);
613 if (dentry->d_inode) 614 if (d_unhashed(dentry))
614 rpc_close_pipes(dentry->d_inode); 615 return 0;
615 if ((error = simple_rmdir(dir, dentry)) != 0) 616 if ((error = simple_rmdir(dir, dentry)) != 0)
616 return error; 617 return error;
617 if (!error) { 618 if (!error) {
@@ -684,28 +685,20 @@ err_dput:
684} 685}
685 686
686int 687int
687rpc_rmdir(char *path) 688rpc_rmdir(struct dentry *dentry)
688{ 689{
689 struct nameidata nd; 690 struct dentry *parent;
690 struct dentry *dentry;
691 struct inode *dir; 691 struct inode *dir;
692 int error; 692 int error;
693 693
694 if ((error = rpc_lookup_parent(path, &nd)) != 0) 694 parent = dget_parent(dentry);
695 return error; 695 dir = parent->d_inode;
696 dir = nd.dentry->d_inode;
697 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); 696 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
698 dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len);
699 if (IS_ERR(dentry)) {
700 error = PTR_ERR(dentry);
701 goto out_release;
702 }
703 rpc_depopulate(dentry); 697 rpc_depopulate(dentry);
704 error = __rpc_rmdir(dir, dentry); 698 error = __rpc_rmdir(dir, dentry);
705 dput(dentry); 699 dput(dentry);
706out_release:
707 mutex_unlock(&dir->i_mutex); 700 mutex_unlock(&dir->i_mutex);
708 rpc_release_path(&nd); 701 dput(parent);
709 return error; 702 return error;
710} 703}
711 704
@@ -746,32 +739,26 @@ err_dput:
746} 739}
747 740
748int 741int
749rpc_unlink(char *path) 742rpc_unlink(struct dentry *dentry)
750{ 743{
751 struct nameidata nd; 744 struct dentry *parent;
752 struct dentry *dentry;
753 struct inode *dir; 745 struct inode *dir;
754 int error; 746 int error = 0;
755 747
756 if ((error = rpc_lookup_parent(path, &nd)) != 0) 748 parent = dget_parent(dentry);
757 return error; 749 dir = parent->d_inode;
758 dir = nd.dentry->d_inode;
759 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); 750 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
760 dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len); 751 if (!d_unhashed(dentry)) {
761 if (IS_ERR(dentry)) { 752 d_drop(dentry);
762 error = PTR_ERR(dentry); 753 if (dentry->d_inode) {
763 goto out_release; 754 rpc_close_pipes(dentry->d_inode);
764 } 755 error = simple_unlink(dir, dentry);
765 d_drop(dentry); 756 }
766 if (dentry->d_inode) { 757 inode_dir_notify(dir, DN_DELETE);
767 rpc_close_pipes(dentry->d_inode);
768 error = simple_unlink(dir, dentry);
769 } 758 }
770 dput(dentry); 759 dput(dentry);
771 inode_dir_notify(dir, DN_DELETE);
772out_release:
773 mutex_unlock(&dir->i_mutex); 760 mutex_unlock(&dir->i_mutex);
774 rpc_release_path(&nd); 761 dput(parent);
775 return error; 762 return error;
776} 763}
777 764