Commit bbb03029 authored by Tom Herbert's avatar Tom Herbert Committed by David S. Miller

strparser: Generalize strparser

Generalize strparser from more than just being used in conjunction
with read_sock. strparser will also be used in the send path with
zero proxy. The primary change is to create strp_process function
that performs the critical processing on skbs. The documentation
is also updated to reflect the new uses.
Signed-off-by: default avatarTom Herbert <tom@quantonium.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 20bf50de
This diff is collapsed.
...@@ -18,26 +18,26 @@ ...@@ -18,26 +18,26 @@
#define STRP_STATS_INCR(stat) ((stat)++) #define STRP_STATS_INCR(stat) ((stat)++)
struct strp_stats { struct strp_stats {
unsigned long long rx_msgs; unsigned long long msgs;
unsigned long long rx_bytes; unsigned long long bytes;
unsigned int rx_mem_fail; unsigned int mem_fail;
unsigned int rx_need_more_hdr; unsigned int need_more_hdr;
unsigned int rx_msg_too_big; unsigned int msg_too_big;
unsigned int rx_msg_timeouts; unsigned int msg_timeouts;
unsigned int rx_bad_hdr_len; unsigned int bad_hdr_len;
}; };
struct strp_aggr_stats { struct strp_aggr_stats {
unsigned long long rx_msgs; unsigned long long msgs;
unsigned long long rx_bytes; unsigned long long bytes;
unsigned int rx_mem_fail; unsigned int mem_fail;
unsigned int rx_need_more_hdr; unsigned int need_more_hdr;
unsigned int rx_msg_too_big; unsigned int msg_too_big;
unsigned int rx_msg_timeouts; unsigned int msg_timeouts;
unsigned int rx_bad_hdr_len; unsigned int bad_hdr_len;
unsigned int rx_aborts; unsigned int aborts;
unsigned int rx_interrupted; unsigned int interrupted;
unsigned int rx_unrecov_intr; unsigned int unrecov_intr;
}; };
struct strparser; struct strparser;
...@@ -48,16 +48,18 @@ struct strp_callbacks { ...@@ -48,16 +48,18 @@ struct strp_callbacks {
void (*rcv_msg)(struct strparser *strp, struct sk_buff *skb); void (*rcv_msg)(struct strparser *strp, struct sk_buff *skb);
int (*read_sock_done)(struct strparser *strp, int err); int (*read_sock_done)(struct strparser *strp, int err);
void (*abort_parser)(struct strparser *strp, int err); void (*abort_parser)(struct strparser *strp, int err);
void (*lock)(struct strparser *strp);
void (*unlock)(struct strparser *strp);
}; };
struct strp_rx_msg { struct strp_msg {
int full_len; int full_len;
int offset; int offset;
}; };
static inline struct strp_rx_msg *strp_rx_msg(struct sk_buff *skb) static inline struct strp_msg *strp_msg(struct sk_buff *skb)
{ {
return (struct strp_rx_msg *)((void *)skb->cb + return (struct strp_msg *)((void *)skb->cb +
offsetof(struct qdisc_skb_cb, data)); offsetof(struct qdisc_skb_cb, data));
} }
...@@ -65,18 +67,18 @@ static inline struct strp_rx_msg *strp_rx_msg(struct sk_buff *skb) ...@@ -65,18 +67,18 @@ static inline struct strp_rx_msg *strp_rx_msg(struct sk_buff *skb)
struct strparser { struct strparser {
struct sock *sk; struct sock *sk;
u32 rx_stopped : 1; u32 stopped : 1;
u32 rx_paused : 1; u32 paused : 1;
u32 rx_aborted : 1; u32 aborted : 1;
u32 rx_interrupted : 1; u32 interrupted : 1;
u32 rx_unrecov_intr : 1; u32 unrecov_intr : 1;
struct sk_buff **rx_skb_nextp; struct sk_buff **skb_nextp;
struct timer_list rx_msg_timer; struct timer_list msg_timer;
struct sk_buff *rx_skb_head; struct sk_buff *skb_head;
unsigned int rx_need_bytes; unsigned int need_bytes;
struct delayed_work rx_delayed_work; struct delayed_work delayed_work;
struct work_struct rx_work; struct work_struct work;
struct strp_stats stats; struct strp_stats stats;
struct strp_callbacks cb; struct strp_callbacks cb;
}; };
...@@ -84,7 +86,7 @@ struct strparser { ...@@ -84,7 +86,7 @@ struct strparser {
/* Must be called with lock held for attached socket */ /* Must be called with lock held for attached socket */
static inline void strp_pause(struct strparser *strp) static inline void strp_pause(struct strparser *strp)
{ {
strp->rx_paused = 1; strp->paused = 1;
} }
/* May be called without holding lock for attached socket */ /* May be called without holding lock for attached socket */
...@@ -97,37 +99,37 @@ static inline void save_strp_stats(struct strparser *strp, ...@@ -97,37 +99,37 @@ static inline void save_strp_stats(struct strparser *strp,
#define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat += \ #define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat += \
strp->stats._stat) strp->stats._stat)
SAVE_PSOCK_STATS(rx_msgs); SAVE_PSOCK_STATS(msgs);
SAVE_PSOCK_STATS(rx_bytes); SAVE_PSOCK_STATS(bytes);
SAVE_PSOCK_STATS(rx_mem_fail); SAVE_PSOCK_STATS(mem_fail);
SAVE_PSOCK_STATS(rx_need_more_hdr); SAVE_PSOCK_STATS(need_more_hdr);
SAVE_PSOCK_STATS(rx_msg_too_big); SAVE_PSOCK_STATS(msg_too_big);
SAVE_PSOCK_STATS(rx_msg_timeouts); SAVE_PSOCK_STATS(msg_timeouts);
SAVE_PSOCK_STATS(rx_bad_hdr_len); SAVE_PSOCK_STATS(bad_hdr_len);
#undef SAVE_PSOCK_STATS #undef SAVE_PSOCK_STATS
if (strp->rx_aborted) if (strp->aborted)
agg_stats->rx_aborts++; agg_stats->aborts++;
if (strp->rx_interrupted) if (strp->interrupted)
agg_stats->rx_interrupted++; agg_stats->interrupted++;
if (strp->rx_unrecov_intr) if (strp->unrecov_intr)
agg_stats->rx_unrecov_intr++; agg_stats->unrecov_intr++;
} }
static inline void aggregate_strp_stats(struct strp_aggr_stats *stats, static inline void aggregate_strp_stats(struct strp_aggr_stats *stats,
struct strp_aggr_stats *agg_stats) struct strp_aggr_stats *agg_stats)
{ {
#define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat += stats->_stat) #define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat += stats->_stat)
SAVE_PSOCK_STATS(rx_msgs); SAVE_PSOCK_STATS(msgs);
SAVE_PSOCK_STATS(rx_bytes); SAVE_PSOCK_STATS(bytes);
SAVE_PSOCK_STATS(rx_mem_fail); SAVE_PSOCK_STATS(mem_fail);
SAVE_PSOCK_STATS(rx_need_more_hdr); SAVE_PSOCK_STATS(need_more_hdr);
SAVE_PSOCK_STATS(rx_msg_too_big); SAVE_PSOCK_STATS(msg_too_big);
SAVE_PSOCK_STATS(rx_msg_timeouts); SAVE_PSOCK_STATS(msg_timeouts);
SAVE_PSOCK_STATS(rx_bad_hdr_len); SAVE_PSOCK_STATS(bad_hdr_len);
SAVE_PSOCK_STATS(rx_aborts); SAVE_PSOCK_STATS(aborts);
SAVE_PSOCK_STATS(rx_interrupted); SAVE_PSOCK_STATS(interrupted);
SAVE_PSOCK_STATS(rx_unrecov_intr); SAVE_PSOCK_STATS(unrecov_intr);
#undef SAVE_PSOCK_STATS #undef SAVE_PSOCK_STATS
} }
...@@ -135,8 +137,11 @@ static inline void aggregate_strp_stats(struct strp_aggr_stats *stats, ...@@ -135,8 +137,11 @@ static inline void aggregate_strp_stats(struct strp_aggr_stats *stats,
void strp_done(struct strparser *strp); void strp_done(struct strparser *strp);
void strp_stop(struct strparser *strp); void strp_stop(struct strparser *strp);
void strp_check_rcv(struct strparser *strp); void strp_check_rcv(struct strparser *strp);
int strp_init(struct strparser *strp, struct sock *csk, int strp_init(struct strparser *strp, struct sock *sk,
struct strp_callbacks *cb); struct strp_callbacks *cb);
void strp_data_ready(struct strparser *strp); void strp_data_ready(struct strparser *strp);
int strp_process(struct strparser *strp, struct sk_buff *orig_skb,
unsigned int orig_offset, size_t orig_len,
size_t max_msg_size, long timeo);
#endif /* __NET_STRPARSER_H_ */ #endif /* __NET_STRPARSER_H_ */
...@@ -155,8 +155,8 @@ static void kcm_format_psock(struct kcm_psock *psock, struct seq_file *seq, ...@@ -155,8 +155,8 @@ static void kcm_format_psock(struct kcm_psock *psock, struct seq_file *seq,
seq_printf(seq, seq_printf(seq,
" psock-%-5u %-10llu %-16llu %-10llu %-16llu %-8d %-8d %-8d %-8d ", " psock-%-5u %-10llu %-16llu %-10llu %-16llu %-8d %-8d %-8d %-8d ",
psock->index, psock->index,
psock->strp.stats.rx_msgs, psock->strp.stats.msgs,
psock->strp.stats.rx_bytes, psock->strp.stats.bytes,
psock->stats.tx_msgs, psock->stats.tx_msgs,
psock->stats.tx_bytes, psock->stats.tx_bytes,
psock->sk->sk_receive_queue.qlen, psock->sk->sk_receive_queue.qlen,
...@@ -170,22 +170,22 @@ static void kcm_format_psock(struct kcm_psock *psock, struct seq_file *seq, ...@@ -170,22 +170,22 @@ static void kcm_format_psock(struct kcm_psock *psock, struct seq_file *seq,
if (psock->tx_stopped) if (psock->tx_stopped)
seq_puts(seq, "TxStop "); seq_puts(seq, "TxStop ");
if (psock->strp.rx_stopped) if (psock->strp.stopped)
seq_puts(seq, "RxStop "); seq_puts(seq, "RxStop ");
if (psock->tx_kcm) if (psock->tx_kcm)
seq_printf(seq, "Rsvd-%d ", psock->tx_kcm->index); seq_printf(seq, "Rsvd-%d ", psock->tx_kcm->index);
if (!psock->strp.rx_paused && !psock->ready_rx_msg) { if (!psock->strp.paused && !psock->ready_rx_msg) {
if (psock->sk->sk_receive_queue.qlen) { if (psock->sk->sk_receive_queue.qlen) {
if (psock->strp.rx_need_bytes) if (psock->strp.need_bytes)
seq_printf(seq, "RxWait=%u ", seq_printf(seq, "RxWait=%u ",
psock->strp.rx_need_bytes); psock->strp.need_bytes);
else else
seq_printf(seq, "RxWait "); seq_printf(seq, "RxWait ");
} }
} else { } else {
if (psock->strp.rx_paused) if (psock->strp.paused)
seq_puts(seq, "RxPause "); seq_puts(seq, "RxPause ");
if (psock->ready_rx_msg) if (psock->ready_rx_msg)
...@@ -371,20 +371,20 @@ static int kcm_stats_seq_show(struct seq_file *seq, void *v) ...@@ -371,20 +371,20 @@ static int kcm_stats_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, seq_printf(seq,
"%-8s %-10llu %-16llu %-10llu %-16llu %-10llu %-10llu %-10u %-10u %-10u %-10u %-10u %-10u %-10u %-10u %-10u\n", "%-8s %-10llu %-16llu %-10llu %-16llu %-10llu %-10llu %-10u %-10u %-10u %-10u %-10u %-10u %-10u %-10u %-10u\n",
"", "",
strp_stats.rx_msgs, strp_stats.msgs,
strp_stats.rx_bytes, strp_stats.bytes,
psock_stats.tx_msgs, psock_stats.tx_msgs,
psock_stats.tx_bytes, psock_stats.tx_bytes,
psock_stats.reserved, psock_stats.reserved,
psock_stats.unreserved, psock_stats.unreserved,
strp_stats.rx_aborts, strp_stats.aborts,
strp_stats.rx_interrupted, strp_stats.interrupted,
strp_stats.rx_unrecov_intr, strp_stats.unrecov_intr,
strp_stats.rx_mem_fail, strp_stats.mem_fail,
strp_stats.rx_need_more_hdr, strp_stats.need_more_hdr,
strp_stats.rx_bad_hdr_len, strp_stats.bad_hdr_len,
strp_stats.rx_msg_too_big, strp_stats.msg_too_big,
strp_stats.rx_msg_timeouts, strp_stats.msg_timeouts,
psock_stats.tx_aborts); psock_stats.tx_aborts);
return 0; return 0;
......
...@@ -96,12 +96,12 @@ static void kcm_update_rx_mux_stats(struct kcm_mux *mux, ...@@ -96,12 +96,12 @@ static void kcm_update_rx_mux_stats(struct kcm_mux *mux,
struct kcm_psock *psock) struct kcm_psock *psock)
{ {
STRP_STATS_ADD(mux->stats.rx_bytes, STRP_STATS_ADD(mux->stats.rx_bytes,
psock->strp.stats.rx_bytes - psock->strp.stats.bytes -
psock->saved_rx_bytes); psock->saved_rx_bytes);
mux->stats.rx_msgs += mux->stats.rx_msgs +=
psock->strp.stats.rx_msgs - psock->saved_rx_msgs; psock->strp.stats.msgs - psock->saved_rx_msgs;
psock->saved_rx_msgs = psock->strp.stats.rx_msgs; psock->saved_rx_msgs = psock->strp.stats.msgs;
psock->saved_rx_bytes = psock->strp.stats.rx_bytes; psock->saved_rx_bytes = psock->strp.stats.bytes;
} }
static void kcm_update_tx_mux_stats(struct kcm_mux *mux, static void kcm_update_tx_mux_stats(struct kcm_mux *mux,
...@@ -1118,7 +1118,7 @@ static int kcm_recvmsg(struct socket *sock, struct msghdr *msg, ...@@ -1118,7 +1118,7 @@ static int kcm_recvmsg(struct socket *sock, struct msghdr *msg,
struct kcm_sock *kcm = kcm_sk(sk); struct kcm_sock *kcm = kcm_sk(sk);
int err = 0; int err = 0;
long timeo; long timeo;
struct strp_rx_msg *rxm; struct strp_msg *stm;
int copied = 0; int copied = 0;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -1132,26 +1132,26 @@ static int kcm_recvmsg(struct socket *sock, struct msghdr *msg, ...@@ -1132,26 +1132,26 @@ static int kcm_recvmsg(struct socket *sock, struct msghdr *msg,
/* Okay, have a message on the receive queue */ /* Okay, have a message on the receive queue */
rxm = strp_rx_msg(skb); stm = strp_msg(skb);
if (len > rxm->full_len) if (len > stm->full_len)
len = rxm->full_len; len = stm->full_len;
err = skb_copy_datagram_msg(skb, rxm->offset, msg, len); err = skb_copy_datagram_msg(skb, stm->offset, msg, len);
if (err < 0) if (err < 0)
goto out; goto out;
copied = len; copied = len;
if (likely(!(flags & MSG_PEEK))) { if (likely(!(flags & MSG_PEEK))) {
KCM_STATS_ADD(kcm->stats.rx_bytes, copied); KCM_STATS_ADD(kcm->stats.rx_bytes, copied);
if (copied < rxm->full_len) { if (copied < stm->full_len) {
if (sock->type == SOCK_DGRAM) { if (sock->type == SOCK_DGRAM) {
/* Truncated message */ /* Truncated message */
msg->msg_flags |= MSG_TRUNC; msg->msg_flags |= MSG_TRUNC;
goto msg_finished; goto msg_finished;
} }
rxm->offset += copied; stm->offset += copied;
rxm->full_len -= copied; stm->full_len -= copied;
} else { } else {
msg_finished: msg_finished:
/* Finished with message */ /* Finished with message */
...@@ -1175,7 +1175,7 @@ static ssize_t kcm_splice_read(struct socket *sock, loff_t *ppos, ...@@ -1175,7 +1175,7 @@ static ssize_t kcm_splice_read(struct socket *sock, loff_t *ppos,
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct kcm_sock *kcm = kcm_sk(sk); struct kcm_sock *kcm = kcm_sk(sk);
long timeo; long timeo;
struct strp_rx_msg *rxm; struct strp_msg *stm;
int err = 0; int err = 0;
ssize_t copied; ssize_t copied;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -1192,12 +1192,12 @@ static ssize_t kcm_splice_read(struct socket *sock, loff_t *ppos, ...@@ -1192,12 +1192,12 @@ static ssize_t kcm_splice_read(struct socket *sock, loff_t *ppos,
/* Okay, have a message on the receive queue */ /* Okay, have a message on the receive queue */
rxm = strp_rx_msg(skb); stm = strp_msg(skb);
if (len > rxm->full_len) if (len > stm->full_len)
len = rxm->full_len; len = stm->full_len;
copied = skb_splice_bits(skb, sk, rxm->offset, pipe, len, flags); copied = skb_splice_bits(skb, sk, stm->offset, pipe, len, flags);
if (copied < 0) { if (copied < 0) {
err = copied; err = copied;
goto err_out; goto err_out;
...@@ -1205,8 +1205,8 @@ static ssize_t kcm_splice_read(struct socket *sock, loff_t *ppos, ...@@ -1205,8 +1205,8 @@ static ssize_t kcm_splice_read(struct socket *sock, loff_t *ppos,
KCM_STATS_ADD(kcm->stats.rx_bytes, copied); KCM_STATS_ADD(kcm->stats.rx_bytes, copied);
rxm->offset += copied; stm->offset += copied;
rxm->full_len -= copied; stm->full_len -= copied;
/* We have no way to return MSG_EOR. If all the bytes have been /* We have no way to return MSG_EOR. If all the bytes have been
* read we still leave the message in the receive socket buffer. * read we still leave the message in the receive socket buffer.
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment