[ovs-dev] [PATCH v6 11/12] netdev: Add reconfigure request mechanism.
Daniele Di Proietto
diproiettod at vmware.com
Mon Mar 28 19:41:45 UTC 2016
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 at vmware.com>
Tested-by: Ilya Maximets <i.maximets at samsung.com>
Acked-by: Ilya Maximets <i.maximets at samsung.com>
---
lib/netdev-bsd.c | 1 +
lib/netdev-dpdk.c | 1 +
lib/netdev-dummy.c | 1 +
lib/netdev-linux.c | 1 +
lib/netdev-provider.h | 27 ++++++++++++++++++++++++++-
lib/netdev-vport.c | 1 +
lib/netdev.c | 38 ++++++++++++++++++++++++++++++++++++++
lib/netdev.h | 4 ++++
8 files changed, 73 insertions(+), 1 deletion(-)
diff --git a/lib/netdev-bsd.c b/lib/netdev-bsd.c
index 75bd5a3..7a430aa 100644
--- a/lib/netdev-bsd.c
+++ b/lib/netdev-bsd.c
@@ -1537,6 +1537,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, \
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index f8c8ddc..7a6e2db 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -2695,6 +2695,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, \
diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
index 8be1ba7..2d3cc3b 100644
--- a/lib/netdev-dummy.c
+++ b/lib/netdev-dummy.c
@@ -1276,6 +1276,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,
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
index 994a27c..7568404 100644
--- a/lib/netdev-linux.c
+++ b/lib/netdev-linux.c
@@ -2807,6 +2807,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, \
diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
index 4419629..ef2da98 100644
--- a/lib/netdev-provider.h
+++ b/lib/netdev-provider.h
@@ -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. */
@@ -64,7 +74,7 @@ struct netdev {
struct ovs_list saved_flags_list; /* Contains "struct netdev_saved_flags". */
};
-static void
+static inline void
netdev_change_seq_changed(const struct netdev *netdev_)
{
struct netdev *netdev = CONST_CAST(struct netdev *, netdev_);
@@ -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 *);
@@ -692,6 +708,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 ## */
/* ## -------------------- ## */
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 2e509d3..09d131c 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -1528,6 +1528,7 @@ netdev_vport_range(struct unixctl_conn *conn, int argc,
NULL, /* arp_lookup */ \
\
netdev_vport_update_flags, \
+ NULL, /* reconfigure */ \
\
NULL, /* rx_alloc */ \
NULL, /* rx_construct */ \
diff --git a/lib/netdev.c b/lib/netdev.c
index 95fdbc7..26b7727 100644
--- a/lib/netdev.c
+++ b/lib/netdev.c
@@ -382,6 +382,8 @@ 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. */
@@ -530,6 +532,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);
@@ -1936,3 +1939,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);
+}
diff --git a/lib/netdev.h b/lib/netdev.h
index 05968b2..e207d44 100644
--- a/lib/netdev.h
+++ b/lib/netdev.h
@@ -308,6 +308,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;
--
2.1.4
More information about the dev
mailing list