]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netinet/tcp_pcap.c
ocs_fc: IO timeout handling and error reporting fix.
[FreeBSD/FreeBSD.git] / sys / netinet / tcp_pcap.c
1 /*-
2  * Copyright (c) 2015
3  *      Jonathan Looney. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/queue.h>
28 #include <sys/param.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <sys/socketvar.h>
32 #include <sys/sysctl.h>
33 #include <sys/systm.h>
34 #include <sys/mbuf.h>
35 #include <sys/eventhandler.h>
36 #include <machine/atomic.h>
37 #include <netinet/tcp_var.h>
38 #include <netinet/tcp_pcap.h>
39
40 #define M_LEADINGSPACE_NOWRITE(m)                                       \
41         ((m)->m_data - M_START(m))
42
43 int tcp_pcap_aggressive_free = 1;
44 static int tcp_pcap_clusters_referenced_cur = 0;
45 static int tcp_pcap_clusters_referenced_max = 0;
46
47 SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcp_pcap_aggressive_free,
48         CTLFLAG_RW, &tcp_pcap_aggressive_free, 0,
49         "Free saved packets when the memory system comes under pressure");
50 SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcp_pcap_clusters_referenced_cur,
51         CTLFLAG_RD, &tcp_pcap_clusters_referenced_cur, 0,
52         "Number of clusters currently referenced on TCP PCAP queues");
53 SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcp_pcap_clusters_referenced_max,
54         CTLFLAG_RW, &tcp_pcap_clusters_referenced_max, 0,
55         "Maximum number of clusters allowed to be referenced on TCP PCAP "
56         "queues");
57
58 static int tcp_pcap_alloc_reuse_ext = 0;
59 static int tcp_pcap_alloc_reuse_mbuf = 0;
60 static int tcp_pcap_alloc_new_mbuf = 0;
61 SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcp_pcap_alloc_reuse_ext,
62         CTLFLAG_RD, &tcp_pcap_alloc_reuse_ext, 0,
63         "Number of mbufs with external storage reused for the TCP PCAP "
64         "functionality");
65 SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcp_pcap_alloc_reuse_mbuf,
66         CTLFLAG_RD, &tcp_pcap_alloc_reuse_mbuf, 0,
67         "Number of mbufs with internal storage reused for the TCP PCAP "
68         "functionality");
69 SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcp_pcap_alloc_new_mbuf,
70         CTLFLAG_RD, &tcp_pcap_alloc_new_mbuf, 0,
71         "Number of new mbufs allocated for the TCP PCAP functionality");
72
73 VNET_DEFINE(int, tcp_pcap_packets) = 0;
74 #define V_tcp_pcap_packets      VNET(tcp_pcap_packets)
75 SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcp_pcap_packets,
76         CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(tcp_pcap_packets), 0,
77         "Default number of packets saved per direction per TCPCB");
78
79 /* Initialize the values. */
80 static void
81 tcp_pcap_max_set(void)
82 {
83
84         tcp_pcap_clusters_referenced_max = nmbclusters / 4;
85 }
86
87 void
88 tcp_pcap_init(void)
89 {
90
91         tcp_pcap_max_set();
92         EVENTHANDLER_REGISTER(nmbclusters_change, tcp_pcap_max_set,
93                 NULL, EVENTHANDLER_PRI_ANY);
94 }
95
96 /*
97  * If we are below the maximum allowed cluster references,
98  * increment the reference count and return TRUE. Otherwise,
99  * leave the reference count alone and return FALSE.
100  */
101 static __inline bool
102 tcp_pcap_take_cluster_reference(void)
103 {
104         if (atomic_fetchadd_int(&tcp_pcap_clusters_referenced_cur, 1) >=
105                 tcp_pcap_clusters_referenced_max) {
106                 atomic_add_int(&tcp_pcap_clusters_referenced_cur, -1);
107                 return FALSE;
108         }
109         return TRUE;
110 }
111
112 /*
113  * For all the external entries in m, apply the given adjustment.
114  * This can be used to adjust the counter when an mbuf chain is
115  * copied or freed.
116  */
117 static __inline void
118 tcp_pcap_adj_cluster_reference(struct mbuf *m, int adj)
119 {
120         while (m) {
121                 if (m->m_flags & M_EXT)
122                         atomic_add_int(&tcp_pcap_clusters_referenced_cur, adj);
123
124                 m = m->m_next;
125         }
126 }
127
128 /*
129  * Free all mbufs in a chain, decrementing the reference count as
130  * necessary.
131  *
132  * Functions in this file should use this instead of m_freem() when
133  * they are freeing mbuf chains that may contain clusters that were
134  * already included in tcp_pcap_clusters_referenced_cur.
135  */
136 static void
137 tcp_pcap_m_freem(struct mbuf *mb)
138 {
139         while (mb != NULL) {
140                 if (mb->m_flags & M_EXT)
141                         atomic_subtract_int(&tcp_pcap_clusters_referenced_cur,
142                             1);
143                 mb = m_free(mb);
144         }
145 }
146
147 /*
148  * Copy data from m to n, where n cannot fit all the data we might
149  * want from m.
150  *
151  * Prioritize data like this:
152  * 1. TCP header
153  * 2. IP header
154  * 3. Data
155  */
156 static void
157 tcp_pcap_copy_bestfit(struct tcphdr *th, struct mbuf *m, struct mbuf *n)
158 {
159         struct mbuf *m_cur = m;
160         int bytes_to_copy=0, trailing_data, skip=0, tcp_off;
161
162         /* Below, we assume these will be non-NULL. */
163         KASSERT(th, ("%s: called with th == NULL", __func__));
164         KASSERT(m, ("%s: called with m == NULL", __func__));
165         KASSERT(n, ("%s: called with n == NULL", __func__));
166
167         /* We assume this initialization occurred elsewhere. */
168         KASSERT(n->m_len == 0, ("%s: called with n->m_len=%d (expected 0)",
169                 __func__, n->m_len));
170         KASSERT(n->m_data == M_START(n),
171                 ("%s: called with n->m_data != M_START(n)", __func__));
172
173         /*
174          * Calculate the size of the TCP header. We use this often
175          * enough that it is worth just calculating at the start.
176          */
177         tcp_off = th->th_off << 2;
178
179         /* Trim off leading empty mbufs. */
180         while (m && m->m_len == 0)
181                 m = m->m_next;
182
183         if (m) {
184                 m_cur = m;
185         }
186         else {
187                 /*
188                  * No data? Highly unusual. We would expect to at
189                  * least see a TCP header in the mbuf.
190                  * As we have a pointer to the TCP header, I guess
191                  * we should just copy that. (???)
192                  */
193 fallback:
194                 bytes_to_copy = tcp_off;
195                 if (bytes_to_copy > M_SIZE(n))
196                         bytes_to_copy = M_SIZE(n);
197                 bcopy(th, n->m_data, bytes_to_copy);
198                 n->m_len = bytes_to_copy;
199                 return;
200         }
201
202         /*
203          * Find TCP header. Record the total number of bytes up to,
204          * and including, the TCP header.
205          */
206         while (m_cur) {
207                 if ((caddr_t) th >= (caddr_t) m_cur->m_data &&
208                         (caddr_t) th < (caddr_t) (m_cur->m_data + m_cur->m_len))
209                         break;
210                 bytes_to_copy += m_cur->m_len;
211                 m_cur = m_cur->m_next;
212         }
213         if (m_cur)
214                 bytes_to_copy += (caddr_t) th - (caddr_t) m_cur->m_data;
215         else
216                 goto fallback;
217         bytes_to_copy += tcp_off;
218
219         /*
220          * If we already want to copy more bytes than we can hold
221          * in the destination mbuf, skip leading bytes and copy
222          * what we can.
223          *
224          * Otherwise, consider trailing data.
225          */
226         if (bytes_to_copy > M_SIZE(n)) {
227                 skip  = bytes_to_copy - M_SIZE(n);
228                 bytes_to_copy = M_SIZE(n);
229         }
230         else {
231                 /*
232                  * Determine how much trailing data is in the chain.
233                  * We start with the length of this mbuf (the one
234                  * containing th) and subtract the size of the TCP
235                  * header (tcp_off) and the size of the data prior
236                  * to th (th - m_cur->m_data).
237                  *
238                  * This *should not* be negative, as the TCP code
239                  * should put the whole TCP header in a single
240                  * mbuf. But, it isn't a problem if it is. We will
241                  * simple work off our negative balance as we look
242                  * at subsequent mbufs.
243                  */
244                 trailing_data = m_cur->m_len - tcp_off;
245                 trailing_data -= (caddr_t) th - (caddr_t) m_cur->m_data;
246                 m_cur = m_cur->m_next;
247                 while (m_cur) {
248                         trailing_data += m_cur->m_len;
249                         m_cur = m_cur->m_next;
250                 }
251                 if ((bytes_to_copy + trailing_data) > M_SIZE(n))
252                         bytes_to_copy = M_SIZE(n);
253                 else
254                         bytes_to_copy += trailing_data;
255         }
256
257         m_copydata(m, skip, bytes_to_copy, n->m_data);
258         n->m_len = bytes_to_copy;
259 }
260
261 void
262 tcp_pcap_add(struct tcphdr *th, struct mbuf *m, struct mbufq *queue)
263 {
264         struct mbuf *n = NULL, *mhead;
265
266         KASSERT(th, ("%s: called with th == NULL", __func__));
267         KASSERT(m, ("%s: called with m == NULL", __func__));
268         KASSERT(queue, ("%s: called with queue == NULL", __func__));
269
270         /* We only care about data packets. */
271         while (m && m->m_type != MT_DATA)
272                 m = m->m_next;
273
274         /* We only need to do something if we still have an mbuf. */
275         if (!m)
276                 return;
277
278         /* If we are not saving mbufs, return now. */
279         if (queue->mq_maxlen == 0)
280                 return;
281
282         /*
283          * Check to see if we will need to recycle mbufs.
284          *
285          * If we need to get rid of mbufs to stay below
286          * our packet count, try to reuse the mbuf. Once
287          * we already have a new mbuf (n), then we can
288          * simply free subsequent mbufs.
289          *
290          * Note that most of the logic in here is to deal
291          * with the reuse. If we are fine with constant
292          * mbuf allocs/deallocs, we could ditch this logic.
293          * But, it only seems to make sense to reuse
294          * mbufs we already have.
295          */
296         while (mbufq_full(queue)) {
297                 mhead = mbufq_dequeue(queue);
298
299                 if (n) {
300                         tcp_pcap_m_freem(mhead);
301                 }
302                 else {
303                         /*
304                          * If this held an external cluster, try to
305                          * detach the cluster. But, if we held the
306                          * last reference, go through the normal
307                          * free-ing process.
308                          */
309                         if (mhead->m_flags & M_EXTPG) {
310                                 /* Don't mess around with these. */
311                                 tcp_pcap_m_freem(mhead);
312                                 continue;
313                         } else if (mhead->m_flags & M_EXT) {
314                                 switch (mhead->m_ext.ext_type) {
315                                 case EXT_SFBUF:
316                                         /* Don't mess around with these. */
317                                         tcp_pcap_m_freem(mhead);
318                                         continue;
319                                 default:
320                                         if (atomic_fetchadd_int(
321                                                 mhead->m_ext.ext_cnt, -1) == 1)
322                                         {
323                                                 /*
324                                                  * We held the last reference
325                                                  * on this cluster. Restore
326                                                  * the reference count and put
327                                                  * it back in the pool.
328                                                  */
329                                                 *(mhead->m_ext.ext_cnt) = 1;
330                                                 tcp_pcap_m_freem(mhead);
331                                                 continue;
332                                         }
333                                         /*
334                                          * We were able to cleanly free the
335                                          * reference.
336                                          */
337                                         atomic_subtract_int(
338                                             &tcp_pcap_clusters_referenced_cur,
339                                             1);
340                                         tcp_pcap_alloc_reuse_ext++;
341                                         break;
342                                 }
343                         } else {
344                                 tcp_pcap_alloc_reuse_mbuf++;
345                         }
346
347                         n = mhead;
348                         tcp_pcap_m_freem(n->m_next);
349                         m_init(n, M_NOWAIT, MT_DATA, 0);
350                 }
351         }
352
353         /* Check to see if we need to get a new mbuf. */
354         if (!n) {
355                 if (!(n = m_get(M_NOWAIT, MT_DATA)))
356                         return;
357                 tcp_pcap_alloc_new_mbuf++;
358         }
359
360         /*
361          * What are we dealing with? If a cluster, attach it. Otherwise,
362          * try to copy the data from the beginning of the mbuf to the
363          * end of data. (There may be data between the start of the data
364          * area and the current data pointer. We want to get this, because
365          * it may contain header information that is useful.)
366          * In cases where that isn't possible, settle for what we can
367          * get.
368          */
369         if ((m->m_flags & (M_EXT|M_EXTPG)) &&
370             tcp_pcap_take_cluster_reference()) {
371                 n->m_data = m->m_data;
372                 n->m_len = m->m_len;
373                 mb_dupcl(n, m);
374         }
375         else if (((m->m_data + m->m_len) - M_START(m)) <= M_SIZE(n)) {
376                 /*
377                  * At this point, n is guaranteed to be a normal mbuf
378                  * with no cluster and no packet header. Because the
379                  * logic in this code block requires this, the assert
380                  * is here to catch any instances where someone
381                  * changes the logic to invalidate that assumption.
382                  */
383                 KASSERT((n->m_flags & (M_EXT | M_PKTHDR)) == 0,
384                         ("%s: Unexpected flags (%#x) for mbuf",
385                         __func__, n->m_flags));
386                 n->m_data = n->m_dat + M_LEADINGSPACE_NOWRITE(m);
387                 n->m_len = m->m_len;
388                 if (m->m_flags & M_EXTPG)
389                         m_copydata(m, 0, m->m_len, n->m_data);
390                 else
391                         bcopy(M_START(m), n->m_dat,
392                             m->m_len + M_LEADINGSPACE_NOWRITE(m));
393         }
394         else {
395                 /*
396                  * This is the case where we need to "settle for what
397                  * we can get". The most probable way to this code
398                  * path is that we've already taken references to the
399                  * maximum number of mbuf clusters we can, and the data
400                  * is too long to fit in an mbuf's internal storage.
401                  * Try for a "best fit".
402                  */
403                 tcp_pcap_copy_bestfit(th, m, n);
404
405                 /* Don't try to get additional data. */
406                 goto add_to_queue;
407         }
408
409         if (m->m_next) {
410                 n->m_next = m_copym(m->m_next, 0, M_COPYALL, M_NOWAIT);
411                 tcp_pcap_adj_cluster_reference(n->m_next, 1);
412         }
413
414 add_to_queue:
415         /* Add the new mbuf to the list. */
416         if (mbufq_enqueue(queue, n)) {
417                 /* This shouldn't happen. If INVARIANTS is defined, panic. */
418                 KASSERT(0, ("%s: mbufq was unexpectedly full!", __func__));
419                 tcp_pcap_m_freem(n);
420         }
421 }
422
423 void
424 tcp_pcap_drain(struct mbufq *queue)
425 {
426         struct mbuf *m;
427         while ((m = mbufq_dequeue(queue)))
428                 tcp_pcap_m_freem(m);
429 }
430
431 void
432 tcp_pcap_tcpcb_init(struct tcpcb *tp)
433 {
434         mbufq_init(&(tp->t_inpkts), V_tcp_pcap_packets);
435         mbufq_init(&(tp->t_outpkts), V_tcp_pcap_packets);
436 }
437
438 void
439 tcp_pcap_set_sock_max(struct mbufq *queue, int newval)
440 {
441         queue->mq_maxlen = newval;
442         while (queue->mq_len > queue->mq_maxlen)
443                 tcp_pcap_m_freem(mbufq_dequeue(queue));
444 }
445
446 int
447 tcp_pcap_get_sock_max(struct mbufq *queue)
448 {
449         return queue->mq_maxlen;
450 }