forked from M-Labs/artiq-zynq
mgmt: Implemented network log access.
This commit is contained in:
parent
855b26aa19
commit
62f39e2c08
|
@ -14,7 +14,7 @@ let
|
|||
version = "0.1.0";
|
||||
|
||||
src = ./src;
|
||||
cargoSha256 = "0xminds5fyp7c9vsx651zv3yzyhxnl9a02rhjl2wfxf8m679r45l";
|
||||
cargoSha256 = "1q66h2avk0gvw8k07jjazzv1f3n1p4y11vkc15c6s31pcapz3d81";
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.gnumake
|
||||
|
|
|
@ -280,6 +280,12 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log_buffer"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f033173c9486b7fe97a79c895c0a3483ae395ab6744c985d10078950e2492419"
|
||||
|
||||
[[package]]
|
||||
name = "managed"
|
||||
version = "0.7.2"
|
||||
|
@ -400,6 +406,7 @@ dependencies = [
|
|||
"libregister",
|
||||
"libsupport_zynq",
|
||||
"log",
|
||||
"log_buffer",
|
||||
"nb",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
|
|
|
@ -22,6 +22,7 @@ void = { version = "1", default-features = false }
|
|||
futures = { version = "0.3", default-features = false, features = ["async-await"] }
|
||||
async-recursion = "0.3"
|
||||
fatfs = { version = "0.3", features = ["core_io"], default-features = false }
|
||||
log_buffer = { version = "1.2" }
|
||||
|
||||
libboard_zynq = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
||||
libsupport_zynq = { default-features = false, git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
||||
|
|
|
@ -27,6 +27,7 @@ use crate::proto_async::*;
|
|||
use crate::kernel;
|
||||
use crate::rpc;
|
||||
use crate::moninj;
|
||||
use crate::mgmt;
|
||||
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
|
@ -356,6 +357,7 @@ pub fn main(timer: GlobalTimer, cfg: &config::Config) {
|
|||
}
|
||||
});
|
||||
|
||||
mgmt::start();
|
||||
moninj::start(timer);
|
||||
|
||||
Sockets::run(&mut iface, || {
|
||||
|
|
|
@ -20,6 +20,7 @@ mod config;
|
|||
mod net_settings;
|
||||
mod proto_core_io;
|
||||
mod proto_async;
|
||||
mod proto_mgmt;
|
||||
mod comms;
|
||||
mod rpc;
|
||||
#[path = "../../../build/pl.rs"]
|
||||
|
@ -31,6 +32,7 @@ mod load_pl;
|
|||
mod eh_artiq;
|
||||
mod panic;
|
||||
mod logger;
|
||||
mod mgmt;
|
||||
|
||||
fn init_gateware() {
|
||||
// Set up PS->PL clocks
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
use futures::{future::poll_fn, task::Poll};
|
||||
use libasync::{smoltcp::TcpStream, task};
|
||||
use libboard_zynq::smoltcp;
|
||||
use log::{self, info, warn};
|
||||
|
||||
use crate::logger::{BufferLogger, LogBufferRef};
|
||||
use crate::proto_async;
|
||||
use crate::proto_mgmt::*;
|
||||
|
||||
async fn get_logger_buffer() -> LogBufferRef<'static> {
|
||||
poll_fn(|ctx| {
|
||||
let logger = unsafe { BufferLogger::get_logger().as_mut().unwrap() };
|
||||
match logger.buffer() {
|
||||
Ok(buffer) => Poll::Ready(buffer),
|
||||
_ => {
|
||||
ctx.waker().wake_by_ref();
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn handle_connection(stream: &mut TcpStream) -> Result<(), Error> {
|
||||
Request::read_magic(stream).await?;
|
||||
|
||||
loop {
|
||||
let req = Request::read_from(stream).await;
|
||||
if let Err(Error::Io(smoltcp::Error::Illegal)) = req {
|
||||
return Ok(());
|
||||
}
|
||||
match req? {
|
||||
Request::GetLog => {
|
||||
let mut buffer = get_logger_buffer().await;
|
||||
Reply::LogContent(buffer.extract()).write_to(stream).await?;
|
||||
}
|
||||
Request::ClearLog => {
|
||||
let mut buffer = get_logger_buffer().await;
|
||||
buffer.clear();
|
||||
Reply::Success.write_to(stream).await?;
|
||||
}
|
||||
Request::PullLog => loop {
|
||||
let mut buffer = get_logger_buffer().await;
|
||||
if buffer.is_empty() {
|
||||
continue;
|
||||
}
|
||||
proto_async::write_chunk(stream, buffer.extract().as_bytes()).await?;
|
||||
buffer.clear();
|
||||
},
|
||||
Request::SetLogFilter(lvl) => {
|
||||
info!("Changing log level to {}", lvl);
|
||||
log::set_max_level(lvl);
|
||||
Reply::Success.write_to(stream).await?;
|
||||
}
|
||||
Request::SetUartLogFilter(lvl) => {
|
||||
info!("Changing UART log level to {}", lvl);
|
||||
unsafe {
|
||||
BufferLogger::get_logger()
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.set_uart_log_level(lvl);
|
||||
}
|
||||
Reply::Success.write_to(stream).await?;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start() {
|
||||
task::spawn(async move {
|
||||
loop {
|
||||
let mut stream = TcpStream::accept(1380, 2048, 2048).await.unwrap();
|
||||
task::spawn(async move {
|
||||
let _ = handle_connection(&mut stream)
|
||||
.await
|
||||
.map_err(|e| warn!("connection terminated: {:?}", e));
|
||||
let _ = stream.flush().await;
|
||||
let _ = stream.abort().await;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
|
@ -7,7 +7,7 @@ use libasync::smoltcp::TcpStream;
|
|||
|
||||
// TODO: use byteorder, make it more like libio
|
||||
|
||||
pub type Result<T> = core::result::Result<T, smoltcp::Error>;
|
||||
type Result<T> = core::result::Result<T, smoltcp::Error>;
|
||||
|
||||
pub async fn expect(stream: &TcpStream, pattern: &[u8]) -> Result<bool> {
|
||||
stream.recv(|buf| {
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
use libasync::smoltcp::TcpStream;
|
||||
use libboard_zynq::smoltcp::Error as IoError;
|
||||
use log;
|
||||
|
||||
use crate::proto_async::*;
|
||||
|
||||
pub enum Error {
|
||||
WrongMagic,
|
||||
UnknownPacket(u8),
|
||||
UnknownLogLevel(u8),
|
||||
Io(IoError),
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for Error {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
use Error::*;
|
||||
match self {
|
||||
WrongMagic => write!(f, "Wrong magic string"),
|
||||
UnknownPacket(v) => write!(f, "Unknown packet {:#02x}", v),
|
||||
UnknownLogLevel(v) => write!(f, "Unknown log level {}", v),
|
||||
Io(e) => write!(f, "{}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IoError> for Error {
|
||||
fn from(value: IoError) -> Error {
|
||||
Error::Io(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Request {
|
||||
GetLog,
|
||||
ClearLog,
|
||||
PullLog,
|
||||
SetLogFilter(log::LevelFilter),
|
||||
SetUartLogFilter(log::LevelFilter),
|
||||
}
|
||||
|
||||
pub enum Reply<'a> {
|
||||
Success,
|
||||
LogContent(&'a str),
|
||||
}
|
||||
|
||||
impl Request {
|
||||
pub async fn read_from(stream: &mut TcpStream) -> Result<Self, Error> {
|
||||
async fn read_log_level_filter(stream: &mut TcpStream) -> Result<log::LevelFilter, Error> {
|
||||
Ok(match read_i8(stream).await? {
|
||||
0 => log::LevelFilter::Off,
|
||||
1 => log::LevelFilter::Error,
|
||||
2 => log::LevelFilter::Warn,
|
||||
3 => log::LevelFilter::Info,
|
||||
4 => log::LevelFilter::Debug,
|
||||
5 => log::LevelFilter::Trace,
|
||||
lv => return Err(Error::UnknownLogLevel(lv as u8)),
|
||||
})
|
||||
}
|
||||
|
||||
Ok(match read_i8(stream).await? {
|
||||
1 => Request::GetLog,
|
||||
2 => Request::ClearLog,
|
||||
7 => Request::PullLog,
|
||||
3 => Request::SetLogFilter(read_log_level_filter(stream).await?),
|
||||
6 => Request::SetUartLogFilter(read_log_level_filter(stream).await?),
|
||||
ty => return Err(Error::UnknownPacket(ty as u8)),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn read_magic(stream: &mut TcpStream) -> Result<(), Error> {
|
||||
if !expect(&stream, b"ARTIQ management\n").await? {
|
||||
return Err(Error::WrongMagic);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Reply<'a> {
|
||||
pub async fn write_to(&self, stream: &mut TcpStream) -> Result<(), IoError> {
|
||||
match *self {
|
||||
Reply::Success => {
|
||||
write_i8(stream, 1).await?;
|
||||
}
|
||||
Reply::LogContent(ref log) => {
|
||||
write_i8(stream, 2).await?;
|
||||
write_chunk(stream, log.as_bytes()).await?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue