]> git.proxmox.com Git - mirror_ovs.git/commitdiff
netdev: Add reconfigure request mechanism.
authorDaniele Di Proietto <diproiettod@vmware.com>
Thu, 25 Feb 2016 01:25:11 +0000 (17:25 -0800)
committerDaniele Di Proietto <diproiettod@vmware.com>
Mon, 23 May 2016 17:27:42 +0000 (10:27 -0700)
A netdev provider, especially a PMD provider (like netdev DPDK) might
not be able to change some of its parameters (such as MTU, or number of
queues) without stopping everything and restarting.

This commit introduces a mechanism that allows a netdev provider to
request a restart (netdev_request_reconfigure()).  The upper layer can
be notified via netdev_wait_reconf_required() and
netdev_is_reconf_required().  After closing all the rxqs the upper layer
can finally call netdev_reconfigure(), to make sure that the new
configuration is in place.

This will be used by next commit to reconfigure rx and tx queues in
netdev-dpdk.

Signed-off-by: Daniele Di Proietto <diproiettod@vmware.com>
Tested-by: Ilya Maximets <i.maximets@samsung.com>
Acked-by: Ilya Maximets <i.maximets@samsung.com>
Acked-by: Mark Kavanagh <mark.b.kavanagh@intel.com>
lib/netdev-bsd.c
lib/netdev-dpdk.c
lib/netdev-dummy.c
lib/netdev-linux.c
lib/netdev-provider.h
lib/netdev-vport.c
lib/netdev.c
lib/netdev.h

