mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +00:00
run: add nic driver performance test
A run script which sends raw ethernet packets from the host machine to the target machine. Three tests are implemented: - The network_stat instrumented driver of usb_drv and net_drv are used to get the raw receive performance of the network driver. - A simple nic_session client is receiving from the un-instrumented network driver raw ethernet packets. - A bridge is added between driver and simple nic_session client.
This commit is contained in:
parent
0920e322c2
commit
b5d3be9c85
262
os/run/network_test_nic.inc
Normal file
262
os/run/network_test_nic.inc
Normal file
@ -0,0 +1,262 @@
|
||||
#
|
||||
# \brief Nic performance test
|
||||
# \author Alexander Boettcher
|
||||
# \date 2013-03-26
|
||||
#
|
||||
|
||||
if {[have_spec linux]} {
|
||||
puts "Run script does not support Linux."; exit 0 }
|
||||
|
||||
#
|
||||
# Build
|
||||
#
|
||||
|
||||
set build_components {
|
||||
core init
|
||||
drivers/pci drivers/timer drivers/nic
|
||||
}
|
||||
|
||||
lappend_if [expr [have_spec omap4] || [have_spec exynos5]] build_components drivers/usb
|
||||
lappend_if [expr [have_spec omap4] || [have_spec exynos5]] build_components drivers/usb_net_stat
|
||||
lappend_if [have_spec acpi] build_components drivers/acpi
|
||||
lappend_if [have_spec pci] build_components drivers/pci/device_pd
|
||||
lappend_if [have_spec x86] build_components drivers/nic_stat
|
||||
|
||||
lappend_if $use_nic_client build_components test/nic_raw
|
||||
lappend_if $use_nic_bridge build_components server/nic_bridge
|
||||
|
||||
#
|
||||
# Choose network driver
|
||||
#
|
||||
if {[expr $use_nic_client && ([have_spec omap4] || [have_spec exynos5])]} {
|
||||
set network_driver "usb_drv" }
|
||||
if {[expr !$use_nic_client && ([have_spec omap4] || [have_spec exynos5])]} {
|
||||
set network_driver "usb_drv_net_stat" }
|
||||
if {[expr $use_nic_client && ![have_spec omap4] && ![have_spec exynos5]]} {
|
||||
set network_driver "nic_drv" }
|
||||
if {[expr !$use_nic_client && ![have_spec omap4] && ![have_spec exynos5]]} {
|
||||
set network_driver "nic_drv_stat" }
|
||||
|
||||
build $build_components
|
||||
|
||||
create_boot_directory
|
||||
|
||||
#
|
||||
# Generate config
|
||||
#
|
||||
|
||||
set config {
|
||||
<config verbose="yes">
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="CAP"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="SIGNAL"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="Timer"/> </provides>
|
||||
</start> }
|
||||
|
||||
append_if [expr [have_spec omap4] || [have_spec exynos5]] config "
|
||||
<start name=\"$network_driver\">
|
||||
<resource name=\"RAM\" quantum=\"12M\"/>
|
||||
<provides>
|
||||
<service name=\"Nic\"/>
|
||||
</provides>
|
||||
<config>
|
||||
<nic mac=\"2e:60:90:0c:4e:01\" />
|
||||
</config>
|
||||
</start>"
|
||||
|
||||
append_if [expr ![have_spec omap4] && ![have_spec exynos5]] config "
|
||||
<start name=\"$network_driver\">
|
||||
<resource name=\"RAM\" quantum=\"4M\"/>
|
||||
<provides><service name=\"Nic\"/></provides>
|
||||
</start>"
|
||||
|
||||
append_if $use_nic_bridge config {
|
||||
<start name="nic_bridge">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides><service name="Nic"/></provides>
|
||||
<route>
|
||||
<service name="Nic"> }
|
||||
append_if $use_nic_bridge config "
|
||||
<child name=\"$network_driver\"/>"
|
||||
append_if $use_nic_bridge config {
|
||||
</service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start> }
|
||||
|
||||
append_if $use_nic_client config {
|
||||
<start name="test-nic_raw">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<route> }
|
||||
append_if [expr $use_nic_client && $use_nic_bridge] config {
|
||||
<service name="Nic"> <child name="nic_bridge"/> </service> }
|
||||
append_if $use_nic_client config {
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start> }
|
||||
|
||||
append_if [have_spec acpi] config {
|
||||
<start name="acpi">
|
||||
<resource name="RAM" quantum="6M"/>
|
||||
<binary name="acpi_drv"/>
|
||||
<provides>
|
||||
<service name="PCI"/>
|
||||
<service name="IRQ" />
|
||||
</provides>
|
||||
<route>
|
||||
<service name="PCI"> <any-child /> </service>
|
||||
<any-service> <parent/> <any-child /> </any-service>
|
||||
</route>
|
||||
</start>}
|
||||
|
||||
append_if [expr ![have_spec acpi] && [have_spec pci]] config {
|
||||
<start name="pci_drv">
|
||||
<resource name="RAM" quantum="3M"/>
|
||||
<provides> <service name="PCI"/> </provides>
|
||||
</start> }
|
||||
|
||||
append config {
|
||||
</config>
|
||||
}
|
||||
|
||||
install_config $config
|
||||
|
||||
#
|
||||
# Boot modules
|
||||
#
|
||||
|
||||
# generic modules
|
||||
set boot_modules {
|
||||
core init timer
|
||||
}
|
||||
|
||||
lappend_if $use_nic_client boot_modules test-nic_raw
|
||||
lappend_if $use_nic_bridge boot_modules nic_bridge
|
||||
|
||||
# platform-specific modules
|
||||
lappend_if [have_spec acpi] boot_modules acpi_drv
|
||||
lappend_if [have_spec pci] boot_modules pci_drv
|
||||
lappend_if [expr [have_spec omap4] || [have_spec exynos5]] boot_modules usb_drv
|
||||
lappend_if [expr [have_spec omap4] || [have_spec exynos5]] boot_modules usb_drv_net_stat
|
||||
lappend_if [expr ![have_spec omap4] && ![have_spec exynos5]] boot_modules nic_drv
|
||||
lappend_if [expr ![have_spec omap4] && ![have_spec exynos5]] boot_modules nic_drv_stat
|
||||
lappend_if [have_spec nova] boot_modules pci_device_pd
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
# build the test client
|
||||
set test_client_dir $genode_dir/os/src/lib/net
|
||||
if {![file exists bin/nic_drv_test_client]} {
|
||||
exec g++ -Wall -o bin/nic_drv_test_client $test_client_dir/stat-client.cc
|
||||
}
|
||||
# set appropriate rights to create raw sockets
|
||||
set cap_rights [exec getcap bin/nic_drv_test_client]
|
||||
if {![regexp cap_net_raw $cap_rights]} {
|
||||
set sudo_command "sudo setcap cap_net_raw=ep bin/nic_drv_test_client"
|
||||
puts "For sending raw packets cap_net_raw permission are required."
|
||||
puts "Trying to execute: '$sudo_command'"
|
||||
eval "exec $sudo_command"
|
||||
}
|
||||
|
||||
#
|
||||
# Execute test case
|
||||
#
|
||||
|
||||
if {[expr [have_spec omap4] || [have_spec exynos5]]} {
|
||||
run_genode_until {announces service "Nic"} 30
|
||||
set serial_id $spawn_id
|
||||
|
||||
set match_string "Using configured mac: "
|
||||
|
||||
sleep 10
|
||||
} else {
|
||||
set match_string {--- get MAC address }
|
||||
run_genode_until "$match_string.*\n" 30
|
||||
set serial_id $spawn_id
|
||||
|
||||
sleep 2
|
||||
|
||||
}
|
||||
|
||||
# remember output string, will be overwritten by next run_genode_until
|
||||
set mac_string $output
|
||||
|
||||
if {$use_nic_client} {
|
||||
# wait until client become ready
|
||||
if {![regexp {ready to receive packets} $output]} {
|
||||
run_genode_until {ready to receive packets} 10 $serial_id
|
||||
}
|
||||
}
|
||||
|
||||
if {$use_nic_bridge} {
|
||||
set match_string "mac: "
|
||||
if {![regexp "$match_string.*\n" $output]} {
|
||||
run_genode_until "$match_string.*\n" 10 $serial_id
|
||||
}
|
||||
}
|
||||
|
||||
grep_output $match_string
|
||||
unify_output {[\r\n\t]+} ""
|
||||
unify_output {[\033]\[0m} ""
|
||||
|
||||
set pos [string first $match_string $mac_string]
|
||||
set mac_addr [string replace $mac_string 0 [expr $pos + [string length $match_string] - 1]]
|
||||
|
||||
#
|
||||
# Start test with different packet size
|
||||
#
|
||||
set test_result ""
|
||||
set packet_size_list [list 64 128 256 512 1024 1500]
|
||||
foreach packet_size $packet_size_list {
|
||||
set packet_count [expr 200 * 1024 * 1024 / $packet_size]
|
||||
|
||||
set time_start [clock milliseconds]
|
||||
spawn bin/nic_drv_test_client eth0 $mac_addr $packet_size $packet_count
|
||||
set test_app_id $spawn_id
|
||||
interact $test_app_id
|
||||
|
||||
run_genode_until "packets dropped.*\n" 15 $serial_id
|
||||
run_genode_until "packets dropped.*\n" 70 $serial_id
|
||||
set time_end [clock milliseconds]
|
||||
|
||||
set target_data [regexp -inline {[0-9]+ kiBytes} $output]
|
||||
set target_data [regexp -inline {[0-9]+} $target_data]
|
||||
|
||||
set match_string {[0-9]+ kBit/s \(raw [0-9]+ kBit/s\), runtime [0-9]+ ms}
|
||||
set target_perf [regexp -inline $match_string $output]
|
||||
set target_perf [regexp -all -inline {[0-9]+} $target_perf]
|
||||
set target_runtime [lindex $target_perf 2]
|
||||
set target_perf [lindex $target_perf 0]
|
||||
|
||||
set host_data [expr $packet_count * $packet_size / 1024 ]
|
||||
# set host_perf [expr $host_data * 1024 * 8 / ($time_end - $time_start)]
|
||||
set host_perf [expr $target_data * 1024 * 8 / ($time_end - $time_start)]
|
||||
|
||||
puts "host : data send - $host_data kiBytes"
|
||||
puts "target: data received - $target_data kiBytes"
|
||||
puts "host : runtime [expr $time_end - $time_start] ms $host_perf kBit/s"
|
||||
puts "target: runtime $target_runtime ms $target_perf kBit/s"
|
||||
puts "! PERF: rx_$packet_size [expr $host_perf / 1000] MBit/s ok"
|
||||
set test_result "$test_result rx_$packet_size:$host_perf"
|
||||
}
|
||||
close -i $serial_id
|
||||
|
||||
puts ""
|
||||
puts "Test succeeded"
|
||||
|
||||
# vi: set ft=tcl :
|
14
os/run/network_test_nic.run
Normal file
14
os/run/network_test_nic.run
Normal file
@ -0,0 +1,14 @@
|
||||
source ${genode_dir}/os/run/network_test_nic_raw.run
|
||||
set test_result_raw $test_result
|
||||
|
||||
source ${genode_dir}/os/run/network_test_nic_raw_client.run
|
||||
set test_result_raw_client $test_result
|
||||
|
||||
source ${genode_dir}/os/run/network_test_nic_raw_bridge_client.run
|
||||
set test_result_raw_bridge_client $test_result
|
||||
|
||||
puts "\nTest results:\n"
|
||||
puts "nic : $test_result_raw"
|
||||
puts "nic+client : $test_result_raw_client"
|
||||
puts "nic+bridge+client: $test_result_raw_bridge_client"
|
||||
puts ""
|
4
os/run/network_test_nic_raw.run
Normal file
4
os/run/network_test_nic_raw.run
Normal file
@ -0,0 +1,4 @@
|
||||
set use_nic_client 0
|
||||
set use_nic_bridge 0
|
||||
|
||||
source ${genode_dir}/os/run/network_test_nic.inc
|
4
os/run/network_test_nic_raw_bridge_client.run
Normal file
4
os/run/network_test_nic_raw_bridge_client.run
Normal file
@ -0,0 +1,4 @@
|
||||
set use_nic_client 1
|
||||
set use_nic_bridge 1
|
||||
|
||||
source ${genode_dir}/os/run/network_test_nic.inc
|
4
os/run/network_test_nic_raw_client.run
Normal file
4
os/run/network_test_nic_raw_client.run
Normal file
@ -0,0 +1,4 @@
|
||||
set use_nic_client 1
|
||||
set use_nic_bridge 0
|
||||
|
||||
source ${genode_dir}/os/run/network_test_nic.inc
|
190
os/src/lib/net/stat-client.cc
Normal file
190
os/src/lib/net/stat-client.cc
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* \brief Send a raw Ethernet frame
|
||||
* \author Alexander Boettcher
|
||||
* \date 2013-04-02
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/ether.h>
|
||||
|
||||
#include <linux/ip.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/if_packet.h>
|
||||
|
||||
enum {
|
||||
FRAG_DONT = 0x40,
|
||||
|
||||
IP_VERSION = 4,
|
||||
IP_HEADER_LENGTH = 5, /* 5 * 4Bytes */
|
||||
|
||||
PROTOCOL_IP_UDP = 17,
|
||||
|
||||
PACKET_BUFFER = 4096,
|
||||
};
|
||||
|
||||
static unsigned short checksum(unsigned short * data, unsigned short count) {
|
||||
unsigned short result = 0;
|
||||
|
||||
for (unsigned i=0; i < count; i++) {
|
||||
result += htons(data[i]);
|
||||
}
|
||||
|
||||
return ~result;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char * net_if_name = argv[1];
|
||||
const char * net_mac_dst = argv[2];
|
||||
struct ifreq net_if, net_mac_src;
|
||||
|
||||
if (argc < 5 || strlen(net_mac_dst) < 17) {
|
||||
printf("argument missing\n");
|
||||
printf("usage: '<net_dev> <mac_addr> <packet_size> <packet_count>'"
|
||||
" - e.g. 'eth0 2e:60:90:0c:4e:01 256 65536'\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned long const packet_size = atol(argv[3]);
|
||||
unsigned long const packet_count = atol(argv[4]);
|
||||
|
||||
char packet[PACKET_BUFFER];
|
||||
memset(packet, 0, sizeof(packet));
|
||||
|
||||
if (packet_size < 64 || packet_size > sizeof(packet)) {
|
||||
printf("packet size must be in the range of 64 - %lu\n",
|
||||
sizeof(packet));
|
||||
return 1;
|
||||
}
|
||||
printf("sending %lu packets a %lu Bytes via %s network interface\n",
|
||||
packet_count, packet_size, net_if_name);
|
||||
|
||||
int const sock_fd = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
|
||||
if (sock_fd < 0) {
|
||||
perror("socket d");
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* get network interface */
|
||||
memset(&net_if, 0, sizeof(net_if));
|
||||
strncpy(net_if.ifr_name, net_if_name, strlen(net_if_name));
|
||||
if (ioctl(sock_fd, SIOCGIFINDEX, &net_if)) {
|
||||
perror("ioctl SIOCGIFINDEX");
|
||||
return 3;
|
||||
}
|
||||
|
||||
/* get mac of network interface */
|
||||
memset(&net_mac_src, 0, sizeof(net_mac_src));
|
||||
strncpy(net_mac_src.ifr_name, net_if_name, strlen(net_if_name));
|
||||
if (ioctl(sock_fd, SIOCGIFHWADDR, &net_mac_src)) {
|
||||
perror("ioctl SIOCGIFHWADDR");
|
||||
return 4;
|
||||
}
|
||||
|
||||
struct ether_header *eh = (struct ether_header *) packet;
|
||||
|
||||
/* create ethernet frame */
|
||||
memcpy(eh->ether_shost, net_mac_src.ifr_hwaddr.sa_data, ETH_ALEN);
|
||||
for (unsigned i=0; i < ETH_ALEN; i++)
|
||||
eh->ether_dhost[i] = strtoul(&net_mac_dst[i*3], 0, 16);
|
||||
eh->ether_type = htons(ETH_P_IP);
|
||||
|
||||
/* debugging */
|
||||
if (true) {
|
||||
printf("%02x", eh->ether_shost[0]);
|
||||
for (unsigned i=1; i < ETH_ALEN; i++)
|
||||
printf(":%02x", eh->ether_shost[i]);
|
||||
|
||||
printf(" -> %02x", eh->ether_dhost[0]);
|
||||
for (unsigned i=1; i < ETH_ALEN; i++)
|
||||
printf(":%02x", eh->ether_dhost[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* create IP frame */
|
||||
struct iphdr *ip = (struct iphdr *) (packet + sizeof(struct ether_header));
|
||||
|
||||
ip->version = IP_VERSION;
|
||||
ip->ihl = IP_HEADER_LENGTH;
|
||||
ip->protocol = PROTOCOL_IP_UDP;
|
||||
/*
|
||||
ip->daddr = (10U) | (65U << 24);
|
||||
ip->saddr = (10U) | (22U << 24);
|
||||
*/
|
||||
ip->tot_len = htons(packet_size - ((char *)ip - packet));
|
||||
ip->ttl = 10;
|
||||
ip->frag_off = FRAG_DONT;
|
||||
|
||||
ip->check = htons(checksum((unsigned short *)ip,
|
||||
sizeof(*ip) / sizeof(unsigned short)));
|
||||
|
||||
/* setup UDP header */
|
||||
struct udphdr *udp = (struct udphdr *) (ip + 1);
|
||||
udp->source = htons(7321);
|
||||
udp->dest = htons(7323);
|
||||
|
||||
/* add UDP data */
|
||||
char * data = (char *) (udp + 1);
|
||||
char txt_magic[] = "Hello world! Genode is greeting.";
|
||||
memcpy(data, txt_magic, sizeof(txt_magic));
|
||||
|
||||
int len = data + sizeof(txt_magic) - packet;
|
||||
udp->len = htons(len - ((char *)udp - packet));
|
||||
|
||||
if ((len + 0UL) > sizeof(packet)) {
|
||||
printf("packet size larger then buffer %d > %lu\n", len, sizeof(packet));
|
||||
return 5;
|
||||
}
|
||||
|
||||
/* send packet */
|
||||
struct sockaddr_ll socket_address;
|
||||
socket_address.sll_ifindex = net_if.ifr_ifindex;
|
||||
socket_address.sll_halen = ETH_ALEN;
|
||||
memcpy(socket_address.sll_addr, net_mac_dst, ETH_ALEN);
|
||||
|
||||
int res = sendto(sock_fd, packet, len, 0, (struct sockaddr*)&socket_address,
|
||||
sizeof(struct sockaddr_ll));
|
||||
if (res != len) {
|
||||
perror("sending packet - start");
|
||||
return 6;
|
||||
}
|
||||
memset(data, 0, sizeof(txt_magic));
|
||||
|
||||
for (unsigned long j=0; j < packet_count;j++)
|
||||
{
|
||||
res = sendto(sock_fd, packet, packet_size, 0,
|
||||
(struct sockaddr*)&socket_address,
|
||||
sizeof(struct sockaddr_ll));
|
||||
}
|
||||
|
||||
memcpy(data, txt_magic, sizeof(txt_magic));
|
||||
|
||||
usleep (5000);
|
||||
res = sendto(sock_fd, packet, len, 0, (struct sockaddr*)&socket_address,
|
||||
sizeof(struct sockaddr_ll));
|
||||
if (res != len) {
|
||||
perror("sending packet - end");
|
||||
return 6;
|
||||
}
|
||||
|
||||
printf("send %lu packets a %lu Bytes = %lu kiBytes\n",
|
||||
packet_count, packet_size,
|
||||
packet_count / 1024 * packet_size);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user