FD.io VPP  v16.09
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
65 {
69  pthread_t rx_thread_handle;
70  /* Plugin message base lookup scheme */
74 
76 
77 static void *
78 rx_thread_fn (void *arg)
79 {
82  api_main_t *am = &api_main;
83 
84  q = am->vl_input_queue;
85 
86  /* So we can make the rx thread terminate cleanly */
87  if (setjmp (mm->rx_thread_jmpbuf) == 0)
88  {
89  mm->rx_thread_jmpbuf_valid = 1;
90  while (1)
91  {
93  }
94  }
95  pthread_exit (0);
96 }
97 
98 static void
100 {
102  vl_msg_api_free (mp);
103  longjmp (mm->rx_thread_jmpbuf, 1);
104 }
105 
106 static void
107 noop_handler (void *notused)
108 {
109 }
110 
111 #define foreach_api_msg \
112 _(RX_THREAD_EXIT, rx_thread_exit)
113 
114 static int
115 connect_to_vlib_internal (char *svm_name, char *client_name,
116  int rx_queue_size, int want_pthread)
117 {
118  int rv = 0;
120 
121  if ((rv = vl_client_api_map (svm_name)))
122  {
123  clib_warning ("vl_client_api map rv %d", rv);
124  return rv;
125  }
126 
127 #define _(N,n) \
128  vl_msg_api_set_handlers(VL_API_##N, #n, \
129  vl_api_##n##_t_handler, \
130  noop_handler, \
131  vl_api_##n##_t_endian, \
132  vl_api_##n##_t_print, \
133  sizeof(vl_api_##n##_t), 1);
135 #undef _
136 
137  if (vl_client_connect (client_name, 0 /* punt quota */ ,
138  rx_queue_size /* input queue */ ) < 0)
139  {
141  return -1;
142  }
143 
144  /* Start the rx queue thread */
145 
146  if (want_pthread)
147  {
148  rv = pthread_create (&mm->rx_thread_handle,
149  NULL /*attr */ , rx_thread_fn, 0);
150  if (rv)
151  clib_warning ("pthread_create returned %d", rv);
152  }
153 
154  mm->connected_to_vlib = 1;
155  return 0;
156 }
157 
158 int
159 vl_client_connect_to_vlib (char *svm_name, char *client_name,
160  int rx_queue_size)
161 {
162  return connect_to_vlib_internal (svm_name, client_name, rx_queue_size,
163  1 /* want pthread */ );
164 }
165 
166 int
167 vl_client_connect_to_vlib_no_rx_pthread (char *svm_name, char *client_name,
168  int rx_queue_size)
169 {
170  return connect_to_vlib_internal (svm_name, client_name, rx_queue_size,
171  0 /* want pthread */ );
172 }
173 
174 void
176 {
178  api_main_t *am = &api_main;
179  uword junk;
180 
181  if (mm->rx_thread_jmpbuf_valid)
182  {
184  ep = vl_msg_api_alloc (sizeof (*ep));
185  ep->_vl_msg_id = ntohs (VL_API_RX_THREAD_EXIT);
186  vl_msg_api_send_shmem (am->vl_input_queue, (u8 *) & ep);
187  pthread_join (mm->rx_thread_handle, (void **) &junk);
188  }
189  if (mm->connected_to_vlib)
190  {
193  }
194  memset (mm, 0, sizeof (*mm));
195 }
196 
199 {
201  i32 retval = ntohl (mp->retval);
202 
203  mm->first_msg_id_reply = (retval >= 0) ? ntohs (mp->first_msg_id) : ~0;
204  mm->first_msg_id_reply_ready = 1;
205 }
206 
207 u16
209 {
211  api_main_t *am = &api_main;
213  f64 timeout;
214  void *old_handler;
215  clib_time_t clib_time;
216  u16 rv = ~0;
217 
218  if (strlen (plugin_name) + 1 > sizeof (mp->name))
219  return (rv);
220 
221  memset (&clib_time, 0, sizeof (clib_time));
222  clib_time_init (&clib_time);
223 
224  /* Push this plugin's first_msg_id_reply handler */
225  old_handler = am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY];
226  am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = (void *)
228 
229  /* Ask the data-plane for the message-ID base of the indicated plugin */
230  mm->first_msg_id_reply_ready = 0;
231 
232  mp = vl_msg_api_alloc (sizeof (*mp));
233  memset (mp, 0, sizeof (*mp));
234  mp->_vl_msg_id = ntohs (VL_API_GET_FIRST_MSG_ID);
235  mp->client_index = am->my_client_index;
236  strncpy ((char *) mp->name, plugin_name, sizeof (mp->name) - 1);
237 
239 
240  /* Synchronously wait for the answer */
241  do
242  {
243  timeout = clib_time_now (&clib_time) + 1.0;
244 
245  while (clib_time_now (&clib_time) < timeout)
246  {
247  if (mm->first_msg_id_reply_ready == 1)
248  {
249  rv = mm->first_msg_id_reply;
250  goto result;
251  }
252  }
253  /* Restore old handler */
254  am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = old_handler;
255 
256  return rv;
257  }
258  while (0);
259 
260 result:
261 
262  /* Restore the old handler */
263  am->msg_handlers[VL_API_GET_FIRST_MSG_ID_REPLY] = old_handler;
264 
265  if (rv == (u16) ~ 0)
266  clib_warning ("plugin '%s' not registered", plugin_name);
267 
268  return rv;
269 }
270 
271 void
273 {
274  clib_warning ("STUB called...");
275 }
276 
277 /*
278  * fd.io coding-style-patch-verification: ON
279  *
280  * Local Variables:
281  * eval: (c-set-style "gnu")
282  * End:
283  */
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)
Fixed length block allocator.
unix_shared_memory_queue_t * vl_input_queue
Definition: api.h:73
int my_client_index
Definition: api.h:171
#define NULL
Definition: clib.h:55
static f64 clib_time_now(clib_time_t *c)
Definition: time.h:202
static void noop_handler(void *notused)
unix_shared_memory_queue_t * vl_input_queue
Definition: api.h:165
api_main_t api_main
Definition: api.h:185
pthread_t rx_thread_handle
Definition: memory_client.c:69
void vl_msg_api_free(void *)
int i32
Definition: types.h:81
static void * rx_thread_fn(void *arg)
Definition: memory_client.c:78
#define clib_warning(format, args...)
Definition: error.h:59
struct vl_shmem_hdr_ * shmem_hdr
Definition: api.h:132
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)
void clib_time_init(clib_time_t *c)
Definition: time.c:165
void * vl_msg_api_alloc(int nbytes)
void vlib_node_sync_stats(vlib_main_t *vm, vlib_node_t *n)
#define foreach_api_msg
int vl_client_connect(char *name, int ctx_quota, int input_queue_size)
Bitmaps built as vectors of machine words.
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:142
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:99
memory_client_main_t memory_client_main
Definition: memory_client.c:75
void(** msg_handlers)(void *)
Definition: api.h:114
void vl_client_disconnect_from_vlib(void)
void vl_msg_api_queue_handler(unix_shared_memory_queue_t *q)
Definition: api_shared.c:690
volatile u8 first_msg_id_reply_ready
Definition: memory_client.c:71
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".
struct _unix_shared_memory_queue unix_shared_memory_queue_t