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

add loopback by multi-socketset #136

Closed
wants to merge 1 commit into from
Closed
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
3,458 changes: 3,458 additions & 0 deletions api/arceos_posix_api/src/ctypes_gen.rs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions apps/c/httpserver_loopback/axbuild.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
app-objs := httpserver.o
4 changes: 4 additions & 0 deletions apps/c/httpserver_loopback/features.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
alloc
paging
net
multitask
139 changes: 139 additions & 0 deletions apps/c/httpserver_loopback/httpserver.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/* Copyright (c) [2023] [Syswonder Community]
* [Ruxos] is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sys/socket.h>

#define PORT 5555
#define BUFFER_SIZE 1024

void *handle_client(void *arg) {
int new_socket = *(int*)arg;
char buffer[BUFFER_SIZE] = {0};

read(new_socket, buffer, BUFFER_SIZE);
printf("Server received: %s\n", buffer);
send(new_socket, "Hello from server", strlen("Hello from server"), 0);
printf("Server sent: %s\n", "Hello from server");

close(new_socket);
free(arg); // Free the allocated memory for the socket

return NULL;
}

void *server_thread(void *arg) {
int server_fd, *new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);

if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Socket failed");
exit(EXIT_FAILURE);
}

address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);

if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("Bind failed");
close(server_fd);
exit(EXIT_FAILURE);
}

if (listen(server_fd, 3) < 0) {
perror("Listen failed");
close(server_fd);
exit(EXIT_FAILURE);
}

printf("Server listening on 127.0.0.1:%d\n", PORT);

while (1) {
new_socket = malloc(sizeof(int));
if ((*new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0) {
perror("Accept failed");
free(new_socket);
continue;
}

pthread_t client_thread;
if (pthread_create(&client_thread, NULL, handle_client, new_socket) != 0) {
perror("Failed to create client thread");
free(new_socket);
}
}

close(server_fd);

return NULL;
}

void *client_thread(void *arg) {
sleep(1); // Ensure the server is listening before the client tries to connect

struct sockaddr_in serv_addr;
char *message = "Hello from client";
char buffer[BUFFER_SIZE] = {0};
int sock = 0;

if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Socket creation error");
return NULL;
}

serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);

if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0) {
perror("Invalid address / Address not supported");
close(sock);
return NULL;
}

if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
perror("Connection failed");
close(sock);
return NULL;
}

send(sock, message, strlen(message), 0);
printf("Client sent: %s\n", message);
read(sock, buffer, BUFFER_SIZE);
printf("Client received: %s\n", buffer);

close(sock);

return NULL;
}

int main() {
pthread_t server_tid, client_tid;

if (pthread_create(&server_tid, NULL, server_thread, NULL) != 0) {
perror("Failed to create server thread");
exit(EXIT_FAILURE);
}

if (pthread_create(&client_tid, NULL, client_thread, NULL) != 0) {
perror("Failed to create client thread");
exit(EXIT_FAILURE);
}

pthread_join(server_tid, NULL);
pthread_join(client_tid, NULL);

return 0;
}
2 changes: 2 additions & 0 deletions crates/driver_net/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ use alloc::sync::Arc;
#[cfg(feature = "ixgbe")]
/// ixgbe NIC device driver.
pub mod ixgbe;
/// loopback device driver
pub mod loopback;
mod net_buf;

use core::ptr::NonNull;
Expand Down
126 changes: 126 additions & 0 deletions crates/driver_net/src/loopback.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/* Copyright (c) [2023] [Syswonder Community]
* [Ruxos] is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
use crate::{EthernetAddress, NetBuf, NetBufBox, NetBufPool, NetBufPtr, NetDriverOps};
use alloc::collections::VecDeque;
use alloc::sync::Arc;
use driver_common::{BaseDriverOps, DevError, DevResult, DeviceType};

extern crate alloc;

const NET_BUF_LEN: usize = 1526;

/// The VirtIO network device driver.
///
/// `QS` is the VirtIO queue size.
pub struct LoopbackDevice {
mac_address: EthernetAddress,
pub(crate) queue: VecDeque<NetBufBox>,
buf_pool: Arc<NetBufPool>,
}

unsafe impl Send for LoopbackDevice {}
unsafe impl Sync for LoopbackDevice {}

impl LoopbackDevice {
/// Creates a new driver instance and initializes the device
pub fn new(mac_address: [u8; 6]) -> Self {
let buf_pool = match NetBufPool::new(1024, NET_BUF_LEN) {
Ok(pool) => pool,
Err(_) => {
panic!("fail to create netbufpool");
}
};
Self {
mac_address: EthernetAddress(mac_address),
queue: VecDeque::new(),
buf_pool: buf_pool,
}
}
}

impl BaseDriverOps for LoopbackDevice {
fn device_name(&self) -> &str {
"loopback"
}

fn device_type(&self) -> DeviceType {
DeviceType::Net
}
}

impl NetDriverOps for LoopbackDevice {
#[inline]
fn mac_address(&self) -> EthernetAddress {
EthernetAddress(self.mac_address.0)
}

#[inline]
fn can_transmit(&self) -> bool {
true
}

#[inline]
fn can_receive(&self) -> bool {
!self.queue.is_empty()
}

#[inline]
fn rx_queue_size(&self) -> usize {
self.queue.len()
}

#[inline]
fn tx_queue_size(&self) -> usize {
self.queue.len()
}

fn fill_rx_buffers(&mut self, buf_pool: &Arc<NetBufPool>) -> DevResult {
Ok(())
}

fn recycle_rx_buffer(&mut self, rx_buf: NetBufPtr) -> DevResult {
Ok(())
}

fn recycle_tx_buffers(&mut self) -> DevResult {
Ok(())
}

fn prepare_tx_buffer(&self, tx_buf: &mut NetBuf, pkt_len: usize) -> DevResult {
Ok(())
}

fn transmit(&mut self, tx_buf: NetBufPtr) -> DevResult {
unsafe { self.queue.push_back(NetBuf::from_buf_ptr(tx_buf)) }
Ok(())
}

fn receive(&mut self) -> DevResult<NetBufPtr> {
if let Some(token) = self.queue.pop_front() {
Ok(token.into_buf_ptr())
} else {
Err(DevError::Again)
}
}

fn alloc_tx_buffer(&mut self, size: usize) -> DevResult<NetBufPtr> {
let mut net_buf = self.buf_pool.alloc_boxed().ok_or(DevError::NoMemory)?;
let pkt_len = size;

// 1. Check if the buffer is large enough.
let hdr_len = net_buf.header_len();
if hdr_len + pkt_len > net_buf.capacity() {
return Err(DevError::InvalidParam);
}
net_buf.set_packet_len(pkt_len);

// 2. Return the buffer.
Ok(net_buf.into_buf_ptr())
}
}
2 changes: 1 addition & 1 deletion modules/ruxfs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ features = [ # no std
]

[dev-dependencies]
ruxdriver = { path = "../ruxdriver", features = ["block", "ramdisk"] }
ruxdriver = { path = "../ruxdriver", features = ["block", "ramdisk", "dyn"] }
driver_block = { path = "../../crates/driver_block", features = ["ramdisk"] }
axsync = { path = "../axsync", features = ["multitask"] }
ruxtask = { path = "../ruxtask", features = ["test"] }
4 changes: 3 additions & 1 deletion modules/ruxfs/tests/test_fatfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ fn test_fatfs() {
// By default, mount_points[0] will be rootfs
let mut mount_points: Vec<ruxfs::MountPoint> = Vec::new();
// setup and initialize blkfs as one mountpoint for rootfs
mount_points.push(ruxfs::init_blkfs(AxDeviceContainer::from_one(disk)));
mount_points.push(ruxfs::init_blkfs(AxDeviceContainer::from_one(Box::new(
disk,
))));
ruxfs::prepare_commonfs(&mut mount_points);

// setup and initialize rootfs
Expand Down
4 changes: 2 additions & 2 deletions modules/ruxfs/tests/test_ramfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ fn test_ramfs() {
// By default, mount_points[0] will be rootfs
let mut mount_points: Vec<ruxfs::MountPoint> = Vec::new();
// setup and initialize blkfs as one mountpoint for rootfs
mount_points.push(ruxfs::init_blkfs(AxDeviceContainer::from_one(
mount_points.push(ruxfs::init_blkfs(AxDeviceContainer::from_one(Box::new(
RamDisk::default(),
)));
))));
ruxfs::prepare_commonfs(&mut mount_points);

// setup and initialize rootfs
Expand Down
2 changes: 1 addition & 1 deletion modules/ruxnet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ ruxhal = { path = "../ruxhal" }
axsync = { path = "../axsync" }
axlog = { path = "../axlog" }
ruxtask = { path = "../ruxtask" }
ruxdriver = { path = "../ruxdriver", features = ["net"] }
ruxdriver = { path = "../ruxdriver", features = ["net", "dyn"] }
cty = { version = "0.2.2", optional = true }
axio = { path = "../../crates/axio" }

Expand Down
Loading
Loading