Skip to content

Commit eabdab7

Browse files
alexandruagalxiord
authored andcommitted
NetEpollHandler: added PATCH_RATE_LIMITERS support
Signed-off-by: Alexandru Agache <[email protected]>
1 parent d2f050c commit eabdab7

File tree

2 files changed

+69
-8
lines changed

2 files changed

+69
-8
lines changed

devices/src/lib.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ extern crate vhost_backend;
2424
extern crate vhost_gen;
2525
extern crate virtio_gen;
2626

27-
use rate_limiter::Error as RateLimiterError;
27+
use rate_limiter::{Error as RateLimiterError, TokenBucket};
2828
use std::fs::File;
2929
use std::io;
3030

@@ -41,6 +41,14 @@ pub type DeviceEventT = u16;
4141
pub enum EpollHandlerPayload {
4242
/// DrivePayload(disk_image)
4343
DrivePayload(File),
44+
/// Used to mutate current RateLimiter settings. The buckets are rx_bytes, rx_ops,
45+
/// tx_bytes, and tx_ops, respectively.
46+
PatchRateLimiters(
47+
Option<TokenBucket>,
48+
Option<TokenBucket>,
49+
Option<TokenBucket>,
50+
Option<TokenBucket>,
51+
),
4452
/// Events that do not need a payload.
4553
Empty,
4654
}

devices/src/virtio/net.rs

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ const TX_RATE_LIMITER_EVENT: DeviceEventT = 4;
5656
// Number of DeviceEventT events supported by this implementation.
5757
pub const NET_EVENTS_COUNT: usize = 5;
5858

59+
// This is not a true DeviceEvent, as we explicitly invoke the handler with this value as a
60+
// parameter when the VMM handles as PATCH rate limiters request. Thus, there's not epoll event
61+
// associated with it.
62+
const PATCH_RATE_LIMITERS: DeviceEventT = 5;
63+
5964
#[derive(Debug)]
6065
pub enum Error {
6166
/// Open tap device failed.
@@ -504,7 +509,7 @@ impl EpollHandler for NetEpollHandler {
504509
&mut self,
505510
device_event: DeviceEventT,
506511
_: u32,
507-
_: EpollHandlerPayload,
512+
payload: EpollHandlerPayload,
508513
) -> result::Result<(), DeviceError> {
509514
match device_event {
510515
RX_QUEUE_EVENT => {
@@ -600,6 +605,17 @@ impl EpollHandler for NetEpollHandler {
600605
}
601606
}
602607
}
608+
PATCH_RATE_LIMITERS => {
609+
if let EpollHandlerPayload::PatchRateLimiters(rx_bytes, rx_ops, tx_bytes, tx_ops) =
610+
payload
611+
{
612+
self.rx.rate_limiter.update_buckets(rx_bytes, rx_ops);
613+
self.tx.rate_limiter.update_buckets(tx_bytes, tx_ops);
614+
Ok(())
615+
} else {
616+
Err(DeviceError::PayloadExpected)
617+
}
618+
}
603619
other => Err(DeviceError::UnknownEvent {
604620
device: "net",
605621
event: other,
@@ -951,6 +967,7 @@ mod tests {
951967
use virtio::queue::tests::*;
952968

953969
use dumbo::pdu::{arp, ethernet};
970+
use rate_limiter::TokenBucket;
954971

955972
/// Will read $metric, run the code in $block, then assert metric has increased by $delta.
956973
macro_rules! check_metric_after_block {
@@ -1484,14 +1501,13 @@ mod tests {
14841501
fn test_invalid_event_handler() {
14851502
let mem = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
14861503
let (mut h, _txq, _rxq) = default_test_netepollhandler(&mem, TestMutators::default());
1487-
let r = h.handle_event(
1488-
NET_EVENTS_COUNT as DeviceEventT,
1489-
0,
1490-
EpollHandlerPayload::Empty,
1491-
);
1504+
1505+
let bad_event = 1000;
1506+
1507+
let r = h.handle_event(bad_event as DeviceEventT, 0, EpollHandlerPayload::Empty);
14921508
match r {
14931509
Err(DeviceError::UnknownEvent { event, device }) => {
1494-
assert_eq!(event, NET_EVENTS_COUNT as DeviceEventT);
1510+
assert_eq!(event, bad_event as DeviceEventT);
14951511
assert_eq!(device, "net");
14961512
}
14971513
_ => panic!("invalid"),
@@ -1910,4 +1926,41 @@ mod tests {
19101926
}
19111927
}
19121928
}
1929+
1930+
#[test]
1931+
fn test_patch_rate_limiters() {
1932+
let mem = GuestMemory::new(&[(GuestAddress(0), 0x10000)]).unwrap();
1933+
let (mut h, _, _) = default_test_netepollhandler(&mem, TestMutators::default());
1934+
1935+
h.set_rx_rate_limiter(RateLimiter::new(10, None, 10, 2, None, 2).unwrap());
1936+
h.set_tx_rate_limiter(RateLimiter::new(10, None, 10, 2, None, 2).unwrap());
1937+
1938+
let rx_bytes = TokenBucket::new(1000, Some(1001), 1002);
1939+
let rx_ops = TokenBucket::new(1003, Some(1004), 1005);
1940+
let tx_bytes = TokenBucket::new(1006, Some(1007), 1008);
1941+
let tx_ops = TokenBucket::new(1009, Some(1010), 1011);
1942+
1943+
h.handle_event(
1944+
PATCH_RATE_LIMITERS,
1945+
0,
1946+
EpollHandlerPayload::PatchRateLimiters(
1947+
Some(rx_bytes.clone()),
1948+
Some(rx_ops.clone()),
1949+
Some(tx_bytes.clone()),
1950+
Some(tx_ops.clone()),
1951+
),
1952+
)
1953+
.unwrap();
1954+
1955+
let compare_buckets = |a: &TokenBucket, b: &TokenBucket| {
1956+
assert_eq!(a.capacity(), b.capacity());
1957+
assert_eq!(a.one_time_burst(), b.one_time_burst());
1958+
assert_eq!(a.refill_time_ms(), b.refill_time_ms());
1959+
};
1960+
1961+
compare_buckets(h.get_rx_rate_limiter().bandwidth().unwrap(), &rx_bytes);
1962+
compare_buckets(h.get_rx_rate_limiter().ops().unwrap(), &rx_ops);
1963+
compare_buckets(h.get_tx_rate_limiter().bandwidth().unwrap(), &tx_bytes);
1964+
compare_buckets(h.get_tx_rate_limiter().ops().unwrap(), &tx_ops);
1965+
}
19131966
}

0 commit comments

Comments
 (0)