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 17 struct 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 27 struct 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 interrupted; 36 unsigned int unrecov_intr; 37 }; 38 39 struct strparser; 40 41 /* Callbacks are called with lock held for the attached socket */ 42 struct strp_callbacks { 43 int (*parse_msg)(struct strparser *strp, struct sk_buff *skb); 44 void (*rcv_msg)(struct strparser *strp, struct sk_buff *skb); 45 int (*read_sock)(struct strparser *strp, read_descriptor_t *desc, 46 sk_read_actor_t recv_actor); 47 int (*read_sock_done)(struct strparser *strp, int err); 48 }; 49 50 struct strp_msg { 51 int full_len; 52 int offset; 53 }; 54 55 struct _strp_msg { 56 /* Internal cb structure. struct strp_msg must be first for passing 57 * to upper layer. 58 */ 59 struct strp_msg strp; 60 int accum_len; 61 }; 62 63 struct sk_skb_cb { 64 #define SK_SKB_CB_PRIV_LEN 20 65 unsigned char data[SK_SKB_CB_PRIV_LEN]; 66 /* align strp on cache line boundary within skb->cb[] */ 67 unsigned char pad[4]; 68 struct _strp_msg strp; 69 70 /* strp users' data follows */ 71 struct tls_msg { 72 u8 control; 73 } tls; 74 /* temp_reg is a temporary register used for bpf_convert_data_end_access 75 * when dst_reg == src_reg. 76 */ 77 u64 temp_reg; 78 }; 79 80 static inline struct strp_msg *strp_msg(struct sk_buff *skb) 81 { 82 return (struct strp_msg *)((void *)skb->cb + 83 offsetof(struct sk_skb_cb, strp)); 84 } 85 86 /* Structure for an attached lower socket */ 87 struct strparser { 88 struct sock *sk; 89 90 u8 stopped; 91 u8 paused; 92 u8 interrupted; 93 u8 unrecov_intr; 94 95 struct sk_buff **skb_nextp; 96 struct sk_buff *skb_head; 97 unsigned int need_bytes; 98 struct delayed_work msg_timer_work; 99 struct work_struct work; 100 struct strp_stats stats; 101 struct strp_callbacks cb; 102 }; 103 104 /* Must be called with lock held for attached socket */ 105 static inline void strp_pause(struct strparser *strp) 106 { 107 strp->paused = 1; 108 } 109 110 /* May be called without holding lock for attached socket */ 111 void strp_unpause(struct strparser *strp); 112 113 static inline void save_strp_stats(struct strparser *strp, 114 struct strp_aggr_stats *agg_stats) 115 { 116 /* Save psock statistics in the mux when psock is being unattached. */ 117 118 #define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat += \ 119 strp->stats._stat) 120 SAVE_PSOCK_STATS(msgs); 121 SAVE_PSOCK_STATS(bytes); 122 SAVE_PSOCK_STATS(mem_fail); 123 SAVE_PSOCK_STATS(need_more_hdr); 124 SAVE_PSOCK_STATS(msg_too_big); 125 SAVE_PSOCK_STATS(msg_timeouts); 126 SAVE_PSOCK_STATS(bad_hdr_len); 127 #undef SAVE_PSOCK_STATS 128 129 if (strp->interrupted) 130 agg_stats->interrupted++; 131 if (strp->unrecov_intr) 132 agg_stats->unrecov_intr++; 133 } 134 135 static 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(interrupted); 147 SAVE_PSOCK_STATS(unrecov_intr); 148 #undef SAVE_PSOCK_STATS 149 150 } 151 152 void strp_done(struct strparser *strp); 153 void strp_stop(struct strparser *strp); 154 void strp_check_rcv(struct strparser *strp); 155 int strp_init(struct strparser *strp, struct sock *sk, 156 const struct strp_callbacks *cb); 157 void strp_data_ready(struct strparser *strp); 158 159 #endif /* __NET_STRPARSER_H_ */ 160