aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@mandriva.com>2005-08-10 11:59:38 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 18:56:28 -0400
commit8c60f3fab55712f23f2bd557ceedfbb00c649f37 (patch)
treea131a54e9790b1b85e5c7f78a2e74e33af2bbd87
parent540722ffc3a0d7e11d97a13e1ce6f3bc23b061c1 (diff)
[CCID3]: Separate most of the packet history code
This also changes the list_for_each_entry_safe_continue behaviour to match its kerneldoc comment, that is, to start after the pos passed. Also adds several helper functions from previously open coded fragments, making the code more clear. Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
-rw-r--r--include/linux/list.h3
-rw-r--r--net/dccp/Makefile3
-rw-r--r--net/dccp/ccids/ccid3.c327
-rw-r--r--net/dccp/ccids/ccid3.h18
-rw-r--r--net/dccp/packet_history.c198
-rw-r--r--net/dccp/packet_history.h182
6 files changed, 518 insertions, 213 deletions
diff --git a/include/linux/list.h b/include/linux/list.h
index 597094e0fdb5..0f2435f92db3 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -427,7 +427,8 @@ static inline void list_splice_init(struct list_head *list,
427 * @member: the name of the list_struct within the struct. 427 * @member: the name of the list_struct within the struct.
428 */ 428 */
429#define list_for_each_entry_safe_continue(pos, n, head, member) \ 429#define list_for_each_entry_safe_continue(pos, n, head, member) \
430 for (pos = n, n = list_entry(n->member.next, typeof(*n), member); \ 430 for (pos = list_entry(pos->member.next, typeof(*pos), member), \
431 n = list_entry(pos->member.next, typeof(*pos), member); \
431 &pos->member != (head); \ 432 &pos->member != (head); \
432 pos = n, n = list_entry(n->member.next, typeof(*n), member)) 433 pos = n, n = list_entry(n->member.next, typeof(*n), member))
433 434
diff --git a/net/dccp/Makefile b/net/dccp/Makefile
index c6e6ba55c36b..25a50bdbf1bb 100644
--- a/net/dccp/Makefile
+++ b/net/dccp/Makefile
@@ -1,5 +1,6 @@
1obj-$(CONFIG_IP_DCCP) += dccp.o 1obj-$(CONFIG_IP_DCCP) += dccp.o
2 2
3dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o timer.o 3dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o \
4 timer.o packet_history.o
4 5
5obj-y += ccids/ 6obj-y += ccids/
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index df4adfeaafac..15c25f622000 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -34,8 +34,10 @@
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 */ 35 */
36 36
37#include <linux/config.h>
37#include "../ccid.h" 38#include "../ccid.h"
38#include "../dccp.h" 39#include "../dccp.h"
40#include "../packet_history.h"
39#include "ccid3.h" 41#include "ccid3.h"
40 42
41#ifdef CCID3_DEBUG 43#ifdef CCID3_DEBUG
@@ -82,60 +84,10 @@ enum ccid3_options {
82 84
83static int ccid3_debug; 85static int ccid3_debug;
84 86
85static kmem_cache_t *ccid3_tx_hist_slab; 87struct dccp_tx_hist *ccid3_tx_hist;
86static kmem_cache_t *ccid3_rx_hist_slab; 88struct dccp_rx_hist *ccid3_rx_hist;
87static kmem_cache_t *ccid3_loss_interval_hist_slab;
88
89static inline struct ccid3_tx_hist_entry *ccid3_tx_hist_entry_new(int prio)
90{
91 struct ccid3_tx_hist_entry *entry = kmem_cache_alloc(ccid3_tx_hist_slab, prio);
92
93 if (entry != NULL)
94 entry->ccid3htx_sent = 0;
95
96 return entry;
97}
98
99static inline void ccid3_tx_hist_entry_delete(struct ccid3_tx_hist_entry *entry)
100{
101 if (entry != NULL)
102 kmem_cache_free(ccid3_tx_hist_slab, entry);
103}
104
105static inline struct ccid3_rx_hist_entry *ccid3_rx_hist_entry_new(struct sock *sk,
106 struct sk_buff *skb,
107 int prio)
108{
109 struct ccid3_rx_hist_entry *entry = kmem_cache_alloc(ccid3_rx_hist_slab, prio);
110
111 if (entry != NULL) {
112 const struct dccp_hdr *dh = dccp_hdr(skb);
113
114 entry->ccid3hrx_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
115 entry->ccid3hrx_win_count = dh->dccph_ccval;
116 entry->ccid3hrx_type = dh->dccph_type;
117 entry->ccid3hrx_ndp = dccp_sk(sk)->dccps_options_received.dccpor_ndp;
118 do_gettimeofday(&(entry->ccid3hrx_tstamp));
119 }
120
121 return entry;
122}
123
124static inline void ccid3_rx_hist_entry_delete(struct ccid3_rx_hist_entry *entry)
125{
126 if (entry != NULL)
127 kmem_cache_free(ccid3_rx_hist_slab, entry);
128}
129 89
130static void ccid3_rx_history_delete(struct list_head *hist) 90static kmem_cache_t *ccid3_loss_interval_hist_slab;
131{
132 struct ccid3_rx_hist_entry *entry, *next;
133
134 list_for_each_entry_safe(entry, next, hist, ccid3hrx_node) {
135 list_del_init(&entry->ccid3hrx_node);
136 kmem_cache_free(ccid3_rx_hist_slab, entry);
137 }
138}
139 91
140static inline struct ccid3_loss_interval_hist_entry *ccid3_loss_interval_hist_entry_new(int prio) 92static inline struct ccid3_loss_interval_hist_entry *ccid3_loss_interval_hist_entry_new(int prio)
141{ 93{
@@ -982,7 +934,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
982{ 934{
983 struct dccp_sock *dp = dccp_sk(sk); 935 struct dccp_sock *dp = dccp_sk(sk);
984 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; 936 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
985 struct ccid3_tx_hist_entry *new_packet = NULL; 937 struct dccp_tx_hist_entry *new_packet;
986 struct timeval now; 938 struct timeval now;
987 long delay; 939 long delay;
988 int rc = -ENOTCONN; 940 int rc = -ENOTCONN;
@@ -997,12 +949,9 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
997 goto out; 949 goto out;
998 950
999 /* See if last packet allocated was not sent */ 951 /* See if last packet allocated was not sent */
1000 if (!list_empty(&hctx->ccid3hctx_hist)) 952 new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
1001 new_packet = list_entry(hctx->ccid3hctx_hist.next, 953 if (new_packet == NULL || new_packet->dccphtx_sent) {
1002 struct ccid3_tx_hist_entry, ccid3htx_node); 954 new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist, SLAB_ATOMIC);
1003
1004 if (new_packet == NULL || new_packet->ccid3htx_sent) {
1005 new_packet = ccid3_tx_hist_entry_new(SLAB_ATOMIC);
1006 955
1007 rc = -ENOBUFS; 956 rc = -ENOBUFS;
1008 if (new_packet == NULL) { 957 if (new_packet == NULL) {
@@ -1011,7 +960,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
1011 goto out; 960 goto out;
1012 } 961 }
1013 962
1014 list_add(&new_packet->ccid3htx_node, &hctx->ccid3hctx_hist); 963 dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet);
1015 } 964 }
1016 965
1017 do_gettimeofday(&now); 966 do_gettimeofday(&now);
@@ -1054,7 +1003,9 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
1054 1003
1055 /* Can we send? if so add options and add to packet history */ 1004 /* Can we send? if so add options and add to packet history */
1056 if (rc == 0) 1005 if (rc == 0)
1057 new_packet->ccid3htx_win_count = DCCP_SKB_CB(skb)->dccpd_ccval = hctx->ccid3hctx_last_win_count; 1006 new_packet->dccphtx_win_count =
1007 DCCP_SKB_CB(skb)->dccpd_ccval =
1008 hctx->ccid3hctx_last_win_count;
1058out: 1009out:
1059 return rc; 1010 return rc;
1060} 1011}
@@ -1063,7 +1014,6 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
1063{ 1014{
1064 struct dccp_sock *dp = dccp_sk(sk); 1015 struct dccp_sock *dp = dccp_sk(sk);
1065 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; 1016 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
1066 struct ccid3_tx_hist_entry *packet = NULL;
1067 struct timeval now; 1017 struct timeval now;
1068 1018
1069// ccid3_pr_debug("%s, sk=%p, more=%d, len=%d\n", dccp_role(sk), sk, more, len); 1019// ccid3_pr_debug("%s, sk=%p, more=%d, len=%d\n", dccp_role(sk), sk, more, len);
@@ -1080,20 +1030,23 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
1080 /* check if we have sent a data packet */ 1030 /* check if we have sent a data packet */
1081 if (len > 0) { 1031 if (len > 0) {
1082 unsigned long quarter_rtt; 1032 unsigned long quarter_rtt;
1033 struct dccp_tx_hist_entry *packet;
1083 1034
1084 if (list_empty(&hctx->ccid3hctx_hist)) { 1035 packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist);
1036 if (packet == NULL) {
1085 printk(KERN_CRIT "%s: packet doesn't exists in history!\n", __FUNCTION__); 1037 printk(KERN_CRIT "%s: packet doesn't exists in history!\n", __FUNCTION__);
1086 return; 1038 return;
1087 } 1039 }
1088 packet = list_entry(hctx->ccid3hctx_hist.next, struct ccid3_tx_hist_entry, ccid3htx_node); 1040 if (packet->dccphtx_sent) {
1089 if (packet->ccid3htx_sent) {
1090 printk(KERN_CRIT "%s: no unsent packet in history!\n", __FUNCTION__); 1041 printk(KERN_CRIT "%s: no unsent packet in history!\n", __FUNCTION__);
1091 return; 1042 return;
1092 } 1043 }
1093 packet->ccid3htx_tstamp = now; 1044 packet->dccphtx_tstamp = now;
1094 packet->ccid3htx_seqno = dp->dccps_gss; 1045 packet->dccphtx_seqno = dp->dccps_gss;
1095 // ccid3_pr_debug("%s, sk=%p, seqno=%llu inserted!\n", dccp_role(sk), sk, packet->ccid3htx_seqno); 1046#if 0
1096 1047 ccid3_pr_debug("%s, sk=%p, seqno=%llu inserted!\n",
1048 dccp_role(sk), sk, packet->dccphtx_seqno);
1049#endif
1097 /* 1050 /*
1098 * Check if win_count have changed */ 1051 * Check if win_count have changed */
1099 /* COMPLIANCE_BEGIN 1052 /* COMPLIANCE_BEGIN
@@ -1106,18 +1059,18 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
1106 min_t(unsigned long, quarter_rtt, 5)) % 16; 1059 min_t(unsigned long, quarter_rtt, 5)) % 16;
1107 ccid3_pr_debug("%s, sk=%p, window changed from %u to %u!\n", 1060 ccid3_pr_debug("%s, sk=%p, window changed from %u to %u!\n",
1108 dccp_role(sk), sk, 1061 dccp_role(sk), sk,
1109 packet->ccid3htx_win_count, 1062 packet->dccphtx_win_count,
1110 hctx->ccid3hctx_last_win_count); 1063 hctx->ccid3hctx_last_win_count);
1111 } 1064 }
1112 /* COMPLIANCE_END */ 1065 /* COMPLIANCE_END */
1113#if 0 1066#if 0
1114 ccid3_pr_debug("%s, sk=%p, packet sent (%llu,%u)\n", 1067 ccid3_pr_debug("%s, sk=%p, packet sent (%llu,%u)\n",
1115 dccp_role(sk), sk, 1068 dccp_role(sk), sk,
1116 packet->ccid3htx_seqno, 1069 packet->dccphtx_seqno,
1117 packet->ccid3htx_win_count); 1070 packet->dccphtx_win_count);
1118#endif 1071#endif
1119 hctx->ccid3hctx_idle = 0; 1072 hctx->ccid3hctx_idle = 0;
1120 packet->ccid3htx_sent = 1; 1073 packet->dccphtx_sent = 1;
1121 } else 1074 } else
1122 ccid3_pr_debug("%s, sk=%p, seqno=%llu NOT inserted!\n", 1075 ccid3_pr_debug("%s, sk=%p, seqno=%llu NOT inserted!\n",
1123 dccp_role(sk), sk, dp->dccps_gss); 1076 dccp_role(sk), sk, dp->dccps_gss);
@@ -1152,7 +1105,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
1152 struct dccp_sock *dp = dccp_sk(sk); 1105 struct dccp_sock *dp = dccp_sk(sk);
1153 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; 1106 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
1154 struct ccid3_options_received *opt_recv; 1107 struct ccid3_options_received *opt_recv;
1155 struct ccid3_tx_hist_entry *entry, *next, *packet; 1108 struct dccp_tx_hist_entry *packet;
1156 unsigned long next_tmout; 1109 unsigned long next_tmout;
1157 u16 t_elapsed; 1110 u16 t_elapsed;
1158 u32 pinv; 1111 u32 pinv;
@@ -1191,13 +1144,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
1191 /* Calculate new round trip sample by 1144 /* Calculate new round trip sample by
1192 * R_sample = (now - t_recvdata) - t_delay */ 1145 * R_sample = (now - t_recvdata) - t_delay */
1193 /* get t_recvdata from history */ 1146 /* get t_recvdata from history */
1194 packet = NULL; 1147 packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist,
1195 list_for_each_entry_safe(entry, next, &hctx->ccid3hctx_hist, ccid3htx_node) 1148 DCCP_SKB_CB(skb)->dccpd_ack_seq);
1196 if (entry->ccid3htx_seqno == DCCP_SKB_CB(skb)->dccpd_ack_seq) {
1197 packet = entry;
1198 break;
1199 }
1200
1201 if (packet == NULL) { 1149 if (packet == NULL) {
1202 ccid3_pr_debug("%s, sk=%p, seqno %llu(%s) does't exist in history!\n", 1150 ccid3_pr_debug("%s, sk=%p, seqno %llu(%s) does't exist in history!\n",
1203 dccp_role(sk), sk, DCCP_SKB_CB(skb)->dccpd_ack_seq, 1151 dccp_role(sk), sk, DCCP_SKB_CB(skb)->dccpd_ack_seq,
@@ -1206,7 +1154,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
1206 } 1154 }
1207 1155
1208 /* Update RTT */ 1156 /* Update RTT */
1209 r_sample = now_delta(packet->ccid3htx_tstamp); 1157 r_sample = now_delta(packet->dccphtx_tstamp);
1210 /* FIXME: */ 1158 /* FIXME: */
1211 // r_sample -= usecs_to_jiffies(t_elapsed * 10); 1159 // r_sample -= usecs_to_jiffies(t_elapsed * 10);
1212 1160
@@ -1273,10 +1221,9 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
1273 ccid3_calc_new_delta(hctx); 1221 ccid3_calc_new_delta(hctx);
1274 1222
1275 /* remove all packets older than the one acked from history */ 1223 /* remove all packets older than the one acked from history */
1276 list_for_each_entry_safe_continue(entry, next, &hctx->ccid3hctx_hist, ccid3htx_node) { 1224 dccp_tx_hist_purge_older(ccid3_tx_hist,
1277 list_del_init(&entry->ccid3htx_node); 1225 &hctx->ccid3hctx_hist, packet);
1278 ccid3_tx_hist_entry_delete(entry); 1226
1279 }
1280 if (hctx->ccid3hctx_x < 10) { 1227 if (hctx->ccid3hctx_x < 10) {
1281 ccid3_pr_debug("ccid3_hc_tx_packet_recv hctx->ccid3hctx_x < 10\n"); 1228 ccid3_pr_debug("ccid3_hc_tx_packet_recv hctx->ccid3hctx_x < 10\n");
1282 hctx->ccid3hctx_x = 10; 1229 hctx->ccid3hctx_x = 10;
@@ -1285,7 +1232,8 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
1285 1232
1286 /* Schedule no feedback timer to expire in max(4 * R, 2 * s / X) */ 1233 /* Schedule no feedback timer to expire in max(4 * R, 2 * s / X) */
1287 next_tmout = max(inet_csk(sk)->icsk_rto, 1234 next_tmout = max(inet_csk(sk)->icsk_rto,
1288 2 * (hctx->ccid3hctx_s * 100000) / (hctx->ccid3hctx_x/10)); 1235 (2 * (hctx->ccid3hctx_s * 100000) /
1236 (hctx->ccid3hctx_x / 10)));
1289 /* maths with 100000 and 10 is to prevent overflow with 32 bit */ 1237 /* maths with 100000 and 10 is to prevent overflow with 32 bit */
1290 1238
1291 ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to expire in %lu jiffies (%luus)\n", 1239 ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to expire in %lu jiffies (%luus)\n",
@@ -1408,7 +1356,6 @@ static void ccid3_hc_tx_exit(struct sock *sk)
1408{ 1356{
1409 struct dccp_sock *dp = dccp_sk(sk); 1357 struct dccp_sock *dp = dccp_sk(sk);
1410 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; 1358 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
1411 struct ccid3_tx_hist_entry *entry, *next;
1412 1359
1413 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); 1360 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
1414 BUG_ON(hctx == NULL); 1361 BUG_ON(hctx == NULL);
@@ -1417,10 +1364,7 @@ static void ccid3_hc_tx_exit(struct sock *sk)
1417 sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); 1364 sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);
1418 1365
1419 /* Empty packet history */ 1366 /* Empty packet history */
1420 list_for_each_entry_safe(entry, next, &hctx->ccid3hctx_hist, ccid3htx_node) { 1367 dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);
1421 list_del_init(&entry->ccid3htx_node);
1422 ccid3_tx_hist_entry_delete(entry);
1423 }
1424 1368
1425 kfree(dp->dccps_hc_tx_ccid_private); 1369 kfree(dp->dccps_hc_tx_ccid_private);
1426 dp->dccps_hc_tx_ccid_private = NULL; 1370 dp->dccps_hc_tx_ccid_private = NULL;
@@ -1462,39 +1406,40 @@ static inline void ccid3_hc_rx_set_state(struct sock *sk, enum ccid3_hc_rx_state
1462 hcrx->ccid3hcrx_state = state; 1406 hcrx->ccid3hcrx_state = state;
1463} 1407}
1464 1408
1465static int ccid3_hc_rx_add_hist(struct sock *sk, struct ccid3_rx_hist_entry *packet) 1409static int ccid3_hc_rx_add_hist(struct sock *sk,
1410 struct dccp_rx_hist_entry *packet)
1466{ 1411{
1467 struct dccp_sock *dp = dccp_sk(sk); 1412 struct dccp_sock *dp = dccp_sk(sk);
1468 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; 1413 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
1469 struct ccid3_rx_hist_entry *entry, *next; 1414 struct dccp_rx_hist_entry *entry, *next, *iter;
1470 u8 num_later = 0; 1415 u8 num_later = 0;
1471 1416
1472 if (list_empty(&hcrx->ccid3hcrx_hist)) 1417 iter = dccp_rx_hist_head(&hcrx->ccid3hcrx_hist);
1473 list_add(&packet->ccid3hrx_node, &hcrx->ccid3hcrx_hist); 1418 if (iter == NULL)
1419 dccp_rx_hist_add_entry(&hcrx->ccid3hcrx_hist, packet);
1474 else { 1420 else {
1475 u64 seqno = packet->ccid3hrx_seqno; 1421 const u64 seqno = packet->dccphrx_seqno;
1476 struct ccid3_rx_hist_entry *iter = list_entry(hcrx->ccid3hcrx_hist.next, 1422
1477 struct ccid3_rx_hist_entry, 1423 if (after48(seqno, iter->dccphrx_seqno))
1478 ccid3hrx_node); 1424 dccp_rx_hist_add_entry(&hcrx->ccid3hcrx_hist, packet);
1479 if (after48(seqno, iter->ccid3hrx_seqno))
1480 list_add(&packet->ccid3hrx_node, &hcrx->ccid3hcrx_hist);
1481 else { 1425 else {
1482 if (iter->ccid3hrx_type == DCCP_PKT_DATA || 1426 if (dccp_rx_hist_entry_data_packet(iter))
1483 iter->ccid3hrx_type == DCCP_PKT_DATAACK)
1484 num_later = 1; 1427 num_later = 1;
1485 1428
1486 list_for_each_entry_continue(iter, &hcrx->ccid3hcrx_hist, ccid3hrx_node) { 1429 list_for_each_entry_continue(iter,
1487 if (after48(seqno, iter->ccid3hrx_seqno)) { 1430 &hcrx->ccid3hcrx_hist,
1488 list_add(&packet->ccid3hrx_node, &iter->ccid3hrx_node); 1431 dccphrx_node) {
1432 if (after48(seqno, iter->dccphrx_seqno)) {
1433 dccp_rx_hist_add_entry(&iter->dccphrx_node,
1434 packet);
1489 goto trim_history; 1435 goto trim_history;
1490 } 1436 }
1491 1437
1492 if (iter->ccid3hrx_type == DCCP_PKT_DATA || 1438 if (dccp_rx_hist_entry_data_packet(iter))
1493 iter->ccid3hrx_type == DCCP_PKT_DATAACK)
1494 num_later++; 1439 num_later++;
1495 1440
1496 if (num_later == TFRC_RECV_NUM_LATE_LOSS) { 1441 if (num_later == TFRC_RECV_NUM_LATE_LOSS) {
1497 ccid3_rx_hist_entry_delete(packet); 1442 dccp_rx_hist_entry_delete(ccid3_rx_hist, packet);
1498 ccid3_pr_debug("%s, sk=%p, packet(%llu) already lost!\n", 1443 ccid3_pr_debug("%s, sk=%p, packet(%llu) already lost!\n",
1499 dccp_role(sk), sk, seqno); 1444 dccp_role(sk), sk, seqno);
1500 return 1; 1445 return 1;
@@ -1502,7 +1447,8 @@ static int ccid3_hc_rx_add_hist(struct sock *sk, struct ccid3_rx_hist_entry *pac
1502 } 1447 }
1503 1448
1504 if (num_later < TFRC_RECV_NUM_LATE_LOSS) 1449 if (num_later < TFRC_RECV_NUM_LATE_LOSS)
1505 list_add_tail(&packet->ccid3hrx_node, &hcrx->ccid3hcrx_hist); 1450 dccp_rx_hist_add_entry(&hcrx->ccid3hcrx_hist,
1451 packet);
1506 /* FIXME: else what? should we destroy the packet like above? */ 1452 /* FIXME: else what? should we destroy the packet like above? */
1507 } 1453 }
1508 } 1454 }
@@ -1512,12 +1458,12 @@ trim_history:
1512 num_later = TFRC_RECV_NUM_LATE_LOSS + 1; 1458 num_later = TFRC_RECV_NUM_LATE_LOSS + 1;
1513 1459
1514 if (!list_empty(&hcrx->ccid3hcrx_loss_interval_hist)) { 1460 if (!list_empty(&hcrx->ccid3hcrx_loss_interval_hist)) {
1515 list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, ccid3hrx_node) { 1461 list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
1462 dccphrx_node) {
1516 if (num_later == 0) { 1463 if (num_later == 0) {
1517 list_del_init(&entry->ccid3hrx_node); 1464 list_del_init(&entry->dccphrx_node);
1518 ccid3_rx_hist_entry_delete(entry); 1465 dccp_rx_hist_entry_delete(ccid3_rx_hist, entry);
1519 } else if (entry->ccid3hrx_type == DCCP_PKT_DATA || 1466 } else if (dccp_rx_hist_entry_data_packet(entry))
1520 entry->ccid3hrx_type == DCCP_PKT_DATAACK)
1521 --num_later; 1467 --num_later;
1522 } 1468 }
1523 } else { 1469 } else {
@@ -1528,7 +1474,8 @@ trim_history:
1528 * We have no loss interval history so we need at least one 1474 * We have no loss interval history so we need at least one
1529 * rtt:s of data packets to approximate rtt. 1475 * rtt:s of data packets to approximate rtt.
1530 */ 1476 */
1531 list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, ccid3hrx_node) { 1477 list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
1478 dccphrx_node) {
1532 if (num_later == 0) { 1479 if (num_later == 0) {
1533 switch (step) { 1480 switch (step) {
1534 case 0: 1481 case 0:
@@ -1540,10 +1487,11 @@ trim_history:
1540 step = 2; 1487 step = 2;
1541 /* OK, find next data packet */ 1488 /* OK, find next data packet */
1542 num_later = 1; 1489 num_later = 1;
1543 win_count = entry->ccid3hrx_win_count; 1490 win_count = entry->dccphrx_win_count;
1544 break; 1491 break;
1545 case 2: 1492 case 2:
1546 tmp = win_count - entry->ccid3hrx_win_count; 1493 tmp = (win_count -
1494 entry->dccphrx_win_count);
1547 if (tmp < 0) 1495 if (tmp < 0)
1548 tmp += TFRC_WIN_COUNT_LIMIT; 1496 tmp += TFRC_WIN_COUNT_LIMIT;
1549 if (tmp > TFRC_WIN_COUNT_PER_RTT + 1) { 1497 if (tmp > TFRC_WIN_COUNT_PER_RTT + 1) {
@@ -1554,12 +1502,11 @@ trim_history:
1554 num_later = 1; 1502 num_later = 1;
1555 break; 1503 break;
1556 case 3: 1504 case 3:
1557 list_del_init(&entry->ccid3hrx_node); 1505 list_del_init(&entry->dccphrx_node);
1558 ccid3_rx_hist_entry_delete(entry); 1506 dccp_rx_hist_entry_delete(ccid3_rx_hist, entry);
1559 break; 1507 break;
1560 } 1508 }
1561 } else if (entry->ccid3hrx_type == DCCP_PKT_DATA || 1509 } else if (dccp_rx_hist_entry_data_packet(entry))
1562 entry->ccid3hrx_type == DCCP_PKT_DATAACK)
1563 --num_later; 1510 --num_later;
1564 } 1511 }
1565 } 1512 }
@@ -1571,7 +1518,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
1571{ 1518{
1572 struct dccp_sock *dp = dccp_sk(sk); 1519 struct dccp_sock *dp = dccp_sk(sk);
1573 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; 1520 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
1574 struct ccid3_rx_hist_entry *entry, *packet; 1521 struct dccp_rx_hist_entry *packet;
1575 1522
1576 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); 1523 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
1577 1524
@@ -1594,14 +1541,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
1594 return; 1541 return;
1595 } 1542 }
1596 1543
1597 packet = NULL; 1544 packet = dccp_rx_hist_find_data_packet(&hcrx->ccid3hcrx_hist);
1598 list_for_each_entry(entry, &hcrx->ccid3hcrx_hist, ccid3hrx_node)
1599 if (entry->ccid3hrx_type == DCCP_PKT_DATA ||
1600 entry->ccid3hrx_type == DCCP_PKT_DATAACK) {
1601 packet = entry;
1602 break;
1603 }
1604
1605 if (packet == NULL) { 1545 if (packet == NULL) {
1606 printk(KERN_CRIT "%s: %s, sk=%p, no data packet in history!\n", 1546 printk(KERN_CRIT "%s: %s, sk=%p, no data packet in history!\n",
1607 __FUNCTION__, dccp_role(sk), sk); 1547 __FUNCTION__, dccp_role(sk), sk);
@@ -1610,12 +1550,12 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
1610 } 1550 }
1611 1551
1612 do_gettimeofday(&(hcrx->ccid3hcrx_tstamp_last_feedback)); 1552 do_gettimeofday(&(hcrx->ccid3hcrx_tstamp_last_feedback));
1613 hcrx->ccid3hcrx_last_counter = packet->ccid3hrx_win_count; 1553 hcrx->ccid3hcrx_last_counter = packet->dccphrx_win_count;
1614 hcrx->ccid3hcrx_seqno_last_counter = packet->ccid3hrx_seqno; 1554 hcrx->ccid3hcrx_seqno_last_counter = packet->dccphrx_seqno;
1615 hcrx->ccid3hcrx_bytes_recv = 0; 1555 hcrx->ccid3hcrx_bytes_recv = 0;
1616 1556
1617 /* Convert to multiples of 10us */ 1557 /* Convert to multiples of 10us */
1618 hcrx->ccid3hcrx_elapsed_time = now_delta(packet->ccid3hrx_tstamp) / 10; 1558 hcrx->ccid3hcrx_elapsed_time = now_delta(packet->dccphrx_tstamp) / 10;
1619 if (hcrx->ccid3hcrx_p == 0) 1559 if (hcrx->ccid3hcrx_p == 0)
1620 hcrx->ccid3hcrx_pinv = ~0; 1560 hcrx->ccid3hcrx_pinv = ~0;
1621 else 1561 else
@@ -1686,7 +1626,7 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
1686{ 1626{
1687 struct dccp_sock *dp = dccp_sk(sk); 1627 struct dccp_sock *dp = dccp_sk(sk);
1688 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; 1628 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
1689 struct ccid3_rx_hist_entry *entry, *next, *tail = NULL; 1629 struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
1690 u32 rtt, delta, x_recv, fval, p, tmp2; 1630 u32 rtt, delta, x_recv, fval, p, tmp2;
1691 struct timeval tstamp, tmp_tv; 1631 struct timeval tstamp, tmp_tv;
1692 int interval = 0; 1632 int interval = 0;
@@ -1694,19 +1634,19 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
1694 int step = 0; 1634 int step = 0;
1695 u64 tmp1; 1635 u64 tmp1;
1696 1636
1697 list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, ccid3hrx_node) { 1637 list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
1698 if (entry->ccid3hrx_type == DCCP_PKT_DATA || 1638 dccphrx_node) {
1699 entry->ccid3hrx_type == DCCP_PKT_DATAACK) { 1639 if (dccp_rx_hist_entry_data_packet(entry)) {
1700 tail = entry; 1640 tail = entry;
1701 1641
1702 switch (step) { 1642 switch (step) {
1703 case 0: 1643 case 0:
1704 tstamp = entry->ccid3hrx_tstamp; 1644 tstamp = entry->dccphrx_tstamp;
1705 win_count = entry->ccid3hrx_win_count; 1645 win_count = entry->dccphrx_win_count;
1706 step = 1; 1646 step = 1;
1707 break; 1647 break;
1708 case 1: 1648 case 1:
1709 interval = win_count - entry->ccid3hrx_win_count; 1649 interval = win_count - entry->dccphrx_win_count;
1710 if (interval < 0) 1650 if (interval < 0)
1711 interval += TFRC_WIN_COUNT_LIMIT; 1651 interval += TFRC_WIN_COUNT_LIMIT;
1712 if (interval > 4) 1652 if (interval > 4)
@@ -1728,7 +1668,7 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
1728 interval = 1; 1668 interval = 1;
1729 } 1669 }
1730found: 1670found:
1731 timeval_sub(tstamp,tail->ccid3hrx_tstamp,&tmp_tv); 1671 timeval_sub(tstamp,tail->dccphrx_tstamp,&tmp_tv);
1732 rtt = (tmp_tv.tv_sec * USEC_IN_SEC + tmp_tv.tv_usec) * 4 / interval; 1672 rtt = (tmp_tv.tv_sec * USEC_IN_SEC + tmp_tv.tv_usec) * 4 / interval;
1733 ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n", 1673 ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n",
1734 dccp_role(sk), sk, rtt); 1674 dccp_role(sk), sk, rtt);
@@ -1797,34 +1737,33 @@ static void ccid3_hc_rx_detect_loss(struct sock *sk)
1797{ 1737{
1798 struct dccp_sock *dp = dccp_sk(sk); 1738 struct dccp_sock *dp = dccp_sk(sk);
1799 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; 1739 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
1800 struct ccid3_rx_hist_entry *entry, *a_next, *b_next, *packet; 1740 struct dccp_rx_hist_entry *entry, *next, *packet;
1801 struct ccid3_rx_hist_entry *a_loss = NULL; 1741 struct dccp_rx_hist_entry *a_loss = NULL;
1802 struct ccid3_rx_hist_entry *b_loss = NULL; 1742 struct dccp_rx_hist_entry *b_loss = NULL;
1803 u64 seq_loss = DCCP_MAX_SEQNO + 1; 1743 u64 seq_loss = DCCP_MAX_SEQNO + 1;
1804 u8 win_loss = 0; 1744 u8 win_loss = 0;
1805 u8 num_later = TFRC_RECV_NUM_LATE_LOSS; 1745 u8 num_later = TFRC_RECV_NUM_LATE_LOSS;
1806 1746
1807 list_for_each_entry_safe(entry, b_next, &hcrx->ccid3hcrx_hist, ccid3hrx_node) { 1747 list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist,
1748 dccphrx_node) {
1808 if (num_later == 0) { 1749 if (num_later == 0) {
1809 b_loss = entry; 1750 b_loss = entry;
1810 break; 1751 break;
1811 } else if (entry->ccid3hrx_type == DCCP_PKT_DATA || 1752 } else if (dccp_rx_hist_entry_data_packet(entry))
1812 entry->ccid3hrx_type == DCCP_PKT_DATAACK)
1813 --num_later; 1753 --num_later;
1814 } 1754 }
1815 1755
1816 if (b_loss == NULL) 1756 if (b_loss == NULL)
1817 goto out_update_li; 1757 goto out_update_li;
1818 1758
1819 a_next = b_next;
1820 num_later = 1; 1759 num_later = 1;
1821 1760
1822 list_for_each_entry_safe_continue(entry, a_next, &hcrx->ccid3hcrx_hist, ccid3hrx_node) { 1761 list_for_each_entry_safe_continue(entry, next, &hcrx->ccid3hcrx_hist,
1762 dccphrx_node) {
1823 if (num_later == 0) { 1763 if (num_later == 0) {
1824 a_loss = entry; 1764 a_loss = entry;
1825 break; 1765 break;
1826 } else if (entry->ccid3hrx_type == DCCP_PKT_DATA || 1766 } else if (dccp_rx_hist_entry_data_packet(entry))
1827 entry->ccid3hrx_type == DCCP_PKT_DATAACK)
1828 --num_later; 1767 --num_later;
1829 } 1768 }
1830 1769
@@ -1844,12 +1783,13 @@ static void ccid3_hc_rx_detect_loss(struct sock *sk)
1844 1783
1845 /* Locate a lost data packet */ 1784 /* Locate a lost data packet */
1846 entry = packet = b_loss; 1785 entry = packet = b_loss;
1847 list_for_each_entry_safe_continue(entry, b_next, &hcrx->ccid3hcrx_hist, ccid3hrx_node) { 1786 list_for_each_entry_safe_continue(entry, next, &hcrx->ccid3hcrx_hist,
1848 u64 delta = dccp_delta_seqno(entry->ccid3hrx_seqno, packet->ccid3hrx_seqno); 1787 dccphrx_node) {
1788 u64 delta = dccp_delta_seqno(entry->dccphrx_seqno,
1789 packet->dccphrx_seqno);
1849 1790
1850 if (delta != 0) { 1791 if (delta != 0) {
1851 if (packet->ccid3hrx_type == DCCP_PKT_DATA || 1792 if (dccp_rx_hist_entry_data_packet(packet))
1852 packet->ccid3hrx_type == DCCP_PKT_DATAACK)
1853 --delta; 1793 --delta;
1854 /* 1794 /*
1855 * FIXME: check this, probably this % usage is because 1795 * FIXME: check this, probably this % usage is because
@@ -1858,10 +1798,12 @@ static void ccid3_hc_rx_detect_loss(struct sock *sk)
1858 */ 1798 */
1859#if 0 1799#if 0
1860 if (delta % DCCP_NDP_LIMIT != 1800 if (delta % DCCP_NDP_LIMIT !=
1861 (packet->ccid3hrx_ndp - entry->ccid3hrx_ndp) % DCCP_NDP_LIMIT) 1801 (packet->dccphrx_ndp -
1802 entry->dccphrx_ndp) % DCCP_NDP_LIMIT)
1862#endif 1803#endif
1863 if (delta != packet->ccid3hrx_ndp - entry->ccid3hrx_ndp) { 1804 if (delta !=
1864 seq_loss = entry->ccid3hrx_seqno; 1805 packet->dccphrx_ndp - entry->dccphrx_ndp) {
1806 seq_loss = entry->dccphrx_seqno;
1865 dccp_inc_seqno(&seq_loss); 1807 dccp_inc_seqno(&seq_loss);
1866 } 1808 }
1867 } 1809 }
@@ -1871,7 +1813,7 @@ static void ccid3_hc_rx_detect_loss(struct sock *sk)
1871 } 1813 }
1872 1814
1873 if (seq_loss != DCCP_MAX_SEQNO + 1) 1815 if (seq_loss != DCCP_MAX_SEQNO + 1)
1874 win_loss = a_loss->ccid3hrx_win_count; 1816 win_loss = a_loss->dccphrx_win_count;
1875 1817
1876out_update_li: 1818out_update_li:
1877 ccid3_hc_rx_update_li(sk, seq_loss, win_loss); 1819 ccid3_hc_rx_update_li(sk, seq_loss, win_loss);
@@ -1920,7 +1862,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
1920{ 1862{
1921 struct dccp_sock *dp = dccp_sk(sk); 1863 struct dccp_sock *dp = dccp_sk(sk);
1922 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; 1864 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
1923 struct ccid3_rx_hist_entry *packet; 1865 struct dccp_rx_hist_entry *packet;
1924 struct timeval now; 1866 struct timeval now;
1925 u8 win_count; 1867 u8 win_count;
1926 u32 p_prev; 1868 u32 p_prev;
@@ -1964,14 +1906,16 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
1964 return; 1906 return;
1965 } 1907 }
1966 1908
1967 packet = ccid3_rx_hist_entry_new(sk, skb, SLAB_ATOMIC); 1909 packet = dccp_rx_hist_entry_new(ccid3_rx_hist,
1910 dp->dccps_options_received.dccpor_ndp,
1911 skb, SLAB_ATOMIC);
1968 if (packet == NULL) { 1912 if (packet == NULL) {
1969 ccid3_pr_debug("%s, sk=%p, Not enough mem to add rx packet to history (consider it lost)!", 1913 ccid3_pr_debug("%s, sk=%p, Not enough mem to add rx packet to history (consider it lost)!",
1970 dccp_role(sk), sk); 1914 dccp_role(sk), sk);
1971 return; 1915 return;
1972 } 1916 }
1973 1917
1974 win_count = packet->ccid3hrx_win_count; 1918 win_count = packet->dccphrx_win_count;
1975 1919
1976 ins = ccid3_hc_rx_add_hist(sk, packet); 1920 ins = ccid3_hc_rx_add_hist(sk, packet);
1977 1921
@@ -2060,7 +2004,7 @@ static void ccid3_hc_rx_exit(struct sock *sk)
2060 ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM); 2004 ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);
2061 2005
2062 /* Empty packet history */ 2006 /* Empty packet history */
2063 ccid3_rx_history_delete(&hcrx->ccid3hcrx_hist); 2007 dccp_rx_hist_purge(ccid3_rx_hist, &hcrx->ccid3hcrx_hist);
2064 2008
2065 /* Empty loss interval history */ 2009 /* Empty loss interval history */
2066 ccid3_loss_interval_history_delete(&hcrx->ccid3hcrx_loss_interval_hist); 2010 ccid3_loss_interval_history_delete(&hcrx->ccid3hcrx_loss_interval_hist);
@@ -2093,41 +2037,38 @@ MODULE_PARM_DESC(ccid3_debug, "Enable debug messages");
2093 2037
2094static __init int ccid3_module_init(void) 2038static __init int ccid3_module_init(void)
2095{ 2039{
2096 int rc = -ENOMEM; 2040 int rc = -ENOBUFS;
2097 2041
2098 ccid3_tx_hist_slab = kmem_cache_create("dccp_ccid3_tx_history", 2042 ccid3_rx_hist = dccp_rx_hist_new("ccid3");
2099 sizeof(struct ccid3_tx_hist_entry), 0, 2043 if (ccid3_rx_hist == NULL)
2100 SLAB_HWCACHE_ALIGN, NULL, NULL);
2101 if (ccid3_tx_hist_slab == NULL)
2102 goto out; 2044 goto out;
2103 2045
2104 ccid3_rx_hist_slab = kmem_cache_create("dccp_ccid3_rx_history", 2046 ccid3_tx_hist = dccp_tx_hist_new("ccid3");
2105 sizeof(struct ccid3_rx_hist_entry), 0, 2047 if (ccid3_tx_hist == NULL)
2106 SLAB_HWCACHE_ALIGN, NULL, NULL); 2048 goto out_free_rx;
2107 if (ccid3_rx_hist_slab == NULL)
2108 goto out_free_tx_history;
2109 2049
2110 ccid3_loss_interval_hist_slab = kmem_cache_create("dccp_ccid3_loss_interval_history", 2050 ccid3_loss_interval_hist_slab = kmem_cache_create("li_hist_ccid3",
2111 sizeof(struct ccid3_loss_interval_hist_entry), 0, 2051 sizeof(struct ccid3_loss_interval_hist_entry),
2112 SLAB_HWCACHE_ALIGN, NULL, NULL); 2052 0, SLAB_HWCACHE_ALIGN,
2053 NULL, NULL);
2113 if (ccid3_loss_interval_hist_slab == NULL) 2054 if (ccid3_loss_interval_hist_slab == NULL)
2114 goto out_free_rx_history; 2055 goto out_free_tx;
2115 2056
2116 rc = ccid_register(&ccid3); 2057 rc = ccid_register(&ccid3);
2117 if (rc != 0) 2058 if (rc != 0)
2118 goto out_free_loss_interval_history; 2059 goto out_free_loss_interval_history;
2119
2120out: 2060out:
2121 return rc; 2061 return rc;
2062
2122out_free_loss_interval_history: 2063out_free_loss_interval_history:
2123 kmem_cache_destroy(ccid3_loss_interval_hist_slab); 2064 kmem_cache_destroy(ccid3_loss_interval_hist_slab);
2124 ccid3_loss_interval_hist_slab = NULL; 2065 ccid3_loss_interval_hist_slab = NULL;
2125out_free_rx_history: 2066out_free_tx:
2126 kmem_cache_destroy(ccid3_rx_hist_slab); 2067 dccp_tx_hist_delete(ccid3_tx_hist);
2127 ccid3_rx_hist_slab = NULL; 2068 ccid3_tx_hist = NULL;
2128out_free_tx_history: 2069out_free_rx:
2129 kmem_cache_destroy(ccid3_tx_hist_slab); 2070 dccp_rx_hist_delete(ccid3_rx_hist);
2130 ccid3_tx_hist_slab = NULL; 2071 ccid3_rx_hist = NULL;
2131 goto out; 2072 goto out;
2132} 2073}
2133module_init(ccid3_module_init); 2074module_init(ccid3_module_init);
@@ -2136,13 +2077,13 @@ static __exit void ccid3_module_exit(void)
2136{ 2077{
2137 ccid_unregister(&ccid3); 2078 ccid_unregister(&ccid3);
2138 2079
2139 if (ccid3_tx_hist_slab != NULL) { 2080 if (ccid3_tx_hist != NULL) {
2140 kmem_cache_destroy(ccid3_tx_hist_slab); 2081 dccp_tx_hist_delete(ccid3_tx_hist);
2141 ccid3_tx_hist_slab = NULL; 2082 ccid3_tx_hist = NULL;
2142 } 2083 }
2143 if (ccid3_rx_hist_slab != NULL) { 2084 if (ccid3_rx_hist != NULL) {
2144 kmem_cache_destroy(ccid3_rx_hist_slab); 2085 dccp_rx_hist_delete(ccid3_rx_hist);
2145 ccid3_rx_hist_slab = NULL; 2086 ccid3_rx_hist = NULL;
2146 } 2087 }
2147 if (ccid3_loss_interval_hist_slab != NULL) { 2088 if (ccid3_loss_interval_hist_slab != NULL) {
2148 kmem_cache_destroy(ccid3_loss_interval_hist_slab); 2089 kmem_cache_destroy(ccid3_loss_interval_hist_slab);
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 5d6b623e64da..d2705fb74195 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -38,15 +38,6 @@
38 38
39#include <linux/types.h> 39#include <linux/types.h>
40#include <linux/list.h> 40#include <linux/list.h>
41#include <linux/timer.h>
42
43struct ccid3_tx_hist_entry {
44 struct list_head ccid3htx_node;
45 u64 ccid3htx_seqno:48,
46 ccid3htx_win_count:8,
47 ccid3htx_sent:1;
48 struct timeval ccid3htx_tstamp;
49};
50 41
51struct ccid3_options_received { 42struct ccid3_options_received {
52 u64 ccid3or_seqno:48, 43 u64 ccid3or_seqno:48,
@@ -102,15 +93,6 @@ struct ccid3_loss_interval_hist_entry {
102 u32 ccid3lih_interval; 93 u32 ccid3lih_interval;
103}; 94};
104 95
105struct ccid3_rx_hist_entry {
106 struct list_head ccid3hrx_node;
107 u64 ccid3hrx_seqno:48,
108 ccid3hrx_win_count:4,
109 ccid3hrx_type:4;
110 u32 ccid3hrx_ndp; /* In fact it is from 8 to 24 bits */
111 struct timeval ccid3hrx_tstamp;
112};
113
114struct ccid3_hc_rx_sock { 96struct ccid3_hc_rx_sock {
115 u64 ccid3hcrx_seqno_last_counter:48, 97 u64 ccid3hcrx_seqno_last_counter:48,
116 ccid3hcrx_state:8, 98 ccid3hcrx_state:8,
diff --git a/net/dccp/packet_history.c b/net/dccp/packet_history.c
new file mode 100644
index 000000000000..6b414898f0c4
--- /dev/null
+++ b/net/dccp/packet_history.c
@@ -0,0 +1,198 @@
1/*
2 * net/dccp/packet_history.h
3 *
4 * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
5 *
6 * An implementation of the DCCP protocol
7 *
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/
10 * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz
11 *
12 * This code also uses code from Lulea University, rereleased as GPL by its
13 * authors:
14 * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
15 *
16 * Changes to meet Linux coding standards, to make it meet latest ccid3 draft
17 * and to make it work as a loadable module in the DCCP stack written by
18 * Arnaldo Carvalho de Melo <acme@conectiva.com.br>.
19 *
20 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
21 *
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 */
36
37#include <linux/config.h>
38#include <linux/string.h>
39
40#include "packet_history.h"
41
42struct dccp_rx_hist *dccp_rx_hist_new(const char *name)
43{
44 struct dccp_rx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
45 static const char dccp_rx_hist_mask[] = "rx_hist_%s";
46 char *slab_name;
47
48 if (hist == NULL)
49 goto out;
50
51 slab_name = kmalloc(strlen(name) + sizeof(dccp_rx_hist_mask) - 1,
52 GFP_ATOMIC);
53 if (slab_name == NULL)
54 goto out_free_hist;
55
56 sprintf(slab_name, dccp_rx_hist_mask, name);
57 hist->dccprxh_slab = kmem_cache_create(slab_name,
58 sizeof(struct dccp_rx_hist_entry),
59 0, SLAB_HWCACHE_ALIGN,
60 NULL, NULL);
61 if (hist->dccprxh_slab == NULL)
62 goto out_free_slab_name;
63out:
64 return hist;
65out_free_slab_name:
66 kfree(slab_name);
67out_free_hist:
68 kfree(hist);
69 hist = NULL;
70 goto out;
71}
72
73EXPORT_SYMBOL_GPL(dccp_rx_hist_new);
74
75void dccp_rx_hist_delete(struct dccp_rx_hist *hist)
76{
77 const char* name = kmem_cache_name(hist->dccprxh_slab);
78
79 kmem_cache_destroy(hist->dccprxh_slab);
80 kfree(name);
81 kfree(hist);
82}
83
84EXPORT_SYMBOL_GPL(dccp_rx_hist_delete);
85
86void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list)
87{
88 struct dccp_rx_hist_entry *entry, *next;
89
90 list_for_each_entry_safe(entry, next, list, dccphrx_node) {
91 list_del_init(&entry->dccphrx_node);
92 kmem_cache_free(hist->dccprxh_slab, entry);
93 }
94}
95
96EXPORT_SYMBOL_GPL(dccp_rx_hist_purge);
97
98struct dccp_rx_hist_entry *
99 dccp_rx_hist_find_data_packet(const struct list_head *list)
100{
101 struct dccp_rx_hist_entry *entry, *packet = NULL;
102
103 list_for_each_entry(entry, list, dccphrx_node)
104 if (entry->dccphrx_type == DCCP_PKT_DATA ||
105 entry->dccphrx_type == DCCP_PKT_DATAACK) {
106 packet = entry;
107 break;
108 }
109
110 return packet;
111}
112
113EXPORT_SYMBOL_GPL(dccp_rx_hist_find_data_packet);
114
115struct dccp_tx_hist *dccp_tx_hist_new(const char *name)
116{
117 struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC);
118 static const char dccp_tx_hist_mask[] = "tx_hist_%s";
119 char *slab_name;
120
121 if (hist == NULL)
122 goto out;
123
124 slab_name = kmalloc(strlen(name) + sizeof(dccp_tx_hist_mask) - 1,
125 GFP_ATOMIC);
126 if (slab_name == NULL)
127 goto out_free_hist;
128
129 sprintf(slab_name, dccp_tx_hist_mask, name);
130 hist->dccptxh_slab = kmem_cache_create(slab_name,
131 sizeof(struct dccp_tx_hist_entry),
132 0, SLAB_HWCACHE_ALIGN,
133 NULL, NULL);
134 if (hist->dccptxh_slab == NULL)
135 goto out_free_slab_name;
136out:
137 return hist;
138out_free_slab_name:
139 kfree(slab_name);
140out_free_hist:
141 kfree(hist);
142 hist = NULL;
143 goto out;
144}
145
146EXPORT_SYMBOL_GPL(dccp_tx_hist_new);
147
148void dccp_tx_hist_delete(struct dccp_tx_hist *hist)
149{
150 const char* name = kmem_cache_name(hist->dccptxh_slab);
151
152 kmem_cache_destroy(hist->dccptxh_slab);
153 kfree(name);
154 kfree(hist);
155}
156
157EXPORT_SYMBOL_GPL(dccp_tx_hist_delete);
158
159struct dccp_tx_hist_entry *dccp_tx_hist_find_entry(const struct list_head *list,
160 const u64 seq)
161{
162 struct dccp_tx_hist_entry *packet = NULL, *entry;
163
164 list_for_each_entry(entry, list, dccphtx_node)
165 if (entry->dccphtx_seqno == seq) {
166 packet = entry;
167 break;
168 }
169
170 return packet;
171}
172
173EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry);
174
175void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, struct list_head *list,
176 struct dccp_tx_hist_entry *packet)
177{
178 struct dccp_tx_hist_entry *next;
179
180 list_for_each_entry_safe_continue(packet, next, list, dccphtx_node) {
181 list_del_init(&packet->dccphtx_node);
182 dccp_tx_hist_entry_delete(hist, packet);
183 }
184}
185
186EXPORT_SYMBOL_GPL(dccp_tx_hist_purge_older);
187
188void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list)
189{
190 struct dccp_tx_hist_entry *entry, *next;
191
192 list_for_each_entry_safe(entry, next, list, dccphtx_node) {
193 list_del_init(&entry->dccphtx_node);
194 dccp_tx_hist_entry_delete(hist, entry);
195 }
196}
197
198EXPORT_SYMBOL_GPL(dccp_tx_hist_purge);
diff --git a/net/dccp/packet_history.h b/net/dccp/packet_history.h
new file mode 100644
index 000000000000..565dc96506e9
--- /dev/null
+++ b/net/dccp/packet_history.h
@@ -0,0 +1,182 @@
1/*
2 * net/dccp/packet_history.h
3 *
4 * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
5 *
6 * An implementation of the DCCP protocol
7 *
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/
10 * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz
11 *
12 * This code also uses code from Lulea University, rereleased as GPL by its
13 * authors:
14 * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
15 *
16 * Changes to meet Linux coding standards, to make it meet latest ccid3 draft
17 * and to make it work as a loadable module in the DCCP stack written by
18 * Arnaldo Carvalho de Melo <acme@conectiva.com.br>.
19 *
20 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
21 *
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 */
36
37#ifndef _DCCP_PKT_HIST_
38#define _DCCP_PKT_HIST_
39
40#include <linux/config.h>
41#include <linux/list.h>
42#include <linux/slab.h>
43#include <linux/time.h>
44
45#include "dccp.h"
46
47struct dccp_tx_hist_entry {
48 struct list_head dccphtx_node;
49 u64 dccphtx_seqno:48,
50 dccphtx_win_count:8,
51 dccphtx_sent:1;
52 struct timeval dccphtx_tstamp;
53};
54
55struct dccp_rx_hist_entry {
56 struct list_head dccphrx_node;
57 u64 dccphrx_seqno:48,
58 dccphrx_win_count:4,
59 dccphrx_type:4;
60 u32 dccphrx_ndp; /* In fact it is from 8 to 24 bits */
61 struct timeval dccphrx_tstamp;
62};
63
64struct dccp_tx_hist {
65 kmem_cache_t *dccptxh_slab;
66};
67
68extern struct dccp_tx_hist *dccp_tx_hist_new(const char *name);
69extern void dccp_tx_hist_delete(struct dccp_tx_hist *hist);
70
71struct dccp_rx_hist {
72 kmem_cache_t *dccprxh_slab;
73};
74
75extern struct dccp_rx_hist *dccp_rx_hist_new(const char *name);
76extern void dccp_rx_hist_delete(struct dccp_rx_hist *hist);
77extern struct dccp_rx_hist_entry *
78 dccp_rx_hist_find_data_packet(const struct list_head *list);
79
80static inline struct dccp_tx_hist_entry *
81 dccp_tx_hist_entry_new(struct dccp_tx_hist *hist,
82 const int prio)
83{
84 struct dccp_tx_hist_entry *entry = kmem_cache_alloc(hist->dccptxh_slab,
85 prio);
86
87 if (entry != NULL)
88 entry->dccphtx_sent = 0;
89
90 return entry;
91}
92
93static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist,
94 struct dccp_tx_hist_entry *entry)
95{
96 if (entry != NULL)
97 kmem_cache_free(hist->dccptxh_slab, entry);
98}
99
100extern struct dccp_tx_hist_entry *
101 dccp_tx_hist_find_entry(const struct list_head *list,
102 const u64 seq);
103
104static inline void dccp_tx_hist_add_entry(struct list_head *list,
105 struct dccp_tx_hist_entry *entry)
106{
107 list_add(&entry->dccphtx_node, list);
108}
109
110extern void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
111 struct list_head *list,
112 struct dccp_tx_hist_entry *next);
113
114extern void dccp_tx_hist_purge(struct dccp_tx_hist *hist,
115 struct list_head *list);
116
117static inline struct dccp_tx_hist_entry *dccp_tx_hist_head(struct list_head *list)
118{
119 struct dccp_tx_hist_entry *head = NULL;
120
121 if (!list_empty(list))
122 head = list_entry(list->next, struct dccp_tx_hist_entry,
123 dccphtx_node);
124 return head;
125}
126
127static inline struct dccp_rx_hist_entry *
128 dccp_rx_hist_entry_new(struct dccp_rx_hist *hist,
129 const u32 ndp,
130 const struct sk_buff *skb,
131 const int prio)
132{
133 struct dccp_rx_hist_entry *entry = kmem_cache_alloc(hist->dccprxh_slab,
134 prio);
135
136 if (entry != NULL) {
137 const struct dccp_hdr *dh = dccp_hdr(skb);
138
139 entry->dccphrx_seqno = DCCP_SKB_CB(skb)->dccpd_seq;
140 entry->dccphrx_win_count = dh->dccph_ccval;
141 entry->dccphrx_type = dh->dccph_type;
142 entry->dccphrx_ndp = ndp;
143 do_gettimeofday(&(entry->dccphrx_tstamp));
144 }
145
146 return entry;
147}
148
149static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist *hist,
150 struct dccp_rx_hist_entry *entry)
151{
152 if (entry != NULL)
153 kmem_cache_free(hist->dccprxh_slab, entry);
154}
155
156extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist,
157 struct list_head *list);
158
159static inline void dccp_rx_hist_add_entry(struct list_head *list,
160 struct dccp_rx_hist_entry *entry)
161{
162 list_add(&entry->dccphrx_node, list);
163}
164
165static inline struct dccp_rx_hist_entry *dccp_rx_hist_head(struct list_head *list)
166{
167 struct dccp_rx_hist_entry *head = NULL;
168
169 if (!list_empty(list))
170 head = list_entry(list->next, struct dccp_rx_hist_entry,
171 dccphrx_node);
172 return head;
173}
174
175static inline int
176 dccp_rx_hist_entry_data_packet(const struct dccp_rx_hist_entry *entry)
177{
178 return entry->dccphrx_type == DCCP_PKT_DATA ||
179 entry->dccphrx_type == DCCP_PKT_DATAACK;
180}
181
182#endif /* _DCCP_PKT_HIST_ */