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
9*266f3128SAlexander 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