index 49c05f49938b909841a00857313fdb45e63d2657..32e8f744b64fa68f51214db1d774404d29d788b5 100644 (file)
@@ -1536,6 +1536,7 @@ netdev_bsd_update_flags(struct netdev *netdev_, enum netdev_flags off,
     netdev_bsd_arp_lookup, /* arp_lookup */          \
                                                      \
     netdev_bsd_update_flags,                         \
+    NULL, /* reconfigure */                          \
                                                      \
     netdev_bsd_rxq_alloc,                            \
     netdev_bsd_rxq_construct,                        \
index 9ffa7ff655a0fcc2b40bc64a4b451914dcecd8d1..1deb44fc11a47055cd8da70e62aab4de375ab55e 100644 (file)
@@ -2841,6 +2841,7 @@ static const struct dpdk_qos_ops egress_policer_ops = {
     NULL,                       /* arp_lookup */              \
                                                               \
     netdev_dpdk_update_flags,                                 \
+    NULL,                       /* reconfigure */             \
                                                               \
     netdev_dpdk_rxq_alloc,                                    \
     netdev_dpdk_rxq_construct,                                \
index 7f0ee764bd47067f724da1a7d9dd42d3de27acd3..2695c1fad2a058eb670932d706a6d90630e1df28 100644 (file)
@@ -1279,6 +1279,7 @@ static const struct netdev_class dummy_class = {
     NULL,                       /* arp_lookup */
 
     netdev_dummy_update_flags,
+    NULL,                       /* reconfigure */
 
     netdev_dummy_rxq_alloc,
     netdev_dummy_rxq_construct,
index 5db18877d1c12b9b72c76751f059703bbf617abd..25e1112228d462fcad38f5773cf424b41f256366 100644 (file)
@@ -2806,6 +2806,7 @@ netdev_linux_update_flags(struct netdev *netdev_, enum netdev_flags off,
     netdev_linux_arp_lookup,                                    \
                                                                 \
     netdev_linux_update_flags,                                  \
+    NULL,                       /* reconfigure */               \
                                                                 \
     netdev_linux_rxq_alloc,                                     \
     netdev_linux_rxq_construct,                                 \
index 6af0708e21e29547af5a85ed8e6a2c1ba1b602a5..a1ba504a025ca3bf57d51c1ec44bc56ca8f9fd29 100644 (file)
@@ -52,6 +52,16 @@ struct netdev {
      * 'netdev''s flags, features, ethernet address, or carrier changes. */
     uint64_t change_seq;
 
+    /* A netdev provider might be unable to change some of the device's
+     * parameter (n_rxq, mtu) when the device is in use.  In this case
+     * the provider can notify the upper layer by calling
+     * netdev_request_reconfigure().  The upper layer will react by stopping
+     * the operations on the device and calling netdev_reconfigure() to allow
+     * the configuration changes.  'last_reconfigure_seq' remembers the value
+     * of 'reconfigure_seq' when the last reconfiguration happened. */
+    struct seq *reconfigure_seq;
+    uint64_t last_reconfigure_seq;
+
     /* The core netdev code initializes these at netdev construction and only
      * provide read-only access to its client.  Netdev implementations may
      * modify them. */
@@ -75,6 +85,12 @@ netdev_change_seq_changed(const struct netdev *netdev_)
     }
 }
 
+static inline void
+netdev_request_reconfigure(struct netdev *netdev)
+{
+    seq_change(netdev->reconfigure_seq);
+}
+
 const char *netdev_get_type(const struct netdev *);
 const struct netdev_class *netdev_get_class(const struct netdev *);
 const char *netdev_get_name(const struct netdev *);
@@ -694,6 +710,15 @@ struct netdev_class {
     int (*update_flags)(struct netdev *netdev, enum netdev_flags off,
                         enum netdev_flags on, enum netdev_flags *old_flags);
 
+    /* If the provider called netdev_request_reconfigure(), the upper layer
+     * will eventually call this.  The provider can update the device
+     * configuration knowing that the upper layer will not call rxq_recv() or
+     * send() until this function returns.
+     *
+     * On error, the configuration is indeterminant and the device cannot be
+     * used to send and receive packets until a successful configuration is
+     * applied. */
+    int (*reconfigure)(struct netdev *netdev);
 /* ## -------------------- ## */
 /* ## netdev_rxq Functions ## */
 /* ## -------------------- ## */
index 8f2229c45a6dac6f9ed9f012f89b9ca0fa8e1764..270058c0318679a88a4fa8bddc61fba2dc4b5574 100644 (file)
@@ -881,6 +881,7 @@ get_stats(const struct netdev *netdev, struct netdev_stats *stats)
     NULL,                       /* arp_lookup */            \
                                                             \
     netdev_vport_update_flags,                              \
+    NULL,                       /* reconfigure */           \
                                                             \
     NULL,                   /* rx_alloc */                  \
     NULL,                   /* rx_construct */              \
index 9d40a2299dc8e79a218ba2bee67d71d62d94b062..2a4318807fbc7af59037bf8ed47b24a178bf1782 100644 (file)
@@ -353,6 +353,9 @@ netdev_open(const char *name, const char *type, struct netdev **netdevp)
                 netdev->netdev_class = rc->class;
                 netdev->name = xstrdup(name);
                 netdev->change_seq = 1;
+                netdev->reconfigure_seq = seq_create();
+                netdev->last_reconfigure_seq =
+                    seq_read(netdev->reconfigure_seq);
                 netdev->node = shash_add(&netdev_shash, name, netdev);
 
                 /* By default enable one tx and rx queue per netdev. */
@@ -500,6 +503,7 @@ netdev_unref(struct netdev *dev)
             shash_delete(&netdev_shash, dev->node);
         }
         free(dev->name);
+        seq_destroy(dev->reconfigure_seq);
         dev->netdev_class->dealloc(dev);
         ovs_mutex_unlock(&netdev_mutex);
 
@@ -1907,3 +1911,38 @@ netdev_get_addrs(const char dev[], struct in6_addr **paddr,
     return 0;
 }
 #endif
+
+void
+netdev_wait_reconf_required(struct netdev *netdev)
+{
+    seq_wait(netdev->reconfigure_seq, netdev->last_reconfigure_seq);
+}
+
+bool
+netdev_is_reconf_required(struct netdev *netdev)
+{
+    return seq_read(netdev->reconfigure_seq) != netdev->last_reconfigure_seq;
+}
+
+/* Give a chance to 'netdev' to reconfigure some of its parameters.
+ *
+ * If a module uses netdev_send() and netdev_rxq_recv(), it must call this
+ * function when netdev_is_reconf_required() returns true.
+ *
+ * Return 0 if successful, otherwise a positive errno value.  If the
+ * reconfiguration fails the netdev will not be able to send or receive
+ * packets.
+ *
+ * When this function is called, no call to netdev_rxq_recv() or netdev_send()
+ * must be issued. */
+int
+netdev_reconfigure(struct netdev *netdev)
+{
+    const struct netdev_class *class = netdev->netdev_class;
+
+    netdev->last_reconfigure_seq = seq_read(netdev->reconfigure_seq);
+
+    return (class->reconfigure
+            ? class->reconfigure(netdev)
+            : EOPNOTSUPP);
+}
index a2921677b935dfa9312f5d578d60586847fa62b7..867ff5d4d4a89f25e7359817472ca0e457f8912f 100644 (file)
@@ -243,6 +243,10 @@ int netdev_get_queue_stats(const struct netdev *, unsigned int queue_id,
                            struct netdev_queue_stats *);
 uint64_t netdev_get_change_seq(const struct netdev *);
 
+int netdev_reconfigure(struct netdev *netdev);
+void netdev_wait_reconf_required(struct netdev *netdev);
+bool netdev_is_reconf_required(struct netdev *netdev);
+
 struct netdev_queue_dump {
     struct netdev *netdev;
     int error;