Merge commit '4b60911067a82fbdfa87b7c2824412da20287ed8'
authorGiuseppe Lettieri <g.lettieri@iet.unipi.it>
Fri, 5 Jul 2013 17:37:07 +0000 (19:37 +0200)
committerGiuseppe Lettieri <g.lettieri@iet.unipi.it>
Fri, 5 Jul 2013 17:37:07 +0000 (19:37 +0200)
1  2 
lib/automake.mk
lib/dpif-netdev.c
lib/netdev-provider.h
lib/netdev.c

diff --combined lib/automake.mk
@@@ -12,6 -12,8 +12,8 @@@ lib_libopenvswitch_a_SOURCES = 
        lib/aes128.h \
        lib/backtrace.c \
        lib/backtrace.h \
+       lib/bfd.c \
+       lib/bfd.h \
        lib/bitmap.c \
        lib/bitmap.h \
        lib/bond.c \
@@@ -88,8 -90,6 +90,8 @@@
        lib/multipath.c \
        lib/multipath.h \
        lib/netdev-dummy.c \
 +      lib/netdev-tunnel.c \
 +      lib/netdev-pltap.c \
        lib/netdev-provider.h \
        lib/netdev-vport.c \
        lib/netdev-vport.h \
        lib/timeval.h \
        lib/token-bucket.c \
        lib/token-bucket.h \
 +      lib/tunalloc.c \
 +      lib/tunalloc.h \
        lib/type-props.h \
        lib/unaligned.h \
        lib/unicode.c \
diff --combined lib/dpif-netdev.c
@@@ -106,6 -106,7 +106,7 @@@ struct dp_netdev_port 
      int port_no;                /* Index into dp_netdev's 'ports'. */
      struct list node;           /* Element in dp_netdev's 'port_list'. */
      struct netdev *netdev;
+     struct netdev_saved_flags *sf;
      char *type;                 /* Port type as requested by user. */
  };
  
@@@ -187,17 -188,10 +188,17 @@@ dpif_netdev_class_is_dummy(const struc
      return class != &dpif_netdev_class;
  }
  
 +static bool
 +dpif_netdev_class_is_planetlab(const struct dpif_class *class)
 +{
 +    return class == &dpif_planetlab_class;
 +}
 +
  static const char *
  dpif_netdev_port_open_type(const struct dpif_class *class, const char *type)
  {
      return strcmp(type, "internal") ? type
 +                  : dpif_netdev_class_is_planetlab(class) ? "pltap"
                    : dpif_netdev_class_is_dummy(class) ? "dummy"
                    : "tap";
  }
