Skip to content

Commit

Permalink
WIP: NLA_HDRLEN is missing
Browse files Browse the repository at this point in the history
  • Loading branch information
kloenk committed Apr 25, 2021
1 parent e0ad809 commit e6b2cb7
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 15 deletions.
19 changes: 14 additions & 5 deletions drivers/net/dummy_rs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#![no_std]
#![feature(allocator_api, global_asm)]

use kernel::prelude::*;
use kernel::{net::netlink::{NlAttrVec, NlExtAck}, prelude::*};
use kernel::net::prelude::*;
use kernel::net::device;

Expand Down Expand Up @@ -60,6 +60,15 @@ fn setup(dev: &mut NetDevice<DummyRsDev>) {
dev.set_mtu(0, 0);
}

fn validate(tb: &NlAttrVec, data: &NlAttrVec, ext_ack: &NlExtAck) -> KernelResult<()> {
if let Some(addr) = tb.get(kernel::bindings::IFLA_ADDRESS) {
if addr.nla_len() != kernel::binding::ETH_ALEN {
return Err(0)
}
}
Ok(())
}

rtnl_link_ops! {
kind: b"dummy_rs",
type: DummyRsDev,
Expand All @@ -79,7 +88,8 @@ impl KernelModule for RustNetDummy {
pr_info!("Rust Network Dummy with {} pseudo devices\n", numdummies.read(&lock));
}

let dev = NetDevice::new(DummyRsDev, kernel::cstr!("dummyrs%d"), kernel::net::device::NetNameAssingType::Enum, 1, 1)?;
let mut dev = NetDevice::new(DummyRsDev, kernel::cstr!("dummyrs%d"), kernel::net::device::NetNameAssingType::Enum, 1, 1)?;
dev.set_rtnl_ops( unsafe { &dummy_rs_rtnl_link_ops });

if let Err(e) = dev.register() {
pr_warn!("could not register: {}", e.to_kernel_errno());
Expand Down Expand Up @@ -122,9 +132,8 @@ impl NetDeviceAdapter for DummyRsDev {

fn setup(dev: &mut NetDevice<Self>) {
pr_info!("called netdev_setup");
//dev.rtnl_link_ops = unsafe { &dummy_rs_rtnl_link_ops as *const kernel::bindings::rtnl_link_ops as *mut _ };
dev.set_rtnl_ops( unsafe { &dummy_rs_rtnl_link_ops });

setup(dev);
//dev.set_rtnl_ops( unsafe { &dummy_rs_rtnl_link_ops });
}
}

Expand Down
10 changes: 5 additions & 5 deletions rust/generate_rust_analyzer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function generate_crate() {
module=$2
member=${3:-"true"}
cfg=${4:-$(generate_cfgs)}
deps=${5:-'[{"crate":0,"name":"core"},{"crate":2,"name":"alloc"},{"crate":3,"name":"kernel"}]'}
deps=${5:-'[{"crate":0,"name":"core"},{"crate":2,"name":"alloc"},{"crate":4,"name":"kernel"}]'}
extra=${EXTRA:-""}

echo "{
Expand All @@ -43,9 +43,6 @@ function generate_kernel() {
generate_crate "alloc" "${lib_src}/alloc/src/lib.rs" "false" "[]" \
'[{"crate":0,"name":"core"},{"crate":1,"name":"compiler_builtins"}]'
echo ","
EXTRA=$dylib_and_extra generate_crate "kernel" "${srctree}/rust/kernel/lib.rs" "true" "$(generate_cfgs)" \
'[{"crate":0,"name":"core"},{"crate":2,"name":"alloc"}]'
echo ","
echo '{
"display_name":"module",
"root_module":"'${srctree}'/rust/module.rs",
Expand All @@ -54,7 +51,10 @@ function generate_kernel() {
"deps": [],
"cfg": []
},'
generate_crate "module" "${srctree}/rust/module.rs"
EXTRA=$dylib_and_extra generate_crate "kernel" "${srctree}/rust/kernel/lib.rs" "true" "$(generate_cfgs)" \
'[{"crate":0,"name":"core"},{"crate":2,"name":"alloc"},{"crate":3,"name":"module"}]'
#echo ","
#generate_crate "module" "${srctree}/rust/module.rs"
echo ","
}

Expand Down
15 changes: 10 additions & 5 deletions rust/kernel/net/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,26 @@ unsafe impl<T: NetDeviceAdapter> Sync for NetDevice<T> {}

impl<T: NetDeviceAdapter> NetDevice<T> {
pub fn new(priv_data: T, format_name: CStr<'static>, name_assign_type: NetNameAssingType, txqs: u32, rxqs: u32) -> KernelResult<Self> {
let _lock = RtnlLock::lock();
// Lock is hold
let dev = unsafe { Self::new_locked(priv_data, format_name, name_assign_type, txqs, rxqs) };
dev
}

pub unsafe fn new_locked(priv_data: T, format_name: CStr<'static>, name_assign_type: NetNameAssingType, txqs: u32, rxqs: u32) -> KernelResult<Self> {
// TODO: check for {t,r}xqs bigger 0
let size = mem::size_of::<T>() as i32;

// Safety: TODO
let ptr = unsafe { bindings::alloc_netdev_mqs(size, format_name.as_ptr() as _, name_assign_type as u8, Some(setup_netdev_callback::<T>), txqs, rxqs) };
let ptr = bindings::alloc_netdev_mqs(size, format_name.as_ptr() as _, name_assign_type as u8, Some(setup_netdev_callback::<T>), txqs, rxqs);
if ptr.is_null() {
return Err(Error::ENOMEM);
}

if size != 0 {
// Safety: T is valid and dest is created by alloc_netdev_mqs
unsafe {
let dest = rust_helper_netdev_priv(ptr) as *mut T;
ptr::write(dest, priv_data);
}
let dest = rust_helper_netdev_priv(ptr) as *mut T;
ptr::write(dest, priv_data);
}

Ok(Self {
Expand Down
1 change: 1 addition & 0 deletions rust/kernel/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pub mod device;
pub mod ethtool;
pub mod rtnl;
pub mod netlink;

#[doc(inline)]
pub use module::rtnl_link_ops;
Expand Down
88 changes: 88 additions & 0 deletions rust/kernel/net/netlink.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// SPDX-License-Identifier: GPL-2.0
use alloc::vec::Vec;
use core::ops::{Deref, DerefMut};

use crate::{bindings, linked_list::Wrapper};
use crate::{c_types, CStr};
use crate::error::{Error, KernelResult};
use crate::sync::Lock;
use crate::user_ptr::{UserSlicePtr, UserSlicePtrReader, UserSlicePtrWriter};

use super::device::{NetDeviceAdapter, NetDevice};


/*#[repr(C)]
pub struct NlAttr {
nla_len: u16,
nla_type: u16,
}*/
pub struct NlAttr(*const bindings::nlattr);

impl NlAttr {
pub fn is_null(&self) -> bool {
self.0.is_null()
}

pub fn nla_len(&self) -> u16 {
if self.is_null() {
return 0;
}

// NO-PANIC: self is valid and not null
let nlattr = self.0.as_ref().unwrap();
nlattr.nla_len - bindings::NLA_HDRLEN
}

/// Constructs a new [`struct nlattr`] wrapper.
///
/// # Safety
///
/// The pointer `ptr` must be non-null and valid for the lifetime of the object.
pub unsafe fn from_ptr(ptr: *const bindings::nlattr) -> Self {
Self(ptr)
}
/*pub unsafe fn from_ptr(ptr: *const bindings::nlattr) -> &'static mut Self {
(ptr as *mut NlAttr).as_mut().unwrap()
}*/
}

pub struct NlExtAck(*const bindings::netlink_ext_ack);

impl NlExtAck {
/// Constructs a new [`struct netlink_ext_ack`] wrapper.
///
/// # Safety
///
/// The pointer `ptr` must be non-null and valid for the lifetime of the object.
pub unsafe fn from_ptr(ptr: *const bindings::netlink_ext_ack) -> Self {
Self(ptr)
}
}

pub struct NlAttrVec<'a>(&'a mut [NlAttr]);

impl<'a> NlAttrVec<'a> {
pub fn get(&self, offset: u32) -> Option<NlAttr> {
if offset > bindings::__IFLA_MAX {
return None;
}

let nlattr = self.0[offset as usize];
if nlattr.is_null() {
None
} else {
Some(nlattr)
}
}

/// Constructs a new [`struct nlattr[]`] wrapper.
///
/// # Safety
///
/// The pointer `ptr` must be non-null and valid for the lifetime of the object.
/// The pointer `ptr` must be valid for the size of `__IFLA_MAX` * `mem::size_of<NlAttr>`
pub unsafe fn from_ptr(ptr: *const bindings::nlattr) -> Self {
// TODO: is this correct?
Self(core::slice::from_raw_parts_mut(ptr as *mut NlAttr, bindings::__IFLA_MAX as usize))
}
}

0 comments on commit e6b2cb7

Please sign in to comment.