diff --git a/board/common/rootfs/etc/finit.d/available/netd.conf b/board/common/rootfs/etc/finit.d/available/netd.conf index e61019c7..34d7e6e6 100644 --- a/board/common/rootfs/etc/finit.d/available/netd.conf +++ b/board/common/rootfs/etc/finit.d/available/netd.conf @@ -1,3 +1,2 @@ #set DEBUG=1 - -service name:netd log [S12345] netd -- Network route daemon +service [2345] name:netd netd -- Network route daemon diff --git a/board/common/rootfs/etc/frr/daemons b/board/common/rootfs/etc/frr/daemons new file mode 100644 index 00000000..2094cd75 --- /dev/null +++ b/board/common/rootfs/etc/frr/daemons @@ -0,0 +1,28 @@ +# Default FRR daemons file for Infix - confd overwrites on routing changes. +# watchfrr, zebra, mgmtd, and staticd are always started by frrinit.sh. +ospfd=no +ripd=no +bfdd=no +bgpd=no +ospf6d=no +ripngd=no +isisd=no +pimd=no +pim6d=no +ldpd=no +eigrpd=no +babeld=no +vrrpd=no +pathd=no + +vtysh_enable=yes +watchfrr_options="-l 4" +zebra_options=" -A 127.0.0.1 -s 90000000" +mgmtd_options=" -A 127.0.0.1" +ospfd_options=" -A 127.0.0.1" +ripd_options=" -A 127.0.0.1" +staticd_options="-A 127.0.0.1" +bfdd_options=" -A 127.0.0.1" + +frr_profile="traditional" + diff --git a/board/common/rootfs/etc/frr/frr.conf b/board/common/rootfs/etc/frr/frr.conf new file mode 100644 index 00000000..89d46717 --- /dev/null +++ b/board/common/rootfs/etc/frr/frr.conf @@ -0,0 +1,2 @@ +# Replaces default frr.conf file +log syslog warnings diff --git a/board/common/rootfs/etc/frr/static.d/.empty b/board/common/rootfs/etc/frr/static.d/.empty deleted file mode 100644 index e69de29b..00000000 diff --git a/board/common/rootfs/etc/frr/static.d/00default.conf b/board/common/rootfs/etc/frr/static.d/00default.conf deleted file mode 100644 index c23631f5..00000000 --- a/board/common/rootfs/etc/frr/static.d/00default.conf +++ /dev/null @@ -1,9 +0,0 @@ -! Default settings for staticd, used for both -! confd generated routes, udhcpc and zeroconf -frr defaults traditional -hostname Router -password zebra -enable password zebra -no log unique-id -log syslog informational -log facility local2 diff --git a/package/netd/Config.in b/package/netd/Config.in index a1af11fe..97e7ddaa 100644 --- a/package/netd/Config.in +++ b/package/netd/Config.in @@ -13,10 +13,21 @@ config BR2_PACKAGE_NETD if BR2_PACKAGE_NETD -config BR2_PACKAGE_NETD_FRR - bool "FRR integration" +config BR2_PACKAGE_NETD_FRR_CONF + bool "FRR frr.conf backend" default y if BR2_PACKAGE_FRR depends on BR2_PACKAGE_FRR + help + Enable FRR integration via frr.conf file generation. + netd assembles a single /etc/frr/frr.conf from routing + config and signals FRR to reload via frrinit.sh. + + Provides full routing support (static routes, RIP, OSPF). + +config BR2_PACKAGE_NETD_FRR + bool "FRR gRPC backend" + depends on BR2_PACKAGE_FRR + depends on !BR2_PACKAGE_NETD_FRR_CONF select BR2_PACKAGE_PROTOBUF select BR2_PACKAGE_GRPC select BR2_PACKAGE_HOST_PROTOBUF diff --git a/package/netd/netd.conf b/package/netd/netd.conf index 377c96a5..fb2f6499 100644 --- a/package/netd/netd.conf +++ b/package/netd/netd.conf @@ -1,3 +1,3 @@ #set DEBUG=1 - -service name:netd log [S12345] netd -p /run/netd.pid -- Network route daemon +service name:netd log \ + [2345] netd -p /run/netd.pid -- Network route daemon diff --git a/package/netd/netd.mk b/package/netd/netd.mk index 3f7f76ef..a4d3ce0c 100644 --- a/package/netd/netd.mk +++ b/package/netd/netd.mk @@ -17,12 +17,16 @@ NETD_CONF_ENV = CFLAGS="$(INFIX_CFLAGS)" NETD_CONF_OPTS = --prefix= --disable-silent-rules -# FRR integration (gRPC backend) or standalone Linux backend -ifeq ($(BR2_PACKAGE_NETD_FRR),y) +# Backend selection: FRR frr.conf, FRR gRPC, or Linux kernel +ifeq ($(BR2_PACKAGE_NETD_FRR_CONF),y) +NETD_DEPENDENCIES += frr +NETD_CONF_OPTS += --with-frr-conf +else ifeq ($(BR2_PACKAGE_NETD_FRR),y) NETD_DEPENDENCIES += frr grpc host-grpc protobuf NETD_CONF_ENV += \ PROTOC="$(HOST_DIR)/bin/protoc" \ GRPC_CPP_PLUGIN="$(HOST_DIR)/bin/grpc_cpp_plugin" +NETD_CONF_OPTS += --with-frr else NETD_CONF_OPTS += --without-frr endif diff --git a/package/skeleton-init-finit/skeleton-init-finit.mk b/package/skeleton-init-finit/skeleton-init-finit.mk index 7e9e5558..3bb72c91 100644 --- a/package/skeleton-init-finit/skeleton-init-finit.mk +++ b/package/skeleton-init-finit/skeleton-init-finit.mk @@ -85,6 +85,12 @@ SKELETON_INIT_FINIT_POST_INSTALL_TARGET_HOOKS += SKELETON_INIT_FINIT_SET_DROPBEA endif ifeq ($(BR2_PACKAGE_FRR),y) +ifeq ($(BR2_PACKAGE_NETD_FRR_CONF),y) +define SKELETON_INIT_FINIT_SET_FRR + cp $(SKELETON_INIT_FINIT_AVAILABLE)/frr/frr.conf $(FINIT_D)/available/frr.conf + ln -sf ../available/frr.conf $(FINIT_D)/enabled/frr.conf +endef +else define SKELETON_INIT_FINIT_SET_FRR for svc in babeld bfdd bgpd mgmtd eigrpd isisd ldpd ospfd ospf6d pathd ripd ripng staticd vrrpd zebra; do \ cp $(SKELETON_INIT_FINIT_AVAILABLE)/frr/$$svc.conf $(FINIT_D)/available/$$svc.conf; \ @@ -93,6 +99,7 @@ define SKELETON_INIT_FINIT_SET_FRR ln -sf ../available/staticd.conf $(FINIT_D)/enabled/staticd.conf ln -sf ../available/mgmtd.conf $(FINIT_D)/enabled/mgmtd.conf endef +endif SKELETON_INIT_FINIT_POST_INSTALL_TARGET_HOOKS += SKELETON_INIT_FINIT_SET_FRR endif # BR2_PACKAGE_FRR diff --git a/package/skeleton-init-finit/skeleton/etc/finit.d/available/frr/frr.conf b/package/skeleton-init-finit/skeleton/etc/finit.d/available/frr/frr.conf new file mode 100644 index 00000000..0e2cedb1 --- /dev/null +++ b/package/skeleton-init-finit/skeleton/etc/finit.d/available/frr/frr.conf @@ -0,0 +1,3 @@ +sysv name:watchfrr pid:!/run/frr/watchfrr.pid \ + reload:'frrinit.sh reload' log:null \ + [2345] frrinit.sh -- FRR routing suite diff --git a/src/confd/src/routing.c b/src/confd/src/routing.c index 3a881b67..6906b5bf 100644 --- a/src/confd/src/routing.c +++ b/src/confd/src/routing.c @@ -18,6 +18,7 @@ #define RIPD_SIGNAL_NEXT RIPD_SIGNAL "+" #define BFDD_SIGNAL "/run/bfd_enabled" /* Just signal that bfd should be enabled*/ #define BFDD_SIGNAL_NEXT BFDD_SIGNAL "+" +#define FRR_DAEMONS "/etc/frr/daemons" #define FRR_STATIC_CONFIG "! Generated by Infix confd\n\ frr defaults traditional\n\ @@ -302,8 +303,10 @@ int parse_ospf(sr_session_ctx_t *session, struct lyd_node *ospf) any_debug = 1; } - if (any_debug) + if (any_debug) { + fputs("log syslog debugging\n", fp); fputs("!\n", fp); + } } areas = lydx_get_child(ospf, "areas"); @@ -337,6 +340,7 @@ int parse_ospf(sr_session_ctx_t *session, struct lyd_node *ospf) (void)touch(BFDD_SIGNAL_NEXT); else (void)remove(BFDD_SIGNAL_NEXT); + return 0; } @@ -401,11 +405,66 @@ static int parse_static_routes(sr_session_ctx_t *session, struct lyd_node *paren return num_routes; } +/* + * Generate the complete /etc/frr/daemons file. Written atomically as a + * single unit so the file is always consistent and easy to read. + */ +static void frr_daemons_write(int ospfd, int ripd, int bfdd) +{ + const char *next = FRR_DAEMONS "+"; + FILE *fp; + + fp = fopen(next, "w"); + if (!fp) { + ERROR("Failed to open %s", next); + return; + } + + /* Daemon selection - watchfrr, zebra, mgmtd, and staticd are + * always started by frrinit.sh regardless of these settings. */ + fprintf(fp, + "# Generated by Infix confd\n" + "ospfd=%s\n" + "ripd=%s\n" + "bfdd=%s\n" + "bgpd=no\n" + "ospf6d=no\n" + "ripngd=no\n" + "isisd=no\n" + "pimd=no\n" + "pim6d=no\n" + "ldpd=no\n" + "eigrpd=no\n" + "babeld=no\n" + "vrrpd=no\n" + "pathd=no\n" + "\n", + ospfd ? "yes" : "no", + ripd ? "yes" : "no", + bfdd ? "yes" : "no"); + + /* Global settings and per-daemon options */ + fputs( + "vtysh_enable=yes\n" + "watchfrr_options=\"-l 4\"\n" + "zebra_options=\" -A 127.0.0.1 -s 90000000\"\n" + "mgmtd_options=\" -A 127.0.0.1\"\n" + "ospfd_options=\" -A 127.0.0.1\"\n" + "ripd_options=\" -A 127.0.0.1\"\n" + "staticd_options=\"-A 127.0.0.1\"\n" + "bfdd_options=\" -A 127.0.0.1\"\n" + "\n" + "frr_profile=\"traditional\"\n", + fp); + + fclose(fp); + rename(next, FRR_DAEMONS); +} + int routing_change(sr_session_ctx_t *session, struct lyd_node *config, struct lyd_node *diff, sr_event_t event, struct confd *confd) { int netd_enabled = 0, ospfd_enabled = 0, bfdd_enabled = 0, ripd_enabled = 0; struct lyd_node *cplane, *cplanes; - bool restart_zebra = false; int rc = SR_ERR_OK; FILE *fp; @@ -413,10 +472,12 @@ int routing_change(sr_session_ctx_t *session, struct lyd_node *config, struct ly return SR_ERR_OK; switch (event) { - case SR_EV_ENABLED: /* first time, on register. */ case SR_EV_CHANGE: /* regular change (copy cand running) */ break; + case SR_EV_ENABLED: /* first time, on register - no SR_EV_DONE follows */ + break; + case SR_EV_ABORT: /* User abort, or other plugin failed */ (void)remove(NETD_CONF_NEXT); return SR_ERR_OK; @@ -427,69 +488,8 @@ int routing_change(sr_session_ctx_t *session, struct lyd_node *config, struct ly ospfd_enabled = fexist(OSPFD_CONF_NEXT); bfdd_enabled = fexist(BFDD_SIGNAL_NEXT); ripd_enabled = fexist(RIPD_SIGNAL_NEXT); + goto activate; - - if (bfdd_enabled) { - (void)rename(BFDD_SIGNAL_NEXT, BFDD_SIGNAL); - systemf("initctl -bfq enable bfdd"); - systemf("initctl -bfq touch bfdd"); - - restart_zebra = true; - } else { - (void)remove(BFDD_SIGNAL); - systemf("initctl -bfq disable bfdd"); - } - if (ospfd_enabled) { - (void)remove(OSPFD_CONF_PREV); - (void)rename(OSPFD_CONF, OSPFD_CONF_PREV); - (void)rename(OSPFD_CONF_NEXT, OSPFD_CONF); - systemf("initctl enable ospfd"); - systemf("initctl touch ospfd"); - - restart_zebra = true; - } else { - systemf("initctl -bfq disable ospfd"); - (void)remove(OSPFD_CONF); - } - - /* Start/stop ripd daemon based on whether RIP config is present */ - if (ripd_enabled) { - systemf("initctl enable ripd"); - systemf("initctl touch ripd"); - restart_zebra = true; - } else { - (void)remove(RIPD_SIGNAL); - systemf("initctl -bfq disable ripd"); - } - - /* netd handles both static routes and RIP */ - if (netd_enabled) { - restart_zebra = true; - (void)remove(NETD_CONF_PREV); - (void)rename(NETD_CONF, NETD_CONF_PREV); - (void)rename(NETD_CONF_NEXT, NETD_CONF); - if (systemf("initctl -bfq touch netd")) - ERROR("Failed to signal netd for reload"); - } else { - if (!remove(NETD_CONF)) { - if (systemf("initctl -bfq touch netd")) - ERROR("Failed to signal netd for reload"); - } - } - - if (restart_zebra) { - /* skip in runlevel S, no routing daemons run here anyway */ - if (systemf("runlevel >/dev/null 2>&1")) - return SR_ERR_OK; - - if (systemf("initctl -bfq touch zebra")) { - ERROR("Failed to restart zebra routing daemon"); - rc = SR_ERR_INTERNAL; - goto err_abandon; - } - } - - return SR_ERR_OK; default: return SR_ERR_OK; } @@ -529,6 +529,52 @@ int routing_change(sr_session_ctx_t *session, struct lyd_node *config, struct ly if (!netd_enabled) (void)remove(NETD_CONF_NEXT); -err_abandon: + if (event == SR_EV_CHANGE) + return rc; + + /* For SR_EV_ENABLED we activate immediately (no SR_EV_DONE follows) */ + netd_enabled = fexist(NETD_CONF_NEXT); + ospfd_enabled = fexist(OSPFD_CONF_NEXT); + bfdd_enabled = fexist(BFDD_SIGNAL_NEXT); + ripd_enabled = fexist(RIPD_SIGNAL_NEXT); + +activate: + /* Generate complete /etc/frr/daemons */ + frr_daemons_write(ospfd_enabled, ripd_enabled, bfdd_enabled); + + if (bfdd_enabled) + (void)rename(BFDD_SIGNAL_NEXT, BFDD_SIGNAL); + else + (void)remove(BFDD_SIGNAL); + + if (ospfd_enabled) { + (void)remove(OSPFD_CONF_PREV); + (void)rename(OSPFD_CONF, OSPFD_CONF_PREV); + (void)rename(OSPFD_CONF_NEXT, OSPFD_CONF); + } else { + (void)remove(OSPFD_CONF); + } + + if (ripd_enabled) + (void)rename(RIPD_SIGNAL_NEXT, RIPD_SIGNAL); + else + (void)remove(RIPD_SIGNAL); + + /* netd handles both static routes and RIP, assembles frr.conf */ + if (netd_enabled) { + (void)remove(NETD_CONF_PREV); + (void)rename(NETD_CONF, NETD_CONF_PREV); + (void)rename(NETD_CONF_NEXT, NETD_CONF); + } else { + (void)remove(NETD_CONF); + } + + /* + * Signal netd to reload - it assembles /etc/frr/frr.conf and + * Finit propagates the restart to the frr sysv service + */ + if (systemf("initctl -bfq touch netd")) + ERROR("Failed to signal netd for reload"); + return rc; } diff --git a/src/netd/Makefile.am b/src/netd/Makefile.am index 0c600979..03be8ab7 100644 --- a/src/netd/Makefile.am +++ b/src/netd/Makefile.am @@ -8,7 +8,7 @@ netd_CFLAGS = -W -Wall -Wextra netd_CFLAGS += $(libite_CFLAGS) $(libconfuse_CFLAGS) $(jansson_CFLAGS) netd_LDADD = $(libite_LIBS) $(libconfuse_LIBS) $(jansson_LIBS) -# Backend selection: FRR gRPC or Linux kernel +# Backend selection: FRR gRPC, FRR frr.conf, or Linux kernel if HAVE_FRR_GRPC BUILT_SOURCES = grpc/frr-northbound.pb.cc grpc/frr-northbound.pb.h \ grpc/frr-northbound.grpc.pb.cc grpc/frr-northbound.grpc.pb.h @@ -29,6 +29,11 @@ netd_LDADD += $(grpc_LIBS) $(protobuf_LIBS) -lstdc++ CLEANFILES = grpc/*.pb.cc grpc/*.pb.h else +if HAVE_FRR_CONF +# FRR frr.conf file backend +netd_SOURCES += src/frrconf_backend.c src/frrconf_backend.h +else # Linux kernel backend (no FRR) netd_SOURCES += src/linux_backend.c src/linux_backend.h endif +endif diff --git a/src/netd/configure.ac b/src/netd/configure.ac index 34e2f825..281d01d1 100644 --- a/src/netd/configure.ac +++ b/src/netd/configure.ac @@ -12,23 +12,33 @@ AC_PROG_CXX AC_PROG_INSTALL # -# FRR gRPC northbound API (optional, enabled by default) +# FRR backend selection # AC_ARG_WITH(frr, - AS_HELP_STRING([--without-frr], [Build without FRR integration (use Linux kernel backend)]), + AS_HELP_STRING([--with-frr], [Build with FRR gRPC backend]), [with_frr=$withval], - [with_frr=yes]) + [with_frr=no]) + +AC_ARG_WITH(frr-conf, + AS_HELP_STRING([--with-frr-conf], [Build with FRR frr.conf file backend (default when FRR available)]), + [with_frr_conf=$withval], + [with_frr_conf=no]) + +# Mutual exclusion check +AS_IF([test "x$with_frr" = "xyes" -a "x$with_frr_conf" = "xyes"], [ + AC_MSG_ERROR([--with-frr and --with-frr-conf are mutually exclusive]) +]) AS_IF([test "x$with_frr" = "xyes"], [ # Check for protoc and grpc_cpp_plugin AC_PATH_PROG([PROTOC], [protoc], [no]) AS_IF([test "x$PROTOC" = "xno"], [ - AC_MSG_ERROR([protoc not found, required for FRR support (use --without-frr to disable)]) + AC_MSG_ERROR([protoc not found, required for FRR gRPC support]) ]) AC_PATH_PROG([GRPC_CPP_PLUGIN], [grpc_cpp_plugin], [no]) AS_IF([test "x$GRPC_CPP_PLUGIN" = "xno"], [ - AC_MSG_ERROR([grpc_cpp_plugin not found, required for FRR support (use --without-frr to disable)]) + AC_MSG_ERROR([grpc_cpp_plugin not found, required for FRR gRPC support]) ]) # Check for grpc++ and protobuf libraries @@ -41,7 +51,12 @@ AS_IF([test "x$with_frr" = "xyes"], [ AC_SUBST(GRPC_CPP_PLUGIN) ]) +AS_IF([test "x$with_frr_conf" = "xyes"], [ + AC_DEFINE(HAVE_FRR_CONF, 1, [Built with FRR frr.conf file backend]) +]) + AM_CONDITIONAL(HAVE_FRR_GRPC, [test "x$with_frr" = "xyes"]) +AM_CONDITIONAL(HAVE_FRR_CONF, [test "x$with_frr_conf" = "xyes"]) # Check for pkg-config first PKG_PROG_PKG_CONFIG @@ -74,8 +89,7 @@ cat < +#include +#include + +#include "netd.h" +#include "frrconf_backend.h" + +#define FRR_CONF "/etc/frr/frr.conf" +#define FRR_CONF_NEXT FRR_CONF "+" +#define OSPFD_CONF "/etc/frr/ospfd.conf" + +static const char *frr_header = + "! Generated by netd\n" + "frr defaults traditional\n" + "hostname Router\n" + "password zebra\n" + "enable password zebra\n" + "no log unique-id\n" + "log syslog warnings\n" + "log facility local2\n" + "!\n"; + +int frrconf_backend_init(void) +{ + INFO("Using FRR frr.conf backend"); + return 0; +} + +void frrconf_backend_cleanup(void) +{ + /* Nothing to clean up */ +} + +static void write_static_routes(FILE *fp, struct route_head *routes) +{ + char prefix_str[INET6_ADDRSTRLEN]; + char gw_str[INET6_ADDRSTRLEN]; + struct route *r; + int count = 0; + + TAILQ_FOREACH(r, routes, entries) { + const char *cmd; + + if (r->family == AF_INET) { + cmd = "ip"; + inet_ntop(AF_INET, &r->prefix.ip4, prefix_str, sizeof(prefix_str)); + } else { + cmd = "ipv6"; + inet_ntop(AF_INET6, &r->prefix.ip6, prefix_str, sizeof(prefix_str)); + } + + fprintf(fp, "%s route %s/%u ", cmd, prefix_str, r->prefixlen); + + switch (r->nh_type) { + case NH_ADDR: + if (r->family == AF_INET) + inet_ntop(AF_INET, &r->gateway.gw4, gw_str, sizeof(gw_str)); + else + inet_ntop(AF_INET6, &r->gateway.gw6, gw_str, sizeof(gw_str)); + fputs(gw_str, fp); + break; + case NH_IFNAME: + fputs(r->ifname, fp); + break; + case NH_BLACKHOLE: + switch (r->bh_type) { + case BH_NULL: + fputs("Null0", fp); + break; + case BH_REJECT: + fputs("reject", fp); + break; + case BH_DROP: + fputs("blackhole", fp); + break; + } + break; + } + + if (r->distance) + fprintf(fp, " %u", r->distance); + + fputc('\n', fp); + count++; + } + + if (count) + fputs("!\n", fp); + + DEBUG("frrconf: wrote %d static routes", count); +} + +static const char *redist_name(enum rip_redist_type type) +{ + switch (type) { + case RIP_REDIST_CONNECTED: return "connected"; + case RIP_REDIST_STATIC: return "static"; + case RIP_REDIST_KERNEL: return "kernel"; + case RIP_REDIST_OSPF: return "ospf"; + } + return "unknown"; +} + +static void write_rip_config(FILE *fp, struct rip_config *rip) +{ + struct rip_redistribute *redist; + struct rip_neighbor *nbr; + struct rip_network *net; + + if (!rip->enabled) + return; + + fputs("router rip\n", fp); + fprintf(fp, " default-metric %u\n", rip->default_metric); + fprintf(fp, " distance %u\n", rip->distance); + fprintf(fp, " timers basic %u %u %u\n", + rip->timers.update, rip->timers.invalid, rip->timers.flush); + + if (rip->default_route) + fputs(" default-information originate\n", fp); + + TAILQ_FOREACH(net, &rip->networks, entries) { + fprintf(fp, " network %s\n", net->ifname); + if (net->passive) + fprintf(fp, " passive-interface %s\n", net->ifname); + } + + TAILQ_FOREACH(nbr, &rip->neighbors, entries) { + char addr[INET_ADDRSTRLEN]; + + inet_ntop(AF_INET, &nbr->addr, addr, sizeof(addr)); + fprintf(fp, " neighbor %s\n", addr); + } + + TAILQ_FOREACH(redist, &rip->redistributes, entries) + fprintf(fp, " redistribute %s\n", redist_name(redist->type)); + + fputs("!\n", fp); + DEBUG("frrconf: wrote RIP configuration"); +} + +static void append_file(FILE *fp, const char *path) +{ + char buf[1024]; + FILE *src; + size_t n; + + src = fopen(path, "r"); + if (!src) + return; + + while ((n = fread(buf, 1, sizeof(buf), src)) > 0) + fwrite(buf, 1, n, fp); + + fclose(src); + DEBUG("frrconf: appended %s", path); +} + +int frrconf_backend_apply(struct route_head *routes, struct rip_config *rip) +{ + FILE *fp; + + fp = fopen(FRR_CONF_NEXT, "w"); + if (!fp) { + ERROR("frrconf: failed to open %s: %s", FRR_CONF_NEXT, strerror(errno)); + return -1; + } + + fputs(frr_header, fp); + write_static_routes(fp, routes); + write_rip_config(fp, rip); + append_file(fp, OSPFD_CONF); + + fclose(fp); + + if (rename(FRR_CONF_NEXT, FRR_CONF)) { + ERROR("frrconf: failed to rename %s to %s: %s", + FRR_CONF_NEXT, FRR_CONF, strerror(errno)); + return -1; + } + + INFO("frrconf: updated %s", FRR_CONF); + return 0; +} diff --git a/src/netd/src/frrconf_backend.h b/src/netd/src/frrconf_backend.h new file mode 100644 index 00000000..bf7b0ba6 --- /dev/null +++ b/src/netd/src/frrconf_backend.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#ifndef NETD_FRRCONF_BACKEND_H_ +#define NETD_FRRCONF_BACKEND_H_ + +#include "netd.h" + +int frrconf_backend_init(void); +void frrconf_backend_cleanup(void); +int frrconf_backend_apply(struct route_head *routes, struct rip_config *rip); + +#endif /* NETD_FRRCONF_BACKEND_H_ */ diff --git a/src/netd/src/netd.c b/src/netd/src/netd.c index cab86372..0793d34f 100644 --- a/src/netd/src/netd.c +++ b/src/netd/src/netd.c @@ -15,6 +15,13 @@ static void backend_cleanup(void) { grpc_backend_cleanup(); } static int backend_apply(struct route_head *routes, struct rip_config *rip) { return grpc_backend_apply(routes, rip); } +#elif defined(HAVE_FRR_CONF) +#include "frrconf_backend.h" +static int backend_init(void) { return frrconf_backend_init(); } +static void backend_cleanup(void) { frrconf_backend_cleanup(); } +static int backend_apply(struct route_head *routes, struct rip_config *rip) { + return frrconf_backend_apply(routes, rip); +} #else #include "linux_backend.h" static int backend_init(void) { return linux_backend_init(); } @@ -35,6 +42,8 @@ static struct rip_config active_rip; static void sighup_handler(int sig) { (void)sig; + + INFO("Got SIGHUP, reloading ..."); do_reload = 1; } @@ -197,8 +206,9 @@ static void reload(void) ERROR("Failed to launch system command: %s", cmd->command); } } - pidfile(NULL); + INFO("Configuration reloaded"); + pidfile(NULL); } static int usage(int rc) @@ -213,7 +223,7 @@ static int usage(int rc) int main(int argc, char *argv[]) { int log_opts = LOG_PID | LOG_NDELAY; - struct sigaction sa; + struct sigaction sa = { 0 }; int c; while ((c = getopt(argc, argv, "dhp:")) != -1) { @@ -230,10 +240,10 @@ int main(int argc, char *argv[]) } openlog("netd", log_opts, LOG_DAEMON); - INFO("netd starting"); + setlogmask(LOG_UPTO(LOG_INFO)); + INFO("starting"); /* Set up signal handlers */ - memset(&sa, 0, sizeof(sa)); sa.sa_handler = sighup_handler; sigaction(SIGHUP, &sa, NULL); @@ -253,7 +263,6 @@ int main(int argc, char *argv[]) /* Initial load */ do_reload = 1; - pidfile(NULL); while (!do_shutdown) { if (do_reload) { do_reload = 0; @@ -262,7 +271,7 @@ int main(int argc, char *argv[]) pause(); } - INFO("netd shutting down"); + INFO("shutting down"); route_list_free(&active_routes); rip_config_free(&active_rip);