Make nic_bridge's MAC address range configurable

By adding a "mac=XX:XX:XX:XX:XX:XX" attribute/value pair to the nic_bridge's
configuration one can define the first MAC address from which the nic_brigde
will allocate MACs for it's clients. Note: that the least relevant byte will
be ignored, and ranges from 0-255. Fixes #424.
This commit is contained in:
Stefan Kalkowski 2012-10-22 16:44:23 +02:00 committed by Norman Feske
parent 1c064d9e70
commit d3902e8538
6 changed files with 89 additions and 38 deletions

View File

@ -16,6 +16,7 @@
#include <nic_session/nic_session.h>
#include <cap_session/connection.h>
#include <os/config.h>
#include <nic/xml_node.h>
#include <util/xml_node.h>
#include <lx_emul.h>
@ -567,39 +568,6 @@ struct sk_buff *skb_dequeue(struct sk_buff_head *list)
** linux/inerrupt.h **
**********************/
namespace Genode {
/**
* Convert ASCII string to mac address
*/
template <>
inline size_t ascii_to<Nic::Mac_address>(char const *s, Nic::Mac_address* mac, unsigned)
{
enum {
HEX = true,
};
if(strlen(s) < MAC_LEN)
throw -1;
char mac_str[6];
for (int i = 0; i < ETH_ALEN; i++) {
int hi = i * 3;
int lo = hi + 1;
if (!is_digit(s[hi], HEX) || !is_digit(s[lo], HEX))
throw -1;
mac_str[i] = (digit(s[hi], HEX) << 4) | digit(s[lo], HEX);
}
Genode::memcpy(mac->addr, mac_str, ETH_ALEN);
return MAC_LEN;
}
}
static void snprint_mac(char *buf, char *mac)
{
for (int i = 0; i < ETH_ALEN; i++)

56
os/include/nic/xml_node.h Normal file
View File

@ -0,0 +1,56 @@
/*
* \brief Xml-node routines used internally in NIC drivers
* \author Sebastian Sumpf
* \author Stefan Kalkowski
* \date 2012-10-22
*/
/*
* Copyright (C) 2012 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.
*/
#ifndef _INCLUDE__NIC__XML_NODE_H_
#define _INCLUDE__NIC__XML_NODE_H_
#include <nic_session/nic_session.h>
#include <util/string.h>
namespace Genode {
/**
* Convert ASCII string to mac address
*/
template <>
inline size_t ascii_to<Nic::Mac_address>(char const *s,
Nic::Mac_address* mac, unsigned)
{
enum {
HEX = true,
MAC_CHAR_LEN = 17, /* 12 number and 6 colons */
MAC_SIZE = 6,
};
if(strlen(s) < MAC_CHAR_LEN)
throw -1;
char mac_str[6];
for (int i = 0; i < MAC_SIZE; i++) {
int hi = i * 3;
int lo = hi + 1;
if (!is_digit(s[hi], HEX) || !is_digit(s[lo], HEX))
throw -1;
mac_str[i] = (digit(s[hi], HEX) << 4) | digit(s[lo], HEX);
}
Genode::memcpy(mac->addr, mac_str, MAC_SIZE);
return MAC_CHAR_LEN;
}
}
#endif /* _INCLUDE__NIC__XML_NODE_H_ */

View File

@ -0,0 +1,17 @@
The nic_bridge provides multiple sessions of the 'Nic' service while
using a single 'Nic' session for forwarding requests. For proper working
it implements some kind of the 'proxy arp' protocol (rfc1027). That
means it allocates a MAC address for each client. Whenever a client
sends a packet it changes the sender MAC address to the one it hold
available for the client. Moreover, it monitors DHCP packets, and
tracks which IP address is used by which client. Whenever ARP packets
come from the outside it will answer them with the corresponding MAC
address.
By adding the following attribute to the 'nic_bridge' config node:
! <config mac="02:02:02:02:02:00"/>
one can define the first MAC address from which the nic_brigde
will allocate MACs for it's clients. Note: that the least relevant
byte will be ignored always starting from 0.

View File

@ -18,4 +18,4 @@
* it's likely, that we will have no clashes here.
* (e.g. Linux uses 02:00... for its tap-devices.)
*/
const Net::Ethernet_frame::Mac_address Net::Mac_allocator::_mac_addr_base(0x02);
Net::Ethernet_frame::Mac_address Net::Mac_allocator::mac_addr_base(0x02);

View File

@ -28,9 +28,6 @@ namespace Net {
{
private:
/* reference MAC address */
static const Ethernet_frame::Mac_address _mac_addr_base;
/* limit available MAC addresses to one byte range */
enum { MSB_MAX = 0xFF };
@ -47,6 +44,9 @@ namespace Net {
class Alloc_failed : Genode::Exception {};
/* reference MAC address */
static Ethernet_frame::Mac_address mac_addr_base;
Mac_allocator() { Genode::memset(&_msbs, 0, sizeof(_msbs)); }
@ -61,7 +61,7 @@ namespace Net {
for (int i=0; i < MSB_MAX; i++) {
if (!_msbs[i].used) {
_msbs[i].used = 1;
Ethernet_frame::Mac_address mac = _mac_addr_base;
Ethernet_frame::Mac_address mac = mac_addr_base;
mac.addr[5] = i;
return mac;
}

View File

@ -17,6 +17,8 @@
#include <cap_session/connection.h>
#include <nic_session/connection.h>
#include <nic/packet_allocator.h>
#include <nic/xml_node.h>
#include <os/config.h>
#include "packet_handler.h"
#include "component.h"
@ -38,6 +40,14 @@ int main(int, char **)
TX_BUF_SIZE = Nic::Session::TX_QUEUE_SIZE * PACKET_SIZE
};
/* read MAC address prefix from config file */
try {
Nic::Mac_address mac;
Genode::config()->xml_node().attribute("mac").value(&mac);
Genode::memcpy(&Net::Mac_allocator::mac_addr_base, &mac,
sizeof(Net::Mac_allocator::mac_addr_base));
} catch(...) {}
Root_capability nic_root_cap;
try {
static Nic::Connection nic(&tx_block_alloc, TX_BUF_SIZE, RX_BUF_SIZE);