18c2ecf20Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci========================= 48c2ecf20Sopenharmony_ciStream Parser (strparser) 58c2ecf20Sopenharmony_ci========================= 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ciIntroduction 88c2ecf20Sopenharmony_ci============ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ciThe stream parser (strparser) is a utility that parses messages of an 118c2ecf20Sopenharmony_ciapplication layer protocol running over a data stream. The stream 128c2ecf20Sopenharmony_ciparser works in conjunction with an upper layer in the kernel to provide 138c2ecf20Sopenharmony_cikernel support for application layer messages. For instance, Kernel 148c2ecf20Sopenharmony_ciConnection Multiplexor (KCM) uses the Stream Parser to parse messages 158c2ecf20Sopenharmony_ciusing a BPF program. 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ciThe strparser works in one of two modes: receive callback or general 188c2ecf20Sopenharmony_cimode. 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ciIn receive callback mode, the strparser is called from the data_ready 218c2ecf20Sopenharmony_cicallback of a TCP socket. Messages are parsed and delivered as they are 228c2ecf20Sopenharmony_cireceived on the socket. 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ciIn general mode, a sequence of skbs are fed to strparser from an 258c2ecf20Sopenharmony_cioutside source. Message are parsed and delivered as the sequence is 268c2ecf20Sopenharmony_ciprocessed. This modes allows strparser to be applied to arbitrary 278c2ecf20Sopenharmony_cistreams of data. 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ciInterface 308c2ecf20Sopenharmony_ci========= 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ciThe API includes a context structure, a set of callbacks, utility 338c2ecf20Sopenharmony_cifunctions, and a data_ready function for receive callback mode. The 348c2ecf20Sopenharmony_cicallbacks include a parse_msg function that is called to perform 358c2ecf20Sopenharmony_ciparsing (e.g. BPF parsing in case of KCM), and a rcv_msg function 368c2ecf20Sopenharmony_cithat is called when a full message has been completed. 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ciFunctions 398c2ecf20Sopenharmony_ci========= 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci :: 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci strp_init(struct strparser *strp, struct sock *sk, 448c2ecf20Sopenharmony_ci const struct strp_callbacks *cb) 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci Called to initialize a stream parser. strp is a struct of type 478c2ecf20Sopenharmony_ci strparser that is allocated by the upper layer. sk is the TCP 488c2ecf20Sopenharmony_ci socket associated with the stream parser for use with receive 498c2ecf20Sopenharmony_ci callback mode; in general mode this is set to NULL. Callbacks 508c2ecf20Sopenharmony_ci are called by the stream parser (the callbacks are listed below). 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci :: 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci void strp_pause(struct strparser *strp) 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci Temporarily pause a stream parser. Message parsing is suspended 578c2ecf20Sopenharmony_ci and no new messages are delivered to the upper layer. 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci :: 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci void strp_unpause(struct strparser *strp) 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci Unpause a paused stream parser. 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci :: 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci void strp_stop(struct strparser *strp); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci strp_stop is called to completely stop stream parser operations. 708c2ecf20Sopenharmony_ci This is called internally when the stream parser encounters an 718c2ecf20Sopenharmony_ci error, and it is called from the upper layer to stop parsing 728c2ecf20Sopenharmony_ci operations. 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci :: 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci void strp_done(struct strparser *strp); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci strp_done is called to release any resources held by the stream 798c2ecf20Sopenharmony_ci parser instance. This must be called after the stream processor 808c2ecf20Sopenharmony_ci has been stopped. 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci :: 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci int strp_process(struct strparser *strp, struct sk_buff *orig_skb, 858c2ecf20Sopenharmony_ci unsigned int orig_offset, size_t orig_len, 868c2ecf20Sopenharmony_ci size_t max_msg_size, long timeo) 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci strp_process is called in general mode for a stream parser to 898c2ecf20Sopenharmony_ci parse an sk_buff. The number of bytes processed or a negative 908c2ecf20Sopenharmony_ci error number is returned. Note that strp_process does not 918c2ecf20Sopenharmony_ci consume the sk_buff. max_msg_size is maximum size the stream 928c2ecf20Sopenharmony_ci parser will parse. timeo is timeout for completing a message. 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci :: 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci void strp_data_ready(struct strparser *strp); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci The upper layer calls strp_tcp_data_ready when data is ready on 998c2ecf20Sopenharmony_ci the lower socket for strparser to process. This should be called 1008c2ecf20Sopenharmony_ci from a data_ready callback that is set on the socket. Note that 1018c2ecf20Sopenharmony_ci maximum messages size is the limit of the receive socket 1028c2ecf20Sopenharmony_ci buffer and message timeout is the receive timeout for the socket. 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci :: 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci void strp_check_rcv(struct strparser *strp); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci strp_check_rcv is called to check for new messages on the socket. 1098c2ecf20Sopenharmony_ci This is normally called at initialization of a stream parser 1108c2ecf20Sopenharmony_ci instance or after strp_unpause. 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ciCallbacks 1138c2ecf20Sopenharmony_ci========= 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ciThere are six callbacks: 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci :: 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci int (*parse_msg)(struct strparser *strp, struct sk_buff *skb); 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci parse_msg is called to determine the length of the next message 1228c2ecf20Sopenharmony_ci in the stream. The upper layer must implement this function. It 1238c2ecf20Sopenharmony_ci should parse the sk_buff as containing the headers for the 1248c2ecf20Sopenharmony_ci next application layer message in the stream. 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci The skb->cb in the input skb is a struct strp_msg. Only 1278c2ecf20Sopenharmony_ci the offset field is relevant in parse_msg and gives the offset 1288c2ecf20Sopenharmony_ci where the message starts in the skb. 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci The return values of this function are: 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci ========= =========================================================== 1338c2ecf20Sopenharmony_ci >0 indicates length of successfully parsed message 1348c2ecf20Sopenharmony_ci 0 indicates more data must be received to parse the message 1358c2ecf20Sopenharmony_ci -ESTRPIPE current message should not be processed by the 1368c2ecf20Sopenharmony_ci kernel, return control of the socket to userspace which 1378c2ecf20Sopenharmony_ci can proceed to read the messages itself 1388c2ecf20Sopenharmony_ci other < 0 Error in parsing, give control back to userspace 1398c2ecf20Sopenharmony_ci assuming that synchronization is lost and the stream 1408c2ecf20Sopenharmony_ci is unrecoverable (application expected to close TCP socket) 1418c2ecf20Sopenharmony_ci ========= =========================================================== 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci In the case that an error is returned (return value is less than 1448c2ecf20Sopenharmony_ci zero) and the parser is in receive callback mode, then it will set 1458c2ecf20Sopenharmony_ci the error on TCP socket and wake it up. If parse_msg returned 1468c2ecf20Sopenharmony_ci -ESTRPIPE and the stream parser had previously read some bytes for 1478c2ecf20Sopenharmony_ci the current message, then the error set on the attached socket is 1488c2ecf20Sopenharmony_ci ENODATA since the stream is unrecoverable in that case. 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci :: 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci void (*lock)(struct strparser *strp) 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci The lock callback is called to lock the strp structure when 1558c2ecf20Sopenharmony_ci the strparser is performing an asynchronous operation (such as 1568c2ecf20Sopenharmony_ci processing a timeout). In receive callback mode the default 1578c2ecf20Sopenharmony_ci function is to lock_sock for the associated socket. In general 1588c2ecf20Sopenharmony_ci mode the callback must be set appropriately. 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci :: 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci void (*unlock)(struct strparser *strp) 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci The unlock callback is called to release the lock obtained 1658c2ecf20Sopenharmony_ci by the lock callback. In receive callback mode the default 1668c2ecf20Sopenharmony_ci function is release_sock for the associated socket. In general 1678c2ecf20Sopenharmony_ci mode the callback must be set appropriately. 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci :: 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci void (*rcv_msg)(struct strparser *strp, struct sk_buff *skb); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci rcv_msg is called when a full message has been received and 1748c2ecf20Sopenharmony_ci is queued. The callee must consume the sk_buff; it can 1758c2ecf20Sopenharmony_ci call strp_pause to prevent any further messages from being 1768c2ecf20Sopenharmony_ci received in rcv_msg (see strp_pause above). This callback 1778c2ecf20Sopenharmony_ci must be set. 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci The skb->cb in the input skb is a struct strp_msg. This 1808c2ecf20Sopenharmony_ci struct contains two fields: offset and full_len. Offset is 1818c2ecf20Sopenharmony_ci where the message starts in the skb, and full_len is the 1828c2ecf20Sopenharmony_ci the length of the message. skb->len - offset may be greater 1838c2ecf20Sopenharmony_ci then full_len since strparser does not trim the skb. 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci :: 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci int (*read_sock_done)(struct strparser *strp, int err); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci read_sock_done is called when the stream parser is done reading 1908c2ecf20Sopenharmony_ci the TCP socket in receive callback mode. The stream parser may 1918c2ecf20Sopenharmony_ci read multiple messages in a loop and this function allows cleanup 1928c2ecf20Sopenharmony_ci to occur when exiting the loop. If the callback is not set (NULL 1938c2ecf20Sopenharmony_ci in strp_init) a default function is used. 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci :: 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci void (*abort_parser)(struct strparser *strp, int err); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci This function is called when stream parser encounters an error 2008c2ecf20Sopenharmony_ci in parsing. The default function stops the stream parser and 2018c2ecf20Sopenharmony_ci sets the error in the socket if the parser is in receive callback 2028c2ecf20Sopenharmony_ci mode. The default function can be changed by setting the callback 2038c2ecf20Sopenharmony_ci to non-NULL in strp_init. 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ciStatistics 2068c2ecf20Sopenharmony_ci========== 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ciVarious counters are kept for each stream parser instance. These are in 2098c2ecf20Sopenharmony_cithe strp_stats structure. strp_aggr_stats is a convenience structure for 2108c2ecf20Sopenharmony_ciaccumulating statistics for multiple stream parser instances. 2118c2ecf20Sopenharmony_cisave_strp_stats and aggregate_strp_stats are helper functions to save 2128c2ecf20Sopenharmony_ciand aggregate statistics. 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ciMessage assembly limits 2158c2ecf20Sopenharmony_ci======================= 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ciThe stream parser provide mechanisms to limit the resources consumed by 2188c2ecf20Sopenharmony_cimessage assembly. 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ciA timer is set when assembly starts for a new message. In receive 2218c2ecf20Sopenharmony_cicallback mode the message timeout is taken from rcvtime for the 2228c2ecf20Sopenharmony_ciassociated TCP socket. In general mode, the timeout is passed as an 2238c2ecf20Sopenharmony_ciargument in strp_process. If the timer fires before assembly completes 2248c2ecf20Sopenharmony_cithe stream parser is aborted and the ETIMEDOUT error is set on the TCP 2258c2ecf20Sopenharmony_cisocket if in receive callback mode. 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ciIn receive callback mode, message length is limited to the receive 2288c2ecf20Sopenharmony_cibuffer size of the associated TCP socket. If the length returned by 2298c2ecf20Sopenharmony_ciparse_msg is greater than the socket buffer size then the stream parser 2308c2ecf20Sopenharmony_ciis aborted with EMSGSIZE error set on the TCP socket. Note that this 2318c2ecf20Sopenharmony_cimakes the maximum size of receive skbuffs for a socket with a stream 2328c2ecf20Sopenharmony_ciparser to be 2*sk_rcvbuf of the TCP socket. 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ciIn general mode the message length limit is passed in as an argument 2358c2ecf20Sopenharmony_cito strp_process. 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ciAuthor 2388c2ecf20Sopenharmony_ci====== 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ciTom Herbert (tom@quantonium.net) 241