Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion applications/tests/test_load_udp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ async fn udp_server(port: u16) {
};

let mut socket =
awkernel_async_lib::net::udp::UdpSocket::bind_on_interface(INTERFACE_ID, config).unwrap();
awkernel_async_lib::net::udp::UdpSocket::bind_on_interface(INTERFACE_ID, &config).unwrap();

const MAX_DATAGRAM_SIZE: usize = 65_507;
let mut buf = [0u8; MAX_DATAGRAM_SIZE];
Expand Down
5 changes: 3 additions & 2 deletions applications/tests/test_network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ const INTERFACE_ID: u64 = 0;

// 10.0.2.0/24 is the IP address range of the Qemu's network.
const INTERFACE_ADDR: Ipv4Addr = Ipv4Addr::new(10, 0, 2, 64);

// const INTERFACE_ADDR: Ipv4Addr = Ipv4Addr::new(192, 168, 100, 52); // For experiment.
// const INTERFACE_ADDR: Ipv4Addr = Ipv4Addr::new(192, 168, 122, 24); // libvirt

// 10.0.2.2 is the IP address of the Qemu's host.
const UDP_TCP_DST_ADDR: Ipv4Addr = Ipv4Addr::new(10, 0, 2, 2);

// const UDP_TCP_DST_ADDR: Ipv4Addr = Ipv4Addr::new(192, 168, 100, 1); // For experiment.
// const UDP_TCP_DST_ADDR: Ipv4Addr = Ipv4Addr::new(192, 168, 122, 1); // libvirt

const UDP_DST_PORT: u16 = 26099;
const TCP_DST_PORT: u16 = 26099;
Expand Down Expand Up @@ -117,6 +117,7 @@ async fn ipv4_multicast_recv_test() {
break;
}
Err(UdpSocketError::SendError) => (),

_ => {
log::error!("Failed to join the multicast group.");
return;
Expand Down
17 changes: 17 additions & 0 deletions applications/tests/test_ntp/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "test_ntp"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
log = "0.4"

[dependencies.awkernel_async_lib]
path = "../../../awkernel_async_lib"
default-features = false

[dependencies.awkernel_lib]
path = "../../../awkernel_lib"
default-features = false
139 changes: 139 additions & 0 deletions applications/tests/test_ntp/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#![no_std]

extern crate alloc;

use core::{net::Ipv4Addr, time::Duration};

use awkernel_async_lib::net::{udp::UdpConfig, IpAddr};
use awkernel_lib::ntp::{packet::NtpPacket, SignedDuration, SystemClock, SystemTime};

// 10.0.2.0/24 is the IP address range of the Qemu's network.
// const INTERFACE_ADDR: Ipv4Addr = Ipv4Addr::new(10, 0, 2, 64);
// const INTERFACE_ADDR: Ipv4Addr = Ipv4Addr::new(192, 168, 100, 52); // For experiment.
const INTERFACE_ADDR: Ipv4Addr = Ipv4Addr::new(192, 168, 122, 24); // libvirt

// time-a-g.nist.gov
// const NTP_SERVER_ADDR: Ipv4Addr = Ipv4Addr::new(129, 6, 15, 28);

// Execute this to start a local NTP server on host:
// $ scripts/ntpserver.py 0.0.0.0 26099
const NTP_SERVER_ADDR: Ipv4Addr = Ipv4Addr::new(192, 168, 122, 1);
const NTP_SERVER_PORT: u16 = 26099;
const INTERFACE_ID: u64 = 0;

pub async fn run() {
awkernel_lib::net::add_ipv4_addr(INTERFACE_ID, INTERFACE_ADDR, 24);

awkernel_async_lib::spawn(
"poll time from server".into(),
poll_time_from_server(),
awkernel_async_lib::scheduler::SchedulerType::FIFO,
)
.await;

awkernel_async_lib::spawn(
"syncronize with server and adjust the system clock".into(),
synchronize_with_server(),
awkernel_async_lib::scheduler::SchedulerType::FIFO,
)
.await;

awkernel_async_lib::spawn(
"get time from kernel".into(),
get_time_from_kernel(),
awkernel_async_lib::scheduler::SchedulerType::FIFO,
)
.await;

awkernel_async_lib::spawn(
"set time from kernel".into(),
set_time(),
awkernel_async_lib::scheduler::SchedulerType::FIFO,
)
.await;
}

async fn get_time_from_server() -> Result<(SignedDuration, SignedDuration), ()> {
let config = UdpConfig {
addr: IpAddr::new_v4(INTERFACE_ADDR),
port: Some(20000),
..Default::default()
};
let mut socket =
awkernel_async_lib::net::udp::UdpSocket::bind_on_interface(INTERFACE_ID, &config).map_err(
|e| {
log::error!("Failed to bind UDP socket: {:?}", e);
()
},
)?;
let server_addr = IpAddr::new_v4(NTP_SERVER_ADDR);
let mut buf = [0u8; 48];

let mut packet = NtpPacket::new();
let originate_ts = SystemClock::now().into();

packet.transmit_timestamp = originate_ts;

socket
.send(&packet.to_bytes(), &server_addr, NTP_SERVER_PORT)
.await
.map_err(|e| {
log::error!("Failed to send a NTP packet: {:?}", e);
})?;

socket.recv(&mut buf).await.unwrap();

let destination_ts = SystemClock::now().into();
let packet = NtpPacket::from_bytes(&buf);
let (delay, ofs) = packet.parse_response(originate_ts, destination_ts);

Ok((delay, ofs))
}

async fn poll_time_from_server() {
for _ in 0..3 {
match get_time_from_server().await {
Ok((delay, ofs)) => {
log::info!("Delay: {:?}", delay);
log::info!("Offset: {:?}", ofs);
}
Err(_) => {
log::error!("Failed to get time from server");
}
};

awkernel_async_lib::sleep(Duration::from_secs(2)).await;
}
}

async fn set_time() {
SystemClock::set(1041379200_000_000_000); // 2003-11-01

let clock = SystemClock::now();
log::info!("set_time_from_packet: Current time: {:?}", clock);

let st = SystemTime::new(1041379200_000_000_000);
assert!(
clock.duration_since(st).unwrap().as_micros() < 100,
"Time set incorrectly",
);
}

async fn get_time_from_kernel() {
let clock = SystemClock::now();
log::info!("get_time_from_packet: Current time: {:?}", clock);
}

async fn synchronize_with_server() {
let (_delay, offset) = match get_time_from_server().await {
Ok((delay, offset)) => (delay, offset),
Err(_) => {
log::error!("Failed to get time from server");
return;
}
};

log::info!("Time before adjustment: {:?}", SystemClock::now());
SystemClock::adjust(offset);
log::info!("Time set to: {:?}", SystemClock::now());
}
7 changes: 6 additions & 1 deletion awkernel_lib/src/arch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub(crate) use self::std_common::StdCommon as ArchImpl;
#[cfg(not(feature = "std"))]
trait Arch:
super::delay::Delay
+ super::ntp::Ntp
+ super::interrupt::Interrupt
+ super::cpu::CPU
+ super::paging::Mapper
Expand All @@ -42,6 +43,10 @@ trait Arch:
#[allow(dead_code)]
#[cfg(feature = "std")]
trait Arch:
super::delay::Delay + super::interrupt::Interrupt + super::cpu::CPU + super::dvfs::Dvfs
super::delay::Delay
+ super::ntp::Ntp
+ super::interrupt::Interrupt
+ super::cpu::CPU
+ super::dvfs::Dvfs
{
}
1 change: 1 addition & 0 deletions awkernel_lib/src/arch/std_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub(super) mod cpu;
pub(super) mod delay;
pub(super) mod dvfs;
pub(super) mod interrupt;
pub(super) mod ntp;

pub fn init() {
delay::init();
Expand Down
21 changes: 21 additions & 0 deletions awkernel_lib/src/arch/std_common/ntp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use awkernel_sync::{mcs::MCSNode, mutex::Mutex};

use crate::ntp::{Ntp, SystemTime};

impl Ntp for super::StdCommon {
/// Get time in microseconds.
fn get_time() -> SystemTime {
let mut tp = libc::timespec {
tv_sec: 0,
tv_nsec: 0,
};
unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut tp) };
let t = tp.tv_sec as u128 * 1_000_000_000 + tp.tv_nsec as u128;

SystemTime::new(t)
}

fn set_time(new: u64) {}

fn adjust_time(_offset: SignedDuration) {}
}
1 change: 1 addition & 0 deletions awkernel_lib/src/arch/x86_64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub(super) mod interrupt;
pub mod interrupt_remap;
pub mod kvm;
pub mod msr;
pub mod ntp;
pub mod page_allocator;
pub mod page_table;
pub(super) mod paging;
Expand Down
40 changes: 40 additions & 0 deletions awkernel_lib/src/arch/x86_64/ntp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use core::time::Duration;

