* [PATCH/RFC flow-net-next 00/10] Flow Table API Cache Enhancements
@ 2014-12-29 2:15 Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 01/10] net: flow: Correct spelling of action Simon Horman
` (9 more replies)
0 siblings, 10 replies; 15+ messages in thread
From: Simon Horman @ 2014-12-29 2:15 UTC (permalink / raw)
To: John Fastabend, netdev; +Cc: Simon Horman
Hi John, Hi All,
the purpose of this patch-set is to propose enhancements to the flow table
API which you have been working on. The enhancements focus on optional
support for tables which act as caches, where a cache is defined to be a
table that may remove entries other than via an explicit remove-flow API
call.
I will be up-front and say that many of the ideas implemented here have
been inspired by OpenFlow: something that I am familiar with.
A possible user of flow timeouts and counters, is Open vSwitch: it does not
currently make use of the Flow Table API but it treats its datapath as a
typically manages the cached by removing flows based on statistics
indicating the idleness of flows.
That said, I am not attempting to make the Flow Table API OpenFlow or Open
vSwitch specific. I have attempted to make all the enhancements optional,
so that they may only be used in software and hardware scenarios where they
make sense.
Thus far I have only prototyped the netlink API side of these enhancements
and compile tested them.
This series is based on John Fastabend's flow-net-next tree
https://github.com/jrfastab/flow-net-next
Simon Horman (10):
net: flow: Correct spelling of action
net: flow: Add features to tables
net: flow: Add timeouts to flows
net: flow: Add counters to flows
net: flow: Add get, set and del notifier commands
net: flow: Add flow removed notification
net: flow: Add importance to flows
net: flow: Add get and set table config commands
net: flow: Add eviction flags to table configuration
net: flow: Add flow removed notification for eviction
include/linux/if_flow.h | 3 +
include/linux/netdevice.h | 10 +
include/uapi/linux/if_flow.h | 232 +++++++++++++++++-
net/core/flow_table.c | 561 ++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 798 insertions(+), 8 deletions(-)
--
2.1.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH/RFC flow-net-next 01/10] net: flow: Correct spelling of action
2014-12-29 2:15 [PATCH/RFC flow-net-next 00/10] Flow Table API Cache Enhancements Simon Horman
@ 2014-12-29 2:15 ` Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 02/10] net: flow: Add features to tables Simon Horman
` (8 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Simon Horman @ 2014-12-29 2:15 UTC (permalink / raw)
To: John Fastabend, netdev; +Cc: Simon Horman
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
Compile tested only
Previously submitted individually to John Fastabend and netdev ML.
---
include/uapi/linux/if_flow.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/uapi/linux/if_flow.h b/include/uapi/linux/if_flow.h
index 598c009..25a6b31 100644
--- a/include/uapi/linux/if_flow.h
+++ b/include/uapi/linux/if_flow.h
@@ -356,7 +356,7 @@ enum {
* @uid unique identifier for flow
* @priority priority to execute flow match/action in table
* @match null terminated set of match uids match criteria
- * @actoin null terminated set of action uids to apply to match
+ * @action null terminated set of action uids to apply to match
*
* Flows must match all entries in match set.
*/
--
2.1.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH/RFC flow-net-next 02/10] net: flow: Add features to tables
2014-12-29 2:15 [PATCH/RFC flow-net-next 00/10] Flow Table API Cache Enhancements Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 01/10] net: flow: Correct spelling of action Simon Horman
@ 2014-12-29 2:15 ` Simon Horman
2014-12-29 23:03 ` Cong Wang
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 03/10] net: flow: Add timeouts to flows Simon Horman
` (7 subsequent siblings)
9 siblings, 1 reply; 15+ messages in thread
From: Simon Horman @ 2014-12-29 2:15 UTC (permalink / raw)
To: John Fastabend, netdev; +Cc: Simon Horman
This is intended to allow flows to advertise optional features.
Its initial intended use case is to advertise support for flow timeouts
which will be proposed by a subsequent patch.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
Compile tested only
---
include/uapi/linux/if_flow.h | 3 ++
net/core/flow_table.c | 79 ++++++++++++++++++++++++++++++++++++++++----
2 files changed, 76 insertions(+), 6 deletions(-)
diff --git a/include/uapi/linux/if_flow.h b/include/uapi/linux/if_flow.h
index 25a6b31..5720698 100644
--- a/include/uapi/linux/if_flow.h
+++ b/include/uapi/linux/if_flow.h
@@ -35,6 +35,7 @@
* [NET_FLOW_TABLE_ATTR_UID]
* [NET_FLOW_TABLE_ATTR_SOURCE]
* [NET_FLOW_TABLE_ATTR_SIZE]
+ * [NET_FLOW_TABLE_ATTR_FEATURES]
* [NET_FLOW_TABLE_ATTR_MATCHES]
* [NET_FLOW_FIELD_REF]
* [NET_FLOW_FIELD_REF]
@@ -422,6 +423,7 @@ struct net_flow_table {
int uid;
int source;
int size;
+ __u32 features;
struct net_flow_field_ref *matches;
net_flow_action_ref *actions;
};
@@ -441,6 +443,7 @@ enum {
NET_FLOW_TABLE_ATTR_SIZE,
NET_FLOW_TABLE_ATTR_MATCHES,
NET_FLOW_TABLE_ATTR_ACTIONS,
+ NET_FLOW_TABLE_ATTR_FEATURES,
__NET_FLOW_TABLE_ATTR_MAX,
};
#define NET_FLOW_TABLE_ATTR_MAX (__NET_FLOW_TABLE_ATTR_MAX - 1)
diff --git a/net/core/flow_table.c b/net/core/flow_table.c
index 5937fb7..1ea88ed 100644
--- a/net/core/flow_table.c
+++ b/net/core/flow_table.c
@@ -63,6 +63,7 @@ struct nla_policy net_flow_table_policy[NET_FLOW_TABLE_ATTR_MAX + 1] = {
[NET_FLOW_TABLE_ATTR_UID] = { .type = NLA_U32 },
[NET_FLOW_TABLE_ATTR_SOURCE] = { .type = NLA_U32 },
[NET_FLOW_TABLE_ATTR_SIZE] = { .type = NLA_U32 },
+ [NET_FLOW_TABLE_ATTR_FEATURES] = { .type = NLA_U32 },
[NET_FLOW_TABLE_ATTR_MATCHES] = { .type = NLA_NESTED },
[NET_FLOW_TABLE_ATTR_ACTIONS] = { .type = NLA_NESTED },
};
@@ -245,6 +246,10 @@ static int net_flow_put_table(struct net_device *dev,
nla_put_u32(skb, NET_FLOW_TABLE_ATTR_SIZE, t->size))
return -EMSGSIZE;
+ if (t->features &&
+ nla_put_u32(skb, NET_FLOW_TABLE_ATTR_FEATURES, t->features))
+ return -EMSGSIZE;
+
matches = nla_nest_start(skb, NET_FLOW_TABLE_ATTR_MATCHES);
if (!matches)
return -EMSGSIZE;
@@ -611,6 +616,9 @@ static int net_flow_get_table(struct net_flow_table *table, struct nlattr *nla)
table->size = tbl[NET_FLOW_TABLE_ATTR_SIZE] ?
nla_get_u32(tbl[NET_FLOW_TABLE_ATTR_SIZE]) : 0;
+ table->features = tbl[NET_FLOW_TABLE_ATTR_FEATURES] ?
+ nla_get_u32(tbl[NET_FLOW_TABLE_ATTR_FEATURES]) : 0;
+
if (tbl[NET_FLOW_TABLE_ATTR_MATCHES]) {
cnt = 0;
nla_for_each_nested(i, tbl[NET_FLOW_TABLE_ATTR_MATCHES], rem)
@@ -719,6 +727,57 @@ static int net_flow_table_cmd_destroy_tables(struct sk_buff *skb,
return -EOPNOTSUPP;
}
+static struct net_flow_table **
+net_flow_get_tables(struct net_device *dev)
+{
+ struct net_flow_table **tables;
+
+ if (!dev->netdev_ops->ndo_flow_get_tables)
+ return ERR_PTR(-EOPNOTSUPP);
+
+ tables = dev->netdev_ops->ndo_flow_get_tables(dev);
+ if (!tables) /* transient failure should always have some table */
+ return ERR_PTR(-EBUSY);
+
+ return tables;
+}
+
+static struct net_flow_table *net_flow_table_get_table(struct net_device *dev,
+ int table_uid)
+{
+ struct net_flow_table **tables;
+ int i;
+
+ tables = net_flow_get_tables(dev);
+ if (IS_ERR(tables))
+ return ERR_PTR(PTR_ERR(tables));
+
+ for (i = 0; tables[i]->uid; i++) {
+ if (tables[i]->uid == table_uid)
+ return tables[i];
+ }
+
+ return ERR_PTR(-ENOENT);
+}
+
+static int net_flow_table_check_features(struct net_device *dev,
+ int table_uid, u32 used_features)
+{
+ struct net_flow_table *table;
+
+ if (!used_features) /* No features: no problems */
+ return 0;
+
+ table = net_flow_table_get_table(dev, table_uid);
+ if (IS_ERR(table))
+ return PTR_ERR(table);
+
+ if ((used_features & table->features) != used_features)
+ return -EINVAL;
+
+ return 0;
+}
+
static int net_flow_table_cmd_get_tables(struct sk_buff *skb,
struct genl_info *info)
{
@@ -730,15 +789,12 @@ static int net_flow_table_cmd_get_tables(struct sk_buff *skb,
if (!dev)
return -EINVAL;
- if (!dev->netdev_ops->ndo_flow_get_tables) {
+ tables = net_flow_get_tables(dev);
+ if (IS_ERR(tables)) {
dev_put(dev);
- return -EOPNOTSUPP;
+ return PTR_ERR(tables);
}
- tables = dev->netdev_ops->ndo_flow_get_tables(dev);
- if (!tables) /* transient failure should always have some table */
- return -EBUSY;
-
msg = net_flow_build_tables_msg(tables, dev,
info->snd_portid,
info->snd_seq,
@@ -1302,6 +1358,8 @@ static int net_flow_table_cmd_flows(struct sk_buff *recv_skb,
err_handle = nla_get_u32(info->attrs[NET_FLOW_FLOWS_ERROR]);
nla_for_each_nested(flow, info->attrs[NET_FLOW_FLOWS], rem) {
+ u32 used_features = 0;
+
if (nla_type(flow) != NET_FLOW_FLOW)
continue;
@@ -1309,6 +1367,15 @@ static int net_flow_table_cmd_flows(struct sk_buff *recv_skb,
if (err)
goto out;
+ /* Set used_features here for each table feature that is used.
+ * (Currently no table features are defined)
+ */
+
+ err = net_flow_table_check_features(dev, this.table_id,
+ used_features);
+ if (err)
+ break;
+
switch (cmd) {
case NET_FLOW_TABLE_CMD_SET_FLOWS:
err = dev->netdev_ops->ndo_flow_set_flows(dev, &this);
--
2.1.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH/RFC flow-net-next 03/10] net: flow: Add timeouts to flows
2014-12-29 2:15 [PATCH/RFC flow-net-next 00/10] Flow Table API Cache Enhancements Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 01/10] net: flow: Correct spelling of action Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 02/10] net: flow: Add features to tables Simon Horman
@ 2014-12-29 2:15 ` Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 04/10] net: flow: Add counters " Simon Horman
` (6 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Simon Horman @ 2014-12-29 2:15 UTC (permalink / raw)
To: John Fastabend, netdev; +Cc: Simon Horman
It may be useful for hardware flow table support for timeouts to be exposed
via the flow API. One possible use case of this is for Open vSwitch to use
the flow API in conjunction with its existing datapath flow management
scheme which in a nutshell treats the datapath as a cache that times out
idle entries.
Inspired by the timeouts present in OpenFlow.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
Compile tested only
Note to John Fastabend: This patch adds u32 fields to struct net_flow_flow.
This is in contrast to existing int fields of that structure. It is unclear
to me which is best and in practice (2^31-1)s seems to be more than ample
for a timeout.
---
include/uapi/linux/if_flow.h | 19 +++++++++++++++++++
net/core/flow_table.c | 21 ++++++++++++++++++---
2 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/include/uapi/linux/if_flow.h b/include/uapi/linux/if_flow.h
index 5720698..28da45b 100644
--- a/include/uapi/linux/if_flow.h
+++ b/include/uapi/linux/if_flow.h
@@ -125,6 +125,8 @@
* [NET_FLOW_ATTR_TABLE]
* [NET_FLOW_ATTR_UID]
* [NET_FLOW_ATTR_PRIORITY]
+ * [NET_FLOW_ATTR_IDLE_TIMEOUT]
+ * [NET_FLOW_ATTR_HARD_TIMEOUT]
* [NET_FLOW_ATTR_MATCHES]
* [NET_FLOW_FIELD_REF]
* [NET_FLOW_FIELD_REF]
@@ -149,6 +151,8 @@
* [NET_FLOW_ATTR_TABLE]
* [NET_FLOW_ATTR_UID]
* [NET_FLOW_ATTR_PRIORITY]
+ * [NET_FLOW_ATTR_IDLE_TIMEOUT]
+ * [NET_FLOW_ATTR_HARD_TIMEOUT]
* [NET_FLOW_MATCHES]
* [NET_FLOW_FIELD_REF]
* [NET_FLOW_FIELD_REF]
@@ -358,6 +362,9 @@ enum {
* @priority priority to execute flow match/action in table
* @match null terminated set of match uids match criteria
* @action null terminated set of action uids to apply to match
+ * @idle_timeout idle timeout of flow in seconds. Zero for no timeout.
+ * @hard_timeout timeout of flow regardless of use in seconds.
+ * Zero for no timeout.
*
* Flows must match all entries in match set.
*/
@@ -365,6 +372,8 @@ struct net_flow_flow {
int table_id;
int uid;
int priority;
+ __u32 idle_timeout;
+ __u32 hard_timeout;
struct net_flow_field_ref *matches;
struct net_flow_action *actions;
};
@@ -403,6 +412,8 @@ enum {
NET_FLOW_ATTR_PRIORITY,
NET_FLOW_ATTR_MATCHES,
NET_FLOW_ATTR_ACTIONS,
+ NET_FLOW_ATTR_IDLE_TIMEOUT,
+ NET_FLOW_ATTR_HARD_TIMEOUT,
__NET_FLOW_ATTR_MAX,
};
#define NET_FLOW_ATTR_MAX (__NET_FLOW_ATTR_MAX - 1)
@@ -448,6 +459,14 @@ enum {
};
#define NET_FLOW_TABLE_ATTR_MAX (__NET_FLOW_TABLE_ATTR_MAX - 1)
+enum {
+ /* Table supports idle timeout of flows */
+ NET_FLOW_TABLE_F_IDLE_TIMEOUT = (1 << 0),
+
+ /* Table supports idle timeout of flows */
+ NET_FLOW_TABLE_F_HARD_TIMEOUT = (1 << 1),
+};
+
#if 0
struct net_flow_offset {
int offset;
diff --git a/net/core/flow_table.c b/net/core/flow_table.c
index 1ea88ed..89ba9bc 100644
--- a/net/core/flow_table.c
+++ b/net/core/flow_table.c
@@ -52,6 +52,8 @@ struct nla_policy net_flow_flow_policy[NET_FLOW_ATTR_MAX + 1] = {
[NET_FLOW_ATTR_TABLE] = { .type = NLA_U32 },
[NET_FLOW_ATTR_UID] = { .type = NLA_U32 },
[NET_FLOW_ATTR_PRIORITY] = { .type = NLA_U32 },
+ [NET_FLOW_ATTR_IDLE_TIMEOUT] = { .type = NLA_U32 },
+ [NET_FLOW_ATTR_HARD_TIMEOUT] = { .type = NLA_U32 },
[NET_FLOW_ATTR_MATCHES] = { .type = NLA_NESTED },
[NET_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
};
@@ -197,6 +199,13 @@ int net_flow_put_flow(struct sk_buff *skb, struct net_flow_flow *flow)
nla_put_u32(skb, NET_FLOW_ATTR_PRIORITY, flow->priority))
goto flows_put_failure;
+ if (flow->idle_timeout &&
+ nla_put_u32(skb, NET_FLOW_ATTR_IDLE_TIMEOUT, flow->idle_timeout))
+ goto flows_put_failure;
+ if (flow->hard_timeout &&
+ nla_put_u32(skb, NET_FLOW_ATTR_HARD_TIMEOUT, flow->hard_timeout))
+ goto flows_put_failure;
+
matches = nla_nest_start(skb, NET_FLOW_ATTR_MATCHES);
if (!matches)
goto flows_put_failure;
@@ -522,6 +531,11 @@ static int net_flow_get_flow(struct net_flow_flow *flow, struct nlattr *attr)
flow->uid = nla_get_u32(f[NET_FLOW_ATTR_UID]);
flow->priority = nla_get_u32(f[NET_FLOW_ATTR_PRIORITY]);
+ if (f[NET_FLOW_ATTR_IDLE_TIMEOUT])
+ flow->idle_timeout = nla_get_u32(f[NET_FLOW_ATTR_IDLE_TIMEOUT]);
+ if (f[NET_FLOW_ATTR_HARD_TIMEOUT])
+ flow->hard_timeout = nla_get_u32(f[NET_FLOW_ATTR_HARD_TIMEOUT]);
+
flow->matches = NULL;
flow->actions = NULL;
@@ -1367,9 +1381,10 @@ static int net_flow_table_cmd_flows(struct sk_buff *recv_skb,
if (err)
goto out;
- /* Set used_features here for each table feature that is used.
- * (Currently no table features are defined)
- */
+ if (this.idle_timeout)
+ used_features |= NET_FLOW_TABLE_F_IDLE_TIMEOUT;
+ if (this.hard_timeout)
+ used_features |= NET_FLOW_TABLE_F_HARD_TIMEOUT;
err = net_flow_table_check_features(dev, this.table_id,
used_features);
--
2.1.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH/RFC flow-net-next 04/10] net: flow: Add counters to flows
2014-12-29 2:15 [PATCH/RFC flow-net-next 00/10] Flow Table API Cache Enhancements Simon Horman
` (2 preceding siblings ...)
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 03/10] net: flow: Add timeouts to flows Simon Horman
@ 2014-12-29 2:15 ` Simon Horman
2014-12-29 7:31 ` Arad, Ronen
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 05/10] net: flow: Add get, set and del notifier commands Simon Horman
` (5 subsequent siblings)
9 siblings, 1 reply; 15+ messages in thread
From: Simon Horman @ 2014-12-29 2:15 UTC (permalink / raw)
To: John Fastabend, netdev; +Cc: Simon Horman
It may be useful for hardware flow table support for counters to be exposed
via the flow API. One possible use case of this is for Open vSwitch to use
the flow API in conjunction with its existing datapath flow management
scheme which in a nutshell treats the datapath as a cache that times out
idle entries.
This patch exposes optionally exposes three counters:
- Number of packets that have matched a flow
- Number of bytes of packets that have matched a flow
- The time in ms when the flow was last hit
Inspired by the flow counters present in Open Flow.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
Compile tested only
---
include/uapi/linux/if_flow.h | 24 ++++++++++++++++++++++++
net/core/flow_table.c | 27 +++++++++++++++++++++++++++
2 files changed, 51 insertions(+)
diff --git a/include/uapi/linux/if_flow.h b/include/uapi/linux/if_flow.h
index 28da45b..18214ea 100644
--- a/include/uapi/linux/if_flow.h
+++ b/include/uapi/linux/if_flow.h
@@ -127,6 +127,9 @@
* [NET_FLOW_ATTR_PRIORITY]
* [NET_FLOW_ATTR_IDLE_TIMEOUT]
* [NET_FLOW_ATTR_HARD_TIMEOUT]
+ * [NET_FLOW_ATTR_BYTE_COUNT]
+ * [NET_FLOW_ATTR_PACKET_COUNT]
+ * [NET_FLOW_ATTR_LAST_USED]
* [NET_FLOW_ATTR_MATCHES]
* [NET_FLOW_FIELD_REF]
* [NET_FLOW_FIELD_REF]
@@ -153,6 +156,9 @@
* [NET_FLOW_ATTR_PRIORITY]
* [NET_FLOW_ATTR_IDLE_TIMEOUT]
* [NET_FLOW_ATTR_HARD_TIMEOUT]
+ * [NET_FLOW_ATTR_BYTE_COUNT]
+ * [NET_FLOW_ATTR_PACKET_COUNT]
+ * [NET_FLOW_ATTR_LAST_USED]
* [NET_FLOW_MATCHES]
* [NET_FLOW_FIELD_REF]
* [NET_FLOW_FIELD_REF]
@@ -365,6 +371,9 @@ enum {
* @idle_timeout idle timeout of flow in seconds. Zero for no timeout.
* @hard_timeout timeout of flow regardless of use in seconds.
* Zero for no timeout.
+ * @byte_count bytes recieved
+ * @byte_count packets recieved
+ * @last_used time of most recent use (msec since system initialisation)
*
* Flows must match all entries in match set.
*/
@@ -374,6 +383,9 @@ struct net_flow_flow {
int priority;
__u32 idle_timeout;
__u32 hard_timeout;
+ __u64 byte_count;
+ __u64 packet_count;
+ __u64 last_used;
struct net_flow_field_ref *matches;
struct net_flow_action *actions;
};
@@ -414,6 +426,9 @@ enum {
NET_FLOW_ATTR_ACTIONS,
NET_FLOW_ATTR_IDLE_TIMEOUT,
NET_FLOW_ATTR_HARD_TIMEOUT,
+ NET_FLOW_ATTR_BYTE_COUNT,
+ NET_FLOW_ATTR_PACKET_COUNT,
+ NET_FLOW_ATTR_LAST_USED,
__NET_FLOW_ATTR_MAX,
};
#define NET_FLOW_ATTR_MAX (__NET_FLOW_ATTR_MAX - 1)
@@ -465,6 +480,15 @@ enum {
/* Table supports idle timeout of flows */
NET_FLOW_TABLE_F_HARD_TIMEOUT = (1 << 1),
+
+ /* Table supports byte counter for flows */
+ NET_FLOW_TABLE_F_BYTE_COUNT = (1 << 2),
+
+ /* Table supports packet counter for flows */
+ NET_FLOW_TABLE_F_PACKET_COUNT = (1 << 3),
+
+ /* Table supports last used counter for flows */
+ NET_FLOW_TABLE_F_PACKET_LAST_USED = (1 << 4),
};
#if 0
diff --git a/net/core/flow_table.c b/net/core/flow_table.c
index 89ba9bc..070e646 100644
--- a/net/core/flow_table.c
+++ b/net/core/flow_table.c
@@ -54,6 +54,9 @@ struct nla_policy net_flow_flow_policy[NET_FLOW_ATTR_MAX + 1] = {
[NET_FLOW_ATTR_PRIORITY] = { .type = NLA_U32 },
[NET_FLOW_ATTR_IDLE_TIMEOUT] = { .type = NLA_U32 },
[NET_FLOW_ATTR_HARD_TIMEOUT] = { .type = NLA_U32 },
+ [NET_FLOW_ATTR_BYTE_COUNT] = { .type = NLA_U64 },
+ [NET_FLOW_ATTR_PACKET_COUNT] = { .type = NLA_U64 },
+ [NET_FLOW_ATTR_LAST_USED] = { .type = NLA_U64 },
[NET_FLOW_ATTR_MATCHES] = { .type = NLA_NESTED },
[NET_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
};
@@ -206,6 +209,16 @@ int net_flow_put_flow(struct sk_buff *skb, struct net_flow_flow *flow)
nla_put_u32(skb, NET_FLOW_ATTR_HARD_TIMEOUT, flow->hard_timeout))
goto flows_put_failure;
+ if (flow->byte_count &&
+ nla_put_u32(skb, NET_FLOW_ATTR_BYTE_COUNT, flow->byte_count))
+ goto flows_put_failure;
+ if (flow->packet_count &&
+ nla_put_u32(skb, NET_FLOW_ATTR_PACKET_COUNT, flow->packet_count))
+ goto flows_put_failure;
+ if (flow->last_used &&
+ nla_put_u32(skb, NET_FLOW_ATTR_LAST_USED, flow->last_used))
+ goto flows_put_failure;
+
matches = nla_nest_start(skb, NET_FLOW_ATTR_MATCHES);
if (!matches)
goto flows_put_failure;
@@ -536,6 +549,13 @@ static int net_flow_get_flow(struct net_flow_flow *flow, struct nlattr *attr)
if (f[NET_FLOW_ATTR_HARD_TIMEOUT])
flow->hard_timeout = nla_get_u32(f[NET_FLOW_ATTR_HARD_TIMEOUT]);
+ if (f[NET_FLOW_ATTR_BYTE_COUNT])
+ flow->byte_count = nla_get_u64(f[NET_FLOW_ATTR_BYTE_COUNT]);
+ if (f[NET_FLOW_ATTR_PACKET_COUNT])
+ flow->packet_count = nla_get_u64(f[NET_FLOW_ATTR_PACKET_COUNT]);
+ if (f[NET_FLOW_ATTR_LAST_USED])
+ flow->last_used = nla_get_u64(f[NET_FLOW_ATTR_LAST_USED]);
+
flow->matches = NULL;
flow->actions = NULL;
@@ -1386,6 +1406,13 @@ static int net_flow_table_cmd_flows(struct sk_buff *recv_skb,
if (this.hard_timeout)
used_features |= NET_FLOW_TABLE_F_HARD_TIMEOUT;
+ if (this.byte_count)
+ used_features |= NET_FLOW_TABLE_F_BYTE_COUNT;
+ if (this.packet_count)
+ used_features |= NET_FLOW_TABLE_F_PACKET_COUNT;
+ if (this.last_used)
+ used_features |= NET_FLOW_TABLE_F_PACKET_LAST_USED;
+
err = net_flow_table_check_features(dev, this.table_id,
used_features);
if (err)
--
2.1.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH/RFC flow-net-next 05/10] net: flow: Add get, set and del notifier commands
2014-12-29 2:15 [PATCH/RFC flow-net-next 00/10] Flow Table API Cache Enhancements Simon Horman
` (3 preceding siblings ...)
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 04/10] net: flow: Add counters " Simon Horman
@ 2014-12-29 2:15 ` Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 06/10] net: flow: Add flow removed notification Simon Horman
` (4 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Simon Horman @ 2014-12-29 2:15 UTC (permalink / raw)
To: John Fastabend, netdev; +Cc: Simon Horman
The purpose of these new commands is to manage the registration
of listeners for flow deletion notifications which will be
proposed in a subsequent patch.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
Compile tested only
---
include/linux/netdevice.h | 6 ++
include/uapi/linux/if_flow.h | 41 +++++++++++
net/core/flow_table.c | 161 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 208 insertions(+)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 2defaae..1174ab7 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1165,6 +1165,12 @@ struct net_device_ops {
struct net_flow_flow *f);
int (*ndo_flow_create_table)(struct net_device *dev,
struct net_flow_table *t);
+ int (*ndo_flow_set_notification)(struct net_device *dev,
+ u32 type, const u32 *pids,
+ size_t n_pids);
+ int (*ndo_flow_get_notification)(struct net_device *dev,
+ u32 type, u32 **pids,
+ size_t *n_pids);
};
/**
diff --git a/include/uapi/linux/if_flow.h b/include/uapi/linux/if_flow.h
index 18214ea..96905fa 100644
--- a/include/uapi/linux/if_flow.h
+++ b/include/uapi/linux/if_flow.h
@@ -172,6 +172,30 @@
* [NET_FLOW_ACTION]
* [..]
* [...]
+ *
+ * Set Flow Notification <Request>,
+ * Get Flow Notification <Request> and
+ * Get Flow Notification <Reply> description.
+ *
+ * Set Flow Notification registers netlink port ids to receive flow
+ * deletion notifications if the NET_FLOW_NOTIFICATION_PIDS attribute is
+ * present. Otherwise it unregisters port ids if they were previously
+ * registered by a Set Flow Notification with the
+ * NET_FLOW_NOTIFICATION_PIDS attribute present.
+ *
+ * Get Flow Notification reports the port ids if they were previously
+ * registered by a Set Flow Notification with the
+ * NET_FLOW_NOTIFICATION_PIDS. If no ids are registered then the
+ * NET_FLOW_NOTIFICATION_PIDS attribute of the reply should be omitted.
+ *
+ * The NET_FLOW_NOTIFICATION_ATTR_PIDS attribute is an array of u32 values.
+ * If the attribute is present then it must contain at least one element.
+ * The implementation may choose to ignore some elements. Currently the
+ * implementation ignores all elements other than the first one.
+ *
+ * [NET_FLOW_NOTIFICATION]
+ * [NET_FLOW_NOTIFICATION_ATTR_TYPE]
+ * [NET_FLOW_NOTIFICATION_ATTR_PIDS]
*/
#ifndef _UAPI_LINUX_IF_FLOW
@@ -633,6 +657,18 @@ enum {
};
enum {
+ NET_FLOW_NOTIFICATION_TYPE_FLOW_REM,
+};
+
+enum {
+ NET_FLOW_NOTIFICATION_ATTR_UNSPEC,
+ NET_FLOW_NOTIFICATION_ATTR_TYPE,
+ NET_FLOW_NOTIFICATION_ATTR_PIDS,
+ __NET_FLOW_NOTIFICATION_ATTR_MAX,
+};
+#define NET_FLOW_NOTIFICATION_ATTR_MAX (__NET_FLOW_NOTIFICATION_ATTR_MAX - 1)
+
+enum {
NET_FLOW_UNSPEC,
NET_FLOW_IDENTIFIER_TYPE,
NET_FLOW_IDENTIFIER,
@@ -644,6 +680,7 @@ enum {
NET_FLOW_TABLE_GRAPH,
NET_FLOW_FLOWS,
NET_FLOW_FLOWS_ERROR,
+ NET_FLOW_NOTIFICATION,
__NET_FLOW_MAX,
NET_FLOW_MAX = (__NET_FLOW_MAX - 1),
@@ -663,6 +700,10 @@ enum {
NET_FLOW_TABLE_CMD_CREATE_TABLE,
NET_FLOW_TABLE_CMD_DESTROY_TABLE,
+
+ NET_FLOW_TABLE_CMD_SET_NOTIFICATION,
+ NET_FLOW_TABLE_CMD_GET_NOTIFICATION,
+
__NET_FLOW_CMD_MAX,
NET_FLOW_CMD_MAX = (__NET_FLOW_CMD_MAX - 1),
};
diff --git a/net/core/flow_table.c b/net/core/flow_table.c
index 070e646..e8047eb 100644
--- a/net/core/flow_table.c
+++ b/net/core/flow_table.c
@@ -21,6 +21,7 @@
#include <uapi/linux/if_flow.h>
#include <linux/if_bridge.h>
#include <linux/types.h>
+#include <net/sock.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/rtnetlink.h>
@@ -1478,6 +1479,156 @@ out:
return -EINVAL;
}
+static const
+struct nla_policy net_flow_notification_policy[NET_FLOW_NOTIFICATION_ATTR_MAX + 1] = {
+ [NET_FLOW_NOTIFICATION_ATTR_TYPE] = { .type = NLA_U32,},
+ [NET_FLOW_NOTIFICATION_ATTR_PIDS] = { .type = NLA_U32,},
+};
+
+static int net_flow_table_cmd_set_notification(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ int err;
+ struct net_device *dev;
+ struct nlattr *tb[NET_FLOW_NOTIFICATION_ATTR_MAX+1];
+ u32 type;
+
+ dev = net_flow_table_get_dev(info);
+ if (!dev)
+ return -EINVAL;
+
+ if (!dev->netdev_ops->ndo_flow_set_notification) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (!info->attrs[NET_FLOW_NOTIFICATION]) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = nla_parse_nested(tb, NET_FLOW_NOTIFICATION_ATTR_MAX,
+ info->attrs[NET_FLOW_NOTIFICATION],
+ net_flow_notification_policy);
+ if (err)
+ goto out;
+
+ if (!tb[NET_FLOW_NOTIFICATION_ATTR_TYPE]) {
+ err = -EINVAL;
+ goto out;
+ }
+ type = nla_get_u32(tb[NET_FLOW_NOTIFICATION_ATTR_TYPE]);
+ if (type != NET_FLOW_NOTIFICATION_TYPE_FLOW_REM) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (tb[NET_FLOW_NOTIFICATION_ATTR_PIDS]) {
+ u32 pid;
+
+ /* Only the first pid is used at this time */
+ pid = nla_get_u32(tb[NET_FLOW_NOTIFICATION_ATTR_PIDS]);
+
+ err = dev->netdev_ops->ndo_flow_set_notification(dev, type,
+ &pid, 1);
+ } else {
+ err = dev->netdev_ops->ndo_flow_set_notification(dev, type,
+ NULL, 0);
+ }
+
+out:
+ dev_put(dev);
+ return err;
+}
+
+static int net_flow_table_cmd_get_notification(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ int err;
+ size_t n_pids;
+ struct genlmsghdr *hdr;
+ struct net_device *dev;
+ struct nlattr *start;
+ struct nlattr *tb[NET_FLOW_NOTIFICATION_ATTR_MAX+1];
+ struct sk_buff *msg = NULL;
+ u32 *pids, type;
+
+ dev = net_flow_table_get_dev(info);
+ if (!dev)
+ return -EINVAL;
+
+ if (!dev->netdev_ops->ndo_flow_get_notification) {
+ err = -EOPNOTSUPP;
+ goto err;
+ }
+
+ if (!info->attrs[NET_FLOW_NOTIFICATION]) {
+ err = -EINVAL;
+ goto err;
+ }
+
+ err = nla_parse_nested(tb, NET_FLOW_NOTIFICATION_ATTR_MAX,
+ info->attrs[NET_FLOW_NOTIFICATION],
+ net_flow_notification_policy);
+ if (err)
+ goto err;
+
+ if (!tb[NET_FLOW_NOTIFICATION_ATTR_TYPE]) {
+ err = -EINVAL;
+ goto err;
+ }
+ type = nla_get_u32(tb[NET_FLOW_NOTIFICATION_ATTR_TYPE]);
+
+ err = dev->netdev_ops->ndo_flow_get_notification(dev, type, &pids,
+ &n_pids);
+ if (err)
+ goto err;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg) {
+ err = -ENOBUFS;
+ goto err;
+ }
+
+ hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+ &net_flow_nl_family, 0,
+ NET_FLOW_TABLE_CMD_GET_NOTIFICATION);
+ if (!hdr) {
+ err = -ENOBUFS;
+ goto err;
+ }
+
+ if (nla_put_u32(msg, NET_FLOW_IDENTIFIER_TYPE, NET_FLOW_IDENTIFIER_IFINDEX) ||
+ nla_put_u32(msg, NET_FLOW_IDENTIFIER, dev->ifindex)) {
+ err = -ENOBUFS;
+ goto err;
+ }
+
+ start = nla_nest_start(msg, NET_FLOW_NOTIFICATION);
+ if (!start)
+ return -EMSGSIZE;
+
+ if (nla_put_u32(msg, NET_FLOW_NOTIFICATION_ATTR_TYPE, type) ||
+ (n_pids > 0 &&
+ nla_put_u32(msg, NET_FLOW_NOTIFICATION_ATTR_PIDS, pids[0])))
+ return -ENOBUFS;
+
+ nla_nest_end(msg, start);
+
+ err = genlmsg_end(msg, hdr);
+ if (err < 0)
+ goto err;
+
+ dev_put(dev);
+
+ return genlmsg_reply(msg, info);
+
+err:
+ nlmsg_free(msg);
+ dev_put(dev);
+ return err;
+}
+
static const struct genl_ops net_flow_table_nl_ops[] = {
{
.cmd = NET_FLOW_TABLE_CMD_GET_TABLES,
@@ -1541,6 +1692,16 @@ static const struct genl_ops net_flow_table_nl_ops[] = {
.doit = net_flow_table_cmd_destroy_tables,
.flags = GENL_ADMIN_PERM,
},
+ {
+ .cmd = NET_FLOW_TABLE_CMD_SET_NOTIFICATION,
+ .doit = net_flow_table_cmd_set_notification,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = NET_FLOW_TABLE_CMD_GET_NOTIFICATION,
+ .doit = net_flow_table_cmd_get_notification,
+ .flags = GENL_ADMIN_PERM,
+ },
};
static int __init net_flow_nl_module_init(void)
--
2.1.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH/RFC flow-net-next 06/10] net: flow: Add flow removed notification
2014-12-29 2:15 [PATCH/RFC flow-net-next 00/10] Flow Table API Cache Enhancements Simon Horman
` (4 preceding siblings ...)
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 05/10] net: flow: Add get, set and del notifier commands Simon Horman
@ 2014-12-29 2:15 ` Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 07/10] net: flow: Add importance to flows Simon Horman
` (3 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Simon Horman @ 2014-12-29 2:15 UTC (permalink / raw)
To: John Fastabend, netdev; +Cc: Simon Horman
The purpose of this change is to provide an optional notification mechanism
for flow removal. It is intended to be used in conjunction with proposals
to optionally allow expiry of flows due to timeouts or resource contention.
The flow removed message is designed to have two forms:
1. A summary form where NET_FLOW_REMOVED_FLOW_COUNT is present,
indicating the number of flows that were removed, and
NET_FLOW_REMOVED_FLOWS_FLOWS is absent. In this form no details are
provided about the removed flows beyond which table they were removed
from and the reason for removal.
The intention is to provide a lightweight mechanism that may be
useful at times of resource contention.
2. A full form where NET_FLOW_REMOVED_FLOWS_FLOWS is present, including
the flows that were removed, and NET_FLOW_REMOVED_FLOW_COUNT is absent.
This form provides full details of the flows removed.
Inspired by flow removed notifications in OpenFlow.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
Compile tested only
---
include/linux/if_flow.h | 3 ++
include/uapi/linux/if_flow.h | 74 ++++++++++++++++++++++++++++++++++-
net/core/flow_table.c | 92 ++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 164 insertions(+), 5 deletions(-)
diff --git a/include/linux/if_flow.h b/include/linux/if_flow.h
index 4af9794..351eb30 100644
--- a/include/linux/if_flow.h
+++ b/include/linux/if_flow.h
@@ -4,4 +4,7 @@
#include <uapi/linux/if_flow.h>
int net_flow_put_flow(struct sk_buff *skb, struct net_flow_flow *flow);
+int net_flow_put_rem_flow_summary_msg(struct net_device *dev,
+ struct net *net, u32 portid, int table,
+ u32 reason, int n_flows, gfp_t flags);
#endif
diff --git a/include/uapi/linux/if_flow.h b/include/uapi/linux/if_flow.h
index 96905fa..d1643f3 100644
--- a/include/uapi/linux/if_flow.h
+++ b/include/uapi/linux/if_flow.h
@@ -36,6 +36,7 @@
* [NET_FLOW_TABLE_ATTR_SOURCE]
* [NET_FLOW_TABLE_ATTR_SIZE]
* [NET_FLOW_TABLE_ATTR_FEATURES]
+ * [NET_FLOW_TABLE_ATTR_FLOW_REM]
* [NET_FLOW_TABLE_ATTR_MATCHES]
* [NET_FLOW_FIELD_REF]
* [NET_FLOW_FIELD_REF]
@@ -159,6 +160,7 @@
* [NET_FLOW_ATTR_BYTE_COUNT]
* [NET_FLOW_ATTR_PACKET_COUNT]
* [NET_FLOW_ATTR_LAST_USED]
+ * [NET_FLOW_ATTR_FLOW_REM]
* [NET_FLOW_MATCHES]
* [NET_FLOW_FIELD_REF]
* [NET_FLOW_FIELD_REF]
@@ -196,6 +198,39 @@
* [NET_FLOW_NOTIFICATION]
* [NET_FLOW_NOTIFICATION_ATTR_TYPE]
* [NET_FLOW_NOTIFICATION_ATTR_PIDS]
+ *
+ * Flow Removed Notification <Kernel-to-user notification>
+ *
+ * [NET_FLOW_REM_FLOW]
+ * [NET_FLOW_REM_FLOW_TABLE]
+ * [NET_FLOW_REM_FLOW_REASON]
+ * [NET_FLOW_REM_FLOW_COUNT]
+ * [NET_FLOW_REM_FLOWS_FLOWS]
+ * [NET_FLOW_FLOW]
+ * [NET_FLOW_ATTR_TABLE]
+ * [NET_FLOW_ATTR_UID]
+ * [NET_FLOW_ATTR_PRIORITY]
+ * [NET_FLOW_ATTR_IDLE_TIMEOUT]
+ * [NET_FLOW_ATTR_HARD_TIMEOUT]
+ * [NET_FLOW_ATTR_BYTE_COUNT]
+ * [NET_FLOW_ATTR_PACKET_COUNT]
+ * [NET_FLOW_ATTR_USED]
+ * [NET_FLOW_ATTR_FLOW_REM]
+ * [NET_FLOW_ATTR_MATCHES]
+ * [NET_FLOW_FIELD_REF]
+ * [NET_FLOW_FIELD_REF]
+ * [...]
+ * [NET_FLOW_ATTR_ACTIONS]
+ * [NET_FLOW_ACTION]
+ * [NET_FLOW_ACTION_ATTR_UID]
+ * [NET_FLOW_ACTION_ATTR_SIGNATURE]
+ * [NET_FLOW_ACTION_ARG]
+ * [...]
+ * [NET_FLOW_ACTION]
+ * [..]
+ * [...]
+ * [NET_FLOW_FLOW]
+ * [...]
*/
#ifndef _UAPI_LINUX_IF_FLOW
@@ -397,7 +432,9 @@ enum {
* Zero for no timeout.
* @byte_count bytes recieved
* @byte_count packets recieved
- * @last_used time of most recent use (msec since system initialisation)
+ * @used time of most recent use (msec)
+ * @flow_rem flow notifications to send.
+ * Bitmap of NET_FLOW_REM_F_*
*
* Flows must match all entries in match set.
*/
@@ -407,6 +444,7 @@ struct net_flow_flow {
int priority;
__u32 idle_timeout;
__u32 hard_timeout;
+ __u32 flow_rem;
__u64 byte_count;
__u64 packet_count;
__u64 last_used;
@@ -453,6 +491,7 @@ enum {
NET_FLOW_ATTR_BYTE_COUNT,
NET_FLOW_ATTR_PACKET_COUNT,
NET_FLOW_ATTR_LAST_USED,
+ NET_FLOW_ATTR_FLOW_REM,
__NET_FLOW_ATTR_MAX,
};
#define NET_FLOW_ATTR_MAX (__NET_FLOW_ATTR_MAX - 1)
@@ -464,6 +503,9 @@ enum {
* @uid unique identifier for table
* @source uid of parent table
* @size max number of entries for table or -1 for unbounded
+ * @features Features supported by table. Bitmap of NET_FLOW_TABLE_F_*
+ * @flow_rem Flow removal notifications supported by table.
+ Bitmap of NET_FLOW_REM_F_*
* @matches null terminated set of supported match types given by match uid
* @actions null terminated set of supported action types given by action uid
* @flows set of flows
@@ -474,6 +516,7 @@ struct net_flow_table {
int source;
int size;
__u32 features;
+ __u32 flow_rem;
struct net_flow_field_ref *matches;
net_flow_action_ref *actions;
};
@@ -494,6 +537,7 @@ enum {
NET_FLOW_TABLE_ATTR_MATCHES,
NET_FLOW_TABLE_ATTR_ACTIONS,
NET_FLOW_TABLE_ATTR_FEATURES,
+ NET_FLOW_TABLE_ATTR_FLOW_REM,
__NET_FLOW_TABLE_ATTR_MAX,
};
#define NET_FLOW_TABLE_ATTR_MAX (__NET_FLOW_TABLE_ATTR_MAX - 1)
@@ -669,6 +713,29 @@ enum {
#define NET_FLOW_NOTIFICATION_ATTR_MAX (__NET_FLOW_NOTIFICATION_ATTR_MAX - 1)
enum {
+ NET_FLOW_REM_FLOW_UNSPEC,
+ NET_FLOW_REM_FLOW_TABLE,
+ NET_FLOW_REM_FLOW_REASON,
+ NET_FLOW_REM_FLOW_COUNT,
+ NET_FLOW_REM_FLOW_FLOWS,
+
+ __NET_FLOW_REM_FLOW_MAX,
+ NET_FLOW_REM_FLOW_MAX = (__NET_FLOW_REM_FLOW_MAX - 1),
+};
+
+enum net_flow_rem_reason {
+ NET_FLOW_REM_FLOW_REASON_IDLE_TIMEOUT, /* Idle timeout */
+ NET_FLOW_REM_FLOW_REASON_HARD_TIMEOUT, /* Hard timeout */
+ NET_FLOW_REM_FLOW_REASON_DELETE, /* Deleted (by NET_FLOW_TABLE_CMD_DEL_FLOWS) */
+};
+
+enum {
+ NET_FLOW_REM_F_IDLE_TIMEOUT = (1 << NET_FLOW_REM_FLOW_REASON_IDLE_TIMEOUT),
+ NET_FLOW_REM_F_HARD_TIMEOUT = (1 << NET_FLOW_REM_FLOW_REASON_HARD_TIMEOUT),
+ NET_FLOW_REM_F_DELETE = (1 << NET_FLOW_REM_FLOW_REASON_DELETE),
+};
+
+enum {
NET_FLOW_UNSPEC,
NET_FLOW_IDENTIFIER_TYPE,
NET_FLOW_IDENTIFIER,
@@ -681,12 +748,14 @@ enum {
NET_FLOW_FLOWS,
NET_FLOW_FLOWS_ERROR,
NET_FLOW_NOTIFICATION,
+ NET_FLOW_REM_FLOW,
__NET_FLOW_MAX,
NET_FLOW_MAX = (__NET_FLOW_MAX - 1),
};
enum {
+ /* Userspace commands. */
NET_FLOW_TABLE_CMD_GET_TABLES,
NET_FLOW_TABLE_CMD_GET_HEADERS,
NET_FLOW_TABLE_CMD_GET_ACTIONS,
@@ -704,6 +773,9 @@ enum {
NET_FLOW_TABLE_CMD_SET_NOTIFICATION,
NET_FLOW_TABLE_CMD_GET_NOTIFICATION,
+ /* Kernel-to-user notifications. */
+ NET_FLOW_TABLE_CMD_REM_FLOW,
+
__NET_FLOW_CMD_MAX,
NET_FLOW_CMD_MAX = (__NET_FLOW_CMD_MAX - 1),
};
diff --git a/net/core/flow_table.c b/net/core/flow_table.c
index e8047eb..10b113f 100644
--- a/net/core/flow_table.c
+++ b/net/core/flow_table.c
@@ -58,6 +58,7 @@ struct nla_policy net_flow_flow_policy[NET_FLOW_ATTR_MAX + 1] = {
[NET_FLOW_ATTR_BYTE_COUNT] = { .type = NLA_U64 },
[NET_FLOW_ATTR_PACKET_COUNT] = { .type = NLA_U64 },
[NET_FLOW_ATTR_LAST_USED] = { .type = NLA_U64 },
+ [NET_FLOW_ATTR_FLOW_REM] = { .type = NLA_U32 },
[NET_FLOW_ATTR_MATCHES] = { .type = NLA_NESTED },
[NET_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
};
@@ -70,6 +71,7 @@ struct nla_policy net_flow_table_policy[NET_FLOW_TABLE_ATTR_MAX + 1] = {
[NET_FLOW_TABLE_ATTR_SOURCE] = { .type = NLA_U32 },
[NET_FLOW_TABLE_ATTR_SIZE] = { .type = NLA_U32 },
[NET_FLOW_TABLE_ATTR_FEATURES] = { .type = NLA_U32 },
+ [NET_FLOW_TABLE_ATTR_FLOW_REM] = { .type = NLA_U32 },
[NET_FLOW_TABLE_ATTR_MATCHES] = { .type = NLA_NESTED },
[NET_FLOW_TABLE_ATTR_ACTIONS] = { .type = NLA_NESTED },
};
@@ -190,7 +192,8 @@ int net_flow_put_flow_action(struct sk_buff *skb, struct net_flow_action *a)
int net_flow_put_flow(struct sk_buff *skb, struct net_flow_flow *flow)
{
- struct nlattr *flows, *matches;
+ struct nlattr *flows;
+ struct nlattr *matches = NULL; /* must be null to unwind */
struct nlattr *actions = NULL; /* must be null to unwind */
int err, j, i = 0;
@@ -220,6 +223,10 @@ int net_flow_put_flow(struct sk_buff *skb, struct net_flow_flow *flow)
nla_put_u32(skb, NET_FLOW_ATTR_LAST_USED, flow->last_used))
goto flows_put_failure;
+ if (flow->flow_rem &&
+ nla_put_u32(skb, NET_FLOW_ATTR_FLOW_REM,
+ flow->flow_rem))
+
matches = nla_nest_start(skb, NET_FLOW_ATTR_MATCHES);
if (!matches)
goto flows_put_failure;
@@ -273,6 +280,10 @@ static int net_flow_put_table(struct net_device *dev,
nla_put_u32(skb, NET_FLOW_TABLE_ATTR_FEATURES, t->features))
return -EMSGSIZE;
+ if (t->flow_rem &&
+ nla_put_u32(skb, NET_FLOW_TABLE_ATTR_FLOW_REM, t->flow_rem))
+ return -EMSGSIZE;
+
matches = nla_nest_start(skb, NET_FLOW_TABLE_ATTR_MATCHES);
if (!matches)
return -EMSGSIZE;
@@ -556,6 +567,8 @@ static int net_flow_get_flow(struct net_flow_flow *flow, struct nlattr *attr)
flow->packet_count = nla_get_u64(f[NET_FLOW_ATTR_PACKET_COUNT]);
if (f[NET_FLOW_ATTR_LAST_USED])
flow->last_used = nla_get_u64(f[NET_FLOW_ATTR_LAST_USED]);
+ if (f[NET_FLOW_ATTR_FLOW_REM])
+ flow->flow_rem = nla_get_u32(f[NET_FLOW_ATTR_FLOW_REM]);
flow->matches = NULL;
flow->actions = NULL;
@@ -654,6 +667,9 @@ static int net_flow_get_table(struct net_flow_table *table, struct nlattr *nla)
table->features = tbl[NET_FLOW_TABLE_ATTR_FEATURES] ?
nla_get_u32(tbl[NET_FLOW_TABLE_ATTR_FEATURES]) : 0;
+ table->flow_rem = tbl[NET_FLOW_TABLE_ATTR_FLOW_REM] ?
+ nla_get_u32(tbl[NET_FLOW_TABLE_ATTR_FLOW_REM]) : 0;
+
if (tbl[NET_FLOW_TABLE_ATTR_MATCHES]) {
cnt = 0;
nla_for_each_nested(i, tbl[NET_FLOW_TABLE_ATTR_MATCHES], rem)
@@ -796,11 +812,13 @@ static struct net_flow_table *net_flow_table_get_table(struct net_device *dev,
}
static int net_flow_table_check_features(struct net_device *dev,
- int table_uid, u32 used_features)
+ int table_uid, u32 used_features,
+ u32 used_flow_rem)
{
struct net_flow_table *table;
- if (!used_features) /* No features: no problems */
+ /* No features, no flags: no problems */
+ if (!used_features && !used_flow_rem)
return 0;
table = net_flow_table_get_table(dev, table_uid);
@@ -810,6 +828,9 @@ static int net_flow_table_check_features(struct net_device *dev,
if ((used_features & table->features) != used_features)
return -EINVAL;
+ if ((used_flow_rem & table->flow_rem) != used_flow_rem)
+ return -EINVAL;
+
return 0;
}
@@ -1415,7 +1436,8 @@ static int net_flow_table_cmd_flows(struct sk_buff *recv_skb,
used_features |= NET_FLOW_TABLE_F_PACKET_LAST_USED;
err = net_flow_table_check_features(dev, this.table_id,
- used_features);
+ used_features,
+ this.flow_rem);
if (err)
break;
@@ -1629,6 +1651,68 @@ err:
return err;
}
+/**
+ * net_flow_put_rem_flow_summary_msg
+ * @dev: network device of flow table from which flows that were removed
+ * @net: network namespce to use when sending message
+ * @portid: netlink portid of the destination socket
+ * @table: table that flows were removed from
+ * @reason: reason for removal
+ * @n_flows: number of flows rem
+ * @flags: the type of memory to allocate
+ */
+int net_flow_put_rem_flow_summary_msg(struct net_device *dev,
+ struct net *net, u32 portid, int table,
+ u32 reason, int n_flows, gfp_t flags)
+{
+ int err = -ENOBUFS;
+ struct genl_info info = {
+ .dst_sk = net->genl_sock,
+ .snd_portid = portid,
+ };
+ struct genlmsghdr *hdr;
+ struct nlattr *start;
+ struct sk_buff *skb;
+
+ skb = genlmsg_new_unicast(NLMSG_DEFAULT_SIZE, &info, flags);
+ if (!skb)
+ goto err;
+
+ hdr = genlmsg_put(skb, 0, 0, &net_flow_nl_family, 0,
+ NET_FLOW_TABLE_CMD_REM_FLOW);
+ if (!hdr)
+ goto err;
+
+ if (nla_put_u32(skb, NET_FLOW_IDENTIFIER_TYPE, NET_FLOW_IDENTIFIER_IFINDEX) ||
+ nla_put_u32(skb, NET_FLOW_IDENTIFIER, dev->ifindex))
+ goto err;
+
+ start = nla_nest_start(skb, NET_FLOW_REM_FLOW);
+ if (!start) {
+ err = -EMSGSIZE;
+ goto err;
+ }
+
+ if (nla_put_u32(skb, NET_FLOW_REM_FLOW_TABLE, table) ||
+ nla_put_u32(skb, NET_FLOW_REM_FLOW_REASON, reason) ||
+ nla_put_u32(skb, NET_FLOW_REM_FLOW_COUNT, n_flows))
+ goto err;
+
+ nla_nest_end(skb, start);
+
+ err = genlmsg_end(skb, hdr);
+ if (err < 0)
+ goto err;
+
+ err = genlmsg_unicast(net, skb, portid);
+ skb = NULL;
+
+err:
+ kfree_skb(skb);
+ return err;
+}
+EXPORT_SYMBOL(net_flow_put_rem_flow_summary_msg);
+
static const struct genl_ops net_flow_table_nl_ops[] = {
{
.cmd = NET_FLOW_TABLE_CMD_GET_TABLES,
--
2.1.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH/RFC flow-net-next 07/10] net: flow: Add importance to flows
2014-12-29 2:15 [PATCH/RFC flow-net-next 00/10] Flow Table API Cache Enhancements Simon Horman
` (5 preceding siblings ...)
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 06/10] net: flow: Add flow removed notification Simon Horman
@ 2014-12-29 2:15 ` Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 08/10] net: flow: Add get and set table config commands Simon Horman
` (2 subsequent siblings)
9 siblings, 0 replies; 15+ messages in thread
From: Simon Horman @ 2014-12-29 2:15 UTC (permalink / raw)
To: John Fastabend, netdev; +Cc: Simon Horman
This is in preparation for adding support for eviction of flows
from tables when resource contention occurs. The importance of
a flow may be used to influence the eviction algorithm.
Inspired by the eviction feature of OpenFlow.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
Compile tested only
---
include/uapi/linux/if_flow.h | 14 ++++++++++++++
net/core/flow_table.c | 12 ++++++++++++
2 files changed, 26 insertions(+)
diff --git a/include/uapi/linux/if_flow.h b/include/uapi/linux/if_flow.h
index d1643f3..91fcfb4 100644
--- a/include/uapi/linux/if_flow.h
+++ b/include/uapi/linux/if_flow.h
@@ -126,6 +126,7 @@
* [NET_FLOW_ATTR_TABLE]
* [NET_FLOW_ATTR_UID]
* [NET_FLOW_ATTR_PRIORITY]
+ * [NET_FLOW_ATTR_IMPORTANCE]
* [NET_FLOW_ATTR_IDLE_TIMEOUT]
* [NET_FLOW_ATTR_HARD_TIMEOUT]
* [NET_FLOW_ATTR_BYTE_COUNT]
@@ -155,6 +156,7 @@
* [NET_FLOW_ATTR_TABLE]
* [NET_FLOW_ATTR_UID]
* [NET_FLOW_ATTR_PRIORITY]
+ * [NET_FLOW_ATTR_IMPORTANCE]
* [NET_FLOW_ATTR_IDLE_TIMEOUT]
* [NET_FLOW_ATTR_HARD_TIMEOUT]
* [NET_FLOW_ATTR_BYTE_COUNT]
@@ -425,6 +427,11 @@ enum {
*
* @uid unique identifier for flow
* @priority priority to execute flow match/action in table
+ * @importance importance of flow used to influence flow eviction algorithm
+ * If eviction is enabled and uses importance then
+ * flows with lower importance values must be evicted
+ * before those with higher importance values.
+ * The values 0xffff ff00 - 0xffff ffff are reserved for future use.
* @match null terminated set of match uids match criteria
* @action null terminated set of action uids to apply to match
* @idle_timeout idle timeout of flow in seconds. Zero for no timeout.
@@ -442,6 +449,7 @@ struct net_flow_flow {
int table_id;
int uid;
int priority;
+ __u32 importance;
__u32 idle_timeout;
__u32 hard_timeout;
__u32 flow_rem;
@@ -484,6 +492,7 @@ enum {
NET_FLOW_ATTR_TABLE,
NET_FLOW_ATTR_UID,
NET_FLOW_ATTR_PRIORITY,
+ NET_FLOW_ATTR_IMPORTANCE,
NET_FLOW_ATTR_MATCHES,
NET_FLOW_ATTR_ACTIONS,
NET_FLOW_ATTR_IDLE_TIMEOUT,
@@ -496,6 +505,8 @@ enum {
};
#define NET_FLOW_ATTR_MAX (__NET_FLOW_ATTR_MAX - 1)
+#define NET_FLOW_ATTR_IMPORTANCE_MAX (0xfffffff00 - 1)
+
/**
* @struct net_flow_table
* @brief define flow table with supported match/actions
@@ -557,6 +568,9 @@ enum {
/* Table supports last used counter for flows */
NET_FLOW_TABLE_F_PACKET_LAST_USED = (1 << 4),
+
+ /* Table supports importance of flows */
+ NET_FLOW_TABLE_F_IMPORTANCE = (1 << 5),
};
#if 0
diff --git a/net/core/flow_table.c b/net/core/flow_table.c
index 10b113f..0bf399c 100644
--- a/net/core/flow_table.c
+++ b/net/core/flow_table.c
@@ -53,6 +53,7 @@ struct nla_policy net_flow_flow_policy[NET_FLOW_ATTR_MAX + 1] = {
[NET_FLOW_ATTR_TABLE] = { .type = NLA_U32 },
[NET_FLOW_ATTR_UID] = { .type = NLA_U32 },
[NET_FLOW_ATTR_PRIORITY] = { .type = NLA_U32 },
+ [NET_FLOW_ATTR_IMPORTANCE] = { .type = NLA_U32 },
[NET_FLOW_ATTR_IDLE_TIMEOUT] = { .type = NLA_U32 },
[NET_FLOW_ATTR_HARD_TIMEOUT] = { .type = NLA_U32 },
[NET_FLOW_ATTR_BYTE_COUNT] = { .type = NLA_U64 },
@@ -206,6 +207,11 @@ int net_flow_put_flow(struct sk_buff *skb, struct net_flow_flow *flow)
nla_put_u32(skb, NET_FLOW_ATTR_PRIORITY, flow->priority))
goto flows_put_failure;
+ if (flow->importance &&
+ (nla_put_u32(skb, NET_FLOW_ATTR_IMPORTANCE, flow->importance) ||
+ flow->importance > NET_FLOW_ATTR_IMPORTANCE_MAX))
+ goto flows_put_failure;
+
if (flow->idle_timeout &&
nla_put_u32(skb, NET_FLOW_ATTR_IDLE_TIMEOUT, flow->idle_timeout))
goto flows_put_failure;
@@ -556,6 +562,9 @@ static int net_flow_get_flow(struct net_flow_flow *flow, struct nlattr *attr)
flow->uid = nla_get_u32(f[NET_FLOW_ATTR_UID]);
flow->priority = nla_get_u32(f[NET_FLOW_ATTR_PRIORITY]);
+ if (f[NET_FLOW_ATTR_IMPORTANCE])
+ flow->importance = nla_get_u32(f[NET_FLOW_ATTR_IMPORTANCE]);
+
if (f[NET_FLOW_ATTR_IDLE_TIMEOUT])
flow->idle_timeout = nla_get_u32(f[NET_FLOW_ATTR_IDLE_TIMEOUT]);
if (f[NET_FLOW_ATTR_HARD_TIMEOUT])
@@ -1423,6 +1432,9 @@ static int net_flow_table_cmd_flows(struct sk_buff *recv_skb,
if (err)
goto out;
+ if (this.importance)
+ used_features |= NET_FLOW_TABLE_F_IMPORTANCE;
+
if (this.idle_timeout)
used_features |= NET_FLOW_TABLE_F_IDLE_TIMEOUT;
if (this.hard_timeout)
--
2.1.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH/RFC flow-net-next 08/10] net: flow: Add get and set table config commands
2014-12-29 2:15 [PATCH/RFC flow-net-next 00/10] Flow Table API Cache Enhancements Simon Horman
` (6 preceding siblings ...)
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 07/10] net: flow: Add importance to flows Simon Horman
@ 2014-12-29 2:15 ` Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 09/10] net: flow: Add eviction flags to table configuration Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 10/10] net: flow: Add flow removed notification for eviction Simon Horman
9 siblings, 0 replies; 15+ messages in thread
From: Simon Horman @ 2014-12-29 2:15 UTC (permalink / raw)
To: John Fastabend, netdev; +Cc: Simon Horman
The intention of this is to allow querying and setting of
configuration attributes of tables which may be useful to manipulate
at runtime. A subsequent patch which proposes per-table eviction settings
will make use of this.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
Compile tested only
---
include/linux/netdevice.h | 4 +
include/uapi/linux/if_flow.h | 39 ++++++++++
net/core/flow_table.c | 176 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 219 insertions(+)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 1174ab7..6073004 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1171,6 +1171,10 @@ struct net_device_ops {
int (*ndo_flow_get_notification)(struct net_device *dev,
u32 type, u32 **pids,
size_t *n_pids);
+ struct net_flow_table_config *(*ndo_flow_table_get_table_config)(struct net_device *dev,
+ int table);
+ int (*ndo_flow_table_set_table_config)(struct net_device *dev,
+ struct net_flow_table_config *tc);
};
/**
diff --git a/include/uapi/linux/if_flow.h b/include/uapi/linux/if_flow.h
index 91fcfb4..bd29145 100644
--- a/include/uapi/linux/if_flow.h
+++ b/include/uapi/linux/if_flow.h
@@ -177,6 +177,17 @@
* [..]
* [...]
*
+ * Get Table Settings <REQUEST> and <REPLY>, and
+ * Set Table Settings <REQUEST> description
+ *
+ * This is intended for configuring run-time attributes of a table.
+ * No such attributes are defined yet.
+ *
+ * [NET_FLOW_TABLE_CONFIGS]
+ * [NET_FLOW_TABLE_CONFIG_TABLE]
+ * [NET_FLOW_TABLE_CONFIG_TABLE_ATTR_UID]
+ * ...
+ *
* Set Flow Notification <Request>,
* Get Flow Notification <Request> and
* Get Flow Notification <Reply> description.
@@ -726,6 +737,30 @@ enum {
};
#define NET_FLOW_NOTIFICATION_ATTR_MAX (__NET_FLOW_NOTIFICATION_ATTR_MAX - 1)
+/**
+ * @struct net_flow_table
+ * @brief flow table configuration
+ *
+ * @table unique identifier of table
+ */
+struct net_flow_table_config {
+ int table;
+};
+
+enum {
+ NET_FLOW_TABLE_CONFIG_UNSPEC,
+ NET_FLOW_TABLE_CONFIG_TABLE,
+ __NET_FLOW_TABLE_CONFIG_MAX,
+};
+#define NET_FLOW_TABLE_CONFIG_MAX (__NET_FLOW_TABLE_CONFIG_MAX - 1)
+
+enum {
+ NET_FLOW_TABLE_CONFIG_TABLE_ATTR_UNSPEC,
+ NET_FLOW_TABLE_CONFIG_TABLE_ATTR_UID,
+ __NET_FLOW_TABLE_CONFIG_TABLE_ATTR_MAX,
+};
+#define NET_FLOW_TABLE_CONFIG_TABLE_ATTR_MAX (__NET_FLOW_TABLE_CONFIG_TABLE_ATTR_MAX - 1)
+
enum {
NET_FLOW_REM_FLOW_UNSPEC,
NET_FLOW_REM_FLOW_TABLE,
@@ -763,6 +798,7 @@ enum {
NET_FLOW_FLOWS_ERROR,
NET_FLOW_NOTIFICATION,
NET_FLOW_REM_FLOW,
+ NET_FLOW_TABLE_CONFIGS,
__NET_FLOW_MAX,
NET_FLOW_MAX = (__NET_FLOW_MAX - 1),
@@ -784,6 +820,9 @@ enum {
NET_FLOW_TABLE_CMD_CREATE_TABLE,
NET_FLOW_TABLE_CMD_DESTROY_TABLE,
+ NET_FLOW_TABLE_CMD_SET_TABLE_CONFIG,
+ NET_FLOW_TABLE_CMD_GET_TABLE_CONFIG,
+
NET_FLOW_TABLE_CMD_SET_NOTIFICATION,
NET_FLOW_TABLE_CMD_GET_NOTIFICATION,
diff --git a/net/core/flow_table.c b/net/core/flow_table.c
index 0bf399c..6c44311 100644
--- a/net/core/flow_table.c
+++ b/net/core/flow_table.c
@@ -1514,6 +1514,172 @@ out:
}
static const
+
+struct nla_policy net_flow_table_config_policy[NET_FLOW_TABLE_CONFIG_MAX + 1] = {
+ [NET_FLOW_TABLE_CONFIG_TABLE] = { .type = NLA_U32,},
+};
+
+static int net_flow_table_cmd_get_table_config(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ int rem, err;
+ struct genlmsghdr *hdr;
+ struct net_device *dev;
+ struct nlattr *tattr;
+ struct sk_buff *msg = NULL;
+
+ dev = net_flow_table_get_dev(info);
+ if (!dev)
+ return -EINVAL;
+
+ if (!dev->netdev_ops->ndo_flow_table_get_table_config) {
+ err = -EOPNOTSUPP;
+ goto err;
+ }
+
+ if (!info->attrs[NET_FLOW_TABLE_CONFIGS]) {
+ err = -EINVAL;
+ goto err;
+ }
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg) {
+ err = -ENOBUFS;
+ goto err;
+ }
+
+ hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+ &net_flow_nl_family, 0,
+ NET_FLOW_TABLE_CMD_GET_TABLE_CONFIG);
+ if (!hdr) {
+ err = -ENOBUFS;
+ goto err;
+ }
+
+ if (nla_put_u32(msg, NET_FLOW_IDENTIFIER_TYPE, NET_FLOW_IDENTIFIER_IFINDEX) ||
+ nla_put_u32(msg, NET_FLOW_IDENTIFIER, dev->ifindex)) {
+ err = -ENOBUFS;
+ goto err;
+ }
+
+ nla_for_each_nested(tattr, info->attrs[NET_FLOW_TABLE_CONFIGS], rem) {
+ const struct net_flow_table_config *tc;
+ int table;
+ struct nlattr *config;
+ struct nlattr *tb[NET_FLOW_TABLE_CONFIG_TABLE_ATTR_MAX+1];
+
+ if (nla_type(tattr) != NET_FLOW_TABLE_CONFIG_TABLE)
+ continue;
+
+ err = nla_parse_nested(tb, NET_FLOW_TABLE_FLOWS_MAX,
+ tattr, net_flow_table_flows_policy);
+ if (err)
+ goto err;
+
+ if (!tb[NET_FLOW_TABLE_CONFIG_TABLE_ATTR_UID]) {
+ err = -EINVAL;
+ goto err;
+ }
+ table = nla_get_u32(tb[NET_FLOW_TABLE_CONFIG_TABLE_ATTR_UID]);
+
+ tc = dev->netdev_ops->ndo_flow_table_get_table_config(dev, table);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ goto err;
+ }
+
+ config = nla_nest_start(msg, NET_FLOW_FLOWS);
+ if (!config) {
+ err = -EMSGSIZE;
+ goto err;
+ }
+
+ if (nla_put_u32(msg, NET_FLOW_TABLE_CONFIG_TABLE_ATTR_UID,
+ table)) {
+ err = -ENOBUFS;
+ goto err;
+ }
+
+ /* Write other attributes of tc: Currently none are defined. */
+
+ nla_nest_end(msg, config);
+ }
+
+ err = genlmsg_end(msg, hdr);
+ if (err < 0)
+ goto err;
+
+ dev_put(dev);
+
+ return genlmsg_reply(msg, info);
+
+err:
+ dev_put(dev);
+ nlmsg_free(msg);
+ return err;
+}
+
+static int net_flow_table_cmd_set_table_config(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ int rem, err;
+ struct net_device *dev;
+ struct nlattr *tattr;
+
+ dev = net_flow_table_get_dev(info);
+ if (!dev)
+ return -EINVAL;
+
+ if (!dev->netdev_ops->ndo_flow_table_get_table_config ||
+ !dev->netdev_ops->ndo_flow_table_set_table_config) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (!info->attrs[NET_FLOW_TABLE_CONFIGS]) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ nla_for_each_nested(tattr, info->attrs[NET_FLOW_TABLE_CONFIGS], rem) {
+ int table;
+ struct net_flow_table_config *tc;
+ struct net_flow_table_config new_tc;
+ struct nlattr *tb[NET_FLOW_TABLE_CONFIG_TABLE_ATTR_MAX+1];
+
+ if (nla_type(tattr) != NET_FLOW_TABLE_CONFIG_TABLE)
+ continue;
+
+ err = nla_parse_nested(tb, NET_FLOW_TABLE_FLOWS_MAX,
+ tattr, net_flow_table_flows_policy);
+ if (err)
+ goto out;
+
+ if (!tb[NET_FLOW_TABLE_CONFIG_TABLE_ATTR_UID]) {
+ err = -EINVAL;
+ goto out;
+ }
+ table = nla_get_u32(tb[NET_FLOW_TABLE_CONFIG_TABLE_ATTR_UID]);
+
+ tc = dev->netdev_ops->ndo_flow_table_get_table_config(dev, table);
+ if (IS_ERR(tc)) {
+ err = PTR_ERR(tc);
+ goto out;
+ }
+
+ new_tc = *tc;
+
+ err = dev->netdev_ops->ndo_flow_table_set_table_config(dev, &new_tc);
+ if (err)
+ goto out;
+ }
+
+out:
+ dev_put(dev);
+ return err;
+}
+
+static const
struct nla_policy net_flow_notification_policy[NET_FLOW_NOTIFICATION_ATTR_MAX + 1] = {
[NET_FLOW_NOTIFICATION_ATTR_TYPE] = { .type = NLA_U32,},
[NET_FLOW_NOTIFICATION_ATTR_PIDS] = { .type = NLA_U32,},
@@ -1789,6 +1955,16 @@ static const struct genl_ops net_flow_table_nl_ops[] = {
.flags = GENL_ADMIN_PERM,
},
{
+ .cmd = NET_FLOW_TABLE_CMD_SET_TABLE_CONFIG,
+ .doit = net_flow_table_cmd_set_table_config,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
+ .cmd = NET_FLOW_TABLE_CMD_GET_TABLE_CONFIG,
+ .doit = net_flow_table_cmd_get_table_config,
+ .flags = GENL_ADMIN_PERM,
+ },
+ {
.cmd = NET_FLOW_TABLE_CMD_SET_NOTIFICATION,
.doit = net_flow_table_cmd_set_notification,
.flags = GENL_ADMIN_PERM,
--
2.1.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH/RFC flow-net-next 09/10] net: flow: Add eviction flags to table configuration
2014-12-29 2:15 [PATCH/RFC flow-net-next 00/10] Flow Table API Cache Enhancements Simon Horman
` (7 preceding siblings ...)
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 08/10] net: flow: Add get and set table config commands Simon Horman
@ 2014-12-29 2:15 ` Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 10/10] net: flow: Add flow removed notification for eviction Simon Horman
9 siblings, 0 replies; 15+ messages in thread
From: Simon Horman @ 2014-12-29 2:15 UTC (permalink / raw)
To: John Fastabend, netdev; +Cc: Simon Horman
The intention is to allow run-time configuration of if and how
a switch or switch-like device may evict flows from tables in
the case of resource contention.
Inspired by a feature of the same name in in OpenFlow.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
include/uapi/linux/if_flow.h | 16 ++++++++++++++++
net/core/flow_table.c | 11 ++++++++---
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/include/uapi/linux/if_flow.h b/include/uapi/linux/if_flow.h
index bd29145..7264629 100644
--- a/include/uapi/linux/if_flow.h
+++ b/include/uapi/linux/if_flow.h
@@ -186,6 +186,7 @@
* [NET_FLOW_TABLE_CONFIGS]
* [NET_FLOW_TABLE_CONFIG_TABLE]
* [NET_FLOW_TABLE_CONFIG_TABLE_ATTR_UID]
+ * [NET_FLOW_TABLE_CONFIG_TABLE_ATTR_EVICTION]
* ...
*
* Set Flow Notification <Request>,
@@ -742,9 +743,11 @@ enum {
* @brief flow table configuration
*
* @table unique identifier of table
+ * @eviction flags to control eviction. Bitmask of NET_FLOW_EVICTION_F_*
*/
struct net_flow_table_config {
int table;
+ __u32 eviction;
};
enum {
@@ -757,10 +760,23 @@ enum {
enum {
NET_FLOW_TABLE_CONFIG_TABLE_ATTR_UNSPEC,
NET_FLOW_TABLE_CONFIG_TABLE_ATTR_UID,
+ NET_FLOW_TABLE_CONFIG_TABLE_ATTR_EVICTION,
__NET_FLOW_TABLE_CONFIG_TABLE_ATTR_MAX,
};
#define NET_FLOW_TABLE_CONFIG_TABLE_ATTR_MAX (__NET_FLOW_TABLE_CONFIG_TABLE_ATTR_MAX - 1)
+
+enum {
+ /* Eviction enabled.
+ * Must be set for any eviction to occur */
+ NET_FLOW_EVICTION_F_ENABLE = (0 << 1),
+
+ /* Evict entries based on their importance */
+ NET_FLOW_EVICTION_F_IMPORTANCE = (1 << 1),
+ /* Evict entries based on how close they are to timing out */
+ NET_FLOW_EVICTION_F_TIMEOUT = (2 << 1),
+};
+
enum {
NET_FLOW_REM_FLOW_UNSPEC,
NET_FLOW_REM_FLOW_TABLE,
diff --git a/net/core/flow_table.c b/net/core/flow_table.c
index 6c44311..3030246 100644
--- a/net/core/flow_table.c
+++ b/net/core/flow_table.c
@@ -1595,13 +1595,14 @@ static int net_flow_table_cmd_get_table_config(struct sk_buff *skb,
}
if (nla_put_u32(msg, NET_FLOW_TABLE_CONFIG_TABLE_ATTR_UID,
- table)) {
+ table) ||
+ nla_put_u32(msg,
+ NET_FLOW_TABLE_CONFIG_TABLE_ATTR_EVICTION,
+ tc->eviction)) {
err = -ENOBUFS;
goto err;
}
- /* Write other attributes of tc: Currently none are defined. */
-
nla_nest_end(msg, config);
}
@@ -1669,6 +1670,10 @@ static int net_flow_table_cmd_set_table_config(struct sk_buff *skb,
new_tc = *tc;
+ if (!tb[NET_FLOW_TABLE_CONFIG_TABLE_ATTR_EVICTION]) {
+ new_tc.eviction = nla_get_u32(tb[NET_FLOW_TABLE_CONFIG_TABLE_ATTR_EVICTION]);
+ }
+
err = dev->netdev_ops->ndo_flow_table_set_table_config(dev, &new_tc);
if (err)
goto out;
--
2.1.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH/RFC flow-net-next 10/10] net: flow: Add flow removed notification for eviction
2014-12-29 2:15 [PATCH/RFC flow-net-next 00/10] Flow Table API Cache Enhancements Simon Horman
` (8 preceding siblings ...)
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 09/10] net: flow: Add eviction flags to table configuration Simon Horman
@ 2014-12-29 2:15 ` Simon Horman
9 siblings, 0 replies; 15+ messages in thread
From: Simon Horman @ 2014-12-29 2:15 UTC (permalink / raw)
To: John Fastabend, netdev; +Cc: Simon Horman
This adds a flag to flows to allow flow removed notifications
to be sent when eviction occurs.
Inspired by OpenFlow.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
Compile tested only
---
include/uapi/linux/if_flow.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/uapi/linux/if_flow.h b/include/uapi/linux/if_flow.h
index 7264629..9db7b30 100644
--- a/include/uapi/linux/if_flow.h
+++ b/include/uapi/linux/if_flow.h
@@ -792,12 +792,14 @@ enum net_flow_rem_reason {
NET_FLOW_REM_FLOW_REASON_IDLE_TIMEOUT, /* Idle timeout */
NET_FLOW_REM_FLOW_REASON_HARD_TIMEOUT, /* Hard timeout */
NET_FLOW_REM_FLOW_REASON_DELETE, /* Deleted (by NET_FLOW_TABLE_CMD_DEL_FLOWS) */
+ NET_FLOW_REM_FLOW_REASON_EVICTION, /* Evicted by switch */
};
enum {
NET_FLOW_REM_F_IDLE_TIMEOUT = (1 << NET_FLOW_REM_FLOW_REASON_IDLE_TIMEOUT),
NET_FLOW_REM_F_HARD_TIMEOUT = (1 << NET_FLOW_REM_FLOW_REASON_HARD_TIMEOUT),
NET_FLOW_REM_F_DELETE = (1 << NET_FLOW_REM_FLOW_REASON_DELETE),
+ NET_FLOW_REM_F_EVICTION = (1 << NET_FLOW_REM_FLOW_REASON_EVICTION),
};
enum {
--
2.1.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* RE: [PATCH/RFC flow-net-next 04/10] net: flow: Add counters to flows
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 04/10] net: flow: Add counters " Simon Horman
@ 2014-12-29 7:31 ` Arad, Ronen
2015-01-05 2:10 ` Simon Horman
0 siblings, 1 reply; 15+ messages in thread
From: Arad, Ronen @ 2014-12-29 7:31 UTC (permalink / raw)
To: Simon Horman, Fastabend, John R, netdev@vger.kernel.org
>-----Original Message-----
>From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org] On
>Behalf Of Simon Horman
>Sent: Monday, December 29, 2014 4:16 AM
>To: Fastabend, John R; netdev@vger.kernel.org
>Cc: Simon Horman
>Subject: [PATCH/RFC flow-net-next 04/10] net: flow: Add counters to flows
>
>It may be useful for hardware flow table support for counters to be exposed
>via the flow API. One possible use case of this is for Open vSwitch to use
>the flow API in conjunction with its existing datapath flow management
>scheme which in a nutshell treats the datapath as a cache that times out
>idle entries.
>
>This patch exposes optionally exposes three counters:
>- Number of packets that have matched a flow
>- Number of bytes of packets that have matched a flow
>- The time in ms when the flow was last hit
>
>Inspired by the flow counters present in Open Flow.
>
>Signed-off-by: Simon Horman <simon.horman@netronome.com>
>
>---
>
>Compile tested only
>---
> include/uapi/linux/if_flow.h | 24 ++++++++++++++++++++++++
> net/core/flow_table.c | 27 +++++++++++++++++++++++++++
> 2 files changed, 51 insertions(+)
>
>diff --git a/include/uapi/linux/if_flow.h b/include/uapi/linux/if_flow.h
>index 28da45b..18214ea 100644
>--- a/include/uapi/linux/if_flow.h
>+++ b/include/uapi/linux/if_flow.h
>@@ -127,6 +127,9 @@
> * [NET_FLOW_ATTR_PRIORITY]
> * [NET_FLOW_ATTR_IDLE_TIMEOUT]
> * [NET_FLOW_ATTR_HARD_TIMEOUT]
>+ * [NET_FLOW_ATTR_BYTE_COUNT]
>+ * [NET_FLOW_ATTR_PACKET_COUNT]
>+ * [NET_FLOW_ATTR_LAST_USED]
> * [NET_FLOW_ATTR_MATCHES]
> * [NET_FLOW_FIELD_REF]
> * [NET_FLOW_FIELD_REF]
>@@ -153,6 +156,9 @@
> * [NET_FLOW_ATTR_PRIORITY]
> * [NET_FLOW_ATTR_IDLE_TIMEOUT]
> * [NET_FLOW_ATTR_HARD_TIMEOUT]
>+ * [NET_FLOW_ATTR_BYTE_COUNT]
>+ * [NET_FLOW_ATTR_PACKET_COUNT]
>+ * [NET_FLOW_ATTR_LAST_USED]
> * [NET_FLOW_MATCHES]
> * [NET_FLOW_FIELD_REF]
> * [NET_FLOW_FIELD_REF]
>@@ -365,6 +371,9 @@ enum {
> * @idle_timeout idle timeout of flow in seconds. Zero for no timeout.
> * @hard_timeout timeout of flow regardless of use in seconds.
> * Zero for no timeout.
>+ * @byte_count bytes recieved
>+ * @byte_count packets recieved
>+ * @last_used time of most recent use (msec since system initialisation)
> *
> * Flows must match all entries in match set.
> */
>@@ -374,6 +383,9 @@ struct net_flow_flow {
> int priority;
> __u32 idle_timeout;
> __u32 hard_timeout;
>+ __u64 byte_count;
>+ __u64 packet_count;
>+ __u64 last_used;
> struct net_flow_field_ref *matches;
> struct net_flow_action *actions;
> };
>@@ -414,6 +426,9 @@ enum {
> NET_FLOW_ATTR_ACTIONS,
> NET_FLOW_ATTR_IDLE_TIMEOUT,
> NET_FLOW_ATTR_HARD_TIMEOUT,
>+ NET_FLOW_ATTR_BYTE_COUNT,
>+ NET_FLOW_ATTR_PACKET_COUNT,
>+ NET_FLOW_ATTR_LAST_USED,
> __NET_FLOW_ATTR_MAX,
> };
> #define NET_FLOW_ATTR_MAX (__NET_FLOW_ATTR_MAX - 1)
>@@ -465,6 +480,15 @@ enum {
>
> /* Table supports idle timeout of flows */
> NET_FLOW_TABLE_F_HARD_TIMEOUT = (1 << 1),
>+
>+ /* Table supports byte counter for flows */
>+ NET_FLOW_TABLE_F_BYTE_COUNT = (1 << 2),
>+
>+ /* Table supports packet counter for flows */
>+ NET_FLOW_TABLE_F_PACKET_COUNT = (1 << 3),
>+
>+ /* Table supports last used counter for flows */
>+ NET_FLOW_TABLE_F_PACKET_LAST_USED = (1 << 4),
> };
>
> #if 0
>diff --git a/net/core/flow_table.c b/net/core/flow_table.c
>index 89ba9bc..070e646 100644
>--- a/net/core/flow_table.c
>+++ b/net/core/flow_table.c
>@@ -54,6 +54,9 @@ struct nla_policy net_flow_flow_policy[NET_FLOW_ATTR_MAX +
>1] = {
> [NET_FLOW_ATTR_PRIORITY] = { .type = NLA_U32 },
> [NET_FLOW_ATTR_IDLE_TIMEOUT] = { .type = NLA_U32 },
> [NET_FLOW_ATTR_HARD_TIMEOUT] = { .type = NLA_U32 },
>+ [NET_FLOW_ATTR_BYTE_COUNT] = { .type = NLA_U64 },
>+ [NET_FLOW_ATTR_PACKET_COUNT] = { .type = NLA_U64 },
>+ [NET_FLOW_ATTR_LAST_USED] = { .type = NLA_U64 },
> [NET_FLOW_ATTR_MATCHES] = { .type = NLA_NESTED },
> [NET_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
> };
>@@ -206,6 +209,16 @@ int net_flow_put_flow(struct sk_buff *skb, struct
>net_flow_flow *flow)
> nla_put_u32(skb, NET_FLOW_ATTR_HARD_TIMEOUT, flow->hard_timeout))
> goto flows_put_failure;
>
>+ if (flow->byte_count &&
>+ nla_put_u32(skb, NET_FLOW_ATTR_BYTE_COUNT, flow->byte_count))
>+ goto flows_put_failure;
>+ if (flow->packet_count &&
>+ nla_put_u32(skb, NET_FLOW_ATTR_PACKET_COUNT, flow->packet_count))
>+ goto flows_put_failure;
>+ if (flow->last_used &&
>+ nla_put_u32(skb, NET_FLOW_ATTR_LAST_USED, flow->last_used))
>+ goto flows_put_failure;
>+
The flow byte_count, packet_count, and last_used fields are defined as __u64 and related netlink attributes are of type NLA_U64 but nla_put_u32() is used to add them to the netlink msg.
> matches = nla_nest_start(skb, NET_FLOW_ATTR_MATCHES);
> if (!matches)
> goto flows_put_failure;
>@@ -536,6 +549,13 @@ static int net_flow_get_flow(struct net_flow_flow *flow,
>struct nlattr *attr)
> if (f[NET_FLOW_ATTR_HARD_TIMEOUT])
> flow->hard_timeout = nla_get_u32(f[NET_FLOW_ATTR_HARD_TIMEOUT]);
>
>+ if (f[NET_FLOW_ATTR_BYTE_COUNT])
>+ flow->byte_count = nla_get_u64(f[NET_FLOW_ATTR_BYTE_COUNT]);
>+ if (f[NET_FLOW_ATTR_PACKET_COUNT])
>+ flow->packet_count = nla_get_u64(f[NET_FLOW_ATTR_PACKET_COUNT]);
>+ if (f[NET_FLOW_ATTR_LAST_USED])
>+ flow->last_used = nla_get_u64(f[NET_FLOW_ATTR_LAST_USED]);
>+
> flow->matches = NULL;
> flow->actions = NULL;
>
>@@ -1386,6 +1406,13 @@ static int net_flow_table_cmd_flows(struct sk_buff
>*recv_skb,
> if (this.hard_timeout)
> used_features |= NET_FLOW_TABLE_F_HARD_TIMEOUT;
>
>+ if (this.byte_count)
>+ used_features |= NET_FLOW_TABLE_F_BYTE_COUNT;
>+ if (this.packet_count)
>+ used_features |= NET_FLOW_TABLE_F_PACKET_COUNT;
>+ if (this.last_used)
>+ used_features |= NET_FLOW_TABLE_F_PACKET_LAST_USED;
>+
> err = net_flow_table_check_features(dev, this.table_id,
> used_features);
> if (err)
>--
>2.1.3
>
>--
>To unsubscribe from this list: send the line "unsubscribe netdev" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH/RFC flow-net-next 02/10] net: flow: Add features to tables
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 02/10] net: flow: Add features to tables Simon Horman
@ 2014-12-29 23:03 ` Cong Wang
2015-01-05 2:18 ` Simon Horman
0 siblings, 1 reply; 15+ messages in thread
From: Cong Wang @ 2014-12-29 23:03 UTC (permalink / raw)
To: Simon Horman; +Cc: John Fastabend, netdev
On Sun, Dec 28, 2014 at 6:15 PM, Simon Horman
<simon.horman@netronome.com> wrote:
> +static struct net_flow_table *net_flow_table_get_table(struct net_device *dev,
> + int table_uid)
> +{
> + struct net_flow_table **tables;
> + int i;
> +
> + tables = net_flow_get_tables(dev);
> + if (IS_ERR(tables))
> + return ERR_PTR(PTR_ERR(tables));
Seriously? :)
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH/RFC flow-net-next 04/10] net: flow: Add counters to flows
2014-12-29 7:31 ` Arad, Ronen
@ 2015-01-05 2:10 ` Simon Horman
0 siblings, 0 replies; 15+ messages in thread
From: Simon Horman @ 2015-01-05 2:10 UTC (permalink / raw)
To: Arad, Ronen; +Cc: Fastabend, John R, netdev@vger.kernel.org
On Mon, Dec 29, 2014 at 07:31:41AM +0000, Arad, Ronen wrote:
>
>
> >-----Original Message-----
> >From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org] On
> >Behalf Of Simon Horman
> >Sent: Monday, December 29, 2014 4:16 AM
> >To: Fastabend, John R; netdev@vger.kernel.org
> >Cc: Simon Horman
> >Subject: [PATCH/RFC flow-net-next 04/10] net: flow: Add counters to flows
> >
> >It may be useful for hardware flow table support for counters to be exposed
> >via the flow API. One possible use case of this is for Open vSwitch to use
> >the flow API in conjunction with its existing datapath flow management
> >scheme which in a nutshell treats the datapath as a cache that times out
> >idle entries.
> >
> >This patch exposes optionally exposes three counters:
> >- Number of packets that have matched a flow
> >- Number of bytes of packets that have matched a flow
> >- The time in ms when the flow was last hit
> >
> >Inspired by the flow counters present in Open Flow.
> >
> >Signed-off-by: Simon Horman <simon.horman@netronome.com>
> >
> >---
> >
> >Compile tested only
> >---
> > include/uapi/linux/if_flow.h | 24 ++++++++++++++++++++++++
> > net/core/flow_table.c | 27 +++++++++++++++++++++++++++
> > 2 files changed, 51 insertions(+)
> >
> >diff --git a/include/uapi/linux/if_flow.h b/include/uapi/linux/if_flow.h
> >index 28da45b..18214ea 100644
> >--- a/include/uapi/linux/if_flow.h
> >+++ b/include/uapi/linux/if_flow.h
> >@@ -127,6 +127,9 @@
> > * [NET_FLOW_ATTR_PRIORITY]
> > * [NET_FLOW_ATTR_IDLE_TIMEOUT]
> > * [NET_FLOW_ATTR_HARD_TIMEOUT]
> >+ * [NET_FLOW_ATTR_BYTE_COUNT]
> >+ * [NET_FLOW_ATTR_PACKET_COUNT]
> >+ * [NET_FLOW_ATTR_LAST_USED]
> > * [NET_FLOW_ATTR_MATCHES]
> > * [NET_FLOW_FIELD_REF]
> > * [NET_FLOW_FIELD_REF]
> >@@ -153,6 +156,9 @@
> > * [NET_FLOW_ATTR_PRIORITY]
> > * [NET_FLOW_ATTR_IDLE_TIMEOUT]
> > * [NET_FLOW_ATTR_HARD_TIMEOUT]
> >+ * [NET_FLOW_ATTR_BYTE_COUNT]
> >+ * [NET_FLOW_ATTR_PACKET_COUNT]
> >+ * [NET_FLOW_ATTR_LAST_USED]
> > * [NET_FLOW_MATCHES]
> > * [NET_FLOW_FIELD_REF]
> > * [NET_FLOW_FIELD_REF]
> >@@ -365,6 +371,9 @@ enum {
> > * @idle_timeout idle timeout of flow in seconds. Zero for no timeout.
> > * @hard_timeout timeout of flow regardless of use in seconds.
> > * Zero for no timeout.
> >+ * @byte_count bytes recieved
> >+ * @byte_count packets recieved
> >+ * @last_used time of most recent use (msec since system initialisation)
> > *
> > * Flows must match all entries in match set.
> > */
> >@@ -374,6 +383,9 @@ struct net_flow_flow {
> > int priority;
> > __u32 idle_timeout;
> > __u32 hard_timeout;
> >+ __u64 byte_count;
> >+ __u64 packet_count;
> >+ __u64 last_used;
> > struct net_flow_field_ref *matches;
> > struct net_flow_action *actions;
> > };
> >@@ -414,6 +426,9 @@ enum {
> > NET_FLOW_ATTR_ACTIONS,
> > NET_FLOW_ATTR_IDLE_TIMEOUT,
> > NET_FLOW_ATTR_HARD_TIMEOUT,
> >+ NET_FLOW_ATTR_BYTE_COUNT,
> >+ NET_FLOW_ATTR_PACKET_COUNT,
> >+ NET_FLOW_ATTR_LAST_USED,
> > __NET_FLOW_ATTR_MAX,
> > };
> > #define NET_FLOW_ATTR_MAX (__NET_FLOW_ATTR_MAX - 1)
> >@@ -465,6 +480,15 @@ enum {
> >
> > /* Table supports idle timeout of flows */
> > NET_FLOW_TABLE_F_HARD_TIMEOUT = (1 << 1),
> >+
> >+ /* Table supports byte counter for flows */
> >+ NET_FLOW_TABLE_F_BYTE_COUNT = (1 << 2),
> >+
> >+ /* Table supports packet counter for flows */
> >+ NET_FLOW_TABLE_F_PACKET_COUNT = (1 << 3),
> >+
> >+ /* Table supports last used counter for flows */
> >+ NET_FLOW_TABLE_F_PACKET_LAST_USED = (1 << 4),
> > };
> >
> > #if 0
> >diff --git a/net/core/flow_table.c b/net/core/flow_table.c
> >index 89ba9bc..070e646 100644
> >--- a/net/core/flow_table.c
> >+++ b/net/core/flow_table.c
> >@@ -54,6 +54,9 @@ struct nla_policy net_flow_flow_policy[NET_FLOW_ATTR_MAX +
> >1] = {
> > [NET_FLOW_ATTR_PRIORITY] = { .type = NLA_U32 },
> > [NET_FLOW_ATTR_IDLE_TIMEOUT] = { .type = NLA_U32 },
> > [NET_FLOW_ATTR_HARD_TIMEOUT] = { .type = NLA_U32 },
> >+ [NET_FLOW_ATTR_BYTE_COUNT] = { .type = NLA_U64 },
> >+ [NET_FLOW_ATTR_PACKET_COUNT] = { .type = NLA_U64 },
> >+ [NET_FLOW_ATTR_LAST_USED] = { .type = NLA_U64 },
> > [NET_FLOW_ATTR_MATCHES] = { .type = NLA_NESTED },
> > [NET_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
> > };
> >@@ -206,6 +209,16 @@ int net_flow_put_flow(struct sk_buff *skb, struct
> >net_flow_flow *flow)
> > nla_put_u32(skb, NET_FLOW_ATTR_HARD_TIMEOUT, flow->hard_timeout))
> > goto flows_put_failure;
> >
> >+ if (flow->byte_count &&
> >+ nla_put_u32(skb, NET_FLOW_ATTR_BYTE_COUNT, flow->byte_count))
> >+ goto flows_put_failure;
> >+ if (flow->packet_count &&
> >+ nla_put_u32(skb, NET_FLOW_ATTR_PACKET_COUNT, flow->packet_count))
> >+ goto flows_put_failure;
> >+ if (flow->last_used &&
> >+ nla_put_u32(skb, NET_FLOW_ATTR_LAST_USED, flow->last_used))
> >+ goto flows_put_failure;
> >+
> The flow byte_count, packet_count, and last_used fields are defined as __u64 and related netlink attributes are of type NLA_U64 but nla_put_u32() is used to add them to the netlink msg.
Thanks, I will fix that up by using nla_put_u64().
> > matches = nla_nest_start(skb, NET_FLOW_ATTR_MATCHES);
> > if (!matches)
> > goto flows_put_failure;
> >@@ -536,6 +549,13 @@ static int net_flow_get_flow(struct net_flow_flow *flow,
> >struct nlattr *attr)
> > if (f[NET_FLOW_ATTR_HARD_TIMEOUT])
> > flow->hard_timeout = nla_get_u32(f[NET_FLOW_ATTR_HARD_TIMEOUT]);
> >
> >+ if (f[NET_FLOW_ATTR_BYTE_COUNT])
> >+ flow->byte_count = nla_get_u64(f[NET_FLOW_ATTR_BYTE_COUNT]);
> >+ if (f[NET_FLOW_ATTR_PACKET_COUNT])
> >+ flow->packet_count = nla_get_u64(f[NET_FLOW_ATTR_PACKET_COUNT]);
> >+ if (f[NET_FLOW_ATTR_LAST_USED])
> >+ flow->last_used = nla_get_u64(f[NET_FLOW_ATTR_LAST_USED]);
> >+
> > flow->matches = NULL;
> > flow->actions = NULL;
> >
> >@@ -1386,6 +1406,13 @@ static int net_flow_table_cmd_flows(struct sk_buff
> >*recv_skb,
> > if (this.hard_timeout)
> > used_features |= NET_FLOW_TABLE_F_HARD_TIMEOUT;
> >
> >+ if (this.byte_count)
> >+ used_features |= NET_FLOW_TABLE_F_BYTE_COUNT;
> >+ if (this.packet_count)
> >+ used_features |= NET_FLOW_TABLE_F_PACKET_COUNT;
> >+ if (this.last_used)
> >+ used_features |= NET_FLOW_TABLE_F_PACKET_LAST_USED;
> >+
> > err = net_flow_table_check_features(dev, this.table_id,
> > used_features);
> > if (err)
> >--
> >2.1.3
> >
> >--
> >To unsubscribe from this list: send the line "unsubscribe netdev" in
> >the body of a message to majordomo@vger.kernel.org
> >More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH/RFC flow-net-next 02/10] net: flow: Add features to tables
2014-12-29 23:03 ` Cong Wang
@ 2015-01-05 2:18 ` Simon Horman
0 siblings, 0 replies; 15+ messages in thread
From: Simon Horman @ 2015-01-05 2:18 UTC (permalink / raw)
To: Cong Wang; +Cc: John Fastabend, netdev
On Mon, Dec 29, 2014 at 03:03:39PM -0800, Cong Wang wrote:
> On Sun, Dec 28, 2014 at 6:15 PM, Simon Horman
> <simon.horman@netronome.com> wrote:
> > +static struct net_flow_table *net_flow_table_get_table(struct net_device *dev,
> > + int table_uid)
> > +{
> > + struct net_flow_table **tables;
> > + int i;
> > +
> > + tables = net_flow_get_tables(dev);
> > + if (IS_ERR(tables))
> > + return ERR_PTR(PTR_ERR(tables));
>
> Seriously? :)
I was looking for a way to handle the type of tables being different
to the return type of net_flow_table_get_table().
Would you recommend a cast?
return (struct net_flow_table *)tables;
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2015-01-05 2:19 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-29 2:15 [PATCH/RFC flow-net-next 00/10] Flow Table API Cache Enhancements Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 01/10] net: flow: Correct spelling of action Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 02/10] net: flow: Add features to tables Simon Horman
2014-12-29 23:03 ` Cong Wang
2015-01-05 2:18 ` Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 03/10] net: flow: Add timeouts to flows Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 04/10] net: flow: Add counters " Simon Horman
2014-12-29 7:31 ` Arad, Ronen
2015-01-05 2:10 ` Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 05/10] net: flow: Add get, set and del notifier commands Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 06/10] net: flow: Add flow removed notification Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 07/10] net: flow: Add importance to flows Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 08/10] net: flow: Add get and set table config commands Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 09/10] net: flow: Add eviction flags to table configuration Simon Horman
2014-12-29 2:15 ` [PATCH/RFC flow-net-next 10/10] net: flow: Add flow removed notification for eviction Simon Horman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).