OpenVPN
mbuf.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2026 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "syshead.h"
28
29#include "buffer.h"
30#include "error.h"
31#include "integer.h"
32#include "misc.h"
33#include "mbuf.h"
34
35#include "memdbg.h"
36
37struct mbuf_set *
38mbuf_init(unsigned int size)
39{
40 ASSERT(size <= MBUF_SIZE_MAX);
41
42 struct mbuf_set *ret;
44 ret->capacity = (unsigned int)adjust_power_of_2(size);
45 ALLOC_ARRAY(ret->array, struct mbuf_item, ret->capacity);
46 return ret;
47}
48
49void
51{
52 if (ms)
53 {
54 for (unsigned int i = 0; i < ms->len; ++i)
55 {
56 struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
57 mbuf_free_buf(item->buffer);
58 }
59 free(ms->array);
60 free(ms);
61 }
62}
63
64struct mbuf_buffer *
66{
67 struct mbuf_buffer *ret;
68 ALLOC_OBJ(ret, struct mbuf_buffer);
69 ret->buf = clone_buf(buf);
70 ret->refcount = 1;
71 ret->flags = 0;
72 return ret;
73}
74
75void
77{
78 if (mb)
79 {
80 if (--mb->refcount <= 0)
81 {
82 free_buf(&mb->buf);
83 free(mb);
84 }
85 }
86}
87
88/*
89 * Dereferenced items cannot be removed from the middle of the ring, so
90 * reclaim them once they reach the head: a ring left without any live
91 * item must not keep looking full.
92 */
93static void
95{
96 while (ms->len && !ms->array[ms->head].instance)
97 {
98 ms->head = MBUF_INDEX(ms->head, 1, ms->capacity);
99 --ms->len;
100 }
101}
102
103void
104mbuf_add_item(struct mbuf_set *ms, const struct mbuf_item *item)
105{
106 ASSERT(ms);
107 if (ms->len == ms->capacity)
108 {
109 struct mbuf_item rm;
110 ASSERT(mbuf_extract_item(ms, &rm));
112 msg(D_MULTI_DROPPED, "MBUF: mbuf packet dropped");
113 }
114
115 ASSERT(ms->len < ms->capacity);
116
117 ms->array[MBUF_INDEX(ms->head, ms->len, ms->capacity)] = *item;
118 if (++ms->len > ms->max_queued)
119 {
120 ms->max_queued = ms->len;
121 }
122 ++item->buffer->refcount;
123}
124
125bool
126mbuf_extract_item(struct mbuf_set *ms, struct mbuf_item *item)
127{
128 bool ret = false;
129 if (ms)
130 {
131 ASSERT(item);
132 while (ms->len)
133 {
134 *item = ms->array[ms->head];
135 ms->head = MBUF_INDEX(ms->head, 1, ms->capacity);
136 --ms->len;
137 if (item->instance) /* ignore dereferenced instances */
138 {
139 ret = true;
140 break;
141 }
142 }
144 }
145 return ret;
146}
147
148struct multi_instance *
150{
151 struct multi_instance *ret = NULL;
152 if (ms)
153 {
154 for (unsigned int i = 0; i < ms->len; ++i)
155 {
156 struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
157 if (item->instance)
158 {
159 ret = item->instance;
160 break;
161 }
162 }
163 }
164 return ret;
165}
166
167void
169{
170 if (ms)
171 {
172 for (unsigned int i = 0; i < ms->len; ++i)
173 {
174 struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
175 if (item->instance == mi)
176 {
177 mbuf_free_buf(item->buffer);
178 item->buffer = NULL;
179 item->instance = NULL;
180 msg(D_MBUF, "MBUF: dereferenced queued packet");
181 }
182 }
184 }
185}
void free_buf(struct buffer *buf)
Free the memory allocated for a buffer.
Definition buffer.c:169
struct buffer clone_buf(const struct buffer *buf)
Duplicate a buffer, including its content.
Definition buffer.c:99
Buffer management functions and garbage collection.
#define ALLOC_OBJ(dptr, type)
Allocate memory for a single object of the given type.
Definition buffer.h:2027
#define ALLOC_OBJ_CLEAR(dptr, type)
Allocate and zero-initialise memory for a single object of the given type.
Definition buffer.h:2038
#define ALLOC_ARRAY(dptr, type, n)
Allocate memory for an array of n elements of the given type.
Definition buffer.h:2054
#define D_MBUF
Definition errlevel.h:98
#define D_MULTI_DROPPED
Definition errlevel.h:100
static size_t adjust_power_of_2(size_t u)
Definition integer.h:205
void mbuf_add_item(struct mbuf_set *ms, const struct mbuf_item *item)
Definition mbuf.c:104
struct mbuf_buffer * mbuf_alloc_buf(const struct buffer *buf)
Definition mbuf.c:65
void mbuf_free_buf(struct mbuf_buffer *mb)
Definition mbuf.c:76
void mbuf_dereference_instance(struct mbuf_set *ms, struct multi_instance *mi)
Definition mbuf.c:168
static void mbuf_reclaim_head(struct mbuf_set *ms)
Definition mbuf.c:94
bool mbuf_extract_item(struct mbuf_set *ms, struct mbuf_item *item)
Definition mbuf.c:126
void mbuf_free(struct mbuf_set *ms)
Definition mbuf.c:50
struct multi_instance * mbuf_peek_dowork(struct mbuf_set *ms)
Definition mbuf.c:149
struct mbuf_set * mbuf_init(unsigned int size)
Definition mbuf.c:38
#define MBUF_SIZE_MAX
Definition mbuf.h:40
#define MBUF_INDEX(head, offset, size)
Definition mbuf.h:38
#define msg(flags,...)
Definition error.h:152
#define ASSERT(x)
Definition error.h:221
Wrapper structure for dynamically allocated memory.
Definition buffer.h:71
unsigned int flags
Definition mbuf.h:48
struct buffer buf
Definition mbuf.h:44
int refcount
Definition mbuf.h:45
struct mbuf_buffer * buffer
Definition mbuf.h:53
struct multi_instance * instance
Definition mbuf.h:54
struct mbuf_item * array
Definition mbuf.h:63
unsigned int max_queued
Definition mbuf.h:62
unsigned int head
Definition mbuf.h:59
unsigned int len
Definition mbuf.h:60
unsigned int capacity
Definition mbuf.h:61
Server-mode state structure for one single VPN tunnel.
Definition multi.h:102