xref: /OK3568_Linux_fs/kernel/net/dccp/ccid.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */
2*4882a593Smuzhiyun #ifndef _CCID_H
3*4882a593Smuzhiyun #define _CCID_H
4*4882a593Smuzhiyun /*
5*4882a593Smuzhiyun  *  net/dccp/ccid.h
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  *  An implementation of the DCCP protocol
8*4882a593Smuzhiyun  *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  *  CCID infrastructure
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #include <net/sock.h>
14*4882a593Smuzhiyun #include <linux/compiler.h>
15*4882a593Smuzhiyun #include <linux/dccp.h>
16*4882a593Smuzhiyun #include <linux/list.h>
17*4882a593Smuzhiyun #include <linux/module.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /* maximum value for a CCID (RFC 4340, 19.5) */
20*4882a593Smuzhiyun #define CCID_MAX		255
21*4882a593Smuzhiyun #define CCID_SLAB_NAME_LENGTH	32
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun struct tcp_info;
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun /**
26*4882a593Smuzhiyun  *  struct ccid_operations  -  Interface to Congestion-Control Infrastructure
27*4882a593Smuzhiyun  *
28*4882a593Smuzhiyun  *  @ccid_id: numerical CCID ID (up to %CCID_MAX, cf. table 5 in RFC 4340, 10.)
29*4882a593Smuzhiyun  *  @ccid_ccmps: the CCMPS including network/transport headers (0 when disabled)
30*4882a593Smuzhiyun  *  @ccid_name: alphabetical identifier string for @ccid_id
31*4882a593Smuzhiyun  *  @ccid_hc_{r,t}x_slab: memory pool for the receiver/sender half-connection
32*4882a593Smuzhiyun  *  @ccid_hc_{r,t}x_obj_size: size of the receiver/sender half-connection socket
33*4882a593Smuzhiyun  *
34*4882a593Smuzhiyun  *  @ccid_hc_{r,t}x_init: CCID-specific initialisation routine (before startup)
35*4882a593Smuzhiyun  *  @ccid_hc_{r,t}x_exit: CCID-specific cleanup routine (before destruction)
36*4882a593Smuzhiyun  *  @ccid_hc_rx_packet_recv: implements the HC-receiver side
37*4882a593Smuzhiyun  *  @ccid_hc_{r,t}x_parse_options: parsing routine for CCID/HC-specific options
38*4882a593Smuzhiyun  *  @ccid_hc_{r,t}x_insert_options: insert routine for CCID/HC-specific options
39*4882a593Smuzhiyun  *  @ccid_hc_tx_packet_recv: implements feedback processing for the HC-sender
40*4882a593Smuzhiyun  *  @ccid_hc_tx_send_packet: implements the sending part of the HC-sender
41*4882a593Smuzhiyun  *  @ccid_hc_tx_packet_sent: does accounting for packets in flight by HC-sender
42*4882a593Smuzhiyun  *  @ccid_hc_{r,t}x_get_info: INET_DIAG information for HC-receiver/sender
43*4882a593Smuzhiyun  *  @ccid_hc_{r,t}x_getsockopt: socket options specific to HC-receiver/sender
44*4882a593Smuzhiyun  */
45*4882a593Smuzhiyun struct ccid_operations {
46*4882a593Smuzhiyun 	unsigned char		ccid_id;
47*4882a593Smuzhiyun 	__u32			ccid_ccmps;
48*4882a593Smuzhiyun 	const char		*ccid_name;
49*4882a593Smuzhiyun 	struct kmem_cache	*ccid_hc_rx_slab,
50*4882a593Smuzhiyun 				*ccid_hc_tx_slab;
51*4882a593Smuzhiyun 	char			ccid_hc_rx_slab_name[CCID_SLAB_NAME_LENGTH];
52*4882a593Smuzhiyun 	char			ccid_hc_tx_slab_name[CCID_SLAB_NAME_LENGTH];
53*4882a593Smuzhiyun 	__u32			ccid_hc_rx_obj_size,
54*4882a593Smuzhiyun 				ccid_hc_tx_obj_size;
55*4882a593Smuzhiyun 	/* Interface Routines */
56*4882a593Smuzhiyun 	int		(*ccid_hc_rx_init)(struct ccid *ccid, struct sock *sk);
57*4882a593Smuzhiyun 	int		(*ccid_hc_tx_init)(struct ccid *ccid, struct sock *sk);
58*4882a593Smuzhiyun 	void		(*ccid_hc_rx_exit)(struct sock *sk);
59*4882a593Smuzhiyun 	void		(*ccid_hc_tx_exit)(struct sock *sk);
60*4882a593Smuzhiyun 	void		(*ccid_hc_rx_packet_recv)(struct sock *sk,
61*4882a593Smuzhiyun 						  struct sk_buff *skb);
62*4882a593Smuzhiyun 	int		(*ccid_hc_rx_parse_options)(struct sock *sk, u8 pkt,
63*4882a593Smuzhiyun 						    u8 opt, u8 *val, u8 len);
64*4882a593Smuzhiyun 	int		(*ccid_hc_rx_insert_options)(struct sock *sk,
65*4882a593Smuzhiyun 						     struct sk_buff *skb);
66*4882a593Smuzhiyun 	void		(*ccid_hc_tx_packet_recv)(struct sock *sk,
67*4882a593Smuzhiyun 						  struct sk_buff *skb);
68*4882a593Smuzhiyun 	int		(*ccid_hc_tx_parse_options)(struct sock *sk, u8 pkt,
69*4882a593Smuzhiyun 						    u8 opt, u8 *val, u8 len);
70*4882a593Smuzhiyun 	int		(*ccid_hc_tx_send_packet)(struct sock *sk,
71*4882a593Smuzhiyun 						  struct sk_buff *skb);
72*4882a593Smuzhiyun 	void		(*ccid_hc_tx_packet_sent)(struct sock *sk,
73*4882a593Smuzhiyun 						  unsigned int len);
74*4882a593Smuzhiyun 	void		(*ccid_hc_rx_get_info)(struct sock *sk,
75*4882a593Smuzhiyun 					       struct tcp_info *info);
76*4882a593Smuzhiyun 	void		(*ccid_hc_tx_get_info)(struct sock *sk,
77*4882a593Smuzhiyun 					       struct tcp_info *info);
78*4882a593Smuzhiyun 	int		(*ccid_hc_rx_getsockopt)(struct sock *sk,
79*4882a593Smuzhiyun 						 const int optname, int len,
80*4882a593Smuzhiyun 						 u32 __user *optval,
81*4882a593Smuzhiyun 						 int __user *optlen);
82*4882a593Smuzhiyun 	int		(*ccid_hc_tx_getsockopt)(struct sock *sk,
83*4882a593Smuzhiyun 						 const int optname, int len,
84*4882a593Smuzhiyun 						 u32 __user *optval,
85*4882a593Smuzhiyun 						 int __user *optlen);
86*4882a593Smuzhiyun };
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun extern struct ccid_operations ccid2_ops;
89*4882a593Smuzhiyun #ifdef CONFIG_IP_DCCP_CCID3
90*4882a593Smuzhiyun extern struct ccid_operations ccid3_ops;
91*4882a593Smuzhiyun #endif
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun int ccid_initialize_builtins(void);
94*4882a593Smuzhiyun void ccid_cleanup_builtins(void);
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun struct ccid {
97*4882a593Smuzhiyun 	struct ccid_operations *ccid_ops;
98*4882a593Smuzhiyun 	char		       ccid_priv[];
99*4882a593Smuzhiyun };
100*4882a593Smuzhiyun 
ccid_priv(const struct ccid * ccid)101*4882a593Smuzhiyun static inline void *ccid_priv(const struct ccid *ccid)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	return (void *)ccid->ccid_priv;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun bool ccid_support_check(u8 const *ccid_array, u8 array_len);
107*4882a593Smuzhiyun int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len);
108*4882a593Smuzhiyun int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
109*4882a593Smuzhiyun 				  char __user *, int __user *);
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun struct ccid *ccid_new(const u8 id, struct sock *sk, bool rx);
112*4882a593Smuzhiyun 
ccid_get_current_rx_ccid(struct dccp_sock * dp)113*4882a593Smuzhiyun static inline int ccid_get_current_rx_ccid(struct dccp_sock *dp)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun 	struct ccid *ccid = dp->dccps_hc_rx_ccid;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	if (ccid == NULL || ccid->ccid_ops == NULL)
118*4882a593Smuzhiyun 		return -1;
119*4882a593Smuzhiyun 	return ccid->ccid_ops->ccid_id;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun 
ccid_get_current_tx_ccid(struct dccp_sock * dp)122*4882a593Smuzhiyun static inline int ccid_get_current_tx_ccid(struct dccp_sock *dp)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun 	struct ccid *ccid = dp->dccps_hc_tx_ccid;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	if (ccid == NULL || ccid->ccid_ops == NULL)
127*4882a593Smuzhiyun 		return -1;
128*4882a593Smuzhiyun 	return ccid->ccid_ops->ccid_id;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk);
132*4882a593Smuzhiyun void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk);
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun /*
135*4882a593Smuzhiyun  * Congestion control of queued data packets via CCID decision.
136*4882a593Smuzhiyun  *
137*4882a593Smuzhiyun  * The TX CCID performs its congestion-control by indicating whether and when a
138*4882a593Smuzhiyun  * queued packet may be sent, using the return code of ccid_hc_tx_send_packet().
139*4882a593Smuzhiyun  * The following modes are supported via the symbolic constants below:
140*4882a593Smuzhiyun  * - timer-based pacing    (CCID returns a delay value in milliseconds);
141*4882a593Smuzhiyun  * - autonomous dequeueing (CCID internally schedules dccps_xmitlet).
142*4882a593Smuzhiyun  */
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun enum ccid_dequeueing_decision {
145*4882a593Smuzhiyun 	CCID_PACKET_SEND_AT_ONCE =	 0x00000,  /* "green light": no delay */
146*4882a593Smuzhiyun 	CCID_PACKET_DELAY_MAX =		 0x0FFFF,  /* maximum delay in msecs  */
147*4882a593Smuzhiyun 	CCID_PACKET_DELAY =		 0x10000,  /* CCID msec-delay mode */
148*4882a593Smuzhiyun 	CCID_PACKET_WILL_DEQUEUE_LATER = 0x20000,  /* CCID autonomous mode */
149*4882a593Smuzhiyun 	CCID_PACKET_ERR =		 0xF0000,  /* error condition */
150*4882a593Smuzhiyun };
151*4882a593Smuzhiyun 
ccid_packet_dequeue_eval(const int return_code)152*4882a593Smuzhiyun static inline int ccid_packet_dequeue_eval(const int return_code)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun 	if (return_code < 0)
155*4882a593Smuzhiyun 		return CCID_PACKET_ERR;
156*4882a593Smuzhiyun 	if (return_code == 0)
157*4882a593Smuzhiyun 		return CCID_PACKET_SEND_AT_ONCE;
158*4882a593Smuzhiyun 	if (return_code <= CCID_PACKET_DELAY_MAX)
159*4882a593Smuzhiyun 		return CCID_PACKET_DELAY;
160*4882a593Smuzhiyun 	return return_code;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun 
ccid_hc_tx_send_packet(struct ccid * ccid,struct sock * sk,struct sk_buff * skb)163*4882a593Smuzhiyun static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
164*4882a593Smuzhiyun 					 struct sk_buff *skb)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL)
167*4882a593Smuzhiyun 		return ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb);
168*4882a593Smuzhiyun 	return CCID_PACKET_SEND_AT_ONCE;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun 
ccid_hc_tx_packet_sent(struct ccid * ccid,struct sock * sk,unsigned int len)171*4882a593Smuzhiyun static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
172*4882a593Smuzhiyun 					  unsigned int len)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun 	if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL)
175*4882a593Smuzhiyun 		ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, len);
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
ccid_hc_rx_packet_recv(struct ccid * ccid,struct sock * sk,struct sk_buff * skb)178*4882a593Smuzhiyun static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk,
179*4882a593Smuzhiyun 					  struct sk_buff *skb)
180*4882a593Smuzhiyun {
181*4882a593Smuzhiyun 	if (ccid->ccid_ops->ccid_hc_rx_packet_recv != NULL)
182*4882a593Smuzhiyun 		ccid->ccid_ops->ccid_hc_rx_packet_recv(sk, skb);
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
ccid_hc_tx_packet_recv(struct ccid * ccid,struct sock * sk,struct sk_buff * skb)185*4882a593Smuzhiyun static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
186*4882a593Smuzhiyun 					  struct sk_buff *skb)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	if (ccid->ccid_ops->ccid_hc_tx_packet_recv != NULL)
189*4882a593Smuzhiyun 		ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun /**
193*4882a593Smuzhiyun  * ccid_hc_tx_parse_options  -  Parse CCID-specific options sent by the receiver
194*4882a593Smuzhiyun  * @pkt: type of packet that @opt appears on (RFC 4340, 5.1)
195*4882a593Smuzhiyun  * @opt: the CCID-specific option type (RFC 4340, 5.8 and 10.3)
196*4882a593Smuzhiyun  * @val: value of @opt
197*4882a593Smuzhiyun  * @len: length of @val in bytes
198*4882a593Smuzhiyun  */
ccid_hc_tx_parse_options(struct ccid * ccid,struct sock * sk,u8 pkt,u8 opt,u8 * val,u8 len)199*4882a593Smuzhiyun static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
200*4882a593Smuzhiyun 					   u8 pkt, u8 opt, u8 *val, u8 len)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun 	if (!ccid || !ccid->ccid_ops->ccid_hc_tx_parse_options)
203*4882a593Smuzhiyun 		return 0;
204*4882a593Smuzhiyun 	return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len);
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun /**
208*4882a593Smuzhiyun  * ccid_hc_rx_parse_options  -  Parse CCID-specific options sent by the sender
209*4882a593Smuzhiyun  * Arguments are analogous to ccid_hc_tx_parse_options()
210*4882a593Smuzhiyun  */
ccid_hc_rx_parse_options(struct ccid * ccid,struct sock * sk,u8 pkt,u8 opt,u8 * val,u8 len)211*4882a593Smuzhiyun static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
212*4882a593Smuzhiyun 					   u8 pkt, u8 opt, u8 *val, u8 len)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	if (!ccid || !ccid->ccid_ops->ccid_hc_rx_parse_options)
215*4882a593Smuzhiyun 		return 0;
216*4882a593Smuzhiyun 	return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len);
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun 
ccid_hc_rx_insert_options(struct ccid * ccid,struct sock * sk,struct sk_buff * skb)219*4882a593Smuzhiyun static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
220*4882a593Smuzhiyun 					    struct sk_buff *skb)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun 	if (ccid->ccid_ops->ccid_hc_rx_insert_options != NULL)
223*4882a593Smuzhiyun 		return ccid->ccid_ops->ccid_hc_rx_insert_options(sk, skb);
224*4882a593Smuzhiyun 	return 0;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun 
ccid_hc_rx_get_info(struct ccid * ccid,struct sock * sk,struct tcp_info * info)227*4882a593Smuzhiyun static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk,
228*4882a593Smuzhiyun 				       struct tcp_info *info)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun 	if (ccid->ccid_ops->ccid_hc_rx_get_info != NULL)
231*4882a593Smuzhiyun 		ccid->ccid_ops->ccid_hc_rx_get_info(sk, info);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
ccid_hc_tx_get_info(struct ccid * ccid,struct sock * sk,struct tcp_info * info)234*4882a593Smuzhiyun static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk,
235*4882a593Smuzhiyun 				       struct tcp_info *info)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	if (ccid->ccid_ops->ccid_hc_tx_get_info != NULL)
238*4882a593Smuzhiyun 		ccid->ccid_ops->ccid_hc_tx_get_info(sk, info);
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun 
ccid_hc_rx_getsockopt(struct ccid * ccid,struct sock * sk,const int optname,int len,u32 __user * optval,int __user * optlen)241*4882a593Smuzhiyun static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
242*4882a593Smuzhiyun 					const int optname, int len,
243*4882a593Smuzhiyun 					u32 __user *optval, int __user *optlen)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun 	int rc = -ENOPROTOOPT;
246*4882a593Smuzhiyun 	if (ccid != NULL && ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL)
247*4882a593Smuzhiyun 		rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len,
248*4882a593Smuzhiyun 						 optval, optlen);
249*4882a593Smuzhiyun 	return rc;
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun 
ccid_hc_tx_getsockopt(struct ccid * ccid,struct sock * sk,const int optname,int len,u32 __user * optval,int __user * optlen)252*4882a593Smuzhiyun static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk,
253*4882a593Smuzhiyun 					const int optname, int len,
254*4882a593Smuzhiyun 					u32 __user *optval, int __user *optlen)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun 	int rc = -ENOPROTOOPT;
257*4882a593Smuzhiyun 	if (ccid != NULL && ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL)
258*4882a593Smuzhiyun 		rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len,
259*4882a593Smuzhiyun 						 optval, optlen);
260*4882a593Smuzhiyun 	return rc;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun #endif /* _CCID_H */
263