1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2010 Rui Paulo <rpaulo@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 *
27 * $FreeBSD: releng/12.0/sys/net80211/ieee80211_ratectl.h 326272 2017-11-27 15:23:17Z pfg $
28 */
29
30enum ieee80211_ratealgs {
31	IEEE80211_RATECTL_AMRR		= 0,
32	IEEE80211_RATECTL_RSSADAPT	= 1,
33	IEEE80211_RATECTL_ONOE		= 2,
34	IEEE80211_RATECTL_SAMPLE	= 3,
35	IEEE80211_RATECTL_NONE		= 4,
36	IEEE80211_RATECTL_MAX
37};
38
39/* used fields for tx_complete() events */
40#define IEEE80211_RATECTL_STATUS_PKTLEN		0x00000001
41#define IEEE80211_RATECTL_STATUS_FINAL_RATE	0x00000002
42#define IEEE80211_RATECTL_STATUS_SHORT_RETRY	0x00000004
43#define IEEE80211_RATECTL_STATUS_LONG_RETRY	0x00000008
44#define IEEE80211_RATECTL_STATUS_RSSI		0x00000010
45
46/* failure reason */
47enum ieee80211_ratectl_tx_fail_reason {
48	IEEE80211_RATECTL_TX_SUCCESS		= 0,
49	IEEE80211_RATECTL_TX_FAIL_SHORT		= 1,	/* too many RTS retries */
50	IEEE80211_RATECTL_TX_FAIL_LONG		= 2,	/* too many retries */
51	IEEE80211_RATECTL_TX_FAIL_EXPIRED	= 3,	/* lifetime expired */
52	IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED	= 4,	/* another reason */
53};
54#define IEEE80211_RATECTL_TX_FAIL_MAX	\
55	(IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED + 1)
56
57struct ieee80211_ratectl_tx_status {
58	uint32_t	flags;		/* mark used fields */
59	enum ieee80211_ratectl_tx_fail_reason status;	/* Tx status */
60
61	int		pktlen;		/* frame length */
62	int		final_rate;	/* transmission rate */
63	uint_fast8_t	short_retries;	/* RTS/CTS retries */
64	uint_fast8_t	long_retries;	/* ACK retries */
65	int8_t		rssi;		/* ACK RSSI */
66
67	uint8_t		spare[15];	/* for future use */
68};
69
70/* used fields for tx_update() events */
71#define IEEE80211_RATECTL_TX_STATS_NODE		0x00000001
72#define IEEE80211_RATECTL_TX_STATS_RETRIES	0x00000002
73
74struct ieee80211_ratectl_tx_stats {
75	uint32_t	flags;		/* mark used fields */
76
77	struct ieee80211_node *ni;	/* receiver */
78	int		nframes;	/* transmitted frames */
79	int		nsuccess;	/* ACKed frames */
80	int		nretries;	/* number of retries */
81};
82
83struct ieee80211_ratectl {
84	const char *ir_name;
85	int	(*ir_attach)(const struct ieee80211vap *);
86	void	(*ir_detach)(const struct ieee80211vap *);
87	void	(*ir_init)(struct ieee80211vap *);
88	void	(*ir_deinit)(struct ieee80211vap *);
89	void	(*ir_node_init)(struct ieee80211_node *);
90	void	(*ir_node_deinit)(struct ieee80211_node *);
91	int	(*ir_rate)(struct ieee80211_node *, void *, uint32_t);
92	void	(*ir_tx_complete)(const struct ieee80211_node *,
93	    			  const struct ieee80211_ratectl_tx_status *);
94	void	(*ir_tx_update)(struct ieee80211vap *,
95				struct ieee80211_ratectl_tx_stats *);
96	void	(*ir_setinterval)(const struct ieee80211vap *, int);
97	void	(*ir_node_stats)(struct ieee80211_node *ni, struct sbuf *s);
98};
99
100void	ieee80211_ratectl_register(int, const struct ieee80211_ratectl *);
101void	ieee80211_ratectl_unregister(int);
102void	ieee80211_ratectl_init(struct ieee80211vap *);
103void	ieee80211_ratectl_set(struct ieee80211vap *, int);
104
105MALLOC_DECLARE(M_80211_RATECTL);
106
107static __inline void
108ieee80211_ratectl_deinit(struct ieee80211vap *vap)
109{
110	vap->iv_rate->ir_deinit(vap);
111}
112
113static __inline void
114ieee80211_ratectl_node_init(struct ieee80211_node *ni)
115{
116	const struct ieee80211vap *vap = ni->ni_vap;
117
118	vap->iv_rate->ir_node_init(ni);
119}
120
121static __inline void
122ieee80211_ratectl_node_deinit(struct ieee80211_node *ni)
123{
124	const struct ieee80211vap *vap = ni->ni_vap;
125
126	vap->iv_rate->ir_node_deinit(ni);
127}
128
129static int __inline
130ieee80211_ratectl_rate(struct ieee80211_node *ni, void *arg, uint32_t iarg)
131{
132	const struct ieee80211vap *vap = ni->ni_vap;
133
134	return vap->iv_rate->ir_rate(ni, arg, iarg);
135}
136
137static __inline void
138ieee80211_ratectl_tx_complete(const struct ieee80211_node *ni,
139    const struct ieee80211_ratectl_tx_status *status)
140{
141	const struct ieee80211vap *vap = ni->ni_vap;
142
143	vap->iv_rate->ir_tx_complete(ni, status);
144}
145
146static __inline void
147ieee80211_ratectl_tx_update(struct ieee80211vap *vap,
148    struct ieee80211_ratectl_tx_stats *stats)
149{
150	if (vap->iv_rate->ir_tx_update == NULL)
151		return;
152	vap->iv_rate->ir_tx_update(vap, stats);
153}
154
155static __inline void
156ieee80211_ratectl_setinterval(const struct ieee80211vap *vap, int msecs)
157{
158	if (vap->iv_rate->ir_setinterval == NULL)
159		return;
160	vap->iv_rate->ir_setinterval(vap, msecs);
161}
162
163static __inline void
164ieee80211_ratectl_node_stats(struct ieee80211_node *ni, struct sbuf *s)
165{
166	const struct ieee80211vap *vap = ni->ni_vap;
167
168	if (vap->iv_rate->ir_node_stats == NULL)
169		return;
170	vap->iv_rate->ir_node_stats(ni, s);
171}
172