aboutsummaryrefslogtreecommitdiffstats
path: root/extras/libmemif/src/memif_private.h
blob: a512ed4eaaa8afb29ed23ad7085f018b2f631d2e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
/*
 *------------------------------------------------------------------
 * Copyright (c) 2017 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *------------------------------------------------------------------
 */


#ifndef _MEMIF_PRIVATE_H_
#define _MEMIF_PRIVATE_H_

#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <stdint.h>
#include <inttypes.h>
#include <limits.h>
#include <sys/timerfd.h>
#include <string.h>

#include <libmemif.h>

#define MEMIF_NAME_LEN 32
_Static_assert (strlen (MEMIF_DEFAULT_APP_NAME) <= MEMIF_NAME_LEN,
		"MEMIF_DEFAULT_APP_NAME max length is 32");

#define MEMIF_DEFAULT_SOCKET_DIR "/run/vpp"
#define MEMIF_DEFAULT_SOCKET_FILENAME  "memif.sock"
#define MEMIF_DEFAULT_RING_SIZE 1024
#define MEMIF_DEFAULT_LOG2_RING_SIZE 10
#define MEMIF_DEFAULT_RX_QUEUES 1
#define MEMIF_DEFAULT_TX_QUEUES 1
#define MEMIF_DEFAULT_BUFFER_SIZE 2048

#define MEMIF_MAX_M2S_RING		255
#define MEMIF_MAX_S2M_RING		255
#define MEMIF_MAX_REGION		255
#define MEMIF_MAX_LOG2_RING_SIZE	15

#define MEMIF_MAX_FDS 512

#define memif_min(a,b) (((a) < (b)) ? (a) : (b))

#ifdef MEMIF_DBG
#define DBG(...) do {                                                             \
                        printf("MEMIF_DEBUG:%s:%s:%d: ", __FILE__, __func__, __LINE__);  \
                        printf(__VA_ARGS__);                                            \
                        printf("\n");                                                   \
                        } while (0)

#define DBG_UNIX(...) do {                                                        \
                      printf("MEMIF_DEBUG_UNIX:%s:%s:%d: ", __FILE__, __func__, __LINE__);  \
                      printf(__VA_ARGS__);                                    \
                      printf("\n");                                           \
                      } while (0)

#define error_return_unix(...) do {                                             \
                                DBG_UNIX(__VA_ARGS__);                          \
                                return -1;                                      \
                                } while (0)
#define error_return(...) do {                                                  \
                            DBG(__VA_ARGS__);                                   \
                            return -1;                                          \
                            } while (0)
#else
#define DBG(...)
#define DBG_UNIX(...)
#define error_return_unix(...) do {                                             \
                                return -1;                                      \
                                } while (0)
#define error_return(...) do {                                                  \
                            return -1;                                          \
                            } while (0)

#endif /* MEMIF_DBG */

typedef struct
{
  void *shm;
  uint32_t region_size;
  int fd;
} memif_region_t;

typedef struct
{
  memif_ring_t *ring;
  uint8_t log2_ring_size;
  uint8_t region;
  uint32_t offset;

  uint16_t last_head;
  uint16_t last_tail;

  int int_fd;

  uint64_t int_count;
  uint32_t alloc_bufs;
} memif_queue_t;

typedef struct memif_msg_queue_elt
{
  memif_msg_t msg;
  int fd;
  struct memif_msg_queue_elt *next;
} memif_msg_queue_elt_t;

struct memif_connection;

typedef struct memif_connection memif_connection_t;

/* functions called by memif_control_fd_handler */
typedef int (memif_fn) (memif_connection_t * conn);

typedef struct
{
  uint8_t num_s2m_rings;
  uint8_t num_m2s_rings;
  uint16_t buffer_size;
  memif_log2_ring_size_t log2_ring_size;
} memif_conn_run_args_t;

