diff --git a/net/native-stack.cc b/net/native-stack.cc index 4a9411d463..54b60d211e 100644 --- a/net/native-stack.cc +++ b/net/native-stack.cc @@ -9,9 +9,17 @@ #include "tcp-stack.hh" #include "udp.hh" #include "virtio.hh" +#include "xenfront.hh" #include "proxy.hh" #include #include +#ifdef HAVE_OSV +#include +#include +#endif +#include +#include +#include namespace net { @@ -37,8 +45,59 @@ native_network_stack::make_udp_channel(ipv4_addr addr) { return _udp.make_channel(addr); } +enum class xen_info { + nonxen = 0, + userspace = 1, + osv = 2, +}; + +static xen_info is_xen() +{ + struct stat buf; + if (!stat("/proc/xen", &buf) || !stat("/dev/xen", &buf)) { + return xen_info::userspace; + } + +#ifdef HAVE_OSV + const char *str = gnu_get_libc_release(); + if (std::string("OSv") != str) { + return xen_info::nonxen; + } + auto firmware = osv::firmware_vendor(); + if (firmware == "Xen") { + return xen_info::osv; + } +#endif + + return xen_info::nonxen; +} + +std::unique_ptr create_native_net_device(boost::program_options::variables_map opts) { + + if (!smp::main_thread()) { + return create_proxy_net_device(opts); + } + + auto xen = is_xen(); + if (xen == xen_info::nonxen) { + return create_virtio_net_device(opts["tap-device"].as(), opts); + } + return create_xenfront_net_device(opts, xen == xen_info::userspace); +} + +void +add_native_net_options_description(boost::program_options::options_description &opts) { + + auto xen = is_xen(); + if (xen != xen_info::nonxen) { + opts.add(get_xenfront_net_options_description()); + } else { + opts.add(get_virtio_net_options_description()); + } +} + native_network_stack::native_network_stack(boost::program_options::variables_map opts) - : _netif(smp::main_thread() ? create_virtio_net_device(opts["tap-device"].as(), opts) : create_proxy_net_device(opts)) + : _netif(create_native_net_device(opts)) , _inet(&_netif) , _udp(_inet) { _inet.set_host_address(ipv4_address(opts["host-ipv4-addr"].as())); @@ -75,7 +134,8 @@ boost::program_options::options_description nns_options() { boost::program_options::value()->default_value(udp_v4::default_queue_size), "Default size of the UDPv4 per-channel packet queue") ; - opts.add(get_virtio_net_options_description()); + + add_native_net_options_description(opts); return opts; }