new makefile target for error reporting
[sliver-openvswitch.git] / lib / netdev-linux.c
index e569750..2db56ac 100644 (file)
@@ -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,
@@ -513,9 +516,8 @@ netdev_linux_run(void)
                     ovs_mutex_lock(&netdev->mutex);
                     netdev_linux_update(netdev, &change);
                     ovs_mutex_unlock(&netdev->mutex);
-
-                    netdev_close(netdev_);
                 }
+                netdev_close(netdev_);
             }
         } else if (error == ENOBUFS) {
             struct shash device_shash;
@@ -980,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);
@@ -995,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) {
@@ -1006,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);
@@ -1037,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;
     }
@@ -1060,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;
@@ -1558,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;
@@ -2479,21 +2492,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;
@@ -2691,7 +2716,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));
@@ -2787,9 +2812,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");
@@ -2797,7 +2823,8 @@ htb_parse_qdisc_details__(struct netdev *netdev,
     if (!hc->max_rate) {
         enum netdev_features current;
 
-        netdev_get_features(netdev, &current, 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;
@@ -2816,7 +2843,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));
@@ -3264,9 +3291,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;
 
@@ -3276,7 +3304,8 @@ hfsc_parse_qdisc_details__(struct netdev *netdev, const struct smap *details,
     if (!max_rate) {
         enum netdev_features current;
 
-        netdev_get_features(netdev, &current, 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;
     }