2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-03 15:55:19 +00:00

dpctl: Properly reflect a rule's offloaded to HW state

Previously, any rule that is offloaded via a netdev, not necessarily
to the HW, would be reported as "offloaded". This patch fixes this
misalignment, and introduces the 'dp' state, as follows:

rule is in HW via TC offload  -> offloaded=yes dp:tc
rule is in not HW over TC DP  -> offloaded=no  dp:tc
rule is in not HW over OVS DP -> offloaded=no  dp:ovs

To achieve this, the flows's 'offloaded' flag was encapsulated in a new
attrs struct, which contains the offloaded state of the flow and the
DP layer the flow is handled in, and instead of setting the flow's
'offloaded' state based solely on the type of dump it was acquired
via, for netdev flows it now sends the new attrs struct to be
collected along with the rest of the flow via the netdev, allowing
it to be set per flow.

For TC offloads, the offloaded state is set based on the 'in_hw' and
'not_in_hw' flags received from the TC as part of the flower. If no
such flag was received, due to lack of kernel support, it defaults
to true.

Signed-off-by: Gavi Teitz <gavi@mellanox.com>
Acked-by: Roi Dayan <roid@mellanox.com>
[simon: resolved conflict in lib/dpctl.man]
Signed-off-by: Simon Horman <simon.horman@netronome.com>
This commit is contained in:
Gavi Teitz
2018-06-07 09:36:59 +03:00
committed by Simon Horman
parent 21aade70f3
commit d63ca5329f
12 changed files with 105 additions and 37 deletions

View File

@@ -771,7 +771,7 @@ dpctl_dump_dps(int argc OVS_UNUSED, const char *argv[] OVS_UNUSED,
static void static void
format_dpif_flow(struct ds *ds, const struct dpif_flow *f, struct hmap *ports, format_dpif_flow(struct ds *ds, const struct dpif_flow *f, struct hmap *ports,
char *type, struct dpctl_params *dpctl_p) struct dpctl_params *dpctl_p)
{ {
if (dpctl_p->verbosity && f->ufid_present) { if (dpctl_p->verbosity && f->ufid_present) {
odp_format_ufid(&f->ufid, ds); odp_format_ufid(&f->ufid, ds);
@@ -782,9 +782,12 @@ format_dpif_flow(struct ds *ds, const struct dpif_flow *f, struct hmap *ports,
ds_put_cstr(ds, ", "); ds_put_cstr(ds, ", ");
dpif_flow_stats_format(&f->stats, ds); dpif_flow_stats_format(&f->stats, ds);
if (dpctl_p->verbosity && !type && f->offloaded) { if (dpctl_p->verbosity && f->attrs.offloaded) {
ds_put_cstr(ds, ", offloaded:yes"); ds_put_cstr(ds, ", offloaded:yes");
} }
if (dpctl_p->verbosity && f->attrs.dp_layer) {
ds_put_format(ds, ", dp:%s", f->attrs.dp_layer);
}
ds_put_cstr(ds, ", actions:"); ds_put_cstr(ds, ", actions:");
format_odp_actions(ds, f->actions, f->actions_len, ports); format_odp_actions(ds, f->actions, f->actions_len, ports);
} }
@@ -794,6 +797,15 @@ static char *supported_dump_types[] = {
"ovs", "ovs",
}; };
static bool
flow_passes_type_filter(const struct dpif_flow *f, char *type)
{
if (!strcmp(type, "offloaded")) {
return f->attrs.offloaded;
}
return true;
}
static struct hmap * static struct hmap *
dpctl_get_portno_names(struct dpif *dpif, const struct dpctl_params *dpctl_p) dpctl_get_portno_names(struct dpif *dpif, const struct dpctl_params *dpctl_p)
{ {
@@ -938,9 +950,10 @@ dpctl_dump_flows(int argc, const char *argv[], struct dpctl_params *dpctl_p)
} }
pmd_id = f.pmd_id; pmd_id = f.pmd_id;
} }
format_dpif_flow(&ds, &f, portno_names, type, dpctl_p); if (!type || flow_passes_type_filter(&f, type)) {
format_dpif_flow(&ds, &f, portno_names, dpctl_p);
dpctl_print(dpctl_p, "%s\n", ds_cstr(&ds)); dpctl_print(dpctl_p, "%s\n", ds_cstr(&ds));
}
} }
dpif_flow_dump_thread_destroy(flow_dump_thread); dpif_flow_dump_thread_destroy(flow_dump_thread);
error = dpif_flow_dump_destroy(flow_dump); error = dpif_flow_dump_destroy(flow_dump);
@@ -1102,7 +1115,7 @@ dpctl_get_flow(int argc, const char *argv[], struct dpctl_params *dpctl_p)
} }
ds_init(&ds); ds_init(&ds);
format_dpif_flow(&ds, &flow, portno_names, NULL, dpctl_p); format_dpif_flow(&ds, &flow, portno_names, dpctl_p);
dpctl_print(dpctl_p, "%s\n", ds_cstr(&ds)); dpctl_print(dpctl_p, "%s\n", ds_cstr(&ds));
ds_destroy(&ds); ds_destroy(&ds);

