[ovs-dev] [PATCH v3 10/11] netdev: Add reconfigure request mechanism.
Daniele Di Proietto
diproiettod at vmware.com
Wed Mar 16 23:04:52 UTC 2016
On 16/03/2016 06:12, "Ilya Maximets" <i.maximets at samsung.com> wrote:
>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 <diproiettod at 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;
>>
More information about the dev
mailing list