@@@ -223,8 -217,7 +224,8 @@@ choose_port(struct dp_netdev *dp, cons
  {
      int port_no;
  
 -    if (dp->class != &dpif_netdev_class) {
 +    if (dp->class != &dpif_netdev_class && 
 +        dp->class != &dpif_planetlab_class) {
          const char *p;
          int start_no = 0;
  
@@@ -382,6 -375,7 +383,7 @@@ static in
  do_add_port(struct dp_netdev *dp, const char *devname, const char *type,
              uint32_t port_no)
  {
+     struct netdev_saved_flags *sf;
      struct dp_netdev_port *port;
      struct netdev *netdev;
      const char *open_type;
          return error;
      }
  
-     error = netdev_turn_flags_on(netdev, NETDEV_PROMISC, false);
+     error = netdev_turn_flags_on(netdev, NETDEV_PROMISC, &sf);
      if (error) {
          netdev_close(netdev);
          return error;
      port = xmalloc(sizeof *port);
      port->port_no = port_no;
      port->netdev = netdev;
+     port->sf = sf;
      port->type = xstrdup(type);
  
      error = netdev_get_mtu(netdev, &mtu);
@@@ -513,6 -508,7 +516,7 @@@ do_del_port(struct dp_netdev *dp, uint3
      dp->serial++;
  
      netdev_close(port->netdev);
+     netdev_restore_flags(port->sf);
      free(port->type);
      free(port);
  
@@@ -1323,49 -1319,41 +1327,49 @@@ dp_netdev_execute_actions(struct dp_net
      }
  }
  
 +#define DPIF_NETDEV_CLASS_FUNCTIONS                   \
 +    dpif_netdev_enumerate,                            \
 +    dpif_netdev_port_open_type,                               \
 +    dpif_netdev_open,                                 \
 +    dpif_netdev_close,                                        \
 +    dpif_netdev_destroy,                              \
 +    dpif_netdev_run,                                  \
 +    dpif_netdev_wait,                                 \
 +    dpif_netdev_get_stats,                            \
 +    dpif_netdev_port_add,                             \
 +    dpif_netdev_port_del,                             \
 +    dpif_netdev_port_query_by_number,                 \
 +    dpif_netdev_port_query_by_name,                   \
 +    dpif_netdev_get_max_ports,                                \
 +    NULL,                       /* port_get_pid */    \
 +    dpif_netdev_port_dump_start,                      \
 +    dpif_netdev_port_dump_next,                               \
 +    dpif_netdev_port_dump_done,                               \
 +    dpif_netdev_port_poll,                            \
 +    dpif_netdev_port_poll_wait,                               \
 +    dpif_netdev_flow_get,                             \
 +    dpif_netdev_flow_put,                             \
 +    dpif_netdev_flow_del,                             \
 +    dpif_netdev_flow_flush,                           \
 +    dpif_netdev_flow_dump_start,                      \
 +    dpif_netdev_flow_dump_next,                               \
 +    dpif_netdev_flow_dump_done,                               \
 +    dpif_netdev_execute,                              \
 +    NULL,                       /* operate */         \
 +    dpif_netdev_recv_set,                             \
 +    dpif_netdev_queue_to_priority,                    \
 +    dpif_netdev_recv,                                 \
 +    dpif_netdev_recv_wait,                            \
 +    dpif_netdev_recv_purge,                           \
 +
  const struct dpif_class dpif_netdev_class = {
      "netdev",
 -    dpif_netdev_enumerate,
 -    dpif_netdev_port_open_type,
 -    dpif_netdev_open,
 -    dpif_netdev_close,
 -    dpif_netdev_destroy,
 -    dpif_netdev_run,
 -    dpif_netdev_wait,
 -    dpif_netdev_get_stats,
 -    dpif_netdev_port_add,
 -    dpif_netdev_port_del,
 -    dpif_netdev_port_query_by_number,
 -    dpif_netdev_port_query_by_name,
 -    dpif_netdev_get_max_ports,
 -    NULL,                       /* port_get_pid */
 -    dpif_netdev_port_dump_start,
 -    dpif_netdev_port_dump_next,
 -    dpif_netdev_port_dump_done,
 -    dpif_netdev_port_poll,
 -    dpif_netdev_port_poll_wait,
 -    dpif_netdev_flow_get,
 -    dpif_netdev_flow_put,
 -    dpif_netdev_flow_del,
 -    dpif_netdev_flow_flush,
 -    dpif_netdev_flow_dump_start,
 -    dpif_netdev_flow_dump_next,
 -    dpif_netdev_flow_dump_done,
 -    dpif_netdev_execute,
 -    NULL,                       /* operate */
 -    dpif_netdev_recv_set,
 -    dpif_netdev_queue_to_priority,
 -    dpif_netdev_recv,
 -    dpif_netdev_recv_wait,
 -    dpif_netdev_recv_purge,
 +    DPIF_NETDEV_CLASS_FUNCTIONS
 +};
 +
 +const struct dpif_class dpif_planetlab_class = {
 +    "planetlab",
 +    DPIF_NETDEV_CLASS_FUNCTIONS
  };
  
  static void
@@@ -1398,4 -1386,3 +1402,4 @@@ dpif_dummy_register(bool override
  
      dpif_dummy_register__("dummy");
  }
 +
diff --combined lib/netdev-provider.h
@@@ -38,6 -38,7 +38,7 @@@ struct netdev_dev 
                                                  this device. */
      int ref_cnt;                        /* Times this devices was opened. */
      struct shash_node *node;            /* Pointer to element in global map. */
+     struct list saved_flags_list; /* Contains "struct netdev_saved_flags". */
  };
  
  void netdev_dev_init(struct netdev_dev *, const char *name,
@@@ -63,9 -64,6 +64,6 @@@ static inline void netdev_dev_assert_cl
  struct netdev {
      struct netdev_dev *netdev_dev;   /* Parent netdev_dev. */
      struct list node;                /* Element in global list. */
-     enum netdev_flags save_flags;    /* Initial device flags. */
-     enum netdev_flags changed_flags; /* Flags that we changed. */
  };
  
  void netdev_init(struct netdev *, struct netdev_dev *);
@@@ -572,14 -570,14 +570,14 @@@ struct netdev_class 
      int (*arp_lookup)(const struct netdev *netdev, ovs_be32 ip,
                        uint8_t mac[6]);
  
-     /* Retrieves the current set of flags on 'netdev' into '*old_flags'.
-      * Then, turns off the flags that are set to 1 in 'off' and turns on the
-      * flags that are set to 1 in 'on'.  (No bit will be set to 1 in both 'off'
-      * and 'on'; that is, off & on == 0.)
+     /* Retrieves the current set of flags on 'dev' into '*old_flags'.  Then,
+      * turns off the flags that are set to 1 in 'off' and turns on the flags
+      * that are set to 1 in 'on'.  (No bit will be set to 1 in both 'off' and
+      * 'on'; that is, off & on == 0.)
       *
       * This function may be invoked from a signal handler.  Therefore, it
       * should not do anything that is not signal-safe (such as logging). */
-     int (*update_flags)(struct netdev *netdev, enum netdev_flags off,
+     int (*update_flags)(struct netdev_dev *dev, enum netdev_flags off,
                          enum netdev_flags on, enum netdev_flags *old_flags);
  
      /* Returns a sequence number which indicates changes in one of 'netdev''s
@@@ -605,9 -603,6 +603,9 @@@ extern const struct netdev_class netdev
  extern const struct netdev_class netdev_bsd_class;
  #endif
  
 +extern const struct netdev_class netdev_tunnel_class;
 +extern const struct netdev_class netdev_pltap_class;
 +
  #ifdef  __cplusplus
  }
  #endif
diff --combined lib/netdev.c
@@@ -48,6 -48,13 +48,13 @@@ COVERAGE_DEFINE(netdev_sent)
  COVERAGE_DEFINE(netdev_add_router);
  COVERAGE_DEFINE(netdev_get_stats);
  
+ struct netdev_saved_flags {
+     struct netdev_dev *dev;
+     struct list node;           /* In struct netdev_dev's saved_flags_list. */
+     enum netdev_flags saved_flags;
+     enum netdev_flags saved_values;
+ };
  static struct shash netdev_classes = SHASH_INITIALIZER(&netdev_classes);
  
  /* All created network devices. */
@@@ -60,8 -67,7 +67,7 @@@ static struct list netdev_list = LIST_I
   * additional log messages. */
  static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
  
- static void close_all_netdevs(void *aux OVS_UNUSED);
- static int restore_flags(struct netdev *netdev);
+ static void restore_all_flags(void *aux OVS_UNUSED);
  void update_device_args(struct netdev_dev *, const struct shash *args);
  
  static void
@@@ -72,7 -78,7 +78,7 @@@ netdev_initialize(void
      if (!inited) {
          inited = true;
  
-         fatal_signal_add_hook(close_all_netdevs, NULL, NULL, true);
+         fatal_signal_add_hook(restore_all_flags, NULL, NULL, true);
          netdev_vport_patch_register();
  
  #ifdef LINUX_DATAPATH
@@@ -85,8 -91,6 +91,8 @@@
          netdev_register_provider(&netdev_tap_class);
          netdev_register_provider(&netdev_bsd_class);
  #endif
 +      netdev_register_provider(&netdev_tunnel_class);
 +      netdev_register_provider(&netdev_pltap_class);
      }
  }
  
@@@ -304,21 -308,24 +310,24 @@@ netdev_get_tunnel_config(const struct n
      }
  }
  
+ static void
+ netdev_dev_unref(struct netdev_dev *dev)
+ {
+     ovs_assert(dev->ref_cnt);
+     if (!--dev->ref_cnt) {
+         netdev_dev_uninit(dev, true);
+     }
+ }
  /* Closes and destroys 'netdev'. */
  void
  netdev_close(struct netdev *netdev)
  {
      if (netdev) {
-         struct netdev_dev *netdev_dev = netdev_get_dev(netdev);
+         struct netdev_dev *dev = netdev_get_dev(netdev);
  
-         ovs_assert(netdev_dev->ref_cnt);
-         netdev_dev->ref_cnt--;
          netdev_uninit(netdev, true);
-         /* If the reference count for the netdev device is zero, destroy it. */
-         if (!netdev_dev->ref_cnt) {
-             netdev_dev_uninit(netdev_dev, true);
-         }
+         netdev_dev_unref(dev);
      }
  }
  
@@@ -793,37 -800,44 +802,44 @@@ netdev_get_in6(const struct netdev *net
  }
  
  /* On 'netdev', turns off the flags in 'off' and then turns on the flags in
-  * 'on'.  If 'permanent' is true, the changes will persist; otherwise, they
-  * will be reverted when 'netdev' is closed or the program exits.  Returns 0 if
-  * successful, otherwise a positive errno value. */
+  * 'on'.  Returns 0 if successful, otherwise a positive errno value. */
  static int
  do_update_flags(struct netdev *netdev, enum netdev_flags off,
                  enum netdev_flags on, enum netdev_flags *old_flagsp,
-                 bool permanent)
+                 struct netdev_saved_flags **sfp)
  {
+     struct netdev_dev *dev = netdev_get_dev(netdev);
+     struct netdev_saved_flags *sf = NULL;
      enum netdev_flags old_flags;
      int error;
  
-     error = netdev_get_dev(netdev)->netdev_class->update_flags(netdev,
-                 off & ~on, on, &old_flags);
+     error = dev->netdev_class->update_flags(dev, off & ~on, on, &old_flags);
      if (error) {
          VLOG_WARN_RL(&rl, "failed to %s flags for network device %s: %s",
                       off || on ? "set" : "get", netdev_get_name(netdev),
                       strerror(error));
          old_flags = 0;
-     } else if ((off || on) && !permanent) {
+     } else if ((off || on) && sfp) {
          enum netdev_flags new_flags = (old_flags & ~off) | on;
          enum netdev_flags changed_flags = old_flags ^ new_flags;
          if (changed_flags) {
-             if (!netdev->changed_flags) {
-                 netdev->save_flags = old_flags;
-             }
-             netdev->changed_flags |= changed_flags;
+             *sfp = sf = xmalloc(sizeof *sf);
+             sf->dev = dev;
+             list_push_front(&dev->saved_flags_list, &sf->node);
+             sf->saved_flags = changed_flags;
+             sf->saved_values = changed_flags & new_flags;
+             dev->ref_cnt++;
          }
      }
      if (old_flagsp) {
          *old_flagsp = old_flags;
      }
+     if (sfp) {
+         *sfp = sf;
+     }
      return error;
  }
  
@@@ -834,40 -848,63 +850,63 @@@ in
  netdev_get_flags(const struct netdev *netdev_, enum netdev_flags *flagsp)
  {
      struct netdev *netdev = CONST_CAST(struct netdev *, netdev_);
-     return do_update_flags(netdev, 0, 0, flagsp, false);
+     return do_update_flags(netdev, 0, 0, flagsp, NULL);
  }
  
  /* Sets the flags for 'netdev' to 'flags'.
-  * If 'permanent' is true, the changes will persist; otherwise, they
-  * will be reverted when 'netdev' is closed or the program exits.
   * Returns 0 if successful, otherwise a positive errno value. */
  int
  netdev_set_flags(struct netdev *netdev, enum netdev_flags flags,
-                  bool permanent)
+                  struct netdev_saved_flags **sfp)
  {
-     return do_update_flags(netdev, -1, flags, NULL, permanent);
+     return do_update_flags(netdev, -1, flags, NULL, sfp);
  }
  
- /* Turns on the specified 'flags' on 'netdev'.
-  * If 'permanent' is true, the changes will persist; otherwise, they
-  * will be reverted when 'netdev' is closed or the program exits.
-  * Returns 0 if successful, otherwise a positive errno value. */
+ /* Turns on the specified 'flags' on 'netdev':
+  *
+  *    - On success, returns 0.  If 'sfp' is nonnull, sets '*sfp' to a newly
+  *      allocated 'struct netdev_saved_flags *' that may be passed to
+  *      netdev_restore_flags() to restore the original values of 'flags' on
+  *      'netdev' (this will happen automatically at program termination if
+  *      netdev_restore_flags() is never called) , or to NULL if no flags were
+  *      actually changed.
+  *
+  *    - On failure, returns a positive errno value.  If 'sfp' is nonnull, sets
+  *      '*sfp' to NULL. */
  int
  netdev_turn_flags_on(struct netdev *netdev, enum netdev_flags flags,
-                      bool permanent)
+                      struct netdev_saved_flags **sfp)
  {
-     return do_update_flags(netdev, 0, flags, NULL, permanent);
+     return do_update_flags(netdev, 0, flags, NULL, sfp);
  }
  
- /* Turns off the specified 'flags' on 'netdev'.
-  * If 'permanent' is true, the changes will persist; otherwise, they
-  * will be reverted when 'netdev' is closed or the program exits.
-  * Returns 0 if successful, otherwise a positive errno value. */
+ /* Turns off the specified 'flags' on 'netdev'.  See netdev_turn_flags_on() for
+  * details of the interface. */
  int
  netdev_turn_flags_off(struct netdev *netdev, enum netdev_flags flags,
-                       bool permanent)
+                       struct netdev_saved_flags **sfp)
+ {
+     return do_update_flags(netdev, flags, 0, NULL, sfp);
+ }
+ /* Restores the flags that were saved in 'sf', and destroys 'sf'.
+  * Does nothing if 'sf' is NULL. */
+ void
+ netdev_restore_flags(struct netdev_saved_flags *sf)
  {
-     return do_update_flags(netdev, flags, 0, NULL, permanent);
+     if (sf) {
+         struct netdev_dev *dev = sf->dev;
+         enum netdev_flags old_flags;
+         dev->netdev_class->update_flags(dev,
+                                         sf->saved_flags & sf->saved_values,
+                                         sf->saved_flags & ~sf->saved_values,
+                                         &old_flags);
+         list_remove(&sf->node);
+         free(sf);
+         netdev_dev_unref(dev);
+     }
  }
  
  /* Looks up the ARP table entry for 'ip' on 'netdev'.  If one exists and can be
@@@ -1117,7 -1154,7 +1156,7 @@@ netdev_set_qos(struct netdev *netdev
  
      if (class->set_qos) {
          if (!details) {
-             static struct smap empty = SMAP_INITIALIZER(&empty);
+             static const struct smap empty = SMAP_INITIALIZER(&empty);
              details = &empty;
          }
          return class->set_qos(netdev, type, details);
@@@ -1295,6 -1332,7 +1334,7 @@@ netdev_dev_init(struct netdev_dev *netd
      netdev_dev->netdev_class = netdev_class;
      netdev_dev->name = xstrdup(name);
      netdev_dev->node = shash_add(&netdev_dev_shash, name, netdev_dev);
+     list_init(&netdev_dev->saved_flags_list);
  }
  
  /* Undoes the results of initialization.
@@@ -1310,6 -1348,7 +1350,7 @@@ netdev_dev_uninit(struct netdev_dev *ne
      char *name = netdev_dev->name;
  
      ovs_assert(!netdev_dev->ref_cnt);
+     ovs_assert(list_is_empty(&netdev_dev->saved_flags_list));
  
      shash_delete(&netdev_dev_shash, netdev_dev->node);
  
@@@ -1392,20 -1431,12 +1433,12 @@@ netdev_init(struct netdev *netdev, stru
  void
  netdev_uninit(struct netdev *netdev, bool close)
  {
-     /* Restore flags that we changed, if any. */
-     int error = restore_flags(netdev);
      list_remove(&netdev->node);
