1 /* 2 * Stream Parser 3 * 4 * Copyright (c) 2016 Tom Herbert <tom@herbertland.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 8 * as published by the Free Software Foundation. 9 */ 10 11 #ifndef __NET_STRPARSER_H_ 12 #define __NET_STRPARSER_H_ 13 14 #include <linux/skbuff.h> 15 #include <net/sock.h> 16 17 #define STRP_STATS_ADD(stat, count) ((stat) += (count)) 18 #define STRP_STATS_INCR(stat) ((stat)++) 19 20 struct strp_stats { 21 unsigned long long msgs; 22 unsigned long long bytes; 23 unsigned int mem_fail; 24 unsigned int need_more_hdr; 25 unsigned int msg_too_big; 26 unsigned int msg_timeouts; 27 unsigned int bad_hdr_len; 28 }; 29 30 struct strp_aggr_stats { 31 unsigned long long msgs; 32 unsigned long long bytes; 33 unsigned int mem_fail; 34 unsigned int need_more_hdr; 35 unsigned int msg_too_big; 36 unsigned int msg_timeouts; 37 unsigned int bad_hdr_len; 38 unsigned int aborts; 39 unsigned int interrupted; 40 unsigned int unrecov_intr; 41 }; 42 43 struct strparser; 44 45 /* Callbacks are called with lock held for the attached socket */ 46 struct strp_callbacks { 47 int (*parse_msg)(struct strparser *strp, struct sk_buff *skb); 48 void (*rcv_msg)(struct strparser *strp, struct sk_buff *skb); 49 int (*read_sock_done)(struct strparser *strp, int err); 50 void (*abort_parser)(struct strparser *strp, int err); 51 void (*lock)(struct strparser *strp); 52 void (*unlock)(struct strparser *strp); 53 }; 54 55 struct strp_msg { 56 int full_len; 57 int offset; 58 }; 59 60 static inline struct strp_msg *strp_msg(struct sk_buff *skb) 61 { 62 return (struct strp_msg *)((void *)skb->cb + 63 offsetof(struct qdisc_skb_cb, data)); 64 } 65 66 /* Structure for an attached lower socket */ 67 struct strparser { 68 struct sock *sk; 69 70 u32 stopped : 1; 71 u32 paused : 1; 72 u32 aborted : 1; 73 u32 interrupted : 1; 74 u32 unrecov_intr : 1; 75 76 struct sk_buff **skb_nextp; 77 struct sk_buff *skb_head; 78 unsigned int need_bytes; 79 struct delayed_work msg_timer_work; 80 struct work_struct work; 81 struct strp_stats stats; 82 struct strp_callbacks cb; 83 }; 84 85 /* Must be called with lock held for attached socket */ 86 static inline void strp_pause(struct strparser *strp) 87 { 88 strp->paused = 1; 89 } 90 91 /* May be called without holding lock for attached socket */ 92 void strp_unpause(struct strparser *strp); 93 94 static inline void save_strp_stats(struct strparser *strp, 95 struct strp_aggr_stats *agg_stats) 96 { 97 /* Save psock statistics in the mux when psock is being unattached. */ 98 99 #define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat += \ 100 strp->stats._stat) 101 SAVE_PSOCK_STATS(msgs); 102 SAVE_PSOCK_STATS(bytes); 103 SAVE_PSOCK_STATS(mem_fail); 104 SAVE_PSOCK_STATS(need_more_hdr); 105 SAVE_PSOCK_STATS(msg_too_big); 106 SAVE_PSOCK_STATS(msg_timeouts); 107 SAVE_PSOCK_STATS(bad_hdr_len); 108 #undef SAVE_PSOCK_STATS 109 110 if (strp->aborted) 111 agg_stats->aborts++; 112 if (strp->interrupted) 113 agg_stats->interrupted++; 114 if (strp->unrecov_intr) 115 agg_stats->unrecov_intr++; 116 } 117 118 static inline void aggregate_strp_stats(struct strp_aggr_stats *stats, 119 struct strp_aggr_stats *agg_stats) 120 { 121 #define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat += stats->_stat) 122 SAVE_PSOCK_STATS(msgs); 123 SAVE_PSOCK_STATS(bytes); 124 SAVE_PSOCK_STATS(mem_fail); 125 SAVE_PSOCK_STATS(need_more_hdr); 126 SAVE_PSOCK_STATS(msg_too_big); 127 SAVE_PSOCK_STATS(msg_timeouts); 128 SAVE_PSOCK_STATS(bad_hdr_len); 129 SAVE_PSOCK_STATS(aborts); 130 SAVE_PSOCK_STATS(interrupted); 131 SAVE_PSOCK_STATS(unrecov_intr); 132 #undef SAVE_PSOCK_STATS 133 134 } 135 136 void strp_done(struct strparser *strp); 137 void strp_stop(struct strparser *strp); 138 void strp_check_rcv(struct strparser *strp); 139 int strp_init(struct strparser *strp, struct sock *sk, 140 const struct strp_callbacks *cb); 141 void strp_data_ready(struct strparser *strp); 142 int strp_process(struct strparser *strp, struct sk_buff *orig_skb, 143 unsigned int orig_offset, size_t orig_len, 144 size_t max_msg_size, long timeo); 145 146 #endif /* __NET_STRPARSER_H_ */ 147