vancouver: Network support

Vancouver is now able to use the Intel 82576 device model from NUL to
give VMs access to the network via the nic_bridge service. In order to
integrate the device model, it had to be renamed to i82576 due to XML
limitations. This is done by a patch applied via the 'make prepare'
mechanism.

Although current network card models in Vancouver panic if they can't
get a MAC address, the OP_GET_MAC hostop now fails gracefully in the
case where no nic_drv or nic_bridge is available.
This commit is contained in:
Markus Partheymueller 2012-10-11 14:41:29 +02:00 committed by Norman Feske
parent 1ca0a66ea9
commit 1c447d98e9
7 changed files with 239 additions and 10 deletions

View File

@ -12,6 +12,18 @@ $(call check_tool,git)
#
PORTS += $(VANCOUVER)
#
# We need to execute some python scripts for preparing the i82576vf
# device model.
#
PYTHON2 := $(notdir $(lastword $(shell which python2 python2.{4,5,6,7,8})))
ifeq ($(PYTHON2),)
prepare: python_not_installed
python_not_installed:
$(ECHO) "Error: Vancouver needs Python 2 to be installed"
@false;
endif
prepare:: $(CONTRIB_DIR)/$(VANCOUVER)
#
@ -23,7 +35,20 @@ $(DOWNLOAD_DIR)/$(VANCOUVER)/.git:
git reset --hard $(VANCOUVER_REV) && \
cd ../.. && touch $@
I82576VF_DIR = $(CONTRIB_DIR)/$(VANCOUVER)/julian/model/82576vf
$(CONTRIB_DIR)/$(VANCOUVER)/.git: $(DOWNLOAD_DIR)/$(VANCOUVER)/.git
$(VERBOSE)git clone $(DOWNLOAD_DIR)/$(VANCOUVER) $(CONTRIB_DIR)/$(VANCOUVER)
$(VERBOSE)patch -d $(CONTRIB_DIR)/$(VANCOUVER) -N -p1 < src/vancouver/rename-82576-i82576.patch
@# fix python version in code generator scripts
$(VERBOSE)sed -i "s/env python2/env $(PYTHON2)/" $(I82576VF_DIR)/genreg.py
$(VERBOSE)sed -i "s/env python2/env $(PYTHON2)/" $(I82576VF_DIR)/genreg2.py
@# call code generators
$(VERBOSE)cd $(I82576VF_DIR); \
./genreg.py reg_pci.py ../../../vancouver/include/model/82576vfpci.inc
$(VERBOSE)cd $(I82576VF_DIR); \
./genreg.py reg_mmio.py ../../../vancouver/include/model/82576vfmmio.inc
$(VERBOSE)cd $(I82576VF_DIR); \
./genreg2.py reg_mmio.py ../../../vancouver/include/model/82576vfmmio_vnet.inc
$(CONTRIB_DIR)/$(VANCOUVER): $(CONTRIB_DIR)/$(VANCOUVER)/.git

View File

