Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

user(app): 初步实现rust ping 用户程序 #879

Merged
merged 28 commits into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
38458c7
修复mprotect系统调用未正确设置vm_flags的错误 (#847)
MemoryShore Jul 16, 2024
af097f9
fix(time): modify update wall time (#836)
1037827920 Jul 16, 2024
2c5ea7b
chore: 调整triagebot.toml以适应新的组织架构 (#848)
fslongjin Jul 16, 2024
9a4832f
doc: 完善README.md (#849)
fslongjin Jul 17, 2024
ef2a79b
chore: 更新sphinx相关配置,适应read the docs的更新 (#850)
fslongjin Jul 17, 2024
1ea2daa
feat(driver/net): 实现Loopback网卡接口 (#845)
smallcjy Jul 22, 2024
79ad6e5
fix: build-scripts和tools目录下的make check指定工具链版本 (#861)
fslongjin Jul 22, 2024
634349e
fix: tcp poll没有正确处理posix socket的listen状态的问题 (#859)
fslongjin Jul 24, 2024
bd70d2d
chore: 将工具链更新到2024-07-23 (#864)
fslongjin Jul 24, 2024
86ee139
feat(fs): add eventfd syscall support (#858)
Godones Jul 25, 2024
816ee5a
refactor: 删除过时的va-pa转换函数,改为统一使用MMArch (#862)
fslongjin Jul 25, 2024
3c0a1c8
默认nightly-2024-07-23 & config改为config.toml (#872)
Jomocool Jul 26, 2024
703ce5a
fix: 修复由于升级到2024-07-23工具链之后,某些机器上面内核运行一直fault的问题。 (#870)
fslongjin Jul 27, 2024
83eda00
实现多线程发送ping用户程序
smallcjy Jul 27, 2024
e06352b
BUGREPORT: 参数parsing发生错误
smallcjy Jul 27, 2024
286dba2
make fmt
smallcjy Jul 27, 2024
a169654
固定ip
smallcjy Jul 28, 2024
bc88cfe
Merge branch 'DragonOS-Community:master' into ping
smallcjy Jul 28, 2024
06066f4
feat(user): 实现多线程ping用户程序
smallcjy Jul 28, 2024
5348772
添加注释
smallcjy Jul 28, 2024
c2a5b1e
把ping加载在usr下
smallcjy Jul 29, 2024
0648a54
feat(cred): 初步实现Cred (#846)
Jomocool Aug 2, 2024
c559abc
Merge branch 'DragonOS-Community:master' into ping
smallcjy Aug 3, 2024
8268d8a
Merge remote-tracking branch 'upstream/feat-network-syscall' into ping
smallcjy Aug 3, 2024
19ab598
多线程有问题,先改成单线程的
smallcjy Aug 4, 2024
850be2a
fix: 无法ping本地主机
smallcjy Aug 4, 2024
55bbea6
feat: 实现多线程ping
smallcjy Aug 5, 2024
6e2831b
加注释
smallcjy Aug 7, 2024
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
6 changes: 3 additions & 3 deletions kernel/src/driver/net/loopback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::driver::base::device::bus::Bus;
use crate::driver::base::device::driver::Driver;
use crate::driver::base::device::{Device, DeviceType, IdTable};
use crate::driver::base::kobject::{KObjType, KObject, KObjectState};
use crate::init::initcall::INITCALL_DEVICE;
use crate::libs::spinlock::SpinLock;
use crate::net::{generate_iface_id, NET_DEVICES};
use crate::time::Instant;
Expand All @@ -15,13 +14,13 @@ use alloc::sync::{Arc, Weak};
use alloc::vec::Vec;
use core::cell::UnsafeCell;
use core::ops::{Deref, DerefMut};
use log::debug;
use smoltcp::wire::HardwareAddress;
use smoltcp::{
phy::{self},
wire::{IpAddress, IpCidr},
};
use system_error::SystemError;
use unified_init::macros::unified_init;

use super::NetDevice;

Expand Down Expand Up @@ -76,6 +75,7 @@ impl phy::TxToken for LoopbackTxToken {
let result = f(buffer.as_mut_slice());
let mut device = self.driver.inner.lock();
device.loopback_transmit(buffer);
debug!("lo transmit!");
result
}
}
Expand Down Expand Up @@ -478,7 +478,7 @@ pub fn loopback_driver_init() {
}

/// ## lo网卡设备的注册函数
#[unified_init(INITCALL_DEVICE)]
// #[unified_init(INITCALL_DEVICE)]
pub fn loopback_init() -> Result<(), SystemError> {
loopback_probe();
return Ok(());
Expand Down
6 changes: 5 additions & 1 deletion kernel/src/init/initial_kthread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ use system_error::SystemError;

use crate::{
arch::{interrupt::TrapFrame, process::arch_switch_to_user},
driver::{net::e1000e::e1000e::e1000e_init, virtio::virtio::virtio_probe},
driver::{
net::{e1000e::e1000e::e1000e_init, loopback::loopback_init},
virtio::virtio::virtio_probe,
},
filesystem::vfs::core::mount_root_fs,
net::net_core::net_init,
process::{kthread::KernelThreadMechanism, stdio::stdio_init, ProcessFlags, ProcessManager},
Expand Down Expand Up @@ -41,6 +44,7 @@ fn kernel_init() -> Result<(), SystemError> {
net_init().unwrap_or_else(|err| {
error!("Failed to initialize network: {:?}", err);
});
loopback_init()?;

debug!("initial kernel thread done.");

Expand Down
2 changes: 1 addition & 1 deletion kernel/src/net/net_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn dhcp_query() -> Result<(), SystemError> {

//由于现在os未实现在用户态为网卡动态分配内存,而lo网卡的id最先分配且ip固定不能被分配
//所以特判取用id为1的网卡(也就是virto_net)
let net_face = binding.get(&1).ok_or(SystemError::ENODEV)?.clone();
let net_face = binding.get(&0).ok_or(SystemError::ENODEV)?.clone();

drop(binding);

Expand Down
2 changes: 1 addition & 1 deletion tools/run-qemu.sh
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ fi
# ps: 下面这条使用tap的方式,无法dhcp获取到ip,暂时不知道为什么
# QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -net nic,netdev=nic0 -netdev tap,id=nic0,model=virtio-net-pci,script=qemu/ifup-nat,downscript=qemu/ifdown-nat -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
QEMU_DEVICES+="${QEMU_DEVICES_DISK} "
QEMU_DEVICES+=" -netdev user,id=hostnet0,hostfwd=tcp::12580-:12580 -device virtio-net-pci,vectors=5,netdev=hostnet0,id=net0 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
QEMU_DEVICES+=" -netdev user,id=hostnet0,hostfwd=tcp::12580-:12580,hostfwd=udp::12549-:12549 -device virtio-net-pci,vectors=5,netdev=hostnet0,id=net0 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
# E1000E
# QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -netdev user,id=hostnet0,hostfwd=tcp::12580-:12580 -net nic,model=e1000e,netdev=hostnet0,id=net0 -netdev user,id=hostnet1,hostfwd=tcp::12581-:12581 -device virtio-net-pci,vectors=5,netdev=hostnet1,id=net1 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 "
QEMU_ARGUMENT+="-d ${QEMU_DISK_IMAGE} -m ${QEMU_MEMORY} -smp ${QEMU_SMP} -boot order=d ${QEMU_MONITOR} -d ${qemu_trace_std} "
Expand Down
3 changes: 3 additions & 0 deletions user/apps/ping/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/target
Cargo.lock
/install/
18 changes: 18 additions & 0 deletions user/apps/ping/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "ping"
version = "0.1.0"
edition = "2021"
description = "ping for dragonOS"
authors = [ "smallc <[email protected]>" ]

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

[dependencies]
anyhow = "1.0.86"
clap = { version = "4.5.11", features = ["derive"] }
crossbeam-channel = "0.5.13"
pnet = "0.35.0"
rand = "0.8.5"
signal-hook = "0.3.17"
socket2 = "0.5.7"
thiserror = "1.0.63"
56 changes: 56 additions & 0 deletions user/apps/ping/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
TOOLCHAIN=
RUSTFLAGS=

ifdef DADK_CURRENT_BUILD_DIR
# 如果是在dadk中编译,那么安装到dadk的安装目录中
INSTALL_DIR = $(DADK_CURRENT_BUILD_DIR)
else
# 如果是在本地编译,那么安装到当前目录下的install目录中
INSTALL_DIR = ./install
endif

ifeq ($(ARCH), x86_64)
export RUST_TARGET=x86_64-unknown-linux-musl
else ifeq ($(ARCH), riscv64)
export RUST_TARGET=riscv64gc-unknown-linux-gnu
else
# 默认为x86_86,用于本地编译
export RUST_TARGET=x86_64-unknown-linux-musl
endif

run:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET)

build:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET)

clean:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET)

test:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET)

doc:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) doc --target $(RUST_TARGET)

fmt:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt

fmt-check:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) fmt --check

run-release:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) run --target $(RUST_TARGET) --release

build-release:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) build --target $(RUST_TARGET) --release

clean-release:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) clean --target $(RUST_TARGET) --release

test-release:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) test --target $(RUST_TARGET) --release

.PHONY: install
install:
RUSTFLAGS=$(RUSTFLAGS) cargo $(TOOLCHAIN) install --target $(RUST_TARGET) --path . --no-track --root $(INSTALL_DIR) --force
23 changes: 23 additions & 0 deletions user/apps/ping/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# PING
为DragonOS实现ping
## NAME
ping - 向网络主机发送ICMP ECHO_REQUEST
## SYNOPSIS
[-c count]: 指定 ping 的次数。例如,`-c 4` 会向目标主机发送 4 个 ping 请求。

[-i interval]:指定两次 ping 请求之间的时间间隔,单位是秒。例如,`-i 2` 会每 2 秒发送一次 ping 请求。

[-w timeout]: 指定等待 ping 响应的超时时间,单位是秒。例如,`-w 5` 会在 5 秒后超时。

[-s packetsize]:指定发送的 ICMP Packet 的大小,单位是字节。例如,`-s 64` 会发送大小为 64 字节的 ICMP Packet。

[-t ttl]:指定 ping 的 TTL (Time to Live)。例如,`-t 64` 会设置 TTL 为 64。

{destination}:指定要 ping 的目标主机。可以是 IP 地址或者主机名。例如,`192.168.1.1` 或 `www.example.com`。

## DESCRIPTION
ping 使用 ICMP 协议的必需的 ECHO_REQUEST 数据报来引发主机或网关的 ICMP ECHO_RESPONSE。ECHO_REQUEST 数据报(“ping”)具有 IP 和 ICMP 头,后面跟着一个 struct timeval,然后是用于填充数据包的任意数量的“填充”字节。

ping 支持 IPv4 和 IPv6。可以通过指定 -4 或 -6 来强制只使用其中一个。

ping 还可以发送 IPv6 节点信息查询(RFC4620)。可能不允许中间跳跃,因为 IPv6 源路由已被弃用(RFC5095)。
50 changes: 50 additions & 0 deletions user/apps/ping/src/args.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use clap::{arg, command, Parser};
use rand::random;

use crate::config::{Config, IpAddress};

/// # Args结构体
/// 使用clap库对命令行输入进行pasing,产生参数配置
#[derive(Parser, Debug, Clone)]
#[command(author, version, about, long_about = None)]
pub struct Args {
// Count of ping times
#[arg(short, default_value_t = 4)]
count: u16,

// Ping packet size
#[arg(short = 's', default_value_t = 64)]
packet_size: usize,

// Ping ttl
#[arg(short = 't', default_value_t = 64)]
ttl: u32,

// Ping timeout seconds
#[arg(short = 'w', default_value_t = 1)]
timeout: u64,

// Ping interval duration milliseconds
#[arg(short = 'i', default_value_t = 1000)]
interval: u64,

// Ping destination, ip or domain
#[arg(value_parser=IpAddress::parse)]
destination: IpAddress,
}

impl Args {
/// # 将Args结构体转换为config结构体
pub fn as_config(&self) -> Config {
Config {
count: self.count,
packet_size: self.packet_size,
ttl: self.ttl,
timeout: self.timeout,
interval: self.interval,
id: random::<u16>(),
sequence: 1,
address: self.destination.clone(),
}
}
}
45 changes: 45 additions & 0 deletions user/apps/ping/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use anyhow::bail;
use std::{
ffi::CString,
net::{self},
};

use crate::error;

///# Config结构体
/// 记录ping指令的一些参数值
#[derive(Debug, Clone)]
pub struct Config {
pub count: u16,
pub packet_size: usize,
pub ttl: u32,
pub timeout: u64,
pub interval: u64,
pub id: u16,
pub sequence: u16,
pub address: IpAddress,
}

///# 目标地址ip结构体
/// ip负责提供给socket使用
/// raw负责打印输出
#[derive(Debug, Clone)]
pub struct IpAddress {
pub ip: net::IpAddr,
pub raw: String,
}

impl IpAddress {
pub fn parse(host: &str) -> anyhow::Result<Self> {
let raw = String::from(host);
let opt = host.parse::<net::IpAddr>().ok();
match opt {
Some(ip) => Ok(Self { ip, raw }),
None => {
bail!(error::PingError::InvalidConfig(
"Invalid Address".to_string()
));
}
}
}
}
10 changes: 10 additions & 0 deletions user/apps/ping/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#![allow(dead_code)]

#[derive(Debug, Clone, thiserror::Error)]
pub enum PingError {
#[error("invaild config")]
InvalidConfig(String),

#[error("invaild packet")]
InvalidPacket,
}
23 changes: 23 additions & 0 deletions user/apps/ping/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use args::Args;
use clap::Parser;
use std::format;

mod args;
mod config;
mod error;
mod ping;
///# ping入口主函数
fn main() {
let args = Args::parse();
match ping::Ping::new(args.as_config()) {
Ok(pinger) => pinger.run().unwrap_or_else(|e| {
exit(format!("Error on run ping: {}", e));
}),
Err(e) => exit(format!("Error on init: {}", e)),
}
}

fn exit(msg: String) {
eprintln!("{}", msg);
std::process::exit(1);
}
Loading
Loading