LCOV - code coverage report
Current view: top level - vpp/api - plugin.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 75 91 82.4 %
Date: 2023-10-26 01:39:38 Functions: 4 4 100.0 %

          Line data    Source code
       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             : 
      24             : plugin_main_t vat_plugin_main;
      25             : 
      26             : static vlib_log_class_t vat_builtin_logger;
      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
      36       27025 : load_one_vat_plugin (plugin_main_t * pm, plugin_info_t * pi)
      37             : {
      38             :   void *handle, *register_handle;
      39             :   clib_error_t *(*fp) (vat_main_t *);
      40             :   clib_error_t *error;
      41             : 
      42       27025 :   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       27025 :   if (handle == 0)
      50             :     {
      51           0 :       PLUGIN_LOG_ERR ("%s", dlerror ());
      52           0 :       return 0;
      53             :     }
      54             : 
      55       27025 :   pi->handle = handle;
      56             : 
      57       27025 :   register_handle = dlsym (pi->handle, "vat_plugin_register");
      58       27025 :   if (register_handle == 0)
      59             :     {
      60           0 :       PLUGIN_LOG_ERR ("%s: symbol vat_plugin_register not found", pi->name);
      61           0 :       dlclose (handle);
      62           0 :       return 0;
      63             :     }
      64             : 
      65       27025 :   fp = register_handle;
      66             : 
      67       27025 :   error = (*fp) (pm->vat_main);
      68             : 
      69       27025 :   if (error)
      70             :     {
      71        1725 :       u8 *err = format (0, "%U%c", format_clib_error, error, 0);
      72        1725 :       PLUGIN_LOG_ERR ((char *) err);
      73        1725 :       clib_error_free (error);
      74        1725 :       dlclose (handle);
      75        1725 :       pi->handle = 0;
      76        1725 :       return 1;
      77             :     }
      78             : 
      79       25300 :   PLUGIN_LOG_NOTICE ("Loaded plugin: %s", pi->name);
      80             : 
      81       25300 :   return 0;
      82             : }
      83             : 
      84             : static u8 **
      85         575 : split_plugin_path (plugin_main_t * pm)
      86             : {
      87             :   int i;
      88         575 :   u8 **rv = 0;
      89         575 :   u8 *path = pm->plugin_path;
      90         575 :   u8 *this = 0;
      91             : 
      92       77625 :   for (i = 0; i < vec_len (pm->plugin_path); i++)
      93             :     {
      94       77050 :       if (path[i] != ':')
      95             :         {
      96       77050 :           vec_add1 (this, path[i]);
      97       77050 :           continue;
      98             :         }
      99           0 :       vec_add1 (this, 0);
     100           0 :       vec_add1 (rv, this);
     101           0 :       this = 0;
     102             :     }
     103         575 :   if (this)
     104             :     {
     105         575 :       vec_add1 (this, 0);
     106         575 :       vec_add1 (rv, this);
     107             :     }
     108         575 :   return rv;
     109             : }
     110             : 
     111             : int
     112         575 : vat_load_new_plugins (plugin_main_t * pm)
     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         575 :   plugin_path = split_plugin_path (pm);
     123             : 
     124        1150 :   for (i = 0; i < vec_len (plugin_path); i++)
     125             :     {
     126         575 :       dp = opendir ((char *) plugin_path[i]);
     127             : 
     128         575 :       if (dp == 0)
     129           0 :         continue;
     130             : 
     131       28750 :       while ((entry = readdir (dp)))
     132             :         {
     133             :           u8 *plugin_name;
     134             :           u8 *file_name;
     135             : 
     136       28175 :           if (pm->plugin_name_filter)
     137             :             {
     138             :               int j;
     139           0 :               for (j = 0; j < vec_len (pm->plugin_name_filter); j++)
     140           0 :                 if (entry->d_name[j] != pm->plugin_name_filter[j])
     141           0 :                   goto next;
     142             :             }
     143             : 
     144       28175 :           file_name = format (0, "%s/%s%c", plugin_path[i], entry->d_name, 0);
     145       28175 :           plugin_name = format (0, "%s%c", entry->d_name, 0);
     146             : 
     147             :           /* unreadable */
     148       28175 :           if (stat ((char *) file_name, &statb) < 0)
     149             :             {
     150           0 :             ignore:
     151        1150 :               vec_free (file_name);
     152        1150 :               vec_free (plugin_name);
     153        2875 :               continue;
     154             :             }
     155             : 
     156             :           /* a dir or other things which aren't plugins */
     157       28175 :           if (!S_ISREG (statb.st_mode))
     158        1150 :             goto ignore;
     159             : 
     160       54050 :           p = hash_get_mem (pm->plugin_by_name_hash, plugin_name);
     161       27025 :           if (p == 0)
     162             :             {
     163       27025 :               vec_add2 (pm->plugin_info, pi, 1);
     164       27025 :               clib_memset (pi, 0, sizeof (*pi));
     165       27025 :               pi->name = plugin_name;
     166       27025 :               pi->filename = file_name;
     167       27025 :               pi->file_info = statb;
     168             : 
     169       27025 :               if (load_one_vat_plugin (pm, pi))
     170             :                 {
     171        1725 :                   vec_free (file_name);
     172        1725 :                   vec_free (plugin_name);
     173        1725 :                   vec_set_len (pm->plugin_info, vec_len (pm->plugin_info) - 1);
     174        1725 :                   continue;
     175             :                 }
     176       50600 :               hash_set_mem (pm->plugin_by_name_hash, plugin_name,
     177             :                             pi - pm->plugin_info);
     178             :             }
     179       25300 :         next:
     180             :           ;
     181             :         }
     182         575 :       closedir (dp);
     183         575 :       vec_free (plugin_path[i]);
     184             :     }
     185         575 :   vec_free (plugin_path);
     186         575 :   return 0;
     187             : }
     188             : 
     189             : #define QUOTE_(x) #x
     190             : #define QUOTE(x) QUOTE_(x)
     191             : 
     192             : extern char *vat_plugin_path;
     193             : 
     194             : char *vat_plugin_name_filter = 0;
     195             : 
     196             : int
     197         575 : vat_plugin_init (vat_main_t * vam)
     198             : {
     199         575 :   plugin_main_t *pm = &vat_plugin_main;
     200             :   u8 *vlib_get_vat_plugin_path (void);
     201             :   u8 *vlib_get_vat_plugin_name_filter (void);
     202             :   u8 *plugin_path;
     203             :   u8 *plugin_name_filter;
     204             : 
     205         575 :   vat_builtin_logger =
     206         575 :     vlib_log_register_class_rate_limit ("vat-plug", "load",
     207             :                                         0x7FFFFFFF /* aka no rate limit */ );
     208             : 
     209         575 :   plugin_path = vlib_get_vat_plugin_path ();
     210         575 :   plugin_name_filter = vlib_get_vat_plugin_name_filter ();
     211             : 
     212         575 :   if (plugin_path)
     213           0 :     vat_plugin_path = (char *) plugin_path;
     214             : 
     215         575 :   if (plugin_name_filter)
     216           0 :     vat_plugin_name_filter = (char *) plugin_name_filter;
     217             : 
     218         575 :   pm->plugin_path = format (0, "%s%c", vat_plugin_path, 0);
     219             : 
     220         575 :   if (vat_plugin_name_filter)
     221           0 :     pm->plugin_name_filter = format (0, "%s%c", vat_plugin_name_filter, 0);
     222             : 
     223         575 :   pm->plugin_by_name_hash = hash_create_string (0, sizeof (uword));
     224         575 :   pm->vat_main = vam;
     225             : 
     226         575 :   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             :  */

Generated by: LCOV version 1.14