xref: /openbmc/linux/net/dccp/ccid.h (revision 8402a31d)
1d2912cb1SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
27c657876SArnaldo Carvalho de Melo #ifndef _CCID_H
37c657876SArnaldo Carvalho de Melo #define _CCID_H
47c657876SArnaldo Carvalho de Melo /*
57c657876SArnaldo Carvalho de Melo  *  net/dccp/ccid.h
67c657876SArnaldo Carvalho de Melo  *
77c657876SArnaldo Carvalho de Melo  *  An implementation of the DCCP protocol
87c657876SArnaldo Carvalho de Melo  *  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
97c657876SArnaldo Carvalho de Melo  *
107c657876SArnaldo Carvalho de Melo  *  CCID infrastructure
117c657876SArnaldo Carvalho de Melo  */
127c657876SArnaldo Carvalho de Melo 
137c657876SArnaldo Carvalho de Melo #include <net/sock.h>
1488f964dbSArnaldo Carvalho de Melo #include <linux/compiler.h>
157c657876SArnaldo Carvalho de Melo #include <linux/dccp.h>
167c657876SArnaldo Carvalho de Melo #include <linux/list.h>
177c657876SArnaldo Carvalho de Melo #include <linux/module.h>
187c657876SArnaldo Carvalho de Melo 
198ed030ddSGerrit Renker /* maximum value for a CCID (RFC 4340, 19.5) */
207c657876SArnaldo Carvalho de Melo #define CCID_MAX		255
218ed030ddSGerrit Renker #define CCID_SLAB_NAME_LENGTH	32
227c657876SArnaldo Carvalho de Melo 
2314c85021SArnaldo Carvalho de Melo struct tcp_info;
2414c85021SArnaldo Carvalho de Melo 
259cb2345aSGerrit Renker /**
269cb2345aSGerrit Renker  *  struct ccid_operations  -  Interface to Congestion-Control Infrastructure
279cb2345aSGerrit Renker  *
289cb2345aSGerrit Renker  *  @ccid_id: numerical CCID ID (up to %CCID_MAX, cf. table 5 in RFC 4340, 10.)
296179983aSGerrit Renker  *  @ccid_ccmps: the CCMPS including network/transport headers (0 when disabled)
309cb2345aSGerrit Renker  *  @ccid_name: alphabetical identifier string for @ccid_id
319cb2345aSGerrit Renker  *  @ccid_hc_{r,t}x_slab: memory pool for the receiver/sender half-connection
329cb2345aSGerrit Renker  *  @ccid_hc_{r,t}x_obj_size: size of the receiver/sender half-connection socket
339cb2345aSGerrit Renker  *
349cb2345aSGerrit Renker  *  @ccid_hc_{r,t}x_init: CCID-specific initialisation routine (before startup)
359cb2345aSGerrit Renker  *  @ccid_hc_{r,t}x_exit: CCID-specific cleanup routine (before destruction)
369cb2345aSGerrit Renker  *  @ccid_hc_rx_packet_recv: implements the HC-receiver side
379cb2345aSGerrit Renker  *  @ccid_hc_{r,t}x_parse_options: parsing routine for CCID/HC-specific options
389cb2345aSGerrit Renker  *  @ccid_hc_{r,t}x_insert_options: insert routine for CCID/HC-specific options
399cb2345aSGerrit Renker  *  @ccid_hc_tx_packet_recv: implements feedback processing for the HC-sender
409cb2345aSGerrit Renker  *  @ccid_hc_tx_send_packet: implements the sending part of the HC-sender
419cb2345aSGerrit Renker  *  @ccid_hc_tx_packet_sent: does accounting for packets in flight by HC-sender
429cb2345aSGerrit Renker  *  @ccid_hc_{r,t}x_get_info: INET_DIAG information for HC-receiver/sender
439cb2345aSGerrit Renker  *  @ccid_hc_{r,t}x_getsockopt: socket options specific to HC-receiver/sender
449cb2345aSGerrit Renker  */
4591f0ebf7SArnaldo Carvalho de Melo struct ccid_operations {
467c657876SArnaldo Carvalho de Melo 	unsigned char		ccid_id;
476179983aSGerrit Renker 	__u32			ccid_ccmps;
487c657876SArnaldo Carvalho de Melo 	const char		*ccid_name;
499cb2345aSGerrit Renker 	struct kmem_cache	*ccid_hc_rx_slab,
509cb2345aSGerrit Renker 				*ccid_hc_tx_slab;
518ed030ddSGerrit Renker 	char			ccid_hc_rx_slab_name[CCID_SLAB_NAME_LENGTH];
528ed030ddSGerrit Renker 	char			ccid_hc_tx_slab_name[CCID_SLAB_NAME_LENGTH];
539cb2345aSGerrit Renker 	__u32			ccid_hc_rx_obj_size,
549cb2345aSGerrit Renker 				ccid_hc_tx_obj_size;
559cb2345aSGerrit Renker 	/* Interface Routines */
5691f0ebf7SArnaldo Carvalho de Melo 	int		(*ccid_hc_rx_init)(struct ccid *ccid, struct sock *sk);
5791f0ebf7SArnaldo Carvalho de Melo 	int		(*ccid_hc_tx_init)(struct ccid *ccid, struct sock *sk);
587c657876SArnaldo Carvalho de Melo 	void		(*ccid_hc_rx_exit)(struct sock *sk);
597c657876SArnaldo Carvalho de Melo 	void		(*ccid_hc_tx_exit)(struct sock *sk);
607690af3fSArnaldo Carvalho de Melo 	void		(*ccid_hc_rx_packet_recv)(struct sock *sk,
617690af3fSArnaldo Carvalho de Melo 						  struct sk_buff *skb);
624874c131SGerrit Renker 	int		(*ccid_hc_rx_parse_options)(struct sock *sk, u8 pkt,
634874c131SGerrit Renker 						    u8 opt, u8 *val, u8 len);
642d0817d1SArnaldo Carvalho de Melo 	int		(*ccid_hc_rx_insert_options)(struct sock *sk,
657690af3fSArnaldo Carvalho de Melo 						     struct sk_buff *skb);
667690af3fSArnaldo Carvalho de Melo 	void		(*ccid_hc_tx_packet_recv)(struct sock *sk,
677690af3fSArnaldo Carvalho de Melo 						  struct sk_buff *skb);
684874c131SGerrit Renker 	int		(*ccid_hc_tx_parse_options)(struct sock *sk, u8 pkt,
694874c131SGerrit Renker 						    u8 opt, u8 *val, u8 len);
707c657876SArnaldo Carvalho de Melo 	int		(*ccid_hc_tx_send_packet)(struct sock *sk,
716b57c93dSGerrit Renker 						  struct sk_buff *skb);
726b57c93dSGerrit Renker 	void		(*ccid_hc_tx_packet_sent)(struct sock *sk,
73baf9e782SGerrit Renker 						  unsigned int len);
742babe1f6SArnaldo Carvalho de Melo 	void		(*ccid_hc_rx_get_info)(struct sock *sk,
752babe1f6SArnaldo Carvalho de Melo 					       struct tcp_info *info);
762babe1f6SArnaldo Carvalho de Melo 	void		(*ccid_hc_tx_get_info)(struct sock *sk,
772babe1f6SArnaldo Carvalho de Melo 					       struct tcp_info *info);
7888f964dbSArnaldo Carvalho de Melo 	int		(*ccid_hc_rx_getsockopt)(struct sock *sk,
7988f964dbSArnaldo Carvalho de Melo 						 const int optname, int len,
8088f964dbSArnaldo Carvalho de Melo 						 u32 __user *optval,
8188f964dbSArnaldo Carvalho de Melo 						 int __user *optlen);
8288f964dbSArnaldo Carvalho de Melo 	int		(*ccid_hc_tx_getsockopt)(struct sock *sk,
8388f964dbSArnaldo Carvalho de Melo 						 const int optname, int len,
8488f964dbSArnaldo Carvalho de Melo 						 u32 __user *optval,
8588f964dbSArnaldo Carvalho de Melo 						 int __user *optlen);
867c657876SArnaldo Carvalho de Melo };
877c657876SArnaldo Carvalho de Melo 
88ddebc973SGerrit Renker extern struct ccid_operations ccid2_ops;
89ddebc973SGerrit Renker #ifdef CONFIG_IP_DCCP_CCID3
90ddebc973SGerrit Renker extern struct ccid_operations ccid3_ops;
91ddebc973SGerrit Renker #endif
92ddebc973SGerrit Renker 
93a402a5aaSJoe Perches int ccid_initialize_builtins(void);
94a402a5aaSJoe Perches void ccid_cleanup_builtins(void);
957c657876SArnaldo Carvalho de Melo 
9691f0ebf7SArnaldo Carvalho de Melo struct ccid {
9791f0ebf7SArnaldo Carvalho de Melo 	struct ccid_operations *ccid_ops;
988402a31dSGustavo A. R. Silva 	char		       ccid_priv[];
9991f0ebf7SArnaldo Carvalho de Melo };
1007c657876SArnaldo Carvalho de Melo 
ccid_priv(const struct ccid * ccid)10191f0ebf7SArnaldo Carvalho de Melo static inline void *ccid_priv(const struct ccid *ccid)
1027c657876SArnaldo Carvalho de Melo {
10391f0ebf7SArnaldo Carvalho de Melo 	return (void *)ccid->ccid_priv;
1047c657876SArnaldo Carvalho de Melo }
1057c657876SArnaldo Carvalho de Melo 
106a402a5aaSJoe Perches bool ccid_support_check(u8 const *ccid_array, u8 array_len);
107a402a5aaSJoe Perches int ccid_get_builtin_ccids(u8 **ccid_array, u8 *array_len);
108a402a5aaSJoe Perches int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
109d90ebcbfSGerrit Renker 				  char __user *, int __user *);
110d90ebcbfSGerrit Renker 
111a402a5aaSJoe Perches struct ccid *ccid_new(const u8 id, struct sock *sk, bool rx);
11291f0ebf7SArnaldo Carvalho de Melo 
ccid_get_current_rx_ccid(struct dccp_sock * dp)11371c262a3SGerrit Renker static inline int ccid_get_current_rx_ccid(struct dccp_sock *dp)
11471c262a3SGerrit Renker {
11571c262a3SGerrit Renker 	struct ccid *ccid = dp->dccps_hc_rx_ccid;
11671c262a3SGerrit Renker 
11771c262a3SGerrit Renker 	if (ccid == NULL || ccid->ccid_ops == NULL)
11871c262a3SGerrit Renker 		return -1;
11971c262a3SGerrit Renker 	return ccid->ccid_ops->ccid_id;
12071c262a3SGerrit Renker }
12171c262a3SGerrit Renker 
ccid_get_current_tx_ccid(struct dccp_sock * dp)12271c262a3SGerrit Renker static inline int ccid_get_current_tx_ccid(struct dccp_sock *dp)
12371c262a3SGerrit Renker {
12471c262a3SGerrit Renker 	struct ccid *ccid = dp->dccps_hc_tx_ccid;
12571c262a3SGerrit Renker 
12671c262a3SGerrit Renker 	if (ccid == NULL || ccid->ccid_ops == NULL)
12771c262a3SGerrit Renker 		return -1;
12871c262a3SGerrit Renker 	return ccid->ccid_ops->ccid_id;
12971c262a3SGerrit Renker }
13071c262a3SGerrit Renker 
131a402a5aaSJoe Perches void ccid_hc_rx_delete(struct ccid *ccid, struct sock *sk);
132a402a5aaSJoe Perches void ccid_hc_tx_delete(struct ccid *ccid, struct sock *sk);
13391f0ebf7SArnaldo Carvalho de Melo 
134fe84f414SGerrit Renker /*
135fe84f414SGerrit Renker  * Congestion control of queued data packets via CCID decision.
136fe84f414SGerrit Renker  *
137fe84f414SGerrit Renker  * The TX CCID performs its congestion-control by indicating whether and when a
138fe84f414SGerrit Renker  * queued packet may be sent, using the return code of ccid_hc_tx_send_packet().
139fe84f414SGerrit Renker  * The following modes are supported via the symbolic constants below:
140fe84f414SGerrit Renker  * - timer-based pacing    (CCID returns a delay value in milliseconds);
141fe84f414SGerrit Renker  * - autonomous dequeueing (CCID internally schedules dccps_xmitlet).
142fe84f414SGerrit Renker  */
143fe84f414SGerrit Renker 
144fe84f414SGerrit Renker enum ccid_dequeueing_decision {
145fe84f414SGerrit Renker 	CCID_PACKET_SEND_AT_ONCE =	 0x00000,  /* "green light": no delay */
146fe84f414SGerrit Renker 	CCID_PACKET_DELAY_MAX =		 0x0FFFF,  /* maximum delay in msecs  */
147fe84f414SGerrit Renker 	CCID_PACKET_DELAY =		 0x10000,  /* CCID msec-delay mode */
148fe84f414SGerrit Renker 	CCID_PACKET_WILL_DEQUEUE_LATER = 0x20000,  /* CCID autonomous mode */
149fe84f414SGerrit Renker 	CCID_PACKET_ERR =		 0xF0000,  /* error condition */
150fe84f414SGerrit Renker };
151fe84f414SGerrit Renker 
ccid_packet_dequeue_eval(const int return_code)152fe84f414SGerrit Renker static inline int ccid_packet_dequeue_eval(const int return_code)
153fe84f414SGerrit Renker {
154fe84f414SGerrit Renker 	if (return_code < 0)
155fe84f414SGerrit Renker 		return CCID_PACKET_ERR;
156fe84f414SGerrit Renker 	if (return_code == 0)
157fe84f414SGerrit Renker 		return CCID_PACKET_SEND_AT_ONCE;
158fe84f414SGerrit Renker 	if (return_code <= CCID_PACKET_DELAY_MAX)
159fe84f414SGerrit Renker 		return CCID_PACKET_DELAY;
160fe84f414SGerrit Renker 	return return_code;
161fe84f414SGerrit Renker }
162fe84f414SGerrit Renker 
ccid_hc_tx_send_packet(struct ccid * ccid,struct sock * sk,struct sk_buff * skb)1637c657876SArnaldo Carvalho de Melo static inline int ccid_hc_tx_send_packet(struct ccid *ccid, struct sock *sk,
1646b57c93dSGerrit Renker 					 struct sk_buff *skb)
1657c657876SArnaldo Carvalho de Melo {
16691f0ebf7SArnaldo Carvalho de Melo 	if (ccid->ccid_ops->ccid_hc_tx_send_packet != NULL)
167fe84f414SGerrit Renker 		return ccid->ccid_ops->ccid_hc_tx_send_packet(sk, skb);
168fe84f414SGerrit Renker 	return CCID_PACKET_SEND_AT_ONCE;
1697c657876SArnaldo Carvalho de Melo }
1707c657876SArnaldo Carvalho de Melo 
ccid_hc_tx_packet_sent(struct ccid * ccid,struct sock * sk,unsigned int len)1717c657876SArnaldo Carvalho de Melo static inline void ccid_hc_tx_packet_sent(struct ccid *ccid, struct sock *sk,
172baf9e782SGerrit Renker 					  unsigned int len)
1737c657876SArnaldo Carvalho de Melo {
17491f0ebf7SArnaldo Carvalho de Melo 	if (ccid->ccid_ops->ccid_hc_tx_packet_sent != NULL)
175baf9e782SGerrit Renker 		ccid->ccid_ops->ccid_hc_tx_packet_sent(sk, len);
1767c657876SArnaldo Carvalho de Melo }
1777c657876SArnaldo Carvalho de Melo 
ccid_hc_rx_packet_recv(struct ccid * ccid,struct sock * sk,struct sk_buff * skb)1787c657876SArnaldo Carvalho de Melo static inline void ccid_hc_rx_packet_recv(struct ccid *ccid, struct sock *sk,
1797c657876SArnaldo Carvalho de Melo 					  struct sk_buff *skb)
1807c657876SArnaldo Carvalho de Melo {
18191f0ebf7SArnaldo Carvalho de Melo 	if (ccid->ccid_ops->ccid_hc_rx_packet_recv != NULL)
18291f0ebf7SArnaldo Carvalho de Melo 		ccid->ccid_ops->ccid_hc_rx_packet_recv(sk, skb);
1837c657876SArnaldo Carvalho de Melo }
1847c657876SArnaldo Carvalho de Melo 
ccid_hc_tx_packet_recv(struct ccid * ccid,struct sock * sk,struct sk_buff * skb)1857c657876SArnaldo Carvalho de Melo static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
1867c657876SArnaldo Carvalho de Melo 					  struct sk_buff *skb)
1877c657876SArnaldo Carvalho de Melo {
18891f0ebf7SArnaldo Carvalho de Melo 	if (ccid->ccid_ops->ccid_hc_tx_packet_recv != NULL)
18991f0ebf7SArnaldo Carvalho de Melo 		ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb);
1907c657876SArnaldo Carvalho de Melo }
1917c657876SArnaldo Carvalho de Melo 
1924874c131SGerrit Renker /**
1934874c131SGerrit Renker  * ccid_hc_tx_parse_options  -  Parse CCID-specific options sent by the receiver
1944874c131SGerrit Renker  * @pkt: type of packet that @opt appears on (RFC 4340, 5.1)
1954874c131SGerrit Renker  * @opt: the CCID-specific option type (RFC 4340, 5.8 and 10.3)
1964874c131SGerrit Renker  * @val: value of @opt
1974874c131SGerrit Renker  * @len: length of @val in bytes
1984874c131SGerrit Renker  */
ccid_hc_tx_parse_options(struct ccid * ccid,struct sock * sk,u8 pkt,u8 opt,u8 * val,u8 len)1997c657876SArnaldo Carvalho de Melo static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
2004874c131SGerrit Renker 					   u8 pkt, u8 opt, u8 *val, u8 len)
2017c657876SArnaldo Carvalho de Melo {
2029b1f19d8SEric Dumazet 	if (!ccid || !ccid->ccid_ops->ccid_hc_tx_parse_options)
2034874c131SGerrit Renker 		return 0;
2044874c131SGerrit Renker 	return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len);
2057c657876SArnaldo Carvalho de Melo }
2067c657876SArnaldo Carvalho de Melo 
2074874c131SGerrit Renker /**
2084874c131SGerrit Renker  * ccid_hc_rx_parse_options  -  Parse CCID-specific options sent by the sender
2094874c131SGerrit Renker  * Arguments are analogous to ccid_hc_tx_parse_options()
2104874c131SGerrit Renker  */
ccid_hc_rx_parse_options(struct ccid * ccid,struct sock * sk,u8 pkt,u8 opt,u8 * val,u8 len)2117c657876SArnaldo Carvalho de Melo static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
2124874c131SGerrit Renker 					   u8 pkt, u8 opt, u8 *val, u8 len)
2137c657876SArnaldo Carvalho de Melo {
2149b1f19d8SEric Dumazet 	if (!ccid || !ccid->ccid_ops->ccid_hc_rx_parse_options)
2154874c131SGerrit Renker 		return 0;
2164874c131SGerrit Renker 	return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len);
2177c657876SArnaldo Carvalho de Melo }
2187c657876SArnaldo Carvalho de Melo 
ccid_hc_rx_insert_options(struct ccid * ccid,struct sock * sk,struct sk_buff * skb)2192d0817d1SArnaldo Carvalho de Melo static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk,
2207c657876SArnaldo Carvalho de Melo 					    struct sk_buff *skb)
2217c657876SArnaldo Carvalho de Melo {
22291f0ebf7SArnaldo Carvalho de Melo 	if (ccid->ccid_ops->ccid_hc_rx_insert_options != NULL)
2232d0817d1SArnaldo Carvalho de Melo 		return ccid->ccid_ops->ccid_hc_rx_insert_options(sk, skb);
2242d0817d1SArnaldo Carvalho de Melo 	return 0;
2257c657876SArnaldo Carvalho de Melo }
2262babe1f6SArnaldo Carvalho de Melo 
ccid_hc_rx_get_info(struct ccid * ccid,struct sock * sk,struct tcp_info * info)2272babe1f6SArnaldo Carvalho de Melo static inline void ccid_hc_rx_get_info(struct ccid *ccid, struct sock *sk,
2282babe1f6SArnaldo Carvalho de Melo 				       struct tcp_info *info)
2292babe1f6SArnaldo Carvalho de Melo {
23091f0ebf7SArnaldo Carvalho de Melo 	if (ccid->ccid_ops->ccid_hc_rx_get_info != NULL)
23191f0ebf7SArnaldo Carvalho de Melo 		ccid->ccid_ops->ccid_hc_rx_get_info(sk, info);
2322babe1f6SArnaldo Carvalho de Melo }
2332babe1f6SArnaldo Carvalho de Melo 
ccid_hc_tx_get_info(struct ccid * ccid,struct sock * sk,struct tcp_info * info)2342babe1f6SArnaldo Carvalho de Melo static inline void ccid_hc_tx_get_info(struct ccid *ccid, struct sock *sk,
2352babe1f6SArnaldo Carvalho de Melo 				       struct tcp_info *info)
2362babe1f6SArnaldo Carvalho de Melo {
23791f0ebf7SArnaldo Carvalho de Melo 	if (ccid->ccid_ops->ccid_hc_tx_get_info != NULL)
23891f0ebf7SArnaldo Carvalho de Melo 		ccid->ccid_ops->ccid_hc_tx_get_info(sk, info);
2392babe1f6SArnaldo Carvalho de Melo }
24088f964dbSArnaldo Carvalho de Melo 
ccid_hc_rx_getsockopt(struct ccid * ccid,struct sock * sk,const int optname,int len,u32 __user * optval,int __user * optlen)24188f964dbSArnaldo Carvalho de Melo static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk,
24288f964dbSArnaldo Carvalho de Melo 					const int optname, int len,
24388f964dbSArnaldo Carvalho de Melo 					u32 __user *optval, int __user *optlen)
24488f964dbSArnaldo Carvalho de Melo {
24588f964dbSArnaldo Carvalho de Melo 	int rc = -ENOPROTOOPT;
246276bdb82SMathias Krause 	if (ccid != NULL && ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL)
24791f0ebf7SArnaldo Carvalho de Melo 		rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len,
24888f964dbSArnaldo Carvalho de Melo 						 optval, optlen);
24988f964dbSArnaldo Carvalho de Melo 	return rc;
25088f964dbSArnaldo Carvalho de Melo }
25188f964dbSArnaldo Carvalho de Melo 
ccid_hc_tx_getsockopt(struct ccid * ccid,struct sock * sk,const int optname,int len,u32 __user * optval,int __user * optlen)25288f964dbSArnaldo Carvalho de Melo static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk,
25388f964dbSArnaldo Carvalho de Melo 					const int optname, int len,
25488f964dbSArnaldo Carvalho de Melo 					u32 __user *optval, int __user *optlen)
25588f964dbSArnaldo Carvalho de Melo {
25688f964dbSArnaldo Carvalho de Melo 	int rc = -ENOPROTOOPT;
257276bdb82SMathias Krause 	if (ccid != NULL && ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL)
25891f0ebf7SArnaldo Carvalho de Melo 		rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len,
25988f964dbSArnaldo Carvalho de Melo 						 optval, optlen);
26088f964dbSArnaldo Carvalho de Melo 	return rc;
26188f964dbSArnaldo Carvalho de Melo }
2627c657876SArnaldo Carvalho de Melo #endif /* _CCID_H */
263