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 <diproiet...@vmware.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 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
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to