Netdev List
 help / color / mirror / Atom feed
* [RFC] xfrm: x86_64 CONFIG_COMPAT support
From: Florian Westphal @ 2010-02-05  1:47 UTC (permalink / raw)
  To: netdev

At the moment, it is not possible to use the xfrm netlink interface on
x86_64 with a 32bit userland.

The problem is due to a few structures, notably struct xfrm_usersa_info,
which have different sizes in user/kernelspace (3 byte padding on x86, 7
byte on x86_64). Thus, when the kernel skips the family specific header,
it skips 4 additional bytes; netlink verification thus fails.

What follows is a (incomplete, untested) draft patch that tries
to solve this by introducing a delta table.  With the changes in place
so far its possible to run
"ip xfrm state add ..." with a 32bit ip binary.

Unfortunately, the MSG_COMPAT flag seems to get lost along
the way, so this uses x86_64 is_compat_task() for now.

The delta table is not sufficient, as struct xfrm_usersa_info
can be embedded inside other structs, so when accessing data
after xfrm_usersa_info, one has to use an appropriate compat
structure definition.

Before I spend any more time on this, my questions are:

- does this approach look somewhat sane to you?
- do you have any suggestions how xfrm CONFIG_COMPAT support should
  look like?
- are you aware of pitfalls other than xfrm structure padding?
- are there platforms other than x86_64 that have this problem?

Thanks in advance, Florian

diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index d5a7129..e8747fb 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -11,6 +11,7 @@
  */
 
 #include <linux/crypto.h>
+#include <linux/compat.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -31,6 +32,35 @@
 #include <linux/in6.h>
 #endif
 
+#if defined(CONFIG_X86_64) && defined(CONFIG_COMPAT)
+#define XFRM_COMPAT_TEST is_compat_task()
+/* userspace size decreases by this amount due to padding */
+static const u8 xfrm_msg_min_compat_pad[XFRM_NR_MSGTYPES] = {
+	[XFRM_MSG_NEWSA       - XFRM_MSG_BASE] = 4,
+	[XFRM_MSG_NEWPOLICY   - XFRM_MSG_BASE] = 4,
+
+	[XFRM_MSG_ALLOCSPI    - XFRM_MSG_BASE] = 4, /* need converter */
+	[XFRM_MSG_ACQUIRE     - XFRM_MSG_BASE] = 4, /* need converter */
+	[XFRM_MSG_EXPIRE      - XFRM_MSG_BASE] = 4, /* need converter */
+	[XFRM_MSG_UPDPOLICY   - XFRM_MSG_BASE] = 4,
+	[XFRM_MSG_UPDSA       - XFRM_MSG_BASE] = 4,
+	[XFRM_MSG_POLEXPIRE   - XFRM_MSG_BASE] = 4, /* need converter */
+
+	[XFRM_MSG_NEWAE       - XFRM_MSG_BASE] = 4,
+	[XFRM_MSG_GETAE       - XFRM_MSG_BASE] = 4,
+};
+
+#else
+#define XFRM_COMPAT_TEST 0
+#endif	/* defined(CONFIG_X86_64) && defined(CONFIG_COMPAT) */
+
+struct xfrm_compat_userspi_info {
+	__u32 xfrm_usersa_info[55];
+	__u32 min, max;
+};
+
+static int xfrm_msg_hdrlen(int type);
+
 static inline int aead_len(struct xfrm_algo_aead *alg)
 {
 	return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
@@ -700,9 +730,10 @@ static int dump_one_state(struct xfrm_state *x, int count, void *ptr)
 	struct xfrm_usersa_info *p;
 	struct nlmsghdr *nlh;
 	int err;
+	int type = XFRM_MSG_NEWSA - XFRM_MSG_BASE;
 
 	nlh = nlmsg_put(skb, NETLINK_CB(in_skb).pid, sp->nlmsg_seq,
-			XFRM_MSG_NEWSA, sizeof(*p), sp->nlmsg_flags);
+			XFRM_MSG_NEWSA, xfrm_msg_hdrlen(type), sp->nlmsg_flags);
 	if (nlh == NULL)
 		return -EMSGSIZE;
 
@@ -916,6 +947,30 @@ out_noput:
 
 static int verify_userspi_info(struct xfrm_userspi_info *p)
 {
+	if (XFRM_COMPAT_TEST) {
+		struct xfrm_compat_userspi_info *compat = (struct xfrm_compat_userspi_info  *) p;
+
+		switch (p->info.id.proto) {
+		case IPPROTO_AH:
+		case IPPROTO_ESP:
+			break;
+
+		case IPPROTO_COMP:
+			/* IPCOMP spi is 16-bits. */
+			if (compat->max >= 0x10000)
+				return -EINVAL;
+		break;
+
+		default:
+			return -EINVAL;
+		}
+
+		if (compat->min > compat->max)
+			return -EINVAL;
+
+		return 0;
+	}
+
 	switch (p->info.id.proto) {
 	case IPPROTO_AH:
 	case IPPROTO_ESP:
@@ -974,7 +1029,12 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
 	if (x == NULL)
 		goto out_noput;
 
-	err = xfrm_alloc_spi(x, p->min, p->max);
+	if (XFRM_COMPAT_TEST) {
+		struct xfrm_compat_userspi_info *compat = (struct xfrm_compat_userspi_info  *) p;
+		err = xfrm_alloc_spi(x, compat->min, compat->max);
+	} else {
+		err = xfrm_alloc_spi(x, p->min, p->max);
+	}
 	if (err)
 		goto out;
 
@@ -2102,6 +2162,13 @@ static struct xfrm_link {
 	[XFRM_MSG_GETSPDINFO  - XFRM_MSG_BASE] = { .doit = xfrm_get_spdinfo   },
 };
 
+static int xfrm_msg_hdrlen(int type)
+{
+	if (unlikely(XFRM_COMPAT_TEST))
+		return xfrm_msg_min[type] - xfrm_msg_min_compat_pad[type];
+	return xfrm_msg_min[type];
+}
+
 static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 {
 	struct net *net = sock_net(skb->sk);
@@ -2129,7 +2196,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 		return netlink_dump_start(net->xfrm.nlsk, skb, nlh, link->dump, link->done);
 	}
 
-	err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX,
+	err = nlmsg_parse(nlh, xfrm_msg_hdrlen(type), attrs, XFRMA_MAX,
 			  xfrma_policy);
 	if (err < 0)
 		return err;

^ permalink raw reply related

* Re: [PATCH 00/13] net: simplify seq_file code
From: Andrew Morton @ 2010-02-05  1:58 UTC (permalink / raw)
  To: Li Zefan; +Cc: David Miller, LKML, netdev@vger.kernel.org
In-Reply-To: <4B6B780D.10003@cn.fujitsu.com>

On Fri, 05 Feb 2010 09:44:45 +0800 Li Zefan <lizf@cn.fujitsu.com> wrote:

> +struct hlist_node *seq_hlist_start(struct hlist_head *head, loff_t pos)
> +{
> +	struct hlist_node *node;
> +
> +	hlist_for_each(node, head)
> +		if (pos-- == 0)
> +			return node;
> +	return NULL;
> +}
> +EXPORT_SYMBOL(seq_hlist_start);
> +
> +struct hlist_node *seq_hlist_start_head(struct hlist_head *head, loff_t pos)
> +{
> +	if (!pos)
> +		return SEQ_START_TOKEN;
> +
> +	return seq_hlist_start(head, pos - 1);
> +}
> +EXPORT_SYMBOL(seq_hlist_start_head);
> +
> +struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head,
> +				  loff_t *ppos)
> +{
> +	struct hlist_node *node = v;
> +
> +	++*ppos;
> +	if (v == SEQ_START_TOKEN)
> +		return head->first;
> +	else
> +		return node->next;
> +}
> +EXPORT_SYMBOL(seq_hlist_next);

Oy.  Most of the global functions in seq_file.c are kerneldocumented,
as they should be!

Shouldn't seq_hlist_start_head() have been called seq_hlist_prev()?

Should seq_hlist_start() be passed *ppos, and update *ppos so the
caller can then call seq_hlist_next() and seq_hlist_prev()?


^ permalink raw reply

* Re: [PATCH 00/13] net: simplify seq_file code
From: Li Zefan @ 2010-02-05  2:12 UTC (permalink / raw)
  To: Andrew Morton; +Cc: David Miller, LKML, netdev@vger.kernel.org
In-Reply-To: <20100204175828.51b9e8a1.akpm@linux-foundation.org>

Andrew Morton wrote:
> On Fri, 05 Feb 2010 09:44:45 +0800 Li Zefan <lizf@cn.fujitsu.com> wrote:
> 
>> +struct hlist_node *seq_hlist_start(struct hlist_head *head, loff_t pos)
>> +{
>> +	struct hlist_node *node;
>> +
>> +	hlist_for_each(node, head)
>> +		if (pos-- == 0)
>> +			return node;
>> +	return NULL;
>> +}
>> +EXPORT_SYMBOL(seq_hlist_start);
>> +
>> +struct hlist_node *seq_hlist_start_head(struct hlist_head *head, loff_t pos)
>> +{
>> +	if (!pos)
>> +		return SEQ_START_TOKEN;
>> +
>> +	return seq_hlist_start(head, pos - 1);
>> +}
>> +EXPORT_SYMBOL(seq_hlist_start_head);
>> +
>> +struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head,
>> +				  loff_t *ppos)
>> +{
>> +	struct hlist_node *node = v;
>> +
>> +	++*ppos;
>> +	if (v == SEQ_START_TOKEN)
>> +		return head->first;
>> +	else
>> +		return node->next;
>> +}
>> +EXPORT_SYMBOL(seq_hlist_next);
> 
> Oy.  Most of the global functions in seq_file.c are kerneldocumented,
> as they should be!
> 

I'll add kerneldoc in v2 patchset if I have to resend, otherwise I'll
send a delta patch for this.

> Shouldn't seq_hlist_start_head() have been called seq_hlist_prev()?
> 

The list_head version has the name seq_list_start_head().

If you need to print a title in a seq_file, call seq_list_start_head()
in ->start() handler, otherwise call seq_list_start().

Those functions really need kerneldoc. ;)

> Should seq_hlist_start() be passed *ppos, and update *ppos so the
> caller can then call seq_hlist_next() and seq_hlist_prev()?
> 

