On 19 April 2017 at 07:38, Roi Dayan <r...@mellanox.com> wrote: > > > On 14/04/2017 03:51, Joe Stringer wrote: >> >> On 7 April 2017 at 06:12, Roi Dayan <r...@mellanox.com> wrote: >>> >>> From: Paul Blakey <pa...@mellanox.com> >>> >>> While dumping flows, dump flows that were offloaded to >>> netdev and parse them back to dpif flow. >>> >>> Signed-off-by: Paul Blakey <pa...@mellanox.com> >>> Reviewed-by: Roi Dayan <r...@mellanox.com> >>> Reviewed-by: Simon Horman <simon.hor...@netronome.com> >>> --- >>> lib/dpif-netlink.c | 179 >>> ++++++++++++++++++++++++++++++++++++++++++++++++++++- >>> lib/netdev.c | 32 ++++++++++ >>> 2 files changed, 210 insertions(+), 1 deletion(-) >>> >>> diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c >>> index 02dd6c2..4e3bc8c 100644 >>> --- a/lib/dpif-netlink.c >>> +++ b/lib/dpif-netlink.c >>> @@ -38,6 +38,7 @@ >>> #include "flow.h" >>> #include "fat-rwlock.h" >>> #include "netdev.h" >>> +#include "netdev-provider.h" >>> #include "netdev-linux.h" >>> #include "netdev-vport.h" >>> #include "netlink-conntrack.h" >>> @@ -55,6 +56,7 @@ >>> #include "unaligned.h" >>> #include "util.h" >>> #include "openvswitch/vlog.h" >>> +#include "openvswitch/match.h" >>> >>> VLOG_DEFINE_THIS_MODULE(dpif_netlink); >>> #ifdef _WIN32 >>> @@ -72,6 +74,8 @@ 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 >>> + >>> struct dpif_netlink_dp { >>> /* Generic Netlink header. */ >>> uint8_t cmd; >>> @@ -1373,6 +1377,10 @@ 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 */ >>> }; >>> >>> static struct dpif_netlink_flow_dump * >>> @@ -1381,6 +1389,26 @@ 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 (!netdev_flow_api_enabled) { >>> + 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_dumps_create(DPIF_HMAP_KEY(dpif_), >>> + &dump->netdev_dumps_num); >>> + ovs_mutex_unlock(&dump->netdev_lock); >>> +} >>> + >>> static struct dpif_flow_dump * >>> dpif_netlink_flow_dump_create(const struct dpif *dpif_, bool terse) >>> { >>> @@ -1405,6 +1433,8 @@ dpif_netlink_flow_dump_create(const struct dpif >>> *dpif_, bool terse) >>> atomic_init(&dump->status, 0); >>> dump->up.terse = terse; >>> >>> + start_netdev_dump(dpif_, dump); >>> + >>> return &dump->up; >>> } >>> >>> @@ -1415,6 +1445,16 @@ dpif_netlink_flow_dump_destroy(struct >>> dpif_flow_dump *dump_) >>> unsigned int nl_status = nl_dump_done(&dump->nl_dump); >>> int dump_status; >>> >>> + 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); >>> @@ -1428,6 +1468,13 @@ 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 * >>> @@ -1447,6 +1494,8 @@ 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; >>> } >>> @@ -1484,6 +1533,96 @@ dpif_netlink_flow_to_dpif_flow(struct dpif *dpif, >>> struct dpif_flow *dpif_flow, >>> dpif_netlink_flow_get_stats(datapath_flow, &dpif_flow->stats); >>> } >>> >>> +/* 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 struct odp_support netdev_flow_support = { >>> + .max_mpls_depth = SIZE_MAX, >>> + .recirc = false, >>> + .ct_state = false, >>> + .ct_zone = false, >>> + .ct_mark = false, >>> + .ct_label = false, >>> +}; >> >> >> Perhaps we should add a comment above this structure to state how it's >> only used for translating netdev flows into dpif flows, and current >> implementations of the netdev flow interface don't support these >> features so it's not relevant to serialize those fields into the >> nlattr-formatted buffers in the function below? > > > I think we don't actually need this. can just reset support to zero as we > don't support any of those attributes for now. > We'll bring this back when we actually will support those.
OK sure, that works too. _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev