Skip to content

Commit

Permalink
lib: new defaults logic
Browse files Browse the repository at this point in the history
Since we've been writing out "frr version" and "frr defaults" for about
a year and a half now, we can now actually use them to manage defaults.

Signed-off-by: David Lamparter <equinox@diac24.net>
  • Loading branch information
eqvinox committed Dec 6, 2019
1 parent 96673e0 commit ac4adef
Show file tree
Hide file tree
Showing 8 changed files with 376 additions and 73 deletions.
2 changes: 0 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,6 @@ EXTRA_DIST += \
vrrpd/Makefile \
# end

noinst_HEADERS += defaults.h

clean-local: clean-python
.PHONY: clean-python
clean-python:
Expand Down
54 changes: 0 additions & 54 deletions defaults.h

This file was deleted.

17 changes: 3 additions & 14 deletions lib/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -1575,18 +1575,6 @@ DEFUN (show_version,
return CMD_SUCCESS;
}

/* "Set" version ... ignore version tags */
DEFUN (frr_version_defaults,
frr_version_defaults_cmd,
"frr <version|defaults> LINE...",
"FRRouting global parameters\n"
"version configuration was written by\n"
"set of configuration defaults used\n"
"version string\n")
{
return CMD_SUCCESS;
}

/* Help display function for all node. */
DEFUN (config_help,
config_help_cmd,
Expand Down Expand Up @@ -1721,8 +1709,10 @@ static int vty_write_config(struct vty *vty)
vty_out(vty, "!\n");
}

if (strcmp(frr_defaults_version(), FRR_VER_SHORT))
vty_out(vty, "! loaded from %s\n", frr_defaults_version());
vty_out(vty, "frr version %s\n", FRR_VER_SHORT);
vty_out(vty, "frr defaults %s\n", DFLT_NAME);
vty_out(vty, "frr defaults %s\n", frr_defaults_profile());
vty_out(vty, "!\n");

for (i = 0; i < vector_active(cmdvec); i++)
Expand Down Expand Up @@ -2941,7 +2931,6 @@ void cmd_init(int terminal)
install_element(CONFIG_NODE, &no_hostname_cmd);
install_element(CONFIG_NODE, &domainname_cmd);
install_element(CONFIG_NODE, &no_domainname_cmd);
install_element(CONFIG_NODE, &frr_version_defaults_cmd);

if (terminal > 0) {
install_element(CONFIG_NODE, &debug_memstats_cmd);
Expand Down
152 changes: 151 additions & 1 deletion lib/defaults.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,20 @@
#include <zebra.h>

#include "defaults.h"
#include "libfrr.h"
#include "version.h"

static char df_version[128] = FRR_VER_SHORT, df_profile[128] = DFLT_NAME;
static struct frr_default *dflt_first = NULL, **dflt_next = &dflt_first;

/* these are global for all FRR daemons. they have to be, since we write an
* integrated config with the same value for all daemons.
*/
const char *frr_defaults_profiles[] = {
"traditional",
"datacenter",
NULL,
};

static int version_value(int ch)
{
/* non-ASCII shouldn't happen */
Expand Down Expand Up @@ -73,3 +84,142 @@ int frr_version_cmp(const char *aa, const char *bb)
}
return 0;
}

static void frr_default_apply_one(struct frr_default *dflt, bool check);

void frr_default_add(struct frr_default *dflt)
{
dflt->next = NULL;
*dflt_next = dflt;
dflt_next = &dflt->next;

frr_default_apply_one(dflt, true);
}

static bool frr_match_version(const char *name, const char *vspec,
const char *version, bool check)
{
int cmp;
static struct spec {
const char *str;
bool dir, eq;
} *s, specs[] = {
{"<=", -1, 1},
{">=", 1, 1},
{"==", 0, 1},
{"<", -1, 0},
{">", 1, 0},
{"=", 0, 1},
{NULL, 0, 0},
};

if (!vspec)
/* NULL = all versions */
return true;

for (s = specs; s->str; s++)
if (!strncmp(s->str, vspec, strlen(s->str)))
break;
if (!s->str) {
if (check)
fprintf(stderr, "invalid version specifier for %s: %s",
name, vspec);
/* invalid version spec, never matches */
return false;
}

vspec += strlen(s->str);
while (isspace((unsigned char)*vspec))
vspec++;

cmp = frr_version_cmp(version, vspec);
if (cmp == s->dir || (s->eq && cmp == 0))
return true;

return false;
}

static void frr_default_apply_one(struct frr_default *dflt, bool check)
{
struct frr_default_entry *entry = dflt->entries;
struct frr_default_entry *dfltentry = NULL, *saveentry = NULL;

for (; entry->match_version || entry->match_profile; entry++) {
if (entry->match_profile
&& strcmp(entry->match_profile, df_profile))
continue;

if (!dfltentry && frr_match_version(dflt->name,
entry->match_version, df_version, check))
dfltentry = entry;
if (!saveentry && frr_match_version(dflt->name,
entry->match_version, FRR_VER_SHORT, check))
saveentry = entry;

if (dfltentry && saveentry && !check)
break;
}
/* found default or arrived at last entry that has NULL,NULL spec */

if (!dfltentry)
dfltentry = entry;
if (!saveentry)
saveentry = entry;

if (dflt->dflt_str)
*dflt->dflt_str = dfltentry->val_str;
if (dflt->dflt_long)
*dflt->dflt_long = dfltentry->val_long;
if (dflt->dflt_ulong)
*dflt->dflt_ulong = dfltentry->val_ulong;
if (dflt->dflt_float)
*dflt->dflt_float = dfltentry->val_float;
if (dflt->save_str)
*dflt->save_str = saveentry->val_str;
if (dflt->save_long)
*dflt->save_long = saveentry->val_long;
if (dflt->save_ulong)
*dflt->save_ulong = saveentry->val_ulong;
if (dflt->save_float)
*dflt->save_float = saveentry->val_float;
}

void frr_defaults_apply(void)
{
struct frr_default *dflt;

for (dflt = dflt_first; dflt; dflt = dflt->next)
frr_default_apply_one(dflt, false);
}

bool frr_defaults_profile_valid(const char *profile)
{
const char **p;

for (p = frr_defaults_profiles; *p; p++)
if (!strcmp(profile, *p))
return true;
return false;
}

const char *frr_defaults_version(void)
{
return df_version;
}

const char *frr_defaults_profile(void)
{
return df_profile;
}

void frr_defaults_version_set(const char *version)
{
strlcpy(df_version, version, sizeof(df_version));
frr_defaults_apply();
}

void frr_defaults_profile_set(const char *profile)
{
strlcpy(df_profile, profile, sizeof(df_profile));
frr_defaults_apply();
}
Loading

0 comments on commit ac4adef

Please sign in to comment.