FD.io VPP  v16.09
Vector Packet Processing
plugin.c
Go to the documentation of this file.
1 /*
2  * plugin.c: plugin handling
3  *
4  * Copyright (c) 2011 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vlib/unix/plugin.h>
19 #include <dlfcn.h>
20 #include <dirent.h>
21 
23 
24 void
26 {
28  pm->handoff_structure_get_cb = cb;
29 }
30 
31 static void *
33 {
34  void *(*fp) (void);
35 
36  fp = vlib_plugin_main.handoff_structure_get_cb;
37  if (fp == 0)
38  return 0;
39  else
40  return (*fp) ();
41 }
42 
43 static int
44 load_one_plugin (plugin_main_t * pm, plugin_info_t * pi, int from_early_init)
45 {
46  void *handle, *register_handle;
47  clib_error_t *(*fp) (vlib_main_t *, void *, int);
48  clib_error_t *error;
49  void *handoff_structure;
50 
51  handle = dlopen ((char *) pi->name, RTLD_LAZY);
52 
53  /*
54  * Note: this can happen if the plugin has an undefined symbol reference,
55  * so print a warning. Otherwise, the poor slob won't know what happened.
56  * Ask me how I know that...
57  */
58  if (handle == 0)
59  {
60  clib_warning ("%s", dlerror ());
61  return -1;
62  }
63 
64  pi->handle = handle;
65 
66 
67  register_handle = dlsym (pi->handle, "vlib_plugin_register");
68  if (register_handle == 0)
69  {
70  dlclose (handle);
71  clib_warning ("Plugin missing vlib_plugin_register: %s\n",
72  (char *) pi->name);
73  return 1;
74  }
75 
76  fp = register_handle;
77 
78  handoff_structure = vnet_get_handoff_structure ();
79 
80  if (handoff_structure == 0)
81  error = clib_error_return (0, "handoff structure callback returned 0");
82  else
83  error = (*fp) (pm->vlib_main, handoff_structure, from_early_init);
84 
85  if (error)
86  {
87  clib_error_report (error);
88  dlclose (handle);
89  return 1;
90  }
91 
92  clib_warning ("Loaded plugin: %s", pi->name);
93 
94  return 0;
95 }
96 
97 static u8 **
99 {
100  int i;
101  u8 **rv = 0;
102  u8 *path = pm->plugin_path;
103  u8 *this = 0;
104 
105  for (i = 0; i < vec_len (pm->plugin_path); i++)
106  {
107  if (path[i] != ':')
108  {
109  vec_add1 (this, path[i]);
110  continue;
111  }
112  vec_add1 (this, 0);
113  vec_add1 (rv, this);
114  this = 0;
115  }
116  if (this)
117  {
118  vec_add1 (this, 0);
119  vec_add1 (rv, this);
120  }
121  return rv;
122 }
123 
124 int
125 vlib_load_new_plugins (plugin_main_t * pm, int from_early_init)
126 {
127  DIR *dp;
128  struct dirent *entry;
129  struct stat statb;
130  uword *p;
131  plugin_info_t *pi;
132  u8 **plugin_path;
133  int i;
134 
135  plugin_path = split_plugin_path (pm);
136 
137  for (i = 0; i < vec_len (plugin_path); i++)
138  {
139  dp = opendir ((char *) plugin_path[i]);
140 
141  if (dp == 0)
142  continue;
143 
144  while ((entry = readdir (dp)))
145  {
146  u8 *plugin_name;
147 
148  if (pm->plugin_name_filter)
149  {
150  int j;
151  for (j = 0; j < vec_len (pm->plugin_name_filter); j++)
152  if (entry->d_name[j] != pm->plugin_name_filter[j])
153  goto next;
154  }
155 
156  plugin_name = format (0, "%s/%s%c", plugin_path[i],
157  entry->d_name, 0);
158 
159  /* Only accept .so */
160  char *ext = strrchr ((const char *) plugin_name, '.');
161  /* unreadable */
162  if (!ext || (strcmp (ext, ".so") != 0) ||
163  stat ((char *) plugin_name, &statb) < 0)
164  {
165  ignore:
166  vec_free (plugin_name);
167  continue;
168  }
169 
170  /* a dir or other things which aren't plugins */
171  if (!S_ISREG (statb.st_mode))
172  goto ignore;
173 
174  p = hash_get_mem (pm->plugin_by_name_hash, plugin_name);
175  if (p == 0)
176  {
177  vec_add2 (pm->plugin_info, pi, 1);
178  pi->name = plugin_name;
179  pi->file_info = statb;
180 
181  if (load_one_plugin (pm, pi, from_early_init))
182  {
183  vec_free (plugin_name);
184  _vec_len (pm->plugin_info) = vec_len (pm->plugin_info) - 1;
185  continue;
186  }
187  memset (pi, 0, sizeof (*pi));
188  hash_set_mem (pm->plugin_by_name_hash, plugin_name,
189  pi - pm->plugin_info);
190  }
191  next:
192  ;
193  }
194  closedir (dp);
195  vec_free (plugin_path[i]);
196  }
197  vec_free (plugin_path);
198  return 0;
199 }
200 
201 char *vlib_plugin_path __attribute__ ((weak));
202 char *vlib_plugin_path = "";
203 char *vlib_plugin_name_filter __attribute__ ((weak));
204 char *vlib_plugin_name_filter = 0;
205 
206 int
208 {
210 
211  pm->plugin_path = format (0, "%s%c", vlib_plugin_path, 0);
212 
213  clib_warning ("plugin path %s", pm->plugin_path);
214 
215  if (vlib_plugin_name_filter)
216  pm->plugin_name_filter = format (0, "%s%c", vlib_plugin_name_filter, 0);
217 
218  pm->plugin_by_name_hash = hash_create_string (0, sizeof (uword));
219  pm->vlib_main = vm;
220 
221  return vlib_load_new_plugins (pm, 1 /* from_early_init */ );
222 }
223 
224 static clib_error_t *
226  unformat_input_t * input, vlib_cli_command_t * cmd)
227 {
229  u8 *s = 0;
230  u8 *key = 0;
231  uword *value = 0;
232  int index = 1;
233 
234  s = format (s, " Plugin path is: %s\n", pm->plugin_path);
235  if (vlib_plugin_name_filter)
236  s = format (s, " Plugin filter: %s\n", vlib_plugin_name_filter);
237 
238  s = format (s, " Plugins loaded: \n");
239  hash_foreach_mem (key, value, pm->plugin_by_name_hash,
240  {
241  if (key != 0)
242  s = format (s, " %d.%s\n", index, key); index++;}
243  );
244 
245  vlib_cli_output (vm, "%v", s);
246  vec_free (s);
247  return 0;
248 }
249 
250 VLIB_CLI_COMMAND (plugins_show_cmd, static) =
251 {
252 .path = "show plugins",.short_help = "show loaded plugins",.function =
254 /*
255  * fd.io coding-style-patch-verification: ON
256  *
257  * Local Variables:
258  * eval: (c-set-style "gnu")
259  * End:
260  */
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
int vlib_load_new_plugins(plugin_main_t *pm, int from_early_init)
Definition: plugin.c:125
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
vlib_main_t * vlib_main
Definition: plugin.h:82
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:521
#define hash_set_mem(h, key, value)
Definition: hash.h:274
#define clib_error_report(e)
Definition: error.h:125
u8 * name
Definition: plugin.h:63
static void * vnet_get_handoff_structure(void)
Definition: plugin.c:32
u8 * plugin_path
Definition: plugin.h:75
#define clib_warning(format, args...)
Definition: error.h:59
static clib_error_t * vlib_plugins_show_cmd_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: plugin.c:225
void vlib_set_get_handoff_structure_cb(void *cb)
Definition: plugin.c:25
#define hash_create_string(elts, value_bytes)
Definition: hash.h:641
static u8 ** split_plugin_path(plugin_main_t *pm)
Definition: plugin.c:98
plugin_main_t vlib_plugin_main
Definition: plugin.c:22
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:575
#define hash_foreach_mem(key_var, value_var, h, body)
Definition: hash.h:426
int vlib_plugin_early_init(vlib_main_t *vm)
Definition: plugin.c:207
uword * plugin_by_name_hash
Definition: plugin.h:72
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
static int load_one_plugin(plugin_main_t *pm, plugin_info_t *pi, int from_early_init)
Definition: plugin.c:44
void * handoff_structure_get_cb
Definition: plugin.h:79
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:418
u64 uword
Definition: types.h:112
plugin_info_t * plugin_info
Definition: plugin.h:71
u8 * plugin_name_filter
Definition: plugin.h:76
VLIB_CLI_COMMAND(set_interface_ip_source_and_port_range_check_command, static)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
#define hash_get_mem(h, key)
Definition: hash.h:268
void * handle
Definition: plugin.h:65
struct stat file_info
Definition: plugin.h:64
#define clib_error_return(e, args...)
Definition: error.h:111
struct _unformat_input_t unformat_input_t