-     if (error) {
-         VLOG_WARN("failed to restore network device flags on %s: %s",
-                   netdev_get_name(netdev), strerror(error));
-     }
      if (close) {
          netdev_get_dev(netdev)->netdev_class->close(netdev);
      }
  }
  
  /* Returns the class type of 'netdev'.
   *
   * The caller must not free the returned value. */
@@@ -1415,7 -1446,6 +1448,6 @@@ netdev_get_type(const struct netdev *ne
      return netdev_get_dev(netdev)->netdev_class->type;
  }
  
  const char *
  netdev_get_type_from_name(const char *name)
  {
@@@ -1429,31 -1459,32 +1461,32 @@@ netdev_get_dev(const struct netdev *net
      return netdev->netdev_dev;
  }
  \f
- /* Restore the network device flags on 'netdev' to those that were active
-  * before we changed them.  Returns 0 if successful, otherwise a positive
-  * errno value.
-  *
-  * To avoid reentry, the caller must ensure that fatal signals are blocked. */
- static int
- restore_flags(struct netdev *netdev)
- {
-     if (netdev->changed_flags) {
-         enum netdev_flags restore = netdev->save_flags & netdev->changed_flags;
-         enum netdev_flags old_flags;
-         return netdev_get_dev(netdev)->netdev_class->update_flags(netdev,
-                                            netdev->changed_flags & ~restore,
-                                            restore, &old_flags);
-     }
-     return 0;
- }
- /* Close all netdevs on shutdown so they can do any needed cleanup such as
-  * destroying devices, restoring flags, etc. */
+ /* Restores all flags that have been saved with netdev_save_flags() and not yet
+  * restored with netdev_restore_flags(). */
  static void
close_all_netdevs(void *aux OVS_UNUSED)
restore_all_flags(void *aux OVS_UNUSED)
  {
-     struct netdev *netdev, *next;
-     LIST_FOR_EACH_SAFE(netdev, next, node, &netdev_list) {
-         netdev_close(netdev);
+     struct shash_node *node;
+     SHASH_FOR_EACH (node, &netdev_dev_shash) {
+         struct netdev_dev *dev = node->data;
+         const struct netdev_saved_flags *sf;
+         enum netdev_flags saved_values;
+         enum netdev_flags saved_flags;
+         saved_values = saved_flags = 0;
+         LIST_FOR_EACH (sf, node, &dev->saved_flags_list) {
+             saved_flags |= sf->saved_flags;
+             saved_values &= ~sf->saved_flags;
+             saved_values |= sf->saved_flags & sf->saved_values;
+         }
+         if (saved_flags) {
+             enum netdev_flags old_flags;
+             dev->netdev_class->update_flags(dev,
+                                             saved_flags & saved_values,
+                                             saved_flags & ~saved_values,
+                                             &old_flags);
+         }
      }
  }