Eliminate excessive CPU consumption when redirecting UART over SSH
Redirecting the external UART via SSH caused the console-server,
console-client, and dropbear to consume ~30% of the available CPU each
when a large amount of data was being written to the UART output.
Buffering all of the small 16550 FIFO bytes into a larger packet and
then sending that to the SSH SW allows more efficient transmission
over the ethernet connection.
Tested this by "ssh root@<bmc.ip.addr> -p 2200" on a system running a
CentOS distribution. Using a BASH console run a large binary file
through "od -t x1 <fname>" to create a large amount of traffic. At
the BMC console run "top" to review the CPU usage. My experience is
after this change is applied:
console-server: ~25% CPU
dropbear: ~3% CPU
console-client: ~1% CPU
Change-Id: Ibabfd285e97a487e7ff040e1cb3159fbff360328
Signed-off-by: Johnathan Mantey <johnathanx.mantey@intel.com>
diff --git a/console-server.h b/console-server.h
index cac88d1..d6822c5 100644
--- a/console-server.h
+++ b/console-server.h
@@ -20,7 +20,9 @@
#include <stdbool.h>
#include <stdint.h>
#include <termios.h> /* for speed_t */
+#include <time.h>
#include <systemd/sd-bus.h>
+#include <sys/time.h>
struct console;
struct config;
@@ -72,18 +74,24 @@
POLLER_EXIT,
};
-typedef enum poller_ret (*poller_fn_t)(struct handler *handler,
+typedef enum poller_ret (*poller_event_fn_t)(struct handler *handler,
int revents, void *data);
+typedef enum poller_ret (*poller_timeout_fn_t)(struct handler *handler,
+ void *data);
struct poller *console_poller_register(struct console *console,
- struct handler *handler, poller_fn_t poller_fn,
- int fd, int events, void *data);
+ struct handler *handler, poller_event_fn_t event_fn,
+ poller_timeout_fn_t timeout_fn, int fd, int events,
+ void *data);
void console_poller_unregister(struct console *console, struct poller *poller);
void console_poller_set_events(struct console *console, struct poller *poller,
int events);
+void console_poller_set_timeout(struct console *console, struct poller *poller,
+ const struct timeval *interval);
+
/* ringbuffer API */
enum ringbuffer_poll_ret {
RINGBUFFER_POLL_OK = 0,
@@ -111,6 +119,8 @@
int ringbuffer_dequeue_commit(struct ringbuffer_consumer *rbc, size_t len);
+size_t ringbuffer_len(struct ringbuffer_consumer *rbc);
+
/* console wrapper around ringbuffer consumer registration */
struct ringbuffer_consumer *console_ringbuffer_consumer_register(
struct console *console,