: New RX history implementation
PATCH 8/16 : New RX history implementation
This provides a new, self-contained and generic RX history service for TFRC based protocols.
Details:
* new data structure, initialisation and cleanup routines;
* allocation of dccp_rx_hist entries local to packet_history.c, as a service exported by the dccp_tfrc_lib module.
* interface to automatically track highest-received seqno;
* receiver-based RTT estimation (needed for instance by RFC 3448, 6.3.1);
* a generic function to test for `data packets' as per RFC 4340, sec. 7.7.
Signed-off-by Gerrit Renker <[email protected]>
Signed-off-by Ian McDonald <[email protected]>
--- net/dccp/ccids/lib/packet_history.c | 98 +++++++++++++++++++++++- net/dccp/ccids/lib/packet_history.h | 143 ++++++++++++++++++++++++++++++++++- net/dccp/ccids/lib/tfrc_module.c | 7 ++ net/dccp/dccp.h | 12 +++ 4 files changed, 255 insertions(+), 5 deletions(-)
net/dccp/ccids/lib/packet_history.c +97 -1
@@ -34,7 +34,6 @@* along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <linux/string.h> #include "packet_history.h"
@@ -289,6 +288,33 @@ void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist,EXPORT_SYMBOL_GPL (dccp_rx_hist_add_packet); +static struct kmem_cache *tfrcxh; + +int tfrc_rx_hist_init (struct tfrc_rx_hist *h) +{ +int i; + +for (i =0 ; i <=NDUPACK ; i++) { + h->ring[i] =kmem_cache_alloc (tfrcxh,GFP_ATOMIC ); +if (h->ring[i] =NULL ) +return 1 ; + } + h->loss_count =0 ; + h->loss_start =0 ; +return 0 ; +} +EXPORT_SYMBOL_GPL (tfrc_rx_hist_init); + +void tfrc_rx_hist_cleanup (struct tfrc_rx_hist *h) +{ +int i; + +for (i=0 ; i <=NDUPACK ; i++) +if (h->ring[i] !=NULL ) +kmem_cache_free (tfrcxh, h->ring[i]); +} +EXPORT_SYMBOL_GPL (tfrc_rx_hist_cleanup); +void dccp_rx_hist_purge (struct dccp_rx_hist *hist,struct list_head *list) {struct dccp_rx_hist_entry *entry, *next;
@@ -300,3 +326,73 @@ void dccp_rx_hist_purge(struct dccp_rx_hist *hist, struct list_head *list) }EXPORT_SYMBOL_GPL (dccp_rx_hist_purge); + +/** +* tfrc_rx_sample_rtt - Sample RTT from timestamp / CCVal +* Based on ideas presented in RFC 4342, 8.1. Returns 0 if it was not able +* to compute a sample with given data - calling function should check this. +*/ +u32 tfrc_rx_sample_rtt (struct tfrc_rx_hist *h,struct sk_buff *skb) +{ +u32 sample =0 , + delta_v =SUB16 (dccp_hdr (skb)->dccph_ccval,rtt_last_s (h)->ccval); + +if (delta_v <1 || delta_v >4 ) {/* unsuitable CCVal delta */ + +if (h->rtt_sample_prev =2 ) {/* previous candidate stored */ + sample =SUB16 (rtt_prev_s (h)->ccval, +rtt_last_s (h)->ccval); +if (sample) + sample =4 / sample + *ktime_us_delta (rtt_prev_s (h)->stamp, +rtt_last_s (h)->stamp); +else /* +* FIXME: This condition is in principle not +* possible but occurs when CCID is used for +* two-way data traffic. I have tried to trace +* it, but the cause does not seem to be here. +*/ +DCCP_BUG ("please report to [email protected]" +" => prev = %u, last = %u" , +rtt_prev_s (h)->ccval, +rtt_last_s (h)->ccval); + }else if (delta_v <1 ) { + h->rtt_sample_prev =1 ; + goto keep_ref_for_next_time; + } + + }else if (delta_v =4 ) {/* optimal match */ + sample =ktime_to_us (net_timedelta (rtt_last_s (h)->stamp)); + + }else {/* suboptimal match */ + h->rtt_sample_prev =2 ; + goto keep_ref_for_next_time; + } + +if (unlikely (sample >DCCP_SANE_RTT_MAX )) { +DCCP_WARN ("RTT sample %u too large, using max\n" , sample); + sample =DCCP_SANE_RTT_MAX ; + } + + h->rtt_sample_prev =0 ;/* use current entry as next reference */ +keep_ref_for_next_time: + +return sample; +} +EXPORT_SYMBOL_GPL (tfrc_rx_sample_rtt); + +/* Module initialisation and cleanup routines */ +int __init packet_history_init (void ) +{ + tfrcxh =kmem_cache_create ("tfrc_rx_hist" , +sizeof (struct tfrc_rx_hist_entry ), +0 ,SLAB_HWCACHE_ALIGN ,NULL ); + +return tfrcxh =NULL ? -ENOBUFS :0 ; +} + +void __exit packet_history_cleanup(void) +{ +if (tfrcxh !=NULL ) +kmem_cache_destroy (tfrcxh); +}
net/dccp/ccids/lib/packet_history.h +139 -4
173 lines not on this page · raw message
net/dccp/ccids/lib/tfrc_module.c +7 -0
@@ -7,18 +7,25 @@#include <linux/moduleparam.h> #include "tfrc.h" +/* Initialisation / Clean-up routines */ extern int dccp_li_init (void );extern void dccp_li_exit (void ); +extern int packet_history_init (void ); +extern void packet_history_cleanup (void );static int __init tfrc_module_init (void ) {int rc =dccp_li_init (); +if (rc =0 ) + rc =packet_history_init (); +return rc; } static void __exit tfrc_module_exit(void) { +packet_history_cleanup ();dccp_li_exit (); }
net/dccp/dccp.h +12 -0
@@ -334,6 +334,7 @@ struct dccp_skb_cb {#define DCCP_SKB_CB (__skb) ((struct dccp_skb_cb *)&((__skb)->cb[0])) +/* RFC 4340, sec. 7.7 */ static inline int dccp_non_data_packet (const struct sk_buff *skb) {const __u8 type =DCCP_SKB_CB (skb)->dccpd_type;
@@ -346,6 +347,17 @@ static inline int dccp_non_data_packet(const struct sk_buff *skb) type =DCCP_PKT_SYNCACK ; } +/* RFC 4340, sec. 7.7 */ +static inline int dccp_data_packet (const struct sk_buff *skb) +{ +const __u8 type =DCCP_SKB_CB (skb)->dccpd_type; + +return type =DCCP_PKT_DATA || + type =DCCP_PKT_DATAACK || + type =DCCP_PKT_REQUEST || + type =DCCP_PKT_RESPONSE ; +} +static inline int dccp_packet_without_ack (const struct sk_buff *skb) {const __u8 type =DCCP_SKB_CB (skb)->dccpd_type;
Signature · 1 line
1.5.2.2.238.g7cbf2f2-dirty