diff options
Diffstat (limited to 'net/dccp')
-rw-r--r-- | net/dccp/Makefile | 3 | ||||
-rw-r--r-- | net/dccp/ccids/ccid3.c | 327 | ||||
-rw-r--r-- | net/dccp/ccids/ccid3.h | 18 | ||||
-rw-r--r-- | net/dccp/packet_history.c | 198 | ||||
-rw-r--r-- | net/dccp/packet_history.h | 182 |
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 @@ | |||
1 | obj-$(CONFIG_IP_DCCP) += dccp.o | 1 | obj-$(CONFIG_IP_DCCP) += dccp.o |
2 | 2 | ||
3 | dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o timer.o | 3 | dccp-y := ccid.o input.o ipv4.o minisocks.o options.o output.o proto.o \ |
4 | timer.o packet_history.o | ||
4 | 5 | ||
5 | obj-y += ccids/ | 6 | obj-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 | ||
83 | static int ccid3_debug; | 85 | static int ccid3_debug; |
84 | 86 | ||
85 | static kmem_cache_t *ccid3_tx_hist_slab; | 87 | struct dccp_tx_hist *ccid3_tx_hist; |
86 | static kmem_cache_t *ccid3_rx_hist_slab; | 88 | struct dccp_rx_hist *ccid3_rx_hist; |
87 | static kmem_cache_t *ccid3_loss_interval_hist_slab; | ||
88 | |||
89 | static 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 | |||
99 | static 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 | |||
105 | static 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 | |||
124 | static 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 | ||
130 | static void ccid3_rx_history_delete(struct list_head *hist) | 90 | static 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 | ||
140 | static inline struct ccid3_loss_interval_hist_entry *ccid3_loss_interval_hist_entry_new(int prio) | 92 | static 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; | ||
1058 | out: | 1009 | out: |
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 | ||
1465 | static int ccid3_hc_rx_add_hist(struct sock *sk, struct ccid3_rx_hist_entry *packet) | 1409 | static 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 | } |
1730 | found: | 1670 | found: |
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 | ||
1876 | out_update_li: | 1818 | out_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 | ||
2094 | static __init int ccid3_module_init(void) | 2038 | static __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 | |||
2120 | out: | 2060 | out: |
2121 | return rc; | 2061 | return rc; |
2062 | |||
2122 | out_free_loss_interval_history: | 2063 | out_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; |
2125 | out_free_rx_history: | 2066 | out_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; |
2128 | out_free_tx_history: | 2069 | out_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 | } |
2133 | module_init(ccid3_module_init); | 2074 | module_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 | |||
43 | struct 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 | ||
51 | struct ccid3_options_received { | 42 | struct 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 | ||
105 | struct 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 | |||
114 | struct ccid3_hc_rx_sock { | 96 | struct 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 | |||
42 | struct 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; | ||
63 | out: | ||
64 | return hist; | ||
65 | out_free_slab_name: | ||
66 | kfree(slab_name); | ||
67 | out_free_hist: | ||
68 | kfree(hist); | ||
69 | hist = NULL; | ||
70 | goto out; | ||
71 | } | ||
72 | |||
73 | EXPORT_SYMBOL_GPL(dccp_rx_hist_new); | ||
74 | |||
75 | void 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 | |||
84 | EXPORT_SYMBOL_GPL(dccp_rx_hist_delete); | ||
85 | |||
86 | void 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 | |||
96 | EXPORT_SYMBOL_GPL(dccp_rx_hist_purge); | ||
97 | |||
98 | struct 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 | |||
113 | EXPORT_SYMBOL_GPL(dccp_rx_hist_find_data_packet); | ||
114 | |||
115 | struct 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; | ||
136 | out: | ||
137 | return hist; | ||
138 | out_free_slab_name: | ||
139 | kfree(slab_name); | ||
140 | out_free_hist: | ||
141 | kfree(hist); | ||
142 | hist = NULL; | ||
143 | goto out; | ||
144 | } | ||
145 | |||
146 | EXPORT_SYMBOL_GPL(dccp_tx_hist_new); | ||
147 | |||
148 | void 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 | |||
157 | EXPORT_SYMBOL_GPL(dccp_tx_hist_delete); | ||
158 | |||
159 | struct 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 | |||
173 | EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry); | ||
174 | |||
175 | void 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 | |||
186 | EXPORT_SYMBOL_GPL(dccp_tx_hist_purge_older); | ||
187 | |||
188 | void 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 | |||
198 | EXPORT_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 | |||
47 | struct 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 | |||
55 | struct 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 | |||
64 | struct dccp_tx_hist { | ||
65 | kmem_cache_t *dccptxh_slab; | ||
66 | }; | ||
67 | |||
68 | extern struct dccp_tx_hist *dccp_tx_hist_new(const char *name); | ||
69 | extern void dccp_tx_hist_delete(struct dccp_tx_hist *hist); | ||
70 | |||
71 | struct dccp_rx_hist { | ||
72 | kmem_cache_t *dccprxh_slab; | ||
73 | }; | ||
74 | |||
75 | extern struct dccp_rx_hist *dccp_rx_hist_new(const char *name); | ||
76 | extern void dccp_rx_hist_delete(struct dccp_rx_hist *hist); | ||
77 | extern struct dccp_rx_hist_entry * | ||
78 | dccp_rx_hist_find_data_packet(const struct list_head *list); | ||
79 | |||
80 | static 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 | |||
93 | static 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 | |||
100 | extern struct dccp_tx_hist_entry * | ||
101 | dccp_tx_hist_find_entry(const struct list_head *list, | ||
102 | const u64 seq); | ||
103 | |||
104 | static 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 | |||
110 | extern void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, | ||
111 | struct list_head *list, | ||
112 | struct dccp_tx_hist_entry *next); | ||
113 | |||
114 | extern void dccp_tx_hist_purge(struct dccp_tx_hist *hist, | ||
115 | struct list_head *list); | ||
116 | |||
117 | static 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 | |||
127 | static 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 | |||
149 | static 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 | |||
156 | extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist, | ||
157 | struct list_head *list); | ||
158 | |||
159 | static 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 | |||
165 | static 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 | |||
175 | static 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_ */ | ||