summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_errors.c6
-rw-r--r--bgpd/bgp_errors.h1
-rw-r--r--bgpd/bgp_network.c6
-rw-r--r--bgpd/bgp_vty.c4
-rw-r--r--doc/user/basic.rst16
-rw-r--r--doc/user/setup.rst35
-rw-r--r--doc/user/zebra.rst7
-rw-r--r--lib/sockunion.c15
-rw-r--r--lib/sockunion.h1
-rw-r--r--lib/thread.c5
-rw-r--r--tools/etc/frr/daemons8
-rw-r--r--zebra/main.c44
-rw-r--r--zebra/rib.h2
-rw-r--r--zebra/zebra_rib.c13
-rw-r--r--zebra/zebra_router.h7
15 files changed, 97 insertions, 73 deletions
diff --git a/bgpd/bgp_errors.c b/bgpd/bgp_errors.c
index 753ee6baf1..6e181697d6 100644
--- a/bgpd/bgp_errors.c
+++ b/bgpd/bgp_errors.c
@@ -122,12 +122,6 @@ static struct log_ref ferr_bgp_warn[] = {
.suggestion = "Please collect log files and open Issue",
},
{
- .code = EC_BGP_NO_SOCKOPT_MARK,
- .title = "Unable to set socket MARK option",
- .description = "BGP attempted to set the SO_MARK option for a socket and was unable to do so",
- .suggestion = "Please collect log files and open Issue",
- },
- {
.code = EC_BGP_EVPN_PMSI_PRESENT,
.title = "BGP Received a EVPN NLRI with PMSI included",
.description = "BGP has received a type-3 NLRI with PMSI information. At this time FRR is not capable of properly handling this NLRI type",
diff --git a/bgpd/bgp_errors.h b/bgpd/bgp_errors.h
index 13bd318e27..39d043ff13 100644
--- a/bgpd/bgp_errors.h
+++ b/bgpd/bgp_errors.h
@@ -88,7 +88,6 @@ enum bgp_log_refs {
EC_BGP_UPDATE_PACKET_LONG,
EC_BGP_UNRECOGNIZED_CAPABILITY,
EC_BGP_NO_TCP_MD5,
- EC_BGP_NO_SOCKOPT_MARK,
EC_BGP_EVPN_PMSI_PRESENT,
EC_BGP_EVPN_VPN_VNI,
EC_BGP_EVPN_ESI,
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 6a5c2c4b38..8e18ed7529 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -588,8 +588,6 @@ static int bgp_update_source(struct peer *peer)
return ret;
}
-#define DATAPLANE_MARK 254 /* main table ID */
-
/* BGP try to connect to the peer. */
int bgp_connect(struct peer *peer)
{
@@ -619,10 +617,6 @@ int bgp_connect(struct peer *peer)
sockopt_reuseaddr(peer->fd);
sockopt_reuseport(peer->fd);
- if (sockopt_mark_default(peer->fd, DATAPLANE_MARK, &bgpd_privs) < 0)
- flog_warn(EC_BGP_NO_SOCKOPT_MARK,
- "Unable to set mark on FD for peer %s, err=%s",
- peer->host, safe_strerror(errno));
#ifdef IPTOS_PREC_INTERNETCONTROL
frr_elevate_privs(&bgpd_privs) {
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 2a08619ec3..ae51f1d780 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -10909,11 +10909,11 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
if (p->password)
vty_out(vty, "Peer Authentication Enabled\n");
- vty_out(vty, "Read thread: %s Write thread: %s\n",
+ vty_out(vty, "Read thread: %s Write thread: %s FD used: %d\n",
p->t_read ? "on" : "off",
CHECK_FLAG(p->thread_flags, PEER_THREAD_WRITES_ON)
? "on"
- : "off");
+ : "off", p->fd);
}
if (p->notify.code == BGP_NOTIFY_OPEN_ERR
diff --git a/doc/user/basic.rst b/doc/user/basic.rst
index f55b1b9d73..3df60169f7 100644
--- a/doc/user/basic.rst
+++ b/doc/user/basic.rst
@@ -414,6 +414,22 @@ Terminal Mode Commands
(view) show [ip] bgp l2vpn evpn all overlay
...
+.. _common-show-commands:
+
+.. index:: show thread cpu
+.. clicmd:: show thread cpu [r|w|t|e|x]
+
+ This command displays system run statistics for all the different event
+ types. If no options is specified all different run types are displayed
+ together. Additionally you can ask to look at (r)ead, (w)rite, (t)imer,
+ (e)vent and e(x)ecute thread event types.
+
+.. index:: show thread poll
+.. clicmd:: show thread poll
+
+ This command displays FRR's poll data. It allows a glimpse into how
+ we are setting each individual fd for the poll command at that point
+ in time.
.. _common-invocation-options:
diff --git a/doc/user/setup.rst b/doc/user/setup.rst
index ffefe37905..2cdd3a7c7f 100644
--- a/doc/user/setup.rst
+++ b/doc/user/setup.rst
@@ -6,8 +6,8 @@ Basic Setup
After installing FRR, some basic configuration must be completed before it is
ready to use.
-Daemons File
-------------
+Daemons Configuration File
+--------------------------
After a fresh install, starting FRR will do nothing. This is because daemons
must be explicitly enabled by editing a file in your configuration directory.
This file is usually located at :file:`/etc/frr/daemons` and determines which
@@ -34,19 +34,6 @@ systemd. The file initially looks like this:
bfdd=no
fabricd=no
-To enable a particular daemon, simply change the corresponding 'no' to 'yes'.
-Subsequent service restarts should start the daemon.
-
-Daemons Configuration File
---------------------------
-There is another file that controls the default options passed to daemons when
-starting FRR as a service. This file is located in your configuration
-directory, usually at :file:`/etc/frr/daemons`.
-
-This file has several parts. Here is an example:
-
-::
-
#
# If this option is set the /etc/init.d/frr script automatically loads
# the config via "vtysh -b" when the servers are started.
@@ -71,6 +58,7 @@ This file has several parts. Here is an example:
bfdd_options=" --daemon -A 127.0.0.1"
fabricd_options=" --daemon -A 127.0.0.1"
+ #MAX_FDS=1024
# The list of daemons to watch is automatically generated by the init script.
#watchfrr_options=""
@@ -85,6 +73,13 @@ Breaking this file down:
::
+ bgpd=yes
+
+To enable a particular daemon, simply change the corresponding 'no' to 'yes'.
+Subsequent service restarts should start the daemon.
+
+::
+
vtysh_enable=yes
As the comment says, this causes :ref:`VTYSH <vty-shell>` to apply
@@ -93,6 +88,16 @@ reasons touched on in the VTYSH documentation and should generally be enabled.
::
+ MAX_FDS=1024
+
+This allows the operator to control the number of open file descriptors
+each daemon is allowed to start with. The current assumed value on
+most operating systems is 1024. If the operator plans to run bgp with
+several thousands of peers than this is where we would modify FRR to
+allow this to happen.
+
+::
+
zebra_options=" -s 90000000 --daemon -A 127.0.0.1"
bgpd_options=" --daemon -A 127.0.0.1"
...
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index f38db9d241..40d8949297 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -23,9 +23,12 @@ Besides the common invocation options (:ref:`common-invocation-options`), the
Runs in batch mode. *zebra* parses configuration file and terminates
immediately.
-.. option:: -k, --keep_kernel
+.. option:: -K TIME, --graceful_restart TIME
- When zebra starts up, don't delete old self inserted routes.
+ If this option is specified, the graceful restart time is TIME seconds.
+ Zebra, when started, will read in routes. Those routes that Zebra
+ identifies that it was the originator of will be swept in TIME seconds.
+ If no time is specified then we will sweep those routes immediately.
.. option:: -r, --retain
diff --git a/lib/sockunion.c b/lib/sockunion.c
index 5afd10eb48..8fa9a3fad9 100644
--- a/lib/sockunion.c
+++ b/lib/sockunion.c
@@ -366,21 +366,6 @@ int sockopt_cork(int sock, int onoff)
return 0;
}
-int sockopt_mark_default(int sock, int mark, struct zebra_privs_t *cap)
-{
-#ifdef SO_MARK
- int ret;
-
- frr_elevate_privs(cap) {
- ret = setsockopt(sock, SOL_SOCKET, SO_MARK, &mark,
- sizeof(mark));
- }
- return ret;
-#else
- return 0;
-#endif
-}
-
int sockopt_minttl(int family, int sock, int minttl)
{
#ifdef IP_MINTTL
diff --git a/lib/sockunion.h b/lib/sockunion.h
index b996735550..7091c1b5e7 100644
--- a/lib/sockunion.h
+++ b/lib/sockunion.h
@@ -93,7 +93,6 @@ extern int sockunion_bind(int sock, union sockunion *, unsigned short,
extern int sockopt_ttl(int family, int sock, int ttl);
extern int sockopt_minttl(int family, int sock, int minttl);
extern int sockopt_cork(int sock, int onoff);
-extern int sockopt_mark_default(int sock, int mark, struct zebra_privs_t *);
extern int sockunion_socket(const union sockunion *su);
extern const char *inet_sutop(const union sockunion *su, char *str);
extern enum connect_result sockunion_connect(int fd, const union sockunion *su,
diff --git a/lib/thread.c b/lib/thread.c
index 7a9a0ab608..d3fb2cdf36 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -281,7 +281,7 @@ DEFUN (show_thread_cpu,
SHOW_STR
"Thread information\n"
"Thread CPU usage\n"
- "Display filter (rwtexb)\n")
+ "Display filter (rwtex)\n")
{
uint8_t filter = (uint8_t)-1U;
int idx = 0;
@@ -312,7 +312,8 @@ static void show_thread_poll_helper(struct vty *vty, struct thread_master *m)
vty_out(vty, "\nShowing poll FD's for %s\n", name);
vty_out(vty, "----------------------%s\n", underline);
- vty_out(vty, "Count: %u\n", (uint32_t)m->handler.pfdcount);
+ vty_out(vty, "Count: %u/%d\n", (uint32_t)m->handler.pfdcount,
+ m->fd_limit);
for (i = 0; i < m->handler.pfdcount; i++)
vty_out(vty, "\t%6d fd:%6d events:%2d revents:%2d\n", i,
m->handler.pfds[i].fd,
diff --git a/tools/etc/frr/daemons b/tools/etc/frr/daemons
index b920621d70..79c52d30d1 100644
--- a/tools/etc/frr/daemons
+++ b/tools/etc/frr/daemons
@@ -56,6 +56,14 @@ bfdd_options=" -A 127.0.0.1"
fabricd_options="-A 127.0.0.1"
vrrpd_options=" -A 127.0.0.1"
+#
+# This is the maximum number of FD's that will be available.
+# Upon startup this is read by the control files and ulimit
+# is called. Uncomment and use a reasonable value for your
+# setup if you are expecting a large number of peers in
+# say BGP.
+#MAX_FDS=1024
+
# The list of daemons to watch is automatically generated by the init script.
#watchfrr_options=""
diff --git a/zebra/main.c b/zebra/main.c
index cff5e06933..5797a5846a 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -74,8 +74,7 @@ int retain_mode = 0;
/* Allow non-quagga entities to delete quagga routes */
int allow_delete = 0;
-/* Don't delete kernel route. */
-int keep_kernel_mode = 0;
+int graceful_restart;
bool v6_rr_semantics = false;
@@ -95,6 +94,7 @@ struct option longopts[] = {
{"label_socket", no_argument, NULL, 'l'},
{"retain", no_argument, NULL, 'r'},
{"vrfdefaultname", required_argument, NULL, 'o'},
+ {"graceful_restart", required_argument, NULL, 'K'},
#ifdef HAVE_NETLINK
{"vrfwnetns", no_argument, NULL, 'n'},
{"nl-bufsize", required_argument, NULL, 's'},
@@ -262,13 +262,14 @@ int main(int argc, char **argv)
char *netlink_fuzzing = NULL;
#endif /* HANDLE_NETLINK_FUZZING */
+ graceful_restart = 0;
vrf_configure_backend(VRF_BACKEND_VRF_LITE);
logicalrouter_configure_backend(LOGICALROUTER_BACKEND_NETNS);
frr_preinit(&zebra_di, argc, argv);
frr_opt_add(
- "bakz:e:l:o:r"
+ "baz:e:l:o:rK:"
#ifdef HAVE_NETLINK
"s:n"
#endif
@@ -280,24 +281,24 @@ int main(int argc, char **argv)
#endif /* HANDLE_NETLINK_FUZZING */
,
longopts,
- " -b, --batch Runs in batch mode\n"
- " -a, --allow_delete Allow other processes to delete zebra routes\n"
- " -z, --socket Set path of zebra socket\n"
- " -e, --ecmp Specify ECMP to use.\n"
- " -l, --label_socket Socket to external label manager\n"
- " -k, --keep_kernel Don't delete old routes which were installed by zebra.\n"
- " -r, --retain When program terminates, retain added route by zebra.\n"
- " -o, --vrfdefaultname Set default VRF name.\n"
+ " -b, --batch Runs in batch mode\n"
+ " -a, --allow_delete Allow other processes to delete zebra routes\n"
+ " -z, --socket Set path of zebra socket\n"
+ " -e, --ecmp Specify ECMP to use.\n"
+ " -l, --label_socket Socket to external label manager\n"
+ " -r, --retain When program terminates, retain added route by zebra.\n"
+ " -o, --vrfdefaultname Set default VRF name.\n"
+ " -K, --graceful_restart Graceful restart at the kernel level, timer in seconds for expiration\n"
#ifdef HAVE_NETLINK
- " -n, --vrfwnetns Use NetNS as VRF backend\n"
- " -s, --nl-bufsize Set netlink receive buffer size\n"
- " --v6-rr-semantics Use v6 RR semantics\n"
+ " -n, --vrfwnetns Use NetNS as VRF backend\n"
+ " -s, --nl-bufsize Set netlink receive buffer size\n"
+ " --v6-rr-semantics Use v6 RR semantics\n"
#endif /* HAVE_NETLINK */
#if defined(HANDLE_ZAPI_FUZZING)
- " -c <file> Bypass normal startup and use this file for testing of zapi\n"
+ " -c <file> Bypass normal startup and use this file for testing of zapi\n"
#endif /* HANDLE_ZAPI_FUZZING */
#if defined(HANDLE_NETLINK_FUZZING)
- " -w <file> Bypass normal startup and use this file for testing of netlink input\n"
+ " -w <file> Bypass normal startup and use this file for testing of netlink input\n"
#endif /* HANDLE_NETLINK_FUZZING */
);
@@ -316,9 +317,6 @@ int main(int argc, char **argv)
case 'a':
allow_delete = 1;
break;
- case 'k':
- keep_kernel_mode = 1;
- break;
case 'e':
zrouter.multipath_num = atoi(optarg);
if (zrouter.multipath_num > MULTIPATH_NUM
@@ -348,6 +346,9 @@ int main(int argc, char **argv)
case 'r':
retain_mode = 1;
break;
+ case 'K':
+ graceful_restart = atoi(optarg);
+ break;
#ifdef HAVE_NETLINK
case 's':
nl_rcvbufsize = atoi(optarg);
@@ -435,8 +436,9 @@ int main(int argc, char **argv)
* will be equal to the current getpid(). To know about such routes,
* we have to have route_read() called before.
*/
- if (!keep_kernel_mode)
- rib_sweep_route();
+ zrouter.startup_time = monotime(NULL);
+ thread_add_timer(zrouter.master, rib_sweep_route,
+ NULL, graceful_restart, NULL);
/* Needed for BSD routing socket. */
pid = getpid();
diff --git a/zebra/rib.h b/zebra/rib.h
index ca0801c209..0353c9bb99 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -400,7 +400,7 @@ extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p,
extern void rib_update(vrf_id_t vrf_id, rib_update_event_t event);
extern void rib_update_table(struct route_table *table,
rib_update_event_t event);
-extern void rib_sweep_route(void);
+extern int rib_sweep_route(struct thread *t);
extern void rib_sweep_table(struct route_table *table);
extern void rib_close_table(struct route_table *table);
extern void rib_init(void);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 8f27316669..391917ec68 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -3127,6 +3127,7 @@ void rib_sweep_table(struct route_table *table)
for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
RNODE_FOREACH_RE_SAFE (rn, re, next) {
+
if (IS_ZEBRA_DEBUG_RIB)
route_entry_dump(&rn->p, NULL, re);
@@ -3137,6 +3138,14 @@ void rib_sweep_table(struct route_table *table)
continue;
/*
+ * If routes are older than startup_time then
+ * we know we read them in from the kernel.
+ * As such we can safely remove them.
+ */
+ if (zrouter.startup_time < re->uptime)
+ continue;
+
+ /*
* So we are starting up and have received
* routes from the kernel that we have installed
* from a previous run of zebra but not cleaned
@@ -3165,7 +3174,7 @@ void rib_sweep_table(struct route_table *table)
}
/* Sweep all RIB tables. */
-void rib_sweep_route(void)
+int rib_sweep_route(struct thread *t)
{
struct vrf *vrf;
struct zebra_vrf *zvrf;
@@ -3179,6 +3188,8 @@ void rib_sweep_route(void)
}
zebra_router_sweep_route();
+
+ return 0;
}
/* Remove specific by protocol routes from 'table'. */
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index b3def297ac..6c9f3a0f28 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -112,8 +112,15 @@ struct zebra_router {
struct zebra_vrf *evpn_vrf;
uint32_t multipath_num;
+
+ /*
+ * Time for when we sweep the rib from old routes
+ */
+ time_t startup_time;
};
+#define GRACEFUL_RESTART_TIME 60
+
extern struct zebra_router zrouter;
extern void zebra_router_init(void);