No, the ->start() callback of seq_operations shouldn't update *ppos.
I fixed some bugs in ftrace debugfs files which were caused by
updating *ppos in start().

^ permalink raw reply

* Re: [PATCH v2 net-next-2.6] packet: Add GSO/csum offload support.
From: Herbert Xu @ 2010-02-05  2:14 UTC (permalink / raw)
  To: Sridhar Samudrala; +Cc: Michael S. Tsirkin, netdev
In-Reply-To: <1265331730.31059.22.camel@w-sridhar.beaverton.ibm.com>

On Thu, Feb 04, 2010 at 05:02:10PM -0800, Sridhar Samudrala wrote:
> 
> In the case of SOCK_DGRAM reserve is not set and will be 0 and hence
> it is same as calling skb_reset_network_header(skb)

Thanks for the explanation.  The patch looks good to me.

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply

* linux-next: manual merge of the trivial tree with the net tree
From: Stephen Rothwell @ 2010-02-05  2:37 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: linux-next, linux-kernel, Adam Buchbinder, David Miller, netdev,
	Ben Hutchings

Hi Jiri,

Today's linux-next merge of the trivial tree got a conflict in
drivers/net/sfc/mcdi_pcol.h between commit
5297a98d5dd6de86fe1e2ffc9ea60cdf59b71443 ("sfc: Update MCDI protocol
definitions") from the net tree and commit
4887b438e6880c73c4b44d868211e70c1f3deaec ("Fix misspelling of
"successful" and variants in comments") from the trivial tree.

I fixed it up (see below) and can carry the fix as necessary.
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

diff --cc drivers/net/sfc/mcdi_pcol.h
index bd59302,f61e1de..0000000
--- a/drivers/net/sfc/mcdi_pcol.h
+++ b/drivers/net/sfc/mcdi_pcol.h
@@@ -859,14 -852,11 +859,14 @@@
  /* MC_CMD_POLL_PHY_BIST: (variadic output)
   * Poll for BIST completion
   *
 - * Returns a single status code, and a binary blob of phy-specific
 - * bist output. If the driver can't successfully parse the BIST output,
 - * it should still respect the Pass/Fail in OUT.RESULT.
 + * Returns a single status code, and optionally some PHY specific
 + * bist output. The driver should only consume the BIST output
 + * after validating OUTLEN and PHY_CFG.PHY_TYPE.
   *
-  * If a driver can't succesfully parse the BIST output, it should
 - * Locks required: PHY_LOCK  if doing a  PHY BIST
++ * If a driver can't successfully parse the BIST output, it should
 + * still respect the pass/Fail in OUT.RESULT
 + *
 + * Locks required: PHY_LOCK if doing a  PHY BIST
   * Return code: 0, EACCES (if PHY_LOCK is not held)
   */
  #define MC_CMD_POLL_BIST 0x26

^ permalink raw reply

* RE: [PATCH 2.6.33 4/4] net: Add PCI vendor and device ids for Micrel KSZ8841/2 PCI devices
From: Ha, Tristram @ 2010-02-05  2:55 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: Dave Miller, netdev, linux-kernel
In-Reply-To: <20100204154004.44e3d607@nehalam>

Stephen Hemminger wrote:
> On Thu, 4 Feb 2010 15:28:29 -0800
> "Ha, Tristram" <Tristram.Ha@Micrel.Com> wrote:
> 
>> From: Tristram Ha <Tristram.Ha@micrel.com>
>> 
>> Add PCI vendor and device ids for Micrel KSZ8841/2 PCI devices.
>> 
>> Signed-off-by: Tristram Ha <Tristram.Ha@micrel.com> ---
>> This is a resubmission of the Micrel KSZ8841/2 PCI Ethernet driver.
>> 
>> --- linux-2.6.33-rc5.old/include/linux/pci_ids.h	2010-01-21
15:31:35.000000000 -0800
>> +++ linux-2.6.33-rc5.new/include/linux/pci_ids.h	2010-01-29
10:38:53.000000000 -0800 @@ -2199,6
>>  +2199,12 @@ #define PCI_VENDOR_ID_NETCELL		0x169c
>>  #define PCI_DEVICE_ID_REVOLUTION	0x0044
>> 
>> +#define PCI_VENDOR_ID_MICREL_KS		0x16c6
>> +#define PCI_DEVICE_ID_MICREL_KS8692	0x8692
>> +#define PCI_DEVICE_ID_MICREL_KS8695	0x8695
>> +#define PCI_DEVICE_ID_MICREL_KS8841	0x8841
>> +#define PCI_DEVICE_ID_MICREL_KS8842	0x8842
>> +
>>  #define PCI_VENDOR_ID_CENATEK		0x16CA
>>  #define PCI_DEVICE_ID_CENATEK_IDE	0x0001
>> 
> 
> Current practice is to NOT update this file and instead keep constants
in the individual driver.

It seems I received conflicted recommendation from Alan Cox:

>> >> +#define PCI_VENDOR_ID_KS884X		0x16C6
>> >> +#define PCI_DEVICE_ID_KS8841		0x8841
>> >> +#define PCI_DEVICE_ID_KS8842		0x8842
>> > 
>> > Those belong in the pci device id header.
>> > 
>> > 
>> 
>> I do not quite understand your suggestion.  Do I need to put those
IDs 
>> in one of the kernel headers?
> 
> Into include/linux/pci_ids.h

So I do not need to update pci_ids.h with even the PCI vendor ID?

^ permalink raw reply

* Re: [RFC] xfrm: x86_64 CONFIG_COMPAT support
From: David Miller @ 2010-02-05  4:22 UTC (permalink / raw)
  To: fw; +Cc: netdev
In-Reply-To: <20100205014744.GD28659@Chamillionaire.breakpoint.cc>

From: Florian Westphal <fw@strlen.de>
Date: Fri, 5 Feb 2010 02:47:44 +0100

> Unfortunately, the MSG_COMPAT flag seems to get lost along
> the way, so this uses x86_64 is_compat_task() for now.

You can't use is_compat_task() for this.  The current
execution context is not always the same as who is
going to get the message.

This is particularly the case for broadcast events, and
key manager event sending.

The wireless folks have their netlink bits working with
compat programs, you should go see how it works there.

^ permalink raw reply

* Re: [PATCH v2 net-next-2.6] packet: Add GSO/csum offload support.
From: David Miller @ 2010-02-05  4:25 UTC (permalink / raw)
  To: herbert; +Cc: sri, mst, netdev
In-Reply-To: <20100205021406.GA10651@gondor.apana.org.au>

From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Fri, 5 Feb 2010 13:14:06 +1100

> On Thu, Feb 04, 2010 at 05:02:10PM -0800, Sridhar Samudrala wrote:
>> 
>> In the case of SOCK_DGRAM reserve is not set and will be 0 and hence
>> it is same as calling skb_reset_network_header(skb)
> 
> Thanks for the explanation.  The patch looks good to me.

Patch applied, thanks everyone.

Sridhar, your patch had several cases of trailing whitespace which I
fixed up when applying.  Because tools are able to find such errors in
an automated way, these kinds of things should never show up in a
patch submission.  Please fix such things up before submitting patches
in the future.

Thanks again.

^ permalink raw reply

* Re: linux-next: manual merge of the trivial tree with the net tree
From: David Miller @ 2010-02-05  4:26 UTC (permalink / raw)
  To: sfr; +Cc: jkosina, linux-next, linux-kernel, adam.buchbinder, netdev,
	bhutchings
In-Reply-To: <20100205133747.14ca83f2.sfr@canb.auug.org.au>

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Fri, 5 Feb 2010 13:37:47 +1100

> Today's linux-next merge of the trivial tree got a conflict in
> drivers/net/sfc/mcdi_pcol.h between commit
> 5297a98d5dd6de86fe1e2ffc9ea60cdf59b71443 ("sfc: Update MCDI protocol
> definitions") from the net tree and commit
> 4887b438e6880c73c4b44d868211e70c1f3deaec ("Fix misspelling of
> "successful" and variants in comments") from the trivial tree.
> 
> I fixed it up (see below) and can carry the fix as necessary.

Ugh, this is the second spelling fix that's hit a conflict
in the same exact tree.

Please, submit these things to the subsystem maintainers instead
of keeping them together in a totally seperate tree.  That way
we won't have to keep fighting these things.

Thanks.

^ permalink raw reply

* Re: [PATCH 2.6.33 4/4] net: Add PCI vendor and device ids for Micrel KSZ8841/2 PCI devices
From: David Miller @ 2010-02-05  4:27 UTC (permalink / raw)
  To: Tristram.Ha; +Cc: shemminger, netdev, linux-kernel
In-Reply-To: <14385191E87B904DBD836449AA30269D5CC333@MORGANITE.micrel.com>

From: "Ha, Tristram" <Tristram.Ha@Micrel.Com>
Date: Thu, 4 Feb 2010 18:55:31 -0800

> Stephen Hemminger wrote:
>> Current practice is to NOT update this file and instead keep constants
> in the individual driver.
> 
> It seems I received conflicted recommendation from Alan Cox:

Alan's understanding is several years out of date.

Stephen's is correct.

But you don't need these stupid defines at all, all you
use them for is the PCI device ID table in your driver
so just use constants.

^ permalink raw reply

* Re: [PATCH 00/13] net: simplify seq_file code
From: David Miller @ 2010-02-05  4:32 UTC (permalink / raw)
  To: lizf; +Cc: akpm, linux-kernel, netdev
In-Reply-To: <4B6B7EA8.4070104@cn.fujitsu.com>

From: Li Zefan <lizf@cn.fujitsu.com>
Date: Fri, 05 Feb 2010 10:12:56 +0800

> I'll add kerneldoc in v2 patchset if I have to resend, otherwise I'll
> send a delta patch for this.

I want you to, at a minimum, resend the first patch because you
messed up the subject line for it.

Thanks.

^ permalink raw reply

* bridge: Remove unused age_list
From: Herbert Xu @ 2010-02-05  3:31 UTC (permalink / raw)
  To: Stephen Hemminger, David S. Miller

Hi:

bridge: Remove unused age_list

This patch removes the unused age_list member from the net_bridge
structure.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index a2cbe61..35e80e9 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -206,8 +206,6 @@ static struct net_device *new_bridge_dev(struct net *net, const char *name)
 
 	br_netfilter_rtable_init(br);
 
-	INIT_LIST_HEAD(&br->age_list);
-
 	br_stp_timer_init(br);
 
 	return dev;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 2114e45..1f0c4f4 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -93,7 +93,6 @@ struct net_bridge
 	struct net_device		*dev;
 	spinlock_t			hash_lock;
 	struct hlist_head		hash[BR_HASH_SIZE];
-	struct list_head		age_list;
 	unsigned long			feature_mask;
 #ifdef CONFIG_BRIDGE_NETFILTER
 	struct rtable 			fake_rtable;

Cheers,
-- 
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply related

* Re: [RFC Patch v2] net: reserve ports for applications using fixed port numbers
From: Cong Wang @ 2010-02-05  4:41 UTC (permalink / raw)
  To: Tetsuo Handa
  Cc: linux-kernel, linux-security-module, opurdila, eric.dumazet,
	linux-rdma, netdev, nhorman, linux-sctp, davem
In-Reply-To: <201002041959.JEG43202.JQOFHFOVSFMtLO@I-love.SAKURA.ne.jp>

Tetsuo Handa wrote:
> Hello.
> 
> Amerigo Wang wrote:
>> diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
>> index 2b79377..d3e160a 100644
>> --- a/net/ipv4/inet_hashtables.c
>> +++ b/net/ipv4/inet_hashtables.c
>> @@ -456,6 +456,8 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
>>  		local_bh_disable();
>>  		for (i = 1; i <= remaining; i++) {
>>  			port = low + (i + offset) % remaining;
>> +			if (inet_is_reserved_local_port(port))
>> +				continue;
>>  			head = &hinfo->bhash[inet_bhashfn(net, port,
>>  					hinfo->bhash_size)];
>>  			spin_lock(&head->lock);
> 
> I'm planning to add a LSM hook here.
> 
> If root user sets min port value less than 1024 to
> /proc/sys/net/ipv4/ip_local_port_range , a process without CAP_NET_BIND_SERVICE
> capability can bind to privileged port by "bind() with port == 0" or "connect()
> without bind()" because the condition is
> 
> 	err = -EACCES;
> 	if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
> 		goto out;
> 
> I consider this is a security problem if MAC is enabled. MAC is used for
> dividing root user's privilege. With MAC, somebody doing some part of root
> user's jobs may set min port value to less than 1024.
> 
> Also, some applications needs fixed local port numbers (e.g. 3128 for Squid,
> 8080 for Tomcat). The port numbers I want to reserve are more complex than
> simple min-max range like /proc/sys/net/ipv4/ip_local_reserved_ports .
> 
> Therefore, TOMOYO wants to insert a LSM hook (
> http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/net/ipv4/udp.c#L235
> http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/net/ipv4/inet_connection_sock.c#L114
> http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/net/ipv4/inet_hashtables.c#L459
> ) and allow reserving local ports like
> 
>   deny_autobind 0-1023
>   deny_autobind 3128
>   deny_autobind 8080
> 
> so that
> 
>   applications which need such ports won't be unexpectedly blocked by
>   other application's temporary port usage (i.e. "bind() with port == 0" or
>   "connect() without bind()")
> 
> and
> 
>   MAC guarantees that processes without CAP_NET_BIND_SERVICE can never bind
>   to privileged port
> 

Oh, IIUC, TOMOYO is something like SELinux? So, it is somewhat weird
to let users to use TOMOYO to reserve the ports with MAC. For normal
users /proc interface seems more friendly.

Thanks.

^ permalink raw reply

* Re: [RFC Patch] net: reserve ports for applications using fixed port numbers
From: Cong Wang @ 2010-02-05  4:45 UTC (permalink / raw)
  To: Octavian Purdila
  Cc: David Miller, linux-kernel, eric.dumazet, linux-rdma, netdev,
	nhorman, linux-sctp
In-Reply-To: <201002042015.51092.opurdila@ixiacom.com>

Octavian Purdila wrote:
> On Thursday 04 February 2010 19:41:10 you wrote:
> 
>> From: Octavian Purdila <opurdila@ixiacom.com>
>> Date: Thu, 4 Feb 2010 14:44:01 +0200
>>
>>> My concern is that we can have multiple applications that require a
>>> fixed port and if those ports are significantly apart we will
>>> decrease the port range available for connect. And that will hurt
>>> the rate of which new connections can be opened.
>> I'm already uneasy about adding the simple check every time
>> we loop around in the bind port allocator.
>>
>> Adding an LSM hook to this spot?  I absolutely refuse to allow
>> that, it will completely kill bind performance.
>>
> 
> I think Tetsuo was proposing the LSM hook, so I'll leave him the daunting task 
> of convincing you of the benefit of that :) - I have no opinion on this due to 
> massive lack of knowledge.
> 
> I was just proposing to use a discrete set of ports instead of a range. The 
> check in the current patch:
> 
> int inet_is_reserved_local_port(int port)
> {
>        int min, max;
> 
>        inet_get_local_reserved_ports(&min, &max);
>        if (min && max)
>                return (port >= min && port <= max);
>        return 0;
> }
> 
> would become:
> 
> int inet_is_reserved_local_port(int port)
> {
> 	if (test_bit(port, reserved_ports))
> 		return 1;
> 	return 0;
> }
> 
> In theory it might be slower because of the reserved_ports bitmap will have a 
> larger memory footprint than just a min/max, especially with random port 
> allocation. But is this an issue in practice?

Again, using bitmap algorithm is not a problem and it's better, the
problem is sysctl interface, how would you plan to interact with users
via sysctl/proc if you use bitmap to handle this? I would like to hear
more details about this.

Thanks!


^ permalink raw reply

* linux-next: manual merge of the percpu tree with the net tree
From: Stephen Rothwell @ 2010-02-05  4:44 UTC (permalink / raw)
  To: Tejun Heo, Rusty Russell, Christoph Lameter, Ingo Molnar
  Cc: linux-next, linux-kernel, Arnd Bergmann, David Miller, netdev

Hi all,

Today's linux-next merge of the percpu tree got a conflict in
drivers/net/macvlan.c between commit
fc0663d6b5e6d8e9b57f872a644c0aafd82361b7 ("macvlan: allow multiple driver
backends") from the net tree and commit
e20b68160144bcacbde008b9cf7df4e1544b2507 ("percpu: add __percpu sparse
annotations to net drivers") from the percpu tree.

The struct that is being modified by the latter commit has been moved by
the former into include/linux/if_macvlan.h.

I fixed it up (see below) and can carry the fix as necessary.
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Fri, 5 Feb 2010 15:29:35 +1100
Subject: [PATCH] percpu: macvlan merge fix

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
 include/linux/if_macvlan.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index 51f1512..f9cb9ba 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -30,7 +30,7 @@ struct macvlan_dev {
 	struct hlist_node	hlist;
 	struct macvlan_port	*port;
 	struct net_device	*lowerdev;
-	struct macvlan_rx_stats *rx_stats;
+	struct macvlan_rx_stats __percpu *rx_stats;
 	enum macvlan_mode	mode;
 	int (*receive)(struct sk_buff *skb);
 	int (*forward)(struct net_device *dev, struct sk_buff *skb);
-- 
1.6.6.1

^ permalink raw reply related

* [PATCH] mlx4: replace the dma_sync_single_range_for_cpu/device API
From: FUJITA Tomonori @ 2010-02-05  4:57 UTC (permalink / raw)
  To: netdev; +Cc: davem, rolandd, eli, linux-kernel

There are only two users of the dma_sync_single_range_for_cpu/device
API in mainline (mlx4 and ssb). The
dma_sync_single_range_for_cpu/device API has never been documented and
the dma_sync_single_for_cpu/device API also support a partial sync.

This converts mlx4 to use the dma_sync_single_for_cpu/device API
(preparations for the removal of the dma_sync_single_range_for_cpu/device API).

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
---
 drivers/net/mlx4/en_rx.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index 829b9ec..6439464 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -508,11 +508,11 @@ static struct sk_buff *mlx4_en_rx_skb(struct mlx4_en_priv *priv,
 		/* We are copying all relevant data to the skb - temporarily
 		 * synch buffers for the copy */
 		dma = be64_to_cpu(rx_desc->data[0].addr);
-		dma_sync_single_range_for_cpu(&mdev->pdev->dev, dma, 0,
-					      length, DMA_FROM_DEVICE);
+		dma_sync_single_for_cpu(&mdev->pdev->dev, dma, length,
+					DMA_FROM_DEVICE);
 		skb_copy_to_linear_data(skb, va, length);
-		dma_sync_single_range_for_device(&mdev->pdev->dev, dma, 0,
-						 length, DMA_FROM_DEVICE);
+		dma_sync_single_for_device(&mdev->pdev->dev, dma, length,
+					   DMA_FROM_DEVICE);
 		skb->tail += length;
 	} else {
 
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 01/13] seq_file: Add helpers for iteration over a hlist
From: Li Zefan @ 2010-02-05  5:04 UTC (permalink / raw)
  To: David Miller; +Cc: akpm, linux-kernel, netdev
In-Reply-To: <20100204.203216.97839493.davem@davemloft.net>

Some places in kernel need to iterate over a hlist in seq_file,
so provide some common helpers.

Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
---

Here's the resend of the first patch.

I'll send another patch to add some kerneldoc for seq_list_xxx()
and seq_hlist_xxx().

---
 fs/seq_file.c            |   37 ++++++++++++++++++++++++++++++++++---
 include/linux/seq_file.h |   11 +++++++++++
 2 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/fs/seq_file.c b/fs/seq_file.c
index eae7d9d..e833076 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -674,7 +674,6 @@ struct list_head *seq_list_start(struct list_head *head, loff_t pos)
 
 	return NULL;
 }
-
 EXPORT_SYMBOL(seq_list_start);
 
 struct list_head *seq_list_start_head(struct list_head *head, loff_t pos)
@@ -684,7 +683,6 @@ struct list_head *seq_list_start_head(struct list_head *head, loff_t pos)
 
 	return seq_list_start(head, pos - 1);
 }
-
 EXPORT_SYMBOL(seq_list_start_head);
 
 struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos)
@@ -695,5 +693,38 @@ struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos)
 	++*ppos;
 	return lh == head ? NULL : lh;
 }
-
 EXPORT_SYMBOL(seq_list_next);
+
+struct hlist_node *seq_hlist_start(struct hlist_head *head, loff_t pos)
+{
+	struct hlist_node *node;
+
+	hlist_for_each(node, head)
+		if (pos-- == 0)
+			return node;
+	return NULL;
+}
+EXPORT_SYMBOL(seq_hlist_start);
+
+struct hlist_node *seq_hlist_start_head(struct hlist_head *head, loff_t pos)
+{
+	if (!pos)
+		return SEQ_START_TOKEN;
+
+	return seq_hlist_start(head, pos - 1);
+}
+EXPORT_SYMBOL(seq_hlist_start_head);
+
+struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head,
+				  loff_t *ppos)
+{
+	struct hlist_node *node = v;
+
+	++*ppos;
+	if (v == SEQ_START_TOKEN)
+		return head->first;
+	else
+		return node->next;
+}
+EXPORT_SYMBOL(seq_hlist_next);
+
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index 8366d8f..c95bcdc 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -135,4 +135,15 @@ extern struct list_head *seq_list_start_head(struct list_head *head,
 extern struct list_head *seq_list_next(void *v, struct list_head *head,
 		loff_t *ppos);
 
+/*
+ * Helpers for iteration over hlist_head-s in seq_files
+ */
+
+extern struct hlist_node *seq_hlist_start(struct hlist_head *head,
+		loff_t pos);
+extern struct hlist_node *seq_hlist_start_head(struct hlist_head *head,
+		loff_t pos);
+extern struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head,
+		loff_t *ppos);
+
 #endif
-- 1.6.3 

^ permalink raw reply related

* Re: [PATCH] mlx4: replace the dma_sync_single_range_for_cpu/device API
From: David Miller @ 2010-02-05  5:09 UTC (permalink / raw)
  To: fujita.tomonori; +Cc: netdev, rolandd, eli, linux-kernel
In-Reply-To: <20100205135626G.fujita.tomonori@lab.ntt.co.jp>

From: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Date: Fri, 5 Feb 2010 13:57:42 +0900

> There are only two users of the dma_sync_single_range_for_cpu/device
> API in mainline (mlx4 and ssb). The
> dma_sync_single_range_for_cpu/device API has never been documented and
> the dma_sync_single_for_cpu/device API also support a partial sync.
> 
> This converts mlx4 to use the dma_sync_single_for_cpu/device API
> (preparations for the removal of the dma_sync_single_range_for_cpu/device API).
> 
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>

Acked-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply

* [PATCH] ssb: replace the dma_sync_single_range_for_cpu/device API
From: FUJITA Tomonori @ 2010-02-05  5:49 UTC (permalink / raw)
  To: netdev; +Cc: mb, linville, linux-kernel, zambrano, davem

There are only two users of the dma_sync_single_range_for_cpu/device
API in mainline (mlx4 and ssb). The
dma_sync_single_range_for_cpu/device API has never been documented and
the dma_sync_single_for_cpu/device API also support a partial sync.

This converts ssb (and b44) to use the dma_sync_single_for_cpu/device
API (preparations for the removal of the
dma_sync_single_range_for_cpu/device API). It also removes unnecessary
ssb_dma_sync_single_range_for_cpu/device.

This lets dma_desc_align_mask alone in b44 but we can remove it since
dma_sync_single_for_cpu/device() rounds up/down safely.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
---
 drivers/net/b44.c       |   10 +++-----
 include/linux/ssb/ssb.h |   51 -----------------------------------------------
 2 files changed, 4 insertions(+), 57 deletions(-)

diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index 44b66be..c3177e3 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -148,9 +148,8 @@ static inline void b44_sync_dma_desc_for_device(struct ssb_device *sdev,
 						unsigned long offset,
 						enum dma_data_direction dir)
 {
-	ssb_dma_sync_single_range_for_device(sdev, dma_base,
-					     offset & dma_desc_align_mask,
-					     dma_desc_sync_size, dir);
+	ssb_dma_sync_single_for_device(sdev, dma_base + (offset & dma_desc_align_mask),
+				       dma_desc_sync_size, dir);
 }
 
 static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
@@ -158,9 +157,8 @@ static inline void b44_sync_dma_desc_for_cpu(struct ssb_device *sdev,
 					     unsigned long offset,
 					     enum dma_data_direction dir)
 {
-	ssb_dma_sync_single_range_for_cpu(sdev, dma_base,
-					  offset & dma_desc_align_mask,
-					  dma_desc_sync_size, dir);
+	ssb_dma_sync_single_for_cpu(sdev, dma_base + (offset & dma_desc_align_mask),
+				    dma_desc_sync_size, dir);
 }
 
 static inline unsigned long br32(const struct b44 *bp, unsigned long reg)
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index 24f9885..e99c5d3 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -580,57 +580,6 @@ static inline void ssb_dma_sync_single_for_device(struct ssb_device *dev,
 	__ssb_dma_not_implemented(dev);
 }
 
-static inline void ssb_dma_sync_single_range_for_cpu(struct ssb_device *dev,
-						     dma_addr_t dma_addr,
-						     unsigned long offset,
-						     size_t size,
-						     enum dma_data_direction dir)
-{
-	switch (dev->bus->bustype) {
-	case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
-		/* Just sync everything. That's all the PCI API can do. */
-		pci_dma_sync_single_for_cpu(dev->bus->host_pci, dma_addr,
-					    offset + size, dir);
-		return;
-#endif
-		break;
-	case SSB_BUSTYPE_SSB:
-		dma_sync_single_range_for_cpu(dev->dev, dma_addr, offset,
-					      size, dir);
-		return;
-	default:
-		break;
-	}
-	__ssb_dma_not_implemented(dev);
-}
-
-static inline void ssb_dma_sync_single_range_for_device(struct ssb_device *dev,
-							dma_addr_t dma_addr,
-							unsigned long offset,
-							size_t size,
-							enum dma_data_direction dir)
-{
-	switch (dev->bus->bustype) {
-	case SSB_BUSTYPE_PCI:
-#ifdef CONFIG_SSB_PCIHOST
-		/* Just sync everything. That's all the PCI API can do. */
-		pci_dma_sync_single_for_device(dev->bus->host_pci, dma_addr,
-					       offset + size, dir);
-		return;
-#endif
-		break;
-	case SSB_BUSTYPE_SSB:
-		dma_sync_single_range_for_device(dev->dev, dma_addr, offset,
-						 size, dir);
-		return;
-	default:
-		break;
-	}
-	__ssb_dma_not_implemented(dev);
-}
-
-
 #ifdef CONFIG_SSB_PCIHOST
 /* PCI-host wrapper driver */
 extern int ssb_pcihost_register(struct pci_driver *driver);
-- 
1.5.6.5

^ permalink raw reply related

* linux-next: build failure after merge of the net tree
From: Stephen Rothwell @ 2010-02-05  5:50 UTC (permalink / raw)
  To: David Miller, netdev; +Cc: linux-next, linux-kernel, Nick Nunley

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

Hi Dave,

After merging the scsi-post-merge tree, today's linux-next build (powerpc
allyesconfig and i386 defconfig) failed like this:

drivers/net/e1000e/built-in.o: In function `e1000_has_link':
(.opd+0x1d58): multiple definition of `e1000_has_link'
drivers/net/e1000/built-in.o:(.opd+0x588): first defined here

Caused by commit b548192acaebcb05d6a87d1e94f19835b1a18a8b ("e1000: Report
link status in ethtool when interface is down").

I have reverted that commit for today.
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

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

^ permalink raw reply

* Re: [RFC Patch] net: reserve ports for applications using fixed port numbers
From: Cong Wang @ 2010-02-05  6:01 UTC (permalink / raw)
  To: Octavian Purdila
  Cc: Tetsuo Handa, davem, linux-kernel, eric.dumazet, linux-rdma,
	netdev, nhorman, linux-sctp
In-Reply-To: <201002050305.22227.opurdila@ixiacom.com>

Octavian Purdila wrote:
> On Friday 05 February 2010 02:41:12 you wrote:
>> David Miller wrote:
>>>> Octavian Purdila wrote:
>>>>> int inet_is_reserved_local_port(int port)
>>>>> {
>>>>> 	if (test_bit(port, reserved_ports))
>>>>> 		return 1;
>>>>> 	return 0;
>>>>> }
>>>> Above check is exactly what I'm doing in the LSM hook.
>>> But his version can be done inline in 2 or 3 instructions.
>>>
>>> An LSM hook will result in an indirect function call,
>>> all live registers spilled to the stack, then all of
>>> those reloaded when the function returns.
>>>
>>> It will be much more expensive.
>> If you can accept his version, I want to use his version (with an interface
>>  for updating above "reserved_ports" by not only root user's sysctl() but
>>  also MAC's policy configuration).
>>
> 
> I think that simply using an interface to update the reserved_ports from MAC 
> policy configuration module wouldn't work, as root will be able to modify the 
> policy via sysctl.
> 
> I think that we might need to:
> 
> a) have a reserved_port updater
> 
> b) put a LSM hook into that
> 
> c) use the reserved_port updater from sysctl
> 
> 

Ideally, you'd provide an interface for port allocator to use, so
doing port reservation will be easier.

Thanks.



^ permalink raw reply

* [net-next-2.6 PATCH 1/3] ethtool: Introduce n-tuple filter programming support
From: Jeff Kirsher @ 2010-02-05  6:21 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Peter P Waskiewicz Jr, Jeff Kirsher

From: Peter Waskiewicz <peter.p.waskiewicz.jr@intel.com>

This patchset enables the ethtool layer to program n-tuple
filters to an underlying device.  The idea is to allow capable
hardware to have static rules applied that can assist steering
flows into appropriate queues.

Hardware that is known to support these types of filters today
are ixgbe and niu.

Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 include/linux/ethtool.h   |   49 +++++++
 include/linux/netdevice.h |    3 
 net/core/dev.c            |    9 +
 net/core/ethtool.c        |  335 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 395 insertions(+), 1 deletions(-)

diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index ef4a2d8..446c91e 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -14,6 +14,7 @@
 #define _LINUX_ETHTOOL_H
 
 #include <linux/types.h>
+#include <linux/rculist.h>
 
 /* This should work for both 32 and 64 bit userland. */
 struct ethtool_cmd {
@@ -242,6 +243,7 @@ enum ethtool_stringset {
 	ETH_SS_TEST		= 0,
 	ETH_SS_STATS,
 	ETH_SS_PRIV_FLAGS,
+	ETH_SS_NTUPLE_FILTERS,
 };
 
 /* for passing string sets for data tagging */
@@ -290,6 +292,7 @@ struct ethtool_perm_addr {
  */
 enum ethtool_flags {
 	ETH_FLAG_LRO		= (1 << 15),	/* LRO is enabled */
+	ETH_FLAG_NTUPLE		= (1 << 27),	/* N-tuple filters enabled */
 };
 
 /* The following structures are for supporting RX network flow
@@ -363,6 +366,47 @@ struct ethtool_rxnfc {
 	__u32				rule_locs[0];
 };
 
+struct ethtool_rx_ntuple_flow_spec {
+	__u32		 flow_type;
+	union {
+		struct ethtool_tcpip4_spec		tcp_ip4_spec;
+		struct ethtool_tcpip4_spec		udp_ip4_spec;
+		struct ethtool_tcpip4_spec		sctp_ip4_spec;
+		struct ethtool_ah_espip4_spec		ah_ip4_spec;
+		struct ethtool_ah_espip4_spec		esp_ip4_spec;
+		struct ethtool_rawip4_spec		raw_ip4_spec;
+		struct ethtool_ether_spec		ether_spec;
+		struct ethtool_usrip4_spec		usr_ip4_spec;
+		__u8					hdata[64];
+	} h_u, m_u; /* entry, mask */
+
+	__u16	        vlan_tag;
+	__u16	        vlan_tag_mask;
+	__u64		data;      /* user-defined flow spec data */
+	__u64		data_mask; /* user-defined flow spec mask */
+
+	/* signed to distinguish between queue and actions (DROP) */
+	__s32		action;
+#define ETHTOOL_RXNTUPLE_ACTION_DROP -1
+};
+
+struct ethtool_rx_ntuple_flow_spec_container {
+	struct ethtool_rx_ntuple_flow_spec fs;
+	struct list_head list;
+};
+
+struct ethtool_rx_ntuple_list {
+#define ETHTOOL_MAX_NTUPLE_LIST_ENTRY 1024
+#define ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY 14
+	struct list_head	list;
+	int			count;
+};
+
+struct ethtool_rx_ntuple {
+	__u32					cmd;
+	struct ethtool_rx_ntuple_flow_spec	fs;
+};
+
 #define ETHTOOL_FLASH_MAX_FILENAME	128
 enum ethtool_flash_op_type {
 	ETHTOOL_FLASH_ALL_REGIONS	= 0,
@@ -500,6 +544,8 @@ struct ethtool_ops {
 	int	(*set_rxnfc)(struct net_device *, struct ethtool_rxnfc *);
 	int     (*flash_device)(struct net_device *, struct ethtool_flash *);
 	int	(*reset)(struct net_device *, u32 *);
+	int	(*set_rx_ntuple)(struct net_device *, struct ethtool_rx_ntuple *);
+	int	(*get_rx_ntuple)(struct net_device *, u32 stringset, void *);
 };
 #endif /* __KERNEL__ */
 
@@ -559,6 +605,9 @@ struct ethtool_ops {
 #define	ETHTOOL_FLASHDEV	0x00000033 /* Flash firmware to device */
 #define	ETHTOOL_RESET		0x00000034 /* Reset hardware */
 
+#define ETHTOOL_SRXNTUPLE	0x00000035 /* Add an n-tuple filter to device */
+#define ETHTOOL_GRXNTUPLE	0x00000036 /* Get n-tuple filters from device */
+
 /* compatibility with older code */
 #define SPARC_ETH_GSET		ETHTOOL_GSET
 #define SPARC_ETH_SSET		ETHTOOL_SSET
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index e535700..cdf53a8 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -746,6 +746,7 @@ struct net_device {
 #define NETIF_F_FCOE_CRC	(1 << 24) /* FCoE CRC32 */
 #define NETIF_F_SCTP_CSUM	(1 << 25) /* SCTP checksum offload */
 #define NETIF_F_FCOE_MTU	(1 << 26) /* Supports max FCoE MTU, 2158 bytes*/
+#define NETIF_F_NTUPLE		(1 << 27) /* N-tuple filters supported */
 
 	/* Segmentation offload features */
 #define NETIF_F_GSO_SHIFT	16
@@ -954,6 +955,8 @@ struct net_device {
 	/* max exchange id for FCoE LRO by ddp */
 	unsigned int		fcoe_ddp_xid;
 #endif
+	/* n-tuple filter list attached to this device */
+	struct ethtool_rx_ntuple_list ethtool_ntuple_list;
 };
 #define to_net_dev(d) container_of(d, struct net_device, dev)
 
diff --git a/net/core/dev.c b/net/core/dev.c
index 94c1eee..4593abe 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5419,6 +5419,8 @@ struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name,
 
 	netdev_init_queues(dev);
 
+	INIT_LIST_HEAD(&dev->ethtool_ntuple_list.list);
+	dev->ethtool_ntuple_list.count = 0;
 	INIT_LIST_HEAD(&dev->napi_list);
 	INIT_LIST_HEAD(&dev->unreg_list);
 	INIT_LIST_HEAD(&dev->link_watch_list);
@@ -5447,6 +5449,7 @@ EXPORT_SYMBOL(alloc_netdev_mq);
 void free_netdev(struct net_device *dev)
 {
 	struct napi_struct *p, *n;
+	struct ethtool_rx_ntuple_flow_spec_container *fsc, *f;
 
 	release_net(dev_net(dev));
 
@@ -5455,6 +5458,12 @@ void free_netdev(struct net_device *dev)
 	/* Flush device addresses */
 	dev_addr_flush(dev);
 
+	/* Clear ethtool n-tuple list */
+	list_for_each_entry_safe(fsc, f, &dev->ethtool_ntuple_list.list, list) {
+		list_del(&fsc->list);
+	}
+	dev->ethtool_ntuple_list.count = 0;
+
 	list_for_each_entry_safe(p, n, &dev->napi_list, dev_list)
 		netif_napi_del(p);
 
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index d8aee58..fa703c6 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -120,7 +120,7 @@ int ethtool_op_set_ufo(struct net_device *dev, u32 data)
  * NETIF_F_xxx values in include/linux/netdevice.h
  */
 static const u32 flags_dup_features =
-	ETH_FLAG_LRO;
+	(ETH_FLAG_LRO | ETH_FLAG_NTUPLE);
 
 u32 ethtool_op_get_flags(struct net_device *dev)
 {
@@ -139,6 +139,11 @@ int ethtool_op_set_flags(struct net_device *dev, u32 data)
 	else
 		dev->features &= ~NETIF_F_LRO;
 
+	if (data & ETH_FLAG_NTUPLE)
+		dev->features |= NETIF_F_NTUPLE;
+	else
+		dev->features &= ~NETIF_F_NTUPLE;
+
 	return 0;
 }
 
@@ -266,6 +271,313 @@ err_out:
 	return ret;
 }
 
+static int __rx_ntuple_filter_add(struct ethtool_rx_ntuple_list *list,
+                                  struct ethtool_rx_ntuple_flow_spec *spec)
+{
+	struct ethtool_rx_ntuple_flow_spec_container *fsc;
+	int alloc_size;
+
+	/* don't add filters forever */
+	if (list->count >= ETHTOOL_MAX_NTUPLE_LIST_ENTRY)
+		return 0;
+
+	list_for_each_entry(fsc, &list->list, list) { /* run to end */ }
+
+	alloc_size = sizeof(*fsc);
+	if (alloc_size < L1_CACHE_BYTES)
+		alloc_size = L1_CACHE_BYTES;
+	fsc = kmalloc(alloc_size, GFP_ATOMIC);
+	if (!fsc)
+		return -ENOMEM;
+
+	/* Copy the whole filter over */
+	fsc->fs.flow_type = spec->flow_type;
+	memcpy(&fsc->fs.h_u, &spec->h_u, sizeof(spec->h_u));
+	memcpy(&fsc->fs.m_u, &spec->m_u, sizeof(spec->m_u));
+
+	fsc->fs.vlan_tag = spec->vlan_tag;
+	fsc->fs.vlan_tag_mask = spec->vlan_tag_mask;
+	fsc->fs.data = spec->data;
+	fsc->fs.data_mask = spec->data_mask;
+	fsc->fs.action = spec->action;
+
+	/* add to the list */
+	list_add_tail_rcu(&fsc->list, &list->list);
+	list->count++;
+
+	return 0;
+}
+
+static int ethtool_set_rx_ntuple(struct net_device *dev, void __user *useraddr)
+{
+	struct ethtool_rx_ntuple cmd;
+	const struct ethtool_ops *ops = dev->ethtool_ops;
+	int ret;
+
+	if (!ops->set_rx_ntuple)
+		return -EOPNOTSUPP;
+
+	if (!(dev->features & NETIF_F_NTUPLE))
+		return -EINVAL;
+
+	if (copy_from_user(&cmd, useraddr, sizeof(cmd)))
+		return -EFAULT;
+
+	ret = ops->set_rx_ntuple(dev, &cmd);
+
+	/*
+	 * Cache filter in dev struct for GET operation only if
+	 * the underlying driver doesn't have its own GET operation, and
+	 * only if the filter was added successfully.
+	 */
+	if (!ops->get_rx_ntuple && !ret)
+		if (__rx_ntuple_filter_add(&dev->ethtool_ntuple_list, &cmd.fs))
+			return -ENOMEM;
+
+	return ret;
+}
+
+static int ethtool_get_rx_ntuple(struct net_device *dev, void __user *useraddr)
+{
+	struct ethtool_gstrings gstrings;
+	const struct ethtool_ops *ops = dev->ethtool_ops;
+	struct ethtool_rx_ntuple_flow_spec_container *fsc;
+	u8 *data;
+	char *p;
+	int ret, i, num_strings = 0;
+
+	if (!ops->get_sset_count)
+		return -EOPNOTSUPP;
+
+	if (copy_from_user(&gstrings, useraddr, sizeof(gstrings)))
+		return -EFAULT;
+
+	ret = ops->get_sset_count(dev, gstrings.string_set);
+	if (ret < 0)
+		return ret;
+
+	gstrings.len = ret;
+
+	data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
+	if (!data)
+		return -ENOMEM;
+
+	if (ops->get_rx_ntuple) {
+		/* driver-specific filter grab */
+		ret = ops->get_rx_ntuple(dev, gstrings.string_set, data);
+		goto copy;
+	}
+
+	/* default ethtool filter grab */
+	i = 0;
+	p = (char *)data;
+	list_for_each_entry(fsc, &dev->ethtool_ntuple_list.list, list) {
+		sprintf(p, "Filter %d:\n", i);
+		p += ETH_GSTRING_LEN;
+		num_strings++;
+
+		switch (fsc->fs.flow_type) {
+		case TCP_V4_FLOW:
+			sprintf(p, "\tFlow Type: TCP\n");
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			break;
+		case UDP_V4_FLOW:
+			sprintf(p, "\tFlow Type: UDP\n");
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			break;
+		case SCTP_V4_FLOW:
+			sprintf(p, "\tFlow Type: SCTP\n");
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			break;
+		case AH_ESP_V4_FLOW:
+			sprintf(p, "\tFlow Type: AH ESP\n");
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			break;
+		case ESP_V4_FLOW:
+			sprintf(p, "\tFlow Type: ESP\n");
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			break;
+		case IP_USER_FLOW:
+			sprintf(p, "\tFlow Type: Raw IP\n");
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			break;
+		case IPV4_FLOW:
+			sprintf(p, "\tFlow Type: IPv4\n");
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			break;
+		default:
+			sprintf(p, "\tFlow Type: Unknown\n");
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			goto unknown_filter;
+		};
+
+		/* now the rest of the filters */
+		switch (fsc->fs.flow_type) {
+		case TCP_V4_FLOW:
+		case UDP_V4_FLOW:
+		case SCTP_V4_FLOW:
+			sprintf(p, "\tSrc IP addr: 0x%x\n",
+			        fsc->fs.h_u.tcp_ip4_spec.ip4src);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tSrc IP mask: 0x%x\n",
+			        fsc->fs.m_u.tcp_ip4_spec.ip4src);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tDest IP addr: 0x%x\n",
+			        fsc->fs.h_u.tcp_ip4_spec.ip4dst);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tDest IP mask: 0x%x\n",
+			        fsc->fs.m_u.tcp_ip4_spec.ip4dst);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tSrc Port: %d, mask: 0x%x\n",
+			        fsc->fs.h_u.tcp_ip4_spec.psrc,
+			        fsc->fs.m_u.tcp_ip4_spec.psrc);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tDest Port: %d, mask: 0x%x\n",
+			        fsc->fs.h_u.tcp_ip4_spec.pdst,
+			        fsc->fs.m_u.tcp_ip4_spec.pdst);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tTOS: %d, mask: 0x%x\n",
+			        fsc->fs.h_u.tcp_ip4_spec.tos,
+			        fsc->fs.m_u.tcp_ip4_spec.tos);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			break;
+		case AH_ESP_V4_FLOW:
+		case ESP_V4_FLOW:
+			sprintf(p, "\tSrc IP addr: 0x%x\n",
+			        fsc->fs.h_u.ah_ip4_spec.ip4src);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tSrc IP mask: 0x%x\n",
+			        fsc->fs.m_u.ah_ip4_spec.ip4src);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tDest IP addr: 0x%x\n",
+			        fsc->fs.h_u.ah_ip4_spec.ip4dst);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tDest IP mask: 0x%x\n",
+			        fsc->fs.m_u.ah_ip4_spec.ip4dst);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tSPI: %d, mask: 0x%x\n",
+			        fsc->fs.h_u.ah_ip4_spec.spi,
+			        fsc->fs.m_u.ah_ip4_spec.spi);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tTOS: %d, mask: 0x%x\n",
+			        fsc->fs.h_u.ah_ip4_spec.tos,
+			        fsc->fs.m_u.ah_ip4_spec.tos);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			break;
+		case IP_USER_FLOW:
+			sprintf(p, "\tSrc IP addr: 0x%x\n",
+			        fsc->fs.h_u.raw_ip4_spec.ip4src);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tSrc IP mask: 0x%x\n",
+			        fsc->fs.m_u.raw_ip4_spec.ip4src);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tDest IP addr: 0x%x\n",
+			        fsc->fs.h_u.raw_ip4_spec.ip4dst);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tDest IP mask: 0x%x\n",
+			        fsc->fs.m_u.raw_ip4_spec.ip4dst);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			break;
+		case IPV4_FLOW:
+			sprintf(p, "\tSrc IP addr: 0x%x\n",
+			        fsc->fs.h_u.usr_ip4_spec.ip4src);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tSrc IP mask: 0x%x\n",
+			        fsc->fs.m_u.usr_ip4_spec.ip4src);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tDest IP addr: 0x%x\n",
+			        fsc->fs.h_u.usr_ip4_spec.ip4dst);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tDest IP mask: 0x%x\n",
+			        fsc->fs.m_u.usr_ip4_spec.ip4dst);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tL4 bytes: 0x%x, mask: 0x%x\n",
+			        fsc->fs.h_u.usr_ip4_spec.l4_4_bytes,
+			        fsc->fs.m_u.usr_ip4_spec.l4_4_bytes);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tTOS: %d, mask: 0x%x\n",
+			        fsc->fs.h_u.usr_ip4_spec.tos,
+			        fsc->fs.m_u.usr_ip4_spec.tos);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tIP Version: %d, mask: 0x%x\n",
+			        fsc->fs.h_u.usr_ip4_spec.ip_ver,
+			        fsc->fs.m_u.usr_ip4_spec.ip_ver);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			sprintf(p, "\tProtocol: %d, mask: 0x%x\n",
+			        fsc->fs.h_u.usr_ip4_spec.proto,
+			        fsc->fs.m_u.usr_ip4_spec.proto);
+			p += ETH_GSTRING_LEN;
+			num_strings++;
+			break;
+		};
+		sprintf(p, "\tVLAN: %d, mask: 0x%x\n",
+		        fsc->fs.vlan_tag, fsc->fs.vlan_tag_mask);
+		p += ETH_GSTRING_LEN;
+		num_strings++;
+		sprintf(p, "\tUser-defined: 0x%Lx\n", fsc->fs.data);
+		p += ETH_GSTRING_LEN;
+		num_strings++;
+		sprintf(p, "\tUser-defined mask: 0x%Lx\n", fsc->fs.data_mask);
+		p += ETH_GSTRING_LEN;
+		num_strings++;
+		if (fsc->fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP)
+			sprintf(p, "\tAction: Drop\n");
+		else
+			sprintf(p, "\tAction: Direct to queue %d\n",
+			        fsc->fs.action);
+		p += ETH_GSTRING_LEN;
+		num_strings++;
+unknown_filter:
+		i++;
+	}
+copy:
+	/* indicate to userspace how many strings we actually have */
+	gstrings.len = num_strings;
+	ret = -EFAULT;
+	if (copy_to_user(useraddr, &gstrings, sizeof(gstrings)))
+		goto out;
+	useraddr += sizeof(gstrings);
+	if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN))
+		goto out;
+	ret = 0;
+
+out:
+	kfree(data);
+	return ret;
+}
+
 static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
 {
 	struct ethtool_regs regs;
@@ -305,6 +617,7 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr)
 static int ethtool_reset(struct net_device *dev, char __user *useraddr)
 {
 	struct ethtool_value reset;
+	struct ethtool_rx_ntuple_flow_spec_container *fsc, *f;
 	int ret;
 
 	if (!dev->ethtool_ops->reset)
@@ -313,6 +626,12 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr)
 	if (copy_from_user(&reset, useraddr, sizeof(reset)))
 		return -EFAULT;
 
