nic_router/nic_bridge: free MAC addresses

Free a MAC address of a session as soon as the session gets destructed.
Adds also according tests to the autopilot list.

Fixes #2470
This commit is contained in:
Martin Stein 2019-03-15 19:33:03 +01:00 committed by Norman Feske
parent bafe3c3fc3
commit 3a59f11708
10 changed files with 364 additions and 1 deletions

View File

@ -0,0 +1,2 @@
set type "nic_bridge"
source ${genode_dir}/repos/os/run/nic_stress.inc

View File

@ -0,0 +1,2 @@
set type "nic_router"
source ${genode_dir}/repos/os/run/nic_stress.inc

167
repos/os/run/nic_stress.inc Normal file
View File

@ -0,0 +1,167 @@
append build_components {
core init timer
server/nic_router
test/nic_stress
}
append_if [string equal $type "nic_bridge"] build_components { server/nic_bridge }
proc exit_support {} {
if {[have_spec fiasco]} {
return "no"
}
return "yes"
}
proc done_string {} {
set done_string ""
if {[have_spec fiasco]} {
append done_string {.*?finished NIC stress test}
append done_string {.*?\n}
append done_string {.*?finished NIC stress test}
append done_string {.*?\n}
} else {
append done_string {.*?"nic_stress_." exited with exit value 0}
append done_string {.*?\n}
append done_string {.*?"nic_stress_." exited with exit value 0}
append done_string {.*?\n}
}
return $done_string
}
proc nr_of_rounds { test_id } {
if {[have_spec sel4]} {
switch $test_id {
1 { return 19 }
2 { return 12 }
}
} else {
switch $test_id {
1 { return 22 }
2 { return 16 }
}
}
return 0
}
proc nr_of_sessions { test_id } {
switch $test_id {
1 { return 11 }
2 { return 17 }
}
return 0
}
build $build_components
create_boot_directory
append config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<default caps="100"/>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>}
append_if [string equal $type "nic_router"] config {
<start name="nic_router" caps="1000">
<resource name="RAM" quantum="10M"/>
<provides><service name="Nic"/></provides>
<config>
<policy label_prefix="nic_stress_2" domain="default"/>
<policy label_prefix="nic_stress_1" domain="default"/>
<domain name="default" interface="10.0.2.55/24"/>
</config>
</start>
<alias name="nic_server" child="nic_router"/>}
append_if [string equal $type "nic_bridge"] config {
<start name="nic_router" caps="1000">
<resource name="RAM" quantum="10M"/>
<provides><service name="Nic"/></provides>
<config>
<policy label_prefix="nic_bridge" domain="default"/>
<domain name="default" interface="10.0.2.55/24"/>
</config>
</start>
<start name="nic_bridge" caps="1000">
<resource name="RAM" quantum="50M"/>
<provides><service name="Nic"/></provides>
<config mac="02:02:02:02:42:00">
<policy label_prefix="nic_stress_2"/>
<policy label_prefix="nic_stress_1"/>
</config>
<route>
<service name="Nic"> <child name="nic_router"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<alias name="nic_server" child="nic_bridge"/>}
append config {
<start name="nic_stress_1" caps="1000">
<binary name="test-nic_stress"/>
<resource name="RAM" quantum="50M"/>
<config exit_support="} [exit_support] {">
<construct_destruct nr_of_rounds="} [nr_of_rounds 1] {"
nr_of_sessions="} [nr_of_sessions 1] {"/>
</config>
<route>
<service name="Nic"> <child name="nic_server"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="nic_stress_2" caps="1000">
<binary name="test-nic_stress"/>
<resource name="RAM" quantum="100M"/>
<config exit_support="} [exit_support] {">
<construct_destruct nr_of_rounds="} [nr_of_rounds 2] {"
nr_of_sessions="} [nr_of_rounds 2] {"/>
</config>
<route>
<service name="Nic"> <child name="nic_server"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
</config>}
install_config $config
append boot_modules {
core init timer
nic_router
test-nic_stress
ld.lib.so
}
append_if [string equal $type "nic_bridge"] boot_modules { nic_bridge }
build_boot_image $boot_modules
append qemu_args " -nographic "
run_genode_until [done_string] 300

View File

@ -68,7 +68,7 @@ class Net::Address_node : public Genode::Avl_node<Address_node<ADDRESS> >,
***************/
void addr(Address addr) { _addr = addr; }
Address addr() { return _addr; }
Address addr() const { return _addr; }
Session_component &component() { return _component; }

View File

