diff options
| -rw-r--r-- | bgpd/bgp_packet.c | 52 | ||||
| -rw-r--r-- | ospfd/ospf_vty.c | 18 | ||||
| -rw-r--r-- | ospfd/ospfd.c | 15 | ||||
| -rw-r--r-- | zebra/zebra_ptm.c | 11 |
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; } |
