FD.io VPP  v20.05.1-5-g09f167997
Vector Packet Processing
plugin.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  * plugin.c: plugin handling
17  */
18 
19 #include <vat/vat.h>
20 #include <vat/plugin.h>
21 #include <dlfcn.h>
22 #include <dirent.h>
23 
25 
27 
28 #define PLUGIN_LOG_DBG(...) \
29  do {vlib_log_debug (vat_builtin_logger, __VA_ARGS__);} while(0)
30 #define PLUGIN_LOG_ERR(...) \
31  do {vlib_log_err (vat_builtin_logger, __VA_ARGS__);} while(0)
32 #define PLUGIN_LOG_NOTICE(...) \
33  do {vlib_log_notice (vat_builtin_logger, __VA_ARGS__);} while(0)
34 
35 static int
37 {
38  void *handle, *register_handle;
39  clib_error_t *(*fp) (vat_main_t *);
40  clib_error_t *error;
41 
42  handle = dlopen ((char *) pi->filename, RTLD_LAZY);
43 
44  /*
45  * Note: this can happen if the plugin has an undefined symbol reference,
46  * so print a warning. Otherwise, the poor slob won't know what happened.
47  * Ask me how I know that...
48  */
49  if (handle == 0)
50  {
51  PLUGIN_LOG_ERR ("%s", dlerror ());
52  return 0;
53  }
54 
55  pi->handle = handle;
56 
57  register_handle = dlsym (pi->handle, "vat_plugin_register");
58  if (register_handle == 0)
59  {
60  PLUGIN_LOG_ERR ("%s: symbol vat_plugin_register not found", pi->name);
61  dlclose (handle);
62  return 0;
63  }
64 
65  fp = register_handle;
66 
67  error = (*fp) (pm->vat_main);
68 
69  if (error)
70  {
71  u8 *err = format (0, "%U%c", format_clib_error, error, 0);
72  PLUGIN_LOG_ERR ((char *) err);
73  clib_error_free (error);
74  dlclose (handle);
75  pi->handle = 0;
76  return 1;
77  }
78 
79  PLUGIN_LOG_NOTICE ("Loaded plugin: %s", pi->name);
80 
81  return 0;
82 }
83 
84 static u8 **
86 {
87  int i;
88  u8 **rv = 0;
89  u8 *path = pm->plugin_path;
90  u8 *this = 0;
91 
92  for (i = 0; i < vec_len (pm->plugin_path); i++)
93  {
94  if (path[i] != ':')
95  {
96  vec_add1 (this, path[i]);
97  continue;
98  }
99  vec_add1 (this, 0);
100  vec_add1 (rv, this);
101  this = 0;
102  }
103  if (this)
104  {
105  vec_add1 (this, 0);
106  vec_add1 (rv, this);
107  }
108  return rv;
109 }
110 
111 int
113 {
114  DIR *dp;
115  struct dirent *entry;
116  struct stat statb;
117  uword *p;
118  plugin_info_t *pi;
119  u8 **plugin_path;
120  int i;
121 
122  plugin_path = split_plugin_path (pm);
123 
124  for (i = 0; i < vec_len (plugin_path); i++)
125  {
126  dp = opendir ((char *) plugin_path[i]);
127 
128  if (dp == 0)
129  continue;
130 
131  while ((entry = readdir (dp)))
132  {
133  u8 *plugin_name;
134  u8 *file_name;
135 
136  if (pm->plugin_name_filter)
137  {
138  int j;
139  for (j = 0; j < vec_len (pm->plugin_name_filter); j++)
140  if (entry->d_name[j] != pm->plugin_name_filter[j])
141  goto next;
142  }
143 
144  file_name = format (0, "%s/%s%c", plugin_path[i], entry->d_name, 0);
145  plugin_name = format (0, "%s%c", entry->d_name, 0);
146 
147  /* unreadable */
148  if (stat ((char *) file_name, &statb) < 0)
149  {
150  ignore:
151  vec_free (file_name);
152  vec_free (plugin_name);
153  continue;
154  }
155 
156  /* a dir or other things which aren't plugins */
157  if (!S_ISREG (statb.st_mode))
158  goto ignore;
159 
160  p = hash_get_mem (pm->plugin_by_name_hash, plugin_name);
161  if (p == 0)
162  {
163  vec_add2 (pm->plugin_info, pi, 1);
164  pi->name = plugin_name;
165  pi->filename = file_name;
166  pi->file_info = statb;
167 
168  if (load_one_vat_plugin (pm, pi))
169  {
170  vec_free (file_name);
171  vec_free (plugin_name);
172  _vec_len (pm->plugin_info) = vec_len (pm->plugin_info) - 1;
173  continue;
174  }
175  clib_memset (pi, 0, sizeof (*pi));
176  hash_set_mem (pm->plugin_by_name_hash, plugin_name,
177  pi - pm->plugin_info);
178  }
179  next:
180  ;
181  }
182  closedir (dp);
183  vec_free (plugin_path[i]);
184  }
185  vec_free (plugin_path);
186  return 0;
187 }
188 
189 #define QUOTE_(x) #x
190 #define QUOTE(x) QUOTE_(x)
191 
192 extern char *vat_plugin_path;
193 
195 
196 int
197 vat_plugin_init (vat_main_t * vam)
198 {
202  u8 *plugin_path;
203  u8 *plugin_name_filter;
204 
206  vlib_log_register_class_rate_limit ("vat-plug", "load",
207  0x7FFFFFFF /* aka no rate limit */ );
208 
209  plugin_path = vlib_get_vat_plugin_path ();
210  plugin_name_filter = vlib_get_vat_plugin_name_filter ();
211 
212  if (plugin_path)
213  vat_plugin_path = (char *) plugin_path;
214 
215  if (plugin_name_filter)
216  vat_plugin_name_filter = (char *) plugin_name_filter;
217 
218  pm->plugin_path = format (0, "%s%c", vat_plugin_path, 0);
219 
221  pm->plugin_name_filter = format (0, "%s%c", vat_plugin_name_filter, 0);
222 
223  pm->plugin_by_name_hash = hash_create_string (0, sizeof (uword));
224  pm->vat_main = vam;
225 
226  return vat_load_new_plugins (pm);
227 }
228 
229 /*
230  * fd.io coding-style-patch-verification: ON
231  *
232  * Local Variables:
233  * eval: (c-set-style "gnu")
234  * End:
235  */
u8 * vlib_get_vat_plugin_name_filter(void)
Definition: plugin.c:523
u8 * format_clib_error(u8 *s, va_list *va)
Definition: error.c:191
u8 * filename
Definition: plugin.h:73
u8 * plugin_path
Definition: plugin.h:98
u8 * plugin_name_filter
Definition: plugin.h:99
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
char * vat_plugin_path
Definition: main.c:35
u8 * vlib_get_vat_plugin_path(void)
Definition: plugin.c:516
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:590
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:628
#define hash_set_mem(h, key, value)
Definition: hash.h:275
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
vl_api_fib_path_t path
Definition: mfib_types.api:34
#define PLUGIN_LOG_NOTICE(...)
Definition: plugin.c:32
unsigned char u8
Definition: types.h:56
u32 vlib_log_class_t
Definition: vlib.h:51
#define PLUGIN_LOG_ERR(...)
Definition: plugin.c:30
char * vat_plugin_name_filter
Definition: plugin.c:194
u8 * name
Definition: plugin.h:72
vlib_log_class_t vlib_log_register_class_rate_limit(char *class, char *subclass, u32 limit)
Definition: log.c:216
#define hash_create_string(elts, value_bytes)
Definition: hash.h:690
static int load_one_vat_plugin(plugin_main_t *pm, plugin_info_t *pi)
Definition: plugin.c:36
plugin_info_t * plugin_info
Definition: plugin.h:93
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
static u8 ** split_plugin_path(plugin_main_t *pm)
Definition: plugin.c:85
void * handle
Definition: plugin.h:75
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
u64 uword
Definition: types.h:112
int vat_plugin_init(vat_main_t *vam)
Definition: plugin.c:197
#define clib_error_free(e)
Definition: error.h:86
#define hash_get_mem(h, key)
Definition: hash.h:269
plugin_main_t vat_plugin_main
Definition: plugin.c:24
int vat_load_new_plugins(plugin_main_t *pm)
Definition: plugin.c:112
static vlib_log_class_t vat_builtin_logger
Definition: plugin.c:26
struct stat file_info
Definition: plugin.h:74
uword * plugin_by_name_hash
Definition: plugin.h:94