Skip to content

Commit

Permalink
ip li add name type dummy_rs working
Browse files Browse the repository at this point in the history
Signed-off-by: Finn Behrens <[email protected]>
  • Loading branch information
kloenk committed Apr 29, 2021
1 parent 6e3bed3 commit deda3f0
Show file tree
Hide file tree
Showing 10 changed files with 372 additions and 300 deletions.
100 changes: 48 additions & 52 deletions drivers/net/dummy_rs.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
// SPDX-License-Identifier: GPL-2.0

//! Rust dummy network driver
//!
//!
//! This is a demonstration of what a small driver looks like in Rust, based on drivers/net/dummy.c.
//! This code is provided as a demonstration only, not as a proposal to mass-rewrite existing drivers in Rust
// TODO: copyright (see ./dummy.c)


#![no_std]
#![feature(allocator_api, global_asm)]

use core::ops::Deref;

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

module! {
type: RustNetDummy,
name: b"dummy_rs",
author: b"Rust for Linux Contributors",
description: b"Rust dummy network driver",
license: b"GPL v2",
alias: b"rtnl-link-dummy_rs",
alias_rtnl_link: b"dummy_rs",
params: {
numdummies: usize {
default: 0,
Expand All @@ -36,9 +38,10 @@ module! {
}

fn setup(dev: &mut NetDevice<DummyRsDev>) {
pr_info!("called rtnl_setup");
dev.ether_setup();

dev.set_ops();

// Fill in device structure with ethernet-generic values.
dev.add_flag(device::Iff::NOARP);
dev.remove_flag(device::Iff::MULTICAST);
Expand Down Expand Up @@ -67,18 +70,14 @@ fn setup(dev: &mut NetDevice<DummyRsDev>) {
}

fn validate(tb: &NlAttrVec, data: &NlAttrVec, ext_ack: &NlExtAck) -> KernelResult<()> {
pr_info!("validate nlattr");
if let Some(addr) = tb.get(kernel::bindings::IFLA_ADDRESS) {
if addr.nla_len() != kernel::net::netlink::ETH_ALEN {
return Err(Error::EINVAL);
}
if !addr.is_valid_ether_addr() {
return Err(Error::EADDRNOTAVAIL);
}
} else {
pr_info!("no IFLA_ADDRESS in nlattr");
}
pr_info!("valid nlattr");
Ok(())
}

Expand All @@ -90,52 +89,51 @@ rtnl_link_ops! {
}

struct RustNetDummy {
dev: NetDevice<DummyRsDev>,
//dev: NetDevice<DummyRsDev>,
}


impl KernelModule for RustNetDummy {
fn init() -> KernelResult<Self> {
{
let lock =THIS_MODULE.kernel_param_lock();
pr_info!("Rust Network Dummy with {} pseudo devices\n", numdummies.read(&lock));
}

unsafe { dummy_rs_rtnl_link_ops.register() }?;

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());
return Err(e);
let num = {
let lock = THIS_MODULE.kernel_param_lock();
pr_info!(
"Rust Network Dummy with {} pseudo devices\n",
numdummies.read(&lock)
);
numdummies.read(&lock).clone()
};

unsafe { dummy_rs_link_ops.register() }?;

for x in 0..(num) {
let dev = NetDevice::new(
DummyRsDev,
kernel::cstr!("dummyrs%d"),
kernel::net::device::NetNameAssingType::Enum,
1,
1,
)?;
dev.set_rtnl_ops(unsafe { &dummy_rs_link_ops });

if let Err(e) = dev.register() {
pr_warn!("could not register: {}", e.to_kernel_errno());
return Err(e);
}
}
pr_info!("device registered");

Ok(RustNetDummy {
dev,
//dev,
})
}
}

impl Drop for RustNetDummy {
fn drop(&mut self) {
pr_info!("remove rust net dummy");


unsafe {
//let ptr = &dummy_rs_rtnl_link_ops as *const _ as *mut kernel::bindings::rtnl_link_ops;
pr_info!("rtnl: {:#?}", &dummy_rs_rtnl_link_ops.0);
let ptr = &dummy_rs_rtnl_link_ops.get_ptr();
pr_info!("rtnl_link_ops_ptr: {:?}", ptr);
}
// TODO rtnl_link_unregister
// TODO: remove unsafe somehow
unsafe { dummy_rs_rtnl_link_ops.unregister() };
unsafe { dummy_rs_link_ops.unregister() };
}
}


struct DummyRsDev;

impl NetDeviceOps<Self> for DummyRsDev {
Expand All @@ -159,19 +157,15 @@ impl NetDeviceOps<Self> for DummyRsDev {
fn start_xmit(skb: SkBuff, dev: &mut NetDevice<Self>) -> kernel::net::device::NetdevTX {
let mut skb = skb;

// TODO: dev_lstatt_add(dev, skb->len)
dev.lstats_add(skb.len());

skb.tx_timestamp();
drop(skb);

pr_info!("start_xmit called");

kernel::net::device::NetdevTX::TX_OK
}

fn get_stats64(dev: &NetDevice<Self>, stats: &mut rtnl::RtnlLinkStats64) {
pr_info!("get stats64");
stats.dev_read(dev);
}

Expand All @@ -182,18 +176,18 @@ impl NetDeviceOps<Self> for DummyRsDev {
}

fn validate_addr(dev: &NetDevice<Self>) -> KernelResult<()> {
pr_info!("eth_validate_addr");
device::helpers::eth_validate_addr(dev)
}

fn set_mac_addr(dev: &mut NetDevice<Self>, p: *mut kernel::c_types::c_void) -> KernelResult<()> {
fn set_mac_addr(
dev: &mut NetDevice<Self>,
p: *mut kernel::c_types::c_void,
) -> KernelResult<()> {
device::helpers::eth_mac_addr(dev, p)
}

// Someting about faking multicast
fn set_rx_mode(dev: &mut NetDevice<Self>) {
pr_info!("set_rx_mode");
}
// [Someting about faking multicast](https://elixir.bootlin.com/linux/v5.12-rc4/source/drivers/net/dummy.c#L48).
fn set_rx_mode(_dev: &mut NetDevice<Self>) {}
}

impl NetDeviceAdapter for DummyRsDev {
Expand All @@ -204,9 +198,7 @@ impl NetDeviceAdapter for DummyRsDev {
type EthOps = Self;

fn setup(dev: &mut NetDevice<Self>) {
pr_info!("called netdev_setup");
setup(dev);
//dev.set_rtnl_ops( unsafe { &dummy_rs_rtnl_link_ops });
}
}

Expand All @@ -218,7 +210,11 @@ impl EthToolOps<Self> for DummyRsDev {
// FIXME: !!
let info: &kernel::bindings::ethtool_drvinfo = info.deref();
unsafe {
kernel::bindings::strlcpy(&(info.driver) as *const _ as *mut i8, b"dummy_rs\0" as *const _ as *mut i8, 32);
kernel::bindings::strlcpy(
&(info.driver) as *const _ as *mut i8,
b"dummy_rs\0" as *const _ as *mut i8,
32,
);
}
}

Expand Down
2 changes: 1 addition & 1 deletion rust/kernel/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,4 @@ macro_rules! c_from_kernel_result {
$($tt)*
})())
}};
}
}
4 changes: 2 additions & 2 deletions rust/kernel/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ pub mod c_types;
pub mod chrdev;
mod error;
pub mod file_operations;
pub mod net;
pub mod miscdev;
pub mod net;
pub mod pages;

pub mod linked_list;
Expand All @@ -65,7 +65,7 @@ pub mod iov_iter;
mod types;
pub mod user_ptr;

pub use crate::error::{Error, KernelResult, c_from_kernel_result};
pub use crate::error::{c_from_kernel_result, Error, KernelResult};
pub use crate::types::{CStr, Mode};

/// Page size defined in terms of the `PAGE_SHIFT` macro from C.
Expand Down
Loading

0 comments on commit deda3f0

Please sign in to comment.