| 1 | |
| 2 |
|
| 3 | =========================
|
| 4 | Stream Parser (strparser)
|
| 5 | =========================
|
| 6 |
|
| 7 | Introduction
|
| 8 | ============
|
| 9 |
|
| 10 | The stream parser (strparser) is a utility that parses messages of an
|
| 11 | application layer protocol running over a data stream. The stream
|
| 12 | parser works in conjunction with an upper layer in the kernel to provide
|
| 13 | kernel support for application layer messages. For instance, Kernel
|
| 14 | Connection Multiplexor (KCM) uses the Stream Parser to parse messages
|
| 15 | using a BPF program.
|
| 16 |
|
| 17 | The strparser works in one of two modes: receive callback or general
|
| 18 | mode.
|
| 19 |
|
| 20 | In receive callback mode, the strparser is called from the data_ready
|
| 21 | callback of a TCP socket. Messages are parsed and delivered as they are
|
| 22 | received on the socket.
|
| 23 |
|
| 24 | In general mode, a sequence of skbs are fed to strparser from an
|
| 25 | outside source. Message are parsed and delivered as the sequence is
|
| 26 | processed. This modes allows strparser to be applied to arbitrary
|
| 27 | streams of data.
|
| 28 |
|
| 29 | Interface
|
| 30 | =========
|
| 31 |
|
| 32 | The API includes a context structure, a set of callbacks, utility
|
| 33 | functions, and a data_ready function for receive callback mode. The
|
| 34 | callbacks include a parse_msg function that is called to perform
|
| 35 | parsing (e.g. BPF parsing in case of KCM), and a rcv_msg function
|
| 36 | that is called when a full message has been completed.
|
| 37 |
|
| 38 | Functions
|
| 39 | =========
|
| 40 |
|
| 41 | ::
|
| 42 |
|
| 43 | int strp_init(struct strparser *strp, struct sock *sk,
|
| 44 | const struct strp_callbacks *cb)
|
| 45 |
|
| 46 | Called to initialize a stream parser. strp is a struct of type
|
| 47 | strparser that is allocated by the upper layer. sk is the TCP
|
| 48 | socket associated with the stream parser for use with receive
|
| 49 | callback mode; in general mode this is set to NULL. Callbacks
|
| 50 | are called by the stream parser (the callbacks are listed below).
|
| 51 |
|
| 52 | ::
|
| 53 |
|
| 54 | void strp_pause(struct strparser *strp)
|
| 55 |
|
| 56 | Temporarily pause a stream parser. Message parsing is suspended
|
| 57 | and no new messages are delivered to the upper layer.
|
| 58 |
|
| 59 | ::
|
| 60 |
|
| 61 | void strp_unpause(struct strparser *strp)
|
| 62 |
|
| 63 | Unpause a paused stream parser.
|
| 64 |
|
| 65 | ::
|
| 66 |
|
| 67 | void strp_stop(struct strparser *strp);
|
| 68 |
|
| 69 | strp_stop is called to completely stop stream parser operations.
|
| 70 | This is called internally when the stream parser encounters an
|
| 71 | error, and it is called from the upper layer to stop parsing
|
| 72 | operations.
|
| 73 |
|
| 74 | ::
|
| 75 |
|
| 76 | void strp_done(struct strparser *strp);
|
| 77 |
|
| 78 | strp_done is called to release any resources held by the stream
|
| 79 | parser instance. This must be called after the stream processor
|
| 80 | has been stopped. The socket lock must not be held.
|
| 81 |
|
| 82 | ::
|
| 83 |
|
| 84 | int strp_process(struct strparser *strp, struct sk_buff *orig_skb,
|
| 85 | unsigned int orig_offset, size_t orig_len,
|
| 86 | size_t max_msg_size, long timeo)
|
| 87 |
|
| 88 | strp_process is called in general mode for a stream parser to
|
| 89 | parse an sk_buff. The number of bytes processed or a negative
|
| 90 | error number is returned. Note that strp_process does not
|
| 91 | consume the sk_buff. max_msg_size is maximum size the stream
|
| 92 | parser will parse. timeo is timeout for completing a message.
|
| 93 |
|
| 94 | ::
|
| 95 |
|
| 96 | void strp_data_ready(struct strparser *strp);
|
| 97 |
|
| 98 | The upper layer calls strp_data_ready when data is ready on
|
| 99 | the lower socket for strparser to process. This should be called
|
| 100 | from a data_ready callback that is set on the socket. Note that
|
| 101 | maximum messages size is the limit of the receive socket
|
| 102 | buffer and message timeout is the receive timeout for the socket.
|
| 103 |
|
| 104 | ::
|
| 105 |
|
| 106 | void strp_check_rcv(struct strparser *strp);
|
| 107 |
|
| 108 | strp_check_rcv is called to check for new messages on the socket.
|
| 109 | This is normally called at initialization of a stream parser
|
| 110 | instance or after strp_unpause.
|
| 111 |
|
| 112 | Callbacks
|
| 113 | =========
|
| 114 |
|
| 115 | There are seven callbacks:
|
| 116 |
|
| 117 | ::
|
| 118 |
|
| 119 | int (*parse_msg)(struct strparser *strp, struct sk_buff *skb);
|
| 120 |
|
| 121 | parse_msg is called to determine the length of the next message
|
| 122 | in the stream. The upper layer must implement this function. It
|
| 123 | should parse the sk_buff as containing the headers for the
|
| 124 | next application layer message in the stream.
|
| 125 |
|
| 126 | The strparser metadata in the input skb can be accessed with
|
| 127 | strp_msg(skb). Only the offset field is relevant in parse_msg and
|
| 128 | gives the offset where the message starts in the skb.
|
| 129 |
|
| 130 | The return values of this function are:
|
| 131 |
|
| 132 | ========= ===========================================================
|
| 133 | >0 indicates length of successfully parsed message
|
| 134 | 0 indicates more data must be received to parse the message
|
| 135 | -ESTRPIPE current message should not be processed by the
|
| 136 | kernel, return control of the socket to userspace which
|
| 137 | can proceed to read the messages itself
|
| 138 | other < 0 Error in parsing, give control back to userspace
|
| 139 | assuming that synchronization is lost and the stream
|
| 140 | is unrecoverable (application expected to close TCP socket)
|
| 141 | ========= ===========================================================
|
| 142 |
|
| 143 | In the case that an error is returned (return value is less than
|
| 144 | zero) and the parser is in receive callback mode, then it will set
|
| 145 | the error on TCP socket and wake it up. If parse_msg returned
|
| 146 | -ESTRPIPE and the stream parser had previously read some bytes for
|
| 147 | the current message, then the error set on the attached socket is
|
| 148 | ENODATA since the stream is unrecoverable in that case.
|
| 149 |
|
| 150 | ::
|
| 151 |
|
| 152 | void (*lock)(struct strparser *strp)
|
| 153 |
|
| 154 | The lock callback is called to lock the strp structure when
|
| 155 | the strparser is performing an asynchronous operation (such as
|
| 156 | processing a timeout). In receive callback mode the default
|
| 157 | function is to lock_sock for the associated socket. In general
|
| 158 | mode the callback must be set appropriately.
|
| 159 |
|
| 160 | ::
|
| 161 |
|
| 162 | void (*unlock)(struct strparser *strp)
|
| 163 |
|
| 164 | The unlock callback is called to release the lock obtained
|
| 165 | by the lock callback. In receive callback mode the default
|
| 166 | function is release_sock for the associated socket. In general
|
| 167 | mode the callback must be set appropriately.
|
| 168 |
|
| 169 | ::
|
| 170 |
|
| 171 | void (*rcv_msg)(struct strparser *strp, struct sk_buff *skb);
|
| 172 |
|
| 173 | rcv_msg is called when a full message has been received and
|
| 174 | is queued. The callee must consume the sk_buff; it can
|
| 175 | call strp_pause to prevent any further messages from being
|
| 176 | received in rcv_msg (see strp_pause above). This callback
|
| 177 | must be set.
|
| 178 |
|
| 179 | The strparser metadata in the input skb can be accessed with
|
| 180 | strp_msg(skb). This struct contains two fields: offset and full_len.
|
| 181 | Offset is where the message starts in the skb, and full_len is
|
| 182 | the length of the message. skb->len - offset may be greater than
|
| 183 | full_len since strparser does not trim the skb.
|
| 184 |
|
| 185 | ::
|
| 186 |
|
| 187 | int (*read_sock)(struct strparser *strp, read_descriptor_t *desc,
|
| 188 | sk_read_actor_t recv_actor);
|
| 189 |
|
| 190 | The read_sock callback is used by strparser instead of
|
| 191 | sock->ops->read_sock, if provided.
|
| 192 | ::
|
| 193 |
|
| 194 | int (*read_sock_done)(struct strparser *strp, int err);
|
| 195 |
|
| 196 | read_sock_done is called when the stream parser is done reading
|
| 197 | the TCP socket in receive callback mode. The stream parser may
|
| 198 | read multiple messages in a loop and this function allows cleanup
|
| 199 | to occur when exiting the loop. If the callback is not set (NULL
|
| 200 | in strp_init) a default function is used.
|
| 201 |
|
| 202 | ::
|
| 203 |
|
| 204 | void (*abort_parser)(struct strparser *strp, int err);
|
| 205 |
|
| 206 | This function is called when stream parser encounters an error
|
| 207 | in parsing. The default function stops the stream parser and
|
| 208 | sets the error in the socket if the parser is in receive callback
|
| 209 | mode. The default function can be changed by setting the callback
|
| 210 | to non-NULL in strp_init.
|
| 211 |
|
| 212 | Statistics
|
| 213 | ==========
|
| 214 |
|
| 215 | Various counters are kept for each stream parser instance. These are in
|
| 216 | the strp_stats structure. strp_aggr_stats is a convenience structure for
|
| 217 | accumulating statistics for multiple stream parser instances.
|
| 218 | save_strp_stats and aggregate_strp_stats are helper functions to save
|
| 219 | and aggregate statistics.
|
| 220 |
|
| 221 | Message assembly limits
|
| 222 | =======================
|
| 223 |
|
| 224 | The stream parser provide mechanisms to limit the resources consumed by
|
| 225 | message assembly.
|
| 226 |
|
| 227 | A timer is set when assembly starts for a new message. In receive
|
| 228 | callback mode the message timeout is taken from rcvtime for the
|
| 229 | associated TCP socket. In general mode, the timeout is passed as an
|
| 230 | argument in strp_process. If the timer fires before assembly completes
|
| 231 | the stream parser is aborted and the ETIMEDOUT error is set on the TCP
|
| 232 | socket if in receive callback mode.
|
| 233 |
|
| 234 | In receive callback mode, message length is limited to the receive
|
| 235 | buffer size of the associated TCP socket. If the length returned by
|
| 236 | parse_msg is greater than the socket buffer size then the stream parser
|
| 237 | is aborted with EMSGSIZE error set on the TCP socket. Note that this
|
| 238 | makes the maximum size of receive skbuffs for a socket with a stream
|
| 239 | parser to be 2*sk_rcvbuf of the TCP socket.
|
| 240 |
|
| 241 | In general mode the message length limit is passed in as an argument
|
| 242 | to strp_process.
|
| 243 |
|
| 244 | Author
|
| 245 | ======
|
| 246 |
|
| 247 | Tom Herbert ([email protected])
|