back to topotato report
topotato coverage report
Current view: top level - zebra - main.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 89 148 60.1 %
Date: 2023-11-16 17:19:14 Functions: 4 12 33.3 %

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

Generated by: LCOV version v1.16-topotato