xref: /linux-6.15/include/net/strparser.h (revision 0532a79e)
1d2912cb1SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
243a0c675STom Herbert /*
343a0c675STom Herbert  * Stream Parser
443a0c675STom Herbert  *
543a0c675STom Herbert  * Copyright (c) 2016 Tom Herbert <[email protected]>
643a0c675STom Herbert  */
743a0c675STom Herbert 
843a0c675STom Herbert #ifndef __NET_STRPARSER_H_
943a0c675STom Herbert #define __NET_STRPARSER_H_
1043a0c675STom Herbert 
1143a0c675STom Herbert #include <linux/skbuff.h>
1243a0c675STom Herbert #include <net/sock.h>
1343a0c675STom Herbert 
1443a0c675STom Herbert #define STRP_STATS_ADD(stat, count) ((stat) += (count))
1543a0c675STom Herbert #define STRP_STATS_INCR(stat) ((stat)++)
1643a0c675STom Herbert 
1743a0c675STom Herbert struct strp_stats {
18bbb03029STom Herbert 	unsigned long long msgs;
19bbb03029STom Herbert 	unsigned long long bytes;
20bbb03029STom Herbert 	unsigned int mem_fail;
21bbb03029STom Herbert 	unsigned int need_more_hdr;
22bbb03029STom Herbert 	unsigned int msg_too_big;
23bbb03029STom Herbert 	unsigned int msg_timeouts;
24bbb03029STom Herbert 	unsigned int bad_hdr_len;
2543a0c675STom Herbert };
2643a0c675STom Herbert 
2743a0c675STom Herbert struct strp_aggr_stats {
28bbb03029STom Herbert 	unsigned long long msgs;
29bbb03029STom Herbert 	unsigned long long bytes;
30bbb03029STom Herbert 	unsigned int mem_fail;
31bbb03029STom Herbert 	unsigned int need_more_hdr;
32bbb03029STom Herbert 	unsigned int msg_too_big;
33bbb03029STom Herbert 	unsigned int msg_timeouts;
34bbb03029STom Herbert 	unsigned int bad_hdr_len;
35bbb03029STom Herbert 	unsigned int aborts;
36bbb03029STom Herbert 	unsigned int interrupted;
37bbb03029STom Herbert 	unsigned int unrecov_intr;
3843a0c675STom Herbert };
3943a0c675STom Herbert 
4043a0c675STom Herbert struct strparser;
4143a0c675STom Herbert 
4243a0c675STom Herbert /* Callbacks are called with lock held for the attached socket */
4343a0c675STom Herbert struct strp_callbacks {
4443a0c675STom Herbert 	int (*parse_msg)(struct strparser *strp, struct sk_buff *skb);
4543a0c675STom Herbert 	void (*rcv_msg)(struct strparser *strp, struct sk_buff *skb);
46*0532a79eSJiayuan Chen 	int (*read_sock)(struct strparser *strp, read_descriptor_t *desc,
47*0532a79eSJiayuan Chen 			 sk_read_actor_t recv_actor);
4843a0c675STom Herbert 	int (*read_sock_done)(struct strparser *strp, int err);
4943a0c675STom Herbert 	void (*abort_parser)(struct strparser *strp, int err);
50bbb03029STom Herbert 	void (*lock)(struct strparser *strp);
51bbb03029STom Herbert 	void (*unlock)(struct strparser *strp);
5243a0c675STom Herbert };
5343a0c675STom Herbert 
54bbb03029STom Herbert struct strp_msg {
5543a0c675STom Herbert 	int full_len;
5643a0c675STom Herbert 	int offset;
5743a0c675STom Herbert };
5843a0c675STom Herbert 
59e0dc3b93SJohn Fastabend struct _strp_msg {
60e0dc3b93SJohn Fastabend 	/* Internal cb structure. struct strp_msg must be first for passing
61e0dc3b93SJohn Fastabend 	 * to upper layer.
62e0dc3b93SJohn Fastabend 	 */
63e0dc3b93SJohn Fastabend 	struct strp_msg strp;
64e0dc3b93SJohn Fastabend 	int accum_len;
65e0dc3b93SJohn Fastabend };
66e0dc3b93SJohn Fastabend 
67e0dc3b93SJohn Fastabend struct sk_skb_cb {
68e0dc3b93SJohn Fastabend #define SK_SKB_CB_PRIV_LEN 20
69e0dc3b93SJohn Fastabend 	unsigned char data[SK_SKB_CB_PRIV_LEN];
702d91ecacSJakub Kicinski 	/* align strp on cache line boundary within skb->cb[] */
712d91ecacSJakub Kicinski 	unsigned char pad[4];
72e0dc3b93SJohn Fastabend 	struct _strp_msg strp;
732d91ecacSJakub Kicinski 
742d91ecacSJakub Kicinski 	/* strp users' data follows */
75c3f6bb74SJakub Kicinski 	struct tls_msg {
76c3f6bb74SJakub Kicinski 		u8 control;
77c3f6bb74SJakub Kicinski 	} tls;
782d91ecacSJakub Kicinski 	/* temp_reg is a temporary register used for bpf_convert_data_end_access
792d91ecacSJakub Kicinski 	 * when dst_reg == src_reg.
802d91ecacSJakub Kicinski 	 */
812d91ecacSJakub Kicinski 	u64 temp_reg;
82e0dc3b93SJohn Fastabend };
83e0dc3b93SJohn Fastabend 
strp_msg(struct sk_buff * skb)84bbb03029STom Herbert static inline struct strp_msg *strp_msg(struct sk_buff *skb)
8543a0c675STom Herbert {
86bbb03029STom Herbert 	return (struct strp_msg *)((void *)skb->cb +
87e0dc3b93SJohn Fastabend 		offsetof(struct sk_skb_cb, strp));
8843a0c675STom Herbert }
8943a0c675STom Herbert 
9043a0c675STom Herbert /* Structure for an attached lower socket */
9143a0c675STom Herbert struct strparser {
9243a0c675STom Herbert 	struct sock *sk;
9343a0c675STom Herbert 
94bbb03029STom Herbert 	u32 stopped : 1;
95bbb03029STom Herbert 	u32 paused : 1;
96bbb03029STom Herbert 	u32 aborted : 1;
97bbb03029STom Herbert 	u32 interrupted : 1;
98bbb03029STom Herbert 	u32 unrecov_intr : 1;
9943a0c675STom Herbert 
100bbb03029STom Herbert 	struct sk_buff **skb_nextp;
101bbb03029STom Herbert 	struct sk_buff *skb_head;
102bbb03029STom Herbert 	unsigned int need_bytes;
103829385f0STom Herbert 	struct delayed_work msg_timer_work;
104bbb03029STom Herbert 	struct work_struct work;
10543a0c675STom Herbert 	struct strp_stats stats;
10643a0c675STom Herbert 	struct strp_callbacks cb;
10743a0c675STom Herbert };
10843a0c675STom Herbert 
10943a0c675STom Herbert /* Must be called with lock held for attached socket */
strp_pause(struct strparser * strp)11043a0c675STom Herbert static inline void strp_pause(struct strparser *strp)
11143a0c675STom Herbert {
112bbb03029STom Herbert 	strp->paused = 1;
11343a0c675STom Herbert }
11443a0c675STom Herbert 
11543a0c675STom Herbert /* May be called without holding lock for attached socket */
116cff6a334STom Herbert void strp_unpause(struct strparser *strp);
1177170e604SDoron Roberts-Kedes /* Must be called with process lock held (lock_sock) */
1187170e604SDoron Roberts-Kedes void __strp_unpause(struct strparser *strp);
11943a0c675STom Herbert 
save_strp_stats(struct strparser * strp,struct strp_aggr_stats * agg_stats)12043a0c675STom Herbert static inline void save_strp_stats(struct strparser *strp,
12143a0c675STom Herbert 				   struct strp_aggr_stats *agg_stats)
12243a0c675STom Herbert {
12343a0c675STom Herbert 	/* Save psock statistics in the mux when psock is being unattached. */
12443a0c675STom Herbert 
12543a0c675STom Herbert #define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat +=		\
12643a0c675STom Herbert 				 strp->stats._stat)
127bbb03029STom Herbert 	SAVE_PSOCK_STATS(msgs);
128bbb03029STom Herbert 	SAVE_PSOCK_STATS(bytes);
129bbb03029STom Herbert 	SAVE_PSOCK_STATS(mem_fail);
130bbb03029STom Herbert 	SAVE_PSOCK_STATS(need_more_hdr);
131bbb03029STom Herbert 	SAVE_PSOCK_STATS(msg_too_big);
132bbb03029STom Herbert 	SAVE_PSOCK_STATS(msg_timeouts);
133bbb03029STom Herbert 	SAVE_PSOCK_STATS(bad_hdr_len);
13443a0c675STom Herbert #undef SAVE_PSOCK_STATS
13543a0c675STom Herbert 
136bbb03029STom Herbert 	if (strp->aborted)
137bbb03029STom Herbert 		agg_stats->aborts++;
138bbb03029STom Herbert 	if (strp->interrupted)
139bbb03029STom Herbert 		agg_stats->interrupted++;
140bbb03029STom Herbert 	if (strp->unrecov_intr)
141bbb03029STom Herbert 		agg_stats->unrecov_intr++;
14243a0c675STom Herbert }
14343a0c675STom Herbert 
aggregate_strp_stats(struct strp_aggr_stats * stats,struct strp_aggr_stats * agg_stats)14443a0c675STom Herbert static inline void aggregate_strp_stats(struct strp_aggr_stats *stats,
14543a0c675STom Herbert 					struct strp_aggr_stats *agg_stats)
14643a0c675STom Herbert {
14743a0c675STom Herbert #define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat += stats->_stat)
148bbb03029STom Herbert 	SAVE_PSOCK_STATS(msgs);
149bbb03029STom Herbert 	SAVE_PSOCK_STATS(bytes);
150bbb03029STom Herbert 	SAVE_PSOCK_STATS(mem_fail);
151bbb03029STom Herbert 	SAVE_PSOCK_STATS(need_more_hdr);
152bbb03029STom Herbert 	SAVE_PSOCK_STATS(msg_too_big);
153bbb03029STom Herbert 	SAVE_PSOCK_STATS(msg_timeouts);
154bbb03029STom Herbert 	SAVE_PSOCK_STATS(bad_hdr_len);
155bbb03029STom Herbert 	SAVE_PSOCK_STATS(aborts);
156bbb03029STom Herbert 	SAVE_PSOCK_STATS(interrupted);
157bbb03029STom Herbert 	SAVE_PSOCK_STATS(unrecov_intr);
15843a0c675STom Herbert #undef SAVE_PSOCK_STATS
15943a0c675STom Herbert 
16043a0c675STom Herbert }
16143a0c675STom Herbert 
16243a0c675STom Herbert void strp_done(struct strparser *strp);
16343a0c675STom Herbert void strp_stop(struct strparser *strp);
16443a0c675STom Herbert void strp_check_rcv(struct strparser *strp);
165bbb03029STom Herbert int strp_init(struct strparser *strp, struct sock *sk,
1663fd87127SEric Biggers 	      const struct strp_callbacks *cb);
16796a59083STom Herbert void strp_data_ready(struct strparser *strp);
168bbb03029STom Herbert int strp_process(struct strparser *strp, struct sk_buff *orig_skb,
169bbb03029STom Herbert 		 unsigned int orig_offset, size_t orig_len,
170bbb03029STom Herbert 		 size_t max_msg_size, long timeo);
17143a0c675STom Herbert 
17243a0c675STom Herbert #endif /* __NET_STRPARSER_H_ */
173