linux/include/net/strparser.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * Stream Parser
   4 *
   5 * Copyright (c) 2016 Tom Herbert <tom@herbertland.com>
   6 */
   7
   8#ifndef __NET_STRPARSER_H_
   9#define __NET_STRPARSER_H_
  10
  11#include <linux/skbuff.h>
  12#include <net/sock.h>
  13
  14#define STRP_STATS_ADD(stat, count) ((stat) += (count))
  15#define STRP_STATS_INCR(stat) ((stat)++)
  16
  17struct strp_stats {
  18        unsigned long long msgs;
  19        unsigned long long bytes;
  20        unsigned int mem_fail;
  21        unsigned int need_more_hdr;
  22        unsigned int msg_too_big;
  23        unsigned int msg_timeouts;
  24        unsigned int bad_hdr_len;
  25};
  26
  27struct strp_aggr_stats {
  28        unsigned long long msgs;
  29        unsigned long long bytes;
  30        unsigned int mem_fail;
  31        unsigned int need_more_hdr;
  32        unsigned int msg_too_big;
  33        unsigned int msg_timeouts;
  34        unsigned int bad_hdr_len;
  35        unsigned int aborts;
  36        unsigned int interrupted;
  37        unsigned int unrecov_intr;
  38};
  39
  40struct strparser;
  41
  42/* Callbacks are called with lock held for the attached socket */
  43struct strp_callbacks {
  44        int (*parse_msg)(struct strparser *strp, struct sk_buff *skb);
  45        void (*rcv_msg)(struct strparser *strp, struct sk_buff *skb);
  46        int (*read_sock_done)(struct strparser *strp, int err);
  47        void (*abort_parser)(struct strparser *strp, int err);
  48        void (*lock)(struct strparser *strp);
  49        void (*unlock)(struct strparser *strp);
  50};
  51
  52struct strp_msg {
  53        int full_len;
  54        int offset;
  55};
  56
  57struct _strp_msg {
  58        /* Internal cb structure. struct strp_msg must be first for passing
  59         * to upper layer.
  60         */
  61        struct strp_msg strp;
  62        int accum_len;
  63};
  64
  65struct sk_skb_cb {
  66#define SK_SKB_CB_PRIV_LEN 20
  67        unsigned char data[SK_SKB_CB_PRIV_LEN];
  68        struct _strp_msg strp;
  69        /* temp_reg is a temporary register used for bpf_convert_data_end_access
  70         * when dst_reg == src_reg.
  71         */
  72        u64 temp_reg;
  73};
  74
  75static inline struct strp_msg *strp_msg(struct sk_buff *skb)
  76{
  77        return (struct strp_msg *)((void *)skb->cb +
  78                offsetof(struct sk_skb_cb, strp));
  79}
  80
  81/* Structure for an attached lower socket */
  82struct strparser {
  83        struct sock *sk;
  84
  85        u32 stopped : 1;
  86        u32 paused : 1;
  87        u32 aborted : 1;
  88        u32 interrupted : 1;
  89        u32 unrecov_intr : 1;
  90
  91        struct sk_buff **skb_nextp;
  92        struct sk_buff *skb_head;
  93        unsigned int need_bytes;
  94        struct delayed_work msg_timer_work;
  95        struct work_struct work;
  96        struct strp_stats stats;
  97        struct strp_callbacks cb;
  98};
  99
 100/* Must be called with lock held for attached socket */
 101static inline void strp_pause(struct strparser *strp)
 102{
 103        strp->paused = 1;
 104}
 105
 106/* May be called without holding lock for attached socket */
 107void strp_unpause(struct strparser *strp);
 108/* Must be called with process lock held (lock_sock) */
 109void __strp_unpause(struct strparser *strp);
 110
 111static inline void save_strp_stats(struct strparser *strp,
 112                                   struct strp_aggr_stats *agg_stats)
 113{
 114        /* Save psock statistics in the mux when psock is being unattached. */
 115
 116#define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat +=            \
 117                                 strp->stats._stat)
 118        SAVE_PSOCK_STATS(msgs);
 119        SAVE_PSOCK_STATS(bytes);
 120        SAVE_PSOCK_STATS(mem_fail);
 121        SAVE_PSOCK_STATS(need_more_hdr);
 122        SAVE_PSOCK_STATS(msg_too_big);
 123        SAVE_PSOCK_STATS(msg_timeouts);
 124        SAVE_PSOCK_STATS(bad_hdr_len);
 125#undef SAVE_PSOCK_STATS
 126
 127        if (strp->aborted)
 128                agg_stats->aborts++;
 129        if (strp->interrupted)
 130                agg_stats->interrupted++;
 131        if (strp->unrecov_intr)
 132                agg_stats->unrecov_intr++;
 133}
 134
 135static inline void aggregate_strp_stats(struct strp_aggr_stats *stats,
 136                                        struct strp_aggr_stats *agg_stats)
 137{
 138#define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat += stats->_stat)
 139        SAVE_PSOCK_STATS(msgs);
 140        SAVE_PSOCK_STATS(bytes);
 141        SAVE_PSOCK_STATS(mem_fail);
 142        SAVE_PSOCK_STATS(need_more_hdr);
 143        SAVE_PSOCK_STATS(msg_too_big);
 144        SAVE_PSOCK_STATS(msg_timeouts);
 145        SAVE_PSOCK_STATS(bad_hdr_len);
 146        SAVE_PSOCK_STATS(aborts);
 147        SAVE_PSOCK_STATS(interrupted);
 148        SAVE_PSOCK_STATS(unrecov_intr);
 149#undef SAVE_PSOCK_STATS
 150
 151}
 152
 153void strp_done(struct strparser *strp);
 154void strp_stop(struct strparser *strp);
 155void strp_check_rcv(struct strparser *strp);
 156int strp_init(struct strparser *strp, struct sock *sk,
 157              const struct strp_callbacks *cb);
 158void strp_data_ready(struct strparser *strp);
 159int strp_process(struct strparser *strp, struct sk_buff *orig_skb,
 160                 unsigned int orig_offset, size_t orig_len,
 161                 size_t max_msg_size, long timeo);
 162
 163#endif /* __NET_STRPARSER_H_ */
 164