@@ -79,7 +79,6 @@ enum { MAX_PORTS = USHRT_MAX };
* missing if we have old headers. */
#define ETH_FLAG_LRO (1 << 15) /* LRO is enabled */
-#define FLOW_DUMP_MAX_BATCH 50
#define OPERATE_MAX_OPS 50
#ifndef EPOLLEXCLUSIVE
@@ -1602,11 +1601,6 @@ struct dpif_netlink_flow_dump {
struct dpif_flow_dump up;
struct nl_dump nl_dump;
atomic_int status;
- struct netdev_flow_dump **netdev_dumps;
- int netdev_dumps_num; /* Number of netdev_flow_dumps */
- struct ovs_mutex netdev_lock; /* Guards the following. */
- int netdev_current_dump OVS_GUARDED; /* Shared current dump */
- struct dpif_flow_dump_types types; /* Type of dump */
};
static struct dpif_netlink_flow_dump *
@@ -1615,39 +1609,6 @@ dpif_netlink_flow_dump_cast(struct dpif_flow_dump *dump)
return CONTAINER_OF(dump, struct dpif_netlink_flow_dump, up);
}
-static void
-start_netdev_dump(const struct dpif *dpif_,
- struct dpif_netlink_flow_dump *dump)
-{
- ovs_mutex_init(&dump->netdev_lock);
-
- if (!(dump->types.offloaded_flows)) {
- dump->netdev_dumps_num = 0;
- dump->netdev_dumps = NULL;
- return;
- }
-
- ovs_mutex_lock(&dump->netdev_lock);
- dump->netdev_current_dump = 0;
- dump->netdev_dumps
- = netdev_ports_flow_dump_create(dpif_normalize_type(dpif_type(dpif_)),
- &dump->netdev_dumps_num,
- dump->up.terse);
- ovs_mutex_unlock(&dump->netdev_lock);
-}
-
-static void
-dpif_netlink_populate_flow_dump_types(struct dpif_netlink_flow_dump *dump,
- struct dpif_flow_dump_types *types)
-{
- if (!types) {
- dump->types.ovs_flows = true;
- dump->types.offloaded_flows = true;
- } else {
- memcpy(&dump->types, types, sizeof *types);
- }
-}
-
static struct dpif_flow_dump *
dpif_netlink_flow_dump_create(const struct dpif *dpif_, bool terse,
struct dpif_flow_dump_types *types)
@@ -1660,24 +1621,18 @@ dpif_netlink_flow_dump_create(const struct dpif *dpif_, bool terse,
dump = xmalloc(sizeof *dump);
dpif_flow_dump_init(&dump->up, dpif_, terse, types);
- dpif_netlink_populate_flow_dump_types(dump, types);
-
- if (dump->types.ovs_flows) {
- dpif_netlink_flow_init(&request);
- request.cmd = OVS_FLOW_CMD_GET;
- request.dp_ifindex = dpif->dp_ifindex;
- request.ufid_present = false;
- request.ufid_terse = terse;
+ dpif_netlink_flow_init(&request);
+ request.cmd = OVS_FLOW_CMD_GET;
+ request.dp_ifindex = dpif->dp_ifindex;
+ request.ufid_present = false;
+ request.ufid_terse = terse;
- buf = ofpbuf_new(1024);
- dpif_netlink_flow_to_ofpbuf(&request, buf);
- nl_dump_start(&dump->nl_dump, NETLINK_GENERIC, buf);
- ofpbuf_delete(buf);
- }
+ buf = ofpbuf_new(1024);
+ dpif_netlink_flow_to_ofpbuf(&request, buf);
+ nl_dump_start(&dump->nl_dump, NETLINK_GENERIC, buf);
+ ofpbuf_delete(buf);
atomic_init(&dump->status, 0);
- start_netdev_dump(dpif_, dump);
-
return &dump->up;
}
@@ -1685,24 +1640,9 @@ static int
dpif_netlink_flow_dump_destroy(struct dpif_flow_dump *dump_)
{
struct dpif_netlink_flow_dump *dump = dpif_netlink_flow_dump_cast(dump_);
- unsigned int nl_status = 0;
+ unsigned int nl_status = nl_dump_done(&dump->nl_dump);
int dump_status;
- if (dump->types.ovs_flows) {
- nl_status = nl_dump_done(&dump->nl_dump);
- }
-
- for (int i = 0; i < dump->netdev_dumps_num; i++) {
- int err = netdev_flow_dump_destroy(dump->netdev_dumps[i]);
-
- if (err != 0 && err != EOPNOTSUPP) {
- VLOG_ERR("failed dumping netdev: %s", ovs_strerror(err));
- }
- }
-
- free(dump->netdev_dumps);
- ovs_mutex_destroy(&dump->netdev_lock);
-
/* No other thread has access to 'dump' at this point. */
atomic_read_relaxed(&dump->status, &dump_status);
free(dump);
@@ -1716,13 +1656,6 @@ struct dpif_netlink_flow_dump_thread {
struct dpif_flow_stats stats;
struct ofpbuf nl_flows; /* Always used to store flows. */
struct ofpbuf *nl_actions; /* Used if kernel does not supply actions. */
- int netdev_dump_idx; /* This thread current netdev dump index */
- bool netdev_done; /* If we are finished dumping netdevs */
-
- /* (Key/Mask/Actions) Buffers for netdev dumping */
- struct odputil_keybuf keybuf[FLOW_DUMP_MAX_BATCH];
- struct odputil_keybuf maskbuf[FLOW_DUMP_MAX_BATCH];
- struct odputil_keybuf actbuf[FLOW_DUMP_MAX_BATCH];
};
static struct dpif_netlink_flow_dump_thread *
@@ -1742,8 +1675,6 @@ dpif_netlink_flow_dump_thread_create(struct dpif_flow_dump *dump_)
thread->dump = dump;
ofpbuf_init(&thread->nl_flows, NL_DUMP_BUFSIZE);
thread->nl_actions = NULL;
- thread->netdev_dump_idx = 0;
- thread->netdev_done = !(thread->netdev_dump_idx < dump->netdev_dumps_num);
return &thread->up;
}
@@ -1784,39 +1715,6 @@ dpif_netlink_flow_to_dpif_flow(struct dpif_flow *dpif_flow,
dpif_flow->attrs.dp_extra_info = NULL;
}
-/* The design is such that all threads are working together on the first dump
- * to the last, in order (at first they all on dump 0).
- * When the first thread finds that the given dump is finished,
- * they all move to the next. If two or more threads find the same dump
- * is finished at the same time, the first one will advance the shared
- * netdev_current_dump and the others will catch up. */
-static void
-dpif_netlink_advance_netdev_dump(struct dpif_netlink_flow_dump_thread *thread)
-{
- struct dpif_netlink_flow_dump *dump = thread->dump;
-
- ovs_mutex_lock(&dump->netdev_lock);
- /* if we haven't finished (dumped everything) */
- if (dump->netdev_current_dump < dump->netdev_dumps_num) {
- /* if we are the first to find that current dump is finished
- * advance it. */
- if (thread->netdev_dump_idx == dump->netdev_current_dump) {
- thread->netdev_dump_idx = ++dump->netdev_current_dump;
- /* did we just finish the last dump? done. */
- if (dump->netdev_current_dump == dump->netdev_dumps_num) {
- thread->netdev_done = true;
- }
- } else {
- /* otherwise, we are behind, catch up */
- thread->netdev_dump_idx = dump->netdev_current_dump;
- }
- } else {
- /* some other thread finished */
- thread->netdev_done = true;
- }
- ovs_mutex_unlock(&dump->netdev_lock);
-}
-
static int
dpif_netlink_netdev_match_to_dpif_flow(struct match *match,
struct ofpbuf *key_buf,
@@ -1885,56 +1783,11 @@ dpif_netlink_flow_dump_next(struct dpif_flow_dump_thread *thread_,
= dpif_netlink_flow_dump_thread_cast(thread_);
struct dpif_netlink_flow_dump *dump = thread->dump;
struct dpif_netlink *dpif = dpif_netlink_cast(thread->up.dump->dpif);
- int n_flows;
+ int n_flows = 0;
ofpbuf_delete(thread->nl_actions);
thread->nl_actions = NULL;
- n_flows = 0;
- max_flows = MIN(max_flows, FLOW_DUMP_MAX_BATCH);
-
- while (!thread->netdev_done && n_flows < max_flows) {
- struct odputil_keybuf *maskbuf = &thread->maskbuf[n_flows];
- struct odputil_keybuf *keybuf = &thread->keybuf[n_flows];
- struct odputil_keybuf *actbuf = &thread->actbuf[n_flows];
- struct ofpbuf key, mask, act;
- struct dpif_flow *f = &flows[n_flows];
- int cur = thread->netdev_dump_idx;
- struct netdev_flow_dump *netdev_dump = dump->netdev_dumps[cur];
- struct match match;
- struct nlattr *actions;
- struct dpif_flow_stats stats;
- struct dpif_flow_attrs attrs;
- ovs_u128 ufid;
- bool has_next;
-
- ofpbuf_use_stack(&key, keybuf, sizeof *keybuf);
- ofpbuf_use_stack(&act, actbuf, sizeof *actbuf);
- ofpbuf_use_stack(&mask, maskbuf, sizeof *maskbuf);
- has_next = netdev_flow_dump_next(netdev_dump, &match,
- &actions, &stats, &attrs,
- &ufid,
- &thread->nl_flows,
- &act);
- if (has_next) {
- dpif_netlink_netdev_match_to_dpif_flow(&match,
- &key, &mask,
- actions,
- &stats,
- &attrs,
- &ufid,
- f,
- dump->up.terse);
- n_flows++;
- } else {
- dpif_netlink_advance_netdev_dump(thread);
- }
- }
-
- if (!(dump->types.ovs_flows)) {
- return n_flows;
- }
-
while (!n_flows
|| (n_flows < max_flows && thread->nl_flows.size)) {
struct dpif_netlink_flow datapath_flow;
@@ -48,7 +48,7 @@ struct dpif_offload_tc_flow_dump {
struct ovs_mutex netdev_dump_mutex;
size_t netdev_dump_index;
size_t netdev_dump_count;
- struct netdev_flow_dump *netdev_dumps[];
+ struct netdev_tc_flow_dump *netdev_dumps[];
};
#define FLOW_DUMP_MAX_BATCH 50
@@ -333,7 +333,7 @@ dpif_offload_tc_flow_dump_create(const struct dpif_offload *offload_,
port_count = dpif_offload_port_mgr_port_count(offload->port_mgr);
dump = xmalloc(sizeof *dump +
- (port_count * sizeof(struct netdev_flow_dump)));
+ (port_count * sizeof(struct netdev_tc_flow_dump)));
dpif_offload_flow_dump_init(&dump->dump, offload_, terse);
@@ -458,8 +458,8 @@ dpif_offload_tc_flow_dump_next(struct dpif_offload_flow_dump_thread *thread_,
struct odputil_keybuf *maskbuf = &thread->maskbuf[n_flows];
struct odputil_keybuf *keybuf = &thread->keybuf[n_flows];
struct odputil_keybuf *actbuf = &thread->actbuf[n_flows];
+ struct netdev_tc_flow_dump *netdev_dump;
struct dpif_flow *f = &flows[n_flows];
- struct netdev_flow_dump *netdev_dump;
int cur = thread->netdev_dump_index;
struct ofpbuf key, mask, act;
struct dpif_flow_stats stats;
@@ -505,7 +505,7 @@ dpif_offload_tc_flow_dump_destroy(struct dpif_offload_flow_dump *dump_)
dump = dpif_offload_tc_flow_dump_cast(dump_);
for (int i = 0; i < dump->netdev_dump_count; i++) {
- struct netdev_flow_dump *dump_netdev = dump->netdev_dumps[i];
+ struct netdev_tc_flow_dump *dump_netdev = dump->netdev_dumps[i];
int rc = netdev_offload_tc_flow_dump_destroy(dump_netdev);
if (rc && !error) {
@@ -31,29 +31,6 @@ extern "C" {
struct netdev_flow_api {
char *type;
- /* 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,
- bool terse);
- 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.
@@ -501,7 +501,7 @@ static int
get_chains_from_netdev(struct netdev *netdev, struct tcf_id *id,
struct hmap *map)
{
- struct netdev_flow_dump *dump;
+ struct netdev_tc_flow_dump *dump;
struct chain_node *chain_node;
struct ofpbuf rbuffer, reply;
uint32_t chain;
@@ -588,11 +588,11 @@ netdev_offload_tc_flow_flush(struct netdev *netdev)
int
netdev_offload_tc_flow_dump_create(struct netdev *netdev,
- struct netdev_flow_dump **dump_out,
+ struct netdev_tc_flow_dump **dump_out,
bool terse)
{
enum tc_qdisc_hook hook = get_tc_qdisc_hook(netdev);
- struct netdev_flow_dump *dump;
+ struct netdev_tc_flow_dump *dump;
uint32_t block_id = 0;
struct tcf_id id;
int prio = 0;
@@ -619,7 +619,7 @@ netdev_offload_tc_flow_dump_create(struct netdev *netdev,
return 0;
}
int
-netdev_offload_tc_flow_dump_destroy(struct netdev_flow_dump *dump)
+netdev_offload_tc_flow_dump_destroy(struct netdev_tc_flow_dump *dump)
{
nl_dump_done(dump->nl_dump);
netdev_close(dump->netdev);
@@ -1351,7 +1351,7 @@ parse_tc_flower_to_match(const struct netdev *netdev,
}
bool
-netdev_offload_tc_flow_dump_next(struct netdev_flow_dump *dump,
+netdev_offload_tc_flow_dump_next(struct netdev_tc_flow_dump *dump,
struct match *match,
struct nlattr **actions,
struct dpif_flow_stats *stats,
@@ -3070,7 +3070,7 @@ tc_get_policer_action_ids(struct hmap *map)
{
uint32_t police_idx[TCA_ACT_MAX_PRIO];
struct policer_node *policer_node;
- struct netdev_flow_dump *dump;
+ struct netdev_tc_flow_dump *dump;
struct ofpbuf rbuffer, reply;
size_t hash;
int i, err;
@@ -21,13 +21,22 @@
struct dpif_offload;
struct netdev;
+/* Per Netdev flow dump structure. */
+struct netdev_tc_flow_dump {
+ struct nl_dump *nl_dump;
+ struct netdev *netdev;
+ odp_port_t port;
+ bool terse;
+};
+
/* Netdev-specific offload functions. These should only be used by the
* associated dpif offload provider. */
int netdev_offload_tc_flow_flush(struct netdev *);
int netdev_offload_tc_flow_dump_create(struct netdev *,
- struct netdev_flow_dump **, bool terse);
-int netdev_offload_tc_flow_dump_destroy(struct netdev_flow_dump *);
-bool netdev_offload_tc_flow_dump_next(struct netdev_flow_dump *,
+ struct netdev_tc_flow_dump **,
+ bool terse);
+int netdev_offload_tc_flow_dump_destroy(struct netdev_tc_flow_dump *);
+bool netdev_offload_tc_flow_dump_next(struct netdev_tc_flow_dump *,
struct match *, struct nlattr **actions,
struct dpif_flow_stats *,
struct dpif_flow_attrs *, ovs_u128 *ufid,
@@ -202,44 +202,6 @@ netdev_assign_flow_api(struct netdev *netdev)
return -1;
}
-int
-netdev_flow_dump_create(struct netdev *netdev, struct netdev_flow_dump **dump,
- bool terse)
-{
- const struct netdev_flow_api *flow_api =
- ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api);
-
- return (flow_api && flow_api->flow_dump_create)
- ? flow_api->flow_dump_create(netdev, dump, terse)
- : EOPNOTSUPP;
-}
-
-int
-netdev_flow_dump_destroy(struct netdev_flow_dump *dump)
-{
- const struct netdev_flow_api *flow_api =
- ovsrcu_get(const struct netdev_flow_api *, &dump->netdev->flow_api);
-
- return (flow_api && flow_api->flow_dump_destroy)
- ? flow_api->flow_dump_destroy(dump)
- : EOPNOTSUPP;
-}
-
-bool
-netdev_flow_dump_next(struct netdev_flow_dump *dump, struct match *match,
- struct nlattr **actions, struct dpif_flow_stats *stats,
- struct dpif_flow_attrs *attrs, ovs_u128 *ufid,
- struct ofpbuf *rbuffer, struct ofpbuf *wbuffer)
-{
- const struct netdev_flow_api *flow_api =
- ovsrcu_get(const struct netdev_flow_api *, &dump->netdev->flow_api);
-
- return (flow_api && flow_api->flow_dump_next)
- ? flow_api->flow_dump_next(dump, match, actions, stats, attrs,
- ufid, rbuffer, wbuffer)
- : false;
-}
-
int
netdev_flow_put(struct netdev *netdev, struct match *match,
struct nlattr *actions, size_t act_len,
@@ -499,45 +461,6 @@ netdev_ports_traverse(const char *dpif_type,
ovs_rwlock_unlock(&port_to_netdev_rwlock);
}
-struct netdev_flow_dump **
-netdev_ports_flow_dump_create(const char *dpif_type, int *ports, bool terse)
-{
- struct netdev_flow_dump **dumps = NULL;
- struct port_to_netdev_data *data;
- int count = 0;
- int i = 0;
-
- ovs_rwlock_rdlock(&port_to_netdev_rwlock);
- HMAP_FOR_EACH (data, portno_node, &port_to_netdev) {
- if (netdev_get_dpif_type(data->netdev) == dpif_type) {
- count++;
- }
- }
-
- if (!count) {
- goto unlock;
- }
-
- dumps = xzalloc(sizeof *dumps * count);
-
- HMAP_FOR_EACH (data, portno_node, &port_to_netdev) {
- if (netdev_get_dpif_type(data->netdev) == dpif_type) {
- if (netdev_flow_dump_create(data->netdev, &dumps[i], terse)) {
- continue;
- }
-
- dumps[i]->port = data->dpif_port.port_no;
- i++;
- }
- }
-
-unlock:
- ovs_rwlock_unlock(&port_to_netdev_rwlock);
-
- *ports = i;
- return dumps;
-}
-
int
netdev_ports_flow_del(const char *dpif_type, const ovs_u128 *ufid,
struct dpif_flow_stats *stats)
@@ -60,13 +60,6 @@ enum hw_info_type {
HW_INFO_TYPE_OFFL_COUNT = 3 /* Offloaded flow count */
};
-struct netdev_flow_dump {
- struct netdev *netdev;
- odp_port_t port;
- bool terse;
- struct nl_dump *nl_dump;
-};
-
/* Flow offloading. */
struct offload_info {
bool recirc_id_shared_with_tc; /* Indicates whever tc chains will be in
@@ -101,13 +94,6 @@ netdev_offload_thread_id(void)
return id;
}
-int netdev_flow_dump_create(struct netdev *, struct netdev_flow_dump **dump,
- bool terse);
-int netdev_flow_dump_destroy(struct netdev_flow_dump *);
-bool netdev_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_flow_put(struct netdev *, struct match *, struct nlattr *actions,
size_t actions_len, const ovs_u128 *,
struct offload_info *, struct dpif_flow_stats *);
@@ -138,10 +124,6 @@ odp_port_t netdev_ifindex_to_odp_port(int ifindex);
void netdev_ports_traverse(const char *dpif_type,
bool (*cb)(struct netdev *, odp_port_t, void *),
void *aux);
-struct netdev_flow_dump **netdev_ports_flow_dump_create(
- const char *dpif_type,
- int *ports,
- bool terse);
int netdev_ports_flow_del(const char *dpif_type, const ovs_u128 *ufid,
struct dpif_flow_stats *stats);
int netdev_ports_flow_get(const char *dpif_type, struct match *match,
This patch removes the legacy integration between dpif-netlink and netlink-offload. All netdev flow dump structures, flow dump APIs, and supporting code related to offloaded flows in dpif-netlink and netdev-offload have been removed, as (tc) flow offload is now handled entirely through dpif-offload. This simplifies dpif-netlink by decoupling it from all it's offload logic. Signed-off-by: Eelco Chaudron <echaudro@redhat.com> --- lib/dpif-netlink.c | 169 +++------------------------------- lib/dpif-offload-tc.c | 8 +- lib/netdev-offload-provider.h | 23 ----- lib/netdev-offload-tc.c | 12 +-- lib/netdev-offload-tc.h | 15 ++- lib/netdev-offload.c | 77 ---------------- lib/netdev-offload.h | 18 ---- 7 files changed, 33 insertions(+), 289 deletions(-)