+	/* Clear ethtool n-tuple list */
+	list_for_each_entry_safe(fsc, f, &dev->ethtool_ntuple_list.list, list) {
+		list_del(&fsc->list);
+	}
+	dev->ethtool_ntuple_list.count = 0;
+
 	ret = dev->ethtool_ops->reset(dev, &reset.data);
 	if (ret)
 		return ret;
@@ -351,9 +670,17 @@ static int ethtool_set_wol(struct net_device *dev, char __user *useraddr)
 
 static int ethtool_nway_reset(struct net_device *dev)
 {
+	struct ethtool_rx_ntuple_flow_spec_container *fsc, *f;
+
 	if (!dev->ethtool_ops->nway_reset)
 		return -EOPNOTSUPP;
 
+	/* Clear ethtool n-tuple list */
+	list_for_each_entry_safe(fsc, f, &dev->ethtool_ntuple_list.list, list) {
+		list_del(&fsc->list);
+	}
+	dev->ethtool_ntuple_list.count = 0;
+
 	return dev->ethtool_ops->nway_reset(dev);
 }
 
@@ -1112,6 +1439,12 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
 	case ETHTOOL_RESET:
 		rc = ethtool_reset(dev, useraddr);
 		break;
+	case ETHTOOL_SRXNTUPLE:
+		rc = ethtool_set_rx_ntuple(dev, useraddr);
+		break;
+	case ETHTOOL_GRXNTUPLE:
+		rc = ethtool_get_rx_ntuple(dev, useraddr);
+		break;
 	default:
 		rc = -EOPNOTSUPP;
 	}


^ permalink raw reply related

* [net-next-2.6 PATCH 2/3] ixgbe: Add support for the new ethtool n-tuple programming interface
From: Jeff Kirsher @ 2010-02-05  6:22 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Peter P Waskiewicz Jr, Jeff Kirsher
In-Reply-To: <20100205062131.20910.10580.stgit@localhost.localdomain>

From: Peter Waskiewicz <peter.p.waskiewicz.jr@intel.com>

This patch adds n-tuple filter programming to 82599.

Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/ixgbe/ixgbe.h         |    4 +
 drivers/net/ixgbe/ixgbe_82599.c   |  106 +++++++++++++++++++++++++++++++----
 drivers/net/ixgbe/ixgbe_ethtool.c |  111 ++++++++++++++++++++++++++++++++++++-
 drivers/net/ixgbe/ixgbe_main.c    |   13 ++++
 drivers/net/ixgbe/ixgbe_type.h    |    9 +++
 5 files changed, 225 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index bffbe0d..19e94ee 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -453,6 +453,10 @@ extern s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc);
 extern s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
                                                  struct ixgbe_atr_input *input,
                                                  u8 queue);
+extern s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
+                                      struct ixgbe_atr_input *input,
+                                      struct ixgbe_atr_input_masks *input_masks,
+                                      u16 soft_id, u8 queue);
 extern s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input,
                                        u16 vlan_id);
 extern s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input,
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c
index d4ed6ad..4fa8633 100644
--- a/drivers/net/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ixgbe/ixgbe_82599.c
@@ -1439,6 +1439,9 @@ s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc)
 	/* Send interrupt when 64 filters are left */
 	fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
 
+	/* Initialize the drop queue to Rx queue 127 */
+	fdirctrl |= (127 << IXGBE_FDIRCTRL_DROP_Q_SHIFT);
+
 	switch (pballoc) {
 	case IXGBE_FDIR_PBALLOC_64K:
 		/* 2k - 1 perfect filters */
@@ -1628,6 +1631,7 @@ static u16 ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *atr_input,
  *  ixgbe_atr_set_vlan_id_82599 - Sets the VLAN id in the ATR input stream
  *  @input: input stream to modify
  *  @vlan: the VLAN id to load
+ *  @vlan_mask: bitwise mask for the VLAN
  **/
 s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan)
 {
@@ -1641,6 +1645,7 @@ s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan)
  *  ixgbe_atr_set_src_ipv4_82599 - Sets the source IPv4 address
  *  @input: input stream to modify
  *  @src_addr: the IP address to load
+ *  @src_addr_mask: bitwise mask for the source IP address
  **/
 s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr)
 {
@@ -1658,6 +1663,7 @@ s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr)
  *  ixgbe_atr_set_dst_ipv4_82599 - Sets the destination IPv4 address
  *  @input: input stream to modify
  *  @dst_addr: the IP address to load
+ *  @dst_addr_mask: bitwise mask for the destination IP address
  **/
 s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr)
 {
@@ -1680,8 +1686,8 @@ s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr)
  *  @src_addr_4: the fourth 4 bytes of the IP address to load
  **/
 s32 ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input,
-                                        u32 src_addr_1, u32 src_addr_2,
-                                        u32 src_addr_3, u32 src_addr_4)
+                                 u32 src_addr_1, u32 src_addr_2,
+                                 u32 src_addr_3, u32 src_addr_4)
 {
 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET] = src_addr_4 & 0xff;
 	input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] =
@@ -1723,8 +1729,8 @@ s32 ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input,
  *  @dst_addr_4: the fourth 4 bytes of the IP address to load
  **/
 s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input,
-                                        u32 dst_addr_1, u32 dst_addr_2,
-                                        u32 dst_addr_3, u32 dst_addr_4)
+                                 u32 dst_addr_1, u32 dst_addr_2,
+                                 u32 dst_addr_3, u32 dst_addr_4)
 {
 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET] = dst_addr_4 & 0xff;
 	input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] =
@@ -1761,6 +1767,7 @@ s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input,
  *  ixgbe_atr_set_src_port_82599 - Sets the source port
  *  @input: input stream to modify
  *  @src_port: the source port to load
+ *  @src_port_mask: bitwise mask for the source port
  **/
 s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port)
 {
@@ -1774,6 +1781,7 @@ s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port)
  *  ixgbe_atr_set_dst_port_82599 - Sets the destination port
  *  @input: input stream to modify
  *  @dst_port: the destination port to load
+ *  @dst_port_mask: bitwise mask for the destination port
  **/
 s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, u16 dst_port)
 {
@@ -1802,7 +1810,7 @@ s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte)
  *  @vm_pool: the Virtual Machine pool to load
  **/
 s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input,
-                                       u8 vm_pool)
+                                u8 vm_pool)
 {
 	input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET] = vm_pool;
 
@@ -1826,8 +1834,7 @@ s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, u8 l4type)
  *  @input: input stream to search
  *  @vlan: the VLAN id to load
  **/
-static s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input,
-                                       u16 *vlan)
+static s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, u16 *vlan)
 {
 	*vlan = input->byte_stream[IXGBE_ATR_VLAN_OFFSET];
 	*vlan |= input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] << 8;
@@ -2083,23 +2090,26 @@ s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
  *  ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter
  *  @hw: pointer to hardware structure
  *  @input: input bitstream
+ *  @input_masks: bitwise masks for relevant fields
+ *  @soft_id: software index into the silicon hash tables for filter storage
  *  @queue: queue index to direct traffic to
  *
  *  Note that the caller to this function must lock before calling, since the
  *  hardware writes must be protected from one another.
  **/
 s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
-                                               struct ixgbe_atr_input *input,
-                                               u16 soft_id,
-                                               u8 queue)
+                                      struct ixgbe_atr_input *input,
+                                      struct ixgbe_atr_input_masks *input_masks,
+                                      u16 soft_id, u8 queue)
 {
 	u32 fdircmd = 0;
 	u32 fdirhash;
-	u32 src_ipv4, dst_ipv4;
+	u32 src_ipv4 = 0, dst_ipv4 = 0;
 	u32 src_ipv6_1, src_ipv6_2, src_ipv6_3, src_ipv6_4;
 	u16 src_port, dst_port, vlan_id, flex_bytes;
 	u16 bucket_hash;
 	u8  l4type;
+	u8  fdirm = 0;
 
 	/* Get our input values */
 	ixgbe_atr_get_l4type_82599(input, &l4type);
@@ -2154,7 +2164,6 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
 		/* IPv4 */
 		ixgbe_atr_get_src_ipv4_82599(input, &src_ipv4);
 		IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, src_ipv4);
-
 	}
 
 	ixgbe_atr_get_dst_ipv4_82599(input, &dst_ipv4);
@@ -2163,7 +2172,78 @@ s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
 	IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, (vlan_id |
 	                            (flex_bytes << IXGBE_FDIRVLAN_FLEX_SHIFT)));
 	IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, (src_port |
-	                       (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT)));
+	              (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT)));
+
+	/*
+	 * Program the relevant mask registers.  If src/dst_port or src/dst_addr
+	 * are zero, then assume a full mask for that field.  Also assume that
+	 * a VLAN of 0 is unspecified, so mask that out as well.  L4type
+	 * cannot be masked out in this implementation.
+	 *
+	 * This also assumes IPv4 only.  IPv6 masking isn't supported at this
+	 * point in time.
+	 */
+	if (src_ipv4 == 0)
+		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, 0xffffffff);
+	else
+		IXGBE_WRITE_REG(hw, IXGBE_FDIRSIP4M, input_masks->src_ip_mask);
+
+	if (dst_ipv4 == 0)
+		IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, 0xffffffff);
+	else
+		IXGBE_WRITE_REG(hw, IXGBE_FDIRDIP4M, input_masks->dst_ip_mask);
+
+	switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
+	case IXGBE_ATR_L4TYPE_TCP:
+		if (src_port == 0)
+			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM, 0xffff);
+		else
+			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
+			                input_masks->src_port_mask);
+
+		if (dst_port == 0)
+			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
+			               (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) |
+			                (0xffff << 16)));
+		else
+			IXGBE_WRITE_REG(hw, IXGBE_FDIRTCPM,
+			               (IXGBE_READ_REG(hw, IXGBE_FDIRTCPM) |
+			                (input_masks->dst_port_mask << 16)));
+		break;
+	case IXGBE_ATR_L4TYPE_UDP:
+		if (src_port == 0)
+			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM, 0xffff);
+		else
+			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
+			                input_masks->src_port_mask);
+
+		if (dst_port == 0)
+			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
+			               (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) |
+			                (0xffff << 16)));
+		else
+			IXGBE_WRITE_REG(hw, IXGBE_FDIRUDPM,
+			               (IXGBE_READ_REG(hw, IXGBE_FDIRUDPM) |
+			                (input_masks->src_port_mask << 16)));
+		break;
+	default:
+		/* this already would have failed above */
+		break;
+	}
+
+	/* Program the last mask register, FDIRM */
+	if (input_masks->vlan_id_mask || !vlan_id)
+		/* Mask both VLAN and VLANP - bits 0 and 1 */
+		fdirm |= 0x3;
+
+	if (input_masks->data_mask || !flex_bytes)
+		/* Flex bytes need masking, so mask the whole thing - bit 4 */
+		fdirm |= 0x10;
+
+	/* Now mask VM pool and destination IPv6 - bits 5 and 2 */
+	fdirm |= 0x24;
+
+	IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
 
 	fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW;
 	fdircmd |= IXGBE_FDIRCMD_FILTER_UPDATE;
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 07a9410..0d23434 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -979,6 +979,9 @@ static int ixgbe_get_sset_count(struct net_device *netdev, int sset)
 		return IXGBE_TEST_LEN;
 	case ETH_SS_STATS:
 		return IXGBE_STATS_LEN;
+	case ETH_SS_NTUPLE_FILTERS:
+		return (ETHTOOL_MAX_NTUPLE_LIST_ENTRY *
+		        ETHTOOL_MAX_NTUPLE_STRING_PER_ENTRY);
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -2150,23 +2153,124 @@ static int ixgbe_set_coalesce(struct net_device *netdev,
 static int ixgbe_set_flags(struct net_device *netdev, u32 data)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	bool need_reset = false;
 
 	ethtool_op_set_flags(netdev, data);
 
-	if (!(adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE))
-		return 0;
-
 	/* if state changes we need to update adapter->flags and reset */
 	if ((!!(data & ETH_FLAG_LRO)) != 
 	    (!!(adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED))) {
 		adapter->flags2 ^= IXGBE_FLAG2_RSC_ENABLED;
+		need_reset = true;
+	}
+
+	/*
+	 * Check if Flow Director n-tuple support was enabled or disabled.  If
+	 * the state changed, we need to reset.
+	 */
+	if ((adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) &&
+	    (!(data & ETH_FLAG_NTUPLE))) {
+		/* turn off Flow Director perfect, set hash and reset */
+		adapter->flags &= ~IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+		adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+		need_reset = true;
+	} else if ((!(adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE)) &&
+	           (data & ETH_FLAG_NTUPLE)) {
+		/* turn off Flow Director hash, enable perfect and reset */
+		adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE;
+		adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+		need_reset = true;
+	} else {
+		/* no state change */
+	}
+
+	if (need_reset) {
 		if (netif_running(netdev))
 			ixgbe_reinit_locked(adapter);
 		else
 			ixgbe_reset(adapter);
 	}
+
 	return 0;
+}
+
+static int ixgbe_set_rx_ntuple(struct net_device *dev,
+                               struct ethtool_rx_ntuple *cmd)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	struct ethtool_rx_ntuple_flow_spec fs = cmd->fs;
+	struct ixgbe_atr_input input_struct;
+	struct ixgbe_atr_input_masks input_masks;
+	int target_queue;
+
+	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+		return -EOPNOTSUPP;
+
+	/*
+	 * Don't allow programming if the action is a queue greater than
+	 * the number of online Tx queues.
+	 */
+	if ((fs.action >= adapter->num_tx_queues) ||
+	    (fs.action < ETHTOOL_RXNTUPLE_ACTION_DROP))
+		return -EINVAL;
+
+	memset(&input_struct, 0, sizeof(struct ixgbe_atr_input));
+	memset(&input_masks, 0, sizeof(struct ixgbe_atr_input_masks));
+
+	input_masks.src_ip_mask = fs.m_u.tcp_ip4_spec.ip4src;
+	input_masks.dst_ip_mask = fs.m_u.tcp_ip4_spec.ip4dst;
+	input_masks.src_port_mask = fs.m_u.tcp_ip4_spec.psrc;
+	input_masks.dst_port_mask = fs.m_u.tcp_ip4_spec.pdst;
+	input_masks.vlan_id_mask = fs.vlan_tag_mask;
+	/* only use the lowest 2 bytes for flex bytes */
+	input_masks.data_mask = (fs.data_mask & 0xffff);
+
+	switch (fs.flow_type) {
+	case TCP_V4_FLOW:
+		ixgbe_atr_set_l4type_82599(&input_struct, IXGBE_ATR_L4TYPE_TCP);
+		break;
+	case UDP_V4_FLOW:
+		ixgbe_atr_set_l4type_82599(&input_struct, IXGBE_ATR_L4TYPE_UDP);
+		break;
+	case SCTP_V4_FLOW:
+		ixgbe_atr_set_l4type_82599(&input_struct, IXGBE_ATR_L4TYPE_SCTP);
+		break;
+	default:
+		return -1;
+	}
 
+	/* Mask bits from the inputs based on user-supplied mask */
+	ixgbe_atr_set_src_ipv4_82599(&input_struct,
+	            (fs.h_u.tcp_ip4_spec.ip4src & ~fs.m_u.tcp_ip4_spec.ip4src));
+	ixgbe_atr_set_dst_ipv4_82599(&input_struct,
+	            (fs.h_u.tcp_ip4_spec.ip4dst & ~fs.m_u.tcp_ip4_spec.ip4dst));
+	/* 82599 expects these to be byte-swapped for perfect filtering */
+	ixgbe_atr_set_src_port_82599(&input_struct,
+	       ((ntohs(fs.h_u.tcp_ip4_spec.psrc)) & ~fs.m_u.tcp_ip4_spec.psrc));
+	ixgbe_atr_set_dst_port_82599(&input_struct,
+	       ((ntohs(fs.h_u.tcp_ip4_spec.pdst)) & ~fs.m_u.tcp_ip4_spec.pdst));
+
+	/* VLAN and Flex bytes are either completely masked or not */
+	if (!fs.vlan_tag_mask)
+		ixgbe_atr_set_vlan_id_82599(&input_struct, fs.vlan_tag);
+
+	if (!input_masks.data_mask)
+		/* make sure we only use the first 2 bytes of user data */
+		ixgbe_atr_set_flex_byte_82599(&input_struct,
+		                              (fs.data & 0xffff));
+
+	/* determine if we need to drop or route the packet */
+	if (fs.action == ETHTOOL_RXNTUPLE_ACTION_DROP)
+		target_queue = MAX_RX_QUEUES - 1;
+	else
+		target_queue = fs.action;
+
+	spin_lock(&adapter->fdir_perfect_lock);
+	ixgbe_fdir_add_perfect_filter_82599(&adapter->hw, &input_struct,
+	                                    &input_masks, 0, target_queue);
+	spin_unlock(&adapter->fdir_perfect_lock);
+
+	return 0;
 }
 
 static const struct ethtool_ops ixgbe_ethtool_ops = {
@@ -2204,6 +2308,7 @@ static const struct ethtool_ops ixgbe_ethtool_ops = {
 	.set_coalesce           = ixgbe_set_coalesce,
 	.get_flags              = ethtool_op_get_flags,
 	.set_flags              = ixgbe_set_flags,
+	.set_rx_ntuple          = ixgbe_set_rx_ntuple,
 };
 
 void ixgbe_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 2a3c831..ca57e74 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -4187,6 +4187,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
 	struct pci_dev *pdev = adapter->pdev;
+	struct net_device *dev = adapter->netdev;
 	unsigned int rss;
 #ifdef CONFIG_IXGBE_DCB
 	int j;
@@ -4214,10 +4215,18 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
 		adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599;
 		adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE;
 		adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED;
-		adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+		if (dev->features & NETIF_F_NTUPLE) {
+			/* Flow Director perfect filter enabled */
+			adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE;
+			adapter->atr_sample_rate = 0;
+			spin_lock_init(&adapter->fdir_perfect_lock);
+		} else {
+			/* Flow Director hash filters enabled */
+			adapter->flags |= IXGBE_FLAG_FDIR_HASH_CAPABLE;
+			adapter->atr_sample_rate = 20;
+		}
 		adapter->ring_feature[RING_F_FDIR].indices =
 		                                         IXGBE_MAX_FDIR_INDICES;
-		adapter->atr_sample_rate = 20;
 		adapter->fdir_pballoc = 0;
 #ifdef IXGBE_FCOE
 		adapter->flags |= IXGBE_FLAG_FCOE_CAPABLE;
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index 0db67c1..2be9074 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -2129,6 +2129,15 @@ struct ixgbe_atr_input {
 	u8 byte_stream[42];
 };
 
+struct ixgbe_atr_input_masks {
+	u32 src_ip_mask;
+	u32 dst_ip_mask;
+	u16 src_port_mask;
+	u16 dst_port_mask;
+	u16 vlan_id_mask;
+	u16 data_mask;
+};
+
 enum ixgbe_eeprom_type {
 	ixgbe_eeprom_uninitialized = 0,
 	ixgbe_eeprom_spi,


^ permalink raw reply related

* [net-next-2.6 PATCH 3/3] ixgbe: Bump driver version up
From: Jeff Kirsher @ 2010-02-05  6:22 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Peter P Waskiewicz Jr, Jeff Kirsher
In-Reply-To: <20100205062131.20910.10580.stgit@localhost.localdomain>

From: Peter Waskiewicz <peter.p.waskiewicz.jr@intel.com>

Driver has gone under significant changes, the version should
reflect that.

Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/ixgbe/ixgbe_main.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index ca57e74..c308b59 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -51,7 +51,7 @@ char ixgbe_driver_name[] = "ixgbe";
 static const char ixgbe_driver_string[] =
                               "Intel(R) 10 Gigabit PCI Express Network Driver";
 
-#define DRV_VERSION "2.0.44-k2"
+#define DRV_VERSION "2.0.62-k2"
 const char ixgbe_driver_version[] = DRV_VERSION;
 static char ixgbe_copyright[] = "Copyright (c) 1999-2010 Intel Corporation.";
 


^ permalink raw reply related

* Re: linux-next: build failure after merge of the net tree
From: David Miller @ 2010-02-05  6:32 UTC (permalink / raw)
  To: sfr; +Cc: netdev, linux-next, linux-kernel, nicholasx.d.nunley
In-Reply-To: <20100205165059.0b5d5363.sfr@canb.auug.org.au>

From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Fri, 5 Feb 2010 16:50:59 +1100

> Hi Dave,
> 
> After merging the scsi-post-merge tree, today's linux-next build (powerpc
> allyesconfig and i386 defconfig) failed like this:
> 
> drivers/net/e1000e/built-in.o: In function `e1000_has_link':
> (.opd+0x1d58): multiple definition of `e1000_has_link'
> drivers/net/e1000/built-in.o:(.opd+0x588): first defined here
> 
> Caused by commit b548192acaebcb05d6a87d1e94f19835b1a18a8b ("e1000: Report
> link status in ethtool when interface is down").
> 
> I have reverted that commit for today.

Damn namespace pollution, this is one of a zillion reasons
I prefer drivers are written in one sorce file, then people
can name their functions however they like and they're all
marked static so it doesn't cause problems like this.

I've fixed it up as follows in net-next-2.6

Thanks!

e1000e: Fix namespace conflicts wrt. e1000_has_link

Reported by Stephen Rothwell.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 drivers/net/e1000e/e1000.h   |    2 +-
 drivers/net/e1000e/ethtool.c |    2 +-
 drivers/net/e1000e/netdev.c  |    4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index 318bdb2..c2ec095 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -459,7 +459,7 @@ extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter);
 extern void e1000e_free_rx_resources(struct e1000_adapter *adapter);
 extern void e1000e_free_tx_resources(struct e1000_adapter *adapter);
 extern void e1000e_update_stats(struct e1000_adapter *adapter);
-extern bool e1000_has_link(struct e1000_adapter *adapter);
+extern bool e1000e_has_link(struct e1000_adapter *adapter);
 extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter);
 extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter);
 
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 0aa50c2..b33e3cb 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -202,7 +202,7 @@ static u32 e1000_get_link(struct net_device *netdev)
 	if (!netif_carrier_ok(netdev))
 		mac->get_link_status = 1;
 
-	return e1000_has_link(adapter);
+	return e1000e_has_link(adapter);
 }
 
 static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 14a80f8..ffa37c6 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -3472,7 +3472,7 @@ static void e1000_print_link_info(struct e1000_adapter *adapter)
 	       ((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" )));
 }
 
-bool e1000_has_link(struct e1000_adapter *adapter)
+bool e1000e_has_link(struct e1000_adapter *adapter)
 {
 	struct e1000_hw *hw = &adapter->hw;
 	bool link_active = 0;
@@ -3553,7 +3553,7 @@ static void e1000_watchdog_task(struct work_struct *work)
 	u32 link, tctl;
 	int tx_pending = 0;
 
-	link = e1000_has_link(adapter);
+	link = e1000e_has_link(adapter);
 	if ((netif_carrier_ok(netdev)) && link) {
 		e1000e_enable_receives(adapter);
 		goto link_up;
-- 
1.6.6.1

^ permalink raw reply related


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