On 16.03.2016 01:30, Daniele Di Proietto wrote:
> 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 <[email protected]>
> ---
> 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 edf04bf..724e6d4 100644
> --- a/lib/netdev-bsd.c
> +++ b/lib/netdev-bsd.c
> @@ -1602,6 +1602,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 f402354..b5867e8 100644
> --- a/lib/netdev-dpdk.c
> +++ b/lib/netdev-dpdk.c
> @@ -2696,6 +2696,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 ccd4a0a..d7524eb 100644
> --- a/lib/netdev-dummy.c
> +++ b/lib/netdev-dummy.c
> @@ -1251,6 +1251,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 570677e..f9ad126 100644
> --- a/lib/netdev-linux.c
> +++ b/lib/netdev-linux.c
> @@ -2897,6 +2897,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 1952a02..0317910 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 *);
> @@ -699,6 +715,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 df6d8cf..d055f10 100644
> --- a/lib/netdev-vport.c
> +++ b/lib/netdev-vport.c
> @@ -1537,6 +1537,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 150f8d8..7cb7085 100644
> --- a/lib/netdev.c
> +++ b/lib/netdev.c
> @@ -377,6 +377,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. */
> @@ -525,6 +527,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);
>
> @@ -1854,3 +1857,38 @@ netdev_get_change_seq(const struct netdev *netdev)
> {
> return netdev->change_seq;
> }
> +
> +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 concurrent call to netdev_rxq_recv() or
> + * netdev_send() must be issued. */
Not only concurrent. There must be no calls at all.
> +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 a81989e..c2a1d6c 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;
>
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev