Skip to content

Commit

Permalink
socket: support rtnl_getlink for netlink route
Browse files Browse the repository at this point in the history
Signed-off-by: rayylee <rayylee@foxmail.com>
  • Loading branch information
hbuxiaofei committed Apr 8, 2024
1 parent 6843d0d commit ef1df59
Show file tree
Hide file tree
Showing 4 changed files with 251 additions and 26 deletions.
13 changes: 13 additions & 0 deletions modules/axnet/src/netlink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ extern crate alloc;
use alloc::sync::Arc;
use alloc::collections::VecDeque;
use core::cmp::min;
use axtask::yield_now;

use axsync::Mutex;
use axerrno::AxResult;
Expand Down Expand Up @@ -106,6 +107,18 @@ impl NetlinkSocket {
}

pub fn recv_from(&self, buf: &mut [u8]) -> AxResult<usize> {
// loop {
// let len = {
// let tx = self.tx_buffer.lock();
// tx.len()
// };
// if len == 0 {
// yield_now();
// continue;
// }
// break;
// }

let mut tx = self.tx_buffer.lock();
let length = min(buf.len(), tx.len());
for i in 0..length {
Expand Down
15 changes: 5 additions & 10 deletions ulib/axstarry/src/syscall_net/imp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,19 +353,14 @@ pub fn syscall_sendto(args: [usize; 6]) -> SyscallResult {
}
SocketInner::Netlink(s) => {
let ans = s.send(buf);
let addr = buf.as_ptr() as *const u16;
let nlh = unsafe {
NlMsgHdr {
nlmsg_len: *(addr as *const u32),
nlmsg_type: *(addr.add(2) as *const u16),
nlmsg_flags: *(addr.add(3) as *const u16),
nlmsg_seq: *(addr.add(4) as *const u32),
nlmsg_pid: *(addr.add(6) as *const u32),
}
let buf_ptr: *const u8 = buf.as_ptr();
let nlh_ptr: *mut NlMsgHdr = buf_ptr as *mut NlMsgHdr;
let nlh: &mut NlMsgHdr = unsafe {
&mut *nlh_ptr
};
error!(">>> nlmsg: {:?}", nlh);
if nlh.nlmsg_flags > 0 {
netlink_ack(&s, &nlh);
netlink_ack(&s, nlh);
}
ans
}
Expand Down
71 changes: 58 additions & 13 deletions ulib/axstarry/src/syscall_net/netlink.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,69 @@
use super::rtnetlink::*;
use axnet::NetlinkSocket;
use axlog::error;
use num_enum::TryFromPrimitive;
use super::rtnetlink::*;

#[derive(TryFromPrimitive, PartialEq, Eq, Debug)]
#[repr(u16)]
#[allow(non_camel_case_types)]
pub enum NlMessageFlags {
/// It is request message.
NLM_F_REQUEST = 1,
/// Multipart message, terminated by NLMSG_DONE.
NLM_F_MULTI = 2,
/// Reply with ack, with zero or error code.
NLM_F_ACK = 4,
/// Echo this request.
NLM_F_ECHO = 8,
/// Dump was inconsistent due to sequence change.
NLM_F_DUMP_INTR = 16,
}

#[derive(TryFromPrimitive, PartialEq, Eq, Debug)]
#[repr(u16)]
#[allow(non_camel_case_types)]
pub enum NlMessageGet {
NLM_F_ROOT = 0x100,
NLM_F_MATCH = 0x200,
NLM_F_ATOMIC = 0x400,
NLM_F_DUMP = 0x100 | 0x200,
}

#[derive(TryFromPrimitive, PartialEq, Eq, Debug)]
#[repr(u16)]
#[allow(non_camel_case_types)]
pub enum NlMessageNew {
NLM_F_REPLACE = 0x100,
NLM_F_EXCL = 0x200,
NLM_F_CREATE = 0x400,
NLM_F_APPEND = 0x800,
}

pub fn netlink_ack(sk: &NetlinkSocket, nlh: &NlMsgHdr)
pub fn netlink_ack(sk: &NetlinkSocket, nlh: &mut NlMsgHdr)
{
// # define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
// (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
// (nlh)->nlmsg_len <= (len))

let mut buffer: [u8; 20] = [0; 20];
buffer[0] = 16; // nlmsg_len: sizeof(struct nlmsghdr)
buffer[4] = 16; // nlmsg_type: RTM_NEWLINK
buffer[6] = 65; // 'A'
buffer[7] = 66; // 'B'
buffer[8] = 67; // 'C'
buffer[9] = 68; // 'D'
buffer[10] = 69; // 'E'

if nlh.nlmsg_type == 18 || nlh.nlmsg_type == 20 {
let _ = sk.fill_tx(&buffer);
}
let mut done_msg: [u8; 20] = [0; 20];
done_msg[0] = 16; // nlmsg_len: sizeof(struct nlmsghdr)
done_msg[4] = 0x3; // nlmsg_type: NLMSG_DONE
done_msg[6] = 65; // 'A'
done_msg[7] = 66; // 'B'
done_msg[8] = 67; // 'C'
done_msg[9] = 68; // 'D'
done_msg[10] = 69; // 'E'

if let Ok(msg_type) = RtmType::try_from(nlh.nlmsg_type) {
if msg_type == RtmType::RTM_GETLINK || msg_type == RtmType::RTM_GETADDR {
let mut skb = SkBuff::new();
let _ = rtnl_getlink( &mut skb, nlh);
error!(">>> recv nlmsg_len:{} skb: {:?}", nlh.nlmsg_len, skb.get_data());
let _ = sk.fill_tx(skb.get_data());
// let _ = sk.fill_tx(&done_msg);
}
};
}


Expand Down
178 changes: 175 additions & 3 deletions ulib/axstarry/src/syscall_net/rtnetlink.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,36 @@
extern crate alloc;
use alloc::{string::String, string::ToString, collections::BTreeMap, vec::Vec};
use alloc::vec::Vec;

use axerrno::{AxError, AxResult};
use num_enum::TryFromPrimitive;

#[derive(TryFromPrimitive, PartialEq, Eq, Clone, Debug)]
#[repr(u16)]
#[allow(non_camel_case_types)]
pub enum RtmType {
RTM_NEWLINK = 16, // RTM_BASE
RTM_DELLINK = 17,
RTM_GETLINK = 18,
RTM_SETLINK = 19,
RTM_NEWADDR = 20,
RTM_DELADDR = 21,
RTM_GETADDR = 22,
}

#[derive(TryFromPrimitive, PartialEq, Eq, Clone, Debug)]
#[repr(u16)]
#[allow(non_camel_case_types)]
pub enum IflaSpec {
IFLA_UNSPEC = 0,
IFLA_ADDRESS = 1,
IFLA_BROADCAST = 2,
IFLA_IFNAME = 3,
IFLA_MTU = 4,
IFLA_LINK = 5,
IFLA_QDISC = 6,
IFLA_STATS = 7,
IFLA_COST = 8,
}

pub struct SkBuff {
payload: Vec<u8>,
Expand Down Expand Up @@ -65,7 +93,7 @@ impl SkBuff {
}


#[derive(PartialEq, Eq, Clone, Debug)]
#[derive(PartialEq, Eq, Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct NlMsgHdr {
pub nlmsg_len: u32,
Expand All @@ -75,8 +103,152 @@ pub struct NlMsgHdr {
pub nlmsg_pid: u32,
}

type FnPtr = fn(&mut SkBuff, &mut NlMsgHdr);
#[derive(PartialEq, Eq, Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct IfInfoMsg {
pub ifi_family: u8,
pub __ifi_pad: u8,
pub ifi_type: u16,
pub ifi_index: i32,
pub ifi_flags: u32,
pub ifi_change: u32,
}

#[derive(PartialEq, Eq, Copy, Clone, Debug, Default)]
#[repr(C)]
pub struct IfAddrMsg {
pub ifa_family: u8,
/// The prefix length
pub ifa_prefixle: u8,
/// Flags
pub ifa_flags: u8,
/// Address scope
pub ifa_scope: u8,
/// Link index
pub ifa_index: u32,
}

#[derive(PartialEq, Eq, Clone, Debug, Default)]
#[repr(C)]
pub struct RtAddr {
pub rta_len: u16,
pub rta_type: u16,
}

#[derive(PartialEq, Eq, Clone, Debug, Default)]
#[repr(C)]
struct RtnlLinkStats {
pub rx_packets: u32,
pub tx_packets: u32,
pub rx_bytes: u32,
pub tx_bytes: u32,
pub rx_errors: u32,
pub tx_errors: u32,
pub rx_dropped: u32,
pub tx_dropped: u32,
pub multicast: u32,
pub collisions: u32,

pub rx_length_errors: u32,
pub rx_over_errors: u32,
pub rx_crc_errors: u32,
pub rx_frame_errors: u32,
pub rx_fifo_errors: u32,
pub rx_missed_errors: u32,

pub tx_aborted_errors: u32,
pub tx_carrier_errors: u32,
pub tx_fifo_errors: u32,
pub tx_heartbeat_errors: u32,
pub tx_window_errors: u32,

pub rx_compressed: u32,
pub tx_compressed: u32,

pub rx_nohandler: u32,
}

fn nlmsg_end(skb: &mut SkBuff, nlh: &mut NlMsgHdr) -> usize {
nlh.nlmsg_len = skb.length() as u32;

let ptr: *const u8 = skb.get_data().as_ptr();
let nlh_ptr: *mut NlMsgHdr = ptr as *mut NlMsgHdr;
unsafe {
let nlh_new: &mut NlMsgHdr = &mut *nlh_ptr;
nlh_new.nlmsg_len = nlh.nlmsg_len;
}

skb.length()
}

fn nla_put_u8(skb: &mut SkBuff, attrtype: IflaSpec, buf: &[u8]) {
let mut rtattr = RtAddr {
..Default::default()
};
rtattr.rta_type = attrtype as u16;
rtattr.rta_len = core::mem::size_of::<RtAddr>() as u16 + buf.len() as u16;

let ptr = &rtattr as *const RtAddr as *const u8;
let rtattr_slice = unsafe {
core::slice::from_raw_parts(ptr, core::mem::size_of::<RtAddr>())
};

skb.skb_put(rtattr_slice);
skb.skb_put(buf);
}

fn nla_put_u32(skb: &mut SkBuff, attrtype: IflaSpec, value: u32) {
let bytes: [u8; 4] = value.to_ne_bytes();
nla_put_u8(skb, attrtype, &bytes);
}

fn nla_put_string(skb: &mut SkBuff, attrtype: IflaSpec, s: &str) {
let bytes = s.as_bytes();
nla_put_u8(skb, attrtype, &bytes);
}

pub fn rtnl_getlink(skb: &mut SkBuff, nlh: &mut NlMsgHdr) -> AxResult {
nlh.nlmsg_type = RtmType::RTM_NEWLINK as u16;
let ptr = nlh as *const NlMsgHdr as *const u8;
let nlh_buf = unsafe {
core::slice::from_raw_parts(ptr, core::mem::size_of::<NlMsgHdr>())
};
skb.skb_put(nlh_buf);

let ifinfomsg = IfInfoMsg {
..Default::default()
};
let ptr = &ifinfomsg as *const IfInfoMsg as *const u8;
let ifinfomsg_buf = unsafe {
core::slice::from_raw_parts(ptr, core::mem::size_of::<IfInfoMsg>())
};
skb.skb_put(ifinfomsg_buf);

nla_put_string(skb, IflaSpec::IFLA_IFNAME, "eth0");

nla_put_u32(skb, IflaSpec::IFLA_MTU, 1500);

let mut link_state = RtnlLinkStats {
..Default::default()
};
link_state.rx_packets = 75937;
link_state.rx_bytes = 29396057;
link_state.tx_packets = 506109;
link_state.tx_bytes = 174857788;
let ptr = &link_state as *const RtnlLinkStats as *const u8;
let link_state_buf = unsafe {
core::slice::from_raw_parts(ptr, core::mem::size_of::<RtnlLinkStats>())
};
nla_put_u8(skb, IflaSpec::IFLA_STATS, &link_state_buf);

let mac: [u8; 6] = [0x00, 0x0c, 0x29, 0xe9, 0xf2, 0x2e];
nla_put_u8(skb, IflaSpec::IFLA_ADDRESS, &mac);

nlmsg_end(skb, nlh);

Ok(())
}

pub fn rtnl_dump_ifinfo(skb: &mut SkBuff, nlh: &mut NlMsgHdr) -> AxResult {
Ok(())
}

0 comments on commit ef1df59

Please sign in to comment.