use awkernel_sync::{mcs::MCSNode, mutex::Mutex};

use crate::{
delay,
ntp::{Ntp, SignedDuration, SystemTime},
};

/// The time offset from the Unix epoch in nanoseconds.
static TIME_BASE: Mutex<u128> = Mutex::new(1004572800_000_000_000); // 2001-11-01

impl Ntp for super::X86 {
fn get_time() -> SystemTime {
let up = delay::uptime();
let mut node = MCSNode::new();
let guard = TIME_BASE.lock(&mut node);
let syst = SystemTime::new(*guard as u128);
syst + Duration::from_micros(up)
}

fn set_time(new: u128) {
let mut node = MCSNode::new();
let mut guard = TIME_BASE.lock(&mut node);
let up = delay::uptime() as u128 * 1000;
*guard = new - up;
}

fn adjust_time(offset: SignedDuration) {
let mut node = MCSNode::new();
let mut guard = TIME_BASE.lock(&mut node);

let offset = offset.as_nanos();
if offset > 0 {
*guard = guard.wrapping_add(offset as u128);
} else {
*guard = guard.wrapping_sub(-offset as u128);
}
}
}
1 change: 1 addition & 0 deletions awkernel_lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod local_heap;
pub mod logger;
pub mod mmio;
pub mod net;
pub mod ntp;
pub mod priority_queue;
pub mod sanity;
pub mod sync;
Expand Down
5 changes: 5 additions & 0 deletions awkernel_lib/src/net/if_net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ impl IfNetInner {
self.interface.routes_mut().remove_default_ipv4_route();
}

self.interface
.routes_mut()
.add_default_ipv4_route(gateway)
.unwrap();
log::error!("adding {gateway:?} as a gateway");
self.default_gateway_ipv4 = Some(gateway);
}
}
Expand Down
Loading
Loading