X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fnetdev-linux.c;h=26fb32d825c1819c845c1f9d18f7230c2b3fa09c;hb=fd76a6f94338b668175336434b156827458b5e7d;hp=d146ccfcfe090e8ccf097d9fd7310bb2ae50291d;hpb=38e0065b1f25615bf69cfdc000d17935f99c022b;p=sliver-openvswitch.git diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index d146ccfcf..26fb32d82 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -410,6 +410,9 @@ static int netdev_linux_get_ipv4(const struct netdev *, struct in_addr *, int cmd, const char *cmd_name); static int get_flags(const struct netdev *, unsigned int *flags); static int set_flags(const char *, unsigned int flags); +static int update_flags(struct netdev_linux *netdev, enum netdev_flags off, + enum netdev_flags on, enum netdev_flags *old_flagsp) + OVS_REQUIRES(netdev->mutex); static int do_get_ifindex(const char *netdev_name); static int get_ifindex(const struct netdev *, int *ifindexp); static int do_set_addr(struct netdev *netdev, @@ -616,7 +619,7 @@ netdev_linux_alloc(void) static void netdev_linux_common_construct(struct netdev_linux *netdev) { - ovs_mutex_init(&netdev->mutex, PTHREAD_MUTEX_NORMAL); + ovs_mutex_init(&netdev->mutex); netdev->change_seq = 1; } @@ -979,7 +982,7 @@ netdev_linux_set_etheraddr(struct netdev *netdev_, const uint8_t mac[ETH_ADDR_LEN]) { struct netdev_linux *netdev = netdev_linux_cast(netdev_); - struct netdev_saved_flags *sf = NULL; + enum netdev_flags old_flags = 0; int error; ovs_mutex_lock(&netdev->mutex); @@ -994,7 +997,7 @@ netdev_linux_set_etheraddr(struct netdev *netdev_, /* Tap devices must be brought down before setting the address. */ if (is_tap_netdev(netdev_)) { - netdev_turn_flags_off(netdev_, NETDEV_UP, &sf); + update_flags(netdev, NETDEV_UP, 0, &old_flags); } error = set_etheraddr(netdev_get_name(netdev_), mac); if (!error || error == ENODEV) { @@ -1005,7 +1008,9 @@ netdev_linux_set_etheraddr(struct netdev *netdev_, } } - netdev_restore_flags(sf); + if (is_tap_netdev(netdev_) && old_flags & NETDEV_UP) { + update_flags(netdev, 0, NETDEV_UP, &old_flags); + } exit: ovs_mutex_unlock(&netdev->mutex); @@ -1036,21 +1041,16 @@ netdev_linux_get_etheraddr(const struct netdev *netdev_, return error; } -/* Returns the maximum size of transmitted (and received) packets on 'netdev', - * in bytes, not including the hardware header; thus, this is typically 1500 - * bytes for Ethernet devices. */ static int -netdev_linux_get_mtu(const struct netdev *netdev_, int *mtup) +netdev_linux_get_mtu__(struct netdev_linux *netdev, int *mtup) { - struct netdev_linux *netdev = netdev_linux_cast(netdev_); int error; - ovs_mutex_lock(&netdev->mutex); if (!(netdev->cache_valid & VALID_MTU)) { struct ifreq ifr; netdev->netdev_mtu_error = af_inet_ifreq_ioctl( - netdev_get_name(netdev_), &ifr, SIOCGIFMTU, "SIOCGIFMTU"); + netdev_get_name(&netdev->up), &ifr, SIOCGIFMTU, "SIOCGIFMTU"); netdev->mtu = ifr.ifr_mtu; netdev->cache_valid |= VALID_MTU; } @@ -1059,6 +1059,21 @@ netdev_linux_get_mtu(const struct netdev *netdev_, int *mtup) if (!error) { *mtup = netdev->mtu; } + + return error; +} + +/* Returns the maximum size of transmitted (and received) packets on 'netdev', + * in bytes, not including the hardware header; thus, this is typically 1500 + * bytes for Ethernet devices. */ +static int +netdev_linux_get_mtu(const struct netdev *netdev_, int *mtup) +{ + struct netdev_linux *netdev = netdev_linux_cast(netdev_); + int error; + + ovs_mutex_lock(&netdev->mutex); + error = netdev_linux_get_mtu__(netdev, mtup); ovs_mutex_unlock(&netdev->mutex); return error; @@ -1557,7 +1572,6 @@ netdev_internal_set_stats(struct netdev *netdev, static void netdev_linux_read_features(struct netdev_linux *netdev) - OVS_REQUIRES(netdev->mutex) { struct ethtool_cmd ecmd; uint32_t speed; @@ -2086,35 +2100,35 @@ start_queue_dump(const struct netdev *netdev, struct nl_dump *dump) return true; } +struct netdev_linux_queue_state { + unsigned int *queues; + size_t cur_queue; + size_t n_queues; +}; + static int -netdev_linux_dump_queues(const struct netdev *netdev_, - netdev_dump_queues_cb *cb, void *aux) +netdev_linux_queue_dump_start(const struct netdev *netdev_, void **statep) { - struct netdev_linux *netdev = netdev_linux_cast(netdev_); + const struct netdev_linux *netdev = netdev_linux_cast(netdev_); int error; ovs_mutex_lock(&netdev->mutex); error = tc_query_qdisc(netdev_); if (!error) { if (netdev->tc->ops->class_get) { - struct tc_queue *queue, *next_queue; - struct smap details; - - smap_init(&details); - HMAP_FOR_EACH_SAFE (queue, next_queue, hmap_node, - &netdev->tc->queues) { - int retval; - - smap_clear(&details); - - retval = netdev->tc->ops->class_get(netdev_, queue, &details); - if (!retval) { - (*cb)(queue->queue_id, &details, aux); - } else { - error = retval; - } + struct netdev_linux_queue_state *state; + struct tc_queue *queue; + size_t i; + + *statep = state = xmalloc(sizeof *state); + state->n_queues = hmap_count(&netdev->tc->queues); + state->cur_queue = 0; + state->queues = xmalloc(state->n_queues * sizeof *state->queues); + + i = 0; + HMAP_FOR_EACH (queue, hmap_node, &netdev->tc->queues) { + state->queues[i++] = queue->queue_id; } - smap_destroy(&details); } else { error = EOPNOTSUPP; } @@ -2124,6 +2138,41 @@ netdev_linux_dump_queues(const struct netdev *netdev_, return error; } +static int +netdev_linux_queue_dump_next(const struct netdev *netdev_, void *state_, + unsigned int *queue_idp, struct smap *details) +{ + const struct netdev_linux *netdev = netdev_linux_cast(netdev_); + struct netdev_linux_queue_state *state = state_; + int error = EOF; + + ovs_mutex_lock(&netdev->mutex); + while (state->cur_queue < state->n_queues) { + unsigned int queue_id = state->queues[state->cur_queue++]; + struct tc_queue *queue = tc_find_queue(netdev_, queue_id); + + if (queue) { + *queue_idp = queue_id; + error = netdev->tc->ops->class_get(netdev_, queue, details); + break; + } + } + ovs_mutex_unlock(&netdev->mutex); + + return error; +} + +static int +netdev_linux_queue_dump_done(const struct netdev *netdev OVS_UNUSED, + void *state_) +{ + struct netdev_linux_queue_state *state = state_; + + free(state->queues); + free(state); + return 0; +} + static int netdev_linux_dump_queue_stats(const struct netdev *netdev_, netdev_dump_queue_stats_cb *cb, void *aux) @@ -2478,21 +2527,33 @@ iff_to_nd_flags(int iff) } static int -netdev_linux_update_flags(struct netdev *netdev_, enum netdev_flags off, - enum netdev_flags on, enum netdev_flags *old_flagsp) +update_flags(struct netdev_linux *netdev, enum netdev_flags off, + enum netdev_flags on, enum netdev_flags *old_flagsp) + OVS_REQUIRES(netdev->mutex) { - struct netdev_linux *netdev = netdev_linux_cast(netdev_); int old_flags, new_flags; int error = 0; - ovs_mutex_lock(&netdev->mutex); old_flags = netdev->ifi_flags; *old_flagsp = iff_to_nd_flags(old_flags); new_flags = (old_flags & ~nd_to_iff_flags(off)) | nd_to_iff_flags(on); if (new_flags != old_flags) { - error = set_flags(netdev_get_name(netdev_), new_flags); - get_flags(netdev_, &netdev->ifi_flags); + error = set_flags(netdev_get_name(&netdev->up), new_flags); + get_flags(&netdev->up, &netdev->ifi_flags); } + + return error; +} + +static int +netdev_linux_update_flags(struct netdev *netdev_, enum netdev_flags off, + enum netdev_flags on, enum netdev_flags *old_flagsp) +{ + struct netdev_linux *netdev = netdev_linux_cast(netdev_); + int error; + + ovs_mutex_lock(&netdev->mutex); + error = update_flags(netdev, off, on, old_flagsp); ovs_mutex_unlock(&netdev->mutex); return error; @@ -2554,7 +2615,9 @@ netdev_linux_change_seq(const struct netdev *netdev_) netdev_linux_set_queue, \ netdev_linux_delete_queue, \ netdev_linux_get_queue_stats, \ - netdev_linux_dump_queues, \ + netdev_linux_queue_dump_start, \ + netdev_linux_queue_dump_next, \ + netdev_linux_queue_dump_done, \ netdev_linux_dump_queue_stats, \ \ netdev_linux_get_in4, \ @@ -2690,7 +2753,7 @@ htb_setup_class__(struct netdev *netdev, unsigned int handle, int error; int mtu; - error = netdev_get_mtu(netdev, &mtu); + error = netdev_linux_get_mtu__(netdev_linux_cast(netdev), &mtu); if (error) { VLOG_WARN_RL(&rl, "cannot set up HTB on device %s that lacks MTU", netdev_get_name(netdev)); @@ -2786,9 +2849,10 @@ htb_parse_tcmsg__(struct ofpbuf *tcmsg, unsigned int *queue_id, } static void -htb_parse_qdisc_details__(struct netdev *netdev, +htb_parse_qdisc_details__(struct netdev *netdev_, const struct smap *details, struct htb_class *hc) { + struct netdev_linux *netdev = netdev_linux_cast(netdev_); const char *max_rate_s; max_rate_s = smap_get(details, "max-rate"); @@ -2796,7 +2860,8 @@ htb_parse_qdisc_details__(struct netdev *netdev, if (!hc->max_rate) { enum netdev_features current; - netdev_get_features(netdev, ¤t, NULL, NULL, NULL); + netdev_linux_read_features(netdev); + current = !netdev->get_features_error ? netdev->current : 0; hc->max_rate = netdev_features_to_bps(current, 100 * 1000 * 1000) / 8; } hc->min_rate = hc->max_rate; @@ -2815,7 +2880,7 @@ htb_parse_class_details__(struct netdev *netdev, const char *priority_s = smap_get(details, "priority"); int mtu, error; - error = netdev_get_mtu(netdev, &mtu); + error = netdev_linux_get_mtu__(netdev_linux_cast(netdev), &mtu); if (error) { VLOG_WARN_RL(&rl, "cannot parse HTB class on device %s that lacks MTU", netdev_get_name(netdev)); @@ -3263,9 +3328,10 @@ hfsc_query_class__(const struct netdev *netdev, unsigned int handle, } static void -hfsc_parse_qdisc_details__(struct netdev *netdev, const struct smap *details, +hfsc_parse_qdisc_details__(struct netdev *netdev_, const struct smap *details, struct hfsc_class *class) { + struct netdev_linux *netdev = netdev_linux_cast(netdev_); uint32_t max_rate; const char *max_rate_s; @@ -3275,7 +3341,8 @@ hfsc_parse_qdisc_details__(struct netdev *netdev, const struct smap *details, if (!max_rate) { enum netdev_features current; - netdev_get_features(netdev, ¤t, NULL, NULL, NULL); + netdev_linux_read_features(netdev); + current = !netdev->get_features_error ? netdev->current : 0; max_rate = netdev_features_to_bps(current, 100 * 1000 * 1000) / 8; }