aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp')
-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
5 files changed, 516 insertions, 212 deletions
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_ */