typedef struct memif_connection
{
  uint16_t index;
  memif_conn_args_t args;
  memif_conn_run_args_t run_args;

  int fd;
  int listener_fd;

  memif_fn *write_fn, *read_fn, *error_fn;

  memif_connection_update_t *on_connect, *on_disconnect;
  memif_interrupt_t *on_interrupt;
  void *private_ctx;

  /* connection message queue */
  memif_msg_queue_elt_t *msg_queue;

  uint8_t remote_if_name[MEMIF_NAME_LEN];
  uint8_t remote_name[MEMIF_NAME_LEN];
  uint8_t remote_disconnect_string[96];

  memif_region_t *regions;

  memif_queue_t *rx_queues;
  memif_queue_t *tx_queues;

  uint16_t flags;
#define MEMIF_CONNECTION_FLAG_WRITE (1 << 0)
} memif_connection_t;

/*
 * WIP
 */
typedef struct
{
  int key;			/* fd or id */
  void *data_struct;
} memif_list_elt_t;

/*
 * WIP
 */
typedef struct
{
  int fd;
  uint16_t use_count;
  uint8_t *filename;
  uint16_t interface_list_len;
  memif_list_elt_t *interface_list;	/* memif master interfaces listening on this socket */
} memif_socket_t;

/*
 * WIP
 */
/* probably function like memif_cleanup () will need to be called to close timerfd */
typedef struct
{
  memif_control_fd_update_t *control_fd_update;
  int timerfd;
  struct itimerspec arm, disarm;
  uint16_t disconn_slaves;
  uint8_t app_name[MEMIF_NAME_LEN];

  /* master implementation... */
  memif_socket_t ms;

  uint16_t control_list_len;
  uint16_t interrupt_list_len;
  uint16_t listener_list_len;
  uint16_t pending_list_len;
  memif_list_elt_t *control_list;
  memif_list_elt_t *interrupt_list;
  memif_list_elt_t *listener_list;
  memif_list_elt_t *pending_list;
} libmemif_main_t;

extern libmemif_main_t libmemif_main;
extern int memif_epfd;

/* main.c */

/* if region doesn't contain shared memory, mmap region, check ring cookie */
int memif_connect1 (memif_connection_t * c);

/* memory map region, initalize rings and queues */
int memif_init_regions_and_queues (memif_connection_t * c);

int memif_disconnect_internal (memif_connection_t * c);

/* map errno to memif error code */
int memif_syscall_error_handler (int err_code);

int add_list_elt (memif_list_elt_t * e, memif_list_elt_t ** list,
		  uint16_t * len);

int get_list_elt (memif_list_elt_t ** e, memif_list_elt_t * list,
		  uint16_t len, int key);

int free_list_elt (memif_list_elt_t * list, uint16_t len, int key);

#ifndef __NR_memfd_create
#if defined __x86_64__
#define __NR_memfd_create 319
#elif defined __arm__
#define __NR_memfd_create 385
#elif defined __aarch64__
#define __NR_memfd_create 279
#else
#error "__NR_memfd_create unknown for this architecture"
#endif
#endif

#ifndef HAVE_MEMFD_CREATE
static inline int
memfd_create (const char *name, unsigned int flags)
{
  return syscall (__NR_memfd_create, name, flags);
}
#endif

static inline void *
memif_get_buffer (memif_connection_t * conn, memif_ring_t * ring,
		  uint16_t index)
{
  return (conn->regions[ring->desc[index].region].shm +
	  ring->desc[index].offset);
}

#ifndef F_LINUX_SPECIFIC_BASE
#define F_LINUX_SPECIFIC_BASE 1024
#endif

#ifndef MFD_ALLOW_SEALING
#define MFD_ALLOW_SEALING       0x0002U
#endif

#ifndef F_ADD_SEALS
#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)

#define F_SEAL_SEAL     0x0001	/* prevent further seals from being set */
#define F_SEAL_SHRINK   0x0002	/* prevent file from shrinking */
#define F_SEAL_GROW     0x0004	/* prevent file from growing */
#define F_SEAL_WRITE    0x0008	/* prevent writes */
#endif

#endif /* _MEMIF_PRIVATE_H_ */