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 rx_msgs; 22 unsigned long long rx_bytes; 23 unsigned int rx_mem_fail; 24 unsigned int rx_need_more_hdr; 25 unsigned int rx_msg_too_big; 26 unsigned int rx_msg_timeouts; 27 unsigned int rx_bad_hdr_len; 28 }; 29 30 struct strp_aggr_stats { 31 unsigned long long rx_msgs; 32 unsigned long long rx_bytes; 33 unsigned int rx_mem_fail; 34 unsigned int rx_need_more_hdr; 35 unsigned int rx_msg_too_big; 36 unsigned int rx_msg_timeouts; 37 unsigned int rx_bad_hdr_len; 38 unsigned int rx_aborts; 39 unsigned int rx_interrupted; 40 unsigned int rx_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 }; 52 53 struct strp_rx_msg { 54 int full_len; 55 int offset; 56 }; 57 58 static inline struct strp_rx_msg *strp_rx_msg(struct sk_buff *skb) 59 { 60 return (struct strp_rx_msg *)((void *)skb->cb + 61 offsetof(struct qdisc_skb_cb, data)); 62 } 63 64 /* Structure for an attached lower socket */ 65 struct strparser { 66 struct sock *sk; 67 68 u32 rx_stopped : 1; 69 u32 rx_paused : 1; 70 u32 rx_aborted : 1; 71 u32 rx_interrupted : 1; 72 u32 rx_unrecov_intr : 1; 73 74 struct sk_buff **rx_skb_nextp; 75 struct timer_list rx_msg_timer; 76 struct sk_buff *rx_skb_head; 77 unsigned int rx_need_bytes; 78 struct delayed_work rx_delayed_work; 79 struct work_struct rx_work; 80 struct strp_stats stats; 81 struct strp_callbacks cb; 82 }; 83 84 /* Must be called with lock held for attached socket */ 85 static inline void strp_pause(struct strparser *strp) 86 { 87 strp->rx_paused = 1; 88 } 89 90 /* May be called without holding lock for attached socket */ 91 void strp_unpause(struct strparser *strp); 92 93 static inline void save_strp_stats(struct strparser *strp, 94 struct strp_aggr_stats *agg_stats) 95 { 96 /* Save psock statistics in the mux when psock is being unattached. */ 97 98 #define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat += \ 99 strp->stats._stat) 100 SAVE_PSOCK_STATS(rx_msgs); 101 SAVE_PSOCK_STATS(rx_bytes); 102 SAVE_PSOCK_STATS(rx_mem_fail); 103 SAVE_PSOCK_STATS(rx_need_more_hdr); 104 SAVE_PSOCK_STATS(rx_msg_too_big); 105 SAVE_PSOCK_STATS(rx_msg_timeouts); 106 SAVE_PSOCK_STATS(rx_bad_hdr_len); 107 #undef SAVE_PSOCK_STATS 108 109 if (strp->rx_aborted) 110 agg_stats->rx_aborts++; 111 if (strp->rx_interrupted) 112 agg_stats->rx_interrupted++; 113 if (strp->rx_unrecov_intr) 114 agg_stats->rx_unrecov_intr++; 115 } 116 117 static inline void aggregate_strp_stats(struct strp_aggr_stats *stats, 118 struct strp_aggr_stats *agg_stats) 119 { 120 #define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat += stats->_stat) 121 SAVE_PSOCK_STATS(rx_msgs); 122 SAVE_PSOCK_STATS(rx_bytes); 123 SAVE_PSOCK_STATS(rx_mem_fail); 124 SAVE_PSOCK_STATS(rx_need_more_hdr); 125 SAVE_PSOCK_STATS(rx_msg_too_big); 126 SAVE_PSOCK_STATS(rx_msg_timeouts); 127 SAVE_PSOCK_STATS(rx_bad_hdr_len); 128 SAVE_PSOCK_STATS(rx_aborts); 129 SAVE_PSOCK_STATS(rx_interrupted); 130 SAVE_PSOCK_STATS(rx_unrecov_intr); 131 #undef SAVE_PSOCK_STATS 132 133 } 134 135 void strp_done(struct strparser *strp); 136 void strp_stop(struct strparser *strp); 137 void strp_check_rcv(struct strparser *strp); 138 int strp_init(struct strparser *strp, struct sock *csk, 139 struct strp_callbacks *cb); 140 void strp_data_ready(struct strparser *strp); 141 142 #endif /* __NET_STRPARSER_H_ */ 143