X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fnetdev-linux.c;h=611b86dd35273ea3c8bc3d2fbb701c74c658591a;hb=1e3f34c7693bcabae8e443ac1b246680ef9b60e2;hp=61363c6383b0da07aadf9bbf6bb47f2e6f1aa829;hpb=79f1cbe9f86ddfb1b5d92b80d85e09cd44768d6c;p=sliver-openvswitch.git diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index 61363c638..611b86dd3 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -69,6 +69,7 @@ #include "sset.h" #include "timer.h" #include "vlog.h" +#include "tunalloc.h" VLOG_DEFINE_THIS_MODULE(netdev_linux); @@ -77,7 +78,8 @@ COVERAGE_DEFINE(netdev_arp_lookup); COVERAGE_DEFINE(netdev_get_ifindex); COVERAGE_DEFINE(netdev_get_hwaddr); COVERAGE_DEFINE(netdev_set_hwaddr); -COVERAGE_DEFINE(netdev_ethtool); +COVERAGE_DEFINE(netdev_get_ethtool); +COVERAGE_DEFINE(netdev_set_ethtool); /* These were introduced in Linux 2.6.14, so they might be missing if we have @@ -506,6 +508,7 @@ netdev_linux_get_drvinfo(struct netdev_dev_linux *netdev_dev) return 0; } + COVERAGE_INC(netdev_get_ethtool); memset(&netdev_dev->drvinfo, 0, sizeof netdev_dev->drvinfo); error = netdev_linux_do_ethtool(netdev_dev->netdev_dev.name, (struct ethtool_cmd *)&netdev_dev->drvinfo, @@ -730,7 +733,7 @@ netdev_linux_destroy(struct netdev_dev *netdev_dev_) netdev_dev->tc->ops->tc_destroy(netdev_dev->tc); } - if (class == &netdev_tap_class) { + if (class == &netdev_tap_class || class == &netdev_tap_pl_class) { destroy_tap(netdev_dev); } free(netdev_dev); @@ -766,7 +769,7 @@ netdev_linux_open(struct netdev_dev *netdev_dev_, struct netdev **netdevp) } } - if (!strcmp(netdev_dev_get_type(netdev_dev_), "tap") && + if (!strncmp(netdev_dev_get_type(netdev_dev_), "tap", 3) && !netdev_dev->state.tap.opened) { /* We assume that the first user of the tap device is the primary user @@ -791,7 +794,7 @@ netdev_linux_close(struct netdev *netdev_) { struct netdev_linux *netdev = netdev_linux_cast(netdev_); - if (netdev->fd > 0 && strcmp(netdev_get_type(netdev_), "tap")) { + if (netdev->fd > 0 && strncmp(netdev_get_type(netdev_), "tap", 3)) { close(netdev->fd); } free(netdev); @@ -865,7 +868,8 @@ netdev_linux_recv(struct netdev *netdev_, void *data, size_t size) for (;;) { ssize_t retval; - retval = (netdev_->netdev_dev->netdev_class == &netdev_tap_class + retval = ((netdev_->netdev_dev->netdev_class == &netdev_tap_class || + netdev_->netdev_dev->netdev_class == &netdev_tap_pl_class) ? read(netdev->fd, data, size) : recv(netdev->fd, data, size, MSG_TRUNC)); if (retval >= 0) { @@ -898,7 +902,7 @@ netdev_linux_drain(struct netdev *netdev_) struct netdev_linux *netdev = netdev_linux_cast(netdev_); if (netdev->fd < 0) { return 0; - } else if (!strcmp(netdev_get_type(netdev_), "tap")) { + } else if (!strncmp(netdev_get_type(netdev_), "tap", 3)) { struct ifreq ifr; int error = netdev_linux_do_ioctl(netdev_get_name(netdev_), &ifr, SIOCGIFTXQLEN, "SIOCGIFTXQLEN"); @@ -953,7 +957,7 @@ netdev_linux_send(struct netdev *netdev_, const void *data, size_t size) sll.sll_family = AF_PACKET; sll.sll_ifindex = ifindex; - iov.iov_base = (void *) data; + iov.iov_base = CONST_CAST(void *, data); iov.iov_len = size; msg.msg_name = &sll; @@ -1009,7 +1013,7 @@ netdev_linux_send_wait(struct netdev *netdev_) struct netdev_linux *netdev = netdev_linux_cast(netdev_); if (netdev->fd < 0) { /* Nothing to do. */ - } else if (strcmp(netdev_get_type(netdev_), "tap")) { + } else if (strncmp(netdev_get_type(netdev_), "tap", 3)) { poll_fd_wait(netdev->fd, POLLOUT); } else { /* TAP device always accepts packets.*/ @@ -1203,6 +1207,7 @@ netdev_linux_get_miimon(const char *name, bool *miimon) VLOG_DBG_RL(&rl, "%s: failed to query MII, falling back to ethtool", name); + COVERAGE_INC(netdev_get_ethtool); memset(&ecmd, 0, sizeof ecmd); error = netdev_linux_do_ethtool(name, &ecmd, ETHTOOL_GLINK, "ETHTOOL_GLINK"); @@ -1496,6 +1501,7 @@ netdev_linux_read_features(struct netdev_dev_linux *netdev_dev) return; } + COVERAGE_INC(netdev_get_ethtool); memset(&ecmd, 0, sizeof ecmd); error = netdev_linux_do_ethtool(netdev_dev->netdev_dev.name, &ecmd, ETHTOOL_GSET, "ETHTOOL_GSET"); @@ -1652,6 +1658,7 @@ netdev_linux_set_advertisements(struct netdev *netdev, struct ethtool_cmd ecmd; int error; + COVERAGE_INC(netdev_get_ethtool); memset(&ecmd, 0, sizeof ecmd); error = netdev_linux_do_ethtool(netdev_get_name(netdev), &ecmd, ETHTOOL_GSET, "ETHTOOL_GSET"); @@ -1696,6 +1703,7 @@ netdev_linux_set_advertisements(struct netdev *netdev, if (advertise & NETDEV_F_PAUSE_ASYM) { ecmd.advertising |= ADVERTISED_Asym_Pause; } + COVERAGE_INC(netdev_set_ethtool); return netdev_linux_do_ethtool(netdev_get_name(netdev), &ecmd, ETHTOOL_SSET, "ETHTOOL_SSET"); } @@ -1780,6 +1788,51 @@ netdev_linux_get_qos_types(const struct netdev *netdev OVS_UNUSED, return 0; } +static int +netdev_linux_create_tap_pl(const struct netdev_class *class OVS_UNUSED, + const char *name, struct netdev_dev **netdev_devp) +{ + struct netdev_dev_linux *netdev_dev; + struct tap_state *state; + char real_name[IFNAMSIZ]; + int error; + + netdev_dev = xzalloc(sizeof *netdev_dev); + state = &netdev_dev->state.tap; + + error = cache_notifier_ref(); + if (error) { + goto error; + } + + /* Open tap device. */ + state->fd = tun_alloc(IFF_TAP, real_name); + if (state->fd < 0) { + error = errno; + VLOG_WARN("tun_alloc(IFF_TAP, %s) failed: %s", name, strerror(error)); + goto error_unref_notifier; + } + if (strcmp(name, real_name)) { + VLOG_WARN("tap_pl: requested %s, created %s", name, real_name); + } + + /* Make non-blocking. */ + error = set_nonblocking(state->fd); + if (error) { + goto error_unref_notifier; + } + + netdev_dev_init(&netdev_dev->netdev_dev, name, &netdev_tap_pl_class); + *netdev_devp = &netdev_dev->netdev_dev; + return 0; + +error_unref_notifier: + cache_notifier_unref(); +error: + free(netdev_dev); + return error; +} + static const struct tc_ops * tc_lookup_ovs_name(const char *name) { @@ -2371,6 +2424,13 @@ netdev_linux_update_flags(struct netdev *netdev, enum netdev_flags off, return error; } +static int +netdev_tap_pl_update_flags(struct netdev *netdev, enum netdev_flags off, + enum netdev_flags on, enum netdev_flags *old_flagsp) +{ + return 0; +} + static unsigned int netdev_linux_change_seq(const struct netdev *netdev) { @@ -2378,7 +2438,8 @@ netdev_linux_change_seq(const struct netdev *netdev) } #define NETDEV_LINUX_CLASS(NAME, CREATE, GET_STATS, SET_STATS, \ - GET_FEATURES, GET_STATUS) \ + GET_FEATURES, GET_STATUS, \ + UPDATE_FLAGS) \ { \ NAME, \ \ @@ -2436,7 +2497,7 @@ netdev_linux_change_seq(const struct netdev *netdev) GET_STATUS, \ netdev_linux_arp_lookup, \ \ - netdev_linux_update_flags, \ + UPDATE_FLAGS, \ \ netdev_linux_change_seq \ } @@ -2448,7 +2509,8 @@ const struct netdev_class netdev_linux_class = netdev_linux_get_stats, NULL, /* set_stats */ netdev_linux_get_features, - netdev_linux_get_drv_info); + netdev_linux_get_drv_info, + netdev_linux_update_flags); const struct netdev_class netdev_tap_class = NETDEV_LINUX_CLASS( @@ -2457,7 +2519,8 @@ const struct netdev_class netdev_tap_class = netdev_tap_get_stats, NULL, /* set_stats */ netdev_linux_get_features, - netdev_linux_get_drv_info); + netdev_linux_get_drv_info, + netdev_linux_update_flags); const struct netdev_class netdev_internal_class = NETDEV_LINUX_CLASS( @@ -2466,7 +2529,18 @@ const struct netdev_class netdev_internal_class = netdev_internal_get_stats, netdev_vport_set_stats, NULL, /* get_features */ - netdev_internal_get_drv_info); + netdev_internal_get_drv_info, + netdev_linux_update_flags); + +const struct netdev_class netdev_tap_pl_class = + NETDEV_LINUX_CLASS( + "tap_pl", + netdev_linux_create_tap_pl, + netdev_tap_get_stats, + NULL, /* set_stats */ + netdev_linux_get_features, + netdev_linux_get_drv_info, + netdev_tap_pl_update_flags); /* HTB traffic control class. */ @@ -4100,7 +4174,7 @@ tc_query_qdisc(const struct netdev *netdev) } /* Instantiate it. */ - load_error = ops->tc_load((struct netdev *) netdev, qdisc); + load_error = ops->tc_load(CONST_CAST(struct netdev *, netdev), qdisc); assert((load_error == 0) == (netdev_dev->tc != NULL)); ofpbuf_delete(qdisc); @@ -4197,6 +4271,7 @@ netdev_linux_ethtool_set_flag(struct netdev *netdev, uint32_t flag, uint32_t new_flags; int error; + COVERAGE_INC(netdev_get_ethtool); memset(&evalue, 0, sizeof evalue); error = netdev_linux_do_ethtool(netdev_name, (struct ethtool_cmd *)&evalue, @@ -4205,6 +4280,7 @@ netdev_linux_ethtool_set_flag(struct netdev *netdev, uint32_t flag, return error; } + COVERAGE_INC(netdev_set_ethtool); evalue.data = new_flags = (evalue.data & ~flag) | (enable ? flag : 0); error = netdev_linux_do_ethtool(netdev_name, (struct ethtool_cmd *)&evalue, @@ -4213,6 +4289,7 @@ netdev_linux_ethtool_set_flag(struct netdev *netdev, uint32_t flag, return error; } + COVERAGE_INC(netdev_get_ethtool); memset(&evalue, 0, sizeof evalue); error = netdev_linux_do_ethtool(netdev_name, (struct ethtool_cmd *)&evalue, @@ -4488,7 +4565,6 @@ netdev_linux_do_ethtool(const char *name, struct ethtool_cmd *ecmd, ifr.ifr_data = (caddr_t) ecmd; ecmd->cmd = cmd; - COVERAGE_INC(netdev_ethtool); if (ioctl(af_inet_sock, SIOCETHTOOL, &ifr) == 0) { return 0; } else {