diff options
| -rw-r--r-- | doc/Makefile.am | 6 | ||||
| -rw-r--r-- | doc/manpages/conf.py | 1 | ||||
| -rw-r--r-- | doc/manpages/index.rst | 1 | ||||
| -rw-r--r-- | doc/manpages/sharpd.rst | 38 | ||||
| -rw-r--r-- | doc/user/index.rst | 1 | ||||
| -rw-r--r-- | doc/user/sharp.rst | 67 | ||||
| -rw-r--r-- | lib/plist.c | 48 | ||||
| -rw-r--r-- | lib/plist_int.h | 2 | ||||
| -rw-r--r-- | lib/routemap.c | 14 | ||||
| -rw-r--r-- | lib/routemap.h | 4 | ||||
| -rw-r--r-- | vtysh/vtysh.c | 15 |
11 files changed, 159 insertions, 38 deletions
diff --git a/doc/Makefile.am b/doc/Makefile.am index dec6b53e0f..053842283e 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -82,6 +82,10 @@ if EIGRPD man_MANS += $(MANPAGE_BUILDDIR)/eigrpd.8 endif +if SHARPD +man_MANS += $(MANPAGE_BUILDDIR)/sharpd.8 +endif + # Automake is particular about manpages. It is aware of them and has some # special facilities for handling them, but it assumes that manpages are always # given in groff source and so these facilities are limited to simply @@ -146,6 +150,7 @@ EXTRA_DIST = frr-sphinx.mk \ manpages/ripd.rst \ manpages/pbrd.rst \ manpages/ripngd.rst \ + manpages/sharpd.rst \ manpages/vtysh.rst \ manpages/watchfrr.rst \ manpages/zebra.rst \ @@ -212,6 +217,7 @@ EXTRA_DIST = frr-sphinx.mk \ user/routemap.rst \ user/routeserver.rst \ user/rpki.rst \ + user/sharp.rst \ user/snmp.rst \ user/snmptrap.rst \ user/Useful_Sysctl_Settings.md \ diff --git a/doc/manpages/conf.py b/doc/manpages/conf.py index 41683ed678..2b0f7e3893 100644 --- a/doc/manpages/conf.py +++ b/doc/manpages/conf.py @@ -323,6 +323,7 @@ man_pages = [ ('nhrpd', 'nhrpd', fwfrr.format("a Next Hop Routing Protocol "), [], 8), ('pimd', 'pimd', fwfrr.format("a PIM "), [], 8), ('pbrd', 'pbrd', fwfrr.format("a PBR "), [], 8), + ('sharpd', 'sharpd', fwfrr.format("a SHARP "), [], 8), ('mtracebis', 'mtracebis', "a multicast trace client", [], 8), ('ripd', 'ripd', fwfrr.format("a RIP "), [], 8), ('ripngd', 'ripngd', fwfrr.format("a RIPNG "), [], 8), diff --git a/doc/manpages/index.rst b/doc/manpages/index.rst index 964cc07d71..ae622bb699 100644 --- a/doc/manpages/index.rst +++ b/doc/manpages/index.rst @@ -22,6 +22,7 @@ Welcome to FRR's documentation! mtracebis ripd ripngd + sharpd watchfrr zebra vtysh diff --git a/doc/manpages/sharpd.rst b/doc/manpages/sharpd.rst new file mode 100644 index 0000000000..016f3f9254 --- /dev/null +++ b/doc/manpages/sharpd.rst @@ -0,0 +1,38 @@ +****** +SHARPD +****** + +.. include:: defines.rst +.. |DAEMON| replace:: sharpd + +SYNOPSIS +======== +|DAEMON| |synopsis-options-hv| + +|DAEMON| |synopsis-options| + +DESCRIPTION +=========== +|DAEMON| is a routing component that works with the FRRouting engine. + +OPTIONS +======= +OPTIONS available for the |DAEMON| command: + +.. include:: common-options.rst + +FILES +===== + +|INSTALL_PREFIX_SBIN|/|DAEMON| + The default location of the |DAEMON| binary. + +|INSTALL_PREFIX_ETC|/|DAEMON|.conf + The default location of the |DAEMON| config file. + +$(PWD)/|DAEMON|.log + If the |DAEMON| process is configured to output logs to a file, then you will find this file in the directory where you started |DAEMON|. + +.. include:: epilogue.rst + + diff --git a/doc/user/index.rst b/doc/user/index.rst index c264b4c83e..28a85da8aa 100644 --- a/doc/user/index.rst +++ b/doc/user/index.rst @@ -25,6 +25,7 @@ Welcome to FRR's documentation! pbr ripd ripngd + sharp vnc glossary appendix diff --git a/doc/user/sharp.rst b/doc/user/sharp.rst new file mode 100644 index 0000000000..090628044c --- /dev/null +++ b/doc/user/sharp.rst @@ -0,0 +1,67 @@ +.. _sharp: + +*** +SHARP +*** + +:abbr:`SHARP` Super Happy Advanced Routing Process. This daemon is useful +for the testing of FRR itself as well as useful for creation of Proof of +Concept labs. + +.. _starting-sharp: + +Starting SHARP +============== + +Default configuration file for *sharpd* is :file:`sharpd.conf`. The typical +location of :file:`sharpd.conf` is |INSTALL_PREFIX_ETC|/sharpd.conf. + +If the user is using integrated config, then :file:`sharpd.conf` need not be +present and the :file:`frr.conf` is read instead. + +.. program:: sharpd + +:abbr:`SHARP` supports all the common FRR daemon start options which are +documented elsewhere. + +.. _using-sharp: + +USING SHARP +=========== + +All sharp commands are under the enable node and proceeded by the +:abbr:`sharp` keyword. There are currently no permenent sharp +commands for configuration. + +..index:: sharp install +..clicmd:: sharp install routes A.B.C.D nexthop E.F.G.H (1-1000000) + +Install up to a million /32 routes starting at A.B.C.D with specified nexthop +E.F.G.H. The nexthop is a NEXTHOP_TYPE_IPV4 and must be reachable to be +installed into the kernel. The routes are installed into zebra as +ZEBRA_ROUTE_SHARP and can be used as part of a normal route redistribution. +Route installation time is noted in the debug log and upon zebra successful +installation into the kernel and sharp receiving the notification of all +route installs the success will be noted in the debug log as well. + +..index:: sharp remove +..clicmd:: sharp remove routes A.B.C.D (1-1000000) + +Remove up 1000000 million /32 routes starting at A.B.C.D. The routes are +removed from zebra. Route deletion start is noted in the debug log +and when all routes have been successfully deleted the debug log will +be updated with this information as well. + +..index:: sharp label +..clicmd:: sharp label <ipv4|ipv6> vrf NAME label (0-1000000) + +Install a label into the kernel that causes the specified vrf NAME table to be +used for pop and forward operations when the specified label is seen. + +..index:: sharp watch +..clicmd: sharp watch nexthop <A.B.C.D|X:X::X:X> + +Instruct zebra to monitor and notify sharp when the specified nexthop is +changed. The notification from zebra is written into the debug log. + + diff --git a/lib/plist.c b/lib/plist.c index 01b55f9f1d..e1dac46a90 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -73,7 +73,7 @@ struct prefix_master { struct prefix_list_list str; /* Whether sequential number is used. */ - int seqnum; + bool seqnum; /* The latest update. */ struct prefix_list *recent; @@ -348,7 +348,7 @@ static void prefix_list_delete(struct prefix_list *plist) static struct prefix_list_entry * prefix_list_entry_make(struct prefix *prefix, enum prefix_list_type type, - int seq, int le, int ge, int any) + int64_t seq, int le, int ge, int any) { struct prefix_list_entry *pentry; @@ -381,10 +381,10 @@ void prefix_list_delete_hook(void (*func)(struct prefix_list *plist)) } /* Calculate new sequential number. */ -static int prefix_new_seq_get(struct prefix_list *plist) +static int64_t prefix_new_seq_get(struct prefix_list *plist) { - int maxseq; - int newseq; + int64_t maxseq; + int64_t newseq; struct prefix_list_entry *pentry; maxseq = newseq = 0; @@ -401,7 +401,7 @@ static int prefix_new_seq_get(struct prefix_list *plist) /* Return prefix list entry which has same seq number. */ static struct prefix_list_entry *prefix_seq_check(struct prefix_list *plist, - int seq) + int64_t seq) { struct prefix_list_entry *pentry; @@ -413,7 +413,8 @@ static struct prefix_list_entry *prefix_seq_check(struct prefix_list *plist, static struct prefix_list_entry * prefix_list_entry_lookup(struct prefix_list *plist, struct prefix *prefix, - enum prefix_list_type type, int seq, int le, int ge) + enum prefix_list_type type, int64_t seq, + int le, int ge) { struct prefix_list_entry *pentry; @@ -771,7 +772,7 @@ static void __attribute__((unused)) prefix_list_print(struct prefix_list *plist) p = &pentry->prefix; - printf(" seq %u %s %s/%d", pentry->seq, + printf(" seq %" PRId64 " %s %s/%d", pentry->seq, prefix_list_type_str(pentry), inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen); @@ -793,7 +794,7 @@ prefix_entry_dup_check(struct prefix_list *plist, struct prefix_list_entry *new) size_t validbits = new->prefix.prefixlen; struct pltrie_table *table; struct prefix_list_entry *pentry; - int seq = 0; + int64_t seq = 0; if (new->seq == -1) seq = prefix_new_seq_get(plist); @@ -845,13 +846,13 @@ static int vty_prefix_list_install(struct vty *vty, afi_t afi, const char *name, struct prefix_list_entry *dup; struct prefix p, p_tmp; int any = 0; - int seqnum = -1; + int64_t seqnum = -1; int lenum = 0; int genum = 0; /* Sequential number. */ if (seq) - seqnum = atoi(seq); + seqnum = (int64_t)atol(seq); /* ge and le number */ if (ge) @@ -972,7 +973,7 @@ static int vty_prefix_list_uninstall(struct vty *vty, afi_t afi, struct prefix_list *plist; struct prefix_list_entry *pentry; struct prefix p; - int seqnum = -1; + int64_t seqnum = -1; int lenum = 0; int genum = 0; @@ -998,7 +999,7 @@ static int vty_prefix_list_uninstall(struct vty *vty, afi_t afi, /* Check sequence number. */ if (seq) - seqnum = atoi(seq); + seqnum = (int64_t)atol(seq); /* ge and le number */ if (ge) @@ -1113,7 +1114,7 @@ static void vty_show_prefix_entry(struct vty *vty, afi_t afi, vty_out(vty, " Description: %s\n", plist->desc); vty_out(vty, - " count: %d, range entries: %d, sequences: %u - %u\n", + " count: %d, range entries: %d, sequences: %" PRId64 " - %" PRId64 "\n", plist->count, plist->rangecount, plist->head ? plist->head->seq : 0, plist->tail ? plist->tail->seq : 0); @@ -1128,7 +1129,7 @@ static void vty_show_prefix_entry(struct vty *vty, afi_t afi, vty_out(vty, " "); if (master->seqnum) - vty_out(vty, "seq %u ", pentry->seq); + vty_out(vty, "seq %" PRId64 " ", pentry->seq); vty_out(vty, "%s ", prefix_list_type_str(pentry)); @@ -1164,14 +1165,14 @@ static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name, { struct prefix_list *plist; struct prefix_master *master; - int seqnum = 0; + int64_t seqnum = 0; master = prefix_master_get(afi, 0); if (master == NULL) return CMD_WARNING; if (seq) - seqnum = atoi(seq); + seqnum = (int64_t)atol(seq); if (name) { plist = prefix_list_lookup(afi, name); @@ -1236,7 +1237,7 @@ static int vty_show_prefix_list_prefix(struct vty *vty, afi_t afi, } if (match) { - vty_out(vty, " seq %u %s ", pentry->seq, + vty_out(vty, " seq %" PRId64 " %s ", pentry->seq, prefix_list_type_str(pentry)); if (pentry->any) @@ -1387,7 +1388,7 @@ DEFPY (ip_prefix_list_sequence_number, PREFIX_LIST_STR "Include/exclude sequence numbers in NVGEN\n") { - prefix_master_ipv4.seqnum = no ? 0 : 1; + prefix_master_ipv4.seqnum = no ? false : true; return CMD_SUCCESS; } @@ -1581,7 +1582,7 @@ DEFPY (ipv6_prefix_list_sequence_number, PREFIX_LIST_STR "Include/exclude sequence numbers in NVGEN\n") { - prefix_master_ipv6.seqnum = no ? 0 : 1; + prefix_master_ipv6.seqnum = no ? false : true; return CMD_SUCCESS; } @@ -1744,7 +1745,7 @@ static int config_write_prefix_afi(afi_t afi, struct vty *vty) afi == AFI_IP ? "" : "v6", plist->name); if (master->seqnum) - vty_out(vty, "seq %u ", pentry->seq); + vty_out(vty, "seq %" PRId64 " ", pentry->seq); vty_out(vty, "%s ", prefix_list_type_str(pentry)); @@ -1783,7 +1784,7 @@ static int config_write_prefix_afi(afi_t afi, struct vty *vty) afi == AFI_IP ? "" : "v6", plist->name); if (master->seqnum) - vty_out(vty, "seq %u ", pentry->seq); + vty_out(vty, "seq %" PRId64 " ", pentry->seq); vty_out(vty, "%s", prefix_list_type_str(pentry)); @@ -1959,7 +1960,8 @@ int prefix_bgp_show_prefix_list(struct vty *vty, afi_t afi, char *name, struct prefix *p = &pentry->prefix; char buf[BUFSIZ]; - vty_out(vty, " seq %u %s %s/%d", pentry->seq, + vty_out(vty, " seq %" PRId64 " %s %s/%d", + pentry->seq, prefix_list_type_str(pentry), inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen); diff --git a/lib/plist_int.h b/lib/plist_int.h index aa81a3bce2..6bc2d034d6 100644 --- a/lib/plist_int.h +++ b/lib/plist_int.h @@ -48,7 +48,7 @@ struct prefix_list { /* Each prefix-list's entry. */ struct prefix_list_entry { - int seq; + int64_t seq; int le; int ge; diff --git a/lib/routemap.c b/lib/routemap.c index ea61043a8d..892b19dac5 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -722,7 +722,7 @@ static void route_map_delete(struct route_map *map) /* Clear all dependencies */ route_map_clear_all_references(name); - map->deleted = 1; + map->deleted = true; /* Execute deletion hook. */ if (route_map_master.delete_hook) { (*route_map_master.delete_hook)(name); @@ -762,19 +762,19 @@ int route_map_mark_updated(const char *name, int del_later) map = route_map_lookup_by_name(name); - /* If we did not find the routemap with deleted=0 try again - * with deleted=1 + /* If we did not find the routemap with deleted=false try again + * with deleted=true */ if (!map) { memset(&tmp_map, 0, sizeof(struct route_map)); tmp_map.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); - tmp_map.deleted = 1; + tmp_map.deleted = true; map = hash_lookup(route_map_master_hash, &tmp_map); XFREE(MTYPE_ROUTE_MAP_NAME, tmp_map.name); } if (map) { - map->to_be_processed = 1; + map->to_be_processed = true; ret = 0; } @@ -786,7 +786,7 @@ int route_map_clear_updated(struct route_map *map) int ret = -1; if (map) { - map->to_be_processed = 0; + map->to_be_processed = false; if (map->deleted) route_map_free_map(map); } @@ -2743,7 +2743,7 @@ void route_map_finish(void) /* cleanup route_map */ while (route_map_master.head) { struct route_map *map = route_map_master.head; - map->to_be_processed = 0; + map->to_be_processed = false; route_map_delete(map); } diff --git a/lib/routemap.h b/lib/routemap.h index 0046b77c46..990c7fa72f 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -158,8 +158,8 @@ struct route_map { struct route_map *prev; /* Maintain update info */ - int to_be_processed; /* True if modification isn't acted on yet */ - int deleted; /* If 1, then this node will be deleted */ + bool to_be_processed; /* True if modification isn't acted on yet */ + bool deleted; /* If 1, then this node will be deleted */ QOBJ_FIELDS }; diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index cdc047e5ae..867dc9cd15 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -2611,20 +2611,25 @@ DEFUN (vtysh_write_memory, /* If integrated frr.conf explicitely set. */ if (want_config_integrated()) { ret = CMD_WARNING_CONFIG_FAILED; + + /* first attempt to use watchfrr if it's available */ + bool used_watchfrr = false; + for (i = 0; i < array_size(vtysh_client); i++) if (vtysh_client[i].flag == VTYSH_WATCHFRR) break; - if (i < array_size(vtysh_client) && vtysh_client[i].fd != -1) + if (i < array_size(vtysh_client) && vtysh_client[i].fd != -1) { + used_watchfrr = true; ret = vtysh_client_execute(&vtysh_client[i], "do write integrated", outputfile); + } /* - * If watchfrr returns CMD_WARNING_CONFIG_FAILED this means - * that it could not write the config, but additionally - * indicates that we should not try either + * If we didn't use watchfrr, fallback to writing the config + * ourselves */ - if (ret != CMD_SUCCESS && ret != CMD_WARNING_CONFIG_FAILED) { + if (!used_watchfrr) { printf("\nWarning: attempting direct configuration write without " "watchfrr.\nFile permissions and ownership may be " "incorrect, or write may fail.\n\n"); |
