FD.io VPP  v16.06
Vector Packet Processing
memory_client.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * memory_client.c - API message handling, client code.
4  *
5  * Copyright (c) 2010 Cisco and/or its affiliates.
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at:
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *------------------------------------------------------------------
18  */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <setjmp.h>
23 #include <sys/types.h>
24 #include <sys/mman.h>
25 #include <sys/stat.h>
26 #include <netinet/in.h>
27 #include <signal.h>
28 #include <pthread.h>
29 #include <unistd.h>
30 #include <time.h>
31 #include <fcntl.h>
32 #include <string.h>
33 #include <vppinfra/clib.h>
34 #include <vppinfra/vec.h>
35 #include <vppinfra/hash.h>
36 #include <vppinfra/bitmap.h>
37 #include <vppinfra/fifo.h>
38 #include <vppinfra/time.h>
39 #include <vppinfra/mheap.h>
40 #include <vppinfra/heap.h>
41 #include <vppinfra/pool.h>
42 #include <vppinfra/format.h>
43 
44 #include <vlib/vlib.h>
45 #include <vlib/unix/unix.h>
46 #include <vlibmemory/api.h>
47 
49 
50 #define vl_typedefs /* define message structures */
52 #undef vl_typedefs
53 
54 #define vl_endianfun /* define message structures */
56 #undef vl_endianfun
57 
58 /* instantiate all the print functions we know about */
59 #define vl_print(handle, ...) clib_warning (__VA_ARGS__)
60 #define vl_printfun
62 #undef vl_printfun
63 
64 typedef struct {
68  pthread_t rx_thread_handle;
69  /* Plugin message base lookup scheme */
73 
75 
76 static void *rx_thread_fn(void *arg)
77 {
80  api_main_t *am = &api_main;
81 
82  q = am->vl_input_queue;
83 
84  /* So we can make the rx thread terminate cleanly */
85  if (setjmp(mm->rx_thread_jmpbuf) == 0) {
86  mm->rx_thread_jmpbuf_valid = 1;
87  while (1) {
89  }
90  }
91  pthread_exit(0);
92 }
93 
96 {
98  vl_msg_api_free (mp);
99  longjmp (mm->rx_thread_jmpbuf, 1);
100 }
101 
102 static void noop_handler (void *notused)
103 {
104 }
105 
106 #define foreach_api_msg \
107 _(RX_THREAD_EXIT, rx_thread_exit)
108 
109 static int connect_to_vlib_internal (char *svm_name, char *client_name,
110  int rx_queue_size, int want_pthread)
111 {
112  int rv=0;
114 
115  if ((rv = vl_client_api_map(svm_name))) {
116  clib_warning ("vl_client_api map rv %d", rv);
117  return rv;
118  }
119 
120 #define _(N,n) \
121  vl_msg_api_set_handlers(VL_API_##N, #n, \
122  vl_api_##n##_t_handler, \
123  noop_handler, \
124  vl_api_##n##_t_endian, \
125  vl_api_##n##_t_print, \
126  sizeof(vl_api_##n##_t), 1);
128 #undef _
129 
130  if (vl_client_connect(client_name, 0 /* punt quota */,
131  rx_queue_size /* input queue */) < 0) {
133  return -1;
134  }
135 
136  /* Start the rx queue thread */
137 
138  if (want_pthread) {
139  rv = pthread_create(&mm->rx_thread_handle,
140  NULL /*attr*/, rx_thread_fn, 0);
141  if (rv)
142  clib_warning("pthread_create returned %d", rv);
143  }
144 
145  mm->connected_to_vlib = 1;
146  return 0;
147 }
148 
149 int vl_client_connect_to_vlib(char *svm_name, char *client_name,
150  int rx_queue_size)
151 {
152  return connect_to_vlib_internal (svm_name, client_name, rx_queue_size,
153  1 /* want pthread */);
154 }
155 
156 int vl_client_connect_to_vlib_no_rx_pthread (char *svm_name, char *client_name,
157  int rx_queue_size)
158 {
159  return connect_to_vlib_internal (svm_name, client_name, rx_queue_size,
160  0 /* want pthread */);
161 }
162 
164 {
166  api_main_t *am = &api_main;
167  uword junk;
168 
169  if (mm->rx_thread_jmpbuf_valid) {
171  ep = vl_msg_api_alloc (sizeof (*ep));
172  ep->_vl_msg_id = ntohs(VL_API_RX_THREAD_EXIT);
174  pthread_join (mm->rx_thread_handle, (void **) &junk);
175  }
176  if (mm->connected_to_vlib) {
179  }
180  memset (mm, 0, sizeof (*mm));
181 }
182 
185 {
187  i32 retval = ntohl(mp->retval);
188 
189  mm->first_msg_id_reply = (retval >= 0) ? ntohs(mp->first_msg_id) : ~0;
190  mm->first_msg_id_reply_ready = 1;
191 }
192 
194 {
196  api_main_t * am = &api_main;
198  f64 timeout;
199  void * old_handler;
200  clib_time_t clib_time;
201  u16 rv = ~0;
202 
203  if (strlen(plugin_name) + 1 > sizeof (mp->name))
204  return (rv);
205 
206  memset (&clib_time, 0, sizeof (clib_time));
207  clib_time_init (&clib_time);
208 
209  /* Push this plugin's first_msg_id_reply handler */
210  old_handler = am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY];
211  am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = (void *)
213 
214  /* Ask the data-plane for the message-ID base of the indicated plugin */
215  mm->first_msg_id_reply_ready = 0;
216 
217  mp = vl_msg_api_alloc (sizeof(*mp));
218  memset (mp, 0, sizeof (*mp));
219  mp->_vl_msg_id = ntohs(VL_API_GET_FIRST_MSG_ID);
220  mp->client_index = am->my_client_index;
221  strncpy ((char *) mp->name, plugin_name, sizeof (mp->name) - 1);
222 
224 
225  /* Synchronously wait for the answer */
226  do {
227  timeout = clib_time_now (&clib_time) + 1.0;
228 
229  while (clib_time_now (&clib_time) < timeout) {
230  if (mm->first_msg_id_reply_ready == 1) {
231  rv = mm->first_msg_id_reply;
232  goto result;
233  }
234  }
235  /* Restore old handler */
236  am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = old_handler;
237 
238  return rv;
239  } while(0);
240 
241 result:
242 
243  /* Restore the old handler */
244  am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = old_handler;
245 
246  if (rv == (u16) ~0)
247  clib_warning ("plugin '%s' not registered", plugin_name);
248 
249  return rv;
250 }
static int connect_to_vlib_internal(char *svm_name, char *client_name, int rx_queue_size, int want_pthread)
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
unix_shared_memory_queue_t * vl_input_queue
Definition: api.h:71
int my_client_index
Definition: api.h:148
#define NULL
Definition: clib.h:55
static void noop_handler(void *notused)
unix_shared_memory_queue_t * vl_input_queue
Definition: api.h:142
api_main_t api_main
Definition: api.h:162
pthread_t rx_thread_handle
Definition: memory_client.c:68
void vl_msg_api_free(void *)
int i32
Definition: types.h:81
static void * rx_thread_fn(void *arg)
Definition: memory_client.c:76
#define clib_warning(format, args...)
Definition: error.h:59
struct vl_shmem_hdr_ * shmem_hdr
Definition: api.h:125
int vl_client_connect_to_vlib(char *svm_name, char *client_name, int rx_queue_size)
int vl_client_api_map(char *region_name)
u16 vl_client_get_first_plugin_msg_id(char *plugin_name)
always_inline f64 clib_time_now(clib_time_t *c)
Definition: time.h:185
void clib_time_init(clib_time_t *c)
Definition: time.c:160
void * vl_msg_api_alloc(int nbytes)
#define foreach_api_msg
int vl_client_connect(char *name, int ctx_quota, int input_queue_size)
int vl_client_connect_to_vlib_no_rx_pthread(char *svm_name, char *client_name, int rx_queue_size)
u64 uword
Definition: types.h:112
void vl_client_disconnect(void)
void vl_client_api_unmap(void)
static void vl_api_get_first_msg_id_reply_t_handler(vl_api_get_first_msg_id_reply_t *mp)
unsigned short u16
Definition: types.h:57
double f64
Definition: types.h:140
unsigned char u8
Definition: types.h:56
static void vl_api_rx_thread_exit_t_handler(vl_api_rx_thread_exit_t *mp)
Definition: memory_client.c:94
memory_client_main_t memory_client_main
Definition: memory_client.c:74
void(** msg_handlers)(void *)
Definition: api.h:107
void vl_client_disconnect_from_vlib(void)
void vl_msg_api_queue_handler(unix_shared_memory_queue_t *q)
Definition: api_shared.c:615
volatile u8 first_msg_id_reply_ready
Definition: memory_client.c:70
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".
struct _unix_shared_memory_queue unix_shared_memory_queue_t