@ -191,6 +191,8 @@ class Net::Session_component : private Net::Stream_allocator,
Size_guard &size_guard) override;
void finalize_packet(Ethernet_frame *, Genode::size_t) override;
Mac_address vmac() const { return _mac_node.addr(); }
};
@ -240,6 +242,13 @@ class Net::Root : public Genode::Root_component<Net::Session_component>
policy.attribute_value("ip_addr", Session_component::Ip_addr()));
}
void _destroy_session(Session_component *session) override
{
_mac_alloc.free(session->vmac());
Genode::destroy(md_alloc(), session);
}
public:
Root(Genode::Env &env,

View File

@ -223,6 +223,8 @@ Session_component *Net::Root::_create_session(char const *args)
void Net::Root::_destroy_session(Session_component *session)
{
Mac_address const mac = session->mac_address();
/* read out initial dataspace and session env and destruct session */
Ram_dataspace_capability ram_ds { session->ram_ds() };
Session_env const &session_env { session->session_env() };
@ -235,6 +237,8 @@ void Net::Root::_destroy_session(Session_component *session)
session_env_stack.detach(&session_env);
session_env_stack.free(ram_ds);
_mac_alloc.free(mac);
/* check for leaked quota */
if (session_env_stack.ram_guard().used().value) {
error("NIC session component \"", session_label, "\" leaks RAM quota of ",

View File

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:include schemaLocation="base_types.xsd"/>
<xs:element name="config">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="construct_destruct">
<xs:complexType>
<xs:attribute name="nr_of_rounds" type="xs:nonNegativeInteger" />
<xs:attribute name="nr_of_sessions" type="xs:nonNegativeInteger" />
</xs:complexType>
</xs:element><!-- construct_destruct -->
</xs:choice>
<xs:attribute name="exit_support" type="Boolean" />
</xs:complexType>
</xs:element><!-- config -->
</xs:schema>

View File

@ -0,0 +1,149 @@
/*
* \brief Stress test for low level NIC interactions
* \author Martin Stein
* \date 2019-03-15
*/
/*
* Copyright (C) 2019 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <base/log.h>
#include <base/heap.h>
#include <base/component.h>
#include <base/attached_rom_dataspace.h>
#include <base/attached_ram_dataspace.h>
#include <nic/packet_allocator.h>
#include <nic_session/connection.h>
namespace Local {
using namespace Genode;
struct Construct_destruct_test;
struct Main;
}
struct Local::Construct_destruct_test
{
enum { DEFAULT_NR_OF_ROUNDS = 10 };
enum { DEFAULT_NR_OF_SESSIONS = 10 };
enum { PKT_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE };
enum { BUF_SIZE = 100 * PKT_SIZE };
using Nic_slot = Constructible<Nic::Connection>;
Env &_env;
Allocator &_alloc;
Signal_context_capability &_completed_sigh;
Xml_node const &_config;
Nic::Packet_allocator _pkt_alloc { &_alloc };
bool const _config_exists { _config.has_sub_node("construct_destruct") };
unsigned long const _nr_of_rounds {
_config_exists ?
_config.sub_node("construct_destruct").
attribute_value("nr_of_rounds",
(unsigned long)DEFAULT_NR_OF_ROUNDS) :
(unsigned long)DEFAULT_NR_OF_ROUNDS };
unsigned long const _nr_of_sessions {
_config_exists ?
_config.sub_node("construct_destruct").
attribute_value("nr_of_sessions",
(unsigned long)DEFAULT_NR_OF_SESSIONS) :
(unsigned long)DEFAULT_NR_OF_SESSIONS };
void construct_all(Nic_slot *const nic,
unsigned const round)
{
for (unsigned idx = 0; idx < _nr_of_sessions; idx++) {
try {
nic[idx].construct(_env, &_pkt_alloc, BUF_SIZE, BUF_SIZE);
log("round ", round + 1, "/", _nr_of_rounds, " nic ", idx + 1,
"/", _nr_of_sessions, " mac ", nic[idx]->mac_address());
}
catch (...) {
for (unsigned destruct_idx = 0; destruct_idx < idx; destruct_idx++) {
nic[destruct_idx].destruct();
throw;
}
}
}
}
void destruct_all(Nic_slot *const nic)
{
for (unsigned idx = 0; idx < _nr_of_sessions; idx++) {
nic[idx].destruct();
}
}
Construct_destruct_test(Env &env,
Allocator &alloc,
Signal_context_capability completed_sigh,
Xml_node const &config)
:
_env { env },
_alloc { alloc },
_completed_sigh { completed_sigh },
_config { config }
{
if (!_nr_of_rounds && !_nr_of_sessions) {
Signal_transmitter(_completed_sigh).submit(); }
size_t const ram_size { _nr_of_sessions * sizeof(Nic_slot) };
Attached_ram_dataspace ram_ds { _env.ram(), _env.rm(), ram_size };
Nic_slot *const nic { ram_ds.local_addr<Nic_slot>() };
try {
for (unsigned round = 0; round < _nr_of_rounds; round++) {
construct_all(nic, round);
destruct_all(nic);
}
Signal_transmitter(_completed_sigh).submit();
}
catch (...) {
error("Construct_destruct_test failed"); }
}
};
struct Local::Main
{
Env &_env;
Heap _heap { &_env.ram(), &_env.rm() };
Attached_rom_dataspace _config_rom { _env, "config" };
Xml_node const _config { _config_rom.xml() };
Constructible<Construct_destruct_test> _test_1 { };
bool const _exit_support {
_config.attribute_value("exit_support", true) };
Signal_handler<Main> _test_completed_handler {
_env.ep(), *this, &Main::_handle_test_completed };
void _handle_test_completed()
{
if (_test_1.constructed()) {
_test_1.destruct();
log("--- finished NIC stress test ---");
if (_exit_support) {
_env.parent().exit(0); }
return;
}
}
Main(Env &env) : _env(env)
{
log("--- NIC stress test ---");
_test_1.construct(_env, _heap, _test_completed_handler, _config);
}
};
void Component::construct(Genode::Env &env) { static Local::Main main(env); }

View File

@ -0,0 +1,4 @@
TARGET = test-nic_stress
SRC_CC = main.cc
LIBS = base
CONFIG_XSD = config.xsd

View File

@ -33,9 +33,11 @@ netperf_lxip_router
netperf_lxip_usb30
netperf_lxip_wifi
nic_bridge
nic_bridge_stress
nic_dump
nic_router
nic_router_flood
nic_router_stress
nic_router_uplinks
noux
noux_tool_chain_auto