1d2912cb1SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */ 2ab7ac4ebSTom Herbert /* 3ab7ac4ebSTom Herbert * Kernel Connection Multiplexor 4ab7ac4ebSTom Herbert * 5ab7ac4ebSTom Herbert * Copyright (c) 2016 Tom Herbert <tom@herbertland.com> 6ab7ac4ebSTom Herbert */ 7ab7ac4ebSTom Herbert 8ab7ac4ebSTom Herbert #ifndef __NET_KCM_H_ 9ab7ac4ebSTom Herbert #define __NET_KCM_H_ 10ab7ac4ebSTom Herbert 11ab7ac4ebSTom Herbert #include <linux/skbuff.h> 12ab7ac4ebSTom Herbert #include <net/sock.h> 139b73896aSTom Herbert #include <net/strparser.h> 14ab7ac4ebSTom Herbert #include <uapi/linux/kcm.h> 15ab7ac4ebSTom Herbert 16ab7ac4ebSTom Herbert extern unsigned int kcm_net_id; 17ab7ac4ebSTom Herbert 18cd6e111bSTom Herbert #define KCM_STATS_ADD(stat, count) ((stat) += (count)) 19cd6e111bSTom Herbert #define KCM_STATS_INCR(stat) ((stat)++) 20cd6e111bSTom Herbert 21cd6e111bSTom Herbert struct kcm_psock_stats { 22cd6e111bSTom Herbert unsigned long long tx_msgs; 23cd6e111bSTom Herbert unsigned long long tx_bytes; 24cd6e111bSTom Herbert unsigned long long reserved; 25cd6e111bSTom Herbert unsigned long long unreserved; 26cd6e111bSTom Herbert unsigned int tx_aborts; 27cd6e111bSTom Herbert }; 28cd6e111bSTom Herbert 29cd6e111bSTom Herbert struct kcm_mux_stats { 30cd6e111bSTom Herbert unsigned long long rx_msgs; 31cd6e111bSTom Herbert unsigned long long rx_bytes; 32cd6e111bSTom Herbert unsigned long long tx_msgs; 33cd6e111bSTom Herbert unsigned long long tx_bytes; 34cd6e111bSTom Herbert unsigned int rx_ready_drops; 35cd6e111bSTom Herbert unsigned int tx_retries; 36cd6e111bSTom Herbert unsigned int psock_attach; 37cd6e111bSTom Herbert unsigned int psock_unattach_rsvd; 38cd6e111bSTom Herbert unsigned int psock_unattach; 39cd6e111bSTom Herbert }; 40cd6e111bSTom Herbert 41cd6e111bSTom Herbert struct kcm_stats { 42cd6e111bSTom Herbert unsigned long long rx_msgs; 43cd6e111bSTom Herbert unsigned long long rx_bytes; 44cd6e111bSTom Herbert unsigned long long tx_msgs; 45cd6e111bSTom Herbert unsigned long long tx_bytes; 46cd6e111bSTom Herbert }; 47cd6e111bSTom Herbert 48ab7ac4ebSTom Herbert struct kcm_tx_msg { 49ab7ac4ebSTom Herbert unsigned int sent; 50ab7ac4ebSTom Herbert unsigned int frag_offset; 51ab7ac4ebSTom Herbert unsigned int msg_flags; 52c31a25e1SDavid Howells bool started_tx; 53ab7ac4ebSTom Herbert struct sk_buff *frag_skb; 54ab7ac4ebSTom Herbert struct sk_buff *last_skb; 55ab7ac4ebSTom Herbert }; 56ab7ac4ebSTom Herbert 57ab7ac4ebSTom Herbert /* Socket structure for KCM client sockets */ 58ab7ac4ebSTom Herbert struct kcm_sock { 59ab7ac4ebSTom Herbert struct sock sk; 60ab7ac4ebSTom Herbert struct kcm_mux *mux; 61ab7ac4ebSTom Herbert struct list_head kcm_sock_list; 62ab7ac4ebSTom Herbert int index; 63ab7ac4ebSTom Herbert u32 done : 1; 64ab7ac4ebSTom Herbert struct work_struct done_work; 65ab7ac4ebSTom Herbert 66cd6e111bSTom Herbert struct kcm_stats stats; 67cd6e111bSTom Herbert 68ab7ac4ebSTom Herbert /* Transmit */ 69ab7ac4ebSTom Herbert struct kcm_psock *tx_psock; 70ab7ac4ebSTom Herbert struct work_struct tx_work; 71ab7ac4ebSTom Herbert struct list_head wait_psock_list; 72ab7ac4ebSTom Herbert struct sk_buff *seq_skb; 73*00425508SKuniyuki Iwashima struct mutex tx_mutex; 749b73896aSTom Herbert u32 tx_stopped : 1; 75ab7ac4ebSTom Herbert 76ab7ac4ebSTom Herbert /* Don't use bit fields here, these are set under different locks */ 77ab7ac4ebSTom Herbert bool tx_wait; 78ab7ac4ebSTom Herbert bool tx_wait_more; 79ab7ac4ebSTom Herbert 80ab7ac4ebSTom Herbert /* Receive */ 81ab7ac4ebSTom Herbert struct kcm_psock *rx_psock; 82ab7ac4ebSTom Herbert struct list_head wait_rx_list; /* KCMs waiting for receiving */ 83ab7ac4ebSTom Herbert bool rx_wait; 84ab7ac4ebSTom Herbert u32 rx_disabled : 1; 85ab7ac4ebSTom Herbert }; 86ab7ac4ebSTom Herbert 87ab7ac4ebSTom Herbert struct bpf_prog; 88ab7ac4ebSTom Herbert 89ab7ac4ebSTom Herbert /* Structure for an attached lower socket */ 90ab7ac4ebSTom Herbert struct kcm_psock { 91ab7ac4ebSTom Herbert struct sock *sk; 929b73896aSTom Herbert struct strparser strp; 93ab7ac4ebSTom Herbert struct kcm_mux *mux; 94ab7ac4ebSTom Herbert int index; 95ab7ac4ebSTom Herbert 96ab7ac4ebSTom Herbert u32 tx_stopped : 1; 97ab7ac4ebSTom Herbert u32 done : 1; 98ab7ac4ebSTom Herbert u32 unattaching : 1; 99ab7ac4ebSTom Herbert 100ab7ac4ebSTom Herbert void (*save_state_change)(struct sock *sk); 101ab7ac4ebSTom Herbert void (*save_data_ready)(struct sock *sk); 102ab7ac4ebSTom Herbert void (*save_write_space)(struct sock *sk); 103ab7ac4ebSTom Herbert 104ab7ac4ebSTom Herbert struct list_head psock_list; 105ab7ac4ebSTom Herbert 106cd6e111bSTom Herbert struct kcm_psock_stats stats; 107cd6e111bSTom Herbert 108ab7ac4ebSTom Herbert /* Receive */ 109ab7ac4ebSTom Herbert struct list_head psock_ready_list; 110ab7ac4ebSTom Herbert struct bpf_prog *bpf_prog; 111ab7ac4ebSTom Herbert struct kcm_sock *rx_kcm; 112cd6e111bSTom Herbert unsigned long long saved_rx_bytes; 113cd6e111bSTom Herbert unsigned long long saved_rx_msgs; 1149b73896aSTom Herbert struct sk_buff *ready_rx_msg; 115ab7ac4ebSTom Herbert 116ab7ac4ebSTom Herbert /* Transmit */ 117ab7ac4ebSTom Herbert struct kcm_sock *tx_kcm; 118ab7ac4ebSTom Herbert struct list_head psock_avail_list; 119cd6e111bSTom Herbert unsigned long long saved_tx_bytes; 120cd6e111bSTom Herbert unsigned long long saved_tx_msgs; 121ab7ac4ebSTom Herbert }; 122ab7ac4ebSTom Herbert 123ab7ac4ebSTom Herbert /* Per net MUX list */ 124ab7ac4ebSTom Herbert struct kcm_net { 125ab7ac4ebSTom Herbert struct mutex mutex; 126cd6e111bSTom Herbert struct kcm_psock_stats aggregate_psock_stats; 127cd6e111bSTom Herbert struct kcm_mux_stats aggregate_mux_stats; 1289b73896aSTom Herbert struct strp_aggr_stats aggregate_strp_stats; 129ab7ac4ebSTom Herbert struct list_head mux_list; 130ab7ac4ebSTom Herbert int count; 131ab7ac4ebSTom Herbert }; 132ab7ac4ebSTom Herbert 133ab7ac4ebSTom Herbert /* Structure for a MUX */ 134ab7ac4ebSTom Herbert struct kcm_mux { 135ab7ac4ebSTom Herbert struct list_head kcm_mux_list; 136ab7ac4ebSTom Herbert struct rcu_head rcu; 137ab7ac4ebSTom Herbert struct kcm_net *knet; 138ab7ac4ebSTom Herbert 139ab7ac4ebSTom Herbert struct list_head kcm_socks; /* All KCM sockets on MUX */ 140ab7ac4ebSTom Herbert int kcm_socks_cnt; /* Total KCM socket count for MUX */ 141ab7ac4ebSTom Herbert struct list_head psocks; /* List of all psocks on MUX */ 142ab7ac4ebSTom Herbert int psocks_cnt; /* Total attached sockets */ 143ab7ac4ebSTom Herbert 144cd6e111bSTom Herbert struct kcm_mux_stats stats; 145cd6e111bSTom Herbert struct kcm_psock_stats aggregate_psock_stats; 1469b73896aSTom Herbert struct strp_aggr_stats aggregate_strp_stats; 147cd6e111bSTom Herbert 148ab7ac4ebSTom Herbert /* Receive */ 149ab7ac4ebSTom Herbert spinlock_t rx_lock ____cacheline_aligned_in_smp; 150ab7ac4ebSTom Herbert struct list_head kcm_rx_waiters; /* KCMs waiting for receiving */ 151ab7ac4ebSTom Herbert struct list_head psocks_ready; /* List of psocks with a msg ready */ 152ab7ac4ebSTom Herbert struct sk_buff_head rx_hold_queue; 153ab7ac4ebSTom Herbert 154ab7ac4ebSTom Herbert /* Transmit */ 155ab7ac4ebSTom Herbert spinlock_t lock ____cacheline_aligned_in_smp; /* TX and mux locking */ 156ab7ac4ebSTom Herbert struct list_head psocks_avail; /* List of available psocks */ 157ab7ac4ebSTom Herbert struct list_head kcm_tx_waiters; /* KCMs waiting for a TX psock */ 158ab7ac4ebSTom Herbert }; 159ab7ac4ebSTom Herbert 160cd6e111bSTom Herbert #ifdef CONFIG_PROC_FS 161cd6e111bSTom Herbert int kcm_proc_init(void); 162cd6e111bSTom Herbert void kcm_proc_exit(void); 163cd6e111bSTom Herbert #else kcm_proc_init(void)164f720d0caSArnd Bergmannstatic inline int kcm_proc_init(void) { return 0; } kcm_proc_exit(void)165f720d0caSArnd Bergmannstatic inline void kcm_proc_exit(void) { } 166cd6e111bSTom Herbert #endif 167cd6e111bSTom Herbert aggregate_psock_stats(struct kcm_psock_stats * stats,struct kcm_psock_stats * agg_stats)168cd6e111bSTom Herbertstatic inline void aggregate_psock_stats(struct kcm_psock_stats *stats, 169cd6e111bSTom Herbert struct kcm_psock_stats *agg_stats) 170cd6e111bSTom Herbert { 171cd6e111bSTom Herbert /* Save psock statistics in the mux when psock is being unattached. */ 172cd6e111bSTom Herbert 173cd6e111bSTom Herbert #define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat += stats->_stat) 174cd6e111bSTom Herbert SAVE_PSOCK_STATS(tx_msgs); 175cd6e111bSTom Herbert SAVE_PSOCK_STATS(tx_bytes); 176cd6e111bSTom Herbert SAVE_PSOCK_STATS(reserved); 177cd6e111bSTom Herbert SAVE_PSOCK_STATS(unreserved); 178cd6e111bSTom Herbert SAVE_PSOCK_STATS(tx_aborts); 179cd6e111bSTom Herbert #undef SAVE_PSOCK_STATS 180cd6e111bSTom Herbert } 181cd6e111bSTom Herbert aggregate_mux_stats(struct kcm_mux_stats * stats,struct kcm_mux_stats * agg_stats)182cd6e111bSTom Herbertstatic inline void aggregate_mux_stats(struct kcm_mux_stats *stats, 183cd6e111bSTom Herbert struct kcm_mux_stats *agg_stats) 184cd6e111bSTom Herbert { 185cd6e111bSTom Herbert /* Save psock statistics in the mux when psock is being unattached. */ 186cd6e111bSTom Herbert 187cd6e111bSTom Herbert #define SAVE_MUX_STATS(_stat) (agg_stats->_stat += stats->_stat) 188cd6e111bSTom Herbert SAVE_MUX_STATS(rx_msgs); 189cd6e111bSTom Herbert SAVE_MUX_STATS(rx_bytes); 190cd6e111bSTom Herbert SAVE_MUX_STATS(tx_msgs); 191cd6e111bSTom Herbert SAVE_MUX_STATS(tx_bytes); 192cd6e111bSTom Herbert SAVE_MUX_STATS(rx_ready_drops); 193cd6e111bSTom Herbert SAVE_MUX_STATS(psock_attach); 194cd6e111bSTom Herbert SAVE_MUX_STATS(psock_unattach_rsvd); 195cd6e111bSTom Herbert SAVE_MUX_STATS(psock_unattach); 196cd6e111bSTom Herbert #undef SAVE_MUX_STATS 197cd6e111bSTom Herbert } 198cd6e111bSTom Herbert 199ab7ac4ebSTom Herbert #endif /* __NET_KCM_H_ */ 200