@ -1,19 +1,28 @@
/*
* \brief Meta-data registry about the device models of Vancouver
* \author Norman Feske
* \author Markus Partheymueller
* \date 2011-11-18
*/
/*
* Copyright (C) 2011-2013 Genode Labs GmbH
* Copyright (C) 2012 Intel Corporation
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*
* The code is partially based on the Vancouver VMM, which is distributed
* under the terms of the GNU General Public License version 2.
*
* Modifications by Intel Corporation are contributed under the terms and
* conditions of the GNU General Public License version 2.
*/
/* local includes */
#include <device_model_registry.h>
Device_model_registry *device_model_registry()
{
static Device_model_registry inst;
@ -72,6 +81,8 @@ MODEL_INFO(pmtimer, "io_port")
MODEL_INFO(pcihostbridge, "bus_num", "bus_count", "io_base", "mem_base")
MODEL_INFO(i82576vf, "promisc", "mem_mmio", "mem_msix", "txpoll_us", "rx_map")
MODEL_INFO_NO_ARG(vbios_disk)
MODEL_INFO_NO_ARG(vbios_keyboard)
MODEL_INFO_NO_ARG(vbios_mem)

View File

@ -43,6 +43,8 @@
#include <rom_session/connection.h>
#include <rm_session/connection.h>
#include <cap_session/connection.h>
#include <base/allocator_avl.h>
#include <nic_session/connection.h>
#include <os/config.h>
#include <os/alarm.h>
#include <timer_session/connection.h>
@ -60,6 +62,7 @@
#include <device_model_registry.h>
#include <boot_module_provider.h>
#include <console.h>
#include <network.h>
enum {
PAGE_SIZE_LOG2 = 12UL,
@ -72,6 +75,12 @@ enum { verbose_debug = false };
enum { verbose_npt = false };
enum { verbose_io = false };
static Genode::Native_utcb utcb_backup;
Genode::Lock *utcb_lock()
{
static Genode::Lock inst;
return &inst;
}
/**
* Semaphore used as global lock
@ -983,6 +992,7 @@ class Vcpu_dispatcher : public Genode::Thread<STACK_SIZE>,
}
};
const void * _forward_pkt;
class Machine : public StaticReceiver<Machine>
{
@ -999,6 +1009,8 @@ class Machine : public StaticReceiver<Machine>
bool _alloc_fb_mem; /* For detecting FB alloc message */
Nic::Session *_nic;
public:
/*********************************************
@ -1173,7 +1185,38 @@ class Machine : public StaticReceiver<Machine>
return true;
}
case MessageHostOp::OP_GET_MAC:
{
Genode::Allocator_avl * tx_block_alloc =
new Genode::Allocator_avl(Genode::env()->heap());
try {
_nic = new Nic::Connection(tx_block_alloc);
} catch (...) {
Logging::printf("No NIC connection possible!\n");
return false;
}
PINF("Our mac address is %2x:%2x:%2x:%2x:%2x:%2x\n",
_nic->mac_address().addr[0],
_nic->mac_address().addr[1],
_nic->mac_address().addr[2],
_nic->mac_address().addr[3],
_nic->mac_address().addr[4],
_nic->mac_address().addr[5]
);
msg.mac = ((Genode::uint64_t)_nic->mac_address().addr[0] & 0xff) << 40 |
((Genode::uint64_t)_nic->mac_address().addr[1] & 0xff) << 32 |
((Genode::uint64_t)_nic->mac_address().addr[2] & 0xff) << 24 |
((Genode::uint64_t)_nic->mac_address().addr[3] & 0xff) << 16 |
((Genode::uint64_t)_nic->mac_address().addr[4] & 0xff) << 8 |
((Genode::uint64_t)_nic->mac_address().addr[5] & 0xff);
/* Start receiver thread for this MAC */
Vancouver_network * netreceiver = new Vancouver_network(_motherboard, _nic);
return true;
}
default:
PWRN("HostOp %d not implemented", msg.type);
@ -1233,9 +1276,47 @@ class Machine : public StaticReceiver<Machine>
bool receive(MessageNetwork &msg)
{
if (verbose_debug)
PDBG("MessageNetwork");
return false;
if (msg.type != MessageNetwork::PACKET) return false;
Genode::Lock::Guard guard(*utcb_lock());
utcb_backup = *Genode::Thread_base::myself()->utcb();
if (msg.buffer == _forward_pkt) {
/* don't end in an endless forwarding loop */
return false;
}
/* allocate transmit packet */
Packet_descriptor tx_packet;
try {
tx_packet = _nic->tx()->alloc_packet(msg.len);
} catch (Nic::Session::Tx::Source::Packet_alloc_failed) {
PERR("tx packet alloc failed");
return false;
}
/* fill packet with content */
char *tx_content = _nic->tx()->packet_content(tx_packet);
_forward_pkt = tx_content;
for (unsigned i = 0; i < msg.len; i++) {
tx_content[i] = msg.buffer[i];
}
_nic->tx()->submit_packet(tx_packet);
/* wait for acknowledgement */
Packet_descriptor ack_tx_packet = _nic->tx()->get_acked_packet();
if (ack_tx_packet.size() != tx_packet.size()
|| ack_tx_packet.offset() != tx_packet.offset()) {
PERR("unexpected acked packet");
}
/* release sent packet to free the space in the tx communication buffer */
_nic->tx()->release_packet(tx_packet);
*Genode::Thread_base::myself()->utcb() = utcb_backup;
return true;
}
bool receive(MessagePciConfig &msg)

View File

@ -0,0 +1,51 @@
/*
* \brief Network receive handler per MAC address
* \author Markus Partheymueller
* \date 2012-07-31
*/
/*
* Copyright (C) 2012 Intel Corporation
* Copyright (C) 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.
*
* The code is partially based on the Vancouver VMM, which is distributed
* under the terms of the GNU General Public License version 2.
*
* Modifications by Intel Corporation are contributed under the terms and
* conditions of the GNU General Public License version 2.
*/
/* local includes */
#include <network.h>
extern const void * _forward_pkt;
Vancouver_network::Vancouver_network(Motherboard &mb, Nic::Session * nic)
: _mb(mb), _nic(nic)
{
start();
}
void Vancouver_network::entry()
{
Logging::printf("Hello, this is the network receiver.\n");
while (true) {
Packet_descriptor rx_packet = _nic->rx()->get_packet();
/* send it to the network bus */
char * rx_content = _nic->rx()->packet_content(rx_packet);
_forward_pkt = rx_content;
MessageNetwork msg((unsigned char *)rx_content, rx_packet.size(), 0);
_mb.bus_network.send(msg);
_forward_pkt = 0;
/* acknowledge received packet */
_nic->rx()->acknowledge_packet(rx_packet);
}
}

View File

@ -0,0 +1,51 @@
/*
* \brief Network receive handler per MAC address
* \author Markus Partheymueller
* \date 2012-07-31
*/
/*
* Copyright (C) 2012 Intel Corporation
* Copyright (C) 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.
*
* The code is partially based on the Vancouver VMM, which is distributed
* under the terms of the GNU General Public License version 2.
*
* Modifications by Intel Corporation are contributed under the terms and
* conditions of the GNU General Public License version 2.
*/
#ifndef _NETWORK_H_
#define _NETWORK_H_
/* Genode includes */
#include <nic_session/connection.h>
/* NOVA userland includes */
#include <nul/motherboard.h>
using Genode::List;
using Genode::Thread;
class Vancouver_network : public Thread<4096>
{
private:
Motherboard &_mb;
Nic::Session *_nic;
public:
/* initialisation */
void entry();
/**
* Constructor
*/
Vancouver_network(Motherboard &mb, Nic::Session *nic);
};
#endif /* _NETWORK_H_ */

View File

@ -0,0 +1,13 @@
diff --git a/julian/model/82576vf.cc b/julian/model/82576vf.cc
index b4d29a5..db8d2f3 100644
--- a/julian/model/82576vf.cc
+++ b/julian/model/82576vf.cc
@@ -950,7 +950,7 @@ public:
};
-PARAM_HANDLER(82576vf,
+PARAM_HANDLER(i82576vf,
"82576vf:[promisc][,mem_mmio][,mem_msix][,txpoll_us][,rx_map] - attach an Intel 82576VF to the PCI bus.",
"promisc - if !=0, be always promiscuous (use for Linux VMs that need it for bridging) (Default 1)",
"txpoll_us - if !=0, map TX registers to guest and poll them every txpoll_us microseconds. (Default 0)",

View File

@ -12,24 +12,21 @@ endif
LIBS += cxx env blit thread alarm signal server
SRC_CC = main.cc nova_user_env.cc device_model_registry.cc
SRC_CC += console.cc keyboard.cc
SRC_CC += console.cc keyboard.cc network.cc
SRC_BIN = mono.tff
#
# '82576vfmmio.inc' is apparently missing from the NOVA userland distribution.
# So let's skip building the 82576vf device model for now.
#
FILTER_OUT = model/82576vf.cc
MODEL_SRC_CC += $(notdir $(wildcard $(VANCOUVER_DIR)/model/*.cc))
EXECUTOR_SRC_CC += $(notdir $(wildcard $(VANCOUVER_DIR)/executor/*.cc))
SERVICE_SRC_CC += hostsink.cc
SRC_CC += $(filter-out $(FILTER_OUT),$(addprefix model/,$(MODEL_SRC_CC)))
SRC_CC += $(CONTRIB_DIR)/julian/model/82576vf.cc
SRC_CC += $(filter-out $(FILTER_OUT),$(addprefix executor/,$(EXECUTOR_SRC_CC)))
SRC_CC += base/service/hostsink.cc base/lib/runtime/string.cc
INC_DIR += $(PRG_DIR)
INC_DIR += $(CONTRIB_DIR)/julian/model
INC_DIR += $(CONTRIB_DIR)/julian/include
INC_DIR += $(VANCOUVER_DIR)/model
INC_DIR += $(VANCOUVER_DIR)/executor
INC_DIR += $(VANCOUVER_DIR)/include