On Wed, May 30, 2018 at 7:10 PM, Daniel J Williams <[email protected]>
wrote:
>
> >Can we use netdev struct to replace the index? Because the net device
> >may have different parameters, not merely index.
>
> We have a solo5_net_info structure, which has mtu and mac address at the
> moment and would likely need to grow at least to cover index. The
> solo5_net_info call would also need to be updated to return info on the
> particular device (although perhaps we should think about having some of
> that in the start_info).
>
> >>> The only risk is breaking the solo5 interface currently used by
> >>> mirage and includeos.
>
> Are there examples of MirageOS unikernels that use two NICs on Xen or
> Unix? That might be a starting point for understanding how the upper
> layers use multiple devices. It sounds like there are already lots of
> examples of IncludeOS using multiple NICs, maybe a pointer to some of the
> relevant code will be helpful.
>
*IncludeOS notes below:*
IncludeOS has vm.json file inside each service which parsed and fed to qemu
and ukvm(recently added). For supporting multiple NICs, this is the
configuration.
{
"image": "test_router.img",
"mem" : 320,
"net" : [{"device" : "virtio"},
{"device" : "virtio"}],
}
Which gets translated to 2 network devices in qemu:
sudo --preserve-env qemu-system-x86_64 -kernel
/Users/nikhil/includeos//includeos/chainloader -append "" -initrd
test_router "" -device virtio-net,netdev=net0 -netdev tap,id=net0, -device
virtio-net,netdev=net1 -netdev tap,id=net1, -m 320 -nographic
In the application, this is how the inet stacks are created on top of nic.
Note that IncludeOS uses an instance of inet/network stack per nic. Hence
if there are more NICs, there are multiple instances of inet/network stack
In test/net/integration/router we have this
auto& inet = Inet::stack<0>();
inet.network_config({ 10, 0, 0, 42 }, // IP
{ 255, 255, 0, 0 }, // Netmask
{ 10, 0, 0, 1 } ); // Gateway
auto& inet2 = Inet::stack<1>();
inet2.network_config({ 10, 42, 42, 43 }, // IP
{ 255, 255, 255, 0 }, // Netmask
{ 10, 42, 42, 2 } ); // Gateway
They pass an integer, 0, 1 as per nic index.
This eventually is called:
// create network stack
auto& nic = hw::Devices::get<hw::Nic>(N);
return inet().create(nic, N, 0);
This is what the solo5 network driver class looks like and it is has single
mac address: Essentially, this is the NIC class
class Solo5Net : public net::Link_layer<net::Ethernet> {
private:
MAC::Addr mac_addr;
}
This is its constructor:
(Note: *It uses the older solo5 API*)
Solo5Net::Solo5Net()
: Link(Link_protocol{{this, &Solo5Net::transmit}, mac()}, bufstore_),
packets_rx_{Statman::get().create(Stat::UINT64, device_name() +
".packets_rx").get_uint64()},
packets_tx_{Statman::get().create(Stat::UINT64, device_name() +
".packets_tx").get_uint64()},
bufstore_{NUM_BUFFERS, 2048u} // don't change this
{
INFO("Solo5Net", "Driver initializing");
mac_addr = MAC::Addr(*solo5_net_mac_str*());
}
With the updated solo5 API, this is what it might look like:
Solo5Net::Solo5Net()
: Link(Link_protocol{{this, &Solo5Net::transmit}, mac()}, bufstore_),
packets_rx_{Statman::get().create(Stat::UINT64, device_name() +
".packets_rx").get_uint64()},
packets_tx_{Statman::get().create(Stat::UINT64, device_name() +
".packets_tx").get_uint64()},
bufstore_{NUM_BUFFERS, 2048u} // don't change this
{
uint8_t macaddr[6];
INFO("Solo5Net", "Driver initializing");
struct solo5_net_info ni;
solo5_net_info(&ni);
memcpy(macaddr, ni.mac_address, sizeof macaddr);
char macaddr_s[(sizeof macaddr * 2) + 1];
tohexs(macaddr_s, macaddr, sizeof macaddr);
mac_addr = MAC::Addr(macaddr_s);
}
We can use solo5_app_main to specify the number of indices.
solo5_net_info, read and write APIs can be extended to pass the NIC
index.
> Thanks,
> Dan
>
>
>
--
Regards,
Nikhil