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";
|
version = "0.1.0";
|
||||||
|
|
||||||
src = ./src;
|
src = ./src;
|
||||||
cargoSha256 = "0xminds5fyp7c9vsx651zv3yzyhxnl9a02rhjl2wfxf8m679r45l";
|
cargoSha256 = "1q66h2avk0gvw8k07jjazzv1f3n1p4y11vkc15c6s31pcapz3d81";
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
pkgs.gnumake
|
pkgs.gnumake
|
||||||
|
7
src/Cargo.lock
generated
7
src/Cargo.lock
generated
@ -280,6 +280,12 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log_buffer"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f033173c9486b7fe97a79c895c0a3483ae395ab6744c985d10078950e2492419"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "managed"
|
name = "managed"
|
||||||
version = "0.7.2"
|
version = "0.7.2"
|
||||||
@ -400,6 +406,7 @@ dependencies = [
|
|||||||
"libregister",
|
"libregister",
|
||||||
"libsupport_zynq",
|
"libsupport_zynq",
|
||||||
"log",
|
"log",
|
||||||
|
"log_buffer",
|
||||||
"nb",
|
"nb",
|
||||||
"num-derive",
|
"num-derive",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
@ -22,6 +22,7 @@ void = { version = "1", default-features = false }
|
|||||||
futures = { version = "0.3", default-features = false, features = ["async-await"] }
|
futures = { version = "0.3", default-features = false, features = ["async-await"] }
|
||||||
async-recursion = "0.3"
|
async-recursion = "0.3"
|
||||||
fatfs = { version = "0.3", features = ["core_io"], default-features = false }
|
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" }
|
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" }
|
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::kernel;
|
||||||
use crate::rpc;
|
use crate::rpc;
|
||||||
use crate::moninj;
|
use crate::moninj;
|
||||||
|
use crate::mgmt;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
@ -356,6 +357,7 @@ pub fn main(timer: GlobalTimer, cfg: &config::Config) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
mgmt::start();
|
||||||
moninj::start(timer);
|
moninj::start(timer);
|
||||||
|
|
||||||
Sockets::run(&mut iface, || {
|
Sockets::run(&mut iface, || {
|
||||||
|
@ -20,6 +20,7 @@ mod config;
|
|||||||
mod net_settings;
|
mod net_settings;
|
||||||
mod proto_core_io;
|
mod proto_core_io;
|
||||||
mod proto_async;
|
mod proto_async;
|
||||||
|
mod proto_mgmt;
|
||||||
mod comms;
|
mod comms;
|
||||||
mod rpc;
|
mod rpc;
|
||||||
#[path = "../../../build/pl.rs"]
|
#[path = "../../../build/pl.rs"]
|
||||||
@ -31,6 +32,7 @@ mod load_pl;
|
|||||||
mod eh_artiq;
|
mod eh_artiq;
|
||||||
mod panic;
|
mod panic;
|
||||||
mod logger;
|
mod logger;
|
||||||
|
mod mgmt;
|
||||||
|
|
||||||
fn init_gateware() {
|
fn init_gateware() {
|
||||||
// Set up PS->PL clocks
|
// Set up PS->PL clocks
|
||||||
|
82
src/runtime/src/mgmt.rs
Normal file
82
src/runtime/src/mgmt.rs
Normal file
@ -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
|
// 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> {
|
pub async fn expect(stream: &TcpStream, pattern: &[u8]) -> Result<bool> {
|
||||||
stream.recv(|buf| {
|
stream.recv(|buf| {
|
||||||
|
91
src/runtime/src/proto_mgmt.rs
Normal file
91
src/runtime/src/proto_mgmt.rs
Normal file
@ -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
Block a user