diff options
| -rw-r--r-- | bgpd/bgp_clist.c | 113 | ||||
| -rw-r--r-- | bgpd/bgp_clist.h | 15 | ||||
| -rw-r--r-- | bgpd/bgp_route.c | 4 | ||||
| -rw-r--r-- | bgpd/bgp_routemap.c | 65 | ||||
| -rw-r--r-- | bgpd/bgp_vty.c | 6 | ||||
| -rwxr-xr-x | configure.ac | 2 | ||||
| -rw-r--r-- | doc/user/bgp.rst | 7 | ||||
| -rw-r--r-- | doc/user/installation.rst | 72 |
8 files changed, 233 insertions, 51 deletions
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index c4a20ca233..84a00488c1 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -26,6 +26,7 @@ #include "queue.h" #include "filter.h" #include "stream.h" +#include "jhash.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_community.h" @@ -35,6 +36,31 @@ #include "bgpd/bgp_regex.h" #include "bgpd/bgp_clist.h" +static uint32_t bgp_clist_hash_key_community_list(void *data) +{ + struct community_list *cl = data; + + if (cl->name_hash) + return cl->name_hash; + + cl->name_hash = bgp_clist_hash_key(cl->name); + return cl->name_hash; +} + +static bool bgp_clist_hash_cmp_community_list(const void *a1, const void *a2) +{ + const struct community_list *cl1 = a1; + const struct community_list *cl2 = a2; + + if (cl1->name_hash != cl2->name_hash) + return false; + + if (strcmp(cl1->name, cl2->name) == 0) + return true; + + return false; +} + /* Lookup master structure for community-list or extcommunity-list. */ struct community_list_master * @@ -125,6 +151,10 @@ community_list_insert(struct community_list_handler *ch, const char *name, /* Allocate new community_list and copy given name. */ new = community_list_new(); new->name = XSTRDUP(MTYPE_COMMUNITY_LIST_NAME, name); + new->name_hash = bgp_clist_hash_key_community_list(new); + + /* Save for later */ + hash_get(cm->hash, new, hash_alloc_intern); /* If name is made by all digit character. We treat it as number. */ @@ -194,9 +224,11 @@ community_list_insert(struct community_list_handler *ch, const char *name, } struct community_list *community_list_lookup(struct community_list_handler *ch, - const char *name, int master) + const char *name, + uint32_t name_hash, + int master) { - struct community_list *list; + struct community_list lookup; struct community_list_master *cm; if (!name) @@ -206,14 +238,9 @@ struct community_list *community_list_lookup(struct community_list_handler *ch, if (!cm) return NULL; - for (list = cm->num.head; list; list = list->next) - if (strcmp(list->name, name) == 0) - return list; - for (list = cm->str.head; list; list = list->next) - if (strcmp(list->name, name) == 0) - return list; - - return NULL; + lookup.name = (char *)name; + lookup.name_hash = name_hash; + return hash_get(cm->hash, &lookup, NULL); } static struct community_list * @@ -222,13 +249,14 @@ community_list_get(struct community_list_handler *ch, const char *name, { struct community_list *list; - list = community_list_lookup(ch, name, master); + list = community_list_lookup(ch, name, 0, master); if (!list) list = community_list_insert(ch, name, master); return list; } -static void community_list_delete(struct community_list *list) +static void community_list_delete(struct community_list_master *cm, + struct community_list *list) { struct community_list_list *clist; struct community_entry *entry, *next; @@ -250,6 +278,7 @@ static void community_list_delete(struct community_list *list) else clist->head = list->next; + hash_release(cm->hash, list); community_list_free(list); } @@ -273,7 +302,8 @@ static void community_list_entry_add(struct community_list *list, } /* Delete community-list entry from the list. */ -static void community_list_entry_delete(struct community_list *list, +static void community_list_entry_delete(struct community_list_master *cm, + struct community_list *list, struct community_entry *entry) { if (entry->next) @@ -289,7 +319,7 @@ static void community_list_entry_delete(struct community_list *list, community_entry_free(entry); if (community_list_empty_p(list)) - community_list_delete(list); + community_list_delete(cm, list); } /* Lookup community-list entry from the list. */ @@ -882,18 +912,20 @@ int community_list_set(struct community_list_handler *ch, const char *name, int community_list_unset(struct community_list_handler *ch, const char *name, const char *str, int direct, int style) { + struct community_list_master *cm = NULL; struct community_entry *entry = NULL; struct community_list *list; struct community *com = NULL; /* Lookup community list. */ - list = community_list_lookup(ch, name, COMMUNITY_LIST_MASTER); + list = community_list_lookup(ch, name, 0, COMMUNITY_LIST_MASTER); if (list == NULL) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; + cm = community_list_master_lookup(ch, COMMUNITY_LIST_MASTER); /* Delete all of entry belongs to this community-list. */ if (!str) { - community_list_delete(list); + community_list_delete(cm, list); route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED); return 0; } @@ -910,7 +942,7 @@ int community_list_unset(struct community_list_handler *ch, const char *name, if (!entry) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; - community_list_entry_delete(list, entry); + community_list_entry_delete(cm, list, entry); route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED); return 0; @@ -1031,19 +1063,21 @@ int lcommunity_list_set(struct community_list_handler *ch, const char *name, int lcommunity_list_unset(struct community_list_handler *ch, const char *name, const char *str, int direct, int style) { + struct community_list_master *cm = NULL; struct community_entry *entry = NULL; struct community_list *list; struct lcommunity *lcom = NULL; regex_t *regex = NULL; /* Lookup community list. */ - list = community_list_lookup(ch, name, LARGE_COMMUNITY_LIST_MASTER); + list = community_list_lookup(ch, name, 0, LARGE_COMMUNITY_LIST_MASTER); if (list == NULL) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; + cm = community_list_master_lookup(ch, LARGE_COMMUNITY_LIST_MASTER); /* Delete all of entry belongs to this community-list. */ if (!str) { - community_list_delete(list); + community_list_delete(cm, list); return 0; } @@ -1068,7 +1102,7 @@ int lcommunity_list_unset(struct community_list_handler *ch, const char *name, if (!entry) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; - community_list_entry_delete(list, entry); + community_list_entry_delete(cm, list, entry); return 0; } @@ -1147,18 +1181,20 @@ int extcommunity_list_set(struct community_list_handler *ch, const char *name, int extcommunity_list_unset(struct community_list_handler *ch, const char *name, const char *str, int direct, int style) { + struct community_list_master *cm = NULL; struct community_entry *entry = NULL; struct community_list *list; struct ecommunity *ecom = NULL; /* Lookup extcommunity list. */ - list = community_list_lookup(ch, name, EXTCOMMUNITY_LIST_MASTER); + list = community_list_lookup(ch, name, 0, EXTCOMMUNITY_LIST_MASTER); if (list == NULL) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; + cm = community_list_master_lookup(ch, EXTCOMMUNITY_LIST_MASTER); /* Delete all of entry belongs to this extcommunity-list. */ if (!str) { - community_list_delete(list); + community_list_delete(cm, list); route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED); return 0; } @@ -1175,7 +1211,7 @@ int extcommunity_list_unset(struct community_list_handler *ch, const char *name, if (!entry) return COMMUNITY_LIST_ERR_CANT_FIND_LIST; - community_list_entry_delete(list, entry); + community_list_entry_delete(cm, list, entry); route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED); return 0; @@ -1187,6 +1223,22 @@ struct community_list_handler *community_list_init(void) struct community_list_handler *ch; ch = XCALLOC(MTYPE_COMMUNITY_LIST_HANDLER, sizeof(struct community_list_handler)); + + ch->community_list.hash = + hash_create_size(4, bgp_clist_hash_key_community_list, + bgp_clist_hash_cmp_community_list, + "Community List Number Quick Lookup"); + + ch->extcommunity_list.hash = + hash_create_size(4, bgp_clist_hash_key_community_list, + bgp_clist_hash_cmp_community_list, + "Extended Community List Quick Lookup"); + + ch->lcommunity_list.hash = + hash_create_size(4, bgp_clist_hash_key_community_list, + bgp_clist_hash_cmp_community_list, + "Large Community List Quick Lookup"); + return ch; } @@ -1198,21 +1250,24 @@ void community_list_terminate(struct community_list_handler *ch) cm = &ch->community_list; while ((list = cm->num.head) != NULL) - community_list_delete(list); + community_list_delete(cm, list); while ((list = cm->str.head) != NULL) - community_list_delete(list); + community_list_delete(cm, list); + hash_free(cm->hash); cm = &ch->lcommunity_list; while ((list = cm->num.head) != NULL) - community_list_delete(list); + community_list_delete(cm, list); while ((list = cm->str.head) != NULL) - community_list_delete(list); + community_list_delete(cm, list); + hash_free(cm->hash); cm = &ch->extcommunity_list; while ((list = cm->num.head) != NULL) - community_list_delete(list); + community_list_delete(cm, list); while ((list = cm->str.head) != NULL) - community_list_delete(list); + community_list_delete(cm, list); + hash_free(cm->hash); XFREE(MTYPE_COMMUNITY_LIST_HANDLER, ch); } diff --git a/bgpd/bgp_clist.h b/bgpd/bgp_clist.h index 9efb34d7b9..9cf8a14a6a 100644 --- a/bgpd/bgp_clist.h +++ b/bgpd/bgp_clist.h @@ -21,6 +21,8 @@ #ifndef _QUAGGA_BGP_CLIST_H #define _QUAGGA_BGP_CLIST_H +#include "jhash.h" + /* Master Community-list. */ #define COMMUNITY_LIST_MASTER 0 #define EXTCOMMUNITY_LIST_MASTER 1 @@ -47,6 +49,9 @@ struct community_list { /* Name of the community-list. */ char *name; + /* Stored hash value of name, to further speed up hash operations */ + uint32_t name_hash; + /* String or number. */ int sort; @@ -100,6 +105,7 @@ struct community_list_list { struct community_list_master { struct community_list_list num; struct community_list_list str; + struct hash *hash; }; /* Community-list handler. community_list_init() returns this @@ -151,7 +157,8 @@ extern struct community_list_master * community_list_master_lookup(struct community_list_handler *, int); extern struct community_list * -community_list_lookup(struct community_list_handler *, const char *, int); +community_list_lookup(struct community_list_handler *c, const char *name, + uint32_t name_hash, int master); extern int community_list_match(struct community *, struct community_list *); extern int ecommunity_list_match(struct ecommunity *, struct community_list *); @@ -163,4 +170,10 @@ extern struct community *community_list_match_delete(struct community *, extern struct lcommunity * lcommunity_list_match_delete(struct lcommunity *lcom, struct community_list *list); + +static inline uint32_t bgp_clist_hash_key(char *name) +{ + return jhash(name, sizeof(name), 0xdeadbeaf); +} + #endif /* _QUAGGA_BGP_CLIST_H */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 3561674700..6bce7261ae 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -9278,7 +9278,7 @@ static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp, { struct community_list *list; - list = community_list_lookup(bgp_clist, lcom, + list = community_list_lookup(bgp_clist, lcom, 0, LARGE_COMMUNITY_LIST_MASTER); if (list == NULL) { vty_out(vty, "%% %s is not a valid large-community-list name\n", @@ -9799,7 +9799,7 @@ static int bgp_show_community_list(struct vty *vty, struct bgp *bgp, { struct community_list *list; - list = community_list_lookup(bgp_clist, com, COMMUNITY_LIST_MASTER); + list = community_list_lookup(bgp_clist, com, 0, COMMUNITY_LIST_MASTER); if (list == NULL) { vty_out(vty, "%% %s is not a valid community-list name\n", com); return CMD_WARNING; diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 30159f9023..d7ee2aa19f 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -1037,6 +1037,7 @@ struct route_map_rule_cmd route_match_aspath_cmd = { /* `match community COMMUNIY' */ struct rmap_community { char *name; + uint32_t name_hash; int exact; }; @@ -1048,13 +1049,14 @@ static route_map_result_t route_match_community(void *rule, { struct community_list *list; struct bgp_path_info *path; - struct rmap_community *rcom; + struct rmap_community *rcom = rule; if (type == RMAP_BGP) { path = object; rcom = rule; list = community_list_lookup(bgp_clist, rcom->name, + rcom->name_hash, COMMUNITY_LIST_MASTER); if (!list) return RMAP_NOMATCH; @@ -1090,6 +1092,8 @@ static void *route_match_community_compile(const char *arg) rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); rcom->exact = 0; } + + rcom->name_hash = bgp_clist_hash_key(rcom->name); return rcom; } @@ -1115,13 +1119,13 @@ static route_map_result_t route_match_lcommunity(void *rule, { struct community_list *list; struct bgp_path_info *path; - struct rmap_community *rcom; + struct rmap_community *rcom = rule; if (type == RMAP_BGP) { path = object; - rcom = rule; list = community_list_lookup(bgp_clist, rcom->name, + rcom->name_hash, LARGE_COMMUNITY_LIST_MASTER); if (!list) return RMAP_NOMATCH; @@ -1150,6 +1154,8 @@ static void *route_match_lcommunity_compile(const char *arg) rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); rcom->exact = 0; } + + rcom->name_hash = bgp_clist_hash_key(rcom->name); return rcom; } @@ -1176,11 +1182,13 @@ static route_map_result_t route_match_ecommunity(void *rule, { struct community_list *list; struct bgp_path_info *path; + struct rmap_community *rcom = rule; if (type == RMAP_BGP) { path = object; - list = community_list_lookup(bgp_clist, (char *)rule, + list = community_list_lookup(bgp_clist, rcom->name, + rcom->name_hash, EXTCOMMUNITY_LIST_MASTER); if (!list) return RMAP_NOMATCH; @@ -1194,13 +1202,22 @@ static route_map_result_t route_match_ecommunity(void *rule, /* Compile function for extcommunity match. */ static void *route_match_ecommunity_compile(const char *arg) { - return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); + struct rmap_community *rcom; + + rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community)); + rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg); + rcom->name_hash = bgp_clist_hash_key(rcom->name); + + return rcom; } /* Compile function for extcommunity match. */ static void route_match_ecommunity_free(void *rule) { - XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); + struct rmap_community *rcom = rule; + + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom); } /* Route map commands for community matching. */ @@ -1932,13 +1949,15 @@ static route_map_result_t route_set_lcommunity_delete(void *rule, struct lcommunity *new; struct lcommunity *old; struct bgp_path_info *path; + struct rmap_community *rcom = rule; if (type == RMAP_BGP) { - if (!rule) + if (!rcom) return RMAP_OKAY; path = object; - list = community_list_lookup(bgp_clist, rule, + list = community_list_lookup(bgp_clist, rcom->name, + rcom->name_hash, LARGE_COMMUNITY_LIST_MASTER); old = path->attr->lcommunity; @@ -1975,10 +1994,13 @@ static route_map_result_t route_set_lcommunity_delete(void *rule, /* Compile function for set lcommunity. */ static void *route_set_lcommunity_delete_compile(const char *arg) { + struct rmap_community *rcom; char *p; char *str; int len; + rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community)); + p = strchr(arg, ' '); if (p) { len = p - arg; @@ -1987,13 +2009,18 @@ static void *route_set_lcommunity_delete_compile(const char *arg) } else str = NULL; - return str; + rcom->name = str; + rcom->name_hash = bgp_clist_hash_key(rcom->name); + return rcom; } /* Free function for set lcommunity. */ static void route_set_lcommunity_delete_free(void *rule) { - XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); + struct rmap_community *rcom = rule; + + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom); } /* Set lcommunity rule structure. */ @@ -2017,13 +2044,15 @@ static route_map_result_t route_set_community_delete( struct community *new; struct community *old; struct bgp_path_info *path; + struct rmap_community *rcom = rule; if (type == RMAP_BGP) { - if (!rule) + if (!rcom) return RMAP_OKAY; path = object; - list = community_list_lookup(bgp_clist, rule, + list = community_list_lookup(bgp_clist, rcom->name, + rcom->name_hash, COMMUNITY_LIST_MASTER); old = path->attr->community; @@ -2060,10 +2089,13 @@ static route_map_result_t route_set_community_delete( /* Compile function for set community. */ static void *route_set_community_delete_compile(const char *arg) { + struct rmap_community *rcom; char *p; char *str; int len; + rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community)); + p = strchr(arg, ' '); if (p) { len = p - arg; @@ -2072,13 +2104,18 @@ static void *route_set_community_delete_compile(const char *arg) } else str = NULL; - return str; + rcom->name = str; + rcom->name_hash = bgp_clist_hash_key(rcom->name); + return rcom; } /* Free function for set community. */ static void route_set_community_delete_free(void *rule) { - XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); + struct rmap_community *rcom = rule; + + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom->name); + XFREE(MTYPE_ROUTE_MAP_COMPILED, rcom); } /* Set community rule structure. */ diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index cf1421f5a6..c6e48cc160 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -14329,7 +14329,7 @@ DEFUN (show_community_list_arg, vty_out(vty, "'show bgp community-list <(1-500)|WORD>'\n"); zlog_warn("Deprecated option: 'ip show community-list <(1-500)|WORD>' being used"); } - list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, + list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, 0, COMMUNITY_LIST_MASTER); if (!list) { vty_out(vty, "%% Can't find community-list\n"); @@ -14854,7 +14854,7 @@ DEFUN (show_lcommunity_list_arg, zlog_warn("Deprecated option: 'ip show large-community-list <(1-500)|WORD>' being used"); } - list = community_list_lookup(bgp_clist, argv[3]->arg, + list = community_list_lookup(bgp_clist, argv[3]->arg, 0, LARGE_COMMUNITY_LIST_MASTER); if (!list) { vty_out(vty, "%% Can't find extcommunity-list\n"); @@ -15255,7 +15255,7 @@ DEFUN (show_extcommunity_list_arg, vty_out(vty, "'show bgp extcommunity-list <(1-500)|WORD>'\n"); zlog_warn("Deprecated option: 'ip show extcommunity-list <(1-500)|WORD>' being used"); } - list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, + list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, 0, EXTCOMMUNITY_LIST_MASTER); if (!list) { vty_out(vty, "%% Can't find extcommunity-list\n"); diff --git a/configure.ac b/configure.ac index 0d75f7d319..7f08e8e764 100755 --- a/configure.ac +++ b/configure.ac @@ -587,7 +587,7 @@ AC_SUBST([DFLT_NAME]) AC_DEFINE_UNQUOTED([DFLT_NAME], ["$DFLT_NAME"], [Name of the configuration default set]) if test "${enable_shell_access}" = "yes"; then - AC_DEFINE([HAVE_SHELL_ACCESS], [1], [Allow user to use ssh/telnet/bash]) + AC_DEFINE([HAVE_SHELL_ACCESS], [1], [Allow user to use ssh/telnet/bash, be aware this is considered insecure]) fi AM_CONDITIONAL([FPM], [test "x$enable_fpm" = "xyes"]) diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index a27243ea77..5b453e75c3 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -968,6 +968,13 @@ Configuring Peers and will not be displayed as part of a `show run`. The no form of the command turns off this ability. +.. index:: [no] bgp default ipv4-unicast +.. clicmd:: [no] bgp default ipv4-unicast + + This command allows the user to specify that v4 peering is turned + on by default or not. This command defaults to on and is not displayed. + The `no bgp default ipv4-unicast` form of the command is displayed. + .. _bgp-peer-filtering: Peer Filtering diff --git a/doc/user/installation.rst b/doc/user/installation.rst index 2decfcc4b2..ebca53ea32 100644 --- a/doc/user/installation.rst +++ b/doc/user/installation.rst @@ -79,9 +79,23 @@ options from the list below. .. program:: configure +.. option:: --enable-tcmalloc + + Enable the alternate malloc library. In some cases this is faster and more efficient, + in some cases it is not. + +.. option:: --disable-doc + + Do not build any documentation, including this one. + +.. option:: --enable-doc-html + + From the documentation build html docs as well in addition to the normal output. + .. option:: --disable-zebra - Do not build zebra daemon. + Do not build zebra daemon. This generally only be useful in a scenario where + you are building bgp as a standalone server. .. option:: --disable-ripd @@ -103,6 +117,52 @@ options from the list below. Do not build bgpd. +.. option:: --disable-ldpd + + Do not build ldpd. + +.. option:: --disable-nhrpd + + Do not build nhrpd. + +.. option:: --disable-eigrpd + + Do not build eigrpd. + +.. option:: --disable-babeld + + Do not build babeld. + +.. option:: --disable-watchfrr + + Do not build watchfrr. Watchfrr is used to integrate daemons into startup/shutdown + software available on your machine. This is needed for systemd integration, if you + disable watchfrr you cannot have any systemd integration. + +.. option:: --enable-systemd + + Build watchfrr with systemd integration, this will allow FRR to communicate with + systemd to tell systemd if FRR has come up properly. + +.. option:: --disable-pimd + + Turn off building of pimd. On some BSD platforms pimd will not build properly due + to lack of kernel support. + +.. option:: --disable-pbrd + + Turn off building of pbrd. This daemon currently requires linux in order to function + properly. + +.. option:: --enable-sharpd + + Turn on building of sharpd. This daemon facilitates testing of FRR and can also + be used as a quick and easy route generator. + +.. option:: --disable-staticd + + Do not build staticd. This daemon is necessary if you want static routes. + .. option:: --disable-bfdd Do not build bfdd. @@ -112,6 +172,10 @@ options from the list below. Make *bgpd* which does not make bgp announcements at all. This feature is good for using *bgpd* as a BGP announcement listener. +.. option:: --disable-bgp-vnc + + Turn off bgpd's ability to use VNC. + .. option:: --enable-datacenter Enable system defaults to work as if in a Data Center. See defaults.h @@ -213,6 +277,12 @@ options from the list below. hardcoded arrays that FRR builds towards, so we need to know how big to make these arrays at build time. +.. option:: --enable-shell-access + + Turn on the ability of FRR to access some shell options( telnet/ssh/bash/etc. ) + from vtysh itself. This option is considered extremely unsecure and should only + be considered for usage if you really really know what you are doing. + .. option:: --enable-gcov Code coverage reports from gcov require adjustments to the C and LD flags. |
