summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_io.c8
-rw-r--r--bgpd/bgp_io.h3
-rw-r--r--bgpd/bgp_packet.c33
-rw-r--r--bgpd/bgp_packet.h1
-rw-r--r--bgpd/bgp_vty.c75
-rw-r--r--bgpd/bgp_vty.h1
-rw-r--r--bgpd/bgpd.c9
-rw-r--r--bgpd/bgpd.h4
8 files changed, 112 insertions, 22 deletions
diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c
index 71c281295..c9e300262 100644
--- a/bgpd/bgp_io.c
+++ b/bgpd/bgp_io.c
@@ -381,9 +381,13 @@ static uint16_t bgp_write(struct peer *peer)
unsigned int count = 0;
unsigned int oc = 0;
uint16_t status = 0;
+ uint32_t wpkt_quanta_old;
- while (count < peer->bgp->wpkt_quanta
- && (s = stream_fifo_head(peer->obuf))) {
+ // cache current write quanta
+ wpkt_quanta_old = atomic_load_explicit(&peer->bgp->wpkt_quanta,
+ memory_order_relaxed);
+
+ while (count < wpkt_quanta_old && (s = stream_fifo_head(peer->obuf))) {
int writenum;
do {
writenum = stream_get_endp(s) - stream_get_getp(s);
diff --git a/bgpd/bgp_io.h b/bgpd/bgp_io.h
index 3e1701003..6cda227a0 100644
--- a/bgpd/bgp_io.h
+++ b/bgpd/bgp_io.h
@@ -23,6 +23,9 @@
#ifndef _FRR_BGP_IO_H
#define _FRR_BGP_IO_H
+#define BGP_WRITE_PACKET_MAX 10U
+#define BGP_READ_PACKET_MAX 10U
+
#include "bgpd/bgpd.h"
#include "frr_pthread.h"
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 28964deef..7c924fd73 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -1963,15 +1963,35 @@ int bgp_process_packet(struct thread *thread)
{
/* Yes first of all get peer pointer. */
struct peer *peer;
+ uint32_t rpkt_quanta_old;
+
peer = THREAD_ARG(thread);
+ rpkt_quanta_old = atomic_load_explicit(&peer->bgp->rpkt_quanta,
+ memory_order_relaxed);
+
+ /*
+ * XXX: At present multiple packet reads per input cycle are
+ * problematic. The issue is that some of the packet processing
+ * functions perform their own FSM checks, that arguably should be
+ * located in bgp_fsm.c. For example if we are in OpenConfirm process a
+ * Keepalive, then a keepalive-received event is placed on the event
+ * queue to handle later. If we then process an Update before that
+ * event has popped, the update function checks that the peer status is
+ * in Established and if not tears down the session. Therefore we'll
+ * limit input processing to 1 packet per cycle, as it traditionally
+ * was, until this problem is rectified.
+ *
+ * @qlyoung June 2017
+ */
+ rpkt_quanta_old = 1;
/* Guard against scheduled events that occur after peer deletion. */
if (peer->status == Deleted || peer->status == Clearing)
return 0;
- int processed = 0;
+ unsigned int processed = 0;
- while (processed < 5 && peer->ibuf->count > 0) {
+ while (processed < rpkt_quanta_old) {
u_char type = 0;
bgp_size_t size;
char notify_data_length[2];
@@ -2054,10 +2074,13 @@ int bgp_process_packet(struct thread *thread)
}
}
- if (peer->ibuf->count > 0) { // more work to do, come back later
- thread_add_background(bm->master, bgp_process_packet, peer, 0,
- &peer->t_process_packet);
+ pthread_mutex_lock(&peer->io_mtx);
+ {
+ if (peer->ibuf->count > 0) // more work to do, come back later
+ thread_add_event(bm->master, bgp_process_packet, peer,
+ 0, NULL);
}
+ pthread_mutex_unlock(&peer->io_mtx);
return 0;
}
diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h
index 502dbbdee..62c3fe671 100644
--- a/bgpd/bgp_packet.h
+++ b/bgpd/bgp_packet.h
@@ -24,7 +24,6 @@
#define BGP_NLRI_LENGTH 1U
#define BGP_TOTAL_ATTR_LEN 2U
#define BGP_UNFEASIBLE_LEN 2U
-#define BGP_WRITE_PACKET_MAX 10U
/* When to refresh */
#define REFRESH_IMMEDIATE 1
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 095379060..6f1620fac 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -57,6 +57,7 @@
#include "bgpd/bgp_packet.h"
#include "bgpd/bgp_updgrp.h"
#include "bgpd/bgp_bfd.h"
+#include "bgpd/bgp_io.h"
static struct peer_group *listen_range_exists(struct bgp *bgp,
struct prefix *range, int exact);
@@ -1332,25 +1333,55 @@ static int bgp_wpkt_quanta_config_vty(struct vty *vty, const char *num,
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
- if (set)
- bgp->wpkt_quanta = strtoul(num, NULL, 10);
- else
- bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX;
+ if (set) {
+ uint32_t quanta = strtoul(num, NULL, 10);
+ atomic_store_explicit(&bgp->wpkt_quanta, quanta,
+ memory_order_relaxed);
+ } else {
+ atomic_store_explicit(&bgp->wpkt_quanta, BGP_WRITE_PACKET_MAX,
+ memory_order_relaxed);
+ }
+
+ return CMD_SUCCESS;
+}
+
+static int bgp_rpkt_quanta_config_vty(struct vty *vty, const char *num,
+ char set)
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (set) {
+ uint32_t quanta = strtoul(num, NULL, 10);
+ atomic_store_explicit(&bgp->rpkt_quanta, quanta,
+ memory_order_relaxed);
+ } else {
+ atomic_store_explicit(&bgp->rpkt_quanta, BGP_READ_PACKET_MAX,
+ memory_order_relaxed);
+ }
return CMD_SUCCESS;
}
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);
+ uint32_t quanta =
+ atomic_load_explicit(&bgp->wpkt_quanta, memory_order_relaxed);
+ if (quanta != BGP_WRITE_PACKET_MAX)
+ vty_out(vty, " write-quanta %d%s", quanta, VTY_NEWLINE);
}
+void bgp_config_write_rpkt_quanta(struct vty *vty, struct bgp *bgp)
+{
+ uint32_t quanta =
+ atomic_load_explicit(&bgp->rpkt_quanta, memory_order_relaxed);
+ if (quanta != BGP_READ_PACKET_MAX)
+ vty_out(vty, " read-quanta %d%s", quanta, VTY_NEWLINE);
+}
-/* Update-delay configuration */
+/* Packet quanta configuration */
DEFUN (bgp_wpkt_quanta,
bgp_wpkt_quanta_cmd,
- "write-quanta (1-10000)",
+ "write-quanta (1-10)",
"How many packets to write to peer socket per run\n"
"Number of packets\n")
{
@@ -1358,18 +1389,38 @@ DEFUN (bgp_wpkt_quanta,
return bgp_wpkt_quanta_config_vty(vty, argv[idx_number]->arg, 1);
}
-/* Update-delay deconfiguration */
DEFUN (no_bgp_wpkt_quanta,
no_bgp_wpkt_quanta_cmd,
- "no write-quanta (1-10000)",
+ "no write-quanta (1-10)",
NO_STR
- "How many packets to write to peer socket per run\n"
+ "How many packets to write to peer socket per I/O cycle\n"
"Number of packets\n")
{
int idx_number = 2;
return bgp_wpkt_quanta_config_vty(vty, argv[idx_number]->arg, 0);
}
+DEFUN (bgp_rpkt_quanta,
+ bgp_rpkt_quanta_cmd,
+ "read-quanta (1-10)",
+ "How many packets to read from peer socket per I/O cycle\n"
+ "Number of packets\n")
+{
+ int idx_number = 1;
+ return bgp_rpkt_quanta_config_vty(vty, argv[idx_number]->arg, 1);
+}
+
+DEFUN (no_bgp_rpkt_quanta,
+ no_bgp_rpkt_quanta_cmd,
+ "no read-quanta (1-10)",
+ NO_STR
+ "How many packets to read from peer socket per I/O cycle\n"
+ "Number of packets\n")
+{
+ int idx_number = 2;
+ return bgp_rpkt_quanta_config_vty(vty, argv[idx_number]->arg, 0);
+}
+
void bgp_config_write_coalesce_time(struct vty *vty, struct bgp *bgp)
{
if (bgp->coalesce_time != BGP_DEFAULT_SUBGROUP_COALESCE_TIME)
@@ -11375,6 +11426,8 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &bgp_wpkt_quanta_cmd);
install_element(BGP_NODE, &no_bgp_wpkt_quanta_cmd);
+ install_element(BGP_NODE, &bgp_rpkt_quanta_cmd);
+ install_element(BGP_NODE, &no_bgp_rpkt_quanta_cmd);
install_element(BGP_NODE, &bgp_coalesce_time_cmd);
install_element(BGP_NODE, &no_bgp_coalesce_time_cmd);
diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h
index 59bc01266..e456f7cae 100644
--- a/bgpd/bgp_vty.h
+++ b/bgpd/bgp_vty.h
@@ -48,6 +48,7 @@ extern const char *afi_safi_print(afi_t, safi_t);
extern const char *afi_safi_json(afi_t, safi_t);
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_rpkt_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);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 527066e0a..b546056c1 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -1162,7 +1162,7 @@ struct peer *peer_new(struct bgp *bgp)
*/
peer->obuf_work =
stream_new(BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
- peer->ibuf_work = stream_new(BGP_MAX_PACKET_SIZE * 5);
+ peer->ibuf_work = stream_new(BGP_MAX_PACKET_SIZE * BGP_READ_PACKET_MAX);
peer->scratch = stream_new(BGP_MAX_PACKET_SIZE);
bgp_sync_init(peer);
@@ -2908,7 +2908,10 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->restart_time, &bgp->t_startup);
}
- bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX;
+ atomic_store_explicit(&bgp->wpkt_quanta, BGP_WRITE_PACKET_MAX,
+ memory_order_relaxed);
+ atomic_store_explicit(&bgp->rpkt_quanta, BGP_READ_PACKET_MAX,
+ memory_order_relaxed);
bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME;
QOBJ_REG(bgp, bgp);
@@ -7192,6 +7195,8 @@ int bgp_config_write(struct vty *vty)
/* write quanta */
bgp_config_write_wpkt_quanta(vty, bgp);
+ /* read quanta */
+ bgp_config_write_rpkt_quanta(vty, bgp);
/* coalesce time */
bgp_config_write_coalesce_time(vty, bgp);
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 208cd897d..79c445aac 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -378,7 +378,9 @@ struct bgp {
#define BGP_FLAG_IBGP_MULTIPATH_SAME_CLUSTERLEN (1 << 0)
} maxpaths[AFI_MAX][SAFI_MAX];
- u_int32_t wpkt_quanta; /* per peer packet quanta to write */
+ _Atomic uint32_t wpkt_quanta; // max # packets to write per i/o cycle
+ _Atomic uint32_t rpkt_quanta; // max # packets to read per i/o cycle
+
u_int32_t coalesce_time;
u_int32_t addpath_tx_id;