17931287dSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
24524b259SArnaldo Carvalho de Melo /*
3276f2edcSArnaldo Carvalho de Melo  *  Packet RX/TX history data structures and routines for TFRC-based protocols.
44524b259SArnaldo Carvalho de Melo  *
5276f2edcSArnaldo Carvalho de Melo  *  Copyright (c) 2007   The University of Aberdeen, Scotland, UK
6e6bccd35SIan McDonald  *  Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand.
74524b259SArnaldo Carvalho de Melo  *
84524b259SArnaldo Carvalho de Melo  *  This code has been developed by the University of Waikato WAND
9266f3128SAlexander A. Klimov  *  research group. For further information please see https://www.wand.net.nz/
10e6bccd35SIan McDonald  *  or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz
114524b259SArnaldo Carvalho de Melo  *
124524b259SArnaldo Carvalho de Melo  *  This code also uses code from Lulea University, rereleased as GPL by its
134524b259SArnaldo Carvalho de Melo  *  authors:
144524b259SArnaldo Carvalho de Melo  *  Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon
154524b259SArnaldo Carvalho de Melo  *
164524b259SArnaldo Carvalho de Melo  *  Changes to meet Linux coding standards, to make it meet latest ccid3 draft
174524b259SArnaldo Carvalho de Melo  *  and to make it work as a loadable module in the DCCP stack written by
184524b259SArnaldo Carvalho de Melo  *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>.
194524b259SArnaldo Carvalho de Melo  *
204524b259SArnaldo Carvalho de Melo  *  Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
214524b259SArnaldo Carvalho de Melo  */
224524b259SArnaldo Carvalho de Melo 
234524b259SArnaldo Carvalho de Melo #ifndef _DCCP_PKT_HIST_
244524b259SArnaldo Carvalho de Melo #define _DCCP_PKT_HIST_
254524b259SArnaldo Carvalho de Melo 
268a9c7e92SGerrit Renker #include <linux/list.h>
278a9c7e92SGerrit Renker #include <linux/slab.h>
288a9c7e92SGerrit Renker #include "tfrc.h"
29072ab6c6SArnaldo Carvalho de Melo 
30d2c72630SGerrit Renker /**
31d2c72630SGerrit Renker  *  tfrc_tx_hist_entry  -  Simple singly-linked TX history list
32d2c72630SGerrit Renker  *  @next:  next oldest entry (LIFO order)
33d2c72630SGerrit Renker  *  @seqno: sequence number of this entry
34d2c72630SGerrit Renker  *  @stamp: send time of packet with sequence number @seqno
35d2c72630SGerrit Renker  */
36d2c72630SGerrit Renker struct tfrc_tx_hist_entry {
37d2c72630SGerrit Renker 	struct tfrc_tx_hist_entry *next;
38d2c72630SGerrit Renker 	u64			  seqno;
39d2c72630SGerrit Renker 	ktime_t			  stamp;
40d2c72630SGerrit Renker };
41d2c72630SGerrit Renker 
42d2c72630SGerrit Renker static inline struct tfrc_tx_hist_entry *
tfrc_tx_hist_find_entry(struct tfrc_tx_hist_entry * head,u64 seqno)43d2c72630SGerrit Renker 	tfrc_tx_hist_find_entry(struct tfrc_tx_hist_entry *head, u64 seqno)
44d2c72630SGerrit Renker {
45d2c72630SGerrit Renker 	while (head != NULL && head->seqno != seqno)
46d2c72630SGerrit Renker 		head = head->next;
47d2c72630SGerrit Renker 	return head;
48d2c72630SGerrit Renker }
494524b259SArnaldo Carvalho de Melo 
50a402a5aaSJoe Perches int tfrc_tx_hist_add(struct tfrc_tx_hist_entry **headp, u64 seqno);
51a402a5aaSJoe Perches void tfrc_tx_hist_purge(struct tfrc_tx_hist_entry **headp);
5285dcb1f7SGerrit Renker 
53b84a2189SArnaldo Carvalho de Melo /* Subtraction a-b modulo-16, respects circular wrap-around */
54b84a2189SArnaldo Carvalho de Melo #define SUB16(a, b) (((a) + 16 - (b)) & 0xF)
55b84a2189SArnaldo Carvalho de Melo 
56b84a2189SArnaldo Carvalho de Melo /* Number of packets to wait after a missing packet (RFC 4342, 6.1) */
57b84a2189SArnaldo Carvalho de Melo #define TFRC_NDUPACK 3
58b84a2189SArnaldo Carvalho de Melo 
59b84a2189SArnaldo Carvalho de Melo /**
60b84a2189SArnaldo Carvalho de Melo  * tfrc_rx_hist_entry - Store information about a single received packet
61b84a2189SArnaldo Carvalho de Melo  * @tfrchrx_seqno:	DCCP packet sequence number
62b84a2189SArnaldo Carvalho de Melo  * @tfrchrx_ccval:	window counter value of packet (RFC 4342, 8.1)
63b84a2189SArnaldo Carvalho de Melo  * @tfrchrx_ndp:	the NDP count (if any) of the packet
64b84a2189SArnaldo Carvalho de Melo  * @tfrchrx_tstamp:	actual receive time of packet
6585dcb1f7SGerrit Renker  */
66d58d1af0SArnaldo Carvalho de Melo struct tfrc_rx_hist_entry {
67d58d1af0SArnaldo Carvalho de Melo 	u64		 tfrchrx_seqno:48,
68d58d1af0SArnaldo Carvalho de Melo 			 tfrchrx_ccval:4,
69d58d1af0SArnaldo Carvalho de Melo 			 tfrchrx_type:4;
705b5d0e70SGerrit Renker 	u64		 tfrchrx_ndp:48;
71d58d1af0SArnaldo Carvalho de Melo 	ktime_t		 tfrchrx_tstamp;
7285dcb1f7SGerrit Renker };
7385dcb1f7SGerrit Renker 
74b84a2189SArnaldo Carvalho de Melo /**
75b84a2189SArnaldo Carvalho de Melo  * tfrc_rx_hist  -  RX history structure for TFRC-based protocols
76b84a2189SArnaldo Carvalho de Melo  * @ring:		Packet history for RTT sampling and loss detection
77b84a2189SArnaldo Carvalho de Melo  * @loss_count:		Number of entries in circular history
78b84a2189SArnaldo Carvalho de Melo  * @loss_start:		Movable index (for loss detection)
79b84a2189SArnaldo Carvalho de Melo  * @rtt_sample_prev:	Used during RTT sampling, points to candidate entry
80b84a2189SArnaldo Carvalho de Melo  */
81b84a2189SArnaldo Carvalho de Melo struct tfrc_rx_hist {
82b84a2189SArnaldo Carvalho de Melo 	struct tfrc_rx_hist_entry *ring[TFRC_NDUPACK + 1];
83b84a2189SArnaldo Carvalho de Melo 	u8			  loss_count:2,
84b84a2189SArnaldo Carvalho de Melo 				  loss_start:2;
85b84a2189SArnaldo Carvalho de Melo #define rtt_sample_prev		  loss_start
86b84a2189SArnaldo Carvalho de Melo };
874524b259SArnaldo Carvalho de Melo 
888995a238SGerrit Renker /**
898995a238SGerrit Renker  * tfrc_rx_hist_index - index to reach n-th entry after loss_start
908995a238SGerrit Renker  */
tfrc_rx_hist_index(const struct tfrc_rx_hist * h,const u8 n)918995a238SGerrit Renker static inline u8 tfrc_rx_hist_index(const struct tfrc_rx_hist *h, const u8 n)
928995a238SGerrit Renker {
938995a238SGerrit Renker 	return (h->loss_start + n) & TFRC_NDUPACK;
948995a238SGerrit Renker }
958995a238SGerrit Renker 
968995a238SGerrit Renker /**
978995a238SGerrit Renker  * tfrc_rx_hist_last_rcv - entry with highest-received-seqno so far
988995a238SGerrit Renker  */
998995a238SGerrit Renker static inline struct tfrc_rx_hist_entry *
tfrc_rx_hist_last_rcv(const struct tfrc_rx_hist * h)1008995a238SGerrit Renker 			tfrc_rx_hist_last_rcv(const struct tfrc_rx_hist *h)
1018995a238SGerrit Renker {
1028995a238SGerrit Renker 	return h->ring[tfrc_rx_hist_index(h, h->loss_count)];
1038995a238SGerrit Renker }
1048995a238SGerrit Renker 
1058995a238SGerrit Renker /**
1068995a238SGerrit Renker  * tfrc_rx_hist_entry - return the n-th history entry after loss_start
1078995a238SGerrit Renker  */
1088995a238SGerrit Renker static inline struct tfrc_rx_hist_entry *
tfrc_rx_hist_entry(const struct tfrc_rx_hist * h,const u8 n)1098995a238SGerrit Renker 			tfrc_rx_hist_entry(const struct tfrc_rx_hist *h, const u8 n)
1108995a238SGerrit Renker {
1118995a238SGerrit Renker 	return h->ring[tfrc_rx_hist_index(h, n)];
1128995a238SGerrit Renker }
1138995a238SGerrit Renker 
1148995a238SGerrit Renker /**
1158995a238SGerrit Renker  * tfrc_rx_hist_loss_prev - entry with highest-received-seqno before loss was detected
1168995a238SGerrit Renker  */
1178995a238SGerrit Renker static inline struct tfrc_rx_hist_entry *
tfrc_rx_hist_loss_prev(const struct tfrc_rx_hist * h)1188995a238SGerrit Renker 			tfrc_rx_hist_loss_prev(const struct tfrc_rx_hist *h)
1198995a238SGerrit Renker {
1208995a238SGerrit Renker 	return h->ring[h->loss_start];
1218995a238SGerrit Renker }
1228995a238SGerrit Renker 
123de0d411cSGerrit Renker /* indicate whether previously a packet was detected missing */
tfrc_rx_hist_loss_pending(const struct tfrc_rx_hist * h)124b552c623SGerrit Renker static inline bool tfrc_rx_hist_loss_pending(const struct tfrc_rx_hist *h)
125de0d411cSGerrit Renker {
126b552c623SGerrit Renker 	return h->loss_count > 0;
127de0d411cSGerrit Renker }
128de0d411cSGerrit Renker 
129a402a5aaSJoe Perches void tfrc_rx_hist_add_packet(struct tfrc_rx_hist *h, const struct sk_buff *skb,
130a402a5aaSJoe Perches 			     const u64 ndp);
1314524b259SArnaldo Carvalho de Melo 
132a402a5aaSJoe Perches int tfrc_rx_hist_duplicate(struct tfrc_rx_hist *h, struct sk_buff *skb);
133de0d411cSGerrit Renker 
1348a9c7e92SGerrit Renker struct tfrc_loss_hist;
135a402a5aaSJoe Perches int tfrc_rx_handle_loss(struct tfrc_rx_hist *h, struct tfrc_loss_hist *lh,
1365b5d0e70SGerrit Renker 			struct sk_buff *skb, const u64 ndp,
137a402a5aaSJoe Perches 			u32 (*first_li)(struct sock *sk), struct sock *sk);
138a402a5aaSJoe Perches u32 tfrc_rx_hist_sample_rtt(struct tfrc_rx_hist *h, const struct sk_buff *skb);
139a402a5aaSJoe Perches int tfrc_rx_hist_alloc(struct tfrc_rx_hist *h);
140a402a5aaSJoe Perches void tfrc_rx_hist_purge(struct tfrc_rx_hist *h);
14129e4f8b3SArnaldo Carvalho de Melo 
1424524b259SArnaldo Carvalho de Melo #endif /* _DCCP_PKT_HIST_ */
143