X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fdevices%2Fvirtio%2Ftap.c;h=cc28df3be7f356b9a62bb4a4dbb2fce0edd17ec6;hb=91c6ef7cae2d20ca17a69003a44090614412c63f;hp=658ba6bfc682fc3fb0ba27ba8921996340969335;hpb=8389fb9112bcf96def69539fa1de13a7a08923f5;p=vpp.git diff --git a/src/vnet/devices/virtio/tap.c b/src/vnet/devices/virtio/tap.c index 658ba6bfc68..cc28df3be7f 100644 --- a/src/vnet/devices/virtio/tap.c +++ b/src/vnet/devices/virtio/tap.c @@ -31,6 +31,9 @@ #include #include #include +#include +#include +#include #include #include @@ -46,98 +49,23 @@ virtio_eth_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hi, u32 flags) { /* nothing for now */ + //TODO On MTU change call vnet_netlink_set_if_mtu return 0; } - -clib_error_t * -clib_netlink_set_if_attr (int ifindex, unsigned short rta_type, void *data, - int data_len) -{ - clib_error_t *err = 0; - int sock; - struct sockaddr_nl ra = { 0 }; - struct - { - struct nlmsghdr nh; - struct ifinfomsg ifmsg; - char attrbuf[512]; - } req; - struct rtattr *rta; - - memset (&req, 0, sizeof (req)); - if ((sock = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) - { - err = clib_error_return_unix (0, "socket(AF_NETLINK)"); - goto error; - } - - ra.nl_family = AF_NETLINK; - ra.nl_pid = getpid (); - - if ((bind (sock, (struct sockaddr *) &ra, sizeof (ra))) == -1) - return clib_error_return_unix (0, "bind"); - - req.nh.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifinfomsg)); - req.nh.nlmsg_flags = NLM_F_REQUEST; - req.nh.nlmsg_type = RTM_SETLINK; - req.ifmsg.ifi_family = AF_UNSPEC; - req.ifmsg.ifi_index = ifindex; - req.ifmsg.ifi_change = 0xffffffff; - rta = (struct rtattr *) (((char *) &req) + NLMSG_ALIGN (req.nh.nlmsg_len)); - rta->rta_type = rta_type; - rta->rta_len = RTA_LENGTH (data_len); - req.nh.nlmsg_len = NLMSG_ALIGN (req.nh.nlmsg_len) + RTA_LENGTH (data_len); - memcpy (RTA_DATA (rta), data, data_len); - - if ((send (sock, &req, req.nh.nlmsg_len, 0)) == -1) - err = clib_error_return_unix (0, "send"); - -error: - return err; -} - -clib_error_t * -clib_netlink_set_if_mtu (int ifindex, int mtu) -{ - clib_error_t *err; - - err = clib_netlink_set_if_attr (ifindex, IFLA_MTU, &mtu, sizeof (int)); - return err; -} - -clib_error_t * -clib_netlink_set_if_namespace (int ifindex, char *net_ns) -{ - clib_error_t *err; - int ns_fd; - u8 *s; - s = format (0, "/var/run/netns/%s%c", net_ns, 0); - ns_fd = open ((char *) s, O_RDONLY); - vec_free (s); - if (ns_fd == -1) - return clib_error_return (0, "namespace '%s' doesn't exist", net_ns); - - err = - clib_netlink_set_if_attr (ifindex, IFLA_NET_NS_FD, &ns_fd, sizeof (int)); - close (ns_fd); - return err; -} - -int +void tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) { vnet_main_t *vnm = vnet_get_main (); virtio_main_t *vim = &virtio_main; vnet_sw_interface_t *sw; vnet_hw_interface_t *hw; - int i; - clib_error_t *err = 0; + int i, fd; struct ifreq ifr; size_t hdrsz; struct vhost_memory *vhost_mem = 0; virtio_if_t *vif = 0; - int rv = 0; + clib_error_t *err = 0; memset (&ifr, 0, sizeof (ifr)); pool_get (vim->interfaces, vif); @@ -146,7 +74,8 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) if ((vif->fd = open ("/dev/vhost-net", O_RDWR | O_NONBLOCK)) < 0) { - rv = VNET_API_ERROR_SYSCALL_ERROR_1; + args->rv = VNET_API_ERROR_SYSCALL_ERROR_1; + args->error = clib_error_return_unix (0, "open '/dev/vhost-net'"); goto error; } @@ -154,19 +83,25 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) if ((vif->remote_features & (1ULL << VIRTIO_NET_F_MRG_RXBUF)) == 0) { - rv = VNET_API_ERROR_UNSUPPORTED; + args->rv = VNET_API_ERROR_UNSUPPORTED; + args->error = clib_error_return (0, "vhost-net backend doesn't support " + "VIRTIO_NET_F_MRG_RXBUF feature"); goto error; } if ((vif->remote_features & (1ULL << VIRTIO_RING_F_INDIRECT_DESC)) == 0) { - rv = VNET_API_ERROR_UNSUPPORTED; + args->rv = VNET_API_ERROR_UNSUPPORTED; + args->error = clib_error_return (0, "vhost-net backend doesn't support " + "VIRTIO_RING_F_INDIRECT_DESC feature"); goto error; } if ((vif->remote_features & (1ULL << VIRTIO_F_VERSION_1)) == 0) { - rv = VNET_API_ERROR_UNSUPPORTED; + args->rv = VNET_API_ERROR_UNSUPPORTED; + args->error = clib_error_return (0, "vhost-net backend doesn't support " + "VIRTIO_F_VERSION_1 features"); goto error; } @@ -178,12 +113,13 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) if ((vif->tap_fd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK)) < 0) { - rv = VNET_API_ERROR_SYSCALL_ERROR_2; + args->rv = VNET_API_ERROR_SYSCALL_ERROR_2; + args->error = clib_error_return_unix (0, "open '/dev/net/tun'"); goto error; } ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE | IFF_VNET_HDR; - strncpy (ifr.ifr_ifrn.ifrn_name, (char *) args->name, IF_NAMESIZE); + strncpy (ifr.ifr_ifrn.ifrn_name, (char *) args->name, IF_NAMESIZE - 1); _IOCTL (vif->tap_fd, TUNSETIFF, (void *) &ifr); vif->ifindex = if_nametoindex ((char *) args->name); @@ -194,13 +130,49 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) _IOCTL (vif->tap_fd, TUNSETVNETHDRSZ, &hdrsz); _IOCTL (vif->fd, VHOST_SET_OWNER, 0); - if (args->net_ns) + if (args->host_bridge) + { + int master_ifindex = if_nametoindex ((char *) args->host_bridge); + args->error = vnet_netlink_set_if_master (vif->ifindex, master_ifindex); + if (args->error) + { + args->rv = VNET_API_ERROR_NETLINK_ERROR; + goto error; + } + } + + if (args->host_namespace) + { + args->error = vnet_netlink_set_if_namespace (vif->ifindex, + (char *) + args->host_namespace); + if (args->error) + { + args->rv = VNET_API_ERROR_NETLINK_ERROR; + goto error; + } + } + + if (args->host_ip4_prefix_len) { - err = clib_netlink_set_if_namespace (vif->ifindex, - (char *) args->net_ns); - if (err) + args->error = vnet_netlink_add_ip4_addr (vif->ifindex, + &args->host_ip4_addr, + args->host_ip4_prefix_len); + if (args->error) { - rv = VNET_API_ERROR_NAMESPACE_CREATE; + args->rv = VNET_API_ERROR_NETLINK_ERROR; + goto error; + } + } + + if (args->host_ip6_prefix_len) + { + args->error = vnet_netlink_add_ip6_addr (vif->ifindex, + &args->host_ip6_addr, + args->host_ip6_prefix_len); + if (args->error) + { + args->rv = VNET_API_ERROR_NETLINK_ERROR; goto error; } } @@ -213,18 +185,29 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) vhost_mem->regions[0].memory_size = (1ULL << 47) - 4096; _IOCTL (vif->fd, VHOST_SET_MEM_TABLE, vhost_mem); - if ((err = virtio_vring_init (vm, vif, 0, args->rx_ring_sz))) + if ((args->error = virtio_vring_init (vm, vif, 0, args->rx_ring_sz))) { - rv = VNET_API_ERROR_VIRTIO_INIT; + args->rv = VNET_API_ERROR_INIT_FAILED; goto error; } - if ((err = virtio_vring_init (vm, vif, 1, args->tx_ring_sz))) + if ((args->error = virtio_vring_init (vm, vif, 1, args->tx_ring_sz))) { - rv = VNET_API_ERROR_VIRTIO_INIT; + args->rv = VNET_API_ERROR_INIT_FAILED; goto error; } + /* set host side up */ + if ((fd = socket (AF_INET, SOCK_STREAM, 0)) > 0) + { + memset (&ifr, 0, sizeof (struct ifreq)); + strncpy (ifr.ifr_name, (char *) args->name, sizeof (ifr.ifr_name) - 1); + _IOCTL (fd, SIOCGIFFLAGS, (void *) &ifr); + ifr.ifr_flags |= IFF_UP | IFF_RUNNING; + _IOCTL (fd, SIOCSIFFLAGS, (void *) &ifr); + close (fd); + } + if (!args->hw_addr_set) { f64 now = vlib_time_now (vm); @@ -238,14 +221,17 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) } vif->name = args->name; args->name = 0; - vif->net_ns = args->net_ns; - args->net_ns = 0; - err = ethernet_register_interface (vnm, virtio_device_class.index, - vif->dev_instance, args->hw_addr, - &vif->hw_if_index, - virtio_eth_flag_change); - if (err) - rv = VNET_API_ERROR_INVALID_REGISTRATION; + vif->net_ns = args->host_namespace; + args->host_namespace = 0; + args->error = ethernet_register_interface (vnm, virtio_device_class.index, + vif->dev_instance, args->hw_addr, + &vif->hw_if_index, + virtio_eth_flag_change); + if (args->error) + { + args->rv = VNET_API_ERROR_INVALID_REGISTRATION; + goto error; + } sw = vnet_get_hw_sw_interface (vnm, vif->hw_if_index); vif->sw_if_index = sw->sw_if_index; @@ -265,6 +251,12 @@ tap_create_if (vlib_main_t * vm, tap_create_if_args_t * args) goto done; error: + if (err) + { + ASSERT (args->error == 0); + args->error = err; + args->rv = VNET_API_ERROR_SYSCALL_ERROR_3; + } if (vif->tap_fd != -1) close (vif->tap_fd); if (vif->fd != -1) @@ -276,8 +268,6 @@ error: done: if (vhost_mem) clib_mem_free (vhost_mem); - - return rv; } int