Commit | Line | Data |
---|---|---|
ab7ac4eb TH |
1 | /* |
2 | * Kernel Connection Multiplexor | |
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_KCM_H_ | |
12 | #define __NET_KCM_H_ | |
13 | ||
14 | #include <linux/skbuff.h> | |
15 | #include <net/sock.h> | |
16 | #include <uapi/linux/kcm.h> | |
17 | ||
18 | extern unsigned int kcm_net_id; | |
19 | ||
cd6e111b TH |
20 | #define KCM_STATS_ADD(stat, count) ((stat) += (count)) |
21 | #define KCM_STATS_INCR(stat) ((stat)++) | |
22 | ||
23 | struct kcm_psock_stats { | |
24 | unsigned long long rx_msgs; | |
25 | unsigned long long rx_bytes; | |
26 | unsigned long long tx_msgs; | |
27 | unsigned long long tx_bytes; | |
28 | unsigned int rx_aborts; | |
29 | unsigned int rx_mem_fail; | |
30 | unsigned int rx_need_more_hdr; | |
7ced95ef | 31 | unsigned int rx_msg_too_big; |
cd6e111b TH |
32 | unsigned int rx_bad_hdr_len; |
33 | unsigned long long reserved; | |
34 | unsigned long long unreserved; | |
35 | unsigned int tx_aborts; | |
36 | }; | |
37 | ||
38 | struct kcm_mux_stats { | |
39 | unsigned long long rx_msgs; | |
40 | unsigned long long rx_bytes; | |
41 | unsigned long long tx_msgs; | |
42 | unsigned long long tx_bytes; | |
43 | unsigned int rx_ready_drops; | |
44 | unsigned int tx_retries; | |
45 | unsigned int psock_attach; | |
46 | unsigned int psock_unattach_rsvd; | |
47 | unsigned int psock_unattach; | |
48 | }; | |
49 | ||
50 | struct kcm_stats { | |
51 | unsigned long long rx_msgs; | |
52 | unsigned long long rx_bytes; | |
53 | unsigned long long tx_msgs; | |
54 | unsigned long long tx_bytes; | |
55 | }; | |
56 | ||
ab7ac4eb TH |
57 | struct kcm_tx_msg { |
58 | unsigned int sent; | |
59 | unsigned int fragidx; | |
60 | unsigned int frag_offset; | |
61 | unsigned int msg_flags; | |
62 | struct sk_buff *frag_skb; | |
63 | struct sk_buff *last_skb; | |
64 | }; | |
65 | ||
66 | struct kcm_rx_msg { | |
67 | int full_len; | |
68 | int accum_len; | |
69 | int offset; | |
7ced95ef | 70 | int early_eaten; |
ab7ac4eb TH |
71 | }; |
72 | ||
73 | /* Socket structure for KCM client sockets */ | |
74 | struct kcm_sock { | |
75 | struct sock sk; | |
76 | struct kcm_mux *mux; | |
77 | struct list_head kcm_sock_list; | |
78 | int index; | |
79 | u32 done : 1; | |
80 | struct work_struct done_work; | |
81 | ||
cd6e111b TH |
82 | struct kcm_stats stats; |
83 | ||
ab7ac4eb TH |
84 | /* Transmit */ |
85 | struct kcm_psock *tx_psock; | |
86 | struct work_struct tx_work; | |
87 | struct list_head wait_psock_list; | |
88 | struct sk_buff *seq_skb; | |
89 | ||
90 | /* Don't use bit fields here, these are set under different locks */ | |
91 | bool tx_wait; | |
92 | bool tx_wait_more; | |
93 | ||
94 | /* Receive */ | |
95 | struct kcm_psock *rx_psock; | |
96 | struct list_head wait_rx_list; /* KCMs waiting for receiving */ | |
97 | bool rx_wait; | |
98 | u32 rx_disabled : 1; | |
99 | }; | |
100 | ||
101 | struct bpf_prog; | |
102 | ||
103 | /* Structure for an attached lower socket */ | |
104 | struct kcm_psock { | |
105 | struct sock *sk; | |
106 | struct kcm_mux *mux; | |
107 | int index; | |
108 | ||
109 | u32 tx_stopped : 1; | |
110 | u32 rx_stopped : 1; | |
111 | u32 done : 1; | |
112 | u32 unattaching : 1; | |
113 | ||
114 | void (*save_state_change)(struct sock *sk); | |
115 | void (*save_data_ready)(struct sock *sk); | |
116 | void (*save_write_space)(struct sock *sk); | |
117 | ||
118 | struct list_head psock_list; | |
119 | ||
cd6e111b TH |
120 | struct kcm_psock_stats stats; |
121 | ||
ab7ac4eb TH |
122 | /* Receive */ |
123 | struct sk_buff *rx_skb_head; | |
124 | struct sk_buff **rx_skb_nextp; | |
125 | struct sk_buff *ready_rx_msg; | |
126 | struct list_head psock_ready_list; | |
127 | struct work_struct rx_work; | |
128 | struct delayed_work rx_delayed_work; | |
129 | struct bpf_prog *bpf_prog; | |
130 | struct kcm_sock *rx_kcm; | |
cd6e111b TH |
131 | unsigned long long saved_rx_bytes; |
132 | unsigned long long saved_rx_msgs; | |
7ced95ef | 133 | unsigned int rx_need_bytes; |
ab7ac4eb TH |
134 | |
135 | /* Transmit */ | |
136 | struct kcm_sock *tx_kcm; | |
137 | struct list_head psock_avail_list; | |
cd6e111b TH |
138 | unsigned long long saved_tx_bytes; |
139 | unsigned long long saved_tx_msgs; | |
ab7ac4eb TH |
140 | }; |
141 | ||
142 | /* Per net MUX list */ | |
143 | struct kcm_net { | |
144 | struct mutex mutex; | |
cd6e111b TH |
145 | struct kcm_psock_stats aggregate_psock_stats; |
146 | struct kcm_mux_stats aggregate_mux_stats; | |
ab7ac4eb TH |
147 | struct list_head mux_list; |
148 | int count; | |
149 | }; | |
150 | ||
151 | /* Structure for a MUX */ | |
152 | struct kcm_mux { | |
153 | struct list_head kcm_mux_list; | |
154 | struct rcu_head rcu; | |
155 | struct kcm_net *knet; | |
156 | ||
157 | struct list_head kcm_socks; /* All KCM sockets on MUX */ | |
158 | int kcm_socks_cnt; /* Total KCM socket count for MUX */ | |
159 | struct list_head psocks; /* List of all psocks on MUX */ | |
160 | int psocks_cnt; /* Total attached sockets */ | |
161 | ||
cd6e111b TH |
162 | struct kcm_mux_stats stats; |
163 | struct kcm_psock_stats aggregate_psock_stats; | |
164 | ||
ab7ac4eb TH |
165 | /* Receive */ |
166 | spinlock_t rx_lock ____cacheline_aligned_in_smp; | |
167 | struct list_head kcm_rx_waiters; /* KCMs waiting for receiving */ | |
168 | struct list_head psocks_ready; /* List of psocks with a msg ready */ | |
169 | struct sk_buff_head rx_hold_queue; | |
170 | ||
171 | /* Transmit */ | |
172 | spinlock_t lock ____cacheline_aligned_in_smp; /* TX and mux locking */ | |
173 | struct list_head psocks_avail; /* List of available psocks */ | |
174 | struct list_head kcm_tx_waiters; /* KCMs waiting for a TX psock */ | |
175 | }; | |
176 | ||
cd6e111b TH |
177 | #ifdef CONFIG_PROC_FS |
178 | int kcm_proc_init(void); | |
179 | void kcm_proc_exit(void); | |
180 | #else | |
181 | static int kcm_proc_init(void) { return 0; } | |
182 | static void kcm_proc_exit(void) { } | |
183 | #endif | |
184 | ||
185 | static inline void aggregate_psock_stats(struct kcm_psock_stats *stats, | |
186 | struct kcm_psock_stats *agg_stats) | |
187 | { | |
188 | /* Save psock statistics in the mux when psock is being unattached. */ | |
189 | ||
190 | #define SAVE_PSOCK_STATS(_stat) (agg_stats->_stat += stats->_stat) | |
191 | SAVE_PSOCK_STATS(rx_msgs); | |
192 | SAVE_PSOCK_STATS(rx_bytes); | |
193 | SAVE_PSOCK_STATS(rx_aborts); | |
194 | SAVE_PSOCK_STATS(rx_mem_fail); | |
195 | SAVE_PSOCK_STATS(rx_need_more_hdr); | |
7ced95ef | 196 | SAVE_PSOCK_STATS(rx_msg_too_big); |
cd6e111b TH |
197 | SAVE_PSOCK_STATS(rx_bad_hdr_len); |
198 | SAVE_PSOCK_STATS(tx_msgs); | |
199 | SAVE_PSOCK_STATS(tx_bytes); | |
200 | SAVE_PSOCK_STATS(reserved); | |
201 | SAVE_PSOCK_STATS(unreserved); | |
202 | SAVE_PSOCK_STATS(tx_aborts); | |
203 | #undef SAVE_PSOCK_STATS | |
204 | } | |
205 | ||
206 | static inline void aggregate_mux_stats(struct kcm_mux_stats *stats, | |
207 | struct kcm_mux_stats *agg_stats) | |
208 | { | |
209 | /* Save psock statistics in the mux when psock is being unattached. */ | |
210 | ||
211 | #define SAVE_MUX_STATS(_stat) (agg_stats->_stat += stats->_stat) | |
212 | SAVE_MUX_STATS(rx_msgs); | |
213 | SAVE_MUX_STATS(rx_bytes); | |
214 | SAVE_MUX_STATS(tx_msgs); | |
215 | SAVE_MUX_STATS(tx_bytes); | |
216 | SAVE_MUX_STATS(rx_ready_drops); | |
217 | SAVE_MUX_STATS(psock_attach); | |
218 | SAVE_MUX_STATS(psock_unattach_rsvd); | |
219 | SAVE_MUX_STATS(psock_unattach); | |
220 | #undef SAVE_MUX_STATS | |
221 | } | |
222 | ||
ab7ac4eb | 223 | #endif /* __NET_KCM_H_ */ |