View File

@@ -119,9 +119,9 @@ flow. As an example, \fBfilter='tcp,tp_src=100'\fR will match the
datapath flow containing '\fBtcp(src=80/0xff00,dst=8080/0xff)\fR'. datapath flow containing '\fBtcp(src=80/0xff00,dst=8080/0xff)\fR'.
.IP .IP
If \fBtype=\fItype\fR is specified, only displays flows of a specific type. If \fBtype=\fItype\fR is specified, only displays flows of a specific type.
\fItype\fR can be \fBoffloaded\fR to display only offloaded rules or \fBovs\fR \fItype\fR can be \fBoffloaded\fR to display only rules offloaded to the HW
to display only non-offloaded rules. or \fBovs\fR to display only rules from the OVS tables.
By default both offloaded and non-offloaded rules are displayed. By default all rules are displayed.
. .
.IP "\*(DX\fBadd\-flow\fR [\fIdp\fR] \fIflow actions\fR" .IP "\*(DX\fBadd\-flow\fR [\fIdp\fR] \fIflow actions\fR"
.TP .TP

View File

@@ -1463,13 +1463,13 @@ dpif_netlink_init_flow_del(struct dpif_netlink *dpif,
} }
enum { enum {
DUMP_OVS_FLOWS_BIT = 0, DUMP_OVS_FLOWS_BIT = 0,
DUMP_OFFLOADED_FLOWS_BIT = 1, DUMP_NETDEV_FLOWS_BIT = 1,
}; };
enum { enum {
DUMP_OVS_FLOWS = (1 << DUMP_OVS_FLOWS_BIT), DUMP_OVS_FLOWS = (1 << DUMP_OVS_FLOWS_BIT),
DUMP_OFFLOADED_FLOWS = (1 << DUMP_OFFLOADED_FLOWS_BIT), DUMP_NETDEV_FLOWS = (1 << DUMP_NETDEV_FLOWS_BIT),
}; };
struct dpif_netlink_flow_dump { struct dpif_netlink_flow_dump {
@@ -1495,7 +1495,7 @@ start_netdev_dump(const struct dpif *dpif_,
{ {
ovs_mutex_init(&dump->netdev_lock); ovs_mutex_init(&dump->netdev_lock);
if (!(dump->type & DUMP_OFFLOADED_FLOWS)) { if (!(dump->type & DUMP_NETDEV_FLOWS)) {
dump->netdev_dumps_num = 0; dump->netdev_dumps_num = 0;
dump->netdev_dumps = NULL; dump->netdev_dumps = NULL;
return; return;
@@ -1518,7 +1518,7 @@ dpif_netlink_get_dump_type(char *str) {
} }
if ((netdev_is_flow_api_enabled() && !str) if ((netdev_is_flow_api_enabled() && !str)
|| (str && (!strcmp(str, "offloaded") || !strcmp(str, "dpctl")))) { || (str && (!strcmp(str, "offloaded") || !strcmp(str, "dpctl")))) {
type |= DUMP_OFFLOADED_FLOWS; type |= DUMP_NETDEV_FLOWS;
} }
return type; return type;
@@ -1656,7 +1656,8 @@ dpif_netlink_flow_to_dpif_flow(struct dpif *dpif, struct dpif_flow *dpif_flow,
&dpif_flow->ufid); &dpif_flow->ufid);
} }
dpif_netlink_flow_get_stats(datapath_flow, &dpif_flow->stats); dpif_netlink_flow_get_stats(datapath_flow, &dpif_flow->stats);
dpif_flow->offloaded = false; dpif_flow->attrs.offloaded = false;
dpif_flow->attrs.dp_layer = "ovs";
} }
/* The design is such that all threads are working together on the first dump /* The design is such that all threads are working together on the first dump
@@ -1698,6 +1699,7 @@ dpif_netlink_netdev_match_to_dpif_flow(struct match *match,
struct ofpbuf *mask_buf, struct ofpbuf *mask_buf,
struct nlattr *actions, struct nlattr *actions,
struct dpif_flow_stats *stats, struct dpif_flow_stats *stats,
struct dpif_flow_attrs *attrs,
ovs_u128 *ufid, ovs_u128 *ufid,
struct dpif_flow *flow, struct dpif_flow *flow,
bool terse OVS_UNUSED) bool terse OVS_UNUSED)
@@ -1740,7 +1742,7 @@ dpif_netlink_netdev_match_to_dpif_flow(struct match *match,
flow->pmd_id = PMD_ID_NULL; flow->pmd_id = PMD_ID_NULL;
flow->offloaded = true; memcpy(&flow->attrs, attrs, sizeof *attrs);
return 0; return 0;
} }
@@ -1772,6 +1774,7 @@ dpif_netlink_flow_dump_next(struct dpif_flow_dump_thread *thread_,
struct match match; struct match match;
struct nlattr *actions; struct nlattr *actions;
struct dpif_flow_stats stats; struct dpif_flow_stats stats;
struct dpif_flow_attrs attrs;
ovs_u128 ufid; ovs_u128 ufid;
bool has_next; bool has_next;
@@ -1779,7 +1782,7 @@ dpif_netlink_flow_dump_next(struct dpif_flow_dump_thread *thread_,
ofpbuf_use_stack(&act, actbuf, sizeof *actbuf); ofpbuf_use_stack(&act, actbuf, sizeof *actbuf);
ofpbuf_use_stack(&mask, maskbuf, sizeof *maskbuf); ofpbuf_use_stack(&mask, maskbuf, sizeof *maskbuf);
has_next = netdev_flow_dump_next(netdev_dump, &match, has_next = netdev_flow_dump_next(netdev_dump, &match,
&actions, &stats, &actions, &stats, &attrs,
&ufid, &ufid,
&thread->nl_flows, &thread->nl_flows,
&act); &act);
@@ -1788,6 +1791,7 @@ dpif_netlink_flow_dump_next(struct dpif_flow_dump_thread *thread_,
&key, &mask, &key, &mask,
actions, actions,
&stats, &stats,
&attrs,
&ufid, &ufid,
f, f,
dump->up.terse); dump->up.terse);
@@ -2055,6 +2059,7 @@ parse_flow_get(struct dpif_netlink *dpif, struct dpif_flow_get *get)
struct match match; struct match match;
struct nlattr *actions; struct nlattr *actions;
struct dpif_flow_stats stats; struct dpif_flow_stats stats;
struct dpif_flow_attrs attrs;
struct ofpbuf buf; struct ofpbuf buf;
uint64_t act_buf[1024 / 8]; uint64_t act_buf[1024 / 8];
struct odputil_keybuf maskbuf; struct odputil_keybuf maskbuf;
@@ -2065,7 +2070,7 @@ parse_flow_get(struct dpif_netlink *dpif, struct dpif_flow_get *get)
ofpbuf_use_stack(&buf, &act_buf, sizeof act_buf); ofpbuf_use_stack(&buf, &act_buf, sizeof act_buf);
err = netdev_ports_flow_get(dpif->dpif.dpif_class, &match, err = netdev_ports_flow_get(dpif->dpif.dpif_class, &match,
&actions, get->ufid, &stats, &buf); &actions, get->ufid, &stats, &attrs, &buf);
if (err) { if (err) {
return err; return err;
} }
@@ -2076,7 +2081,7 @@ parse_flow_get(struct dpif_netlink *dpif, struct dpif_flow_get *get)
ofpbuf_use_stack(&act, &actbuf, sizeof actbuf); ofpbuf_use_stack(&act, &actbuf, sizeof actbuf);
ofpbuf_use_stack(&mask, &maskbuf, sizeof maskbuf); ofpbuf_use_stack(&mask, &maskbuf, sizeof maskbuf);
dpif_netlink_netdev_match_to_dpif_flow(&match, &key, &mask, actions, dpif_netlink_netdev_match_to_dpif_flow(&match, &key, &mask, actions,
&stats, &stats, &attrs,
(ovs_u128 *) get->ufid, (ovs_u128 *) get->ufid,
dpif_flow, dpif_flow,
false); false);

View File

@@ -507,6 +507,11 @@ struct dpif_flow_stats {
uint16_t tcp_flags; uint16_t tcp_flags;
}; };
struct dpif_flow_attrs {
bool offloaded; /* True if flow is offloaded to HW. */
const char *dp_layer; /* DP layer the flow is handled in. */
};
void dpif_flow_stats_extract(const struct flow *, const struct dp_packet *packet, void dpif_flow_stats_extract(const struct flow *, const struct dp_packet *packet,
long long int used, struct dpif_flow_stats *); long long int used, struct dpif_flow_stats *);
void dpif_flow_stats_format(const struct dpif_flow_stats *, struct ds *); void dpif_flow_stats_format(const struct dpif_flow_stats *, struct ds *);
@@ -589,7 +594,7 @@ struct dpif_flow {
bool ufid_present; /* True if 'ufid' was provided by datapath.*/ bool ufid_present; /* True if 'ufid' was provided by datapath.*/
unsigned pmd_id; /* Datapath poll mode driver id. */ unsigned pmd_id; /* Datapath poll mode driver id. */
struct dpif_flow_stats stats; /* Flow statistics. */ struct dpif_flow_stats stats; /* Flow statistics. */
bool offloaded; /* True if flow is offloaded */ struct dpif_flow_attrs attrs; /* Flow attributes. */
}; };
int dpif_flow_dump_next(struct dpif_flow_dump_thread *, int dpif_flow_dump_next(struct dpif_flow_dump_thread *,
struct dpif_flow *flows, int max_flows); struct dpif_flow *flows, int max_flows);

