📄 serial-port-rate-limit
字号:
# HG changeset patch# User Steven Smith <ssmith@xensource.com># Node ID 1d3f52eb256e3522edc12daca91039b319dbbbe5# Parent b7b653e36d20811831f26bb951ea66dca5854b17[HVM] Rate limit guest accesses to the qemu virtual serial port. This stopsgrub's boot menu from hammering dom0.Signed-off-by: Steven Smith <sos22@cam.ac.uk>Index: ioemu/hw/serial.c===================================================================--- ioemu.orig/hw/serial.c 2007-05-03 18:18:01.000000000 +0100+++ ioemu/hw/serial.c 2007-05-03 20:36:58.000000000 +0100@@ -22,6 +22,9 @@ * THE SOFTWARE. */ #include "vl.h"+#include <sys/time.h>+#include <time.h>+#include <assert.h> //#define DEBUG_SERIAL @@ -140,6 +143,67 @@ #endif } +/* Rate limit serial requests so that e.g. grub on a serial console+ doesn't kill dom0. Simple token bucket. If we get some actual+ data from the user, instantly refil the bucket. */++/* How long it takes to generate a token, in microseconds. */+#define TOKEN_PERIOD 1000+/* Maximum and initial size of token bucket */+#define TOKENS_MAX 100000++static int tokens_avail;++static void serial_get_token(void)+{+ static struct timeval last_refil_time;+ static int started;++ assert(tokens_avail >= 0);+ if (!tokens_avail) {+ struct timeval delta, now;+ int generated;++ if (!started) {+ gettimeofday(&last_refil_time, NULL);+ tokens_avail = TOKENS_MAX;+ started = 1;+ return;+ }+ retry:+ gettimeofday(&now, NULL);+ delta.tv_sec = now.tv_sec - last_refil_time.tv_sec;+ delta.tv_usec = now.tv_usec - last_refil_time.tv_usec;+ if (delta.tv_usec < 0) {+ delta.tv_usec += 1000000;+ delta.tv_sec--;+ }+ assert(delta.tv_usec >= 0 && delta.tv_sec >= 0);+ if (delta.tv_usec < TOKEN_PERIOD) {+ struct timespec ts;+ /* Wait until at least one token is available. */+ ts.tv_sec = TOKEN_PERIOD / 1000000;+ ts.tv_nsec = (TOKEN_PERIOD % 1000000) * 1000;+ while (nanosleep(&ts, &ts) < 0 && errno == EINTR)+ ;+ goto retry;+ }+ generated = (delta.tv_sec * 1000000) / TOKEN_PERIOD;+ generated +=+ ((delta.tv_sec * 1000000) % TOKEN_PERIOD + delta.tv_usec) / TOKEN_PERIOD;+ assert(generated > 0);++ last_refil_time.tv_usec += (generated * TOKEN_PERIOD) % 1000000;+ last_refil_time.tv_sec += last_refil_time.tv_usec / 1000000;+ last_refil_time.tv_usec %= 1000000;+ last_refil_time.tv_sec += (generated * TOKEN_PERIOD) / 1000000;+ if (generated > TOKENS_MAX)+ generated = TOKENS_MAX;+ tokens_avail = generated;+ }+ tokens_avail--;+}+ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) { SerialState *s = opaque;@@ -245,9 +309,11 @@ ret = s->mcr; break; case 5:+ serial_get_token(); ret = s->lsr; break; case 6:+ serial_get_token(); if (s->mcr & UART_MCR_LOOP) { /* in loopback, the modem output pins are connected to the inputs */@@ -296,12 +362,14 @@ static void serial_receive1(void *opaque, const uint8_t *buf, int size) { SerialState *s = opaque;+ tokens_avail = TOKENS_MAX; serial_receive_byte(s, buf[0]); } static void serial_event(void *opaque, int event) { SerialState *s = opaque;+ tokens_avail = TOKENS_MAX; if (event == CHR_EVENT_BREAK) serial_receive_break(s); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -