back to topotato report
topotato coverage report
Current view: top level - lib - lib_vty.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 30 126 23.8 %
Date: 2023-02-24 19:38:44 Functions: 4 12 33.3 %

          Line data    Source code
       1             : /*
       2             :  * Assorted library VTY commands
       3             :  *
       4             :  * Copyright (C) 1998 Kunihiro Ishiguro
       5             :  * Copyright (C) 2016-2017  David Lamparter for NetDEF, Inc.
       6             :  *
       7             :  * This program is free software; you can redistribute it and/or modify it
       8             :  * under the terms of the GNU General Public License as published by the Free
       9             :  * Software Foundation; either version 2 of the License, or (at your option)
      10             :  * any later version.
      11             :  *
      12             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      13             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14             :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      15             :  * more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License along
      18             :  * with this program; see the file COPYING; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #include <zebra.h>
      23             : /* malloc.h is generally obsolete, however GNU Libc mallinfo wants it. */
      24             : #ifdef HAVE_MALLOC_H
      25             : #include <malloc.h>
      26             : #endif
      27             : #ifdef HAVE_MALLOC_MALLOC_H
      28             : #include <malloc/malloc.h>
      29             : #endif
      30             : #include <dlfcn.h>
      31             : #ifdef HAVE_LINK_H
      32             : #include <link.h>
      33             : #endif
      34             : 
      35             : #include "log.h"
      36             : #include "memory.h"
      37             : #include "module.h"
      38             : #include "defaults.h"
      39             : #include "lib_vty.h"
      40             : #include "northbound_cli.h"
      41             : 
      42             : /* Looking up memory status from vty interface. */
      43             : #include "vector.h"
      44             : #include "vty.h"
      45             : #include "command.h"
      46             : 
      47             : #if defined(HAVE_MALLINFO2) || defined(HAVE_MALLINFO)
      48           0 : static int show_memory_mallinfo(struct vty *vty)
      49             : {
      50             : #if defined(HAVE_MALLINFO2)
      51           0 :         struct mallinfo2 minfo = mallinfo2();
      52             : #elif defined(HAVE_MALLINFO)
      53             :         struct mallinfo minfo = mallinfo();
      54             : #endif
      55           0 :         char buf[MTYPE_MEMSTR_LEN];
      56             : 
      57           0 :         vty_out(vty, "System allocator statistics:\n");
      58           0 :         vty_out(vty, "  Total heap allocated:  %s\n",
      59             :                 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.arena));
      60           0 :         vty_out(vty, "  Holding block headers: %s\n",
      61             :                 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.hblkhd));
      62           0 :         vty_out(vty, "  Used small blocks:     %s\n",
      63             :                 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.usmblks));
      64           0 :         vty_out(vty, "  Used ordinary blocks:  %s\n",
      65             :                 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.uordblks));
      66           0 :         vty_out(vty, "  Free small blocks:     %s\n",
      67             :                 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.fsmblks));
      68           0 :         vty_out(vty, "  Free ordinary blocks:  %s\n",
      69             :                 mtype_memstr(buf, MTYPE_MEMSTR_LEN, minfo.fordblks));
      70           0 :         vty_out(vty, "  Ordinary blocks:       %ld\n",
      71           0 :                 (unsigned long)minfo.ordblks);
      72           0 :         vty_out(vty, "  Small blocks:          %ld\n",
      73           0 :                 (unsigned long)minfo.smblks);
      74           0 :         vty_out(vty, "  Holding blocks:        %ld\n",
      75           0 :                 (unsigned long)minfo.hblks);
      76           0 :         vty_out(vty, "(see system documentation for 'mallinfo' for meaning)\n");
      77           0 :         return 1;
      78             : }
      79             : #endif /* HAVE_MALLINFO */
      80             : 
      81           0 : static int qmem_walker(void *arg, struct memgroup *mg, struct memtype *mt)
      82             : {
      83           0 :         struct vty *vty = arg;
      84           0 :         if (!mt) {
      85           0 :                 vty_out(vty, "--- qmem %s ---\n", mg->name);
      86           0 :                 vty_out(vty, "%-30s: %8s %-8s%s %8s %9s\n",
      87             :                         "Type", "Current#", "  Size",
      88             : #ifdef HAVE_MALLOC_USABLE_SIZE
      89             :                         "     Total",
      90             : #else
      91             :                         "",
      92             : #endif
      93             :                         "Max#",
      94             : #ifdef HAVE_MALLOC_USABLE_SIZE
      95             :                         "MaxBytes"
      96             : #else
      97             :                         ""
      98             : #endif
      99             :                         );
     100             :         } else {
     101           0 :                 if (mt->n_max != 0) {
     102           0 :                         char size[32];
     103           0 :                         snprintf(size, sizeof(size), "%6zu", mt->size);
     104             : #ifdef HAVE_MALLOC_USABLE_SIZE
     105             : #define TSTR " %9zu"
     106             : #define TARG , mt->total
     107             : #define TARG2 , mt->max_size
     108             : #else
     109             : #define TSTR ""
     110             : #define TARG
     111             : #define TARG2
     112             : #endif
     113           0 :                         vty_out(vty, "%-30s: %8zu %-8s"TSTR" %8zu"TSTR"\n",
     114             :                                 mt->name,
     115           0 :                                 mt->n_alloc,
     116           0 :                                 mt->size == 0 ? ""
     117           0 :                                               : mt->size == SIZE_VAR
     118             :                                                         ? "variable"
     119           0 :                                                         : size
     120           0 :                                 TARG,
     121           0 :                                 mt->n_max
     122           0 :                                 TARG2);
     123             :                 }
     124             :         }
     125           0 :         return 0;
     126             : }
     127             : 
     128             : 
     129           0 : DEFUN_NOSH (show_memory,
     130             :             show_memory_cmd,
     131             :             "show memory",
     132             :             "Show running system information\n"
     133             :             "Memory statistics\n")
     134             : {
     135             : #ifdef HAVE_MALLINFO
     136           0 :         show_memory_mallinfo(vty);
     137             : #endif /* HAVE_MALLINFO */
     138             : 
     139           0 :         qmem_walk(qmem_walker, vty);
     140           0 :         return CMD_SUCCESS;
     141             : }
     142             : 
     143           0 : DEFUN_NOSH (show_modules,
     144             :             show_modules_cmd,
     145             :             "show modules",
     146             :             "Show running system information\n"
     147             :             "Loaded modules\n")
     148             : {
     149           0 :         struct frrmod_runtime *plug = frrmod_list;
     150             : 
     151           0 :         vty_out(vty, "%-12s %-25s %s\n\n", "Module Name", "Version",
     152             :                 "Description");
     153           0 :         while (plug) {
     154           0 :                 const struct frrmod_info *i = plug->info;
     155             : 
     156           0 :                 vty_out(vty, "%-12s %-25s %s\n", i->name, i->version,
     157           0 :                         i->description);
     158           0 :                 if (plug->dl_handle) {
     159             : #ifdef HAVE_DLINFO_ORIGIN
     160           0 :                         char origin[MAXPATHLEN] = "";
     161           0 :                         dlinfo(plug->dl_handle, RTLD_DI_ORIGIN, &origin);
     162             : #ifdef HAVE_DLINFO_LINKMAP
     163           0 :                         const char *name;
     164           0 :                         struct link_map *lm = NULL;
     165           0 :                         dlinfo(plug->dl_handle, RTLD_DI_LINKMAP, &lm);
     166           0 :                         if (lm) {
     167           0 :                                 name = strrchr(lm->l_name, '/');
     168           0 :                                 name = name ? name + 1 : lm->l_name;
     169           0 :                                 vty_out(vty, "\tfrom: %s/%s\n", origin, name);
     170             :                         }
     171             : #else
     172             :                         vty_out(vty, "\tfrom: %s \n", origin, plug->load_name);
     173             : #endif
     174             : #else
     175             :                         vty_out(vty, "\tfrom: %s\n", plug->load_name);
     176             : #endif
     177             :                 }
     178           0 :                 plug = plug->next;
     179             :         }
     180             : 
     181           0 :         vty_out(vty, "pid: %u\n", (uint32_t)(getpid()));
     182             : 
     183           0 :         return CMD_SUCCESS;
     184             : }
     185             : 
     186           0 : DEFUN (frr_defaults,
     187             :        frr_defaults_cmd,
     188             :        "frr defaults PROFILE...",
     189             :        "FRRouting global parameters\n"
     190             :        "set of configuration defaults used\n"
     191             :        "profile string\n")
     192             : {
     193           0 :         char *profile = argv_concat(argv, argc, 2);
     194           0 :         int rv = CMD_SUCCESS;
     195             : 
     196           0 :         if (!frr_defaults_profile_valid(profile)) {
     197           0 :                 vty_out(vty, "%% WARNING: profile %s is not known in this version\n",
     198             :                         profile);
     199           0 :                 rv = CMD_WARNING;
     200             :         }
     201           0 :         frr_defaults_profile_set(profile);
     202           0 :         XFREE(MTYPE_TMP, profile);
     203           0 :         return rv;
     204             : }
     205             : 
     206           0 : DEFUN (frr_version,
     207             :        frr_version_cmd,
     208             :        "frr version VERSION...",
     209             :        "FRRouting global parameters\n"
     210             :        "version configuration was written by\n"
     211             :        "version string\n")
     212             : {
     213           0 :         char *version = argv_concat(argv, argc, 2);
     214             : 
     215           0 :         frr_defaults_version_set(version);
     216           0 :         XFREE(MTYPE_TMP, version);
     217           0 :         return CMD_SUCCESS;
     218             : }
     219             : 
     220             : static struct call_back {
     221             :         time_t readin_time;
     222             : 
     223             :         void (*start_config)(void);
     224             :         void (*end_config)(void);
     225             : } callback;
     226             : 
     227             : 
     228           8 : DEFUN_NOSH(start_config, start_config_cmd, "XFRR_start_configuration",
     229             :            "The Beginning of Configuration\n")
     230             : {
     231           8 :         callback.readin_time = monotime(NULL);
     232             : 
     233           8 :         vty->pending_allowed = 1;
     234             : 
     235           8 :         if (callback.start_config)
     236           0 :                 (*callback.start_config)();
     237             : 
     238           8 :         return CMD_SUCCESS;
     239             : }
     240             : 
     241           8 : DEFUN_NOSH(end_config, end_config_cmd, "XFRR_end_configuration",
     242             :            "The End of Configuration\n")
     243             : {
     244           8 :         time_t readin_time;
     245           8 :         char readin_time_str[MONOTIME_STRLEN];
     246           8 :         int ret;
     247             : 
     248           8 :         readin_time = monotime(NULL);
     249           8 :         readin_time -= callback.readin_time;
     250             : 
     251           8 :         frrtime_to_interval(readin_time, readin_time_str,
     252             :                             sizeof(readin_time_str));
     253             : 
     254           8 :         vty->pending_allowed = 0;
     255           8 :         ret = nb_cli_pending_commit_check(vty);
     256             : 
     257           8 :         zlog_info("Configuration Read in Took: %s", readin_time_str);
     258             : 
     259           8 :         if (callback.end_config)
     260           0 :                 (*callback.end_config)();
     261             : 
     262           8 :         return ret;
     263             : }
     264             : 
     265          48 : void cmd_init_config_callbacks(void (*start_config_cb)(void),
     266             :                                void (*end_config_cb)(void))
     267             : {
     268          48 :         callback.start_config = start_config_cb;
     269          48 :         callback.end_config = end_config_cb;
     270          48 : }
     271             : 
     272             : 
     273           0 : static void defaults_autocomplete(vector comps, struct cmd_token *token)
     274             : {
     275           0 :         const char **p;
     276             : 
     277           0 :         for (p = frr_defaults_profiles; *p; p++)
     278           0 :                 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, *p));
     279           0 : }
     280             : 
     281             : static const struct cmd_variable_handler default_var_handlers[] = {
     282             :         {.tokenname = "PROFILE", .completions = defaults_autocomplete},
     283             :         {.completions = NULL},
     284             : };
     285             : 
     286         218 : void lib_cmd_init(void)
     287             : {
     288         218 :         cmd_variable_handler_register(default_var_handlers);
     289             : 
     290         218 :         install_element(CONFIG_NODE, &frr_defaults_cmd);
     291         218 :         install_element(CONFIG_NODE, &frr_version_cmd);
     292             : 
     293         218 :         install_element(VIEW_NODE, &show_memory_cmd);
     294         218 :         install_element(VIEW_NODE, &show_modules_cmd);
     295             : 
     296         218 :         install_element(CONFIG_NODE, &start_config_cmd);
     297         218 :         install_element(CONFIG_NODE, &end_config_cmd);
     298         218 : }
     299             : 
     300             : /* Stats querying from users */
     301             : /* Return a pointer to a human friendly string describing
     302             :  * the byte count passed in. E.g:
     303             :  * "0 bytes", "2048 bytes", "110kB", "500MiB", "11GiB", etc.
     304             :  * Up to 4 significant figures will be given.
     305             :  * The pointer returned may be NULL (indicating an error)
     306             :  * or point to the given buffer, or point to static storage.
     307             :  */
     308           0 : const char *mtype_memstr(char *buf, size_t len, unsigned long bytes)
     309             : {
     310           0 :         unsigned int m, k;
     311             : 
     312             :         /* easy cases */
     313           0 :         if (!bytes)
     314             :                 return "0 bytes";
     315           0 :         if (bytes == 1)
     316             :                 return "1 byte";
     317             : 
     318             :         /*
     319             :          * When we pass the 2gb barrier mallinfo() can no longer report
     320             :          * correct data so it just does something odd...
     321             :          * Reporting like Terrabytes of data.  Which makes users...
     322             :          * edgy.. yes edgy that's the term for it.
     323             :          * So let's just give up gracefully
     324             :          */
     325           0 :         if (bytes > 0x7fffffff)
     326             :                 return "> 2GB";
     327             : 
     328           0 :         m = bytes >> 20;
     329           0 :         k = bytes >> 10;
     330             : 
     331           0 :         if (m > 10) {
     332           0 :                 if (bytes & (1 << 19))
     333           0 :                         m++;
     334           0 :                 snprintf(buf, len, "%d MiB", m);
     335           0 :         } else if (k > 10) {
     336           0 :                 if (bytes & (1 << 9))
     337           0 :                         k++;
     338           0 :                 snprintf(buf, len, "%d KiB", k);
     339             :         } else
     340           0 :                 snprintf(buf, len, "%ld bytes", bytes);
     341             : 
     342             :         return buf;
     343             : }

Generated by: LCOV version v1.16-topotato