On 14/05/2019 18:16, Roi Dayan wrote:
>
>
> On 07/05/2019 12:24, Ilya Maximets wrote:
>> Current issues with Flow API:
>>
>> * OVS calls offloading functions regardless of successful
>> flow API initialization. (ex. on init_flow_api failure)
>> * Static initilaization of Flow API for a netdev_class forbids
>> having different offloading types for different instances
>> of netdev with the same netdev_class. (ex. different vports in
>> 'system' and 'netdev' datapaths at the same time)
>>
>> Solution:
>>
>> * Move Flow API from the netdev_class to netdev instance.
>> * Make Flow API dynamic, i.e. probe the APIs and choose the
>> suitable one.
>>
>> Side effects:
>>
>> * Flow API providers localized as possible in their modules.
>> * Now we have an ability to make runtime checks. For example,
>> we could check if particular device supports features we
>> need, like if dpdk device supports RSS+MARK action.
>>
>> Signed-off-by: Ilya Maximets <[email protected]>
>> ---
>> lib/automake.mk | 2 +-
>> lib/dpdk.c | 2 +
>> lib/netdev-dpdk.c | 24 +++-
>> lib/netdev-dpdk.h | 3 +
>> lib/netdev-dummy.c | 24 +++-
>> lib/netdev-linux.c | 3 -
>> lib/netdev-linux.h | 10 --
>> lib/netdev-offload-provider.h | 99 +++++++++++++++
>> lib/netdev-provider.h | 67 +----------
>> lib/netdev-rte-offloads.c | 40 +++++-
>> lib/netdev-rte-offloads.h | 41 +------
>> lib/netdev-tc-offloads.c | 39 ++++--
>> lib/netdev-tc-offloads.h | 44 -------
>> lib/netdev-vport.c | 6 +-
>> lib/netdev.c | 221 +++++++++++++++++++++++++++-------
>> tests/dpif-netdev.at | 4 +-
>> tests/ofproto-macros.at | 1 -
>> 17 files changed, 398 insertions(+), 232 deletions(-)
>> create mode 100644 lib/netdev-offload-provider.h
>> delete mode 100644 lib/netdev-tc-offloads.h
>>
>> diff --git a/lib/automake.mk b/lib/automake.mk
>> index cc5dccf39..c70fda3f8 100644
>> --- a/lib/automake.mk
>> +++ b/lib/automake.mk
>> @@ -137,6 +137,7 @@ lib_libopenvswitch_la_SOURCES = \
>> lib/namemap.c \
>> lib/netdev-dpdk.h \
>> lib/netdev-dummy.c \
>> + lib/netdev-offload-provider.h \
>> lib/netdev-provider.h \
>> lib/netdev-rte-offloads.h \
>> lib/netdev-vport.c \
>> @@ -393,7 +394,6 @@ lib_libopenvswitch_la_SOURCES += \
>> lib/netdev-linux.c \
>> lib/netdev-linux.h \
>> lib/netdev-tc-offloads.c \
>> - lib/netdev-tc-offloads.h \
>> lib/netlink-conntrack.c \
>> lib/netlink-conntrack.h \
>> lib/netlink-notifier.c \
>> diff --git a/lib/dpdk.c b/lib/dpdk.c
>> index dc6171546..6c6298635 100644
>> --- a/lib/dpdk.c
>> +++ b/lib/dpdk.c
>> @@ -34,6 +34,7 @@
>> #include "dirs.h"
>> #include "fatal-signal.h"
>> #include "netdev-dpdk.h"
>> +#include "netdev-rte-offloads.h"
>> #include "openvswitch/dynamic-string.h"
>> #include "openvswitch/vlog.h"
>> #include "ovs-numa.h"
>> @@ -442,6 +443,7 @@ dpdk_init__(const struct smap *ovs_other_config)
>>
>> /* Finally, register the dpdk classes */
>> netdev_dpdk_register();
>> + netdev_dpdk_flow_api_register();
>> return true;
>> }
>>
>> diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
>> index 47153dc60..c06c9ef81 100644
>> --- a/lib/netdev-dpdk.c
>> +++ b/lib/netdev-dpdk.c
>> @@ -4204,6 +4204,27 @@ unlock:
>> return err;
>> }
>>
>> +bool
>> +netdev_dpdk_flow_api_supported(struct netdev *netdev)
>> +{
>> + struct netdev_dpdk *dev;
>> + bool ret = false;
>> +
>> + if (!is_dpdk_class(netdev->netdev_class)) {
>> + goto out;
>> + }
>> +
>> + dev = netdev_dpdk_cast(netdev);
>> + ovs_mutex_lock(&dev->mutex);
>> + if (dev->type == DPDK_DEV_ETH) {
>> + /* TODO: Check if we able to offload some minimal flow. */
>> + ret = true;
>> + }
>> + ovs_mutex_unlock(&dev->mutex);
>> +out:
>> + return ret;
>> +}
>> +
>> int
>> netdev_dpdk_rte_flow_destroy(struct netdev *netdev,
>> struct rte_flow *rte_flow,
>> @@ -4268,8 +4289,7 @@ netdev_dpdk_rte_flow_create(struct netdev *netdev,
>> .get_features = netdev_dpdk_get_features, \
>> .get_status = netdev_dpdk_get_status, \
>> .reconfigure = netdev_dpdk_reconfigure, \
>> - .rxq_recv = netdev_dpdk_rxq_recv, \
>> - DPDK_FLOW_OFFLOAD_API
>> + .rxq_recv = netdev_dpdk_rxq_recv
>>
>> static const struct netdev_class dpdk_class = {
>> .type = "dpdk",
>> diff --git a/lib/netdev-dpdk.h b/lib/netdev-dpdk.h
>> index 9bbb8d8d6..60631c4f0 100644
>> --- a/lib/netdev-dpdk.h
>> +++ b/lib/netdev-dpdk.h
>> @@ -34,6 +34,9 @@ struct rte_flow_action;
>>
>> void netdev_dpdk_register(void);
>> void free_dpdk_buf(struct dp_packet *);
>> +
>> +bool netdev_dpdk_flow_api_supported(struct netdev *);
>> +
>> int
>> netdev_dpdk_rte_flow_destroy(struct netdev *netdev,
>> struct rte_flow *rte_flow,
>> diff --git a/lib/netdev-dummy.c b/lib/netdev-dummy.c
>> index 3f90ffa09..18eed4cf4 100644
>> --- a/lib/netdev-dummy.c
>> +++ b/lib/netdev-dummy.c
>> @@ -24,6 +24,7 @@
>> #include "dp-packet.h"
>> #include "dpif-netdev.h"
>> #include "flow.h"
>> +#include "netdev-offload-provider.h"
>> #include "netdev-provider.h"
>> #include "netdev-vport.h"
>> #include "odp-util.h"
>> @@ -1523,10 +1524,6 @@ exit:
>> return error ? -1 : 0;
>> }
>>
>> -#define DUMMY_FLOW_OFFLOAD_API \
>> - .flow_put = netdev_dummy_flow_put, \
>> - .flow_del = netdev_dummy_flow_del
>> -
>> #define NETDEV_DUMMY_CLASS_COMMON \
>> .run = netdev_dummy_run, \
>> .wait = netdev_dummy_wait, \
>> @@ -1559,8 +1556,7 @@ exit:
>> .rxq_dealloc = netdev_dummy_rxq_dealloc, \
>> .rxq_recv = netdev_dummy_rxq_recv, \
>> .rxq_wait = netdev_dummy_rxq_wait, \
>> - .rxq_drain = netdev_dummy_rxq_drain, \
>> - DUMMY_FLOW_OFFLOAD_API
>> + .rxq_drain = netdev_dummy_rxq_drain
>>
>> static const struct netdev_class dummy_class = {
>> NETDEV_DUMMY_CLASS_COMMON,
>> @@ -1578,6 +1574,20 @@ static const struct netdev_class dummy_pmd_class = {
>> .is_pmd = true,
>> .reconfigure = netdev_dummy_reconfigure
>> };
>> +
>> +static int
>> +netdev_dummy_offloads_init_flow_api(struct netdev *netdev)
>> +{
>> + return is_dummy_class(netdev->netdev_class) ? 0 : EOPNOTSUPP;
>> +}
>> +
>> +static const struct netdev_flow_api netdev_dummy_offloads = {
>> + .type = "dummy",
>> + .flow_put = netdev_dummy_flow_put,
>> + .flow_del = netdev_dummy_flow_del,
>> + .init_flow_api = netdev_dummy_offloads_init_flow_api,
>> +};
>> +
>>
>> /* Helper functions. */
>>
>> @@ -2024,5 +2034,7 @@ netdev_dummy_register(enum dummy_level level)
>> netdev_register_provider(&dummy_internal_class);
>> netdev_register_provider(&dummy_pmd_class);
>>
>> + netdev_register_flow_api_provider(&netdev_dummy_offloads);
>> +
>> netdev_vport_tunnel_register();
>> }
>> diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c
>> index f75d73fd3..e4ea94cf9 100644
>> --- a/lib/netdev-linux.c
>> +++ b/lib/netdev-linux.c
>> @@ -55,7 +55,6 @@
>> #include "hash.h"
>> #include "openvswitch/hmap.h"
>> #include "netdev-provider.h"
>> -#include "netdev-tc-offloads.h"
>> #include "netdev-vport.h"
>> #include "netlink-notifier.h"
>> #include "netlink-socket.h"
>> @@ -3321,7 +3320,6 @@ exit:
>>
>> const struct netdev_class netdev_linux_class = {
>> NETDEV_LINUX_CLASS_COMMON,
>> - LINUX_FLOW_OFFLOAD_API,
>> .type = "system",
>> .construct = netdev_linux_construct,
>> .get_stats = netdev_linux_get_stats,
>> @@ -3341,7 +3339,6 @@ const struct netdev_class netdev_tap_class = {
>>
>> const struct netdev_class netdev_internal_class = {
>> NETDEV_LINUX_CLASS_COMMON,
>> - LINUX_FLOW_OFFLOAD_API,
>> .type = "internal",
>> .construct = netdev_linux_construct,
>> .get_stats = netdev_internal_get_stats,
>> diff --git a/lib/netdev-linux.h b/lib/netdev-linux.h
>> index 17ca91201..e1e30f806 100644
>> --- a/lib/netdev-linux.h
>> +++ b/lib/netdev-linux.h
>> @@ -29,14 +29,4 @@ int netdev_linux_ethtool_set_flag(struct netdev *netdev,
>> uint32_t flag,
>> const char *flag_name, bool enable);
>> int linux_get_ifindex(const char *netdev_name);
>>
>> -#define LINUX_FLOW_OFFLOAD_API \
>> - .flow_flush = netdev_tc_flow_flush, \
>> - .flow_dump_create = netdev_tc_flow_dump_create, \
>> - .flow_dump_destroy = netdev_tc_flow_dump_destroy, \
>> - .flow_dump_next = netdev_tc_flow_dump_next, \
>> - .flow_put = netdev_tc_flow_put, \
>> - .flow_get = netdev_tc_flow_get, \
>> - .flow_del = netdev_tc_flow_del, \
>> - .init_flow_api = netdev_tc_init_flow_api
>> -
>> #endif /* netdev-linux.h */
>> diff --git a/lib/netdev-offload-provider.h b/lib/netdev-offload-provider.h
>> new file mode 100644
>> index 000000000..ceeaa50b0
>> --- /dev/null
>> +++ b/lib/netdev-offload-provider.h
>> @@ -0,0 +1,99 @@
>> +/*
>> + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2016 Nicira, Inc.
>> + * Copyright (c) 2019 Samsung Electronics Co.,Ltd.
>> + *
>> + * Licensed under the Apache License, Version 2.0 (the "License");
>> + * you may not use this file except in compliance with the License.
>> + * You may obtain a copy of the License at:
>> + *
>> + *
>> https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.apache.org%2Flicenses%2FLICENSE-2.0&data=02%7C01%7Croid%40mellanox.com%7C320331a5f32d437474f908d6d2cdca07%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C636928178634854039&sdata=%2BVQUoOrR5xFd6smiLUQOIrGGxxHi2FrVoHPkHGQ7hZU%3D&reserved=0
>> + *
>> + * Unless required by applicable law or agreed to in writing, software
>> + * distributed under the License is distributed on an "AS IS" BASIS,
>> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>> + * See the License for the specific language governing permissions and
>> + * limitations under the License.
>> + */
>> +
>> +#ifndef NETDEV_FLOW_API_PROVIDER_H
>> +#define NETDEV_FLOW_API_PROVIDER_H 1
>> +
>> +#include "flow.h"
>> +#include "openvswitch/types.h"
>> +#include "packets.h"
>> +
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>> +struct netdev_flow_api {
>> + char *type;
>> + /* Flush all offloaded flows from a netdev.
>> + * Return 0 if successful, otherwise returns a positive errno value. */
>> + int (*flow_flush)(struct netdev *);
>> +
>> + /* Flow dumping interface.
>> + *
>> + * This is the back-end for the flow dumping interface described in
>> + * dpif.h. Please read the comments there first, because this code
>> + * closely follows it.
>> + *
>> + * On success returns 0 and allocates data, on failure returns
>> + * positive errno. */
>> + int (*flow_dump_create)(struct netdev *, struct netdev_flow_dump
>> **dump);
>> + int (*flow_dump_destroy)(struct netdev_flow_dump *);
>> +
>> + /* Returns true if there are more flows to dump.
>> + * 'rbuffer' is used as a temporary buffer and needs to be pre allocated
>> + * by the caller. While there are more flows the same 'rbuffer'
>> + * should be provided. 'wbuffer' is used to store dumped actions and
>> needs
>> + * to be pre allocated by the caller. */
>> + bool (*flow_dump_next)(struct netdev_flow_dump *, struct match *,
>> + struct nlattr **actions,
>> + struct dpif_flow_stats *stats,
>> + struct dpif_flow_attrs *attrs, ovs_u128 *ufid,
>> + struct ofpbuf *rbuffer, struct ofpbuf *wbuffer);
>> +
>> + /* Offload the given flow on netdev.
>> + * To modify a flow, use the same ufid.
>> + * 'actions' are in netlink format, as with struct dpif_flow_put.
>> + * 'info' is extra info needed to offload the flow.
>> + * 'stats' is populated according to the rules set out in the
>> description
>> + * above 'struct dpif_flow_put'.
>> + * Return 0 if successful, otherwise returns a positive errno value. */
>> + int (*flow_put)(struct netdev *, struct match *, struct nlattr *actions,
>> + size_t actions_len, const ovs_u128 *ufid,
>> + struct offload_info *info, struct dpif_flow_stats *);
>> +
>> + /* Queries a flow specified by ufid on netdev.
>> + * Fills output buffer as 'wbuffer' in flow_dump_next, which
>> + * needs to be be pre allocated.
>> + * Return 0 if successful, otherwise returns a positive errno value. */
>> + int (*flow_get)(struct netdev *, struct match *, struct nlattr
>> **actions,
>> + const ovs_u128 *ufid, struct dpif_flow_stats *,
>> + struct dpif_flow_attrs *, struct ofpbuf *wbuffer);
>> +
>> + /* Delete a flow specified by ufid from netdev.
>> + * 'stats' is populated according to the rules set out in the
>> description
>> + * above 'struct dpif_flow_del'.
>> + * Return 0 if successful, otherwise returns a positive errno value. */
>> + int (*flow_del)(struct netdev *, const ovs_u128 *ufid,
>> + struct dpif_flow_stats *);
>> +
>> + /* Initializies the netdev flow api.
>> + * Return 0 if successful, otherwise returns a positive errno value. */
>> + int (*init_flow_api)(struct netdev *);
>> +};
>> +
>> +int netdev_register_flow_api_provider(const struct netdev_flow_api *);
>> +int netdev_unregister_flow_api_provider(const char *type);
>> +
>> +#ifdef __linux__
>> +extern const struct netdev_flow_api netdev_tc_offloads;
>> +#endif
>> +
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>> +#endif /* NETDEV_FLOW_API_PROVIDER_H */
>> diff --git a/lib/netdev-provider.h b/lib/netdev-provider.h
>> index fb0c27e6e..653854cbd 100644
>> --- a/lib/netdev-provider.h
>> +++ b/lib/netdev-provider.h
>> @@ -23,6 +23,7 @@
>> #include "netdev.h"
>> #include "openvswitch/list.h"
>> #include "ovs-numa.h"
>> +#include "ovs-rcu.h"
>> #include "packets.h"
>> #include "seq.h"
>> #include "openvswitch/shash.h"
>> @@ -93,6 +94,9 @@ struct netdev {
>> int n_rxq;
>> struct shash_node *node; /* Pointer to element in global
>> map. */
>> struct ovs_list saved_flags_list; /* Contains "struct
>> netdev_saved_flags". */
>> +
>> + /* Functions to control flow offloading. */
>> + OVSRCU_TYPE(const struct netdev_flow_api *) flow_api;
>> struct netdev_hw_info hw_info; /* offload-capable netdev info */
>> };
>>
>> @@ -822,69 +826,6 @@ struct netdev_class {
>> /* Discards all packets waiting to be received from 'rx'. */
>> int (*rxq_drain)(struct netdev_rxq *rx);
>>
>> - /* ## -------------------------------- ## */
>> - /* ## netdev flow offloading functions ## */
>> - /* ## -------------------------------- ## */
>> -
>> - /* If a particular netdev class does not support offloading flows,
>> - * all these function pointers must be NULL. */
>> -
>> - /* Flush all offloaded flows from a netdev.
>> - * Return 0 if successful, otherwise returns a positive errno value. */
>> - int (*flow_flush)(struct netdev *);
>> -
>> - /* Flow dumping interface.
>> - *
>> - * This is the back-end for the flow dumping interface described in
>> - * dpif.h. Please read the comments there first, because this code
>> - * closely follows it.
>> - *
>> - * On success returns 0 and allocates data, on failure returns
>> - * positive errno. */
>> - int (*flow_dump_create)(struct netdev *, struct netdev_flow_dump
>> **dump);
>> - int (*flow_dump_destroy)(struct netdev_flow_dump *);
>> -
>> - /* Returns true if there are more flows to dump.
>> - * 'rbuffer' is used as a temporary buffer and needs to be pre allocated
>> - * by the caller. While there are more flows the same 'rbuffer'
>> - * should be provided. 'wbuffer' is used to store dumped actions and
>> needs
>> - * to be pre allocated by the caller. */
>> - bool (*flow_dump_next)(struct netdev_flow_dump *, struct match *,
>> - struct nlattr **actions,
>> - struct dpif_flow_stats *stats,
>> - struct dpif_flow_attrs *attrs, ovs_u128 *ufid,
>> - struct ofpbuf *rbuffer, struct ofpbuf *wbuffer);
>> -
>> - /* Offload the given flow on netdev.
>> - * To modify a flow, use the same ufid.
>> - * 'actions' are in netlink format, as with struct dpif_flow_put.
>> - * 'info' is extra info needed to offload the flow.
>> - * 'stats' is populated according to the rules set out in the
>> description
>> - * above 'struct dpif_flow_put'.
>> - * Return 0 if successful, otherwise returns a positive errno value. */
>> - int (*flow_put)(struct netdev *, struct match *, struct nlattr *actions,
>> - size_t actions_len, const ovs_u128 *ufid,
>> - struct offload_info *info, struct dpif_flow_stats *);
>> -
>> - /* Queries a flow specified by ufid on netdev.
>> - * Fills output buffer as 'wbuffer' in flow_dump_next, which
>> - * needs to be be pre allocated.
>> - * Return 0 if successful, otherwise returns a positive errno value. */
>> - int (*flow_get)(struct netdev *, struct match *, struct nlattr
>> **actions,
>> - const ovs_u128 *ufid, struct dpif_flow_stats *,
>> - struct dpif_flow_attrs *, struct ofpbuf *wbuffer);
>> -
>> - /* Delete a flow specified by ufid from netdev.
>> - * 'stats' is populated according to the rules set out in the
>> description
>> - * above 'struct dpif_flow_del'.
>> - * Return 0 if successful, otherwise returns a positive errno value. */
>> - int (*flow_del)(struct netdev *, const ovs_u128 *ufid,
>> - struct dpif_flow_stats *);
>> -
>> - /* Initializies the netdev flow api.
>> - * Return 0 if successful, otherwise returns a positive errno value. */
>> - int (*init_flow_api)(struct netdev *);
>> -
>> /* Get a block_id from the netdev.
>> * Returns the block_id or 0 if none exists for netdev. */
>> uint32_t (*get_block_id)(struct netdev *);
>> diff --git a/lib/netdev-rte-offloads.c b/lib/netdev-rte-offloads.c
>> index e9ab08624..683763f43 100644
>> --- a/lib/netdev-rte-offloads.c
>> +++ b/lib/netdev-rte-offloads.c
>> @@ -21,6 +21,7 @@
>>
>> #include "cmap.h"
>> #include "dpif-netdev.h"
>> +#include "netdev-offload-provider.h"
>> #include "netdev-provider.h"
>> #include "openvswitch/match.h"
>> #include "openvswitch/vlog.h"
>> @@ -29,6 +30,23 @@
>>
>> VLOG_DEFINE_THIS_MODULE(netdev_rte_offloads);
>>
>> +/* Thread-safety
>> + * =============
>> + *
>> + * Below API is NOT thread safe in following terms:
>> + *
>> + * - The caller must be sure that none of these functions will be called
>> + * simultaneously. Even for different 'netdev's.
>> + *
>> + * - The caller must be sure that 'netdev' will not be
>> destructed/deallocated.
>> + *
>> + * - The caller must be sure that 'netdev' configuration will not be
>> changed.
>> + * For example, simultaneous call of 'netdev_reconfigure()' for the same
>> + * 'netdev' is forbidden.
>> + *
>> + * For current implementation all above restrictions could be fulfilled by
>> + * taking the datapath 'port_mutex' in lib/dpif-netdev.c. */
>> +
>> /*
>> * A mapping from ufid to dpdk rte_flow.
>> */
>> @@ -689,7 +707,7 @@ netdev_rte_offloads_destroy_flow(struct netdev *netdev,
>> return ret;
>> }
>>
>> -int
>> +static int
>> netdev_rte_offloads_flow_put(struct netdev *netdev, struct match *match,
>> struct nlattr *actions, size_t actions_len,
>> const ovs_u128 *ufid, struct offload_info
>> *info,
>> @@ -719,7 +737,7 @@ netdev_rte_offloads_flow_put(struct netdev *netdev,
>> struct match *match,
>> actions_len, ufid, info);
>> }
>>
>> -int
>> +static int
>> netdev_rte_offloads_flow_del(struct netdev *netdev, const ovs_u128 *ufid,
>> struct dpif_flow_stats *stats OVS_UNUSED)
>> {
>> @@ -731,3 +749,21 @@ netdev_rte_offloads_flow_del(struct netdev *netdev,
>> const ovs_u128 *ufid,
>>
>> return netdev_rte_offloads_destroy_flow(netdev, ufid, rte_flow);
>> }
>> +
>> +static int
>> +netdev_rte_offloads_init_flow_api(struct netdev *netdev)
>> +{
>> + return netdev_dpdk_flow_api_supported(netdev) ? 0 : EOPNOTSUPP;
>> +}
>> +
>> +static const struct netdev_flow_api netdev_dpdk_offloads = {
>> + .type = "dpdk_flow_api",
>> + .flow_put = netdev_rte_offloads_flow_put,
>> + .flow_del = netdev_rte_offloads_flow_del,
>> + .init_flow_api = netdev_rte_offloads_init_flow_api,
>> +};
>> +
>> +void netdev_dpdk_flow_api_register(void)
>> +{
>> + netdev_register_flow_api_provider(&netdev_dpdk_offloads);
>> +}
>> diff --git a/lib/netdev-rte-offloads.h b/lib/netdev-rte-offloads.h
>> index 18c8a7558..b9b292114 100644
>> --- a/lib/netdev-rte-offloads.h
>> +++ b/lib/netdev-rte-offloads.h
>> @@ -14,44 +14,9 @@
>> * limitations under the License.
>> */
>>
>> -#ifndef NETDEV_VPORT_OFFLOADS_H
>> -#define NETDEV_VPORT_OFFLOADS_H 1
>> +#ifndef NETDEV_DPDK_OFFLOADS_H
>> +#define NETDEV_DPDK_OFFLOADS_H 1
>>
>> -#include "openvswitch/types.h"
>> -
>> -struct netdev;
>> -struct match;
>> -struct nlattr;
>> -struct offload_info;
>> -struct dpif_flow_stats;
>> -
>> -/* Thread-safety
>> - * =============
>> - *
>> - * Below API is NOT thread safe in following terms:
>> - *
>> - * - The caller must be sure that none of these functions will be called
>> - * simultaneously. Even for different 'netdev's.
>> - *
>> - * - The caller must be sure that 'netdev' will not be
>> destructed/deallocated.
>> - *
>> - * - The caller must be sure that 'netdev' configuration will not be
>> changed.
>> - * For example, simultaneous call of 'netdev_reconfigure()' for the same
>> - * 'netdev' is forbidden.
>> - *
>> - * For current implementation all above restrictions could be fulfilled by
>> - * taking the datapath 'port_mutex' in lib/dpif-netdev.c. */
>> -
>> -int netdev_rte_offloads_flow_put(struct netdev *netdev, struct match *match,
>> - struct nlattr *actions, size_t actions_len,
>> - const ovs_u128 *ufid,
>> - struct offload_info *info,
>> - struct dpif_flow_stats *stats);
>> -int netdev_rte_offloads_flow_del(struct netdev *netdev, const ovs_u128
>> *ufid,
>> - struct dpif_flow_stats *stats);
>> -
>> -#define DPDK_FLOW_OFFLOAD_API \
>> - .flow_put = netdev_rte_offloads_flow_put, \
>> - .flow_del = netdev_rte_offloads_flow_del
>> +void netdev_dpdk_flow_api_register(void);
>>
>> #endif /* netdev-rte-offloads.h */
>> diff --git a/lib/netdev-tc-offloads.c b/lib/netdev-tc-offloads.c
>> index d5c66acc1..b9a4a7302 100644
>> --- a/lib/netdev-tc-offloads.c
>> +++ b/lib/netdev-tc-offloads.c
>> @@ -16,7 +16,6 @@
>> */
>>
>> #include <config.h>
>> -#include "netdev-tc-offloads.h"
>>
>> #include <errno.h>
>> #include <linux/if_ether.h>
>> @@ -31,6 +30,8 @@
>> #include "openvswitch/util.h"
>> #include "openvswitch/vlog.h"
>> #include "netdev-linux.h"
>> +#include "netdev-offload-provider.h"
>> +#include "netdev-provider.h"
>> #include "netlink.h"
>> #include "netlink-socket.h"
>> #include "odp-netlink.h"
>> @@ -350,7 +351,7 @@ get_block_id_from_netdev(struct netdev *netdev)
>> return 0;
>> }
>>
>> -int
>> +static int
>> netdev_tc_flow_flush(struct netdev *netdev)
>> {
>> enum tc_qdisc_hook hook = get_tc_qdisc_hook(netdev);
>> @@ -368,7 +369,7 @@ netdev_tc_flow_flush(struct netdev *netdev)
>> return tc_flush(ifindex, block_id, hook);
>> }
>>
>> -int
>> +static int
>> netdev_tc_flow_dump_create(struct netdev *netdev,
>> struct netdev_flow_dump **dump_out)
>> {
>> @@ -395,7 +396,7 @@ netdev_tc_flow_dump_create(struct netdev *netdev,
>> return 0;
>> }
>>
>> -int
>> +static int
>> netdev_tc_flow_dump_destroy(struct netdev_flow_dump *dump)
>> {
>> nl_dump_done(dump->nl_dump);
>> @@ -729,7 +730,7 @@ parse_tc_flower_to_match(struct tc_flower *flower,
>> return 0;
>> }
>>
>> -bool
>> +static bool
>> netdev_tc_flow_dump_next(struct netdev_flow_dump *dump,
>> struct match *match,
>> struct nlattr **actions,
>> @@ -1082,7 +1083,7 @@ flower_match_to_tun_opt(struct tc_flower *flower,
>> const struct flow_tnl *tnl,
>> flower->mask.tunnel.metadata.present.len = tnl->metadata.present.len;
>> }
>>
>> -int
>> +static int
>> netdev_tc_flow_put(struct netdev *netdev, struct match *match,
>> struct nlattr *actions, size_t actions_len,
>> const ovs_u128 *ufid, struct offload_info *info,
>> @@ -1375,7 +1376,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match
>> *match,
>> return err;
>> }
>>
>> -int
>> +static int
>> netdev_tc_flow_get(struct netdev *netdev OVS_UNUSED,
>> struct match *match,
>> struct nlattr **actions,
>> @@ -1430,7 +1431,7 @@ netdev_tc_flow_get(struct netdev *netdev OVS_UNUSED,
>> return 0;
>> }
>>
>> -int
>> +static int
>> netdev_tc_flow_del(struct netdev *netdev OVS_UNUSED,
>> const ovs_u128 *ufid,
>> struct dpif_flow_stats *stats)
>> @@ -1550,7 +1551,7 @@ probe_tc_block_support(int ifindex)
>> }
>> }
>>
>> -int
>> +static int
>> netdev_tc_init_flow_api(struct netdev *netdev)
>> {
>> static struct ovsthread_once multi_mask_once =
>> OVSTHREAD_ONCE_INITIALIZER;
>> @@ -1562,8 +1563,8 @@ netdev_tc_init_flow_api(struct netdev *netdev)
>>
>> ifindex = netdev_get_ifindex(netdev);
>> if (ifindex < 0) {
>> - VLOG_ERR_RL(&error_rl, "init: failed to get ifindex for %s: %s",
>> - netdev_get_name(netdev), ovs_strerror(-ifindex));
>> + VLOG_INFO("init: failed to get ifindex for %s: %s",
>> + netdev_get_name(netdev), ovs_strerror(-ifindex));
>> return -ifindex;
>> }
>>
>> @@ -1584,8 +1585,8 @@ netdev_tc_init_flow_api(struct netdev *netdev)
>> error = tc_add_del_qdisc(ifindex, true, block_id, hook);
>>
>> if (error && error != EEXIST) {
>> - VLOG_ERR("failed adding ingress qdisc required for offloading: %s",
>> - ovs_strerror(error));
>> + VLOG_INFO("failed adding ingress qdisc required for offloading: %s",
>> + ovs_strerror(error));
>> return error;
>> }
>>
>> @@ -1593,3 +1594,15 @@ netdev_tc_init_flow_api(struct netdev *netdev)
>>
>> return 0;
>> }
>> +
>> +const struct netdev_flow_api netdev_tc_offloads = {
>> + .type = "linux_tc",
>> + .flow_flush = netdev_tc_flow_flush,
>> + .flow_dump_create = netdev_tc_flow_dump_create,
>> + .flow_dump_destroy = netdev_tc_flow_dump_destroy,
>> + .flow_dump_next = netdev_tc_flow_dump_next,
>> + .flow_put = netdev_tc_flow_put,
>> + .flow_get = netdev_tc_flow_get,
>> + .flow_del = netdev_tc_flow_del,
>> + .init_flow_api = netdev_tc_init_flow_api,
>> +};
>> diff --git a/lib/netdev-tc-offloads.h b/lib/netdev-tc-offloads.h
>> deleted file mode 100644
>> index ebd8ca884..000000000
>> --- a/lib/netdev-tc-offloads.h
>> +++ /dev/null
>> @@ -1,44 +0,0 @@
>> -/*
>> - * Copyright (c) 2016 Mellanox Technologies, Ltd.
>> - *
>> - * Licensed under the Apache License, Version 2.0 (the "License");
>> - * you may not use this file except in compliance with the License.
>> - * You may obtain a copy of the License at:
>> - *
>> - *
>> https://eur03.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.apache.org%2Flicenses%2FLICENSE-2.0&data=02%7C01%7Croid%40mellanox.com%7C320331a5f32d437474f908d6d2cdca07%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C0%7C636928178634854039&sdata=%2BVQUoOrR5xFd6smiLUQOIrGGxxHi2FrVoHPkHGQ7hZU%3D&reserved=0
>> - *
>> - * Unless required by applicable law or agreed to in writing, software
>> - * distributed under the License is distributed on an "AS IS" BASIS,
>> - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>> - * See the License for the specific language governing permissions and
>> - * limitations under the License.
>> - */
>> -
>> -#ifndef NETDEV_TC_OFFLOADS_H
>> -#define NETDEV_TC_OFFLOADS_H 1
>> -
>> -#include "netdev-provider.h"
>> -
>> -int netdev_tc_flow_flush(struct netdev *);
>> -int netdev_tc_flow_dump_create(struct netdev *, struct netdev_flow_dump **);
>> -int netdev_tc_flow_dump_destroy(struct netdev_flow_dump *);
>> -bool netdev_tc_flow_dump_next(struct netdev_flow_dump *, struct match *,
>> - struct nlattr **actions,
>> - struct dpif_flow_stats *,
>> - struct dpif_flow_attrs *,
>> - ovs_u128 *ufid,
>> - struct ofpbuf *rbuffer,
>> - struct ofpbuf *wbuffer);
>> -int netdev_tc_flow_put(struct netdev *, struct match *,
>> - struct nlattr *actions, size_t actions_len,
>> - const ovs_u128 *, struct offload_info *,
>> - struct dpif_flow_stats *);
>> -int netdev_tc_flow_get(struct netdev *, struct match *,
>> - struct nlattr **actions, const ovs_u128 *,
>> - struct dpif_flow_stats *,
>> - struct dpif_flow_attrs *, struct ofpbuf *);
>> -int netdev_tc_flow_del(struct netdev *, const ovs_u128 *,
>> - struct dpif_flow_stats *);
>> -int netdev_tc_init_flow_api(struct netdev *);
>> -
>> -#endif /* netdev-tc-offloads.h */
>> diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
>> index ab591667f..92a256af1 100644
>> --- a/lib/netdev-vport.c
>> +++ b/lib/netdev-vport.c
>> @@ -47,7 +47,6 @@
>> #include "unaligned.h"
>> #include "unixctl.h"
>> #include "openvswitch/vlog.h"
>> -#include "netdev-tc-offloads.h"
>> #ifdef __linux__
>> #include "netdev-linux.h"
>> #endif
>> @@ -1116,10 +1115,8 @@ netdev_vport_get_ifindex(const struct netdev *netdev_)
>> }
>>
>> #define NETDEV_VPORT_GET_IFINDEX netdev_vport_get_ifindex
>> -#define NETDEV_FLOW_OFFLOAD_API , LINUX_FLOW_OFFLOAD_API
>> #else /* !__linux__ */
>> #define NETDEV_VPORT_GET_IFINDEX NULL
>> -#define NETDEV_FLOW_OFFLOAD_API
>> #endif /* __linux__ */
>>
>> #define VPORT_FUNCTIONS_COMMON \
>> @@ -1133,8 +1130,7 @@ netdev_vport_get_ifindex(const struct netdev *netdev_)
>> .get_etheraddr = netdev_vport_get_etheraddr, \
>> .get_stats = netdev_vport_get_stats, \
>> .get_pt_mode = netdev_vport_get_pt_mode, \
>> - .update_flags = netdev_vport_update_flags \
>> - NETDEV_FLOW_OFFLOAD_API
>> + .update_flags = netdev_vport_update_flags
>>
>> #define TUNNEL_FUNCTIONS_COMMON \
>> VPORT_FUNCTIONS_COMMON, \
>> diff --git a/lib/netdev.c b/lib/netdev.c
>> index 7d7ecf6f0..de40f72d8 100644
>> --- a/lib/netdev.c
>> +++ b/lib/netdev.c
>> @@ -39,6 +39,7 @@
>> #include "fatal-signal.h"
>> #include "hash.h"
>> #include "openvswitch/list.h"
>> +#include "netdev-offload-provider.h"
>> #include "netdev-provider.h"
>> #include "netdev-vport.h"
>> #include "odp-netlink.h"
>> @@ -98,6 +99,22 @@ struct netdev_registered_class {
>>
>> static bool netdev_flow_api_enabled = false;
>>
>> +/* Protects 'netdev_flow_apis'. */
>> +static struct ovs_mutex netdev_flow_api_provider_mutex =
>> OVS_MUTEX_INITIALIZER;
>> +
>> +/* Contains 'struct netdev_registered_flow_api's. */
>> +static struct cmap netdev_flow_apis = CMAP_INITIALIZER;
>> +
>> +struct netdev_registered_flow_api {
>> + struct cmap_node cmap_node; /* In 'netdev_flow_apis', by
>> flow_api->type. */
>> + const struct netdev_flow_api *flow_api;
>> +
>> + /* Number of references: one for the flow_api itself and one for every
>> + * instance of the netdev that uses it. */
>> + struct ovs_refcount refcnt;
>> +};
>> +
>> +
>> /* This is set pretty low because we probably won't learn anything from the
>> * additional log messages. */
>> static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
>> @@ -146,6 +163,8 @@ netdev_initialize(void)
>> netdev_register_provider(&netdev_internal_class);
>> netdev_register_provider(&netdev_tap_class);
>> netdev_vport_tunnel_register();
>> +
>> + netdev_register_flow_api_provider(&netdev_tc_offloads);
>> #endif
>> #if defined(__FreeBSD__) || defined(__NetBSD__)
>> netdev_register_provider(&netdev_tap_class);
>> @@ -279,6 +298,87 @@ netdev_unregister_provider(const char *type)
>> return error;
>> }
>>
>> +static struct netdev_registered_flow_api *
>> +netdev_lookup_flow_api(const char *type)
>> +{
>> + struct netdev_registered_flow_api *rfa;
>> + CMAP_FOR_EACH_WITH_HASH (rfa, cmap_node, hash_string(type, 0),
>> + &netdev_flow_apis) {
>> + if (!strcmp(type, rfa->flow_api->type)) {
>> + return rfa;
>> + }
>> + }
>> + return NULL;
>> +}
>> +
>> +/* Registers a new netdev flow api provider. */
>> +int
>> +netdev_register_flow_api_provider(const struct netdev_flow_api
>> *new_flow_api)
>> + OVS_EXCLUDED(netdev_flow_api_provider_mutex)
>> +{
>> + int error = 0;
>> +
>> + if (!new_flow_api->init_flow_api) {
>> + VLOG_WARN("attempted to register invalid flow api provider: %s",
>> + new_flow_api->type);
>> + error = EINVAL;
>> + }
>> +
>> + ovs_mutex_lock(&netdev_flow_api_provider_mutex);
>> + if (netdev_lookup_flow_api(new_flow_api->type)) {
>> + VLOG_WARN("attempted to register duplicate flow api provider: %s",
>> + new_flow_api->type);
>> + error = EEXIST;
>> + } else {
>> + struct netdev_registered_flow_api *rfa;
>> +
>> + rfa = xmalloc(sizeof *rfa);
>> + cmap_insert(&netdev_flow_apis, &rfa->cmap_node,
>> + hash_string(new_flow_api->type, 0));
>> + rfa->flow_api = new_flow_api;
>> + ovs_refcount_init(&rfa->refcnt);
>> + VLOG_DBG("netdev: flow API '%s' registered.", new_flow_api->type);
>> + }
>> + ovs_mutex_unlock(&netdev_flow_api_provider_mutex);
>> +
>> + return error;
>> +}
>> +
>> +/* Unregisters a netdev flow api provider. 'type' must have been previously
>> + * registered and not currently be in use by any netdevs. After
>> unregistration
>> + * netdev flow api of that type cannot be used for netdevs. (However, the
>> + * provider may still be accessible from other threads until the next RCU
>> grace
>> + * period, so the caller must not free or re-register the same
>> netdev_flow_api
>> + * until that has passed.) */
>> +int
>> +netdev_unregister_flow_api_provider(const char *type)
>> + OVS_EXCLUDED(netdev_flow_api_provider_mutex)
>> +{
>> + struct netdev_registered_flow_api *rfa;
>> + int error;
>> +
>> + ovs_mutex_lock(&netdev_flow_api_provider_mutex);
>> + rfa = netdev_lookup_flow_api(type);
>> + if (!rfa) {
>> + VLOG_WARN("attempted to unregister a flow api provider that is not "
>> + "registered: %s", type);
>> + error = EAFNOSUPPORT;
>> + } else if (ovs_refcount_unref(&rfa->refcnt) != 1) {
>> + ovs_refcount_ref(&rfa->refcnt);
>> + VLOG_WARN("attempted to unregister in use flow api provider: %s",
>> + type);
>> + error = EBUSY;
>> + } else {
>> + cmap_remove(&netdev_flow_apis, &rfa->cmap_node,
>> + hash_string(rfa->flow_api->type, 0));
>> + ovsrcu_postpone(free, rfa);
>> + error = 0;
>> + }
>> + ovs_mutex_unlock(&netdev_flow_api_provider_mutex);
>> +
>> + return error;
>> +}
>> +
>> /* Clears 'types' and enumerates the types of all currently registered
>> netdev
>> * providers into it. The caller must first initialize the sset. */
>> void
>> @@ -414,6 +514,7 @@ netdev_open(const char *name, const char *type, struct
>> netdev **netdevp)
>> netdev->reconfigure_seq = seq_create();
>> netdev->last_reconfigure_seq =
>> seq_read(netdev->reconfigure_seq);
>> + ovsrcu_set(&netdev->flow_api, NULL);
>> netdev->hw_info.oor = false;
>> netdev->node = shash_add(&netdev_shash, name, netdev);
>>
>> @@ -562,6 +663,8 @@ netdev_unref(struct netdev *dev)
>> ovs_assert(dev->ref_cnt);
>> if (!--dev->ref_cnt) {
>> const struct netdev_class *class = dev->netdev_class;
>> + const struct netdev_flow_api *flow_api =
>> + ovsrcu_get(const struct netdev_flow_api *, &dev->flow_api);
>> struct netdev_registered_class *rc;
>>
>> dev->netdev_class->destruct(dev);
>> @@ -576,6 +679,12 @@ netdev_unref(struct netdev *dev)
>>
>> rc = netdev_lookup_class(class->type);
>> ovs_refcount_unref(&rc->refcnt);
>> +
>> + if (flow_api) {
>> + struct netdev_registered_flow_api *rfa =
>> + netdev_lookup_flow_api(flow_api->type);
>> + ovs_refcount_unref(&rfa->refcnt);
>> + }
>> } else {
>> ovs_mutex_unlock(&netdev_mutex);
>> }
>> @@ -2148,34 +2257,58 @@ netdev_reconfigure(struct netdev *netdev)
>> : EOPNOTSUPP);
>> }
>>
>> +static int
>> +netdev_assign_flow_api(struct netdev *netdev)
>> +{
>> + struct netdev_registered_flow_api *rfa;
>> +
>> + CMAP_FOR_EACH (rfa, cmap_node, &netdev_flow_apis) {
>> + if (!rfa->flow_api->init_flow_api(netdev)) {
>> + ovs_refcount_ref(&rfa->refcnt);
>> + ovsrcu_set(&netdev->flow_api, rfa->flow_api);
>> + VLOG_INFO("%s: Assigned flow API '%s'.",
>> + netdev_get_name(netdev), rfa->flow_api->type);
>> + return 0;
>> + }
>> + VLOG_DBG("%s: flow API '%s' is not suitable.",
>> + netdev_get_name(netdev), rfa->flow_api->type);
>> + }
>> + VLOG_INFO("%s: No suitable flow API found.", netdev_get_name(netdev));
>> +
>> + return -1;
>> +}
>> +
>> int
>> netdev_flow_flush(struct netdev *netdev)
>> {
>> - const struct netdev_class *class = netdev->netdev_class;
>> + const struct netdev_flow_api *flow_api =
>> + ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api);
>>
>> - return (class->flow_flush
>> - ? class->flow_flush(netdev)
>> - : EOPNOTSUPP);
>> + return (flow_api && flow_api->flow_flush)
>> + ? flow_api->flow_flush(netdev)
>> + : EOPNOTSUPP;
>> }
>>
>> int
>> netdev_flow_dump_create(struct netdev *netdev, struct netdev_flow_dump
>> **dump)
>> {
>> - const struct netdev_class *class = netdev->netdev_class;
>> + const struct netdev_flow_api *flow_api =
>> + ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api);
>>
>> - return (class->flow_dump_create
>> - ? class->flow_dump_create(netdev, dump)
>> - : EOPNOTSUPP);
>> + return (flow_api && flow_api->flow_dump_create)
>> + ? flow_api->flow_dump_create(netdev, dump)
>> + : EOPNOTSUPP;
>> }
>>
>> int
>> netdev_flow_dump_destroy(struct netdev_flow_dump *dump)
>> {
>> - const struct netdev_class *class = dump->netdev->netdev_class;
>> + const struct netdev_flow_api *flow_api =
>> + ovsrcu_get(const struct netdev_flow_api *, &dump->netdev->flow_api);
>>
>> - return (class->flow_dump_destroy
>> - ? class->flow_dump_destroy(dump)
>> - : EOPNOTSUPP);
>> + return (flow_api && flow_api->flow_dump_destroy)
>> + ? flow_api->flow_dump_destroy(dump)
>> + : EOPNOTSUPP;
>> }
>>
>> bool
>> @@ -2184,12 +2317,13 @@ netdev_flow_dump_next(struct netdev_flow_dump *dump,
>> struct match *match,
>> struct dpif_flow_attrs *attrs, ovs_u128 *ufid,
>> struct ofpbuf *rbuffer, struct ofpbuf *wbuffer)
>> {
>> - const struct netdev_class *class = dump->netdev->netdev_class;
>> + const struct netdev_flow_api *flow_api =
>> + ovsrcu_get(const struct netdev_flow_api *, &dump->netdev->flow_api);
>>
>> - return (class->flow_dump_next
>> - ? class->flow_dump_next(dump, match, actions, stats, attrs,
>> - ufid, rbuffer, wbuffer)
>> - : false);
>> + return (flow_api && flow_api->flow_dump_next)
>> + ? flow_api->flow_dump_next(dump, match, actions, stats, attrs,
>> + ufid, rbuffer, wbuffer)
>> + : false;
>> }
>>
>> int
>> @@ -2198,12 +2332,13 @@ netdev_flow_put(struct netdev *netdev, struct match
>> *match,
>> const ovs_u128 *ufid, struct offload_info *info,
>> struct dpif_flow_stats *stats)
>> {
>> - const struct netdev_class *class = netdev->netdev_class;
>> + const struct netdev_flow_api *flow_api =
>> + ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api);
>>
>> - return (class->flow_put
>> - ? class->flow_put(netdev, match, actions, act_len, ufid,
>> - info, stats)
>> - : EOPNOTSUPP);
>> + return (flow_api && flow_api->flow_put)
>> + ? flow_api->flow_put(netdev, match, actions, act_len, ufid,
>> + info, stats)
>> + : EOPNOTSUPP;
>> }
>>
>> int
>> @@ -2212,36 +2347,43 @@ netdev_flow_get(struct netdev *netdev, struct match
>> *match,
>> struct dpif_flow_stats *stats,
>> struct dpif_flow_attrs *attrs, struct ofpbuf *buf)
>> {
>> - const struct netdev_class *class = netdev->netdev_class;
>> + const struct netdev_flow_api *flow_api =
>> + ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api);
>>
>> - return (class->flow_get
>> - ? class->flow_get(netdev, match, actions, ufid, stats, attrs,
>> buf)
>> - : EOPNOTSUPP);
>> + return (flow_api && flow_api->flow_get)
>> + ? flow_api->flow_get(netdev, match, actions, ufid,
>> + stats, attrs, buf)
>> + : EOPNOTSUPP;
>> }
>>
>> int
>> netdev_flow_del(struct netdev *netdev, const ovs_u128 *ufid,
>> struct dpif_flow_stats *stats)
>> {
>> - const struct netdev_class *class = netdev->netdev_class;
>> + const struct netdev_flow_api *flow_api =
>> + ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api);
>>
>> - return (class->flow_del
>> - ? class->flow_del(netdev, ufid, stats)
>> - : EOPNOTSUPP);
>> + return (flow_api && flow_api->flow_del)
>> + ? flow_api->flow_del(netdev, ufid, stats)
>> + : EOPNOTSUPP;
>> }
>>
>> int
>> netdev_init_flow_api(struct netdev *netdev)
>> {
>> - const struct netdev_class *class = netdev->netdev_class;
>> -
>> if (!netdev_is_flow_api_enabled()) {
>> return EOPNOTSUPP;
>> }
>>
>> - return (class->init_flow_api
>> - ? class->init_flow_api(netdev)
>> - : EOPNOTSUPP);
>> + if (ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api)) {
>> + return 0;
>> + }
>> +
>> + if (netdev_assign_flow_api(netdev)) {
>> + return EOPNOTSUPP;
>> + }
>> +
>> + return 0;
>> }
>>
>> uint32_t
>> @@ -2573,7 +2715,6 @@ netdev_is_offload_rebalance_policy_enabled(void)
>> return netdev_offload_rebalance_policy;
>> }
>>
>> -#ifdef __linux__
>> static void
>> netdev_ports_flow_init(void)
>> {
>> @@ -2597,8 +2738,10 @@ netdev_set_flow_api_enabled(const struct smap
>> *ovs_other_config)
>>
>> VLOG_INFO("netdev: Flow API Enabled");
>>
>> +#ifdef __linux__
>> tc_set_policy(smap_get_def(ovs_other_config, "tc-policy",
>> TC_POLICY_DEFAULT));
>> +#endif
>>
>> if (smap_get_bool(ovs_other_config, "offload-rebalance",
>> false)) {
>> netdev_offload_rebalance_policy = true;
>> @@ -2610,9 +2753,3 @@ netdev_set_flow_api_enabled(const struct smap
>> *ovs_other_config)
>> }
>> }
>> }
>> -#else
>> -void
>> -netdev_set_flow_api_enabled(const struct smap *ovs_other_config OVS_UNUSED)
>> -{
>> -}
>> -#endif
>> diff --git a/tests/dpif-netdev.at b/tests/dpif-netdev.at
>> index 039ee971b..af8a29e44 100644
>> --- a/tests/dpif-netdev.at
>> +++ b/tests/dpif-netdev.at
>> @@ -361,9 +361,9 @@ AT_CLEANUP
>>
>> m4_define([DPIF_NETDEV_FLOW_HW_OFFLOAD],
>> [AT_SETUP([dpif-netdev - partial hw offload - $1])
>> - AT_SKIP_IF([test "$IS_WIN32" = "yes" || test "$IS_BSD" = "yes"])
>> OVS_VSWITCHD_START(
>> - [add-port br0 p1 -- set interface p1 type=$1 ofport_request=1
>> options:pstream=punix:$OVS_RUNDIR/p1.sock -- \
>> + [add-port br0 p1 -- \
>> + set interface p1 type=$1 ofport_request=1
>> options:pstream=punix:$OVS_RUNDIR/p1.sock options:ifindex=1 -- \
>> set bridge br0 datapath-type=dummy \
>> other-config:datapath-id=1234 fail-mode=secure], [],
>> [],
>> [m4_if([$1], [dummy-pmd], [--dummy-numa="0,0,0,0,1,1,1,1"], [])])
>> diff --git a/tests/ofproto-macros.at b/tests/ofproto-macros.at
>> index 2f33feabc..d0101b532 100644
>> --- a/tests/ofproto-macros.at
>> +++ b/tests/ofproto-macros.at
>> @@ -350,7 +350,6 @@ m4_define([_OVS_VSWITCHD_START],
>> /ofproto|INFO|datapath ID changed to fedcba9876543210/d
>> /dpdk|INFO|DPDK Disabled - Use other_config:dpdk-init to enable/d
>> /netlink_socket|INFO|netlink: could not enable listening to all nsid/d
>> -/netdev: Flow API/d
>> /probe tc:/d
>> /tc: Using policy/d']])
>> ])
>>
>
>
> Hi,
>
> I did a quick ping test between two ports and after this commit the
> command ovs-dpctl dump-flows doesn't show the flows that are in tc.
> which did work before the commit.
> ovs-appctl dpctl/dump-flows does show the flows fine.
>
> I didn't have time to help debug but I'll try to help tomorrow.
>
> Thanks,
> Roi
>
could be ovs-dpctl which is a standalone doesn't ever call
netdev_run()->netdev_initialize()->netdev_register_flow_api_provider() ?
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev