back to topotato report
topotato coverage report
Current view: top level - zebra - main.c (source / functions) Hit Total Coverage
Test: test_pim_crp.py::PIMCandidateBSRTest Lines: 88 142 62.0 %
Date: 2023-02-16 02:09:37 Functions: 4 6 66.7 %

          Line data    Source code
       1             : /* zebra daemon main routine.
       2             :  * Copyright (C) 1997, 98 Kunihiro Ishiguro
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include <lib/version.h>
      24             : #include "getopt.h"
      25             : #include "command.h"
      26             : #include "thread.h"
      27             : #include "filter.h"
      28             : #include "memory.h"
      29             : #include "prefix.h"
      30             : #include "log.h"
      31             : #include "plist.h"
      32             : #include "privs.h"
      33             : #include "sigevent.h"
      34             : #include "vrf.h"
      35             : #include "libfrr.h"
      36             : #include "routemap.h"
      37             : #include "routing_nb.h"
      38             : 
      39             : #include "zebra/zebra_router.h"
      40             : #include "zebra/zebra_errors.h"
      41             : #include "zebra/rib.h"
      42             : #include "zebra/zserv.h"
      43             : #include "zebra/debug.h"
      44             : #include "zebra/router-id.h"
      45             : #include "zebra/irdp.h"
      46             : #include "zebra/rtadv.h"
      47             : #include "zebra/zebra_ptm.h"
      48             : #include "zebra/zebra_ns.h"
      49             : #include "zebra/redistribute.h"
      50             : #include "zebra/zebra_mpls.h"
      51             : #include "zebra/label_manager.h"
      52             : #include "zebra/zebra_netns_notify.h"
      53             : #include "zebra/zebra_rnh.h"
      54             : #include "zebra/zebra_pbr.h"
      55             : #include "zebra/zebra_vxlan.h"
      56             : #include "zebra/zebra_routemap.h"
      57             : #include "zebra/zebra_nb.h"
      58             : #include "zebra/zebra_opaque.h"
      59             : #include "zebra/zebra_srte.h"
      60             : #include "zebra/zebra_srv6.h"
      61             : #include "zebra/zebra_srv6_vty.h"
      62             : 
      63             : #define ZEBRA_PTM_SUPPORT
      64             : 
      65             : /* process id. */
      66             : pid_t pid;
      67             : 
      68             : /* Pacify zclient.o in libfrr, which expects this variable. */
      69             : struct thread_master *master;
      70             : 
      71             : /* Route retain mode flag. */
      72             : int retain_mode = 0;
      73             : 
      74             : int graceful_restart;
      75             : 
      76             : bool v6_rr_semantics = false;
      77             : 
      78             : /* Receive buffer size for kernel control sockets */
      79             : #define RCVBUFSIZE_MIN 4194304
      80             : #ifdef HAVE_NETLINK
      81             : uint32_t rcvbufsize = RCVBUFSIZE_MIN;
      82             : #else
      83             : uint32_t rcvbufsize = 128 * 1024;
      84             : #endif
      85             : 
      86             : #define OPTION_V6_RR_SEMANTICS 2000
      87             : #define OPTION_ASIC_OFFLOAD    2001
      88             : 
      89             : /* Command line options. */
      90             : const struct option longopts[] = {
      91             :         {"batch", no_argument, NULL, 'b'},
      92             :         {"allow_delete", no_argument, NULL, 'a'},
      93             :         {"socket", required_argument, NULL, 'z'},
      94             :         {"ecmp", required_argument, NULL, 'e'},
      95             :         {"retain", no_argument, NULL, 'r'},
      96             :         {"graceful_restart", required_argument, NULL, 'K'},
      97             :         {"asic-offload", optional_argument, NULL, OPTION_ASIC_OFFLOAD},
      98             : #ifdef HAVE_NETLINK
      99             :         {"vrfwnetns", no_argument, NULL, 'n'},
     100             :         {"nl-bufsize", required_argument, NULL, 's'},
     101             :         {"v6-rr-semantics", no_argument, NULL, OPTION_V6_RR_SEMANTICS},
     102             : #endif /* HAVE_NETLINK */
     103             :         {0}};
     104             : 
     105             : zebra_capabilities_t _caps_p[] = {ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN,
     106             :                                   ZCAP_NET_RAW,
     107             : #ifdef HAVE_DPDK
     108             :                                   ZCAP_IPC_LOCK,  ZCAP_READ_SEARCH,
     109             :                                   ZCAP_SYS_RAWIO
     110             : #endif
     111             : };
     112             : 
     113             : /* zebra privileges to run with */
     114             : struct zebra_privs_t zserv_privs = {
     115             : #if defined(FRR_USER) && defined(FRR_GROUP)
     116             :         .user = FRR_USER,
     117             :         .group = FRR_GROUP,
     118             : #endif
     119             : #ifdef VTY_GROUP
     120             :         .vty_group = VTY_GROUP,
     121             : #endif
     122             :         .caps_p = _caps_p,
     123             :         .cap_num_p = array_size(_caps_p),
     124             :         .cap_num_i = 0};
     125             : 
     126             : /* SIGHUP handler. */
     127           0 : static void sighup(void)
     128             : {
     129           0 :         zlog_info("SIGHUP received");
     130             : 
     131             :         /* Reload of config file. */
     132           0 :         ;
     133           0 : }
     134             : 
     135             : /* SIGINT handler. */
     136           3 : static void sigint(void)
     137             : {
     138           3 :         struct vrf *vrf;
     139           3 :         struct zebra_vrf *zvrf;
     140           3 :         struct listnode *ln, *nn;
     141           3 :         struct zserv *client;
     142           3 :         static bool sigint_done;
     143             : 
     144           3 :         if (sigint_done)
     145             :                 return;
     146             : 
     147           3 :         sigint_done = true;
     148             : 
     149           3 :         zlog_notice("Terminating on signal");
     150             : 
     151           3 :         atomic_store_explicit(&zrouter.in_shutdown, true,
     152             :                               memory_order_relaxed);
     153             : 
     154             :         /* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
     155           3 :         rtadv_stop_ra_all();
     156             : 
     157           3 :         frr_early_fini();
     158             : 
     159             :         /* Stop the opaque module pthread */
     160           3 :         zebra_opaque_stop();
     161             : 
     162           3 :         zebra_dplane_pre_finish();
     163             : 
     164             :         /* Clean up GR related info. */
     165           3 :         zebra_gr_stale_client_cleanup(zrouter.stale_client_list);
     166           3 :         list_delete_all_node(zrouter.stale_client_list);
     167             : 
     168             :         /* Clean up zapi clients and server module */
     169          12 :         for (ALL_LIST_ELEMENTS(zrouter.client_list, ln, nn, client))
     170           6 :                 zserv_close_client(client);
     171             : 
     172           3 :         zserv_close();
     173           3 :         list_delete_all_node(zrouter.client_list);
     174             : 
     175             :         /* Once all the zclients are cleaned up, clean up the opaque module */
     176           3 :         zebra_opaque_finish();
     177             : 
     178           3 :         zebra_ptm_finish();
     179             : 
     180           3 :         if (retain_mode) {
     181           0 :                 zebra_nhg_mark_keep();
     182           0 :                 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
     183           0 :                         zvrf = vrf->info;
     184           0 :                         if (zvrf)
     185           0 :                                 SET_FLAG(zvrf->flags, ZEBRA_VRF_RETAIN);
     186             :                 }
     187             :         }
     188             : 
     189           3 :         if (zrouter.lsp_process_q)
     190           0 :                 work_queue_free_and_null(&zrouter.lsp_process_q);
     191             : 
     192           3 :         vrf_terminate();
     193             : 
     194           3 :         ns_walk_func(zebra_ns_early_shutdown, NULL, NULL);
     195           3 :         zebra_ns_notify_close();
     196             : 
     197           3 :         access_list_reset();
     198           3 :         prefix_list_reset();
     199             :         /*
     200             :          * zebra_routemap_finish will
     201             :          * 1 set rmap upd timer to 0 so that rmap update wont be scheduled again
     202             :          * 2 Put off the rmap update thread
     203             :          * 3 route_map_finish
     204             :          */
     205           3 :         zebra_routemap_finish();
     206             : 
     207           3 :         list_delete(&zrouter.client_list);
     208             : 
     209             :         /* Indicate that all new dplane work has been enqueued. When that
     210             :          * work is complete, the dataplane will enqueue an event
     211             :          * with the 'finalize' function.
     212             :          */
     213           3 :         zebra_dplane_finish();
     214             : }
     215             : 
     216             : /*
     217             :  * Final shutdown step for the zebra main thread. This is run after all
     218             :  * async update processing has completed.
     219             :  */
     220           3 : void zebra_finalize(struct thread *dummy)
     221             : {
     222           3 :         zlog_info("Zebra final shutdown");
     223             : 
     224             :         /* Stop dplane thread and finish any cleanup */
     225           3 :         zebra_dplane_shutdown();
     226             : 
     227             :         /* Final shutdown of ns resources */
     228           3 :         ns_walk_func(zebra_ns_final_shutdown, NULL, NULL);
     229             : 
     230           3 :         zebra_router_terminate();
     231             : 
     232           3 :         ns_terminate();
     233           3 :         frr_fini();
     234           3 :         exit(0);
     235             : }
     236             : 
     237             : /* SIGUSR1 handler. */
     238           0 : static void sigusr1(void)
     239             : {
     240           0 :         zlog_rotate();
     241           0 : }
     242             : 
     243             : struct frr_signal_t zebra_signals[] = {
     244             :         {
     245             :                 .signal = SIGHUP,
     246             :                 .handler = &sighup,
     247             :         },
     248             :         {
     249             :                 .signal = SIGUSR1,
     250             :                 .handler = &sigusr1,
     251             :         },
     252             :         {
     253             :                 .signal = SIGINT,
     254             :                 .handler = &sigint,
     255             :         },
     256             :         {
     257             :                 .signal = SIGTERM,
     258             :                 .handler = &sigint,
     259             :         },
     260             : };
     261             : 
     262             : static const struct frr_yang_module_info *const zebra_yang_modules[] = {
     263             :         &frr_filter_info,
     264             :         &frr_interface_info,
     265             :         &frr_route_map_info,
     266             :         &frr_zebra_info,
     267             :         &frr_vrf_info,
     268             :         &frr_routing_info,
     269             :         &frr_zebra_route_map_info,
     270             : };
     271             : 
     272           3 : FRR_DAEMON_INFO(
     273             :         zebra, ZEBRA, .vty_port = ZEBRA_VTY_PORT, .flags = FRR_NO_ZCLIENT,
     274             : 
     275             :         .proghelp =
     276             :                 "Daemon which manages kernel routing table management and\nredistribution between different routing protocols.",
     277             : 
     278             :         .signals = zebra_signals, .n_signals = array_size(zebra_signals),
     279             : 
     280             :         .privs = &zserv_privs,
     281             : 
     282             :         .yang_modules = zebra_yang_modules,
     283             :         .n_yang_modules = array_size(zebra_yang_modules),
     284             : );
     285             : 
     286             : /* Main startup routine. */
     287           3 : int main(int argc, char **argv)
     288             : {
     289             :         // int batch_mode = 0;
     290           3 :         char *zserv_path = NULL;
     291           3 :         struct sockaddr_storage dummy;
     292           3 :         socklen_t dummylen;
     293           3 :         bool asic_offload = false;
     294           3 :         bool notify_on_ack = true;
     295             : 
     296           3 :         graceful_restart = 0;
     297           3 :         vrf_configure_backend(VRF_BACKEND_VRF_LITE);
     298             : 
     299           3 :         frr_preinit(&zebra_di, argc, argv);
     300             : 
     301           3 :         frr_opt_add(
     302             :                 "baz:e:rK:s:"
     303             : #ifdef HAVE_NETLINK
     304             :                 "n"
     305             : #endif
     306             :                 ,
     307             :                 longopts,
     308             :                 "  -b, --batch              Runs in batch mode\n"
     309             :                 "  -a, --allow_delete       Allow other processes to delete zebra routes\n"
     310             :                 "  -z, --socket             Set path of zebra socket\n"
     311             :                 "  -e, --ecmp               Specify ECMP to use.\n"
     312             :                 "  -r, --retain             When program terminates, retain added route by zebra.\n"
     313             :                 "  -K, --graceful_restart   Graceful restart at the kernel level, timer in seconds for expiration\n"
     314             :                 "  -A, --asic-offload       FRR is interacting with an asic underneath the linux kernel\n"
     315             : #ifdef HAVE_NETLINK
     316             :                 "  -s, --nl-bufsize         Set netlink receive buffer size\n"
     317             :                 "  -n, --vrfwnetns          Use NetNS as VRF backend\n"
     318             :                 "      --v6-rr-semantics    Use v6 RR semantics\n"
     319             : #else
     320             :                 "  -s,                      Set kernel socket receive buffer size\n"
     321             : #endif /* HAVE_NETLINK */
     322             :         );
     323             : 
     324           3 :         while (1) {
     325           3 :                 int opt = frr_getopt(argc, argv, NULL);
     326             : 
     327           3 :                 if (opt == EOF)
     328             :                         break;
     329             : 
     330           0 :                 switch (opt) {
     331             :                 case 0:
     332             :                         break;
     333             :                 case 'b':
     334             :                         // batch_mode = 1;
     335             :                         break;
     336           0 :                 case 'a':
     337           0 :                         zrouter.allow_delete = true;
     338           0 :                         break;
     339           0 :                 case 'e': {
     340           0 :                         unsigned long int parsed_multipath =
     341           0 :                                 strtoul(optarg, NULL, 10);
     342           0 :                         if (parsed_multipath == 0
     343             :                             || parsed_multipath > MULTIPATH_NUM
     344           0 :                             || parsed_multipath > UINT32_MAX) {
     345           0 :                                 flog_err(
     346             :                                         EC_ZEBRA_BAD_MULTIPATH_NUM,
     347             :                                         "Multipath Number specified must be less than %u and greater than 0",
     348             :                                         MULTIPATH_NUM);
     349           0 :                                 return 1;
     350             :                         }
     351           0 :                         zrouter.multipath_num = parsed_multipath;
     352           0 :                         break;
     353             :                 }
     354           0 :                 case 'z':
     355           0 :                         zserv_path = optarg;
     356           0 :                         if (!frr_zclient_addr(&dummy, &dummylen, optarg)) {
     357           0 :                                 fprintf(stderr,
     358             :                                         "Invalid zserv socket path: %s\n",
     359             :                                         optarg);
     360           0 :                                 exit(1);
     361             :                         }
     362             :                         break;
     363           0 :                 case 'r':
     364           0 :                         retain_mode = 1;
     365           0 :                         break;
     366           0 :                 case 'K':
     367           0 :                         graceful_restart = atoi(optarg);
     368           0 :                         break;
     369           0 :                 case 's':
     370           0 :                         rcvbufsize = atoi(optarg);
     371           0 :                         if (rcvbufsize < RCVBUFSIZE_MIN)
     372           0 :                                 fprintf(stderr,
     373             :                                         "Rcvbufsize is smaller than recommended value: %d\n",
     374             :                                         RCVBUFSIZE_MIN);
     375             :                         break;
     376             : #ifdef HAVE_NETLINK
     377           0 :                 case 'n':
     378           0 :                         vrf_configure_backend(VRF_BACKEND_NETNS);
     379           0 :                         break;
     380           0 :                 case OPTION_V6_RR_SEMANTICS:
     381           0 :                         v6_rr_semantics = true;
     382           0 :                         break;
     383           0 :                 case OPTION_ASIC_OFFLOAD:
     384           0 :                         if (!strcmp(optarg, "notify_on_offload"))
     385           0 :                                 notify_on_ack = false;
     386           0 :                         if (!strcmp(optarg, "notify_on_ack"))
     387           0 :                                 notify_on_ack = true;
     388             :                         asic_offload = true;
     389             :                         break;
     390             : #endif /* HAVE_NETLINK */
     391           0 :                 default:
     392           0 :                         frr_help_exit(1);
     393             :                 }
     394             :         }
     395             : 
     396           3 :         zrouter.master = frr_init();
     397             : 
     398             :         /* Zebra related initialize. */
     399           3 :         zebra_router_init(asic_offload, notify_on_ack);
     400           3 :         zserv_init();
     401           3 :         rib_init();
     402           3 :         zebra_if_init();
     403           3 :         zebra_debug_init();
     404             : 
     405             :         /*
     406             :          * Initialize NS( and implicitly the VRF module), and make kernel
     407             :          * routing socket. */
     408           3 :         zebra_ns_init();
     409           3 :         router_id_cmd_init();
     410           3 :         zebra_vty_init();
     411           3 :         access_list_init();
     412           3 :         prefix_list_init();
     413           3 :         rtadv_cmd_init();
     414             : /* PTM socket */
     415             : #ifdef ZEBRA_PTM_SUPPORT
     416           3 :         zebra_ptm_init();
     417             : #endif
     418             : 
     419           3 :         zebra_mpls_init();
     420           3 :         zebra_mpls_vty_init();
     421           3 :         zebra_pw_vty_init();
     422           3 :         zebra_pbr_init();
     423           3 :         zebra_opaque_init();
     424           3 :         zebra_srte_init();
     425           3 :         zebra_srv6_init();
     426           3 :         zebra_srv6_vty_init();
     427             : 
     428             :         /* For debug purpose. */
     429             :         /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */
     430             : 
     431             :         /* Process the configuration file. Among other configuration
     432             :         *  directives we can meet those installing static routes. Such
     433             :         *  requests will not be executed immediately, but queued in
     434             :         *  zebra->ribq structure until we enter the main execution loop.
     435             :         *  The notifications from kernel will show originating PID equal
     436             :         *  to that after daemon() completes (if ever called).
     437             :         */
     438           3 :         frr_config_fork();
     439             : 
     440             :         /* After we have successfully acquired the pidfile, we can be sure
     441             :         *  about being the only copy of zebra process, which is submitting
     442             :         *  changes to the FIB.
     443             :         *  Clean up zebra-originated routes. The requests will be sent to OS
     444             :         *  immediately, so originating PID in notifications from kernel
     445             :         *  will be equal to the current getpid(). To know about such routes,
     446             :         * we have to have route_read() called before.
     447             :         */
     448           3 :         zrouter.startup_time = monotime(NULL);
     449           3 :         thread_add_timer(zrouter.master, rib_sweep_route, NULL,
     450             :                          graceful_restart, &zrouter.sweeper);
     451             : 
     452             :         /* Needed for BSD routing socket. */
     453           3 :         pid = getpid();
     454             : 
     455             :         /* Start dataplane system */
     456           3 :         zebra_dplane_start();
     457             : 
     458             :         /* Start the ted module, before zserv */
     459           3 :         zebra_opaque_start();
     460             : 
     461             :         /* Start Zebra API server */
     462           3 :         zserv_start(zserv_path);
     463             : 
     464             :         /* Init label manager */
     465           3 :         label_manager_init();
     466             : 
     467             :         /* RNH init */
     468           3 :         zebra_rnh_init();
     469             : 
     470             :         /* Config handler Init */
     471           3 :         zebra_evpn_init();
     472             : 
     473             :         /* Error init */
     474           3 :         zebra_error_init();
     475             : 
     476           3 :         frr_run(zrouter.master);
     477             : 
     478             :         /* Not reached... */
     479           3 :         return 0;
     480             : }

Generated by: LCOV version v1.16-topotato