mgmt: Implemented network log access.

core0-buffer
pca006132 2020-07-13 15:00:53 +08:00
parent 855b26aa19
commit 62f39e2c08
8 changed files with 187 additions and 2 deletions

View File

@ -14,7 +14,7 @@ let
version = "0.1.0";
src = ./src;
cargoSha256 = "0xminds5fyp7c9vsx651zv3yzyhxnl9a02rhjl2wfxf8m679r45l";
cargoSha256 = "1q66h2avk0gvw8k07jjazzv1f3n1p4y11vkc15c6s31pcapz3d81";
nativeBuildInputs = [
pkgs.gnumake

7
src/Cargo.lock generated
View File

@ -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",

View File

@ -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" }

View File

@ -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, || {

View File

@ -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

82
src/runtime/src/mgmt.rs Normal file
View 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;
});
}
});
}

View File

@ -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| {

View 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(())
}
}