Line data Source code
1 : /*
2 : *------------------------------------------------------------------
3 : * Copyright (c) 2016 Cisco and/or its affiliates.
4 : * Licensed under the Apache License, Version 2.0 (the "License");
5 : * you may not use this file except in compliance with the License.
6 : * You may obtain a copy of the License at:
7 : *
8 : * http://www.apache.org/licenses/LICENSE-2.0
9 : *
10 : * Unless required by applicable law or agreed to in writing, software
11 : * distributed under the License is distributed on an "AS IS" BASIS,
12 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : * See the License for the specific language governing permissions and
14 : * limitations under the License.
15 : *------------------------------------------------------------------
16 : */
17 :
18 : #define _GNU_SOURCE
19 : #include <stdint.h>
20 : #include <net/if.h>
21 : #include <sys/types.h>
22 : #include <fcntl.h>
23 : #include <sys/ioctl.h>
24 : #include <sys/socket.h>
25 : #include <sys/un.h>
26 : #include <sys/uio.h>
27 : #include <sys/mman.h>
28 : #include <sys/prctl.h>
29 : #include <sys/eventfd.h>
30 : #include <inttypes.h>
31 : #include <limits.h>
32 :
33 : #include <vlib/vlib.h>
34 : #include <vlib/unix/unix.h>
35 : #include <vnet/plugin/plugin.h>
36 : #include <vnet/ethernet/ethernet.h>
37 : #include <vpp/app/version.h>
38 :
39 : #include <memif/memif.h>
40 : #include <memif/private.h>
41 :
42 : void
43 16 : memif_socket_close (clib_socket_t ** s)
44 : {
45 16 : memif_file_del_by_index ((*s)->private_data);
46 16 : clib_mem_free (*s);
47 16 : *s = 0;
48 16 : }
49 :
50 : static u8 *
51 35 : memif_str2vec (uint8_t * str, int len)
52 : {
53 35 : u8 *s = 0;
54 : int i;
55 :
56 35 : if (str[0] == 0)
57 0 : return s;
58 :
59 658 : for (i = 0; i < len; i++)
60 : {
61 658 : vec_add1 (s, str[i]);
62 658 : if (str[i] == 0)
63 35 : return s;
64 : }
65 0 : vec_add1 (s, 0);
66 :
67 0 : return s;
68 : }
69 :
70 : static void
71 35 : memif_msg_enq_ack (memif_if_t * mif)
72 : {
73 : memif_msg_fifo_elt_t *e;
74 35 : clib_fifo_add2 (mif->msg_queue, e);
75 :
76 35 : e->msg.type = MEMIF_MSG_TYPE_ACK;
77 35 : e->fd = -1;
78 35 : }
79 :
80 : static void
81 39 : memif_msg_strlcpy (u8 * dest, u32 len, const u8 * src)
82 : {
83 39 : len = clib_min (len - 1, vec_len (src));
84 39 : memcpy (dest, src, len);
85 39 : dest[len] = '\0';
86 39 : }
87 :
88 : static void
89 28 : memif_msg_snprintf (u8 * dest, u32 len, const char *fmt, ...)
90 : {
91 : va_list va;
92 28 : va_start (va, fmt);
93 28 : u8 *s = va_format (0, fmt, &va);
94 28 : va_end (va);
95 28 : memif_msg_strlcpy (dest, len, s);
96 28 : vec_free (s);
97 28 : }
98 :
99 : static clib_error_t *
100 7 : memif_msg_enq_hello (clib_socket_t * sock)
101 : {
102 7 : memif_msg_t msg = { 0 };
103 7 : memif_msg_hello_t *h = &msg.hello;
104 7 : msg.type = MEMIF_MSG_TYPE_HELLO;
105 7 : h->min_version = MEMIF_VERSION;
106 7 : h->max_version = MEMIF_VERSION;
107 7 : h->max_m2s_ring = MEMIF_MAX_M2S_RING;
108 7 : h->max_s2m_ring = MEMIF_MAX_S2M_RING;
109 7 : h->max_region = MEMIF_MAX_REGION;
110 7 : h->max_log2_ring_size = MEMIF_MAX_LOG2_RING_SIZE;
111 7 : memif_msg_snprintf (h->name, sizeof (h->name), "VPP %s", VPP_BUILD_VER);
112 7 : return clib_socket_sendmsg (sock, &msg, sizeof (memif_msg_t), 0, 0);
113 : }
114 :
115 : static void
116 7 : memif_msg_enq_init (memif_if_t * mif)
117 : {
118 : memif_msg_fifo_elt_t *e;
119 7 : clib_fifo_add2 (mif->msg_queue, e);
120 7 : memif_msg_init_t *i = &e->msg.init;
121 :
122 7 : e->msg.type = MEMIF_MSG_TYPE_INIT;
123 7 : e->fd = -1;
124 7 : i->version = MEMIF_VERSION;
125 7 : i->id = mif->id;
126 7 : i->mode = mif->mode;
127 7 : memif_msg_snprintf (i->name, sizeof (i->name), "VPP %s", VPP_BUILD_VER);
128 7 : if (mif->secret)
129 3 : memif_msg_strlcpy (i->secret, sizeof (i->secret), mif->secret);
130 7 : }
131 :
132 : static void
133 14 : memif_msg_enq_add_region (memif_if_t * mif, u8 region)
134 : {
135 : memif_msg_fifo_elt_t *e;
136 14 : clib_fifo_add2 (mif->msg_queue, e);
137 14 : memif_msg_add_region_t *ar = &e->msg.add_region;
138 :
139 14 : e->msg.type = MEMIF_MSG_TYPE_ADD_REGION;
140 14 : e->fd = mif->regions[region].fd;
141 14 : ar->index = region;
142 14 : ar->size = mif->regions[region].region_size;
143 14 : }
144 :
145 : static void
146 14 : memif_msg_enq_add_ring (memif_if_t * mif, u8 index, u8 direction)
147 : {
148 : memif_msg_fifo_elt_t *e;
149 14 : clib_fifo_add2 (mif->msg_queue, e);
150 14 : memif_msg_add_ring_t *ar = &e->msg.add_ring;
151 : memif_queue_t *mq;
152 :
153 14 : ASSERT ((mif->flags & MEMIF_IF_FLAG_IS_SLAVE) != 0);
154 :
155 14 : e->msg.type = MEMIF_MSG_TYPE_ADD_RING;
156 :
157 14 : if (direction == MEMIF_RING_M2S)
158 7 : mq = vec_elt_at_index (mif->rx_queues, index);
159 : else
160 7 : mq = vec_elt_at_index (mif->tx_queues, index);
161 :
162 14 : e->fd = mq->int_fd;
163 14 : ar->index = index;
164 14 : ar->region = mq->region;
165 14 : ar->offset = mq->offset;
166 14 : ar->log2_ring_size = mq->log2_ring_size;
167 14 : ar->flags = (direction == MEMIF_RING_S2M) ? MEMIF_MSG_ADD_RING_FLAG_S2M : 0;
168 14 : ar->private_hdr_size = 0;
169 14 : }
170 :
171 : static void
172 7 : memif_msg_enq_connect (memif_if_t * mif)
173 : {
174 : memif_msg_fifo_elt_t *e;
175 7 : clib_fifo_add2 (mif->msg_queue, e);
176 7 : memif_msg_connect_t *c = &e->msg.connect;
177 :
178 7 : e->msg.type = MEMIF_MSG_TYPE_CONNECT;
179 7 : e->fd = -1;
180 7 : memif_msg_snprintf (c->if_name, sizeof (c->if_name), "%U",
181 : format_memif_device_name, mif->dev_instance);
182 7 : }
183 :
184 : static void
185 7 : memif_msg_enq_connected (memif_if_t * mif)
186 : {
187 : memif_msg_fifo_elt_t *e;
188 7 : clib_fifo_add2 (mif->msg_queue, e);
189 7 : memif_msg_connected_t *c = &e->msg.connected;
190 :
191 7 : e->msg.type = MEMIF_MSG_TYPE_CONNECTED;
192 7 : e->fd = -1;
193 7 : memif_msg_snprintf (c->if_name, sizeof (c->if_name), "%U",
194 : format_memif_device_name, mif->dev_instance);
195 7 : }
196 :
197 : clib_error_t *
198 8 : memif_msg_send_disconnect (memif_if_t * mif, clib_error_t * err)
199 : {
200 8 : memif_msg_t msg = { 0 };
201 8 : msg.type = MEMIF_MSG_TYPE_DISCONNECT;
202 8 : memif_msg_disconnect_t *d = &msg.disconnect;
203 :
204 8 : d->code = err->code;
205 8 : memif_msg_strlcpy (d->string, sizeof (d->string), err->what);
206 :
207 8 : return clib_socket_sendmsg (mif->sock, &msg, sizeof (memif_msg_t), 0, 0);
208 : }
209 :
210 : static clib_error_t *
211 7 : memif_msg_receive_hello (memif_if_t * mif, memif_msg_t * msg)
212 : {
213 7 : memif_msg_hello_t *h = &msg->hello;
214 :
215 7 : if (msg->hello.min_version > MEMIF_VERSION ||
216 7 : msg->hello.max_version < MEMIF_VERSION)
217 0 : return clib_error_return (0, "incompatible protocol version");
218 :
219 7 : mif->run.num_s2m_rings = clib_min (h->max_s2m_ring + 1,
220 : mif->cfg.num_s2m_rings);
221 7 : mif->run.num_m2s_rings = clib_min (h->max_m2s_ring + 1,
222 : mif->cfg.num_m2s_rings);
223 7 : mif->run.log2_ring_size = clib_min (h->max_log2_ring_size,
224 : mif->cfg.log2_ring_size);
225 7 : mif->run.buffer_size = mif->cfg.buffer_size;
226 :
227 7 : mif->remote_name = memif_str2vec (h->name, sizeof (h->name));
228 :
229 7 : return 0;
230 : }
231 :
232 : static clib_error_t *
233 7 : memif_msg_receive_init (memif_if_t ** mifp, memif_msg_t * msg,
234 : clib_socket_t * sock, uword socket_file_index)
235 : {
236 7 : memif_main_t *mm = &memif_main;
237 7 : memif_socket_file_t *msf =
238 7 : vec_elt_at_index (mm->socket_files, socket_file_index);
239 7 : memif_msg_init_t *i = &msg->init;
240 : memif_if_t *mif, tmp;
241 : clib_error_t *err;
242 : uword *p;
243 :
244 7 : if (i->version != MEMIF_VERSION)
245 : {
246 0 : memif_file_del_by_index (sock->private_data);
247 0 : return clib_error_return (0, "unsupported version");
248 : }
249 :
250 7 : p = mhash_get (&msf->dev_instance_by_id, &i->id);
251 :
252 7 : if (!p)
253 : {
254 0 : err = clib_error_return (0, "unmatched interface id");
255 0 : goto error;
256 : }
257 :
258 7 : mif = vec_elt_at_index (mm->interfaces, p[0]);
259 :
260 7 : if (mif->flags & MEMIF_IF_FLAG_IS_SLAVE)
261 : {
262 0 : err = clib_error_return (0, "cannot connect to slave");
263 0 : goto error;
264 : }
265 :
266 7 : if (mif->sock)
267 : {
268 0 : err = clib_error_return (0, "already connected");
269 0 : goto error;
270 : }
271 :
272 7 : if (i->mode != mif->mode)
273 : {
274 0 : err = clib_error_return (0, "mode mismatch");
275 0 : goto error;
276 : }
277 :
278 7 : mif->sock = sock;
279 7 : hash_set (msf->dev_instance_by_fd, mif->sock->fd, mif->dev_instance);
280 7 : mif->remote_name = memif_str2vec (i->name, sizeof (i->name));
281 7 : *mifp = mif;
282 :
283 7 : if (mif->secret)
284 : {
285 : u8 *s;
286 : int r;
287 3 : s = memif_str2vec (i->secret, sizeof (i->secret));
288 3 : if (s == 0)
289 0 : return clib_error_return (0, "secret required");
290 :
291 15 : r = vec_cmp (s, mif->secret);
292 3 : vec_free (s);
293 :
294 3 : if (r)
295 0 : return clib_error_return (0, "incorrect secret");
296 : }
297 :
298 7 : return 0;
299 :
300 0 : error:
301 0 : tmp.sock = sock;
302 0 : memif_msg_send_disconnect (&tmp, err);
303 0 : memif_socket_close (&sock);
304 0 : return err;
305 : }
306 :
307 : static clib_error_t *
308 14 : memif_msg_receive_add_region (memif_if_t * mif, memif_msg_t * msg, int fd)
309 : {
310 14 : memif_msg_add_region_t *ar = &msg->add_region;
311 : memif_region_t *mr;
312 14 : if (fd < 0)
313 0 : return clib_error_return (0, "missing memory region fd");
314 :
315 14 : if (ar->index != vec_len (mif->regions))
316 0 : return clib_error_return (0, "unexpected region index");
317 :
318 14 : if (ar->index > MEMIF_MAX_REGION)
319 0 : return clib_error_return (0, "too many regions");
320 :
321 14 : vec_validate_aligned (mif->regions, ar->index, CLIB_CACHE_LINE_BYTES);
322 14 : mr = vec_elt_at_index (mif->regions, ar->index);
323 14 : mr->fd = fd;
324 14 : mr->region_size = ar->size;
325 :
326 14 : return 0;
327 : }
328 :
329 : static clib_error_t *
330 14 : memif_msg_receive_add_ring (memif_if_t * mif, memif_msg_t * msg, int fd)
331 : {
332 14 : memif_msg_add_ring_t *ar = &msg->add_ring;
333 : memif_queue_t *mq;
334 :
335 14 : if (fd < 0)
336 0 : return clib_error_return (0, "missing ring interrupt fd");
337 :
338 14 : if (ar->private_hdr_size != 0)
339 0 : return clib_error_return (0, "private headers not supported");
340 :
341 14 : if (ar->flags & MEMIF_MSG_ADD_RING_FLAG_S2M)
342 : {
343 7 : if (ar->index != vec_len (mif->rx_queues))
344 0 : return clib_error_return (0, "unexpected ring index");
345 :
346 7 : if (ar->index > MEMIF_MAX_S2M_RING)
347 0 : return clib_error_return (0, "too many rings");
348 :
349 7 : vec_validate_aligned (mif->rx_queues, ar->index, CLIB_CACHE_LINE_BYTES);
350 7 : mq = vec_elt_at_index (mif->rx_queues, ar->index);
351 7 : mif->run.num_s2m_rings = vec_len (mif->rx_queues);
352 : }
353 : else
354 : {
355 7 : if (ar->index != vec_len (mif->tx_queues))
356 0 : return clib_error_return (0, "unexpected ring index");
357 :
358 7 : if (ar->index > MEMIF_MAX_M2S_RING)
359 0 : return clib_error_return (0, "too many rings");
360 :
361 7 : vec_validate_aligned (mif->tx_queues, ar->index, CLIB_CACHE_LINE_BYTES);
362 7 : mq = vec_elt_at_index (mif->tx_queues, ar->index);
363 7 : mif->run.num_m2s_rings = vec_len (mif->tx_queues);
364 : }
365 :
366 : // clear previous cache data if interface reconnected
367 14 : clib_memset (mq, 0, sizeof (memif_queue_t));
368 14 : mq->int_fd = fd;
369 14 : mq->int_clib_file_index = ~0;
370 14 : mq->log2_ring_size = ar->log2_ring_size;
371 14 : mq->region = ar->region;
372 14 : mq->offset = ar->offset;
373 14 : mq->type =
374 14 : (ar->flags & MEMIF_MSG_ADD_RING_FLAG_S2M) ? MEMIF_RING_S2M :
375 : MEMIF_RING_M2S;
376 :
377 14 : return 0;
378 : }
379 :
380 : static clib_error_t *
381 7 : memif_msg_receive_connect (memif_if_t * mif, memif_msg_t * msg)
382 : {
383 : clib_error_t *err;
384 7 : memif_msg_connect_t *c = &msg->connect;
385 :
386 7 : if ((err = memif_connect (mif)))
387 0 : return err;
388 :
389 7 : mif->remote_if_name = memif_str2vec (c->if_name, sizeof (c->if_name));
390 :
391 7 : return 0;
392 : }
393 :
394 : static clib_error_t *
395 7 : memif_msg_receive_connected (memif_if_t * mif, memif_msg_t * msg)
396 : {
397 : clib_error_t *err;
398 7 : memif_msg_connected_t *c = &msg->connected;
399 :
400 7 : if ((err = memif_connect (mif)))
401 0 : return err;
402 :
403 7 : mif->remote_if_name = memif_str2vec (c->if_name, sizeof (c->if_name));
404 7 : return 0;
405 : }
406 :
407 : static clib_error_t *
408 4 : memif_msg_receive_disconnect (memif_if_t * mif, memif_msg_t * msg)
409 : {
410 4 : memif_msg_disconnect_t *d = &msg->disconnect;
411 :
412 4 : mif->remote_disc_string = memif_str2vec (d->string, sizeof (d->string));
413 4 : return clib_error_return (0, "disconnect received");
414 : }
415 :
416 : static clib_error_t *
417 95 : memif_msg_receive (memif_if_t ** mifp, clib_socket_t * sock, clib_file_t * uf)
418 : {
419 95 : memif_msg_t msg = { 0 };
420 95 : clib_error_t *err = 0;
421 95 : int fd = -1;
422 : int i;
423 95 : memif_if_t *mif = *mifp;
424 :
425 95 : err = clib_socket_recvmsg (sock, &msg, sizeof (memif_msg_t), &fd, 1);
426 95 : if (err)
427 0 : goto error;
428 :
429 95 : if (mif == 0 && msg.type != MEMIF_MSG_TYPE_INIT)
430 : {
431 0 : memif_socket_close (&sock);
432 0 : err = clib_error_return (0, "unexpected message received");
433 0 : goto error;
434 : }
435 :
436 95 : memif_log_debug (mif, "Message type %u received", msg.type);
437 : /* process the message based on its type */
438 95 : switch (msg.type)
439 : {
440 35 : case MEMIF_MSG_TYPE_ACK:
441 35 : break;
442 :
443 7 : case MEMIF_MSG_TYPE_HELLO:
444 7 : if ((err = memif_msg_receive_hello (mif, &msg)))
445 0 : goto error;
446 7 : if ((err = memif_init_regions_and_queues (mif)))
447 0 : goto error;
448 7 : memif_msg_enq_init (mif);
449 : /* *INDENT-OFF* */
450 21 : vec_foreach_index (i, mif->regions)
451 14 : memif_msg_enq_add_region (mif, i);
452 14 : vec_foreach_index (i, mif->tx_queues)
453 7 : memif_msg_enq_add_ring (mif, i, MEMIF_RING_S2M);
454 14 : vec_foreach_index (i, mif->rx_queues)
455 7 : memif_msg_enq_add_ring (mif, i, MEMIF_RING_M2S);
456 : /* *INDENT-ON* */
457 7 : memif_msg_enq_connect (mif);
458 7 : break;
459 :
460 7 : case MEMIF_MSG_TYPE_INIT:
461 7 : if ((err = memif_msg_receive_init (mifp, &msg, sock, uf->private_data)))
462 0 : goto error;
463 7 : mif = *mifp;
464 7 : vec_reset_length (uf->description);
465 7 : uf->description = format (uf->description, "%U ctl",
466 : format_memif_device_name, mif->dev_instance);
467 7 : memif_msg_enq_ack (mif);
468 7 : break;
469 :
470 14 : case MEMIF_MSG_TYPE_ADD_REGION:
471 14 : if ((err = memif_msg_receive_add_region (mif, &msg, fd)))
472 0 : goto error;
473 14 : memif_msg_enq_ack (mif);
474 14 : break;
475 :
476 14 : case MEMIF_MSG_TYPE_ADD_RING:
477 14 : if ((err = memif_msg_receive_add_ring (mif, &msg, fd)))
478 0 : goto error;
479 14 : memif_msg_enq_ack (mif);
480 14 : break;
481 :
482 7 : case MEMIF_MSG_TYPE_CONNECT:
483 7 : if ((err = memif_msg_receive_connect (mif, &msg)))
484 0 : goto error;
485 7 : memif_msg_enq_connected (mif);
486 7 : break;
487 :
488 7 : case MEMIF_MSG_TYPE_CONNECTED:
489 7 : if ((err = memif_msg_receive_connected (mif, &msg)))
490 0 : goto error;
491 7 : break;
492 :
493 4 : case MEMIF_MSG_TYPE_DISCONNECT:
494 4 : if ((err = memif_msg_receive_disconnect (mif, &msg)))
495 4 : goto error;
496 0 : break;
497 :
498 0 : default:
499 0 : err = clib_error_return (0, "unknown message type (0x%x)", msg.type);
500 0 : goto error;
501 : }
502 :
503 91 : if (clib_fifo_elts (mif->msg_queue))
504 84 : clib_file_set_data_available_to_write (&file_main,
505 84 : mif->sock->private_data, 1);
506 91 : return 0;
507 :
508 4 : error:
509 4 : memif_log_err (mif, "%U", format_clib_error, err);
510 4 : return err;
511 : }
512 :
513 : clib_error_t *
514 45 : memif_master_conn_fd_read_ready (clib_file_t * uf)
515 : {
516 45 : memif_main_t *mm = &memif_main;
517 45 : memif_socket_file_t *msf =
518 45 : pool_elt_at_index (mm->socket_files, uf->private_data);
519 : uword *p;
520 45 : memif_if_t *mif = 0;
521 45 : clib_socket_t *sock = 0;
522 45 : clib_error_t *err = 0;
523 :
524 45 : p = hash_get (msf->dev_instance_by_fd, uf->file_descriptor);
525 45 : if (p)
526 : {
527 38 : mif = vec_elt_at_index (mm->interfaces, p[0]);
528 38 : sock = mif->sock;
529 : }
530 : else
531 : {
532 : /* This is new connection, remove index from pending vector */
533 : int i;
534 7 : vec_foreach_index (i, msf->pending_clients)
535 7 : if (msf->pending_clients[i]->fd == uf->file_descriptor)
536 : {
537 7 : sock = msf->pending_clients[i];
538 7 : vec_del1 (msf->pending_clients, i);
539 7 : break;
540 : }
541 7 : ASSERT (sock != 0);
542 : }
543 45 : err = memif_msg_receive (&mif, sock, uf);
544 45 : if (err)
545 : {
546 3 : memif_disconnect (mif, err);
547 3 : clib_error_free (err);
548 : }
549 45 : return 0;
550 : }
551 :
552 : clib_error_t *
553 50 : memif_slave_conn_fd_read_ready (clib_file_t * uf)
554 : {
555 50 : memif_main_t *mm = &memif_main;
556 : clib_error_t *err;
557 50 : memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data);
558 50 : err = memif_msg_receive (&mif, mif->sock, uf);
559 50 : if (err)
560 : {
561 1 : memif_disconnect (mif, err);
562 1 : clib_error_free (err);
563 : }
564 50 : return 0;
565 : }
566 :
567 : static clib_error_t *
568 84 : memif_conn_fd_write_ready (clib_file_t * uf, memif_if_t * mif)
569 : {
570 : memif_msg_fifo_elt_t *e;
571 84 : clib_fifo_sub2 (mif->msg_queue, e);
572 84 : clib_file_set_data_available_to_write (&file_main,
573 84 : mif->sock->private_data, 0);
574 168 : return clib_socket_sendmsg (mif->sock, &e->msg, sizeof (memif_msg_t),
575 84 : &e->fd, e->fd > -1 ? 1 : 0);
576 : }
577 :
578 : clib_error_t *
579 42 : memif_master_conn_fd_write_ready (clib_file_t * uf)
580 : {
581 42 : memif_main_t *mm = &memif_main;
582 42 : memif_socket_file_t *msf =
583 42 : pool_elt_at_index (mm->socket_files, uf->private_data);
584 : uword *p;
585 : memif_if_t *mif;
586 :
587 42 : p = hash_get (msf->dev_instance_by_fd, uf->file_descriptor);
588 42 : if (!p)
589 0 : return 0;
590 :
591 42 : mif = vec_elt_at_index (mm->interfaces, p[0]);
592 42 : return memif_conn_fd_write_ready (uf, mif);
593 : }
594 :
595 : clib_error_t *
596 42 : memif_slave_conn_fd_write_ready (clib_file_t * uf)
597 : {
598 42 : memif_main_t *mm = &memif_main;
599 42 : memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data);
600 42 : return memif_conn_fd_write_ready (uf, mif);
601 : }
602 :
603 : clib_error_t *
604 0 : memif_slave_conn_fd_error (clib_file_t * uf)
605 : {
606 0 : memif_main_t *mm = &memif_main;
607 0 : memif_if_t *mif = vec_elt_at_index (mm->interfaces, uf->private_data);
608 : clib_error_t *err;
609 :
610 0 : err = clib_error_return (0, "connection fd error");
611 0 : memif_disconnect (mif, err);
612 0 : clib_error_free (err);
613 :
614 0 : return 0;
615 : }
616 :
617 : clib_error_t *
618 0 : memif_master_conn_fd_error (clib_file_t * uf)
619 : {
620 0 : memif_main_t *mm = &memif_main;
621 0 : memif_socket_file_t *msf =
622 0 : pool_elt_at_index (mm->socket_files, uf->private_data);
623 : uword *p;
624 :
625 :
626 0 : p = hash_get (msf->dev_instance_by_fd, uf->file_descriptor);
627 0 : if (p)
628 : {
629 : memif_if_t *mif;
630 : clib_error_t *err;
631 0 : mif = vec_elt_at_index (mm->interfaces, p[0]);
632 0 : err = clib_error_return (0, "connection fd error");
633 0 : memif_disconnect (mif, err);
634 0 : clib_error_free (err);
635 : }
636 : else
637 : {
638 : int i;
639 0 : vec_foreach_index (i, msf->pending_clients)
640 0 : if (msf->pending_clients[i]->fd == uf->file_descriptor)
641 : {
642 0 : clib_socket_t *s = msf->pending_clients[i];
643 0 : memif_socket_close (&s);
644 0 : vec_del1 (msf->pending_clients, i);
645 0 : return 0;
646 : }
647 : }
648 :
649 0 : memif_log_warn (0, "Error on unknown file descriptor %d",
650 : uf->file_descriptor);
651 0 : if (uf->file_descriptor != ~0)
652 0 : memif_file_del (uf);
653 0 : return 0;
654 : }
655 :
656 :
657 : clib_error_t *
658 7 : memif_conn_fd_accept_ready (clib_file_t * uf)
659 : {
660 7 : memif_main_t *mm = &memif_main;
661 7 : memif_socket_file_t *msf =
662 7 : pool_elt_at_index (mm->socket_files, uf->private_data);
663 7 : clib_file_t template = { 0 };
664 : clib_error_t *err;
665 : clib_socket_t *client;
666 :
667 7 : client = clib_mem_alloc (sizeof (clib_socket_t));
668 7 : clib_memset (client, 0, sizeof (clib_socket_t));
669 7 : err = clib_socket_accept (msf->sock, client);
670 7 : if (err)
671 0 : goto error;
672 :
673 7 : template.read_function = memif_master_conn_fd_read_ready;
674 7 : template.write_function = memif_master_conn_fd_write_ready;
675 7 : template.error_function = memif_master_conn_fd_error;
676 7 : template.file_descriptor = client->fd;
677 7 : template.private_data = uf->private_data;
678 7 : template.description = format (0, "memif in conn on %s", msf->filename);
679 :
680 7 : memif_file_add (&client->private_data, &template);
681 :
682 7 : err = memif_msg_enq_hello (client);
683 7 : if (err)
684 : {
685 0 : clib_socket_close (client);
686 0 : goto error;
687 : }
688 :
689 7 : vec_add1 (msf->pending_clients, client);
690 :
691 7 : return 0;
692 :
693 0 : error:
694 0 : memif_log_err (0, "%U", format_clib_error, err);
695 0 : clib_mem_free (client);
696 0 : return err;
697 : }
698 :
699 : /*
700 : * fd.io coding-style-patch-verification: ON
701 : *
702 : * Local Variables:
703 : * eval: (c-set-style "gnu")
704 : * End:
705 : */
|