On Wed, May 30, 2018 at 7:10 PM, Daniel J Williams <djwil...@us.ibm.com> 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