View File

@@ -33,6 +33,7 @@
#include "util.h" #include "util.h"
struct dpif_flow_stats; struct dpif_flow_stats;
struct dpif_flow_attrs;
struct ds; struct ds;
struct flow_wildcards; struct flow_wildcards;
struct minimask; struct minimask;

View File

@@ -837,7 +837,8 @@ struct netdev_class {
* to be pre allocated by the caller. */ * to be pre allocated by the caller. */
bool (*flow_dump_next)(struct netdev_flow_dump *, struct match *, bool (*flow_dump_next)(struct netdev_flow_dump *, struct match *,
struct nlattr **actions, struct nlattr **actions,
struct dpif_flow_stats *stats, ovs_u128 *ufid, struct dpif_flow_stats *stats,
struct dpif_flow_attrs *attrs, ovs_u128 *ufid,
struct ofpbuf *rbuffer, struct ofpbuf *wbuffer); struct ofpbuf *rbuffer, struct ofpbuf *wbuffer);
/* Offload the given flow on netdev. /* Offload the given flow on netdev.
@@ -857,7 +858,7 @@ struct netdev_class {
* Return 0 if successful, otherwise returns a positive errno value. */ * Return 0 if successful, otherwise returns a positive errno value. */
int (*flow_get)(struct netdev *, struct match *, struct nlattr **actions, int (*flow_get)(struct netdev *, struct match *, struct nlattr **actions,
const ovs_u128 *ufid, struct dpif_flow_stats *, const ovs_u128 *ufid, struct dpif_flow_stats *,
struct ofpbuf *wbuffer); struct dpif_flow_attrs *, struct ofpbuf *wbuffer);
/* Delete a flow specified by ufid from netdev. /* Delete a flow specified by ufid from netdev.
* 'stats' is populated according to the rules set out in the description * 'stats' is populated according to the rules set out in the description

View File

@@ -398,6 +398,7 @@ parse_tc_flower_to_match(struct tc_flower *flower,
struct match *match, struct match *match,
struct nlattr **actions, struct nlattr **actions,
struct dpif_flow_stats *stats, struct dpif_flow_stats *stats,
struct dpif_flow_attrs *attrs,
struct ofpbuf *buf) struct ofpbuf *buf)
{ {
size_t act_off; size_t act_off;
@@ -565,6 +566,10 @@ parse_tc_flower_to_match(struct tc_flower *flower,
stats->used = flower->lastused; stats->used = flower->lastused;
} }
attrs->offloaded = (flower->offloaded_state == TC_OFFLOADED_STATE_IN_HW)
|| (flower->offloaded_state == TC_OFFLOADED_STATE_UNDEFINED);
attrs->dp_layer = "tc";
return 0; return 0;
} }
@@ -573,6 +578,7 @@ netdev_tc_flow_dump_next(struct netdev_flow_dump *dump,
struct match *match, struct match *match,
struct nlattr **actions, struct nlattr **actions,
struct dpif_flow_stats *stats, struct dpif_flow_stats *stats,
struct dpif_flow_attrs *attrs,
ovs_u128 *ufid, ovs_u128 *ufid,
struct ofpbuf *rbuffer, struct ofpbuf *rbuffer,
struct ofpbuf *wbuffer) struct ofpbuf *wbuffer)
@@ -587,7 +593,7 @@ netdev_tc_flow_dump_next(struct netdev_flow_dump *dump,
continue; continue;
} }
if (parse_tc_flower_to_match(&flower, match, actions, stats, if (parse_tc_flower_to_match(&flower, match, actions, stats, attrs,
wbuffer)) { wbuffer)) {
continue; continue;
} }
@@ -1119,6 +1125,7 @@ netdev_tc_flow_get(struct netdev *netdev OVS_UNUSED,
struct nlattr **actions, struct nlattr **actions,
const ovs_u128 *ufid, const ovs_u128 *ufid,
struct dpif_flow_stats *stats, struct dpif_flow_stats *stats,
struct dpif_flow_attrs *attrs,
struct ofpbuf *buf) struct ofpbuf *buf)
{ {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20);
@@ -1154,7 +1161,7 @@ netdev_tc_flow_get(struct netdev *netdev OVS_UNUSED,
} }
in_port = netdev_ifindex_to_odp_port(ifindex); in_port = netdev_ifindex_to_odp_port(ifindex);
parse_tc_flower_to_match(&flower, match, actions, stats, buf); parse_tc_flower_to_match(&flower, match, actions, stats, attrs, buf);
match->wc.masks.in_port.odp_port = u32_to_odp(UINT32_MAX); match->wc.masks.in_port.odp_port = u32_to_odp(UINT32_MAX);
match->flow.in_port.odp_port = in_port; match->flow.in_port.odp_port = in_port;

View File

@@ -25,6 +25,7 @@ int netdev_tc_flow_dump_destroy(struct netdev_flow_dump *);
bool netdev_tc_flow_dump_next(struct netdev_flow_dump *, struct match *, bool netdev_tc_flow_dump_next(struct netdev_flow_dump *, struct match *,
struct nlattr **actions, struct nlattr **actions,
struct dpif_flow_stats *, struct dpif_flow_stats *,
struct dpif_flow_attrs *,
ovs_u128 *ufid, ovs_u128 *ufid,
struct ofpbuf *rbuffer, struct ofpbuf *rbuffer,
struct ofpbuf *wbuffer); struct ofpbuf *wbuffer);
@@ -34,7 +35,8 @@ int netdev_tc_flow_put(struct netdev *, struct match *,
struct dpif_flow_stats *); struct dpif_flow_stats *);
int netdev_tc_flow_get(struct netdev *, struct match *, int netdev_tc_flow_get(struct netdev *, struct match *,
struct nlattr **actions, const ovs_u128 *, struct nlattr **actions, const ovs_u128 *,
struct dpif_flow_stats *, struct ofpbuf *); struct dpif_flow_stats *,
struct dpif_flow_attrs *, struct ofpbuf *);
int netdev_tc_flow_del(struct netdev *, const ovs_u128 *, int netdev_tc_flow_del(struct netdev *, const ovs_u128 *,
struct dpif_flow_stats *); struct dpif_flow_stats *);
int netdev_tc_init_flow_api(struct netdev *); int netdev_tc_init_flow_api(struct netdev *);

View File

@@ -2162,14 +2162,14 @@ netdev_flow_dump_destroy(struct netdev_flow_dump *dump)
bool bool
netdev_flow_dump_next(struct netdev_flow_dump *dump, struct match *match, netdev_flow_dump_next(struct netdev_flow_dump *dump, struct match *match,
struct nlattr **actions, struct dpif_flow_stats *stats, struct nlattr **actions, struct dpif_flow_stats *stats,
ovs_u128 *ufid, struct ofpbuf *rbuffer, struct dpif_flow_attrs *attrs, ovs_u128 *ufid,
struct ofpbuf *wbuffer) struct ofpbuf *rbuffer, struct ofpbuf *wbuffer)
{ {
const struct netdev_class *class = dump->netdev->netdev_class; const struct netdev_class *class = dump->netdev->netdev_class;
return (class->flow_dump_next return (class->flow_dump_next
? class->flow_dump_next(dump, match, actions, stats, ufid, ? class->flow_dump_next(dump, match, actions, stats, attrs,
rbuffer, wbuffer) ufid, rbuffer, wbuffer)
: false); : false);
} }
@@ -2190,12 +2190,13 @@ netdev_flow_put(struct netdev *netdev, struct match *match,
int int
netdev_flow_get(struct netdev *netdev, struct match *match, netdev_flow_get(struct netdev *netdev, struct match *match,
struct nlattr **actions, const ovs_u128 *ufid, struct nlattr **actions, const ovs_u128 *ufid,
struct dpif_flow_stats *stats, struct ofpbuf *buf) struct dpif_flow_stats *stats,
struct dpif_flow_attrs *attrs, struct ofpbuf *buf)
{ {
const struct netdev_class *class = netdev->netdev_class; const struct netdev_class *class = netdev->netdev_class;
return (class->flow_get return (class->flow_get
? class->flow_get(netdev, match, actions, ufid, stats, buf) ? class->flow_get(netdev, match, actions, ufid, stats, attrs, buf)
: EOPNOTSUPP); : EOPNOTSUPP);
} }
@@ -2430,7 +2431,8 @@ netdev_ports_flow_del(const struct dpif_class *dpif_class,
int int
netdev_ports_flow_get(const struct dpif_class *dpif_class, struct match *match, netdev_ports_flow_get(const struct dpif_class *dpif_class, struct match *match,
struct nlattr **actions, const ovs_u128 *ufid, struct nlattr **actions, const ovs_u128 *ufid,
struct dpif_flow_stats *stats, struct ofpbuf *buf) struct dpif_flow_stats *stats,
struct dpif_flow_attrs *attrs, struct ofpbuf *buf)
{ {
struct port_to_netdev_data *data; struct port_to_netdev_data *data;
@@ -2438,7 +2440,7 @@ netdev_ports_flow_get(const struct dpif_class *dpif_class, struct match *match,
HMAP_FOR_EACH (data, portno_node, &port_to_netdev) { HMAP_FOR_EACH (data, portno_node, &port_to_netdev) {
if (data->dpif_class == dpif_class if (data->dpif_class == dpif_class
&& !netdev_flow_get(data->netdev, match, actions, && !netdev_flow_get(data->netdev, match, actions,
ufid, stats, buf)) { ufid, stats, attrs, buf)) {
ovs_mutex_unlock(&netdev_hmap_mutex); ovs_mutex_unlock(&netdev_hmap_mutex);
return 0; return 0;
} }

View File

@@ -209,14 +209,14 @@ int netdev_flow_dump_create(struct netdev *, struct netdev_flow_dump **dump);
int netdev_flow_dump_destroy(struct netdev_flow_dump *); int netdev_flow_dump_destroy(struct netdev_flow_dump *);
bool netdev_flow_dump_next(struct netdev_flow_dump *, struct match *, bool netdev_flow_dump_next(struct netdev_flow_dump *, struct match *,
struct nlattr **actions, struct dpif_flow_stats *, struct nlattr **actions, struct dpif_flow_stats *,
ovs_u128 *ufid, struct ofpbuf *rbuffer, struct dpif_flow_attrs *, ovs_u128 *ufid,
struct ofpbuf *wbuffer); struct ofpbuf *rbuffer, struct ofpbuf *wbuffer);
int netdev_flow_put(struct netdev *, struct match *, struct nlattr *actions, int netdev_flow_put(struct netdev *, struct match *, struct nlattr *actions,
size_t actions_len, const ovs_u128 *, size_t actions_len, const ovs_u128 *,
struct offload_info *, struct dpif_flow_stats *); struct offload_info *, struct dpif_flow_stats *);
int netdev_flow_get(struct netdev *, struct match *, struct nlattr **actions, int netdev_flow_get(struct netdev *, struct match *, struct nlattr **actions,
const ovs_u128 *, struct dpif_flow_stats *, const ovs_u128 *, struct dpif_flow_stats *,
struct ofpbuf *wbuffer); struct dpif_flow_attrs *, struct ofpbuf *wbuffer);
int netdev_flow_del(struct netdev *, const ovs_u128 *, int netdev_flow_del(struct netdev *, const ovs_u128 *,
struct dpif_flow_stats *); struct dpif_flow_stats *);
int netdev_init_flow_api(struct netdev *); int netdev_init_flow_api(struct netdev *);
@@ -239,6 +239,7 @@ int netdev_ports_flow_get(const struct dpif_class *, struct match *match,
struct nlattr **actions, struct nlattr **actions,
const ovs_u128 *ufid, const ovs_u128 *ufid,
struct dpif_flow_stats *stats, struct dpif_flow_stats *stats,
struct dpif_flow_attrs *attrs,
struct ofpbuf *buf); struct ofpbuf *buf);
/* native tunnel APIs */ /* native tunnel APIs */

View File

@@ -458,6 +458,28 @@ nl_parse_flower_ip(struct nlattr **attrs, struct tc_flower *flower) {
} }
} }
static enum tc_offloaded_state
nl_get_flower_offloaded_state(struct nlattr **attrs)
{
uint32_t flower_flags = 0;
if (attrs[TCA_FLOWER_FLAGS]) {
flower_flags = nl_attr_get_u32(attrs[TCA_FLOWER_FLAGS]);
if (flower_flags & TCA_CLS_FLAGS_NOT_IN_HW) {
return TC_OFFLOADED_STATE_NOT_IN_HW;
} else if (flower_flags & TCA_CLS_FLAGS_IN_HW) {
return TC_OFFLOADED_STATE_IN_HW;
}
}
return TC_OFFLOADED_STATE_UNDEFINED;
}
static void
nl_parse_flower_flags(struct nlattr **attrs, struct tc_flower *flower)
{
flower->offloaded_state = nl_get_flower_offloaded_state(attrs);
}
static const struct nl_policy pedit_policy[] = { static const struct nl_policy pedit_policy[] = {
[TCA_PEDIT_PARMS_EX] = { .type = NL_A_UNSPEC, [TCA_PEDIT_PARMS_EX] = { .type = NL_A_UNSPEC,
.min_len = sizeof(struct tc_pedit), .min_len = sizeof(struct tc_pedit),
@@ -942,6 +964,7 @@ nl_parse_flower_options(struct nlattr *nl_options, struct tc_flower *flower)
nl_parse_flower_vlan(attrs, flower); nl_parse_flower_vlan(attrs, flower);
nl_parse_flower_ip(attrs, flower); nl_parse_flower_ip(attrs, flower);
nl_parse_flower_tunnel(attrs, flower); nl_parse_flower_tunnel(attrs, flower);
nl_parse_flower_flags(attrs, flower);
return nl_parse_flower_actions(attrs, flower); return nl_parse_flower_actions(attrs, flower);
} }

View File

@@ -141,6 +141,12 @@ struct tc_action {
enum tc_action_type type; enum tc_action_type type;
}; };
enum tc_offloaded_state {
TC_OFFLOADED_STATE_UNDEFINED,
TC_OFFLOADED_STATE_IN_HW,
TC_OFFLOADED_STATE_NOT_IN_HW,
};
struct tc_flower { struct tc_flower {
uint32_t handle; uint32_t handle;
uint32_t prio; uint32_t prio;
@@ -180,6 +186,8 @@ struct tc_flower {
struct tc_cookie act_cookie; struct tc_cookie act_cookie;
bool needs_full_ip_proto_mask; bool needs_full_ip_proto_mask;
enum tc_offloaded_state offloaded_state;
}; };
/* assert that if we overflow with a masked write of uint32_t to the last byte /* assert that if we overflow with a masked write of uint32_t to the last byte