summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_packet.c52
-rw-r--r--ospfd/ospf_vty.c18
-rw-r--r--ospfd/ospfd.c15
-rw-r--r--zebra/zebra_ptm.c11
4 files changed, 65 insertions, 31 deletions
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index eed5fdc65d..0ce2466f52 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -545,19 +545,26 @@ void bgp_open_send(struct peer *peer)
bgp_writes_on(peer);
}
-/* This is only for sending NOTIFICATION message to neighbor. */
+/*
+ * Writes NOTIFICATION message directly to a peer socket without waiting for
+ * the I/O thread.
+ *
+ * There must be exactly one stream on the peer->obuf FIFO, and the data within
+ * this stream must match the format of a BGP NOTIFICATION message.
+ * Transmission is best-effort.
+ *
+ * @requires peer->io_mtx
+ * @param peer
+ * @return 0
+ */
static int bgp_write_notify(struct peer *peer)
{
int ret, val;
u_char type;
struct stream *s;
- pthread_mutex_lock(&peer->io_mtx);
- {
- /* There should be at least one packet. */
- s = stream_fifo_pop(peer->obuf);
- }
- pthread_mutex_unlock(&peer->io_mtx);
+ /* There should be at least one packet. */
+ s = stream_fifo_pop(peer->obuf);
if (!s)
return 0;
@@ -622,6 +629,14 @@ static int bgp_write_notify(struct peer *peer)
* This function attempts to write the packet from the thread it is called
* from, to ensure the packet gets out ASAP.
*
+ * This function may be called from multiple threads. Since the function
+ * modifies I/O buffer(s) in the peer, these are locked for the duration of the
+ * call to prevent tampering from other threads.
+ *
+ * Delivery of the NOTIFICATION is attempted once and is best-effort. After
+ * return, the peer structure *must* be reset; no assumptions about session
+ * state are valid.
+ *
* @param peer
* @param code BGP error code
* @param sub_code BGP error subcode
@@ -634,6 +649,10 @@ void bgp_notify_send_with_data(struct peer *peer, u_char code, u_char sub_code,
struct stream *s;
int length;
+ /* Lock I/O mutex to prevent other threads from pushing packets */
+ pthread_mutex_lock(&peer->io_mtx);
+ /* ============================================== */
+
/* Allocate new stream. */
s = stream_new(BGP_MAX_PACKET_SIZE);
@@ -651,20 +670,8 @@ void bgp_notify_send_with_data(struct peer *peer, u_char code, u_char sub_code,
/* Set BGP packet length. */
length = bgp_packet_set_size(s);
- /*
- * Turn off keepalive generation for peer. This is necessary because
- * otherwise between the time we wipe the output buffer and the time we
- * push the NOTIFY onto it, the KA generation thread could have pushed
- * a KEEPALIVE in the middle.
- */
- bgp_keepalives_off(peer);
-
/* wipe output buffer */
- pthread_mutex_lock(&peer->io_mtx);
- {
- stream_fifo_clean(peer->obuf);
- }
- pthread_mutex_unlock(&peer->io_mtx);
+ stream_fifo_clean(peer->obuf);
/*
* If possible, store last packet for debugging purposes. This check is
@@ -728,9 +735,12 @@ void bgp_notify_send_with_data(struct peer *peer, u_char code, u_char sub_code,
peer->last_reset = PEER_DOWN_NOTIFY_SEND;
/* Add packet to peer's output queue */
- bgp_packet_add(peer, s);
+ stream_fifo_push(peer->obuf, s);
bgp_write_notify(peer);
+
+ /* ============================================== */
+ pthread_mutex_unlock(&peer->io_mtx);
}
/*
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 6d28c2cdc5..3b18d152e8 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -8116,7 +8116,7 @@ DEFUN (no_ip_ospf_area,
DEFUN (ospf_redistribute_source,
ospf_redistribute_source_cmd,
- "redistribute " FRR_REDIST_STR_OSPFD " [<metric (0-16777214)|metric-type (1-2)|route-map WORD>]",
+ "redistribute " FRR_REDIST_STR_OSPFD " [{metric (0-16777214)|metric-type (1-2)|route-map WORD}]",
REDIST_STR
FRR_REDIST_HELP_STR_OSPFD
"Metric for redistributed routes\n"
@@ -8150,12 +8150,12 @@ DEFUN (ospf_redistribute_source,
return CMD_WARNING_CONFIG_FAILED;
}
/* Get metric type. */
- else if (argv_find(argv, argc, "(1-2)", &idx)) {
+ if (argv_find(argv, argc, "(1-2)", &idx)) {
if (!str2metric_type(argv[idx]->arg, &type))
return CMD_WARNING_CONFIG_FAILED;
}
/* Get route-map */
- else if (argv_find(argv, argc, "WORD", &idx)) {
+ if (argv_find(argv, argc, "WORD", &idx)) {
ospf_routemap_set(red, argv[idx]->arg);
} else
ospf_routemap_unset(red);
@@ -8165,7 +8165,7 @@ DEFUN (ospf_redistribute_source,
DEFUN (no_ospf_redistribute_source,
no_ospf_redistribute_source_cmd,
- "no redistribute " FRR_REDIST_STR_OSPFD " [<metric (0-16777214)|metric-type (1-2)|route-map WORD>]",
+ "no redistribute " FRR_REDIST_STR_OSPFD " [{metric (0-16777214)|metric-type (1-2)|route-map WORD}]",
NO_STR
REDIST_STR
FRR_REDIST_HELP_STR_OSPFD
@@ -8355,7 +8355,7 @@ DEFUN (no_ospf_distribute_list_out,
/* Default information originate. */
DEFUN (ospf_default_information_originate,
ospf_default_information_originate_cmd,
- "default-information originate [<always|metric (0-16777214)|metric-type (1-2)|route-map WORD>]",
+ "default-information originate [{always|metric (0-16777214)|metric-type (1-2)|route-map WORD}]",
"Control distribution of default information\n"
"Distribute a default route\n"
"Always advertise default route\n"
@@ -8379,17 +8379,17 @@ DEFUN (ospf_default_information_originate,
if (argv_find(argv, argc, "always", &idx))
default_originate = DEFAULT_ORIGINATE_ALWAYS;
/* Get metric value */
- else if (argv_find(argv, argc, "(0-16777214)", &idx)) {
+ if (argv_find(argv, argc, "(0-16777214)", &idx)) {
if (!str2metric(argv[idx]->arg, &metric))
return CMD_WARNING_CONFIG_FAILED;
}
/* Get metric type. */
- else if (argv_find(argv, argc, "(1-2)", &idx)) {
+ if (argv_find(argv, argc, "(1-2)", &idx)) {
if (!str2metric_type(argv[idx]->arg, &type))
return CMD_WARNING_CONFIG_FAILED;
}
/* Get route-map */
- else if (argv_find(argv, argc, "WORD", &idx))
+ if (argv_find(argv, argc, "WORD", &idx))
ospf_routemap_set(red, argv[idx]->arg);
else
ospf_routemap_unset(red);
@@ -8400,7 +8400,7 @@ DEFUN (ospf_default_information_originate,
DEFUN (no_ospf_default_information_originate,
no_ospf_default_information_originate_cmd,
- "no default-information originate [<always|metric (0-16777214)|metric-type (1-2)|route-map WORD>]",
+ "no default-information originate [{always|metric (0-16777214)|metric-type (1-2)|route-map WORD}]",
NO_STR
"Control distribution of default information\n"
"Distribute a default route\n"
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 89b08552a8..e6f19369ef 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -32,6 +32,7 @@
#include "log.h"
#include "sockunion.h" /* for inet_aton () */
#include "zclient.h"
+#include "routemap.h"
#include "plist.h"
#include "sockopt.h"
#include "bfd.h"
@@ -554,6 +555,20 @@ void ospf_terminate(void)
for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf))
ospf_finish(ospf);
+ /* Cleanup route maps */
+ route_map_add_hook(NULL);
+ route_map_delete_hook(NULL);
+ route_map_event_hook(NULL);
+ route_map_finish();
+
+ /* reverse prefix_list_init */
+ prefix_list_add_hook(NULL);
+ prefix_list_delete_hook(NULL);
+ prefix_list_reset();
+
+ /* Cleanup vrf info */
+ ospf_vrf_terminate();
+
/* Deliberately go back up, hopefully to thread scheduler, as
* One or more ospf_finish()'s may have deferred shutdown to a timer
* thread
diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c
index 953f74ecec..7f5fd472f1 100644
--- a/zebra/zebra_ptm.c
+++ b/zebra/zebra_ptm.c
@@ -816,6 +816,8 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length,
ptm_cb.out_data);
zebra_ptm_send_message(ptm_cb.out_data, data_len);
+ return 0;
+
stream_failure:
ptm_lib_cleanup_msg(ptm_hdl, out_ctxt);
return 0;
@@ -946,6 +948,8 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length,
zebra_ptm_send_message(ptm_cb.out_data, data_len);
+ return 0;
+
stream_failure:
ptm_lib_cleanup_msg(ptm_hdl, out_ctxt);
return 0;
@@ -957,7 +961,7 @@ int zebra_ptm_bfd_client_register(struct zserv *client,
{
struct stream *s;
unsigned int pid;
- void *out_ctxt;
+ void *out_ctxt = NULL;
char tmp_buf[64];
int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
@@ -999,7 +1003,12 @@ int zebra_ptm_bfd_client_register(struct zserv *client,
SET_FLAG(ptm_cb.client_flags[client->proto],
ZEBRA_PTM_BFD_CLIENT_FLAG_REG);
+
+ return 0;
+
stream_failure:
+ if (out_ctxt)
+ ptm_lib_cleanup_msg(ptm_hdl, out_ctxt);
return 0;
}