From 32f3268f51479989ec29790f7ba9ec03a2cacdcc Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 27 Aug 2017 20:38:54 +0200 Subject: [PATCH 1/9] vtysh: cleanup SUID handling Eliminate several more SUID problems (VTYSH_LOG, history file) and make the whole SUID approach more robust. Still possibly unsafe to use, but much better. [v2: wrap seteuid/setegid calls] Signed-off-by: David Lamparter --- vtysh/vtysh.h | 3 ++ vtysh/vtysh_main.c | 78 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index b0866ec7f3..e10ab11da9 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -93,6 +93,9 @@ void vtysh_config_init(void); void vtysh_pager_init(void); +void suid_on(void); +void suid_off(void); + /* Child process execution flag. */ extern int execute_flag; diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index 8145bf3641..b9909b4930 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -44,6 +44,10 @@ /* VTY shell program name. */ char *progname; +/* SUID mode */ +static uid_t elevuid, realuid; +static gid_t elevgid, realgid; + /* Configuration file name and directory. */ static char vtysh_config_always[MAXPATHLEN] = SYSCONFDIR VTYSH_DEFAULT_CONFIG; static char quagga_config_default[MAXPATHLEN] = SYSCONFDIR FRR_DEFAULT_CONFIG; @@ -249,6 +253,30 @@ static void vtysh_unflock_config(void) close(flock_fd); } +void suid_on(void) +{ + if (elevuid != realuid && seteuid(elevuid)) { + perror("seteuid(on)"); + exit(1); + } + if (elevgid != realgid && setegid(elevgid)) { + perror("setegid(on)"); + exit(1); + } +} + +void suid_off(void) +{ + if (elevuid != realuid && seteuid(realuid)) { + perror("seteuid(off)"); + exit(1); + } + if (elevgid != realgid && setegid(realgid)) { + perror("setegid(off)"); + exit(1); + } +} + /* VTY shell main routine. */ int main(int argc, char **argv, char **env) { @@ -270,17 +298,18 @@ int main(int argc, char **argv, char **env) int writeconfig = 0; int ret = 0; char *homedir = NULL; + int ditch_suid = 0; - /* check for restricted functionality if vtysh is run setuid */ - int restricted = (getuid() != geteuid()) || (getgid() != getegid()); + /* SUID: drop down to calling user & go back up when needed */ + elevuid = geteuid(); + elevgid = getegid(); + realuid = getuid(); + realgid = getgid(); + suid_off(); /* Preserve name of myself. */ progname = ((p = strrchr(argv[0], '/')) ? ++p : argv[0]); - /* if logging open now */ - if ((p = getenv("VTYSH_LOG")) != NULL) - logfile = fopen(p, "a"); - /* Option handling. */ while (1) { opt = getopt_long(argc, argv, "be:c:d:nf:mEhCw", longopts, 0); @@ -307,17 +336,11 @@ int main(int argc, char **argv, char **env) tail = cr; } break; case OPTION_VTYSOCK: + ditch_suid = 1; /* option disables SUID */ vty_sock_path = optarg; break; case OPTION_CONFDIR: - /* - * Skip option for Config Directory if setuid - */ - if (restricted) { - fprintf(stderr, - "Overriding of Config Directory blocked for vtysh with setuid"); - return 1; - } + ditch_suid = 1; /* option disables SUID */ /* * Overwrite location for vtysh.conf */ @@ -395,6 +418,11 @@ int main(int argc, char **argv, char **env) } } + if (ditch_suid) { + elevuid = realuid; + elevgid = realgid; + } + if (!vty_sock_path) vty_sock_path = frr_vtydir; @@ -425,8 +453,11 @@ int main(int argc, char **argv, char **env) vty_init_vtysh(); - /* Read vtysh configuration file before connecting to daemons. */ + /* Read vtysh configuration file before connecting to daemons. + * (file may not be readable to calling user in SUID mode) */ + suid_on(); vtysh_read_config(vtysh_config_always); + suid_off(); if (markfile) { if (!inputfile) { @@ -486,6 +517,9 @@ int main(int argc, char **argv, char **env) } } + /* SUID: go back up elevated privs */ + suid_on(); + /* Make sure we pass authentication before proceeding. */ vtysh_auth(); @@ -498,6 +532,9 @@ int main(int argc, char **argv, char **env) exit(1); } + /* SUID: back down, don't need privs further on */ + suid_off(); + if (writeconfig) { vtysh_execute("enable"); return vtysh_write_config_integrated(); @@ -531,6 +568,17 @@ int main(int argc, char **argv, char **env) } } + if (getenv("VTYSH_LOG")) { + const char *logpath = getenv("VTYSH_LOG"); + + logfile = fopen(logpath, "a"); + if (!logfile) { + fprintf(stderr, "Failed to open logfile (%s): %s\n", + logpath, strerror(errno)); + exit(1); + } + } + /* If eval mode. */ if (cmd) { /* Enter into enable node. */ From 9b8a82496a677e1ec0509f66026f6c3ef4ee3365 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 27 Aug 2017 20:57:34 +0200 Subject: [PATCH 2/9] vtysh: simplify path handling Signed-off-by: David Lamparter --- vtysh/vtysh.c | 24 ++++++------- vtysh/vtysh.h | 9 ++--- vtysh/vtysh_main.c | 86 +++++++++++++--------------------------------- 3 files changed, 37 insertions(+), 82 deletions(-) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 85cbcae4df..b729af9823 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -2295,12 +2295,12 @@ int vtysh_write_config_integrated(void) fprintf(stdout, "Building Configuration...\n"); - backup_config_file(quagga_config); - fp = fopen(quagga_config, "w"); + backup_config_file(frr_config); + fp = fopen(frr_config, "w"); if (fp == NULL) { fprintf(stdout, "%% Error: failed to open configuration file %s: %s\n", - quagga_config, safe_strerror(errno)); + frr_config, safe_strerror(errno)); return CMD_WARNING_CONFIG_FAILED; } fd = fileno(fp); @@ -2313,7 +2313,7 @@ int vtysh_write_config_integrated(void) if (fchmod(fd, CONFIGFILE_MASK) != 0) { printf("%% Warning: can't chmod configuration file %s: %s\n", - quagga_config, safe_strerror(errno)); + frr_config, safe_strerror(errno)); err++; } @@ -2345,18 +2345,18 @@ int vtysh_write_config_integrated(void) if ((uid != (uid_t)-1 || gid != (gid_t)-1) && fchown(fd, uid, gid)) { printf("%% Warning: can't chown configuration file %s: %s\n", - quagga_config, safe_strerror(errno)); + frr_config, safe_strerror(errno)); err++; } } else { - printf("%% Warning: stat() failed on %s: %s\n", quagga_config, + printf("%% Warning: stat() failed on %s: %s\n", frr_config, safe_strerror(errno)); err++; } fclose(fp); - printf("Integrated configuration saved to %s\n", quagga_config); + printf("Integrated configuration saved to %s\n", frr_config); if (err) return CMD_WARNING; @@ -2370,7 +2370,7 @@ static bool want_config_integrated(void) switch (vtysh_write_integrated) { case WRITE_INTEGRATED_UNSPECIFIED: - if (stat(quagga_config, &s) && errno == ENOENT) + if (stat(frr_config, &s) && errno == ENOENT) return false; return true; case WRITE_INTEGRATED_NO: @@ -2712,7 +2712,7 @@ static int vtysh_connect(struct vtysh_client *vclient) if (!vclient->path[0]) snprintf(vclient->path, sizeof(vclient->path), "%s/%s.vty", - vty_sock_path, vclient->name); + vtydir, vclient->name); path = vclient->path; /* Stat socket to see if we have permission to access it. */ @@ -2806,7 +2806,7 @@ static void vtysh_update_all_insances(struct vtysh_client *head_client) return; /* ls vty_sock_dir and look for all files ending in .vty */ - dir = opendir(vty_sock_path); + dir = opendir(vtydir); if (dir) { while ((file = readdir(dir)) != NULL) { if (begins_with(file->d_name, "ospfd-") @@ -2814,7 +2814,7 @@ static void vtysh_update_all_insances(struct vtysh_client *head_client) if (n == MAXIMUM_INSTANCES) { fprintf(stderr, "Parsing %s, client limit(%d) reached!\n", - vty_sock_path, n); + vtydir, n); break; } client = (struct vtysh_client *)malloc( @@ -2823,7 +2823,7 @@ static void vtysh_update_all_insances(struct vtysh_client *head_client) client->name = "ospfd"; client->flag = VTYSH_OSPFD; snprintf(client->path, sizeof(client->path), - "%s/%s", vty_sock_path, file->d_name); + "%s/%s", vtydir, file->d_name); client->next = NULL; vtysh_client_sorted_insert(head_client, client); n++; diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index e10ab11da9..9d6ea4bda4 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -49,10 +49,6 @@ DECLARE_MGROUP(MVTYSH) #define VTYSH_NS VTYSH_ZEBRA #define VTYSH_VRF VTYSH_ZEBRA|VTYSH_PIMD -/* vtysh local configuration file. */ -#define VTYSH_DEFAULT_CONFIG "vtysh.conf" -#define FRR_DEFAULT_CONFIG "frr.conf" - enum vtysh_write_integrated { WRITE_INTEGRATED_UNSPECIFIED, WRITE_INTEGRATED_NO, @@ -61,7 +57,8 @@ enum vtysh_write_integrated { extern enum vtysh_write_integrated vtysh_write_integrated; -extern char *quagga_config; +extern char frr_config[]; +extern char vtydir[]; void vtysh_init_vty(void); void vtysh_init_cmd(void); @@ -101,6 +98,4 @@ extern int execute_flag; extern struct vty *vty; -extern const char *vty_sock_path; - #endif /* VTYSH_H */ diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index b9909b4930..0f1fe4857b 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -48,18 +48,18 @@ char *progname; static uid_t elevuid, realuid; static gid_t elevgid, realgid; +#define VTYSH_CONFIG_NAME "vtysh.conf" +#define FRR_CONFIG_NAME "frr.conf" + /* Configuration file name and directory. */ -static char vtysh_config_always[MAXPATHLEN] = SYSCONFDIR VTYSH_DEFAULT_CONFIG; -static char quagga_config_default[MAXPATHLEN] = SYSCONFDIR FRR_DEFAULT_CONFIG; -char *quagga_config = quagga_config_default; -char history_file[MAXPATHLEN]; +static char vtysh_config[MAXPATHLEN]; +char frr_config[MAXPATHLEN]; +char vtydir[MAXPATHLEN]; +static char history_file[MAXPATHLEN]; /* Flag for indicate executing child command. */ int execute_flag = 0; -/* VTY Socket prefix */ -const char *vty_sock_path = NULL; - /* For sigsetjmp() & siglongjmp(). */ static sigjmp_buf jmpbuf; @@ -286,7 +286,6 @@ int main(int argc, char **argv, char **env) int boot_flag = 0; const char *daemon_name = NULL; const char *inputfile = NULL; - const char *vtysh_configfile_name; struct cmd_rec { char *line; struct cmd_rec *next; @@ -299,6 +298,7 @@ int main(int argc, char **argv, char **env) int ret = 0; char *homedir = NULL; int ditch_suid = 0; + char sysconfdir[MAXPATHLEN]; /* SUID: drop down to calling user & go back up when needed */ elevuid = geteuid(); @@ -310,6 +310,9 @@ int main(int argc, char **argv, char **env) /* Preserve name of myself. */ progname = ((p = strrchr(argv[0], '/')) ? ++p : argv[0]); + strlcpy(sysconfdir, frr_sysconfdir, sizeof(sysconfdir)); + strlcpy(vtydir, frr_vtydir, sizeof(vtydir)); + /* Option handling. */ while (1) { opt = getopt_long(argc, argv, "be:c:d:nf:mEhCw", longopts, 0); @@ -337,56 +340,11 @@ int main(int argc, char **argv, char **env) } break; case OPTION_VTYSOCK: ditch_suid = 1; /* option disables SUID */ - vty_sock_path = optarg; + strlcpy(vtydir, optarg, sizeof(vtydir)); break; case OPTION_CONFDIR: ditch_suid = 1; /* option disables SUID */ - /* - * Overwrite location for vtysh.conf - */ - vtysh_configfile_name = - strrchr(VTYSH_DEFAULT_CONFIG, '/'); - if (vtysh_configfile_name) - /* skip '/' */ - vtysh_configfile_name++; - else - /* - * VTYSH_DEFAULT_CONFIG configured with relative - * path - * during config? Should really never happen for - * sensible config - */ - vtysh_configfile_name = - (char *)VTYSH_DEFAULT_CONFIG; - strlcpy(vtysh_config_always, optarg, - sizeof(vtysh_config_always)); - strlcat(vtysh_config_always, "/", - sizeof(vtysh_config_always)); - strlcat(vtysh_config_always, vtysh_configfile_name, - sizeof(vtysh_config_always)); - /* - * Overwrite location for frr.conf - */ - vtysh_configfile_name = - strrchr(FRR_DEFAULT_CONFIG, '/'); - if (vtysh_configfile_name) - /* skip '/' */ - vtysh_configfile_name++; - else - /* - * FRR_DEFAULT_CONFIG configured with relative - * path - * during config? Should really never happen for - * sensible config - */ - vtysh_configfile_name = - (char *)FRR_DEFAULT_CONFIG; - strlcpy(quagga_config_default, optarg, - sizeof(vtysh_config_always)); - strlcat(quagga_config_default, "/", - sizeof(vtysh_config_always)); - strlcat(quagga_config_default, vtysh_configfile_name, - sizeof(quagga_config_default)); + strlcpy(sysconfdir, optarg, sizeof(sysconfdir)); break; case 'd': daemon_name = optarg; @@ -423,9 +381,6 @@ int main(int argc, char **argv, char **env) elevgid = realgid; } - if (!vty_sock_path) - vty_sock_path = frr_vtydir; - if (markfile + writeconfig + dryrun + boot_flag > 1) { fprintf(stderr, "Invalid combination of arguments. Please specify at " @@ -438,6 +393,11 @@ int main(int argc, char **argv, char **env) "NOT SUPPORTED since its\nresults are inconsistent!\n"); } + snprintf(vtysh_config, sizeof(vtysh_config), "%s/%s", + sysconfdir, VTYSH_CONFIG_NAME); + snprintf(frr_config, sizeof(frr_config), "%s/%s", + sysconfdir, FRR_CONFIG_NAME); + /* Initialize user input buffer. */ line_read = NULL; setlinebuf(stdout); @@ -456,7 +416,7 @@ int main(int argc, char **argv, char **env) /* Read vtysh configuration file before connecting to daemons. * (file may not be readable to calling user in SUID mode) */ suid_on(); - vtysh_read_config(vtysh_config_always); + vtysh_read_config(vtysh_config); suid_off(); if (markfile) { @@ -473,7 +433,7 @@ int main(int argc, char **argv, char **env) if (inputfile) { ret = vtysh_read_config(inputfile); } else { - ret = vtysh_read_config(quagga_config_default); + ret = vtysh_read_config(frr_config); } exit(ret); @@ -640,13 +600,13 @@ int main(int argc, char **argv, char **env) /* Boot startup configuration file. */ if (boot_flag) { - vtysh_flock_config(quagga_config); - int ret = vtysh_read_config(quagga_config); + vtysh_flock_config(frr_config); + int ret = vtysh_read_config(frr_config); vtysh_unflock_config(); if (ret) { fprintf(stderr, "Configuration file[%s] processing failure: %d\n", - quagga_config, ret); + frr_config, ret); if (no_error) exit(0); else From d1b4fc1f896b3dea3865869166614e99bad6623a Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 27 Aug 2017 21:03:12 +0200 Subject: [PATCH 3/9] lib: add -N/--pathspace option This allows running the daemons inside of Linux network namespaces without messing with an additional mount/fs namespace (or a ton of options). Signed-off-by: David Lamparter --- lib/libfrr.c | 50 +++++++++++++++++++++++++++++++++++++++----------- lib/libfrr.h | 1 + 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/lib/libfrr.c b/lib/libfrr.c index 9944fdd1e1..3e2e008223 100644 --- a/lib/libfrr.c +++ b/lib/libfrr.c @@ -101,13 +101,15 @@ static const struct optspec os_always = { static const struct option lo_cfg_pid_dry[] = { {"pid_file", required_argument, NULL, 'i'}, {"config_file", required_argument, NULL, 'f'}, + {"pathspace", required_argument, NULL, 'N'}, {"dryrun", no_argument, NULL, 'C'}, {"terminal", no_argument, NULL, 't'}, {NULL}}; static const struct optspec os_cfg_pid_dry = { - "f:i:Ct", + "f:i:CtN:", " -f, --config_file Set configuration file name\n" " -i, --pid_file Set process identifier file name\n" + " -N, --pathspace Insert prefix into config & socket paths\n" " -C, --dryrun Check configuration for validity and exit\n" " -t, --terminal Open terminal session on stdio\n" " -d -t Daemonize after terminal session ends\n", @@ -351,6 +353,23 @@ static int frr_opt(int opt) return 1; di->config_file = optarg; break; + case 'N': + if (di->flags & FRR_NO_CFG_PID_DRY) + return 1; + if (di->pathspace) { + fprintf(stderr, + "-N/--pathspace option specified more than once!\n"); + errors++; + break; + } + if (strchr(optarg, '/') || strchr(optarg, '.')) { + fprintf(stderr, + "slashes or dots are not permitted in the --pathspace option.\n"); + errors++; + break; + } + di->pathspace = optarg; + break; case 'C': if (di->flags & FRR_NO_CFG_PID_DRY) return 1; @@ -500,14 +519,25 @@ struct thread_master *frr_init(void) struct option_chain *oc; struct frrmod_runtime *module; char moderr[256]; + char p_instance[16] = "", p_pathspace[256] = ""; const char *dir; dir = di->module_path ? di->module_path : frr_moduledir; srandom(time(NULL)); - if (di->instance) + if (di->instance) { snprintf(frr_protonameinst, sizeof(frr_protonameinst), "%s[%u]", di->logname, di->instance); + snprintf(p_instance, sizeof(p_instance), "-%d", di->instance); + } + if (di->pathspace) + snprintf(p_pathspace, sizeof(p_pathspace), "/%s", + di->pathspace); + + snprintf(config_default, sizeof(config_default), "%s%s/%s%s.conf", + frr_sysconfdir, p_pathspace, di->name, p_instance); + snprintf(pidfile_default, sizeof(pidfile_default), "%s%s/%s%s.pid", + frr_vtydir, p_pathspace, di->name, p_instance); zprivs_preinit(di->privs); @@ -695,14 +725,6 @@ void frr_config_fork(void) { hook_call(frr_late_init, master); - if (di->instance) { - snprintf(config_default, sizeof(config_default), - "%s/%s-%d.conf", frr_sysconfdir, di->name, - di->instance); - snprintf(pidfile_default, sizeof(pidfile_default), - "%s/%s-%d.pid", frr_vtydir, di->name, di->instance); - } - vty_read_config(di->config_file, config_default); /* Don't start execution if we are in dry-run mode */ @@ -723,7 +745,13 @@ void frr_vty_serv(void) * (not currently set anywhere) */ if (!di->vty_path) { const char *dir; - dir = di->vty_sock_path ? di->vty_sock_path : frr_vtydir; + char defvtydir[256]; + + snprintf(defvtydir, sizeof(defvtydir), "%s%s%s", frr_vtydir, + di->pathspace ? "/" : "", + di->pathspace ? di->pathspace : ""); + + dir = di->vty_sock_path ? di->vty_sock_path : defvtydir; if (di->instance) snprintf(vtypath_default, sizeof(vtypath_default), diff --git a/lib/libfrr.h b/lib/libfrr.h index f7d69eecb3..fe6c46670a 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -54,6 +54,7 @@ struct frr_daemon_info { const char *pid_file; const char *vty_path; const char *module_path; + const char *pathspace; const char *proghelp; void (*printhelp)(FILE *target); From 8bd33a03b514d10777ad292f0957cb01d5b9f1a5 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 27 Aug 2017 21:03:32 +0200 Subject: [PATCH 4/9] vtysh: add -N/--pathspace option Signed-off-by: David Lamparter --- vtysh/vtysh_main.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c index 0f1fe4857b..961201ea90 100644 --- a/vtysh/vtysh_main.c +++ b/vtysh/vtysh_main.c @@ -149,6 +149,7 @@ static void usage(int status) "-m, --markfile Mark input file with context end\n" " --vty_socket Override vty socket path\n" " --config_dir Override config directory path\n" + "-N --pathspace Insert prefix into config & socket paths\n" "-w, --writeconfig Write integrated config (frr.conf) and exit\n" "-h, --help Display this help and exit\n\n" "Note that multiple commands may be executed from the command\n" @@ -178,6 +179,7 @@ struct option longopts[] = { {"noerror", no_argument, NULL, 'n'}, {"mark", no_argument, NULL, 'm'}, {"writeconfig", no_argument, NULL, 'w'}, + {"pathspace", no_argument, NULL, 'N'}, {0}}; /* Read a string, and return a pointer to it. Returns NULL on EOF. */ @@ -299,6 +301,7 @@ int main(int argc, char **argv, char **env) char *homedir = NULL; int ditch_suid = 0; char sysconfdir[MAXPATHLEN]; + char pathspace[MAXPATHLEN] = ""; /* SUID: drop down to calling user & go back up when needed */ elevuid = geteuid(); @@ -346,6 +349,14 @@ int main(int argc, char **argv, char **env) ditch_suid = 1; /* option disables SUID */ strlcpy(sysconfdir, optarg, sizeof(sysconfdir)); break; + case 'N': + if (strchr(optarg, '/') || strchr(optarg, '.')) { + fprintf(stderr, + "slashes or dots are not permitted in the --pathspace option.\n"); + exit(1); + } + snprintf(pathspace, sizeof(pathspace), "/%s", optarg); + break; case 'd': daemon_name = optarg; break; @@ -393,10 +404,11 @@ int main(int argc, char **argv, char **env) "NOT SUPPORTED since its\nresults are inconsistent!\n"); } - snprintf(vtysh_config, sizeof(vtysh_config), "%s/%s", - sysconfdir, VTYSH_CONFIG_NAME); - snprintf(frr_config, sizeof(frr_config), "%s/%s", - sysconfdir, FRR_CONFIG_NAME); + snprintf(vtysh_config, sizeof(vtysh_config), "%s%s/%s", + sysconfdir, pathspace, VTYSH_CONFIG_NAME); + snprintf(frr_config, sizeof(frr_config), "%s%s/%s", + sysconfdir, pathspace, FRR_CONFIG_NAME); + strlcat(vtydir, pathspace, sizeof(vtydir)); /* Initialize user input buffer. */ line_read = NULL; From 2071aa0ebbc5701e9b53621f93656c10cb48061b Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 5 Feb 2010 09:48:45 +0100 Subject: [PATCH 5/9] lib: add vty_frame() to get rid of unneeded config vty_frame() can be used to reduce the amount of output produced by "show running-config" and "write ...". It buffers output in struct vty->frame (1024 bytes) and outputs it when vty_out is called. If vty_out isn't called, it can be removed with vty_endframe() later. Signed-off-by: David Lamparter --- lib/vty.c | 24 ++++++++++++++++++++++++ lib/vty.h | 15 +++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/lib/vty.c b/lib/vty.c index 59a8825357..1bd27cfa95 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -91,6 +91,25 @@ char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG; static int do_log_commands = 0; +void vty_frame(struct vty *vty, const char *format, ...) +{ + va_list args; + + va_start(args, format); + vsnprintf(vty->frame + vty->frame_pos, + sizeof(vty->frame) - vty->frame_pos, + format, args); + vty->frame_pos = strlen(vty->frame); + va_end(args); +} + +void vty_endframe(struct vty *vty, const char *endtext) +{ + if (vty->frame_pos == 0 && endtext) + vty_out(vty, "%s", endtext); + vty->frame_pos = 0; +} + /* VTY standard output function. */ int vty_out(struct vty *vty, const char *format, ...) { @@ -100,6 +119,11 @@ int vty_out(struct vty *vty, const char *format, ...) char buf[1024]; char *p = NULL; + if (vty->frame_pos) { + vty->frame_pos = 0; + vty_out(vty, "%s", vty->frame); + } + if (vty_shell(vty)) { va_start(args, format); vprintf(format, args); diff --git a/lib/vty.h b/lib/vty.h index 9acd62af3c..3b75afb02c 100644 --- a/lib/vty.h +++ b/lib/vty.h @@ -125,6 +125,12 @@ struct vty { /* What address is this vty comming from. */ char address[SU_ADDRSTRLEN]; + + /* "frame" output. This is buffered and will be printed if some + * actual output follows, or will be discarded if the frame ends + * without any output. */ + size_t frame_pos; + char frame[1024]; }; static inline void vty_push_context(struct vty *vty, int node, uint64_t id) @@ -247,7 +253,16 @@ extern void vty_terminate(void); extern void vty_reset(void); extern struct vty *vty_new(void); extern struct vty *vty_stdio(void (*atclose)(int isexit)); + +/* - vty_frame() output goes to a buffer (for context-begin markers) + * - vty_out() will first print this buffer, and clear it + * - vty_endframe() clears the buffer without printing it, and prints an + * extra string if the buffer was empty before (for context-end markers) + */ extern int vty_out(struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3); +extern void vty_frame(struct vty *, const char *, ...) PRINTF_ATTRIBUTE(2, 3); +extern void vty_endframe(struct vty *, const char *); + extern void vty_read_config(const char *, char *); extern void vty_time_print(struct vty *, int); extern void vty_serv_sock(const char *, unsigned short, const char *); From a8b828f3c3e55eacdfba77f31750ada20ed13390 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Fri, 5 Feb 2010 09:48:45 +0100 Subject: [PATCH 6/9] *: remove empty "interface XYZ" config blocks Using the previously-added vty_frame() support, this gets rid of all the pointless empty "interface XYZ" blocks that get added for any interface that shows up in the system (e.g. dummys, tunnels, etc.) Signed-off-by: David Lamparter --- babeld/babel_interface.c | 4 ++-- eigrpd/eigrp_vty.c | 8 ++++---- isisd/isis_circuit.c | 4 ++-- nhrpd/nhrp_vty.c | 4 ++-- ospf6d/ospf6_interface.c | 4 ++-- ospfd/ospf_vty.c | 6 ++++-- pimd/pim_vty.c | 4 ++-- ripd/rip_interface.c | 4 ++-- ripngd/ripng_interface.c | 4 ++-- zebra/interface.c | 4 ++-- 10 files changed, 24 insertions(+), 22 deletions(-) diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c index 9fa32ee6fa..2895ac1e69 100644 --- a/babeld/babel_interface.c +++ b/babeld/babel_interface.c @@ -1321,7 +1321,7 @@ interface_config_write (struct vty *vty) int write = 0; for (ALL_LIST_ELEMENTS_RO (vrf_iflist(VRF_DEFAULT), node, ifp)) { - vty_out (vty, "interface %s\n",ifp->name); + vty_frame (vty, "interface %s\n",ifp->name); if (ifp->desc) vty_out (vty, " description %s\n",ifp->desc); babel_interface_nfo *babel_ifp = babel_get_if_nfo (ifp); @@ -1377,7 +1377,7 @@ interface_config_write (struct vty *vty) write++; } } - vty_out (vty, "!\n"); + vty_endframe (vty, "!\n"); write++; } return write; diff --git a/eigrpd/eigrp_vty.c b/eigrpd/eigrp_vty.c index 4a8842f30e..5c657b6db5 100644 --- a/eigrpd/eigrp_vty.c +++ b/eigrpd/eigrp_vty.c @@ -93,7 +93,7 @@ static int config_write_interfaces(struct vty *vty, struct eigrp *eigrp) struct listnode *node; for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) { - vty_out(vty, "interface %s\n", ei->ifp->name); + vty_frame(vty, "interface %s\n", ei->ifp->name); if ((IF_DEF_PARAMS(ei->ifp)->auth_type) == EIGRP_AUTH_TYPE_MD5) { @@ -128,7 +128,7 @@ static int config_write_interfaces(struct vty *vty, struct eigrp *eigrp) } /*Separate this EIGRP interface configuration from the others*/ - vty_out(vty, "!\n"); + vty_endframe(vty, "!\n"); } return 0; @@ -140,7 +140,7 @@ static int eigrp_write_interface(struct vty *vty) struct interface *ifp; for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { - vty_out(vty, "interface %s\n", ifp->name); + vty_frame(vty, "interface %s\n", ifp->name); if (ifp->desc) vty_out(vty, " description %s\n", ifp->desc); @@ -157,7 +157,7 @@ static int eigrp_write_interface(struct vty *vty) vty_out(vty, " ip hold-time eigrp %u\n", IF_DEF_PARAMS(ifp)->v_wait); - vty_out(vty, "!\n"); + vty_endframe(vty, "!\n"); } return 0; diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index a1aa87e396..7dd8303907 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -948,7 +948,7 @@ int isis_interface_config_write(struct vty *vty) continue; /* IF name */ - vty_out(vty, "interface %s\n", ifp->name); + vty_frame(vty, "interface %s\n", ifp->name); write++; /* IF desc */ if (ifp->desc) { @@ -1145,7 +1145,7 @@ int isis_interface_config_write(struct vty *vty) } write += circuit_write_mt_settings(circuit, vty); } - vty_out(vty, "!\n"); + vty_endframe(vty, "!\n"); } return write; diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c index 6d78fc1d2b..bd5b1aa6f1 100644 --- a/nhrpd/nhrp_vty.c +++ b/nhrpd/nhrp_vty.c @@ -854,7 +854,7 @@ static int interface_config_write(struct vty *vty) int i; for (ALL_LIST_ELEMENTS_RO(vrf_iflist(VRF_DEFAULT), node, ifp)) { - vty_out (vty, "interface %s\n", ifp->name); + vty_frame(vty, "interface %s\n", ifp->name); if (ifp->desc) vty_out (vty, " description %s\n", ifp->desc); @@ -913,7 +913,7 @@ static int interface_config_write(struct vty *vty) } } - vty_out (vty, "!\n"); + vty_endframe(vty, "!\n"); } return 0; diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index bb63fb966e..8cfed81a81 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -1755,7 +1755,7 @@ static int config_write_ospf6_interface(struct vty *vty) if (oi == NULL) continue; - vty_out(vty, "interface %s\n", oi->interface->name); + vty_frame(vty, "interface %s\n", oi->interface->name); if (ifp->desc) vty_out(vty, " description %s\n", ifp->desc); @@ -1808,7 +1808,7 @@ static int config_write_ospf6_interface(struct vty *vty) ospf6_bfd_write_config(vty, oi); - vty_out(vty, "!\n"); + vty_endframe(vty, "!\n"); } return 0; } diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 87aef1ea97..fd392fcc7d 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -8152,8 +8152,8 @@ static int config_write_interface(struct vty *vty) if (ifp->ifindex == IFINDEX_DELETED) continue; - vty_out(vty, "!\n"); - vty_out(vty, "interface %s\n", ifp->name); + vty_frame(vty, "!\n"); + vty_frame(vty, "interface %s\n", ifp->name); if (ifp->desc) vty_out(vty, " description %s\n", ifp->desc); @@ -8367,6 +8367,8 @@ static int config_write_interface(struct vty *vty) } while (rn); ospf_opaque_config_write_if(vty, ifp); + + vty_endframe(vty, NULL); } return write; diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 8914f6eb00..6eb413a4eb 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -255,7 +255,7 @@ int pim_interface_config_write(struct vty *vty) /* IF name */ if (vrf->vrf_id == VRF_DEFAULT) - vty_out(vty, "interface %s\n", ifp->name); + vty_frame(vty, "interface %s\n", ifp->name); else vty_out(vty, "interface %s vrf %s\n", ifp->name, vrf->name); @@ -363,7 +363,7 @@ int pim_interface_config_write(struct vty *vty) pim_static_write_mroute(pim, vty, ifp); pim_bfd_write_config(vty, ifp); } - vty_out(vty, "!\n"); + vty_endframe(vty, "!\n"); ++writes; } } diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 00b6d1cadd..1b2cbb61c3 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -1751,7 +1751,7 @@ static int rip_interface_config_write(struct vty *vty) && (!ri->auth_str) && (!ri->key_chain)) continue; - vty_out(vty, "interface %s\n", ifp->name); + vty_frame(vty, "interface %s\n", ifp->name); if (ifp->desc) vty_out(vty, " description %s\n", ifp->desc); @@ -1807,7 +1807,7 @@ static int rip_interface_config_write(struct vty *vty) vty_out(vty, " ip rip authentication key-chain %s\n", ri->key_chain); - vty_out(vty, "!\n"); + vty_endframe(vty, "!\n"); } return 0; } diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c index 02fab68254..5c65f522ef 100644 --- a/ripngd/ripng_interface.c +++ b/ripngd/ripng_interface.c @@ -1084,7 +1084,7 @@ static int interface_config_write(struct vty *vty) && (ri->split_horizon == ri->split_horizon_default)) continue; - vty_out(vty, "interface %s\n", ifp->name); + vty_frame(vty, "interface %s\n", ifp->name); if (ifp->desc) vty_out(vty, " description %s\n", ifp->desc); @@ -1105,7 +1105,7 @@ static int interface_config_write(struct vty *vty) } } - vty_out(vty, "!\n"); + vty_endframe(vty, "!\n"); write++; } diff --git a/zebra/interface.c b/zebra/interface.c index c17e408ea0..9e2e116145 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -2791,7 +2791,7 @@ static int if_config_write(struct vty *vty) vrf = vrf_lookup_by_id(ifp->vrf_id); if (ifp->vrf_id == VRF_DEFAULT) - vty_out(vty, "interface %s\n", ifp->name); + vty_frame(vty, "interface %s\n", ifp->name); else vty_out(vty, "interface %s vrf %s\n", ifp->name, vrf->name); @@ -2842,7 +2842,7 @@ static int if_config_write(struct vty *vty) link_params_config_write(vty, ifp); - vty_out(vty, "!\n"); + vty_endframe(vty, "!\n"); } return 0; } From 2b79110731dc86fedb9c38f88b228813f7320770 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 27 Aug 2017 22:18:32 +0200 Subject: [PATCH 7/9] bgpd: get rid of afi_header_vty_out() & co. afi_header_vty_out() is easily replaced with vty_frame(), which means we can drop a whole batch of "int *write" args as well as the entirety of bgp_config_write_family_header(). => AFI/SAFI config writing is now a lot simpler. Signed-off-by: David Lamparter --- bgpd/bgp_evpn_vty.c | 34 +---- bgpd/bgp_evpn_vty.h | 2 +- bgpd/bgp_route.c | 58 +++----- bgpd/bgp_route.h | 9 +- bgpd/bgp_vty.c | 36 ++--- bgpd/bgp_vty.h | 8 +- bgpd/bgp_zebra.h | 8 +- bgpd/bgpd.c | 346 +++++++++++++++++--------------------------- bgpd/bgpd.h | 1 - 9 files changed, 176 insertions(+), 326 deletions(-) diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 948c7f50f2..1467083c01 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -48,11 +48,6 @@ struct vni_walk_ctx { struct in_addr vtep_ip; }; -struct evpn_config_write { - int write; - struct vty *vty; -}; - #if defined(HAVE_CUMULUS) static void display_import_rt(struct vty *vty, struct irt_node *irt) { @@ -1709,17 +1704,14 @@ static void evpn_unset_advertise_all_vni(struct bgp *bgp) } #endif /* HAVE_CUMULUS */ -static void write_vni_config(struct vty *vty, struct bgpevpn *vpn, int *write) +static void write_vni_config(struct vty *vty, struct bgpevpn *vpn) { char buf1[INET6_ADDRSTRLEN]; - afi_t afi = AFI_L2VPN; - safi_t safi = SAFI_EVPN; char *ecom_str; struct listnode *node, *nnode; struct ecommunity *ecom; if (is_vni_configured(vpn)) { - bgp_config_write_family_header(vty, afi, safi, write); vty_out(vty, " vni %d\n", vpn->vni); if (is_rd_configured(vpn)) vty_out(vty, " rd %s\n", @@ -1755,10 +1747,10 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn, int *write) } static void write_vni_config_for_entry(struct hash_backet *backet, - struct evpn_config_write *cfg) + struct vty *vty) { struct bgpevpn *vpn = (struct bgpevpn *)backet->data; - write_vni_config(cfg->vty, vpn, &cfg->write); + write_vni_config(vty, vpn); } #if defined(HAVE_CUMULUS) @@ -2741,29 +2733,19 @@ DEFUN (no_bgp_evpn_vni_rt_without_val, * Output EVPN configuration information. */ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi, int *write) + safi_t safi) { - struct evpn_config_write cfg; - - if (bgp->vnihash) { - cfg.write = *write; - cfg.vty = vty; + if (bgp->vnihash) hash_iterate(bgp->vnihash, (void (*)(struct hash_backet *, void *))write_vni_config_for_entry, - &cfg); - *write = cfg.write; - } + vty); - if (bgp->advertise_all_vni) { - bgp_config_write_family_header(vty, afi, safi, write); + if (bgp->advertise_all_vni) vty_out(vty, " advertise-all-vni\n"); - } - if (bgp->advertise_gw_macip) { - bgp_config_write_family_header(vty, afi, safi, write); + if (bgp->advertise_gw_macip) vty_out(vty, " advertise-default-gw\n"); - } } void bgp_ethernetvpn_init(void) diff --git a/bgpd/bgp_evpn_vty.h b/bgpd/bgp_evpn_vty.h index 3bc24593f4..4d07f7d038 100644 --- a/bgpd/bgp_evpn_vty.h +++ b/bgpd/bgp_evpn_vty.h @@ -22,7 +22,7 @@ #define _FRR_BGP_EVPN_VTY_H extern void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, - afi_t afi, safi_t safi, int *write); + afi_t afi, safi_t safi); extern void bgp_ethernetvpn_init(void); #define L2VPN_HELP_STR "Layer 2 Virtual Private Network\n" diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 288271e5a1..814efdb4e6 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -4947,16 +4947,13 @@ static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi, return CMD_SUCCESS; } -int bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi, int *write) +void bgp_config_write_table_map(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi) { if (bgp->table_map[afi][safi].name) { - bgp_config_write_family_header(vty, afi, safi, write); vty_out(vty, " table-map %s\n", bgp->table_map[afi][safi].name); } - - return 0; } DEFUN (bgp_table_map, @@ -10978,8 +10975,8 @@ DEFUN (clear_ip_bgp_dampening_address_mask, } /* also used for encap safi */ -static int bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp, - afi_t afi, safi_t safi, int *write) +static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp, + afi_t afi, safi_t safi) { struct bgp_node *prn; struct bgp_node *rn; @@ -11001,10 +10998,6 @@ static int bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp, p = &rn->p; prd = (struct prefix_rd *)&prn->p; - /* "address-family" display. */ - bgp_config_write_family_header( - vty, afi, safi, write); - /* "network" configuration display. */ prefix_rd2str(prd, rdbuf, RD_ADDRSTRLEN); @@ -11030,11 +11023,10 @@ static int bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp, } vty_out(vty, "\n"); } - return 0; } -static int bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, - afi_t afi, safi_t safi, int *write) +static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, + afi_t afi, safi_t safi) { struct bgp_node *prn; struct bgp_node *rn; @@ -11066,10 +11058,6 @@ static int bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, p = &rn->p; prd = (struct prefix_rd *)&prn->p; - /* "address-family" display. */ - bgp_config_write_family_header( - vty, afi, safi, write); - /* "network" configuration display. */ prefix_rd2str(prd, rdbuf, RD_ADDRSTRLEN); @@ -11094,13 +11082,12 @@ static int bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, if (esi) XFREE(MTYPE_TMP, esi); } - return 0; } /* Configuration of static route announcement and aggregate information. */ -int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi, int *write) +void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi) { struct bgp_node *rn; struct prefix *p; @@ -11108,12 +11095,15 @@ int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi, struct bgp_aggregate *bgp_aggregate; char buf[SU_ADDRSTRLEN]; - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) - return bgp_config_write_network_vpn(vty, bgp, afi, safi, write); + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) { + bgp_config_write_network_vpn(vty, bgp, afi, safi); + return; + } - if (afi == AFI_L2VPN && safi == SAFI_EVPN) - return bgp_config_write_network_evpn(vty, bgp, afi, safi, - write); + if (afi == AFI_L2VPN && safi == SAFI_EVPN) { + bgp_config_write_network_evpn(vty, bgp, afi, safi); + return; + } /* Network configuration. */ for (rn = bgp_table_top(bgp->route[afi][safi]); rn; @@ -11121,9 +11111,6 @@ int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi, if ((bgp_static = rn->info) != NULL) { p = &rn->p; - /* "address-family" display. */ - bgp_config_write_family_header(vty, afi, safi, write); - /* "network" configuration display. */ if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) { @@ -11175,9 +11162,6 @@ int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi, if ((bgp_aggregate = rn->info) != NULL) { p = &rn->p; - /* "address-family" display. */ - bgp_config_write_family_header(vty, afi, safi, write); - if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) { struct in_addr netmask; @@ -11202,12 +11186,10 @@ int bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi, vty_out(vty, "\n"); } - - return 0; } -int bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi, int *write) +void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi) { struct bgp_node *rn; struct bgp_distance *bdistance; @@ -11219,7 +11201,6 @@ int bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi, || bgp->distance_ibgp[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT || bgp->distance_local[afi][safi] != ZEBRA_IBGP_DISTANCE_DEFAULT)) { - bgp_config_write_family_header(vty, afi, safi, write); vty_out(vty, " distance bgp %d %d %d\n", bgp->distance_ebgp[afi][safi], bgp->distance_ibgp[afi][safi], @@ -11231,15 +11212,12 @@ int bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi, if ((bdistance = rn->info) != NULL) { char buf[PREFIX_STRLEN]; - bgp_config_write_family_header(vty, afi, safi, write); vty_out(vty, " distance %d %s %s\n", bdistance->distance, prefix2str(&rn->p, buf, sizeof(buf)), bdistance->access_list ? bdistance->access_list : ""); } - - return *write; } /* Allocate routing table structure and install commands. */ diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 55f812d4a0..eb64530e51 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -367,12 +367,9 @@ extern void bgp_process(struct bgp *, struct bgp_node *, afi_t, safi_t); * queue element with NULL bgp node. */ extern void bgp_add_eoiu_mark(struct bgp *); -extern int bgp_config_write_table_map(struct vty *, struct bgp *, afi_t, safi_t, - int *); -extern int bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t, - int *); -extern int bgp_config_write_distance(struct vty *, struct bgp *, afi_t, safi_t, - int *); +extern void bgp_config_write_table_map(struct vty *, struct bgp *, afi_t, safi_t); +extern void bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t); +extern void bgp_config_write_distance(struct vty *, struct bgp *, afi_t, safi_t); extern void bgp_aggregate_increment(struct bgp *, struct prefix *, struct bgp_info *, afi_t, safi_t); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index f040ed9a08..fafa005d0e 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -1279,7 +1279,7 @@ static int bgp_update_delay_deconfig_vty(struct vty *vty) return CMD_SUCCESS; } -int bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp) +void bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp) { if (bgp->v_update_delay != BGP_UPDATE_DELAY_DEF) { vty_out(vty, " update-delay %d", bgp->v_update_delay); @@ -1287,8 +1287,6 @@ int bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp) vty_out(vty, " %d", bgp->v_establish_wait); vty_out(vty, "\n"); } - - return 0; } @@ -1342,12 +1340,10 @@ static int bgp_wpkt_quanta_config_vty(struct vty *vty, const char *num, return CMD_SUCCESS; } -int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp) +void bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp) { if (bgp->wpkt_quanta != BGP_WRITE_PACKET_MAX) vty_out(vty, " write-quanta %d\n", bgp->wpkt_quanta); - - return 0; } @@ -1374,12 +1370,10 @@ DEFUN (no_bgp_wpkt_quanta, return bgp_wpkt_quanta_config_vty(vty, argv[idx_number]->arg, 0); } -int bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp) +void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp) { if (bgp->coalesce_time != BGP_DEFAULT_SUBGROUP_COALESCE_TIME) vty_out(vty, " coalesce-time %u\n", bgp->coalesce_time); - - return 0; } @@ -1503,17 +1497,15 @@ ALIAS_HIDDEN(no_bgp_maxpaths_ibgp, no_bgp_maxpaths_ibgp_hidden_cmd, "Number of paths\n" "Match the cluster length\n") -int bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi, int *write) +void bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi) { if (bgp->maxpaths[afi][safi].maxpaths_ebgp != MULTIPATH_NUM) { - bgp_config_write_family_header(vty, afi, safi, write); vty_out(vty, " maximum-paths %d\n", bgp->maxpaths[afi][safi].maxpaths_ebgp); } if (bgp->maxpaths[afi][safi].maxpaths_ibgp != MULTIPATH_NUM) { - bgp_config_write_family_header(vty, afi, safi, write); vty_out(vty, " maximum-paths ibgp %d", bgp->maxpaths[afi][safi].maxpaths_ibgp); if (CHECK_FLAG(bgp->maxpaths[afi][safi].ibgp_flags, @@ -1521,8 +1513,6 @@ int bgp_config_write_maxpaths(struct vty *vty, struct bgp *bgp, afi_t afi, vty_out(vty, " equal-cluster-length"); vty_out(vty, "\n"); } - - return 0; } /* BGP timers. */ @@ -2459,7 +2449,7 @@ DEFUN (no_bgp_listen_range, return bgp_vty_return(vty, ret); } -int bgp_config_write_listen(struct vty *vty, struct bgp *bgp) +void bgp_config_write_listen(struct vty *vty, struct bgp *bgp) { struct peer_group *group; struct listnode *node, *nnode, *rnode, *nrnode; @@ -2482,8 +2472,6 @@ int bgp_config_write_listen(struct vty *vty, struct bgp *bgp) } } } - - return 0; } @@ -11041,14 +11029,14 @@ DEFUN (no_bgp_redistribute_ipv6, return bgp_redistribute_unset(bgp, AFI_IP6, type, 0); } -int bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi, int *write) +void bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi) { int i; /* Unicast redistribution only. */ if (safi != SAFI_UNICAST) - return 0; + return; for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { /* Redistribute BGP does not make sense. */ @@ -11062,11 +11050,6 @@ int bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi, continue; for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { - /* Display "address-family" when it is not yet - * diplayed. */ - bgp_config_write_family_header(vty, afi, safi, - write); - /* "redistribute" configuration. */ vty_out(vty, " redistribute %s", zebra_route_string(i)); @@ -11082,7 +11065,6 @@ int bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi, } } } - return *write; } /* BGP node structure. */ diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index 62bc27d507..59bc012661 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -46,10 +46,10 @@ struct bgp; extern void bgp_vty_init(void); extern const char *afi_safi_print(afi_t, safi_t); extern const char *afi_safi_json(afi_t, safi_t); -extern int bgp_config_write_update_delay(struct vty *, struct bgp *); -extern int bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp); -extern int bgp_config_write_listen(struct vty *vty, struct bgp *bgp); -extern int bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp); +extern void bgp_config_write_update_delay(struct vty *, struct bgp *); +extern void bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp); +extern void bgp_config_write_listen(struct vty *vty, struct bgp *bgp); +extern void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp); extern int bgp_vty_return(struct vty *vty, int ret); extern struct peer *peer_and_group_lookup_vty(struct vty *vty, const char *peer_str); diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index 11405d1c1b..7d37864f44 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -26,10 +26,10 @@ extern void bgp_zebra_init(struct thread_master *master); extern void bgp_zebra_destroy(void); extern int bgp_if_update_all(void); -extern int bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t, safi_t, - int *); -extern int bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t, - safi_t, int *); +extern void bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t, + safi_t); +extern void bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t, + safi_t); extern void bgp_zebra_announce(struct bgp_node *, struct prefix *, struct bgp_info *, struct bgp *, afi_t, safi_t); extern void bgp_zebra_announce_table(struct bgp *, afi_t, safi_t); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 92121f6aef..0e848c33cc 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -6184,14 +6184,8 @@ char *peer_uptime(time_t uptime2, char *buf, size_t len, u_char use_json, return buf; } -#define afi_header_vty_out(vty, afi, safi, write, format, ...) \ - do { \ - bgp_config_write_family_header(vty, afi, safi, write); \ - vty_out(vty, format, ## __VA_ARGS__); \ - } while (0) - static void bgp_config_write_filter(struct vty *vty, struct peer *peer, - afi_t afi, safi_t safi, int *write) + afi_t afi, safi_t safi) { struct bgp_filter *filter; struct bgp_filter *gfilter = NULL; @@ -6210,16 +6204,13 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer, if (!gfilter || !gfilter->dlist[in].name || strcmp(filter->dlist[in].name, gfilter->dlist[in].name) != 0) { - afi_header_vty_out( - vty, afi, safi, write, - " neighbor %s distribute-list %s in\n", addr, - filter->dlist[in].name); + vty_out(vty, " neighbor %s distribute-list %s in\n", + addr, filter->dlist[in].name); } if (filter->dlist[out].name && !gfilter) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s distribute-list %s out\n", - addr, filter->dlist[out].name); + vty_out(vty, " neighbor %s distribute-list %s out\n", addr, + filter->dlist[out].name); } /* prefix-list. */ @@ -6227,19 +6218,17 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer, if (!gfilter || !gfilter->plist[in].name || strcmp(filter->plist[in].name, gfilter->plist[in].name) != 0) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s prefix-list %s in\n", - addr, filter->plist[in].name); + vty_out(vty, " neighbor %s prefix-list %s in\n", addr, + filter->plist[in].name); } - if (filter->plist[out].name) - if (!gfilter || !gfilter->plist[out].name - || strcmp(filter->plist[out].name, gfilter->plist[out].name) - != 0) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s prefix-list %s out\n", - addr, filter->plist[out].name); - } + if (filter->plist[out].name) + if (!gfilter || !gfilter->plist[out].name + || strcmp(filter->plist[out].name, gfilter->plist[out].name) + != 0) { + vty_out(vty, " neighbor %s prefix-list %s out\n", addr, + filter->plist[out].name); + } /* route-map. */ if (filter->map[RMAP_IN].name) @@ -6247,9 +6236,8 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer, || strcmp(filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s route-map %s in\n", - addr, filter->map[RMAP_IN].name); + vty_out(vty, " neighbor %s route-map %s in\n", addr, + filter->map[RMAP_IN].name); } if (filter->map[RMAP_OUT].name) @@ -6257,16 +6245,14 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer, || strcmp(filter->map[RMAP_OUT].name, gfilter->map[RMAP_OUT].name) != 0) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s route-map %s out\n", - addr, filter->map[RMAP_OUT].name); + vty_out(vty, " neighbor %s route-map %s out\n", addr, + filter->map[RMAP_OUT].name); } /* unsuppress-map */ if (filter->usmap.name && !gfilter) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s unsuppress-map %s\n", addr, - filter->usmap.name); + vty_out(vty, " neighbor %s unsuppress-map %s\n", addr, + filter->usmap.name); } /* filter-list. */ @@ -6274,15 +6260,13 @@ static void bgp_config_write_filter(struct vty *vty, struct peer *peer, if (!gfilter || !gfilter->aslist[in].name || strcmp(filter->aslist[in].name, gfilter->aslist[in].name) != 0) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s filter-list %s in\n", - addr, filter->aslist[in].name); + vty_out(vty, " neighbor %s filter-list %s in\n", addr, + filter->aslist[in].name); } if (filter->aslist[out].name && !gfilter) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s filter-list %s out\n", addr, - filter->aslist[out].name); + vty_out(vty, " neighbor %s filter-list %s out\n", addr, + filter->aslist[out].name); } } @@ -6602,8 +6586,7 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp, /* BGP peer configuration display function. */ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, - struct peer *peer, afi_t afi, safi_t safi, - int *write) + struct peer *peer, afi_t afi, safi_t safi) { struct peer *g_peer = NULL; char *addr; @@ -6626,36 +6609,29 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, /* If the peer-group is active but peer is not, print a 'no * activate' */ if (g_peer->afc[afi][safi] && !peer->afc[afi][safi]) { - afi_header_vty_out(vty, afi, safi, write, - " no neighbor %s activate\n", addr); + vty_out(vty, " no neighbor %s activate\n", addr); } /* If the peer-group is not active but peer is, print an 'activate' */ else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi]) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s activate\n", addr); + vty_out(vty, " neighbor %s activate\n", addr); } } else { if (peer->afc[afi][safi]) { if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) { if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4)) { - afi_header_vty_out( - vty, afi, safi, write, - " neighbor %s activate\n", + vty_out(vty, " neighbor %s activate\n", addr); } } else - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s activate\n", - addr); + vty_out(vty, " neighbor %s activate\n", addr); } else { if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) { if (!bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4)) { - afi_header_vty_out( - vty, afi, safi, write, + vty_out(vty, " no neighbor %s activate\n", addr); } @@ -6666,25 +6642,20 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, /* addpath TX knobs */ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ADDPATH_TX_ALL_PATHS)) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s addpath-tx-all-paths\n", - addr); + vty_out(vty, " neighbor %s addpath-tx-all-paths\n", addr); } if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s addpath-tx-bestpath-per-AS\n", - addr); + vty_out(vty, " neighbor %s addpath-tx-bestpath-per-AS\n", + addr); } /* ORF capability. */ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) || peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM)) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s capability orf prefix-list", - addr); + vty_out(vty, " neighbor %s capability orf prefix-list", addr); if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) @@ -6702,57 +6673,46 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, /* Route reflector client. */ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s route-reflector-client\n", - addr); + vty_out(vty, " neighbor %s route-reflector-client\n", addr); } /* next-hop-self force */ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_FORCE_NEXTHOP_SELF)) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s next-hop-self force\n", addr); + vty_out(vty, " neighbor %s next-hop-self force\n", addr); } /* next-hop-self */ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s next-hop-self\n", addr); + vty_out(vty, " neighbor %s next-hop-self\n", addr); } /* remove-private-AS */ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) { - afi_header_vty_out( - vty, afi, safi, write, - " neighbor %s remove-private-AS all replace-AS\n", + vty_out(vty, " neighbor %s remove-private-AS all replace-AS\n", addr); } else if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) { - afi_header_vty_out( - vty, afi, safi, write, - " neighbor %s remove-private-AS replace-AS\n", addr); + vty_out(vty, " neighbor %s remove-private-AS replace-AS\n", + addr); } else if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s remove-private-AS all\n", - addr); + vty_out(vty, " neighbor %s remove-private-AS all\n", addr); } else if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s remove-private-AS\n", addr); + vty_out(vty, " neighbor %s remove-private-AS\n", addr); } /* as-override */ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s as-override\n", addr); + vty_out(vty, " neighbor %s as-override\n", addr); } /* send-community print. */ @@ -6764,27 +6724,21 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, && peergroup_af_flag_check( peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY)) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s send-community all\n", - addr); + vty_out(vty, " neighbor %s send-community all\n", + addr); } else if (peergroup_af_flag_check( peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY)) { - afi_header_vty_out( - vty, afi, safi, write, - " neighbor %s send-community large\n", addr); + vty_out(vty, " neighbor %s send-community large\n", + addr); } else if (peergroup_af_flag_check( peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)) { - afi_header_vty_out( - vty, afi, safi, write, - " neighbor %s send-community extended\n", + vty_out(vty, " neighbor %s send-community extended\n", addr); } else if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s send-community\n", - addr); + vty_out(vty, " neighbor %s send-community\n", addr); } } else { if (!peer_af_flag_check(peer, afi, safi, @@ -6801,9 +6755,8 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, && (!g_peer || peer_af_flag_check( g_peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY))) { - afi_header_vty_out( - vty, afi, safi, write, - " no neighbor %s send-community all\n", addr); + vty_out(vty, " no neighbor %s send-community all\n", + addr); } else { if (!peer_af_flag_check(peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY) @@ -6811,8 +6764,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, || peer_af_flag_check( g_peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY))) { - afi_header_vty_out( - vty, afi, safi, write, + vty_out(vty, " no neighbor %s send-community large\n", addr); } @@ -6823,8 +6775,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, || peer_af_flag_check( g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))) { - afi_header_vty_out( - vty, afi, safi, write, + vty_out(vty, " no neighbor %s send-community extended\n", addr); } @@ -6834,8 +6785,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, && (!g_peer || peer_af_flag_check( g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))) { - afi_header_vty_out( - vty, afi, safi, write, + vty_out(vty, " no neighbor %s send-community\n", addr); } @@ -6853,8 +6803,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, || (peer->default_rmap[afi][safi].name && strcmp(peer->default_rmap[afi][safi].name, g_peer->default_rmap[afi][safi].name))))) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s default-originate", addr); + vty_out(vty, " neighbor %s default-originate", addr); if (peer->default_rmap[afi][safi].name) vty_out(vty, " route-map %s", peer->default_rmap[afi][safi].name); @@ -6863,9 +6812,8 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, /* Soft reconfiguration inbound. */ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) { - afi_header_vty_out( - vty, afi, safi, write, - " neighbor %s soft-reconfiguration inbound\n", addr); + vty_out(vty, " neighbor %s soft-reconfiguration inbound\n", + addr); } /* maximum-prefix. */ @@ -6878,9 +6826,8 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, PEER_FLAG_MAX_PREFIX_WARNING) != CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s maximum-prefix %lu", - addr, peer->pmax[afi][safi]); + vty_out(vty, " neighbor %s maximum-prefix %lu", addr, + peer->pmax[afi][safi]); if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT) vty_out(vty, " %u", @@ -6897,16 +6844,13 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, /* Route server client. */ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_RSERVER_CLIENT)) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s route-server-client\n", addr); + vty_out(vty, " neighbor %s route-server-client\n", addr); } /* Nexthop-local unchanged. */ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s nexthop-local unchanged\n", - addr); + vty_out(vty, " neighbor %s nexthop-local unchanged\n", addr); } /* allowas-in <1-10> */ @@ -6917,14 +6861,11 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi]) { if (peer->allowas_in[afi][safi] == 3) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s allowas-in\n", - addr); + vty_out(vty, " neighbor %s allowas-in\n", + addr); } else { - afi_header_vty_out( - vty, afi, safi, write, - " neighbor %s allowas-in %d\n", addr, - peer->allowas_in[afi][safi]); + vty_out(vty, " neighbor %s allowas-in %d\n", + addr, peer->allowas_in[afi][safi]); } } } @@ -6935,9 +6876,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, if (!peer_group_active(peer) || !peer_af_flag_check(g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN)) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s allowas-in origin\n", - addr); + vty_out(vty, " neighbor %s allowas-in origin\n", addr); } } @@ -6947,15 +6886,13 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, || !peer_af_flag_check(g_peer, afi, safi, PEER_FLAG_WEIGHT) || peer->weight[afi][safi] != g_peer->weight[afi][safi]) { if (peer->weight[afi][safi]) { - afi_header_vty_out(vty, afi, safi, write, - " neighbor %s weight %lu\n", - addr, - peer->weight[afi][safi]); + vty_out(vty, " neighbor %s weight %lu\n", addr, + peer->weight[afi][safi]); } } /* Filter. */ - bgp_config_write_filter(vty, peer, afi, safi, write); + bgp_config_write_filter(vty, peer, afi, safi); /* atribute-unchanged. */ if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) || @@ -6970,8 +6907,7 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_MED_UNCHANGED)) { - afi_header_vty_out( - vty, afi, safi, write, + vty_out(vty, " neighbor %s attribute-unchanged%s%s%s\n", addr, peer_af_flag_check( @@ -6992,64 +6928,52 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp, } } -/* Display "address-family" configuration header. */ -void bgp_config_write_family_header(struct vty *vty, afi_t afi, safi_t safi, - int *write) -{ - if (*write) - return; - - vty_out(vty, " !\n address-family "); - - if (afi == AFI_IP) { - if (safi == SAFI_UNICAST) - vty_out(vty, "ipv4 unicast"); - else if (safi == SAFI_LABELED_UNICAST) - vty_out(vty, "ipv4 labeled-unicast"); - else if (safi == SAFI_MULTICAST) - vty_out(vty, "ipv4 multicast"); - else if (safi == SAFI_MPLS_VPN) - vty_out(vty, "ipv4 vpn"); - else if (safi == SAFI_ENCAP) - vty_out(vty, "ipv4 encap"); - } else if (afi == AFI_IP6) { - if (safi == SAFI_UNICAST) - vty_out(vty, "ipv6 unicast"); - else if (safi == SAFI_LABELED_UNICAST) - vty_out(vty, "ipv6 labeled-unicast"); - else if (safi == SAFI_MULTICAST) - vty_out(vty, "ipv6 multicast"); - else if (safi == SAFI_MPLS_VPN) - vty_out(vty, "ipv6 vpn"); - else if (safi == SAFI_ENCAP) - vty_out(vty, "ipv6 encap"); - } else if (afi == AFI_L2VPN) { - if (safi == SAFI_EVPN) - vty_out(vty, "l2vpn evpn"); - } - vty_out(vty, "\n"); - - *write = 1; -} - /* Address family based peer configuration display. */ -static int bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi, - safi_t safi) +static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi, + safi_t safi) { - int write = 0; struct peer *peer; struct peer_group *group; struct listnode *node, *nnode; - bgp_config_write_distance(vty, bgp, afi, safi, &write); - bgp_config_write_network(vty, bgp, afi, safi, &write); + vty_frame(vty, " !\n address-family "); + if (afi == AFI_IP) { + if (safi == SAFI_UNICAST) + vty_frame(vty, "ipv4 unicast"); + else if (safi == SAFI_LABELED_UNICAST) + vty_frame(vty, "ipv4 labeled-unicast"); + else if (safi == SAFI_MULTICAST) + vty_frame(vty, "ipv4 multicast"); + else if (safi == SAFI_MPLS_VPN) + vty_frame(vty, "ipv4 vpn"); + else if (safi == SAFI_ENCAP) + vty_frame(vty, "ipv4 encap"); + } else if (afi == AFI_IP6) { + if (safi == SAFI_UNICAST) + vty_frame(vty, "ipv6 unicast"); + else if (safi == SAFI_LABELED_UNICAST) + vty_frame(vty, "ipv6 labeled-unicast"); + else if (safi == SAFI_MULTICAST) + vty_frame(vty, "ipv6 multicast"); + else if (safi == SAFI_MPLS_VPN) + vty_frame(vty, "ipv6 vpn"); + else if (safi == SAFI_ENCAP) + vty_frame(vty, "ipv6 encap"); + } else if (afi == AFI_L2VPN) { + if (safi == SAFI_EVPN) + vty_frame(vty, "l2vpn evpn"); + } + vty_frame(vty, "\n"); - bgp_config_write_redistribute(vty, bgp, afi, safi, &write); + bgp_config_write_distance(vty, bgp, afi, safi); + + bgp_config_write_network(vty, bgp, afi, safi); + + bgp_config_write_redistribute(vty, bgp, afi, safi); for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) - bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi, - &write); + bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi); for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { /* Skip dynamic neighbors. */ @@ -7058,20 +6982,16 @@ static int bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi, /* Do not display doppelganger peers */ if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) - bgp_config_write_peer_af(vty, bgp, peer, afi, safi, - &write); + bgp_config_write_peer_af(vty, bgp, peer, afi, safi); } - bgp_config_write_maxpaths(vty, bgp, afi, safi, &write); - bgp_config_write_table_map(vty, bgp, afi, safi, &write); + bgp_config_write_maxpaths(vty, bgp, afi, safi); + bgp_config_write_table_map(vty, bgp, afi, safi); if (safi == SAFI_EVPN) - bgp_config_write_evpn_info(vty, bgp, afi, safi, &write); + bgp_config_write_evpn_info(vty, bgp, afi, safi); - if (write) - vty_out(vty, " exit-address-family\n"); - - return write; + vty_endframe(vty, " exit-address-family\n"); } int bgp_config_write(struct vty *vty) @@ -7099,11 +7019,11 @@ int bgp_config_write(struct vty *vty) vty_out(vty, "bgp route-map delay-timer %u\n", bm->rmap_update_timer); + if (write) + vty_out(vty, "!\n"); + /* BGP configuration. */ for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { - if (write) - vty_out(vty, "!\n"); - /* Router bgp ASN */ vty_out(vty, "router bgp %u", bgp->as); @@ -7323,54 +7243,46 @@ int bgp_config_write(struct vty *vty) vty_out(vty, " no auto-summary\n"); /* IPv4 unicast configuration. */ - write += - bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST); + bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST); /* IPv4 multicast configuration. */ - write += bgp_config_write_family(vty, bgp, AFI_IP, - SAFI_MULTICAST); + bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MULTICAST); /* IPv4 labeled-unicast configuration. */ - write += bgp_config_write_family(vty, bgp, AFI_IP, - SAFI_LABELED_UNICAST); + bgp_config_write_family(vty, bgp, AFI_IP, SAFI_LABELED_UNICAST); /* IPv4 VPN configuration. */ - write += bgp_config_write_family(vty, bgp, AFI_IP, - SAFI_MPLS_VPN); + bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MPLS_VPN); /* ENCAPv4 configuration. */ - write += bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP); + bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP); /* IPv6 unicast configuration. */ - write += bgp_config_write_family(vty, bgp, AFI_IP6, - SAFI_UNICAST); + bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_UNICAST); /* IPv6 multicast configuration. */ - write += bgp_config_write_family(vty, bgp, AFI_IP6, - SAFI_MULTICAST); + bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MULTICAST); /* IPv6 labeled-unicast configuration. */ - write += bgp_config_write_family(vty, bgp, AFI_IP6, - SAFI_LABELED_UNICAST); + bgp_config_write_family(vty, bgp, AFI_IP6, + SAFI_LABELED_UNICAST); /* IPv6 VPN configuration. */ - write += bgp_config_write_family(vty, bgp, AFI_IP6, - SAFI_MPLS_VPN); + bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MPLS_VPN); /* ENCAPv6 configuration. */ - write += bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP); + bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP); /* EVPN configuration. */ - write += - bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN); + bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN); #if ENABLE_BGP_VNC - write += bgp_rfapi_cfg_write(vty, bgp); + bgp_rfapi_cfg_write(vty, bgp); #endif - write++; + vty_out(vty, "!\n"); } - return write; + return 0; } void bgp_master_init(struct thread_master *master) diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 5ede9ba13d..610fc7aea1 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1234,7 +1234,6 @@ extern void peer_xfer_config(struct peer *dst, struct peer *src); extern char *peer_uptime(time_t, char *, size_t, u_char, json_object *); extern int bgp_config_write(struct vty *); -extern void bgp_config_write_family_header(struct vty *, afi_t, safi_t, int *); extern void bgp_master_init(struct thread_master *master); From ea47320b1d0eeaa56f945fa356da7e4ca7f2b0b2 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Sun, 27 Aug 2017 22:51:35 +0200 Subject: [PATCH 8/9] bgpd: remove some deep nesting Some of this was so egregiously stupid, I couldn't look at it without gouging my eyes out... Signed-off-by: David Lamparter --- bgpd/bgp_evpn_vty.c | 285 +++++++------- bgpd/bgp_route.c | 903 +++++++++++++++++++++----------------------- bgpd/bgp_vty.c | 643 +++++++++++++++---------------- 3 files changed, 900 insertions(+), 931 deletions(-) diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 1467083c01..809ffa72ce 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -375,155 +375,150 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd, if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) continue; - if ((table = rn->info) != NULL) { - rd_header = 1; + if ((table = rn->info) == NULL) + continue; - for (rm = bgp_table_top(table); rm; - rm = bgp_route_next(rm)) - for (ri = rm->info; ri; ri = ri->next) { - total_count++; - if (type == bgp_show_type_neighbor) { - union sockunion *su = - output_arg; + rd_header = 1; - if (ri->peer->su_remote == NULL - || !sockunion_same( - ri->peer->su_remote, - su)) - continue; - } - if (header == 0) { - if (use_json) { - if (option - == SHOW_DISPLAY_TAGS) { - json_object_int_add( - json, - "bgpTableVersion", - 0); - json_object_string_add( - json, - "bgpLocalRouterId", - inet_ntoa( - bgp->router_id)); - json_object_object_add( - json, - "bgpStatusCodes", - json_scode); - json_object_object_add( - json, - "bgpOriginCodes", - json_ocode); - } - } else { - if (option - == SHOW_DISPLAY_TAGS) - vty_out(vty, - V4_HEADER_TAG); - else if ( - option - == SHOW_DISPLAY_OVERLAY) - vty_out(vty, - V4_HEADER_OVERLAY); - else { - vty_out(vty, - "BGP table version is 0, local router ID is %s\n", - inet_ntoa( - bgp->router_id)); - vty_out(vty, - "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n"); - vty_out(vty, - "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"); - vty_out(vty, - V4_HEADER); - } - } - header = 0; - } - if (rd_header) { - u_int16_t type; - struct rd_as rd_as; - struct rd_ip rd_ip; - u_char *pnt; + for (rm = bgp_table_top(table); rm; + rm = bgp_route_next(rm)) + for (ri = rm->info; ri; ri = ri->next) { + total_count++; + if (type == bgp_show_type_neighbor) { + union sockunion *su = + output_arg; - pnt = rn->p.u.val; - - /* Decode RD type. */ - type = decode_rd_type(pnt); - /* Decode RD value. */ - if (type == RD_TYPE_AS) - decode_rd_as(pnt + 2, - &rd_as); - else if (type == RD_TYPE_AS4) - decode_rd_as4(pnt + 2, - &rd_as); - else if (type == RD_TYPE_IP) - decode_rd_ip(pnt + 2, - &rd_ip); - if (use_json) { - char buffer[BUFSIZ]; - if (type == RD_TYPE_AS - || type == RD_TYPE_AS4) - sprintf(buffer, - "%u:%d", - rd_as.as, - rd_as.val); - else if (type - == RD_TYPE_IP) - sprintf(buffer, - "%s:%d", - inet_ntoa( - rd_ip.ip), - rd_ip.val); - json_object_string_add( - json_nroute, - "routeDistinguisher", - buffer); - } else { - vty_out(vty, - "Route Distinguisher: "); - if (type == RD_TYPE_AS) - vty_out(vty, - "as2 %u:%d", - rd_as.as, - rd_as.val); - else if (type - == RD_TYPE_AS4) - vty_out(vty, - "as4 %u:%d", - rd_as.as, - rd_as.val); - else if (type - == RD_TYPE_IP) - vty_out(vty, - "ip %s:%d", - inet_ntoa( - rd_ip.ip), - rd_ip.val); - vty_out(vty, "\n\n"); - } - rd_header = 0; - } - if (use_json) - json_array = - json_object_new_array(); - else - json_array = NULL; - if (option == SHOW_DISPLAY_TAGS) - route_vty_out_tag( - vty, &rm->p, ri, 0, - SAFI_EVPN, json_array); - else if (option == SHOW_DISPLAY_OVERLAY) - route_vty_out_overlay( - vty, &rm->p, ri, 0, - json_array); - else - route_vty_out(vty, &rm->p, ri, - 0, SAFI_EVPN, - json_array); - output_count++; + if (ri->peer->su_remote == NULL + || !sockunion_same( + ri->peer->su_remote, + su)) + continue; } - /* XXX json */ - } + if (header == 0) { + if (use_json) { + if (option + == SHOW_DISPLAY_TAGS) { + json_object_int_add( + json, + "bgpTableVersion", + 0); + json_object_string_add( + json, + "bgpLocalRouterId", + inet_ntoa( + bgp->router_id)); + json_object_object_add( + json, + "bgpStatusCodes", + json_scode); + json_object_object_add( + json, + "bgpOriginCodes", + json_ocode); + } + } else { + if (option + == SHOW_DISPLAY_TAGS) + vty_out(vty, + V4_HEADER_TAG); + else if ( + option + == SHOW_DISPLAY_OVERLAY) + vty_out(vty, + V4_HEADER_OVERLAY); + else { + vty_out(vty, + "BGP table version is 0, local router ID is %s\n", + inet_ntoa( + bgp->router_id)); + vty_out(vty, + "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n"); + vty_out(vty, + "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n"); + vty_out(vty, + V4_HEADER); + } + } + header = 0; + } + if (rd_header) { + u_int16_t type; + struct rd_as rd_as; + struct rd_ip rd_ip; + u_char *pnt; + + pnt = rn->p.u.val; + + /* Decode RD type. */ + type = decode_rd_type(pnt); + /* Decode RD value. */ + if (type == RD_TYPE_AS) + decode_rd_as(pnt + 2, &rd_as); + else if (type == RD_TYPE_AS4) + decode_rd_as4(pnt + 2, &rd_as); + else if (type == RD_TYPE_IP) + decode_rd_ip(pnt + 2, &rd_ip); + if (use_json) { + char buffer[BUFSIZ]; + if (type == RD_TYPE_AS + || type == RD_TYPE_AS4) + sprintf(buffer, + "%u:%d", + rd_as.as, + rd_as.val); + else if (type + == RD_TYPE_IP) + sprintf(buffer, + "%s:%d", + inet_ntoa( + rd_ip.ip), + rd_ip.val); + json_object_string_add( + json_nroute, + "routeDistinguisher", + buffer); + } else { + vty_out(vty, + "Route Distinguisher: "); + if (type == RD_TYPE_AS) + vty_out(vty, + "as2 %u:%d", + rd_as.as, + rd_as.val); + else if (type + == RD_TYPE_AS4) + vty_out(vty, + "as4 %u:%d", + rd_as.as, + rd_as.val); + else if (type + == RD_TYPE_IP) + vty_out(vty, + "ip %s:%d", + inet_ntoa( + rd_ip.ip), + rd_ip.val); + vty_out(vty, "\n\n"); + } + rd_header = 0; + } + if (use_json) + json_array = json_object_new_array(); + else + json_array = NULL; + if (option == SHOW_DISPLAY_TAGS) + route_vty_out_tag(vty, &rm->p, ri, 0, + SAFI_EVPN, + json_array); + else if (option == SHOW_DISPLAY_OVERLAY) + route_vty_out_overlay(vty, &rm->p, ri, + 0, json_array); + else + route_vty_out(vty, &rm->p, ri, 0, + SAFI_EVPN, json_array); + output_count++; + } + /* XXX json */ } if (output_count == 0) vty_out(vty, "No prefixes displayed, %ld exist\n", total_count); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 814efdb4e6..a2097f461e 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -3391,21 +3391,22 @@ static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi, for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) for (ain = rn->adj_in; ain; ain = ain->next) { - if (ain->peer == peer) { - struct bgp_info *ri = rn->info; - mpls_label_t label = - (ri && ri->extra) ? ri->extra->label - : MPLS_INVALID_LABEL; + if (ain->peer != peer) + continue; - ret = bgp_update( - peer, &rn->p, ain->addpath_rx_id, - ain->attr, afi, safi, ZEBRA_ROUTE_BGP, - BGP_ROUTE_NORMAL, prd, &label, 1, NULL); + struct bgp_info *ri = rn->info; + mpls_label_t label = + (ri && ri->extra) ? ri->extra->label + : MPLS_INVALID_LABEL; - if (ret < 0) { - bgp_unlock_node(rn); - return; - } + ret = bgp_update(peer, &rn->p, ain->addpath_rx_id, + ain->attr, afi, safi, ZEBRA_ROUTE_BGP, + BGP_ROUTE_NORMAL, prd, &label, 1, + NULL); + + if (ret < 0) { + bgp_unlock_node(rn); + return; } } } @@ -3454,24 +3455,25 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data) /* It is possible that we have multiple paths for a prefix from a peer * if that peer is using AddPath. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == peer) { - /* graceful restart STALE flag set. */ - if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT) - && peer->nsf[afi][safi] - && !CHECK_FLAG(ri->flags, BGP_INFO_STALE) - && !CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) - bgp_info_set_flag(rn, ri, BGP_INFO_STALE); - else { - /* If this is an EVPN route, process for - * un-import. */ - if (safi == SAFI_EVPN) - bgp_evpn_unimport_route(peer->bgp, afi, - safi, &rn->p, - ri); - bgp_rib_remove(rn, ri, peer, afi, safi); - } + for (ri = rn->info; ri; ri = ri->next) { + if (ri->peer != peer) + continue; + + /* graceful restart STALE flag set. */ + if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT) + && peer->nsf[afi][safi] + && !CHECK_FLAG(ri->flags, BGP_INFO_STALE) + && !CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) + bgp_info_set_flag(rn, ri, BGP_INFO_STALE); + else { + /* If this is an EVPN route, process for + * un-import. */ + if (safi == SAFI_EVPN) + bgp_evpn_unimport_route(peer->bgp, afi, safi, + &rn->p, ri); + bgp_rib_remove(rn, ri, peer, afi, safi); } + } return WQ_SUCCESS; } @@ -3705,34 +3707,33 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi) struct bgp_info *ri; /* look for neighbor in tables */ - if ((table = rn->info) != NULL) { - for (rm = bgp_table_top(table); rm; - rm = bgp_route_next(rm)) - for (ri = rm->info; ri; ri = ri->next) - if (ri->peer == peer) { - if (CHECK_FLAG( - ri->flags, - BGP_INFO_STALE)) - bgp_rib_remove( - rm, ri, - peer, - afi, - safi); - break; - } - } + if ((table = rn->info) == NULL) + continue; + + for (rm = bgp_table_top(table); rm; + rm = bgp_route_next(rm)) + for (ri = rm->info; ri; ri = ri->next) { + if (ri->peer != peer) + continue; + if (!CHECK_FLAG(ri->flags, + BGP_INFO_STALE)) + break; + + bgp_rib_remove(rm, ri, peer, afi, safi); + break; + } } } else { for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn; rn = bgp_route_next(rn)) - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == peer) { - if (CHECK_FLAG(ri->flags, - BGP_INFO_STALE)) - bgp_rib_remove(rn, ri, peer, - afi, safi); + for (ri = rn->info; ri; ri = ri->next) { + if (ri->peer != peer) + continue; + if (!CHECK_FLAG(ri->flags, BGP_INFO_STALE)) break; - } + bgp_rib_remove(rn, ri, peer, afi, safi); + break; + } } } @@ -4556,28 +4557,30 @@ void bgp_static_add(struct bgp *bgp) for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) for (rn = bgp_table_top(bgp->route[afi][safi]); rn; - rn = bgp_route_next(rn)) - if (rn->info != NULL) { - if ((safi == SAFI_MPLS_VPN) - || (safi == SAFI_ENCAP) - || (safi == SAFI_EVPN)) { - table = rn->info; + rn = bgp_route_next(rn)) { + if (rn->info == NULL) + continue; - for (rm = bgp_table_top(table); - rm; - rm = bgp_route_next(rm)) { - bgp_static = rm->info; - bgp_static_update_safi( - bgp, &rm->p, - bgp_static, afi, - safi); - } - } else { - bgp_static_update(bgp, &rn->p, - rn->info, afi, - safi); + if ((safi == SAFI_MPLS_VPN) + || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) { + table = rn->info; + + for (rm = bgp_table_top(table); + rm; + rm = bgp_route_next(rm)) { + bgp_static = rm->info; + bgp_static_update_safi( + bgp, &rm->p, + bgp_static, afi, + safi); } + } else { + bgp_static_update(bgp, &rn->p, + rn->info, afi, + safi); } + } } /* Called from bgp_delete(). Delete all static routes from the BGP @@ -4594,37 +4597,38 @@ void bgp_static_delete(struct bgp *bgp) for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) for (rn = bgp_table_top(bgp->route[afi][safi]); rn; - rn = bgp_route_next(rn)) - if (rn->info != NULL) { - if ((safi == SAFI_MPLS_VPN) - || (safi == SAFI_ENCAP) - || (safi == SAFI_EVPN)) { - table = rn->info; + rn = bgp_route_next(rn)) { + if (rn->info == NULL) + continue; - for (rm = bgp_table_top(table); - rm; - rm = bgp_route_next(rm)) { - bgp_static = rm->info; - bgp_static_withdraw_safi( - bgp, &rm->p, - AFI_IP, safi, - (struct - prefix_rd *)&rn - ->p); - bgp_static_free( - bgp_static); - rn->info = NULL; - bgp_unlock_node(rn); - } - } else { - bgp_static = rn->info; - bgp_static_withdraw(bgp, &rn->p, - afi, safi); + if ((safi == SAFI_MPLS_VPN) + || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) { + table = rn->info; + + for (rm = bgp_table_top(table); + rm; + rm = bgp_route_next(rm)) { + bgp_static = rm->info; + bgp_static_withdraw_safi( + bgp, &rm->p, + AFI_IP, safi, + (struct + prefix_rd *)&rn + ->p); bgp_static_free(bgp_static); rn->info = NULL; bgp_unlock_node(rn); } + } else { + bgp_static = rn->info; + bgp_static_withdraw(bgp, &rn->p, + afi, safi); + bgp_static_free(bgp_static); + rn->info = NULL; + bgp_unlock_node(rn); } + } } void bgp_static_redo_import_check(struct bgp *bgp) @@ -4641,29 +4645,31 @@ void bgp_static_redo_import_check(struct bgp *bgp) for (afi = AFI_IP; afi < AFI_MAX; afi++) for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) for (rn = bgp_table_top(bgp->route[afi][safi]); rn; - rn = bgp_route_next(rn)) - if (rn->info != NULL) { - if ((safi == SAFI_MPLS_VPN) - || (safi == SAFI_ENCAP) - || (safi == SAFI_EVPN)) { - table = rn->info; + rn = bgp_route_next(rn)) { + if (rn->info == NULL) + continue; - for (rm = bgp_table_top(table); - rm; - rm = bgp_route_next(rm)) { - bgp_static = rm->info; - bgp_static_update_safi( - bgp, &rm->p, - bgp_static, afi, - safi); - } - } else { - bgp_static = rn->info; - bgp_static_update(bgp, &rn->p, - bgp_static, - afi, safi); + if ((safi == SAFI_MPLS_VPN) + || (safi == SAFI_ENCAP) + || (safi == SAFI_EVPN)) { + table = rn->info; + + for (rm = bgp_table_top(table); + rm; + rm = bgp_route_next(rm)) { + bgp_static = rm->info; + bgp_static_update_safi( + bgp, &rm->p, + bgp_static, afi, + safi); } + } else { + bgp_static = rn->info; + bgp_static_update(bgp, &rn->p, + bgp_static, + afi, safi); } + } bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS); } @@ -5684,83 +5690,76 @@ static void bgp_aggregate_add(struct bgp *bgp, struct prefix *p, afi_t afi, /* If routes exists below this node, generate aggregate routes. */ top = bgp_node_get(table, p); for (rn = bgp_node_get(table, p); rn; - rn = bgp_route_next_until(rn, top)) - if (rn->p.prefixlen > p->prefixlen) { - match = 0; + rn = bgp_route_next_until(rn, top)) { + if (rn->p.prefixlen <= p->prefixlen) + continue; - for (ri = rn->info; ri; ri = ri->next) { - if (BGP_INFO_HOLDDOWN(ri)) - continue; + match = 0; - if (ri->attr->flag - & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) - atomic_aggregate = 1; + for (ri = rn->info; ri; ri = ri->next) { + if (BGP_INFO_HOLDDOWN(ri)) + continue; - if (ri->sub_type != BGP_ROUTE_AGGREGATE) { - /* summary-only aggregate route suppress - aggregated - route announcement. */ - if (aggregate->summary_only) { - (bgp_info_extra_get(ri)) - ->suppress++; - bgp_info_set_flag( - rn, ri, - BGP_INFO_ATTR_CHANGED); - match++; - } + if (ri->attr->flag + & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) + atomic_aggregate = 1; - /* If at least one route among routes - * that are aggregated has - * ORIGIN with the value INCOMPLETE, - * then the aggregated route - * MUST have the ORIGIN attribute with - * the value INCOMPLETE. - * Otherwise, if at least one route - * among routes that are - * aggregated has ORIGIN with the value - * EGP, then the aggregated - * route MUST have the ORIGIN attribute - * with the value EGP. - */ - if (origin < ri->attr->origin) - origin = ri->attr->origin; + if (ri->sub_type == BGP_ROUTE_AGGREGATE) + continue; - /* as-set aggregate route generate - origin, as path, - community aggregation. */ - if (aggregate->as_set) { - if (aspath) { - asmerge = aspath_aggregate( - aspath, - ri->attr->aspath); - aspath_free(aspath); - aspath = asmerge; - } else - aspath = aspath_dup( - ri->attr->aspath); - - if (ri->attr->community) { - if (community) { - commerge = community_merge( - community, - ri->attr->community); - community = community_uniq_sort( - commerge); - community_free( - commerge); - } else - community = community_dup( - ri->attr->community); - } - } - aggregate->count++; - } + /* summary-only aggregate route suppress + * aggregated route announcement. */ + if (aggregate->summary_only) { + (bgp_info_extra_get(ri))->suppress++; + bgp_info_set_flag(rn, ri, + BGP_INFO_ATTR_CHANGED); + match++; } - /* If this node is suppressed, process the change. */ - if (match) - bgp_process(bgp, rn, afi, safi); + /* If at least one route among routes that are + * aggregated has ORIGIN with the value INCOMPLETE, + * then the aggregated route MUST have the ORIGIN + * attribute with the value INCOMPLETE. Otherwise, if + * at least one route among routes that are aggregated + * has ORIGIN with the value EGP, then the aggregated + * route MUST have the ORIGIN attribute with the value + * EGP. + */ + if (origin < ri->attr->origin) + origin = ri->attr->origin; + + /* as-set aggregate route generate origin, as path, + * community aggregation. */ + if (aggregate->as_set) { + if (aspath) { + asmerge = aspath_aggregate(aspath, + ri->attr->aspath); + aspath_free(aspath); + aspath = asmerge; + } else + aspath = aspath_dup(ri->attr->aspath); + + if (ri->attr->community) { + if (community) { + commerge = community_merge( + community, + ri->attr->community); + community = community_uniq_sort( + commerge); + community_free( + commerge); + } else + community = community_dup( + ri->attr->community); + } + } + aggregate->count++; } + + /* If this node is suppressed, process the change. */ + if (match) + bgp_process(bgp, rn, afi, safi); + } bgp_unlock_node(top); /* Add aggregate route to BGP table. */ @@ -5806,34 +5805,34 @@ void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi, /* If routes exists below this node, generate aggregate routes. */ top = bgp_node_get(table, p); for (rn = bgp_node_get(table, p); rn; - rn = bgp_route_next_until(rn, top)) - if (rn->p.prefixlen > p->prefixlen) { - match = 0; + rn = bgp_route_next_until(rn, top)) { + if (rn->p.prefixlen <= p->prefixlen) + continue; + match = 0; - for (ri = rn->info; ri; ri = ri->next) { - if (BGP_INFO_HOLDDOWN(ri)) - continue; + for (ri = rn->info; ri; ri = ri->next) { + if (BGP_INFO_HOLDDOWN(ri)) + continue; - if (ri->sub_type != BGP_ROUTE_AGGREGATE) { - if (aggregate->summary_only - && ri->extra) { - ri->extra->suppress--; + if (ri->sub_type == BGP_ROUTE_AGGREGATE) + continue; - if (ri->extra->suppress == 0) { - bgp_info_set_flag( - rn, ri, - BGP_INFO_ATTR_CHANGED); - match++; - } - } - aggregate->count--; + if (aggregate->summary_only && ri->extra) { + ri->extra->suppress--; + + if (ri->extra->suppress == 0) { + bgp_info_set_flag(rn, ri, + BGP_INFO_ATTR_CHANGED); + match++; } } - - /* If this node was suppressed, process the change. */ - if (match) - bgp_process(bgp, rn, afi, safi); + aggregate->count--; } + + /* If this node was suppressed, process the change. */ + if (match) + bgp_process(bgp, rn, afi, safi); + } bgp_unlock_node(top); /* Delete aggregate route from BGP table. */ @@ -8561,55 +8560,44 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) continue; - if ((table = rn->info) != NULL) { - header = 1; + if ((table = rn->info) == NULL) + continue; - if ((rm = bgp_node_match(table, &match)) - != NULL) { - if (prefix_check - && rm->p.prefixlen - != match.prefixlen) { - bgp_unlock_node(rm); - continue; - } + header = 1; - for (ri = rm->info; ri; ri = ri->next) { - if (header) { - route_vty_out_detail_header( - vty, bgp, rm, - (struct - prefix_rd *)&rn - ->p, - AFI_IP, safi, - json); - header = 0; - } - display++; + if ((rm = bgp_node_match(table, &match)) == NULL) + continue; - if (pathtype == BGP_PATH_ALL - || (pathtype - == BGP_PATH_BESTPATH - && CHECK_FLAG( - ri->flags, - BGP_INFO_SELECTED)) - || (pathtype - == BGP_PATH_MULTIPATH - && (CHECK_FLAG( - ri->flags, - BGP_INFO_MULTIPATH) - || CHECK_FLAG( - ri->flags, - BGP_INFO_SELECTED)))) - route_vty_out_detail( - vty, bgp, - &rm->p, ri, - AFI_IP, safi, - json_paths); - } - - bgp_unlock_node(rm); - } + if (prefix_check + && rm->p.prefixlen != match.prefixlen) { + bgp_unlock_node(rm); + continue; } + + for (ri = rm->info; ri; ri = ri->next) { + if (header) { + route_vty_out_detail_header(vty, bgp, + rm, (struct prefix_rd *)&rn->p, + AFI_IP, safi, json); + header = 0; + } + display++; + + if (pathtype == BGP_PATH_ALL + || (pathtype == BGP_PATH_BESTPATH + && CHECK_FLAG(ri->flags, + BGP_INFO_SELECTED)) + || (pathtype == BGP_PATH_MULTIPATH + && (CHECK_FLAG(ri->flags, + BGP_INFO_MULTIPATH) + || CHECK_FLAG(ri->flags, + BGP_INFO_SELECTED)))) + route_vty_out_detail(vty, bgp, &rm->p, + ri, AFI_IP, safi, + json_paths); + } + + bgp_unlock_node(rm); } } else { header = 1; @@ -9995,60 +9983,55 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { if (in) { for (ain = rn->adj_in; ain; ain = ain->next) { - if (ain->peer == peer) { - if (header1) { - if (use_json) { - json_object_int_add( - json, - "bgpTableVersion", - 0); - json_object_string_add( - json, - "bgpLocalRouterId", - inet_ntoa( - bgp->router_id)); - json_object_object_add( - json, - "bgpStatusCodes", - json_scode); - json_object_object_add( - json, - "bgpOriginCodes", - json_ocode); - } else { - vty_out(vty, - "BGP table version is 0, local router ID is %s\n", - inet_ntoa( - bgp->router_id)); - vty_out(vty, - BGP_SHOW_SCODE_HEADER); - vty_out(vty, - BGP_SHOW_OCODE_HEADER); - } - header1 = 0; - } - if (header2) { - if (!use_json) - vty_out(vty, - BGP_SHOW_HEADER); - header2 = 0; - } - if (ain->attr) { - bgp_attr_dup(&attr, ain->attr); - if (bgp_input_modifier( - peer, &rn->p, &attr, - afi, safi, - rmap_name) - != RMAP_DENY) { - route_vty_out_tmp( - vty, &rn->p, - &attr, safi, - use_json, - json_ar); - output_count++; - } else - filtered_count++; + if (ain->peer != peer) + continue; + if (header1) { + if (use_json) { + json_object_int_add( + json, + "bgpTableVersion", + 0); + json_object_string_add( + json, + "bgpLocalRouterId", + inet_ntoa( + bgp->router_id)); + json_object_object_add( + json, + "bgpStatusCodes", + json_scode); + json_object_object_add( + json, + "bgpOriginCodes", + json_ocode); + } else { + vty_out(vty, + "BGP table version is 0, local router ID is %s\n", + inet_ntoa( + bgp->router_id)); + vty_out(vty, + BGP_SHOW_SCODE_HEADER); + vty_out(vty, + BGP_SHOW_OCODE_HEADER); } + header1 = 0; + } + if (header2) { + if (!use_json) + vty_out(vty, BGP_SHOW_HEADER); + header2 = 0; + } + if (ain->attr) { + bgp_attr_dup(&attr, ain->attr); + if (bgp_input_modifier(peer, &rn->p, + &attr, afi, safi, rmap_name) + != RMAP_DENY) { + route_vty_out_tmp(vty, &rn->p, + &attr, safi, use_json, + json_ar); + output_count++; + } else + filtered_count++; } } } else { @@ -10856,32 +10839,27 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, rn = bgp_route_next(rn)) { if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0) continue; + if ((table = rn->info) == NULL) + continue; + if ((rm = bgp_node_match(table, &match)) == NULL) + continue; - if ((table = rn->info) != NULL) - if ((rm = bgp_node_match(table, &match)) - != NULL) { - if (!prefix_check - || rm->p.prefixlen - == match.prefixlen) { - ri = rm->info; - while (ri) { - if (ri->extra - && ri->extra - ->damp_info) { - ri_temp = - ri->next; - bgp_damp_info_free( - ri->extra - ->damp_info, - 1); - ri = ri_temp; - } else - ri = ri->next; - } - } - - bgp_unlock_node(rm); + if (!prefix_check + || rm->p.prefixlen == match.prefixlen) { + ri = rm->info; + while (ri) { + if (ri->extra + && ri->extra->damp_info) { + ri_temp = ri->next; + bgp_damp_info_free( + ri->extra->damp_info, 1); + ri = ri_temp; + } else + ri = ri->next; } + } + + bgp_unlock_node(rm); } } else { if ((rn = bgp_node_match(bgp->rib[afi][safi], &match)) @@ -10990,39 +10968,39 @@ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp, /* Network configuration. */ for (prn = bgp_table_top(bgp->route[afi][safi]); prn; - prn = bgp_route_next(prn)) - if ((table = prn->info) != NULL) - for (rn = bgp_table_top(table); rn; - rn = bgp_route_next(rn)) - if ((bgp_static = rn->info) != NULL) { - p = &rn->p; - prd = (struct prefix_rd *)&prn->p; + prn = bgp_route_next(prn)) { + if ((table = prn->info) == NULL) + continue; - /* "network" configuration display. */ - prefix_rd2str(prd, rdbuf, - RD_ADDRSTRLEN); - label = decode_label( - &bgp_static->label); + for (rn = bgp_table_top(table); rn; + rn = bgp_route_next(rn)) { + if ((bgp_static = rn->info) == NULL) + continue; - vty_out(vty, " network %s/%d rd %s", - inet_ntop(p->family, - &p->u.prefix, buf, - SU_ADDRSTRLEN), - p->prefixlen, rdbuf); - if (safi == SAFI_MPLS_VPN) - vty_out(vty, " label %u", - label); + p = &rn->p; + prd = (struct prefix_rd *)&prn->p; - if (bgp_static->rmap.name) - vty_out(vty, " route-map %s", - bgp_static->rmap.name); - else { - if (bgp_static->backdoor) - vty_out(vty, - " backdoor"); - } - vty_out(vty, "\n"); - } + /* "network" configuration display. */ + prefix_rd2str(prd, rdbuf, RD_ADDRSTRLEN); + label = decode_label(&bgp_static->label); + + vty_out(vty, " network %s/%d rd %s", + inet_ntop(p->family, &p->u.prefix, buf, + SU_ADDRSTRLEN), + p->prefixlen, rdbuf); + if (safi == SAFI_MPLS_VPN) + vty_out(vty, " label %u", label); + + if (bgp_static->rmap.name) + vty_out(vty, " route-map %s", + bgp_static->rmap.name); + else { + if (bgp_static->backdoor) + vty_out(vty, " backdoor"); + } + vty_out(vty, "\n"); + } + } } static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, @@ -11040,48 +11018,45 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp, /* Network configuration. */ for (prn = bgp_table_top(bgp->route[afi][safi]); prn; - prn = bgp_route_next(prn)) - if ((table = prn->info) != NULL) - for (rn = bgp_table_top(table); rn; - rn = bgp_route_next(rn)) - if ((bgp_static = rn->info) != NULL) { - char *macrouter = NULL; - char *esi = NULL; + prn = bgp_route_next(prn)) { + if ((table = prn->info) == NULL) + continue; - if (bgp_static->router_mac) - macrouter = prefix_mac2str( - bgp_static->router_mac, - NULL, 0); - if (bgp_static->eth_s_id) - esi = esi2str( - bgp_static->eth_s_id); - p = &rn->p; - prd = (struct prefix_rd *)&prn->p; + for (rn = bgp_table_top(table); rn; + rn = bgp_route_next(rn)) { + if ((bgp_static = rn->info) == NULL) + continue; - /* "network" configuration display. */ - prefix_rd2str(prd, rdbuf, - RD_ADDRSTRLEN); + char *macrouter = NULL; + char *esi = NULL; - inet_ntop(AF_INET, - &bgp_static->igpnexthop, buf2, - SU_ADDRSTRLEN); + if (bgp_static->router_mac) + macrouter = prefix_mac2str( + bgp_static->router_mac, NULL, 0); + if (bgp_static->eth_s_id) + esi = esi2str(bgp_static->eth_s_id); + p = &rn->p; + prd = (struct prefix_rd *)&prn->p; - prefix2str(p, buf, sizeof(buf)), - vty_out(vty, - " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s", - buf, rdbuf, - p->u.prefix_evpn - .eth_tag, - decode_label( - &bgp_static - ->label), - esi, buf2, macrouter); - vty_out(vty, "\n"); - if (macrouter) - XFREE(MTYPE_TMP, macrouter); - if (esi) - XFREE(MTYPE_TMP, esi); - } + /* "network" configuration display. */ + prefix_rd2str(prd, rdbuf, RD_ADDRSTRLEN); + + inet_ntop(AF_INET, &bgp_static->igpnexthop, buf2, + SU_ADDRSTRLEN); + + prefix2str(p, buf, sizeof(buf)); + vty_out(vty, + " network %s rd %s ethtag %u tag %u esi %s gwip %s routermac %s\n", + buf, rdbuf, p->u.prefix_evpn .eth_tag, + decode_label(&bgp_static ->label), esi, buf2, + macrouter); + + if (macrouter) + XFREE(MTYPE_TMP, macrouter); + if (esi) + XFREE(MTYPE_TMP, esi); + } + } } /* Configuration of static route announcement and aggregate @@ -11107,85 +11082,83 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi, /* Network configuration. */ for (rn = bgp_table_top(bgp->route[afi][safi]); rn; - rn = bgp_route_next(rn)) - if ((bgp_static = rn->info) != NULL) { - p = &rn->p; + rn = bgp_route_next(rn)) { + if ((bgp_static = rn->info) == NULL) + continue; - /* "network" configuration display. */ - if (bgp_option_check(BGP_OPT_CONFIG_CISCO) - && afi == AFI_IP) { - u_int32_t destination; - struct in_addr netmask; + p = &rn->p; - destination = ntohl(p->u.prefix4.s_addr); - masklen2ip(p->prefixlen, &netmask); - vty_out(vty, " network %s", - inet_ntop(p->family, &p->u.prefix, buf, - SU_ADDRSTRLEN)); + /* "network" configuration display. */ + if (bgp_option_check(BGP_OPT_CONFIG_CISCO) + && afi == AFI_IP) { + u_int32_t destination; + struct in_addr netmask; - if ((IN_CLASSC(destination) - && p->prefixlen == 24) - || (IN_CLASSB(destination) - && p->prefixlen == 16) - || (IN_CLASSA(destination) - && p->prefixlen == 8) - || p->u.prefix4.s_addr == 0) { - /* Natural mask is not display. */ - } else - vty_out(vty, " mask %s", - inet_ntoa(netmask)); - } else { - vty_out(vty, " network %s/%d", - inet_ntop(p->family, &p->u.prefix, buf, - SU_ADDRSTRLEN), - p->prefixlen); - } + destination = ntohl(p->u.prefix4.s_addr); + masklen2ip(p->prefixlen, &netmask); + vty_out(vty, " network %s", + inet_ntop(p->family, &p->u.prefix, buf, + SU_ADDRSTRLEN)); - if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) - vty_out(vty, " label-index %u", - bgp_static->label_index); - - if (bgp_static->rmap.name) - vty_out(vty, " route-map %s", - bgp_static->rmap.name); - else { - if (bgp_static->backdoor) - vty_out(vty, " backdoor"); - } - - vty_out(vty, "\n"); + if ((IN_CLASSC(destination) && p->prefixlen == 24) + || (IN_CLASSB(destination) && p->prefixlen == 16) + || (IN_CLASSA(destination) && p->prefixlen == 8) + || p->u.prefix4.s_addr == 0) { + /* Natural mask is not display. */ + } else + vty_out(vty, " mask %s", inet_ntoa(netmask)); + } else { + vty_out(vty, " network %s/%d", + inet_ntop(p->family, &p->u.prefix, buf, + SU_ADDRSTRLEN), + p->prefixlen); } + if (bgp_static->label_index != BGP_INVALID_LABEL_INDEX) + vty_out(vty, " label-index %u", + bgp_static->label_index); + + if (bgp_static->rmap.name) + vty_out(vty, " route-map %s", bgp_static->rmap.name); + else { + if (bgp_static->backdoor) + vty_out(vty, " backdoor"); + } + + vty_out(vty, "\n"); + } + /* Aggregate-address configuration. */ for (rn = bgp_table_top(bgp->aggregate[afi][safi]); rn; - rn = bgp_route_next(rn)) - if ((bgp_aggregate = rn->info) != NULL) { - p = &rn->p; + rn = bgp_route_next(rn)) { + if ((bgp_aggregate = rn->info) == NULL) + continue; - if (bgp_option_check(BGP_OPT_CONFIG_CISCO) - && afi == AFI_IP) { - struct in_addr netmask; + p = &rn->p; - masklen2ip(p->prefixlen, &netmask); - vty_out(vty, " aggregate-address %s %s", - inet_ntop(p->family, &p->u.prefix, buf, - SU_ADDRSTRLEN), - inet_ntoa(netmask)); - } else { - vty_out(vty, " aggregate-address %s/%d", - inet_ntop(p->family, &p->u.prefix, buf, - SU_ADDRSTRLEN), - p->prefixlen); - } + if (bgp_option_check(BGP_OPT_CONFIG_CISCO) && afi == AFI_IP) { + struct in_addr netmask; - if (bgp_aggregate->as_set) - vty_out(vty, " as-set"); - - if (bgp_aggregate->summary_only) - vty_out(vty, " summary-only"); - - vty_out(vty, "\n"); + masklen2ip(p->prefixlen, &netmask); + vty_out(vty, " aggregate-address %s %s", + inet_ntop(p->family, &p->u.prefix, buf, + SU_ADDRSTRLEN), + inet_ntoa(netmask)); + } else { + vty_out(vty, " aggregate-address %s/%d", + inet_ntop(p->family, &p->u.prefix, buf, + SU_ADDRSTRLEN), + p->prefixlen); } + + if (bgp_aggregate->as_set) + vty_out(vty, " as-set"); + + if (bgp_aggregate->summary_only) + vty_out(vty, " summary-only"); + + vty_out(vty, "\n"); + } } void bgp_config_write_distance(struct vty *vty, struct bgp *bgp, afi_t afi, diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index fafa005d0e..359451fcc4 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -6610,368 +6610,369 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi, if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)) continue; - if (peer->afc[afi][safi]) { - if (!count) { - unsigned long ents; - char memstrbuf[MTYPE_MEMSTR_LEN]; - int vrf_id_ui; + if (!peer->afc[afi][safi]) + continue; - vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN) - ? -1 - : bgp->vrf_id; + if (!count) { + unsigned long ents; + char memstrbuf[MTYPE_MEMSTR_LEN]; + int vrf_id_ui; - /* Usage summary and header */ + vrf_id_ui = (bgp->vrf_id == VRF_UNKNOWN) + ? -1 + : bgp->vrf_id; + + /* Usage summary and header */ + if (use_json) { + json_object_string_add( + json, "routerId", + inet_ntoa(bgp->router_id)); + json_object_int_add(json, "as", + bgp->as); + json_object_int_add(json, "vrfId", + vrf_id_ui); + json_object_string_add( + json, "vrfName", + (bgp->inst_type + == BGP_INSTANCE_TYPE_DEFAULT) + ? "Default" + : bgp->name); + } else { + vty_out(vty, + "BGP router identifier %s, local AS number %u vrf-id %d", + inet_ntoa(bgp->router_id), + bgp->as, vrf_id_ui); + vty_out(vty, "\n"); + } + + if (bgp_update_delay_configured(bgp)) { if (use_json) { - json_object_string_add( - json, "routerId", - inet_ntoa(bgp->router_id)); - json_object_int_add(json, "as", - bgp->as); - json_object_int_add(json, "vrfId", - vrf_id_ui); - json_object_string_add( - json, "vrfName", - (bgp->inst_type - == BGP_INSTANCE_TYPE_DEFAULT) - ? "Default" - : bgp->name); - } else { - vty_out(vty, - "BGP router identifier %s, local AS number %u vrf-id %d", - inet_ntoa(bgp->router_id), - bgp->as, vrf_id_ui); - vty_out(vty, "\n"); - } + json_object_int_add( + json, + "updateDelayLimit", + bgp->v_update_delay); - if (bgp_update_delay_configured(bgp)) { - if (use_json) { + if (bgp->v_update_delay + != bgp->v_establish_wait) json_object_int_add( json, - "updateDelayLimit", - bgp->v_update_delay); + "updateDelayEstablishWait", + bgp->v_establish_wait); - if (bgp->v_update_delay - != bgp->v_establish_wait) - json_object_int_add( - json, - "updateDelayEstablishWait", - bgp->v_establish_wait); - - if (bgp_update_delay_active( - bgp)) { + if (bgp_update_delay_active( + bgp)) { + json_object_string_add( + json, + "updateDelayFirstNeighbor", + bgp->update_delay_begin_time); + json_object_boolean_true_add( + json, + "updateDelayInProgress"); + } else { + if (bgp->update_delay_over) { json_object_string_add( json, "updateDelayFirstNeighbor", bgp->update_delay_begin_time); - json_object_boolean_true_add( + json_object_string_add( json, - "updateDelayInProgress"); - } else { - if (bgp->update_delay_over) { - json_object_string_add( - json, - "updateDelayFirstNeighbor", - bgp->update_delay_begin_time); - json_object_string_add( - json, - "updateDelayBestpathResumed", - bgp->update_delay_end_time); - json_object_string_add( - json, - "updateDelayZebraUpdateResume", - bgp->update_delay_zebra_resume_time); - json_object_string_add( - json, - "updateDelayPeerUpdateResume", - bgp->update_delay_peers_resume_time); - } + "updateDelayBestpathResumed", + bgp->update_delay_end_time); + json_object_string_add( + json, + "updateDelayZebraUpdateResume", + bgp->update_delay_zebra_resume_time); + json_object_string_add( + json, + "updateDelayPeerUpdateResume", + bgp->update_delay_peers_resume_time); } - } else { + } + } else { + vty_out(vty, + "Read-only mode update-delay limit: %d seconds\n", + bgp->v_update_delay); + if (bgp->v_update_delay + != bgp->v_establish_wait) vty_out(vty, - "Read-only mode update-delay limit: %d seconds\n", - bgp->v_update_delay); - if (bgp->v_update_delay - != bgp->v_establish_wait) - vty_out(vty, - " Establish wait: %d seconds\n", - bgp->v_establish_wait); + " Establish wait: %d seconds\n", + bgp->v_establish_wait); - if (bgp_update_delay_active( - bgp)) { + if (bgp_update_delay_active( + bgp)) { + vty_out(vty, + " First neighbor established: %s\n", + bgp->update_delay_begin_time); + vty_out(vty, + " Delay in progress\n"); + } else { + if (bgp->update_delay_over) { vty_out(vty, " First neighbor established: %s\n", bgp->update_delay_begin_time); vty_out(vty, - " Delay in progress\n"); - } else { - if (bgp->update_delay_over) { - vty_out(vty, - " First neighbor established: %s\n", - bgp->update_delay_begin_time); - vty_out(vty, - " Best-paths resumed: %s\n", - bgp->update_delay_end_time); - vty_out(vty, - " zebra update resumed: %s\n", - bgp->update_delay_zebra_resume_time); - vty_out(vty, - " peers update resumed: %s\n", - bgp->update_delay_peers_resume_time); - } + " Best-paths resumed: %s\n", + bgp->update_delay_end_time); + vty_out(vty, + " zebra update resumed: %s\n", + bgp->update_delay_zebra_resume_time); + vty_out(vty, + " peers update resumed: %s\n", + bgp->update_delay_peers_resume_time); } } } - - if (use_json) { - if (bgp_maxmed_onstartup_configured(bgp) - && bgp->maxmed_active) - json_object_boolean_true_add( - json, - "maxMedOnStartup"); - if (bgp->v_maxmed_admin) - json_object_boolean_true_add( - json, - "maxMedAdministrative"); - - json_object_int_add( - json, "tableVersion", - bgp_table_version( - bgp->rib[afi][safi])); - - ents = bgp_table_count( - bgp->rib[afi][safi]); - json_object_int_add(json, "ribCount", - ents); - json_object_int_add( - json, "ribMemory", - ents * sizeof(struct bgp_node)); - - ents = listcount(bgp->peer); - json_object_int_add(json, "peerCount", - ents); - json_object_int_add( - json, "peerMemory", - ents * sizeof(struct peer)); - - if ((ents = listcount(bgp->group))) { - json_object_int_add( - json, "peerGroupCount", - ents); - json_object_int_add( - json, "peerGroupMemory", - ents * sizeof(struct - peer_group)); - } - - if (CHECK_FLAG(bgp->af_flags[afi][safi], - BGP_CONFIG_DAMPENING)) - json_object_boolean_true_add( - json, - "dampeningEnabled"); - } else { - if (bgp_maxmed_onstartup_configured(bgp) - && bgp->maxmed_active) - vty_out(vty, - "Max-med on-startup active\n"); - if (bgp->v_maxmed_admin) - vty_out(vty, - "Max-med administrative active\n"); - - vty_out(vty, - "BGP table version %" PRIu64 - "\n", - bgp_table_version( - bgp->rib[afi][safi])); - - ents = bgp_table_count( - bgp->rib[afi][safi]); - vty_out(vty, - "RIB entries %ld, using %s of memory\n", - ents, - mtype_memstr( - memstrbuf, - sizeof(memstrbuf), - ents * sizeof(struct - bgp_node))); - - /* Peer related usage */ - ents = listcount(bgp->peer); - vty_out(vty, - "Peers %ld, using %s of memory\n", - ents, - mtype_memstr( - memstrbuf, - sizeof(memstrbuf), - ents * sizeof(struct - peer))); - - if ((ents = listcount(bgp->group))) - vty_out(vty, - "Peer groups %ld, using %s of memory\n", - ents, - mtype_memstr( - memstrbuf, - sizeof(memstrbuf), - ents * sizeof(struct - peer_group))); - - if (CHECK_FLAG(bgp->af_flags[afi][safi], - BGP_CONFIG_DAMPENING)) - vty_out(vty, - "Dampening enabled.\n"); - vty_out(vty, "\n"); - - /* Subtract 8 here because 'Neighbor' is - * 8 characters */ - vty_out(vty, "Neighbor"); - vty_out(vty, "%*s", - max_neighbor_width - 8, " "); - vty_out(vty, - "V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd\n"); - } } - count++; - if (use_json) { - json_peer = json_object_new_object(); - - if (peer_dynamic_neighbor(peer)) + if (bgp_maxmed_onstartup_configured(bgp) + && bgp->maxmed_active) json_object_boolean_true_add( - json_peer, "dynamicPeer"); + json, + "maxMedOnStartup"); + if (bgp->v_maxmed_admin) + json_object_boolean_true_add( + json, + "maxMedAdministrative"); - if (peer->hostname) - json_object_string_add(json_peer, - "hostname", - peer->hostname); - - if (peer->domainname) - json_object_string_add( - json_peer, "domainname", - peer->domainname); - - json_object_int_add(json_peer, "remoteAs", - peer->as); - json_object_int_add(json_peer, "version", 4); json_object_int_add( - json_peer, "msgRcvd", - peer->open_in + peer->update_in - + peer->keepalive_in - + peer->notify_in - + peer->refresh_in - + peer->dynamic_cap_in); + json, "tableVersion", + bgp_table_version( + bgp->rib[afi][safi])); + + ents = bgp_table_count( + bgp->rib[afi][safi]); + json_object_int_add(json, "ribCount", + ents); json_object_int_add( - json_peer, "msgSent", - peer->open_out + peer->update_out - + peer->keepalive_out - + peer->notify_out - + peer->refresh_out - + peer->dynamic_cap_out); + json, "ribMemory", + ents * sizeof(struct bgp_node)); - json_object_int_add(json_peer, "tableVersion", - peer->version[afi][safi]); - json_object_int_add(json_peer, "outq", - peer->obuf->count); - json_object_int_add(json_peer, "inq", 0); - peer_uptime(peer->uptime, timebuf, - BGP_UPTIME_LEN, use_json, - json_peer); + ents = listcount(bgp->peer); + json_object_int_add(json, "peerCount", + ents); json_object_int_add( - json_peer, "prefixReceivedCount", - peer->pcount[afi][pfx_rcd_safi]); + json, "peerMemory", + ents * sizeof(struct peer)); - if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) - json_object_string_add(json_peer, - "state", - "Idle (Admin)"); - else if (CHECK_FLAG( - peer->sflags, - PEER_STATUS_PREFIX_OVERFLOW)) - json_object_string_add(json_peer, - "state", - "Idle (PfxCt)"); - else - json_object_string_add( - json_peer, "state", - lookup_msg(bgp_status_msg, - peer->status, NULL)); + if ((ents = listcount(bgp->group))) { + json_object_int_add( + json, "peerGroupCount", + ents); + json_object_int_add( + json, "peerGroupMemory", + ents * sizeof(struct + peer_group)); + } - if (peer->conf_if) - json_object_string_add(json_peer, - "idType", - "interface"); - else if (peer->su.sa.sa_family == AF_INET) - json_object_string_add( - json_peer, "idType", "ipv4"); - else if (peer->su.sa.sa_family == AF_INET6) - json_object_string_add( - json_peer, "idType", "ipv6"); - - json_object_object_add(json_peers, peer->host, - json_peer); + if (CHECK_FLAG(bgp->af_flags[afi][safi], + BGP_CONFIG_DAMPENING)) + json_object_boolean_true_add( + json, + "dampeningEnabled"); } else { - memset(dn_flag, '\0', sizeof(dn_flag)); - if (peer_dynamic_neighbor(peer)) { - dn_count++; - dn_flag[0] = '*'; - } + if (bgp_maxmed_onstartup_configured(bgp) + && bgp->maxmed_active) + vty_out(vty, + "Max-med on-startup active\n"); + if (bgp->v_maxmed_admin) + vty_out(vty, + "Max-med administrative active\n"); - if (peer->hostname - && bgp_flag_check(bgp, - BGP_FLAG_SHOW_HOSTNAME)) - len = vty_out(vty, "%s%s(%s)", dn_flag, - peer->hostname, - peer->host); - else - len = vty_out(vty, "%s%s", dn_flag, - peer->host); + vty_out(vty, + "BGP table version %" PRIu64 + "\n", + bgp_table_version( + bgp->rib[afi][safi])); - /* pad the neighbor column with spaces */ - if (len < max_neighbor_width) - vty_out(vty, "%*s", - max_neighbor_width - len, " "); + ents = bgp_table_count( + bgp->rib[afi][safi]); + vty_out(vty, + "RIB entries %ld, using %s of memory\n", + ents, + mtype_memstr( + memstrbuf, + sizeof(memstrbuf), + ents * sizeof(struct + bgp_node))); - vty_out(vty, "4 %10u %7d %7d %8" PRIu64 - " %4d %4zd %8s", - peer->as, - peer->open_in + peer->update_in - + peer->keepalive_in - + peer->notify_in - + peer->refresh_in - + peer->dynamic_cap_in, - peer->open_out + peer->update_out - + peer->keepalive_out - + peer->notify_out - + peer->refresh_out - + peer->dynamic_cap_out, - peer->version[afi][safi], 0, - peer->obuf->count, - peer_uptime(peer->uptime, timebuf, - BGP_UPTIME_LEN, 0, NULL)); + /* Peer related usage */ + ents = listcount(bgp->peer); + vty_out(vty, + "Peers %ld, using %s of memory\n", + ents, + mtype_memstr( + memstrbuf, + sizeof(memstrbuf), + ents * sizeof(struct + peer))); - if (peer->status == Established) - vty_out(vty, " %12ld", - peer->pcount[afi] - [pfx_rcd_safi]); - else { - if (CHECK_FLAG(peer->flags, - PEER_FLAG_SHUTDOWN)) - vty_out(vty, " Idle (Admin)"); - else if ( - CHECK_FLAG( - peer->sflags, - PEER_STATUS_PREFIX_OVERFLOW)) - vty_out(vty, " Idle (PfxCt)"); - else - vty_out(vty, " %12s", - lookup_msg( - bgp_status_msg, - peer->status, - NULL)); - } + if ((ents = listcount(bgp->group))) + vty_out(vty, + "Peer groups %ld, using %s of memory\n", + ents, + mtype_memstr( + memstrbuf, + sizeof(memstrbuf), + ents * sizeof(struct + peer_group))); + + if (CHECK_FLAG(bgp->af_flags[afi][safi], + BGP_CONFIG_DAMPENING)) + vty_out(vty, + "Dampening enabled.\n"); vty_out(vty, "\n"); + + /* Subtract 8 here because 'Neighbor' is + * 8 characters */ + vty_out(vty, "Neighbor"); + vty_out(vty, "%*s", + max_neighbor_width - 8, " "); + vty_out(vty, + "V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd\n"); } } + + count++; + + if (use_json) { + json_peer = json_object_new_object(); + + if (peer_dynamic_neighbor(peer)) + json_object_boolean_true_add( + json_peer, "dynamicPeer"); + + if (peer->hostname) + json_object_string_add(json_peer, + "hostname", + peer->hostname); + + if (peer->domainname) + json_object_string_add( + json_peer, "domainname", + peer->domainname); + + json_object_int_add(json_peer, "remoteAs", + peer->as); + json_object_int_add(json_peer, "version", 4); + json_object_int_add( + json_peer, "msgRcvd", + peer->open_in + peer->update_in + + peer->keepalive_in + + peer->notify_in + + peer->refresh_in + + peer->dynamic_cap_in); + json_object_int_add( + json_peer, "msgSent", + peer->open_out + peer->update_out + + peer->keepalive_out + + peer->notify_out + + peer->refresh_out + + peer->dynamic_cap_out); + + json_object_int_add(json_peer, "tableVersion", + peer->version[afi][safi]); + json_object_int_add(json_peer, "outq", + peer->obuf->count); + json_object_int_add(json_peer, "inq", 0); + peer_uptime(peer->uptime, timebuf, + BGP_UPTIME_LEN, use_json, + json_peer); + json_object_int_add( + json_peer, "prefixReceivedCount", + peer->pcount[afi][pfx_rcd_safi]); + + if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) + json_object_string_add(json_peer, + "state", + "Idle (Admin)"); + else if (CHECK_FLAG( + peer->sflags, + PEER_STATUS_PREFIX_OVERFLOW)) + json_object_string_add(json_peer, + "state", + "Idle (PfxCt)"); + else + json_object_string_add( + json_peer, "state", + lookup_msg(bgp_status_msg, + peer->status, NULL)); + + if (peer->conf_if) + json_object_string_add(json_peer, + "idType", + "interface"); + else if (peer->su.sa.sa_family == AF_INET) + json_object_string_add( + json_peer, "idType", "ipv4"); + else if (peer->su.sa.sa_family == AF_INET6) + json_object_string_add( + json_peer, "idType", "ipv6"); + + json_object_object_add(json_peers, peer->host, + json_peer); + } else { + memset(dn_flag, '\0', sizeof(dn_flag)); + if (peer_dynamic_neighbor(peer)) { + dn_count++; + dn_flag[0] = '*'; + } + + if (peer->hostname + && bgp_flag_check(bgp, + BGP_FLAG_SHOW_HOSTNAME)) + len = vty_out(vty, "%s%s(%s)", dn_flag, + peer->hostname, + peer->host); + else + len = vty_out(vty, "%s%s", dn_flag, + peer->host); + + /* pad the neighbor column with spaces */ + if (len < max_neighbor_width) + vty_out(vty, "%*s", + max_neighbor_width - len, " "); + + vty_out(vty, "4 %10u %7d %7d %8" PRIu64 + " %4d %4zd %8s", + peer->as, + peer->open_in + peer->update_in + + peer->keepalive_in + + peer->notify_in + + peer->refresh_in + + peer->dynamic_cap_in, + peer->open_out + peer->update_out + + peer->keepalive_out + + peer->notify_out + + peer->refresh_out + + peer->dynamic_cap_out, + peer->version[afi][safi], 0, + peer->obuf->count, + peer_uptime(peer->uptime, timebuf, + BGP_UPTIME_LEN, 0, NULL)); + + if (peer->status == Established) + vty_out(vty, " %12ld", + peer->pcount[afi] + [pfx_rcd_safi]); + else { + if (CHECK_FLAG(peer->flags, + PEER_FLAG_SHUTDOWN)) + vty_out(vty, " Idle (Admin)"); + else if ( + CHECK_FLAG( + peer->sflags, + PEER_STATUS_PREFIX_OVERFLOW)) + vty_out(vty, " Idle (PfxCt)"); + else + vty_out(vty, " %12s", + lookup_msg( + bgp_status_msg, + peer->status, + NULL)); + } + vty_out(vty, "\n"); + } } if (use_json) { From 5309b14eae13b6664646c93d2ad8ecb6401c8593 Mon Sep 17 00:00:00 2001 From: David Lamparter Date: Mon, 28 Aug 2017 23:48:51 +0200 Subject: [PATCH 9/9] doc: new frr-args(8) man page with general options Signed-off-by: David Lamparter --- configure.ac | 1 + debian/frr.install | 1 + doc/Makefile.am | 2 +- doc/frr-args.8.in | 248 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 doc/frr-args.8.in diff --git a/configure.ac b/configure.ac index bf66e00f9f..5505ba32d3 100755 --- a/configure.ac +++ b/configure.ac @@ -1819,6 +1819,7 @@ AC_CONFIG_FILES([Makefile doc/watchfrr.8 doc/zebra.8 doc/frr.1 + doc/frr-args.8 pkgsrc/bgpd.sh pkgsrc/ospf6d.sh pkgsrc/ospfd.sh pkgsrc/ripd.sh pkgsrc/ripngd.sh pkgsrc/zebra.sh pkgsrc/eigrpd.sh]) diff --git a/debian/frr.install b/debian/frr.install index 49aeb395bb..8fc5fa5fa6 100644 --- a/debian/frr.install +++ b/debian/frr.install @@ -16,6 +16,7 @@ usr/share/man/man8/ripngd.8 usr/share/man/man8/zebra.8 usr/share/man/man8/isisd.8 usr/share/man/man8/watchfrr.8 +usr/share/man/man8/frr-args.8 usr/share/snmp/mibs/ tools/etc/* etc/ tools/*.service lib/systemd/system diff --git a/doc/Makefile.am b/doc/Makefile.am index 9016df7372..b6b7d1dba1 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -79,7 +79,7 @@ frr_TEXINFOS = appendix.texi basic.texi bgpd.texi isisd.texi filter.texi \ .dia.png: $(DIATOPNG) "$@" $< -man_MANS = frr.1 +man_MANS = frr.1 frr-args.8 if PIMD man_MANS += pimd.8 diff --git a/doc/frr-args.8.in b/doc/frr-args.8.in new file mode 100644 index 0000000000..3dc84e1e22 --- /dev/null +++ b/doc/frr-args.8.in @@ -0,0 +1,248 @@ +.TH frr-args 8 "28 August 2017" "@PACKAGE_FULLNAME@ general options" "Version @PACKAGE_VERSION@" +.SH NAME +frr-args \- common command line options for all @PACKAGE_FULLNAME@ daemons. +.SH SYNOPSIS +<\fBzebra\fR|\fBbgpd\fR|\fB...\fR> +[\fB\-h\fR] [\fB\-v\fR] + +<\fBzebra\fR|\fBbgpd\fR|\fB...\fR> +[\fB\-d\fR|\fB\-t\fR|\fB\-dt\fR] +[\fB\-C\fR] +[\fB\-f\fR \fIconfig-file\fR] +[\fB\-i\fR \fIpid-file\fR] +[\fB\-z\fR \fIzclient-path\fR] +[\fB\-u\fR \fIuser\fR] +[\fB\-g\fR \fIgroup\fR] +[\fB\-A\fR \fIvty-addr\fR] +[\fB\-P\fR \fIvty-port\fR] +[\fB\-M\fR \fImodule\fR[\fB:\fIoptions\fR]] +[\fB\-N\fR \fIpathspace\fR] +[\fB\-\-vty_socket\fR \fIvty-path\fR] +[\fB\-\-moduledir\fR \fImodule-path\fR] + +.SH DESCRIPTION +@PACKAGE_NAME@ daemons share a large part of their command line options; +this man page documents these. For options on specific daemons please refer +to their respective man pages. Most of the common options are related to +process control, configuration and common library functionality. + +.SH HELP AND VERSION +.TP +\fB\-h\fR, \fB\-\-help\fR +Print a short description of the daemon's command line options. +.TP +\fB\-v\fR, \fB\-\-version\fR +Print version and build information for the daemon. +.PP +Both of these options inhibit normal operation and will immediately exit. + +.SH PROCESS CONTROL +These options control background operation: +.TP +\fB\-d\fR, \fB\-\-daemon\fR +Launches the process in background/daemon mode, forking and detaching from +the terminal. + +The parent process will delay its exit until the daemon/child has finished +its initialization and has entered its main loop. This is important for +\fBzebra\fR startup because the other daemons will attempt to connect to +\fBzebra\fR. A return from \fBzebra -d\fR guarantees its readiness to +accept these connections. +.TP +\fB\-t\fR, \fB\-\-terminal\fR +Opens an interactive VTY session on the terminal, allowing for both state +and configuration operations. Note that the terminal starts operating after +startup has completed and the configuration file has been loaded. + +The process will exit when end of file is detected on the terminal. It is +possible to daemonize a process started with \fB-t\fR (but without \fB-d\fR) +by sending \fISIGQUIT\fR to the process (normally mapped to a \fI^\\\fR +keypress.) +.TP +\fB\-dt\fR, \fB\-\-daemon \-\-terminal\fR +This combination of the previous two options will delay the daemon from +going into background until the terminal session ends (by end of file.) + +If the process receives \fISIGINT\fR (e.g. a \fI^C\fR keypress) in this +mode, it will exit instead of daemonizing. +.PP +It is safe to suspend (\fISIGTSTP\fR / \fI^Z\fR) the terminal session +opened by the previous two options; this will only stop the terminal but +not the protocol daemon itself (which runs in a separate second process.) + +.SH CONFIGURATION AND PATHS +The following options control configuration and file system locations for +@PACKAGE_NAME@ processes: +.TP +\fB\-f\fR, \fB\-\-config_file\fR \fIconfig-file\fR +Specify a configuration file to be used instead of the default +\fB\fI@CFG_SYSCONF@/.conf\fR file. + +Note that the daemon will attempt to write to this file if the +\fIwrite file\fR command is issued on its VTY interface or through +\fBvtysh\fR. +.TP +\fB\-C\fR, \fB\-\-dryrun\fR +Load the configuration file and check its validity, then exit. +.TP +\fB\-i\fR, \fB\-\-pid_file\fR \fIpid-file\fR +Output a pid file to a location other than the default +\fB\fI@CFG_STATE@/.pid\fR. +.TP +\fB\-z\fR, \fB\-\-socket\fR \fIzclient-path\fR +Override the path of the ZAPI socket used to communicate between \fBzebra\fR +and the various protocol daemons. The default is +\fB\fI@CFG_STATE@/zserv.api\fR. The value of this option must be the same +across all daemons. +.TP +\fB\-N\fR, \fB\-\-pathspace\fR \fIpathspace\fR +Insert \fIpathspace\fR into all default paths, changing the defaults to: +.IP +\fB@CFG_SYSCONF@/\fIpathspace\fB/.conf\fR +.br +\fB@CFG_STATE@/\fIpathspace\fB/.pid\fR +.br +\fB@CFG_STATE@/\fIpathspace\fB/.vty\fR +.br +\fB@CFG_STATE@/\fIpathspace\fB/zserv.api\fR + +\'.\' and \'/\' characters will not be accepted in \fIpathspace\fR, but the +empty string will be accepted. + +Note that this only changes the respective defaults, it has no effect on +the respective path if the \fB\-f\fR, \fB\-i\fR, \fB\-z\fR or +\fB\-\-vty_socket\fR options are used. + +The purpose of this option is to easily group all file system related +bits together for running multiple fully-separate "logical routers" on a +system, particularly with Linux network namespaces. Groups of daemons +running with distinct \fIpathspace\fR values will be completely unaware +of each other and not interact in any way. + +This option does not do any system setup (like network namespaces.) This +must be done by the user, for example by running: +.IP +\fBip netns exec \fInamespace \fB -N \fInamespace\fR + +.SH PROCESS CREDENTIALS +.TP +\fB\-u\fR, \fB\-\-user\fR \fIuser\fR +(default: \fB@enable_user@\fR) +.TP +\fB\-g\fR, \fB\-\-group\fR \fIgroup\fR +(default: \fB@enable_group@\fR) +.IP +Change the user/group which the daemon will switch to. +.PP +Note that there is an additional group, \fB@enable_vty_group@\fR, which +controls group ownership of the VTY sockets. The name of this group cannot +currently be changed, and \fIuser\fR must be a member of this group. + +.SH VTY SETUP +These following options control the daemon's VTY (interactive command line) +interface. The interface is available over TCP, using the telnet protocol, +as well as through the \fBvtysh\fR frontend. +.TP +\fB\-A\fR, \fB--vty_addr\fR \fIvty-addr\fR +Specify an IP/IPv6 address to bind the TCP VTY interface to. It is +generally recommended to specify \fI::1\fR or \fI127.0.0.1\fR. For reasons +of backwards compatibility, the default is to listen on all interfaces. +.TP +\fB\-P\fR, \fB--vty_port\fR \fIvty-port\fR +Override the daemon's default TCP VTY port (each daemon has a different +default value upwards of 2600, listed below.) Specifying \fI0\fR disables +the TCP VTY interface. + +Default ports are: + +.ta 16m +zebra 2601 +.br +ripd 2602 +.br +ripngd 2603 +.br +ospfd 2604 +.br +bgpd 2605 +.br +ospf6d 2606 +.br +isisd 2608 +.br +babeld 2609 +.br +nhrpd 2610 +.br +pimd 2611 +.br +ldpd 2612 +.br +eigrpd 2613 + +Port 2607 is used for ospfd's Opaque LSA API, while port 2600 is used for +the (insecure) TCP-ZEBRA interface. +.TP +\fB\-\-vty_socket\fR \fIvty-path\fR +Overrides the directory used for the \fB.vty\fR sockets. +\fBvtysh\fR connects to these sockets in order to access each daemon's +VTY. +.br +Default: \fB\fI@CFG_STATE@\fR[\fB/\fI\fR] + +NB: Unlike the other options, this option specifies a \fBdirectory\fR, +not a full path. + +This option is primarily used by the SNAP packaging system, its semantics +may change. It should not be neccessary in most other scenarios. + +.SH MODULE LOADING +@PACKAGE_NAME@ supports optional dynamically loadable modules, although +these can only be loaded at startup. The set of available modules may vary +across distributions and packages, and modules may be available for +installation as separate packages. +.TP +\fB\-M\fR, \fB\-\-module\fR \fImodule\fR[\fB:\fIoptions\fR] +Load a module named \fImodule\fR, optionally passing \fIoptions\fR to it. + +If there is a \'/\' character in \fImodule\fR, the value is assumed to be +a pathname to a module. + +If there is no \'/\' character, the module directory (see next option) +is searched first for a module named "\fI\fB_\fI\fB.so\fR", +then for "\fI\fB.so\fR". +This allows for a module to exist in variations appropriate for particular +daemons, e.g. \fIzebra_snmp\fR and \fIbgp_snmp\fR, with the correct one +selected by \fI\-M snmp\fR. + +The meaning of \fIoptions\fR is specific to the module being loaded. Most +modules currently ignore it. + +Modules are loaded in the order as listed on the command line. This is +not generally relevant. +.TP +\fB\-\-moduledir\fR \fImodule-path\fR +Look for modules in the \fImodule-path\fR directory instead of the default +\fI@CFG_MODULE@\fR. (This path is \fBnot\fR affected by the \fB\-N\fR +option.) +.PP +The list of loaded modules can be inspected at runtime with the +\fBshow modules\fR VTY command. + + +.SH "SEE ALSO" +.BR zebra (8), +.BR vtysh (1), +.BR ripd (8), +.BR ripngd (8), +.BR ospfd (8), +.BR ospf6d (8), +.BR bgpd (8), +.BR isisd (8), +.BR babeld (8), +.BR nhrpd (8), +.BR pimd (8), +.BR ldpd (8), +.BR eigrpd (8) + +\fIhttps://frrouting.org/