Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH v2 3/4] can: kvaser_usb: Don't send a RESET_CHIP for non-existing channels
From: Olivier Sobrie @ 2014-12-28 21:54 UTC (permalink / raw)
  To: Ahmed S. Darwish
  Cc: Oliver Hartkopp, Wolfgang Grandegger, Marc Kleine-Budde,
	David S. Miller, Paul Gortmaker, Greg KH, Linux-CAN, netdev, LKML
In-Reply-To: <20141225000256.GB24302@vivalin-002>

On Thu, Dec 25, 2014 at 02:02:56AM +0200, Ahmed S. Darwish wrote:
> From: Ahmed S. Darwish <ahmed.darwish@valeo.com>
> 
> "Someone reported me that recent leaf firmwares go in trouble when
> you send a command for a channel that does not exist. Instead ...
> you can move the reset command to kvaser_usb_init_one() function."

Please adapt the commit log message as follows:
Recent Leaf firmware versions (>= 3.1.557) do not allow to send commands for
non-existing channels. If a command is send for a non-existing channel,
the firmware crashes.

And you can add:
Reported-by: Christopher Storah <Christopher.Storah@invetech.com.au>
Signed-off-by: Olivier Sobrie <olivier@sobrie.be>

Kr,

Olivier

> 
> Suggested-by: Olivier Sobrie <olivier@sobrie.be>
> Signed-off-by: Ahmed S. Darwish <ahmed.darwish@valeo.com>
> ---
>  drivers/net/can/usb/kvaser_usb.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c
> index 598e251..2791501 100644
> --- a/drivers/net/can/usb/kvaser_usb.c
> +++ b/drivers/net/can/usb/kvaser_usb.c
> @@ -1505,6 +1505,10 @@ static int kvaser_usb_init_one(struct usb_interface *intf,
>  	struct kvaser_usb_net_priv *priv;
>  	int i, err;
>  
> +	err = kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, channel);
> +	if (err)
> +		return err;
> +
>  	netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS);
>  	if (!netdev) {
>  		dev_err(&intf->dev, "Cannot alloc candev\n");
> @@ -1609,9 +1613,6 @@ static int kvaser_usb_probe(struct usb_interface *intf,
>  
>  	usb_set_intfdata(intf, dev);
>  
> -	for (i = 0; i < MAX_NET_DEVICES; i++)
> -		kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, i);
> -
>  	err = kvaser_usb_get_software_info(dev);
>  	if (err) {
>  		dev_err(&intf->dev,

^ permalink raw reply

* Re: [PATCH iproute2] man ss: Add state filter description
From: Vadim Kochan @ 2014-12-28 22:19 UTC (permalink / raw)
  To: netdev; +Cc: Vadim Kochan
In-Reply-To: <1419766748-4468-1-git-send-email-vadim4j@gmail.com>

On Sun, Dec 28, 2014 at 01:39:08PM +0200, Vadim Kochan wrote:
> From: Vadim Kochan <vadim4j@gmail.com>
> 
> Stolen from generated doc/ss.html
> Also added reference to RFC 739 for TCP states.
> 

Will re-send v2 because of wrong RFC number ...

^ permalink raw reply

* [PATCH iproute2 v2] man ss: Add state filter description
From: Vadim Kochan @ 2014-12-28 22:20 UTC (permalink / raw)
  To: netdev; +Cc: Vadim Kochan

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 2191 bytes --]

From: Vadim Kochan <vadim4j@gmail.com>

Stolen from generated doc/ss.html
Also added reference to RFC 793 for TCP states.

Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
---
 man/man8/ss.8 | 41 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 39 insertions(+), 2 deletions(-)

diff --git a/man/man8/ss.8 b/man/man8/ss.8
index 2a4bbc5..f4b709b 100644
--- a/man/man8/ss.8
+++ b/man/man8/ss.8
@@ -127,8 +127,41 @@ Do not display anything, just dump raw information about TCP sockets to FILE aft
 Read filter information from FILE.
 Each line of FILE is interpreted like single command line option. If FILE is - stdin is used.
 .TP
-.B FILTER := [ state TCP-STATE ] [ EXPRESSION ]
+.B FILTER := [ state STATE-FILTER ] [ EXPRESSION ]
 Please take a look at the official documentation (Debian package iproute-doc) for details regarding filters.
+
+.SH STATE-FILTER
+
+.B STATE-FILTER
+allows to construct arbitrary set of states to match. Its syntax is sequence of keywords state and exclude followed by identifier of state.
+.TP
+Available identifiers are:
+
+All standard TCP states:
+.BR established ", " syn-sent ", " syn-recv ", " fin-wait-1 ", " fin-wait-2 ", " time-wait ", " closed ", " close-wait ", " last-ack ", "
+.BR  listen " and " closing.
+
+.B all
+- for all the states
+
+.B connected
+- all the states except for
+.BR listen " and " closed
+
+.B synchronized
+- all the
+.B connected
+states except for
+.B syn-sent
+
+.B bucket
+- states, which are maintained as minisockets, i.e.
+.BR time-wait " and " syn-recv
+
+.B big
+- opposite to
+.B bucket
+
 .SH USAGE EXAMPLES
 .TP
 .B ss -t -a
@@ -150,7 +183,11 @@ Find all local processes connected to X server.
 List all the tcp sockets in state FIN-WAIT-1 for our apache to network 193.233.7/24 and look at their timers.
 .SH SEE ALSO
 .BR ip (8),
-.BR /usr/share/doc/iproute-doc/ss.html " (package iproute­doc)"
+.BR /usr/share/doc/iproute-doc/ss.html " (package iproute­doc)",
+.br
+.BR RFC " 793 "
+- https://tools.ietf.org/rfc/rfc793.txt (TCP states) 
+
 .SH AUTHOR
 .I ss 
 was written by Alexey Kuznetosv, <kuznet@ms2.inr.ac.ru>.
-- 
2.1.3

^ permalink raw reply related

* [CPSW driver] broadcast ethernet pkg will be dropped?
From: Zheng Yi @ 2014-12-29  1:36 UTC (permalink / raw)
  To: David S. Miller, netdev; +Cc: Mugunthan V N, Lokesh Vutla

[-- Attachment #1: Type: text/plain, Size: 2293 bytes --]

Hi Sir

   I found your mail address from Linux kernel git repo. I think there
   is a problem in CPSW driver. If it is not your duty to maintain
   those code, could you please tell me the ones who are in charge of
   it?

   I found that when a AM3352 board boot, I use a laptop to send ARP
   request to it, the board do not reponse. Even ifconfig do not show
   that there is any pkg sent to the CPSW device. I'm sure that the
   ARP request PKG received by SoC(confirmed by my oscilloscope).

   After reading the SoC doc (Tech ref manual) and reading the driver code, i found that:
   15.3.2.7 Address Lookup Engine (ALE)
   "Broadcast packets will be dropped unless the broadcast address is entered into the table with the super bit set."

   and in driver: drivers/net/ether/ti/cpsw_ale.c

   int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
                          int flags, u16 vid, int mcast_state)
   {
          /* ....... */

          cpsw_ale_set_super(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);

          /* ....... */
   }

   I have searched all of the calling of that function, and found no
   ALE_BLOCKED flag was set.  Especially, in
   cpsw_add_dual_emac_def_ale_entries(), only ALE_VLAN was provided
   for the broadcast address.

   After change the flag(brutally), my board can response to the ARP broadcast requests correctly.

   Here are some questions I do not found the answer:
   1. the macro ALE_BLOCKED seems be used uncorrectly.
      If one want the pkg should be "blocked", the "super" bit should be cleared, not be set.
      So, in cpsw_ale_add_mcast(), we should do like this:
          cpsw_ale_set_super(ale_entry, (flags & ALE_BLOCKED) ? 0 : 1);

      Do you think the current logic is reversed?

   2. broadcast ethernet pkg from "FF:FF:FF:FF:FF:FF" should be alowed.
      If by default, it desiged to be filtered out, why not add an interface to support
      restore it? I do not found any code that can change filtering the broadcast pkg in runtime.






--
Brock Zheng <yzheng@techyauld.com>
郑 祎

北京中科腾越科技发展有限公司
北京市海淀区东北旺西路8号中关村软件园21号楼启明星辰大厦二层六区(邮编:100094)

[-- Attachment #2: Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply

* [PATCH/RFC flow-net-next 00/10] Flow Table API Cache Enhancements
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

* [PATCH/RFC flow-net-next 01/10] net: flow: Correct spelling of action
From: Simon Horman @ 2014-12-29  2:15 UTC (permalink / raw)
  To: John Fastabend, netdev; +Cc: Simon Horman
In-Reply-To: <1419819340-19000-1-git-send-email-simon.horman@netronome.com>

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

* [PATCH/RFC flow-net-next 02/10] net: flow: Add features to tables
From: Simon Horman @ 2014-12-29  2:15 UTC (permalink / raw)
  To: John Fastabend, netdev; +Cc: Simon Horman
In-Reply-To: <1419819340-19000-1-git-send-email-simon.horman@netronome.com>

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

* [PATCH/RFC flow-net-next 03/10] net: flow: Add timeouts to flows
From: Simon Horman @ 2014-12-29  2:15 UTC (permalink / raw)
  To: John Fastabend, netdev; +Cc: Simon Horman
In-Reply-To: <1419819340-19000-1-git-send-email-simon.horman@netronome.com>

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

* [PATCH/RFC flow-net-next 04/10] net: flow: Add counters to flows
From: Simon Horman @ 2014-12-29  2:15 UTC (permalink / raw)
  To: John Fastabend, netdev; +Cc: Simon Horman
In-Reply-To: <1419819340-19000-1-git-send-email-simon.horman@netronome.com>

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

* [PATCH/RFC flow-net-next 05/10] net: flow: Add get, set and del notifier commands
From: Simon Horman @ 2014-12-29  2:15 UTC (permalink / raw)
  To: John Fastabend, netdev; +Cc: Simon Horman
In-Reply-To: <1419819340-19000-1-git-send-email-simon.horman@netronome.com>

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

* [PATCH/RFC flow-net-next 06/10] net: flow: Add flow removed notification
From: Simon Horman @ 2014-12-29  2:15 UTC (permalink / raw)
  To: John Fastabend, netdev; +Cc: Simon Horman
In-Reply-To: <1419819340-19000-1-git-send-email-simon.horman@netronome.com>

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

* [PATCH/RFC flow-net-next 07/10] net: flow: Add importance to flows
From: Simon Horman @ 2014-12-29  2:15 UTC (permalink / raw)
  To: John Fastabend, netdev; +Cc: Simon Horman
In-Reply-To: <1419819340-19000-1-git-send-email-simon.horman@netronome.com>

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

* [PATCH/RFC flow-net-next 08/10] net: flow: Add get and set table config commands
From: Simon Horman @ 2014-12-29  2:15 UTC (permalink / raw)
  To: John Fastabend, netdev; +Cc: Simon Horman
In-Reply-To: <1419819340-19000-1-git-send-email-simon.horman@netronome.com>

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

* [PATCH/RFC flow-net-next 09/10] net: flow: Add eviction flags to table configuration
From: Simon Horman @ 2014-12-29  2:15 UTC (permalink / raw)
  To: John Fastabend, netdev; +Cc: Simon Horman
In-Reply-To: <1419819340-19000-1-git-send-email-simon.horman@netronome.com>

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

* [PATCH/RFC flow-net-next 10/10] net: flow: Add flow removed notification for eviction
From: Simon Horman @ 2014-12-29  2:15 UTC (permalink / raw)
  To: John Fastabend, netdev; +Cc: Simon Horman
In-Reply-To: <1419819340-19000-1-git-send-email-simon.horman@netronome.com>

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

* [PATCH] net: flow: Guard against accessing non-existent attributes
From: Simon Horman @ 2014-12-29  2:17 UTC (permalink / raw)
  To: John Fastabend, netdev; +Cc: Simon Horman

Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
 net/core/flow_table.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/net/core/flow_table.c b/net/core/flow_table.c
index 5937fb7..df2adf6 100644
--- a/net/core/flow_table.c
+++ b/net/core/flow_table.c
@@ -480,6 +480,10 @@ static int net_flow_get_action(struct net_flow_action *a, struct nlattr *attr)
 	if (err < 0)
 		return err;
 
+	if (!act[NET_FLOW_ACTION_ATTR_UID] ||
+	    !act[NET_FLOW_ACTION_ATTR_SIGNATURE])
+		return -EINVAL;
+
 	a->uid = nla_get_u32(act[NET_FLOW_ACTION_ATTR_UID]);
 
 	nla_for_each_nested(args, act[NET_FLOW_ACTION_ATTR_SIGNATURE], rem)
@@ -513,6 +517,10 @@ static int net_flow_get_flow(struct net_flow_flow *flow, struct nlattr *attr)
 	if (err < 0)
 		return -EINVAL;
 
+	if (!f[NET_FLOW_ATTR_TABLE] || !f[NET_FLOW_ATTR_UID] ||
+	    !f[NET_FLOW_ATTR_PRIORITY])
+		return -EINVAL;
+
 	flow->table_id = nla_get_u32(f[NET_FLOW_ATTR_TABLE]);
 	flow->uid = nla_get_u32(f[NET_FLOW_ATTR_UID]);
 	flow->priority = nla_get_u32(f[NET_FLOW_ATTR_PRIORITY]);
@@ -1209,6 +1217,9 @@ static int net_flow_table_cmd_get_flows(struct sk_buff *skb,
 	if (err)
 		goto out;
 
+	if (!tb[NET_FLOW_TABLE_FLOWS_TABLE])
+		goto out;
+
 	table = nla_get_u32(tb[NET_FLOW_TABLE_FLOWS_TABLE]);
 
 	if (tb[NET_FLOW_TABLE_FLOWS_MINPRIO])
-- 
2.1.3

^ permalink raw reply related

* [PATCH] net: flow: Allow actions and matches to be NULL in net_flow_put_flow()
From: Simon Horman @ 2014-12-29  2:20 UTC (permalink / raw)
  To: John Fastabend, netdev; +Cc: Simon Horman

This makes the handing of the absence of actions or matches
symmetric with net_flow_get_flow().

Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
 net/core/flow_table.c | 40 ++++++++++++++++++++++------------------
 1 file changed, 22 insertions(+), 18 deletions(-)

diff --git a/net/core/flow_table.c b/net/core/flow_table.c
index df2adf6..0992806 100644
--- a/net/core/flow_table.c
+++ b/net/core/flow_table.c
@@ -196,32 +196,36 @@ 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;
 
-	matches = nla_nest_start(skb, NET_FLOW_ATTR_MATCHES);
-	if (!matches)
-		goto flows_put_failure;
-	for (j = 0; flow->matches[j].header; j++) {
-		struct net_flow_field_ref *f = &flow->matches[j];
+	if (flow->matches) {
+		matches = nla_nest_start(skb, NET_FLOW_ATTR_MATCHES);
+		if (!matches)
+			goto flows_put_failure;
+		for (j = 0; flow->matches[j].header; j++) {
+			struct net_flow_field_ref *f = &flow->matches[j];
 
-		if (!f->header)
-			continue;
+			if (!f->header)
+				continue;
 
-		nla_put(skb, NET_FLOW_FIELD_REF, sizeof(*f), f);
+			nla_put(skb, NET_FLOW_FIELD_REF, sizeof(*f), f);
+		}
+		nla_nest_end(skb, matches);
 	}
-	nla_nest_end(skb, matches);
-
-	actions = nla_nest_start(skb, NET_FLOW_ATTR_ACTIONS);
-	if (!actions)
-		goto flows_put_failure;
 
-	for (i = 0; flow->actions[i].uid; i++) {
-		err = net_flow_put_flow_action(skb, &flow->actions[i]);
-		if (err) {
-			nla_nest_cancel(skb, actions);
+	if (flow->actions) {
+		actions = nla_nest_start(skb, NET_FLOW_ATTR_ACTIONS);
+		if (!actions)
 			goto flows_put_failure;
+
+		for (i = 0; flow->actions[i].uid; i++) {
+			err = net_flow_put_flow_action(skb, &flow->actions[i]);
+			if (err) {
+				nla_nest_cancel(skb, actions);
+				goto flows_put_failure;
+			}
 		}
+		nla_nest_end(skb, actions);
 	}
 
-	nla_nest_end(skb, actions);
 	nla_nest_end(skb, flows);
 	return 0;
 
-- 
2.1.3

^ permalink raw reply related

* Re: [PATCH 15/27] net: sxgbe: Use setup_timer
From: GIRISH K S @ 2014-12-29  4:50 UTC (permalink / raw)
  To: Julia Lawall, ByungHo An
  Cc: kernel-janitors@vger.kernel.org, Vipul Chandrakant,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org



------- Original Message -------
Sender : Julia Lawall<Julia.Lawall@lip6.fr>
Date : Dec 26, 2014 20:05 (GMT+05:30)
Title : [PATCH 15/27] net: sxgbe: Use setup_timer

Convert a call to init_timer and accompanying intializations of
the timer's data and function fields to a call to setup_timer.

A simplified version of the semantic match that fixes this problem is as
follows: (http://coccinelle.lip6.fr/)

// 
@@
expression t,f,d;
@@

-init_timer(&t);
+setup_timer(&t,f,d);
-t.function = f;
-t.data = d;
// 

Signed-off-by: Julia Lawall 

---
drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c |   10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index 6984944..b6612d6 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -133,9 +133,8 @@ bool sxgbe_eee_init(struct sxgbe_priv_data * const priv)
return false;

priv->eee_active = 1;
- init_timer(&priv->eee_ctrl_timer);
- priv->eee_ctrl_timer.function = sxgbe_eee_ctrl_timer;
- priv->eee_ctrl_timer.data = (unsigned long)priv;
+ setup_timer(&priv->eee_ctrl_timer, sxgbe_eee_ctrl_timer,
+     (unsigned long)priv);
priv->eee_ctrl_timer.expires = SXGBE_LPI_TIMER(eee_timer);
add_timer(&priv->eee_ctrl_timer);

@@ -1009,10 +1008,9 @@ static void sxgbe_tx_init_coalesce(struct sxgbe_priv_data *priv)
struct sxgbe_tx_queue *p = priv->txq[queue_num];
p->tx_coal_frames =  SXGBE_TX_FRAMES;
p->tx_coal_timer = SXGBE_COAL_TX_TIMER;
- init_timer(&p->txtimer);
+ setup_timer(&p->txtimer, sxgbe_tx_timer,
+     (unsigned long)&priv->txq[queue_num]);
p->txtimer.expires = SXGBE_COAL_TIMER(p->tx_coal_timer);
- p->txtimer.data = (unsigned long)&priv->txq[queue_num];
- p->txtimer.function = sxgbe_tx_timer;
add_timer(&p->txtimer);
}
}
Looks good to me.
Acked by: Girish K S <ks.giri@samsung.com>

^ permalink raw reply related

* Re: [PATCH v3 00/20] kselftest install target feature
From: Michael Ellerman @ 2014-12-29  4:53 UTC (permalink / raw)
  To: Shuah Khan
  Cc: mmarek-AlSwsSmVLrQ, gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	rostedt-nx8X9YLhiw1AfugRpC6u6w, mingo-H+wXaHxf7aLQT0dZR+AlfA,
	davem-fT/PcQaiUtIeIZ0/mPfg9Q, keescook-F7+t8E8rja9g9hUCZPvPmw,
	tranmanphong-Re5JQEeQqe8AvxtiuMwx3w, cov-sgV2jX0FEOL9JmXXK+q4OQ,
	dh.herrmann-Re5JQEeQqe8AvxtiuMwx3w, hughd-hpIqsD4AKlfQT0dZR+AlfA,
	bobby.prani-Re5JQEeQqe8AvxtiuMwx3w,
	serge.hallyn-GeWIH/nMZzLQT0dZR+AlfA,
	ebiederm-aS9lmoZGLiVWk0Htik3J/w, tim.bird-/MT0OVThwyLZJqsBc5GL+g,
	josh-iaAMLnmF4UmaiuxdJuQwMA, koct9i-Re5JQEeQqe8AvxtiuMwx3w,
	linux-kbuild-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-api-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <cover.1419387513.git.shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>

On Wed, 2014-12-24 at 09:27 -0700, Shuah Khan wrote:
> This patch series adds a new kselftest_install make target
> to enable selftest install. When make kselftest_install is
> run, selftests are installed on the system. A new install
> target is added to selftests Makefile which will install
> targets for the tests that are specified in INSTALL_TARGETS.
> During install, a script is generated to run tests that are
> installed. This script will be installed in the selftest install
> directory. Individual test Makefiles are changed to add to the
> script. This will allow new tests to add install and run test
> commands to the generated kselftest script. kselftest target
> now depends on kselftest_install and runs the generated kselftest
> script to reduce duplicate work and for common look and feel when
> running tests.
> 
> This approach leverages and extends the existing framework that
> uses makefile targets to implement run_tests and adds install
> target. This will scale well as new tests get added and makes
> it easier for test writers to add install target at the same
> time new test gets added.
> 
> This v3 series reduces duplicate code to generate script
> in indiviual test Makefiles and consolidates support in
> selftests main Makefile. In the main Makefile, it does
> minimal work to set and export install path. In this
> series exec and powerpc tests are not included in the
> install, this work will be done in future patches. exec
> and powerpc are still run when make kselftest is invoked.

Any particular reason you excluded the powerpc tests? Going by a quick count,
powerpc has 32 of the 54 self tests, ie. more than half.

Sorry I didn't get a chance to review v1 or v2, but is this really the best
solution we can come up with? It seems to involve a lot of boiler plate getting
repeated in every Makefile.

I'm off this week so I can't immediately come up with something better, I'll
try in the new year.

cheers

^ permalink raw reply

* Re: net-next + qemu
From: Michael S. Tsirkin @ 2014-12-29  7:03 UTC (permalink / raw)
  To: Scott Feldman; +Cc: David Miller, netdev
In-Reply-To: <CAE4R7bB8Fdx2u+RmX=HAhz8T-GHWtot7fSU-PKCrUYvxMnf0aQ@mail.gmail.com>

On Sun, Dec 28, 2014 at 10:48:40PM -0800, Scott Feldman wrote:
> Hi Michael,
> 
> I was doing some testing with latest net-next and latest qemu and
> can't get Linux to load an image when using -drive
> file=xxx.img,if=virtio.  I git bisected net-next and the breakage
> happened on this commit in net-next:
> 
> 38eb4a2 virtio_pci: split out legacy device support
> 
> Qemu image will load if I remove if=virtio.
> 
> Are things in transition right now, and I just got unlucky with this
> combination of net-next and qemu?
> 
> -scott

Yes, if you make virtio-pci modular, it won't load unless
you have this commit:

commit 5ff16110c637726111662c1df41afd9df7ef36bd
Author: Herbert Xu <herbert@gondor.apana.org.au>
Date:   Wed Dec 17 00:54:03 2014 +0200

    virtio_pci: restore module attributes

So v3.19-rc1 is OK, but net-next/master is not.

Dave - will v3.19-rc1 be merged into net-next?
Could you please confirm?

-- 
MST

^ permalink raw reply

* Re: [PATCH] bonding: move ipoib_header_ops to vmlinux
From: Wengang @ 2014-12-29  7:13 UTC (permalink / raw)
  To: David Miller
  Cc: netdev-u79uwXL29TY76Z2rM5mHXA, linux-rdma-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20141125.010741.450666241983239119.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>

Hi David,

This is a real case not a potential crash. The call stack is like this:

crash> bt
PID: 47323 TASK: ffff881722954140 CPU: 13 COMMAND: "arping"
#0 [ffff881518437860] machine_kexec at ffffffff8103aac9
#1 [ffff8815184378d0] crash_kexec at ffffffff810b9943
#2 [ffff8815184379a0] oops_end at ffffffff8150e9b8
#3 [ffff8815184379d0] no_context at ffffffff8104855c
#4 [ffff881518437a10] __bad_area_nosemaphore at ffffffff81048685
#5 [ffff881518437a60] bad_area_nosemaphore at ffffffff810487e3
#6 [ffff881518437a70] do_page_fault at ffffffff81511558
#7 [ffff881518437b80] page_fault at ffffffff8150df55
[exception RIP: packet_snd+608]
RIP: ffffffff814ddbc0 RSP: ffff881518437c38 RFLAGS: 00010282
RAX: ffffffffa0316040 RBX: ffff881518437e58 RCX: 0000000000000000
RDX: 0000000000000048 RSI: 0000000000000038 RDI: ffff88172508a080
RBP: ffff881518437ca8 R8: ffff88176568f400 R9: 0000000000000038
R10: ffff88172508a080 R11: 0000000000000000 R12: ffff8817e94f2080
R13: ffff8817eba0f400 R14: ffff8817eaef6000 R15: 0000000000000038
ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018
#8 [ffff881518437cb0] packet_sendmsg at ffffffff814ddee3
#9 [ffff881518437cc0] sock_sendmsg at ffffffff8142ad3f
#10 [ffff881518437e40] sys_sendto at ffffffff8142af09
#11 [ffff881518437f80] system_call_fastpath at ffffffff81515c42
RIP: 00007f4a03095853 RSP: 00007fffad354bf8 RFLAGS: 00010202
RAX: 000000000000002c RBX: ffffffff81515c42 RCX: 00007f4a02fde7ce
RDX: 0000000000000038 RSI: 00007fffad354ab0 RDI: 0000000000000003
RBP: 0000000000000038 R8: 00007f4a03b87e00 R9: 0000000000000020
R10: 0000000000000000 R11: 0000000000000246 R12: 00007f4a03b87e00
R13: 00007f4a03b87e4c R14: 00007fffad354ae4 R15: 00007f4a03b87e98
ORIG_RAX: 000000000000002c CS: 0033 SS: 002b

Though the crash is not based on mainline code, mainline has the same issue.

I think Or Gerlitz answered the question "IPOIB should not work over 
bonding as it requires that the device use ARPHRD_ETHER.".

IPoIB devices can be enslaved to both bonding and teaming in their HA mode,
the bond device type becomes ARPHRD_INFINIBAND when this happens.

So, what information else do you need?

thanks,
wengang


于 2014年11月25日 14:07, David Miller 写道:
> From: Wengang Wang <wen.gang.wang-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
> Date: Tue, 25 Nov 2014 13:36:08 +0800
>
>> When last slave of a bonding master is removed, the bonding then does not work.
>> At the time if packet_snd is called against with a master net_device, it calls
>> then header_ops->create which points to slave's header_ops. In case the slave
>> is ipoib and the module is unloaded, header_ops would point to invalid address.
>> Accessing it will cause problem.
>> This patch tries to fix this issue by moving ipoib_header_ops to vmlinux to keep
>> it valid even when ipoib module is unloaded.
>>
>> Signed-off-by: Wengang Wang <wen.gang.wang-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
> IPOIB should not work over bonding as it requires that the device
> use ARPHRD_ETHER.
>
> Someone mentioned this, and I did not see any response.
>
> Please show how a legitimate real bonding configuration can be
> created, reproduce a stray memory access, and therefore potentially
> cause a crash.
>
> Using various debugging features of the kernel should allow you to
> trigger an assertion quite easily if this bug really exists.

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* RE: [PATCH/RFC flow-net-next 04/10] net: flow: Add counters to flows
From: Arad, Ronen @ 2014-12-29  7:31 UTC (permalink / raw)
  To: Simon Horman, Fastabend, John R, netdev@vger.kernel.org
In-Reply-To: <1419819340-19000-5-git-send-email-simon.horman@netronome.com>



>-----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

* Re: [PATCH net-next] net: stmmac: add BQL support
From: Florian Fainelli @ 2014-12-29  7:48 UTC (permalink / raw)
  To: Beniamino Galvani
  Cc: David S. Miller, Giuseppe Cavallaro, netdev,
	linux-kernel@vger.kernel.org
In-Reply-To: <1419778631-23067-1-git-send-email-b.galvani@gmail.com>

2014-12-28 6:57 GMT-08:00 Beniamino Galvani <b.galvani@gmail.com>:
> Add support for Byte Queue Limits to the STMicro MAC driver.
>
> Tested on a Amlogic S805 Cortex-A5 board, where the use of BQL
> slightly decreases the ping latency from ~10ms to ~3ms when the
> 100Mbps link is saturated by TCP streams. No difference is
> observed at 1Gbps.
>
> Signed-off-by: Beniamino Galvani <b.galvani@gmail.com>
> ---

[snip]

>         priv->dev->stats.tx_errors++;
> @@ -2049,6 +2057,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
>                 skb_tx_timestamp(skb);
>
>         priv->hw->dma->enable_dma_transmission(priv->ioaddr);
> +       netdev_sent_queue(dev, skb->len);

You are introducing a potential use after free here in case tx_lock is
eliminated one day and your TX reclaim logic kicks in and frees the
freshly transmitted SKB, it would be safer to just cache skb->len in a
local variable, and use it here.

>
>         spin_unlock(&priv->tx_lock);
>         return NETDEV_TX_OK;
-- 
Florian

^ permalink raw reply

* Re: [PATCH] ipnetns: fix exec for netns not in NETNS_RUN_DIR
From: Shahar Lev @ 2014-12-29  9:25 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20141227100548.4fbd3e31@urahara>

>
> This breaks existing users since you now require full pathname.
>

Providing a full path is not a requirement.
If there's no dash ('/') in the parameter provided it defaults to
opening relative to NETNS_RUN_DIR (the existing behavior).
So this is just an extension.

^ permalink raw reply

* Re: am335x: cpsw: interrupt failure
From: Yegor Yefremov @ 2014-12-29  9:33 UTC (permalink / raw)
  To: Felipe Balbi; +Cc: netdev, N, Mugunthan V, linux-omap@vger.kernel.org
In-Reply-To: <CAGm1_kuYrGsfjRO6TVr554yS8dcD4_Z9-j9KL0xpD=X+31OkXQ@mail.gmail.com>

On Fri, Dec 12, 2014 at 8:19 PM, Yegor Yefremov
<yegorslists@googlemail.com> wrote:
> On Fri, Dec 12, 2014 at 6:32 PM, Felipe Balbi <balbi@ti.com> wrote:
>> Hi,
>>
>> On Fri, Dec 12, 2014 at 01:00:51PM +0100, Yegor Yefremov wrote:
>>> U-Boot version: 2014.07
>>> Kernel config is omap2plus with enabled USB
>>>
>>> # cat /proc/version
>>> Linux version 3.18.0 (user@user-VirtualBox) (gcc version 4.8.3
>>> 20140320 (prerelease) (Sourcery CodeBench Lite 2014.05-29) ) #6 SMP
>>> Mon Dec 8 22:47:43 CET 2014
>>
>> Wasn't GCC 4.8.x total crap for building ARM kernels ? IIRC it was even
>> blacklisted. Can you try with 4.9.x just to make sure ?
>
> Will do.

Adding linux-omap. Beginning of this discussion:
http://comments.gmane.org/gmane.linux.network/341427

Quick summary: starting with kernel 3.18 or commit
55601c9f24670ba926ebdd4d712ac3b177232330 am335x (at least BBB and some
custom boards) stalls at high network load. Reproducible via nuttcp
within some minutes

nuttcp -S (on BBB)
nuttcp -t -N 4 -T30m 192.168.1.235 (on host)

As Felipe Balbi suggested, I tried both 4.8.3 and 4.9.2 toolchains,
but both show the same behavior.

Linux version 3.18.0 (user@user-VirtualBox) (gcc version 4.8.3
20140320 (prerelease) (Sourcery CodeBench Lite 2014.05-29) ) #6 SMP
Mon Dec 8 22:47:43 CET 2014
Linux version 3.18.1 (user@user-VirtualBox) (gcc version 4.9.2
(Buildroot 2015.02-git-00582-g10b9761) ) #1 SMP Mon Dec 29 09:22:29
CET 2014

Let me know, if you can reproduce this issue.

Thanks.

Yegor

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox