Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] tcp: split tcp_ecn sysctl knob to distinguish between IPv4 and IPv6
From: Stephen Hemminger @ 2012-12-31 22:05 UTC (permalink / raw)
  To: Hannes Frederic Sowa; +Cc: netdev
In-Reply-To: <20121231173532.GA11700@order.stressinduktion.org>

On Mon, 31 Dec 2012 18:35:33 +0100
Hannes Frederic Sowa <hannes@stressinduktion.org> wrote:

> ECN could be more reliable when used with IPv6 (I don't have proofs). For
> people who want to try ECN with IPv6 but still have problems connecting
> to destinations because of broken IPv4 routers this switch allows one
> to enable ECN just for IPv6.
> 
> Perhaps ECN could be enabled by default in future.
> 
> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>

Any new or modified sysctl should be documented in:
  Documentation/networking/ip-sysctl.txt

^ permalink raw reply

* Re: [PATCH v2 net-next] team: add ethtool support
From: Ben Hutchings @ 2012-12-31 22:16 UTC (permalink / raw)
  To: Flavio Leitner; +Cc: netdev, Jiri Pirko
In-Reply-To: <1356835053-25602-1-git-send-email-fbl@redhat.com>

On Sun, 2012-12-30 at 00:37 -0200, Flavio Leitner wrote:
> This patch adds few ethtool operations to team driver.
> 
> Signed-off-by: Flavio Leitner <fbl@redhat.com>
> ---
> v2 - removed generic statistics from ethtool
> 
>  drivers/net/team/team.c | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 
> diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
> index ad86660..7665a088 100644
> --- a/drivers/net/team/team.c
> +++ b/drivers/net/team/team.c
[...]
> +static void team_ethtool_get_drvinfo(struct net_device *dev,
> +				     struct ethtool_drvinfo *drvinfo)
> +{
> +	strncpy(drvinfo->driver, DRV_NAME, 32);
> +	strncpy(drvinfo->version, UTS_RELEASE, 32);
> +}
[...]

These must be null-terminated, so use strlcpy() not strncpy().

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: [PATCH RFC 15/15] via-rhine: add helper (reduce type-unsafe void * assignments).
From: David Miller @ 2012-12-31 22:21 UTC (permalink / raw)
  To: andi; +Cc: andim2, rl, netdev, romieu
In-Reply-To: <1356967549-5056-16-git-send-email-andi@lisas.de>

From: Andreas Mohr <andi@lisas.de>
Date: Mon, 31 Dec 2012 16:25:49 +0100

> From: Andreas Mohr <andim2@users.sf.net>
> 
> Signed-off-by: Andreas Mohr <andim2@users.sf.net>

This is of zero value.

It is just as likely one would forget to use the helper as it would be
to assign pci_get_drvdata() to a pointer of the wrong type.

^ permalink raw reply

* Re: [PATCH] net: fix checking boundary of valid vlan id
From: Glen Turner @ 2012-12-31 22:30 UTC (permalink / raw)
  To: Benny Amorsen; +Cc: Florian Westphal, akong, netdev, davem
In-Reply-To: <m3fw2mp2lh.fsf@ursa.amorsen.dk>


On 01/01/2013, at 3:42 AM, Benny Amorsen wrote:

> Glen Turner <gdt@gdt.id.au> writes:
> 
>> It may be a valid VLAN ID, or it may not. The meaning of FFF is
>> reserved for vendor use, which doesn't preclude a vendor using it as a
>> (non-interoperable) VLAN identifier. Many vendor's products treat 4096
>> as they do any other VID.
> 
> I may be missing something vital, but 4096 is 0x1000 not 0xFFF? 4095 is
> reserved and 0 means "treat as if the packet was untagged". 4096 is
> impossible, there are only 12 bit and the encoding is AFAIK bog standard
> binary.

Yep, I've failed at hex math. 0xfff = 4095 is the maximal VID value, and is the one reserved for vendor use.
Which means that the patch checking values 1 to 4095 is correct.

My apologies,
glen

^ permalink raw reply

* Re: [PATCH net-next 0/8] Add complementary BPF conditional jump instructions
From: David Miller @ 2012-12-31 22:37 UTC (permalink / raw)
  To: dborkman; +Cc: netdev
In-Reply-To: <cover.1356960070.git.dborkman@redhat.com>

From: Daniel Borkmann <dborkman@redhat.com>
Date: Mon, 31 Dec 2012 14:59:40 +0100

> This set adds adds jump operations for lt (<), le (<=), ne (!=) that
> compare A with K resp. X in order to facilitate filter programming
> with conditional jumps, as also available in McCanne et. al's BPF+
> paper (``BPF+: Exploiting Global Data-flow Optimization in a Generalized
> Packet Filter Architecture'').
> 
> Also, follow-up BPF JIT implementations for x86, Sparc and PowerPC
> are added in this set.

Whilst I agree that adding NE jumps adds great value and closes a
serious gap, the rest can be synthesized by simply swapping the
arguments and using a comparison that does already exist.

Why isn't that sufficient?

^ permalink raw reply

* Re: [PATCH] poll: prevent missed events if _qproc is NULL
From: Eric Wong @ 2012-12-31 23:24 UTC (permalink / raw)
  To: linux-kernel
  Cc: Hans Verkuil, Jiri Olsa, Jonathan Corbet, Al Viro, Davide Libenzi,
	Hans de Goede, Mauro Carvalho Chehab, David Miller, Eric Dumazet,
	Andrew Morton, Linus Torvalds, Andreas Voellmy,
	Junchang(Jason) Wang, netdev, linux-fsdevel
In-Reply-To: <1356960060-1263-1-git-send-email-normalperson@yhbt.net>

Eric Wong <normalperson@yhbt.net> wrote:
> This patch seems to fix my issue with ppoll() being stuck on my
> SMP machine: http://article.gmane.org/gmane.linux.file-systems/70414

OK, it doesn't fix my issue, but it seems to make it harder-to-hit...

> The change to sock_poll_wait() in
> commit 626cf236608505d376e4799adb4f7eb00a8594af
>   (poll: add poll_requested_events() and poll_does_not_wait() functions)
> seems to have allowed additional cases where the SMP memory barrier
> is not issued before checking for readiness.
> 
> In my case, this affects the select()-family of functions
> which register descriptors once and set _qproc to NULL before
> checking events again (after poll_schedule_timeout() returns).
> The set_mb() barrier in poll_schedule_timeout() appears to be
> insufficient on my SMP x86-64 machine (as it's only an xchg()).
> 
> This may also be related to the epoll issue described by
> Andreas Voellmy in http://thread.gmane.org/gmane.linux.kernel/1408782/

However, I believe my patch will still fix Andreas' issue with epoll
due to how ep_modify() uses a NULL qproc when calling ->poll().

(I've never been able to reproduce Andreas' issue on my 4-core system,
 but he's been hitting it since 3.4 (at least))

^ permalink raw reply

* Re: [PATCH] tcp: split tcp_ecn sysctl knob to distinguish between IPv4 and IPv6
From: Hannes Frederic Sowa @ 2012-12-31 23:48 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20121231140412.7dee9821@nehalam.linuxnetplumber.net>

On Mon, Dec 31, 2012 at 02:04:12PM -0800, Stephen Hemminger wrote:
> On Mon, 31 Dec 2012 18:35:33 +0100
> Hannes Frederic Sowa <hannes@stressinduktion.org> wrote:
> 
> > diff --git a/include/net/sock.h b/include/net/sock.h
> > index 182ca99..aa3c30e 100644
> > --- a/include/net/sock.h
> > +++ b/include/net/sock.h
> > @@ -944,6 +944,7 @@ struct proto {
> >  	int			*sysctl_rmem;
> >  	int			max_header;
> >  	bool			no_autobind;
> > +	int			ecn;
> >  
> Why isn't this a bool?

It is a tristate: disable ecn(0), request ecn(1) and accept ecn(2).

^ permalink raw reply

* Re: [PATCH] tcp: split tcp_ecn sysctl knob to distinguish between IPv4 and IPv6
From: Hannes Frederic Sowa @ 2012-12-31 23:58 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: netdev
In-Reply-To: <20121231140538.6e55c82d@nehalam.linuxnetplumber.net>

On Mon, Dec 31, 2012 at 02:05:38PM -0800, Stephen Hemminger wrote:
> On Mon, 31 Dec 2012 18:35:33 +0100
> Hannes Frederic Sowa <hannes@stressinduktion.org> wrote:
> 
> > ECN could be more reliable when used with IPv6 (I don't have proofs). For
> > people who want to try ECN with IPv6 but still have problems connecting
> > to destinations because of broken IPv4 routers this switch allows one
> > to enable ECN just for IPv6.
> > 
> > Perhaps ECN could be enabled by default in future.
> > 
> > Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
> 
> Any new or modified sysctl should be documented in:
>   Documentation/networking/ip-sysctl.txt

Ack. I'll wait a bit for further feedback and will submit a -v2 with updated
documentation.

^ permalink raw reply

* Re: [patch net-next 01/15] net: introduce upper device lists
From: Jiri Pirko @ 2013-01-01  1:04 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: netdev, davem, edumazet, bhutchings, faisal.latif, fbl, roland,
	sean.hefty, hal.rosenstock, fubar, andy, divy, jitendra.kalsaria,
	sony.chacko, linux-driver, kaber, ursula.braun, blaschka,
	schwidefsky, heiko.carstens, ebiederm, joe, amwang, nhorman,
	john.r.fastabend, pablo
In-Reply-To: <20121231112212.03319226@nehalam.linuxnetplumber.net>

Mon, Dec 31, 2012 at 08:22:12PM CET, shemminger@vyatta.com wrote:
>On Sun, 30 Dec 2012 12:58:08 +0100
>Jiri Pirko <jiri@resnulli.us> wrote:
>
>> This lists are supposed to serve for storing pointers to all upper devices.
>> Eventually it will replace dev->master pointer which is used for
>> bonding, bridge, team but it cannot be used for vlan, macvlan where
>> there might be multiple upper present. In case the upper link is
>> replacement for dev->master, it is marked with "master" flag.
>> 
>> New upper device list resolves this limitation. Also, the information
>> stored in lists is used for preventing looping setups like
>> "bond->somethingelse->samebond"
>> 
>> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
>
>I like the concept of knowing the topology of layered network devices.
>The name "upper device lists" is a little confusing to me.

Well, it's a list of devices "upper" to this one. Please provide more
suitable name alternative. I can't think of any, in fact I think "upper"
is pretty suitable.


>Also, the amount of additional data structures and book keeping
>seems more than needed; but not sure how to reduce it down to the
>least code.

Yep, that's it. I tried to make that as slim as possible. Trimming ideas
are very welcome.

>
>For simple case of detecting loops, just using existing master
>pointer is sufficient.
>       ethernet --> bonding --> bridge --+
>                       ^                 |
>                       |                 |
>                       +-----------------+
>This is the simple case of detecting if singularly linked list
>is a loop.
>
>The only device where multiple upper devices is possible seems
>to be macvlan. Could the special case code be limited to there?

Well, there are others, vlan for example. And the whole concept is to
make this uniform and generic, to avoid specific code for specific
drivers. And there are some usecases which can benefit from the upper
lists, like for example drivers which need to obtain l3 address info
(cxgb3, qlcnic, qeth).

But in any case, I doubt that this alternative approach will
lead to much smaller code footprint. I think it would be just more
messy.

^ permalink raw reply

* Re: [PATCH net-next 5/8] net: bpf: add neq jump operations to bpf machine
From: Eric Dumazet @ 2013-01-01  3:25 UTC (permalink / raw)
  To: Daniel Borkmann; +Cc: davem, netdev
In-Reply-To: <ce1ddcbf8c0effcfa561b224630e3645504a6ad4.1356960070.git.dborkman@redhat.com>

On Mon, 2012-12-31 at 14:59 +0100, Daniel Borkmann wrote:
> This patch adds jump operations for neq (!=) that compare A
> with K resp. X in order to facilitate filter programming with
> conditional jumps, since currently only eq (==) is present in
> the BPF machine. For user-space filter programming / compilers,
> it might be good to also have this complementary operation.
> They don't need to be as ancillary, since they fit into the
> instruction encoding directly. Follow-up BPF JIT patches are
> welcomed.
> 
> Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
> ---
>  include/linux/filter.h      |  2 ++
>  include/uapi/linux/filter.h |  1 +
>  net/core/filter.c           | 14 ++++++++++++++
>  3 files changed, 17 insertions(+)
> 
> diff --git a/include/linux/filter.h b/include/linux/filter.h
> index 36630bc..256c01f 100644
> --- a/include/linux/filter.h
> +++ b/include/linux/filter.h
> @@ -105,6 +105,8 @@ enum {
>  	BPF_S_JMP_JA,
>  	BPF_S_JMP_JEQ_K,
>  	BPF_S_JMP_JEQ_X,
> +	BPF_S_JMP_JNEQ_K,
> +	BPF_S_JMP_JNEQ_X,
>  	BPF_S_JMP_JGE_K,
>  	BPF_S_JMP_JGE_X,
>  	BPF_S_JMP_JGT_K,
> diff --git a/include/uapi/linux/filter.h b/include/uapi/linux/filter.h
> index 3ebcc2e..d909a6f 100644
> --- a/include/uapi/linux/filter.h
> +++ b/include/uapi/linux/filter.h
> @@ -80,6 +80,7 @@ struct sock_fprog {	/* Required for SO_ATTACH_FILTER. */
>  #define         BPF_JSET        0x40
>  #define         BPF_JLT         0x50
>  #define         BPF_JLE         0x60
> +#define         BPF_JNEQ        0x70
>  
>  #define BPF_SRC(code)   ((code) & 0x08)
>  #define         BPF_K           0x00
> diff --git a/net/core/filter.c b/net/core/filter.c
> index 2122eba..b360fb3 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -228,6 +228,9 @@ unsigned int sk_run_filter(const struct sk_buff *skb,
>  		case BPF_S_JMP_JEQ_K:
>  			fentry += (A == K) ? fentry->jt : fentry->jf;
>  			continue;
> +		case BPF_S_JMP_JNEQ_K:
> +			fentry += (A != K) ? fentry->jt : fentry->jf;
> +			continue;
>  		case BPF_S_JMP_JSET_K:
>  			fentry += (A & K) ? fentry->jt : fentry->jf;
>  			continue;

This makes no sense at all to me, it seems kernel bloat.

The JNE instruction already exists.

You only have to take the JEQ (jt,jf) and swap the jt/jf targets.

^ permalink raw reply

* Re: [PATCH net-next 0/8] Add complementary BPF conditional jump instructions
From: Eric Dumazet @ 2013-01-01  3:29 UTC (permalink / raw)
  To: David Miller; +Cc: dborkman, netdev
In-Reply-To: <20121231.143715.1238174487756359071.davem@davemloft.net>

On Mon, 2012-12-31 at 14:37 -0800, David Miller wrote:

> Whilst I agree that adding NE jumps adds great value and closes a
> serious gap, the rest can be synthesized by simply swapping the
> arguments and using a comparison that does already exist.
> 
> Why isn't that sufficient?

I am afraid none of these patches is needed at all.

Swapping the jt/jf is plainly enough for the user land compiler.

libcap seems to do it already

# tcpdump -i lo 'len!=0 && ip6' -d
(000) ld       #pktlen
(001) jeq      #0x0             jt 5	jf 2
(002) ldh      [12]
(003) jeq      #0x86dd          jt 4	jf 5
(004) ret      #96
(005) ret      #0
# tcpdump -i lo 'len==0 && ip6' -d
(000) ld       #pktlen
(001) jeq      #0x0             jt 2	jf 5
(002) ldh      [12]
(003) jeq      #0x86dd          jt 4	jf 5
(004) ret      #96
(005) ret      #0

^ permalink raw reply

* Re: [PATCH net-next 0/8] Add complementary BPF conditional jump instructions
From: David Miller @ 2013-01-01  5:18 UTC (permalink / raw)
  To: eric.dumazet; +Cc: dborkman, netdev
In-Reply-To: <1357010942.21409.8948.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 31 Dec 2012 19:29:02 -0800

> On Mon, 2012-12-31 at 14:37 -0800, David Miller wrote:
> 
>> Whilst I agree that adding NE jumps adds great value and closes a
>> serious gap, the rest can be synthesized by simply swapping the
>> arguments and using a comparison that does already exist.
>> 
>> Why isn't that sufficient?
> 
> I am afraid none of these patches is needed at all.
> 
> Swapping the jt/jf is plainly enough for the user land compiler.
> 
> libcap seems to do it already

Agreed.

^ permalink raw reply

* [PATCH net-next 1/3] netpoll: prepare for ipv6
From: Cong Wang @ 2013-01-01  8:01 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Cong Wang

From: Cong Wang <amwang@redhat.com>

This patch adjusts some struct and functions, to prepare
for supporting IPv6.

Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 drivers/net/netconsole.c |   12 +-
 include/linux/netpoll.h  |   13 ++-
 net/core/netpoll.c       |  398 +++++++++++++++++++++++++---------------------
 3 files changed, 239 insertions(+), 184 deletions(-)

diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 6989ebe..998fa02 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -269,12 +269,14 @@ static ssize_t show_remote_port(struct netconsole_target *nt, char *buf)
 
 static ssize_t show_local_ip(struct netconsole_target *nt, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.local_ip);
+	if (!nt->np.ipv6)
+		return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.local_ip);
 }
 
 static ssize_t show_remote_ip(struct netconsole_target *nt, char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.remote_ip);
+	if (!nt->np.ipv6)
+		return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.remote_ip);
 }
 
 static ssize_t show_local_mac(struct netconsole_target *nt, char *buf)
@@ -410,7 +412,8 @@ static ssize_t store_local_ip(struct netconsole_target *nt,
 		return -EINVAL;
 	}
 
-	nt->np.local_ip = in_aton(buf);
+	if (!strnchr(buf, count, ':'))
+		nt->np.local_ip.ip = in_aton(buf);
 
 	return strnlen(buf, count);
 }
@@ -426,7 +429,8 @@ static ssize_t store_remote_ip(struct netconsole_target *nt,
 		return -EINVAL;
 	}
 
-	nt->np.remote_ip = in_aton(buf);
+	if (!strnchr(buf, count, ':'))
+		nt->np.remote_ip.ip = in_aton(buf);
 
 	return strnlen(buf, count);
 }
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index 66d5379..24da730 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -12,13 +12,22 @@
 #include <linux/rcupdate.h>
 #include <linux/list.h>
 
+union inet_addr {
+	__u32		all[4];
+	__be32		ip;
+	__be32		ip6[4];
+	struct in_addr	in;
+	struct in6_addr	in6;
+};
+
 struct netpoll {
 	struct net_device *dev;
 	char dev_name[IFNAMSIZ];
 	const char *name;
 	void (*rx_hook)(struct netpoll *, int, char *, int);
 
-	__be32 local_ip, remote_ip;
+	int ipv6;
+	union inet_addr local_ip, remote_ip;
 	u16 local_port, remote_port;
 	u8 remote_mac[ETH_ALEN];
 
@@ -33,7 +42,7 @@ struct netpoll_info {
 	spinlock_t rx_lock;
 	struct list_head rx_np; /* netpolls that registered an rx_hook */
 
-	struct sk_buff_head arp_tx; /* list of arp requests to reply to */
+	struct sk_buff_head neigh_tx; /* list of neigh requests to reply to */
 	struct sk_buff_head txq;
 
 	struct delayed_work tx_work;
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 3151acf..46e8d1c 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -55,7 +55,7 @@ static atomic_t trapped;
 	 MAX_UDP_CHUNK)
 
 static void zap_completion_queue(void);
-static void netpoll_arp_reply(struct sk_buff *skb, struct netpoll_info *npinfo);
+static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo);
 
 static unsigned int carrier_timeout = 4;
 module_param(carrier_timeout, uint, 0644);
@@ -181,13 +181,13 @@ static void poll_napi(struct net_device *dev)
 	}
 }
 
-static void service_arp_queue(struct netpoll_info *npi)
+static void service_neigh_queue(struct netpoll_info *npi)
 {
 	if (npi) {
 		struct sk_buff *skb;
 
-		while ((skb = skb_dequeue(&npi->arp_tx)))
-			netpoll_arp_reply(skb, npi);
+		while ((skb = skb_dequeue(&npi->neigh_tx)))
+			netpoll_neigh_reply(skb, npi);
 	}
 }
 
@@ -213,14 +213,14 @@ static void netpoll_poll_dev(struct net_device *dev)
 			struct net_device *bond_dev = dev->master;
 			struct sk_buff *skb;
 			struct netpoll_info *bond_ni = rcu_dereference_bh(bond_dev->npinfo);
-			while ((skb = skb_dequeue(&ni->arp_tx))) {
+			while ((skb = skb_dequeue(&ni->neigh_tx))) {
 				skb->dev = bond_dev;
-				skb_queue_tail(&bond_ni->arp_tx, skb);
+				skb_queue_tail(&bond_ni->neigh_tx, skb);
 			}
 		}
 	}
 
-	service_arp_queue(ni);
+	service_neigh_queue(ni);
 
 	zap_completion_queue();
 }
@@ -383,7 +383,9 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 	static atomic_t ip_ident;
 
 	udp_len = len + sizeof(*udph);
-	ip_len = udp_len + sizeof(*iph);
+	if (!np->ipv6)
+		ip_len = udp_len + sizeof(*iph);
+
 	total_len = ip_len + LL_RESERVED_SPACE(np->dev);
 
 	skb = find_skb(np, total_len + np->dev->needed_tailroom,
@@ -400,34 +402,38 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 	udph->source = htons(np->local_port);
 	udph->dest = htons(np->remote_port);
 	udph->len = htons(udp_len);
-	udph->check = 0;
-	udph->check = csum_tcpudp_magic(np->local_ip,
-					np->remote_ip,
-					udp_len, IPPROTO_UDP,
-					csum_partial(udph, udp_len, 0));
-	if (udph->check == 0)
-		udph->check = CSUM_MANGLED_0;
-
-	skb_push(skb, sizeof(*iph));
-	skb_reset_network_header(skb);
-	iph = ip_hdr(skb);
-
-	/* iph->version = 4; iph->ihl = 5; */
-	put_unaligned(0x45, (unsigned char *)iph);
-	iph->tos      = 0;
-	put_unaligned(htons(ip_len), &(iph->tot_len));
-	iph->id       = htons(atomic_inc_return(&ip_ident));
-	iph->frag_off = 0;
-	iph->ttl      = 64;
-	iph->protocol = IPPROTO_UDP;
-	iph->check    = 0;
-	put_unaligned(np->local_ip, &(iph->saddr));
-	put_unaligned(np->remote_ip, &(iph->daddr));
-	iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);
-
-	eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
-	skb_reset_mac_header(skb);
-	skb->protocol = eth->h_proto = htons(ETH_P_IP);
+
+	if (!np->ipv6) {
+		udph->check = 0;
+		udph->check = csum_tcpudp_magic(np->local_ip.ip,
+						np->remote_ip.ip,
+						udp_len, IPPROTO_UDP,
+						csum_partial(udph, udp_len, 0));
+		if (udph->check == 0)
+			udph->check = CSUM_MANGLED_0;
+
+		skb_push(skb, sizeof(*iph));
+		skb_reset_network_header(skb);
+		iph = ip_hdr(skb);
+
+		/* iph->version = 4; iph->ihl = 5; */
+		put_unaligned(0x45, (unsigned char *)iph);
+		iph->tos      = 0;
+		put_unaligned(htons(ip_len), &(iph->tot_len));
+		iph->id       = htons(atomic_inc_return(&ip_ident));
+		iph->frag_off = 0;
+		iph->ttl      = 64;
+		iph->protocol = IPPROTO_UDP;
+		iph->check    = 0;
+		put_unaligned(np->local_ip.ip, &(iph->saddr));
+		put_unaligned(np->remote_ip.ip, &(iph->daddr));
+		iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);
+
+		eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
+		skb_reset_mac_header(skb);
+		skb->protocol = eth->h_proto = htons(ETH_P_IP);
+	}
+
 	memcpy(eth->h_source, np->dev->dev_addr, ETH_ALEN);
 	memcpy(eth->h_dest, np->remote_mac, ETH_ALEN);
 
@@ -437,7 +443,7 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 }
 EXPORT_SYMBOL(netpoll_send_udp);
 
-static void netpoll_arp_reply(struct sk_buff *skb, struct netpoll_info *npinfo)
+static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo)
 {
 	struct arphdr *arp;
 	unsigned char *arp_ptr;
@@ -448,7 +454,7 @@ static void netpoll_arp_reply(struct sk_buff *skb, struct netpoll_info *npinfo)
 	struct netpoll *np, *tmp;
 	unsigned long flags;
 	int hlen, tlen;
-	int hits = 0;
+	int hits = 0, proto;
 
 	if (list_empty(&npinfo->rx_np))
 		return;
@@ -466,94 +472,97 @@ static void netpoll_arp_reply(struct sk_buff *skb, struct netpoll_info *npinfo)
 	if (!hits)
 		return;
 
-	/* No arp on this interface */
-	if (skb->dev->flags & IFF_NOARP)
-		return;
-
-	if (!pskb_may_pull(skb, arp_hdr_len(skb->dev)))
-		return;
+	proto = ntohs(eth_hdr(skb)->h_proto);
+	if (proto == ETH_P_IP) {
+		/* No arp on this interface */
+		if (skb->dev->flags & IFF_NOARP)
+			return;
 
-	skb_reset_network_header(skb);
-	skb_reset_transport_header(skb);
-	arp = arp_hdr(skb);
+		if (!pskb_may_pull(skb, arp_hdr_len(skb->dev)))
+			return;
 
-	if ((arp->ar_hrd != htons(ARPHRD_ETHER) &&
-	     arp->ar_hrd != htons(ARPHRD_IEEE802)) ||
-	    arp->ar_pro != htons(ETH_P_IP) ||
-	    arp->ar_op != htons(ARPOP_REQUEST))
-		return;
+		skb_reset_network_header(skb);
+		skb_reset_transport_header(skb);
+		arp = arp_hdr(skb);
 
-	arp_ptr = (unsigned char *)(arp+1);
-	/* save the location of the src hw addr */
-	sha = arp_ptr;
-	arp_ptr += skb->dev->addr_len;
-	memcpy(&sip, arp_ptr, 4);
-	arp_ptr += 4;
-	/* If we actually cared about dst hw addr,
-	   it would get copied here */
-	arp_ptr += skb->dev->addr_len;
-	memcpy(&tip, arp_ptr, 4);
-
-	/* Should we ignore arp? */
-	if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip))
-		return;
+		if ((arp->ar_hrd != htons(ARPHRD_ETHER) &&
+		     arp->ar_hrd != htons(ARPHRD_IEEE802)) ||
+		    arp->ar_pro != htons(ETH_P_IP) ||
+		    arp->ar_op != htons(ARPOP_REQUEST))
+			return;
 
-	size = arp_hdr_len(skb->dev);
+		arp_ptr = (unsigned char *)(arp+1);
+		/* save the location of the src hw addr */
+		sha = arp_ptr;
+		arp_ptr += skb->dev->addr_len;
+		memcpy(&sip, arp_ptr, 4);
+		arp_ptr += 4;
+		/* If we actually cared about dst hw addr,
+		   it would get copied here */
+		arp_ptr += skb->dev->addr_len;
+		memcpy(&tip, arp_ptr, 4);
 
-	spin_lock_irqsave(&npinfo->rx_lock, flags);
-	list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) {
-		if (tip != np->local_ip)
-			continue;
+		/* Should we ignore arp? */
+		if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip))
+			return;
 
-		hlen = LL_RESERVED_SPACE(np->dev);
-		tlen = np->dev->needed_tailroom;
-		send_skb = find_skb(np, size + hlen + tlen, hlen);
-		if (!send_skb)
-			continue;
+		size = arp_hdr_len(skb->dev);
 
-		skb_reset_network_header(send_skb);
-		arp = (struct arphdr *) skb_put(send_skb, size);
-		send_skb->dev = skb->dev;
-		send_skb->protocol = htons(ETH_P_ARP);
+		spin_lock_irqsave(&npinfo->rx_lock, flags);
+		list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) {
+			if (tip != np->local_ip.ip)
+				continue;
+
+			hlen = LL_RESERVED_SPACE(np->dev);
+			tlen = np->dev->needed_tailroom;
+			send_skb = find_skb(np, size + hlen + tlen, hlen);
+			if (!send_skb)
+				continue;
+
+			skb_reset_network_header(send_skb);
+			arp = (struct arphdr *) skb_put(send_skb, size);
+			send_skb->dev = skb->dev;
+			send_skb->protocol = htons(ETH_P_ARP);
+
+			/* Fill the device header for the ARP frame */
+			if (dev_hard_header(send_skb, skb->dev, ptype,
+					    sha, np->dev->dev_addr,
+					    send_skb->len) < 0) {
+				kfree_skb(send_skb);
+				continue;
+			}
 
-		/* Fill the device header for the ARP frame */
-		if (dev_hard_header(send_skb, skb->dev, ptype,
-				    sha, np->dev->dev_addr,
-				    send_skb->len) < 0) {
-			kfree_skb(send_skb);
-			continue;
+			/*
+			 * Fill out the arp protocol part.
+			 *
+			 * we only support ethernet device type,
+			 * which (according to RFC 1390) should
+			 * always equal 1 (Ethernet).
+			 */
+
+			arp->ar_hrd = htons(np->dev->type);
+			arp->ar_pro = htons(ETH_P_IP);
+			arp->ar_hln = np->dev->addr_len;
+			arp->ar_pln = 4;
+			arp->ar_op = htons(type);
+
+			arp_ptr = (unsigned char *)(arp + 1);
+			memcpy(arp_ptr, np->dev->dev_addr, np->dev->addr_len);
+			arp_ptr += np->dev->addr_len;
+			memcpy(arp_ptr, &tip, 4);
+			arp_ptr += 4;
+			memcpy(arp_ptr, sha, np->dev->addr_len);
+			arp_ptr += np->dev->addr_len;
+			memcpy(arp_ptr, &sip, 4);
+
+			netpoll_send_skb(np, send_skb);
+
+			/* If there are several rx_hooks for the same address,
+			   we're fine by sending a single reply */
+			break;
 		}
-
-		/*
-		 * Fill out the arp protocol part.
-		 *
-		 * we only support ethernet device type,
-		 * which (according to RFC 1390) should
-		 * always equal 1 (Ethernet).
-		 */
-
-		arp->ar_hrd = htons(np->dev->type);
-		arp->ar_pro = htons(ETH_P_IP);
-		arp->ar_hln = np->dev->addr_len;
-		arp->ar_pln = 4;
-		arp->ar_op = htons(type);
-
-		arp_ptr = (unsigned char *)(arp + 1);
-		memcpy(arp_ptr, np->dev->dev_addr, np->dev->addr_len);
-		arp_ptr += np->dev->addr_len;
-		memcpy(arp_ptr, &tip, 4);
-		arp_ptr += 4;
-		memcpy(arp_ptr, sha, np->dev->addr_len);
-		arp_ptr += np->dev->addr_len;
-		memcpy(arp_ptr, &sip, 4);
-
-		netpoll_send_skb(np, send_skb);
-
-		/* If there are several rx_hooks for the same address,
-		   we're fine by sending a single reply */
-		break;
+		spin_unlock_irqrestore(&npinfo->rx_lock, flags);
 	}
-	spin_unlock_irqrestore(&npinfo->rx_lock, flags);
 }
 
 int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
@@ -573,7 +582,7 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
 	/* check if netpoll clients need ARP */
 	if (skb->protocol == htons(ETH_P_ARP) &&
 	    atomic_read(&trapped)) {
-		skb_queue_tail(&npinfo->arp_tx, skb);
+		skb_queue_tail(&npinfo->neigh_tx, skb);
 		return 1;
 	}
 
@@ -584,60 +593,61 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
 	}
 
 	proto = ntohs(eth_hdr(skb)->h_proto);
-	if (proto != ETH_P_IP)
+	if (proto != ETH_P_IP && proto != ETH_P_IPV6)
 		goto out;
 	if (skb->pkt_type == PACKET_OTHERHOST)
 		goto out;
 	if (skb_shared(skb))
 		goto out;
 
-	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
-		goto out;
-	iph = (struct iphdr *)skb->data;
-	if (iph->ihl < 5 || iph->version != 4)
-		goto out;
-	if (!pskb_may_pull(skb, iph->ihl*4))
-		goto out;
-	iph = (struct iphdr *)skb->data;
-	if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
-		goto out;
-
-	len = ntohs(iph->tot_len);
-	if (skb->len < len || len < iph->ihl*4)
-		goto out;
-
-	/*
-	 * Our transport medium may have padded the buffer out.
-	 * Now We trim to the true length of the frame.
-	 */
-	if (pskb_trim_rcsum(skb, len))
-		goto out;
+	if (proto == ETH_P_IP) {
+		if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+			goto out;
+		iph = (struct iphdr *)skb->data;
+		if (iph->ihl < 5 || iph->version != 4)
+			goto out;
+		if (!pskb_may_pull(skb, iph->ihl*4))
+			goto out;
+		iph = (struct iphdr *)skb->data;
+		if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
+			goto out;
 
-	iph = (struct iphdr *)skb->data;
-	if (iph->protocol != IPPROTO_UDP)
-		goto out;
+		len = ntohs(iph->tot_len);
+		if (skb->len < len || len < iph->ihl*4)
+			goto out;
 
-	len -= iph->ihl*4;
-	uh = (struct udphdr *)(((char *)iph) + iph->ihl*4);
-	ulen = ntohs(uh->len);
+		/*
+		 * Our transport medium may have padded the buffer out.
+		 * Now We trim to the true length of the frame.
+		 */
+		if (pskb_trim_rcsum(skb, len))
+			goto out;
 
-	if (ulen != len)
-		goto out;
-	if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr))
-		goto out;
+		iph = (struct iphdr *)skb->data;
+		if (iph->protocol != IPPROTO_UDP)
+			goto out;
 
-	list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) {
-		if (np->local_ip && np->local_ip != iph->daddr)
-			continue;
-		if (np->remote_ip && np->remote_ip != iph->saddr)
-			continue;
-		if (np->local_port && np->local_port != ntohs(uh->dest))
-			continue;
+		len -= iph->ihl*4;
+		uh = (struct udphdr *)(((char *)iph) + iph->ihl*4);
+		ulen = ntohs(uh->len);
 
-		np->rx_hook(np, ntohs(uh->source),
-			       (char *)(uh+1),
-			       ulen - sizeof(struct udphdr));
-		hits++;
+		if (ulen != len)
+			goto out;
+		if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr))
+			goto out;
+		list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) {
+			if (np->local_ip.ip && np->local_ip.ip != iph->daddr)
+				continue;
+			if (np->remote_ip.ip && np->remote_ip.ip != iph->saddr)
+				continue;
+			if (np->local_port && np->local_port != ntohs(uh->dest))
+				continue;
+
+			np->rx_hook(np, ntohs(uh->source),
+				       (char *)(uh+1),
+				       ulen - sizeof(struct udphdr));
+			hits++;
+		}
 	}
 
 	if (!hits)
@@ -658,17 +668,36 @@ out:
 void netpoll_print_options(struct netpoll *np)
 {
 	np_info(np, "local port %d\n", np->local_port);
-	np_info(np, "local IP %pI4\n", &np->local_ip);
+	if (!np->ipv6)
+		np_info(np, "local IPv4 address %pI4\n", &np->local_ip.ip);
 	np_info(np, "interface '%s'\n", np->dev_name);
 	np_info(np, "remote port %d\n", np->remote_port);
-	np_info(np, "remote IP %pI4\n", &np->remote_ip);
+	if (!np->ipv6)
+		np_info(np, "remote IPv4 address %pI4\n", &np->remote_ip.ip);
 	np_info(np, "remote ethernet address %pM\n", np->remote_mac);
 }
 EXPORT_SYMBOL(netpoll_print_options);
 
+static int netpoll_parse_ip_addr(const char *str, union inet_addr *addr)
+{
+	const char *end;
+
+	if (!strchr(str, ':') &&
+	    in4_pton(str, -1, (void *)addr, -1, &end) > 0) {
+		if (!*end)
+			return 0;
+	}
+	if (in6_pton(str, -1, addr->in6.s6_addr, -1, &end) > 0) {
+		if (!*end)
+			return 1;
+	}
+	return -1;
+}
+
 int netpoll_parse_options(struct netpoll *np, char *opt)
 {
 	char *cur=opt, *delim;
+	int ipv6;
 
 	if (*cur != '@') {
 		if ((delim = strchr(cur, '@')) == NULL)
@@ -684,7 +713,11 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
 		if ((delim = strchr(cur, '/')) == NULL)
 			goto parse_failed;
 		*delim = 0;
-		np->local_ip = in_aton(cur);
+		ipv6 = netpoll_parse_ip_addr(cur, &np->local_ip);
+		if (ipv6 < 0)
+			goto parse_failed;
+		else
+			np->ipv6 = ipv6;
 		cur = delim;
 	}
 	cur++;
@@ -716,7 +749,13 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
 	if ((delim = strchr(cur, '/')) == NULL)
 		goto parse_failed;
 	*delim = 0;
-	np->remote_ip = in_aton(cur);
+	ipv6 = netpoll_parse_ip_addr(cur, &np->remote_ip);
+	if (ipv6 < 0)
+		goto parse_failed;
+	else if (np->ipv6 != ipv6)
+		goto parse_failed;
+	else
+		np->ipv6 = ipv6;
 	cur = delim + 1;
 
 	if (*cur != 0) {
@@ -764,7 +803,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp)
 		INIT_LIST_HEAD(&npinfo->rx_np);
 
 		spin_lock_init(&npinfo->rx_lock);
-		skb_queue_head_init(&npinfo->arp_tx);
+		skb_queue_head_init(&npinfo->neigh_tx);
 		skb_queue_head_init(&npinfo->txq);
 		INIT_DELAYED_WORK(&npinfo->tx_work, queue_process);
 
@@ -856,21 +895,24 @@ int netpoll_setup(struct netpoll *np)
 		}
 	}
 
-	if (!np->local_ip) {
-		rcu_read_lock();
-		in_dev = __in_dev_get_rcu(ndev);
+	if (!np->local_ip.ip) {
+		if (!np->ipv6) {
+			rcu_read_lock();
+			in_dev = __in_dev_get_rcu(ndev);
 
-		if (!in_dev || !in_dev->ifa_list) {
+
+			if (!in_dev || !in_dev->ifa_list) {
+				rcu_read_unlock();
+				np_err(np, "no IP address for %s, aborting\n",
+				       np->dev_name);
+				err = -EDESTADDRREQ;
+				goto put;
+			}
+
+			np->local_ip.ip = in_dev->ifa_list->ifa_local;
 			rcu_read_unlock();
-			np_err(np, "no IP address for %s, aborting\n",
-			       np->dev_name);
-			err = -EDESTADDRREQ;
-			goto put;
+			np_info(np, "local IP %pI4\n", &np->local_ip.ip);
 		}
-
-		np->local_ip = in_dev->ifa_list->ifa_local;
-		rcu_read_unlock();
-		np_info(np, "local IP %pI4\n", &np->local_ip);
 	}
 
 	/* fill up the skb queue */
@@ -903,7 +945,7 @@ static void rcu_cleanup_netpoll_info(struct rcu_head *rcu_head)
 	struct netpoll_info *npinfo =
 			container_of(rcu_head, struct netpoll_info, rcu);
 
-	skb_queue_purge(&npinfo->arp_tx);
+	skb_queue_purge(&npinfo->neigh_tx);
 	skb_queue_purge(&npinfo->txq);
 
 	/* we can't call cancel_delayed_work_sync here, as we are in softirq */
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH net-next 3/3] netconsole: add IPv6 example in doc
From: Cong Wang @ 2013-01-01  8:01 UTC (permalink / raw)
  To: netdev; +Cc: Cong Wang
In-Reply-To: <1357027288-28675-1-git-send-email-amwang@redhat.com>

From: Cong Wang <amwang@redhat.com>

Update the netconsole document as well.

Signed-off-by: Cong Wang <amwang@redhat.com>
---
 Documentation/networking/netconsole.txt |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/Documentation/networking/netconsole.txt b/Documentation/networking/netconsole.txt
index 2e9e0ae2..a5d574a 100644
--- a/Documentation/networking/netconsole.txt
+++ b/Documentation/networking/netconsole.txt
@@ -1,9 +1,10 @@
 
 started by Ingo Molnar <mingo@redhat.com>, 2001.09.17
 2.6 port and netpoll api by Matt Mackall <mpm@selenic.com>, Sep 9 2003
+IPv6 support by Cong Wang <xiyou.wangcong@gmail.com>, Jan 1 2013
 
 Please send bug reports to Matt Mackall <mpm@selenic.com>
-and Satyam Sharma <satyam.sharma@gmail.com>
+Satyam Sharma <satyam.sharma@gmail.com>, and Cong Wang <xiyou.wangcong@gmail.com>
 
 Introduction:
 =============
@@ -41,6 +42,10 @@ Examples:
 
  insmod netconsole netconsole=@/,@10.0.0.2/
 
+  or using IPv6
+
+ insmod netconsole netconsole=@/,@fd00:1:2:3::1/
+
 It also supports logging to multiple remote agents by specifying
 parameters for the multiple agents separated by semicolons and the
 complete string enclosed in "quotes", thusly:
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH net-next 2/3] netpoll: add IPv6 support
From: Cong Wang @ 2013-01-01  8:01 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Cong Wang
In-Reply-To: <1357027288-28675-1-git-send-email-amwang@redhat.com>

From: Cong Wang <amwang@redhat.com>

Currently, netpoll only support IPv4. This patch adds IPv6
support to netpoll, so that we can run netconsole over IPv6 network.

Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 drivers/net/netconsole.c |   44 +++++++-
 include/net/udp.h        |    2 +
 net/core/netpoll.c       |  246 ++++++++++++++++++++++++++++++++++++++++++++--
 net/ipv6/udp.c           |    3 +-
 4 files changed, 277 insertions(+), 18 deletions(-)

diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 998fa02..2fd281a 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -269,13 +269,17 @@ static ssize_t show_remote_port(struct netconsole_target *nt, char *buf)
 
 static ssize_t show_local_ip(struct netconsole_target *nt, char *buf)
 {
-	if (!nt->np.ipv6)
+	if (nt->np.ipv6)
+		return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.local_ip.in6);
+	else
 		return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.local_ip);
 }
 
 static ssize_t show_remote_ip(struct netconsole_target *nt, char *buf)
 {
-	if (!nt->np.ipv6)
+	if (nt->np.ipv6)
+		return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.remote_ip.in6);
+	else
 		return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.remote_ip);
 }
 
@@ -412,8 +416,22 @@ static ssize_t store_local_ip(struct netconsole_target *nt,
 		return -EINVAL;
 	}
 
-	if (!strnchr(buf, count, ':'))
-		nt->np.local_ip.ip = in_aton(buf);
+	if (strnchr(buf, count, ':')) {
+		const char *end;
+		if (in6_pton(buf, count, nt->np.local_ip.in6.s6_addr, -1, &end) > 0) {
+			if (*end && *end != '\n') {
+				printk(KERN_ERR "netconsole: invalid IPv6 address at: <%c>\n", *end);
+				return -EINVAL;
+			}
+			nt->np.ipv6 = 1;
+		} else
+			return -EINVAL;
+	} else {
+		if (!nt->np.ipv6)
+			nt->np.local_ip.ip = in_aton(buf);
+		else
+			return -EINVAL;
+	}
 
 	return strnlen(buf, count);
 }
@@ -429,8 +447,22 @@ static ssize_t store_remote_ip(struct netconsole_target *nt,
 		return -EINVAL;
 	}
 
-	if (!strnchr(buf, count, ':'))
-		nt->np.remote_ip.ip = in_aton(buf);
+	if (strnchr(buf, count, ':')) {
+		const char *end;
+		if (in6_pton(buf, count, nt->np.remote_ip.in6.s6_addr, -1, &end) > 0) {
+			if (*end && *end != '\n') {
+				printk(KERN_ERR "netconsole: invalid IPv6 address at: <%c>\n", *end);
+				return -EINVAL;
+			}
+			nt->np.ipv6 = 1;
+		} else
+			return -EINVAL;
+	} else {
+		if (!nt->np.ipv6)
+			nt->np.remote_ip.ip = in_aton(buf);
+		else
+			return -EINVAL;
+	}
 
 	return strnlen(buf, count);
 }
diff --git a/include/net/udp.h b/include/net/udp.h
index 065f379..c3ddb4a 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -156,6 +156,8 @@ static inline __wsum udp_csum(struct sk_buff *skb)
 	return csum;
 }
 
+extern int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto);
+
 /* hash routines shared between UDPv4/6 and UDP-Litev4/6 */
 static inline void udp_lib_hash(struct sock *sk)
 {
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 46e8d1c..a2cafa3 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -29,6 +29,8 @@
 #include <linux/if_vlan.h>
 #include <net/tcp.h>
 #include <net/udp.h>
+#include <net/addrconf.h>
+#include <net/ndisc.h>
 #include <asm/unaligned.h>
 #include <trace/events/napi.h>
 
@@ -381,9 +383,12 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 	struct iphdr *iph;
 	struct ethhdr *eth;
 	static atomic_t ip_ident;
+	struct ipv6hdr *ip6h;
 
 	udp_len = len + sizeof(*udph);
-	if (!np->ipv6)
+	if (np->ipv6)
+		ip_len = udp_len + sizeof(*ip6h);
+	else
 		ip_len = udp_len + sizeof(*iph);
 
 	total_len = ip_len + LL_RESERVED_SPACE(np->dev);
@@ -403,7 +408,35 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 	udph->dest = htons(np->remote_port);
 	udph->len = htons(udp_len);
 
-	if (!np->ipv6) {
+	if (np->ipv6) {
+		udph->check = 0;
+		udph->check = csum_ipv6_magic(&np->local_ip.in6,
+					      &np->remote_ip.in6,
+					      udp_len, IPPROTO_UDP,
+					      csum_partial(udph, udp_len, 0));
+		if (udph->check == 0)
+			udph->check = CSUM_MANGLED_0;
+
+		skb_push(skb, sizeof(*ip6h));
+		skb_reset_network_header(skb);
+		ip6h = ipv6_hdr(skb);
+
+		/* ip6h->version = 6; ip6h->priority = 0; */
+		put_unaligned(0x60, (unsigned char *)ip6h);
+		ip6h->flow_lbl[0] = 0;
+		ip6h->flow_lbl[1] = 0;
+		ip6h->flow_lbl[2] = 0;
+
+		ip6h->payload_len = htons(sizeof(struct udphdr) + len);
+		ip6h->nexthdr = IPPROTO_UDP;
+		ip6h->hop_limit = 32;
+		ip6h->saddr = np->local_ip.in6;
+		ip6h->daddr = np->remote_ip.in6;
+
+		eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
+		skb_reset_mac_header(skb);
+		skb->protocol = eth->h_proto = htons(ETH_P_IPV6);
+	} else {
 		udph->check = 0;
 		udph->check = csum_tcpudp_magic(np->local_ip.ip,
 						np->remote_ip.ip,
@@ -445,9 +478,7 @@ EXPORT_SYMBOL(netpoll_send_udp);
 
 static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo)
 {
-	struct arphdr *arp;
-	unsigned char *arp_ptr;
-	int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
+	int size, type = ARPOP_REPLY;
 	__be32 sip, tip;
 	unsigned char *sha;
 	struct sk_buff *send_skb;
@@ -474,6 +505,8 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo
 
 	proto = ntohs(eth_hdr(skb)->h_proto);
 	if (proto == ETH_P_IP) {
+		struct arphdr *arp;
+		unsigned char *arp_ptr;
 		/* No arp on this interface */
 		if (skb->dev->flags & IFF_NOARP)
 			return;
@@ -525,7 +558,7 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo
 			send_skb->protocol = htons(ETH_P_ARP);
 
 			/* Fill the device header for the ARP frame */
-			if (dev_hard_header(send_skb, skb->dev, ptype,
+			if (dev_hard_header(send_skb, skb->dev, ETH_P_ARP,
 					    sha, np->dev->dev_addr,
 					    send_skb->len) < 0) {
 				kfree_skb(send_skb);
@@ -562,14 +595,140 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo
 			break;
 		}
 		spin_unlock_irqrestore(&npinfo->rx_lock, flags);
+	} else if( proto == ETH_P_IPV6) {
+		struct nd_msg *msg;
+		struct ndisc_options ndopts;
+		u8 *lladdr = NULL;
+		struct ipv6hdr *hdr;
+		struct icmp6hdr *icmp6h;
+		const struct in6_addr *saddr;
+		const struct in6_addr *daddr;
+		struct inet6_dev *in6_dev = NULL;
+		u32 ndoptlen;
+		struct in6_addr *target;
+
+		in6_dev = in6_dev_get(skb->dev);
+		if (!in6_dev || !in6_dev->cnf.accept_ra)
+			return;
+
+		if (!pskb_may_pull(skb, skb->len))
+			return;
+
+		msg = (struct nd_msg *)skb_transport_header(skb);
+
+		__skb_push(skb, skb->data - skb_transport_header(skb));
+
+		if (ipv6_hdr(skb)->hop_limit != 255)
+			return;
+		if (msg->icmph.icmp6_code != 0)
+			return;
+		if (msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION)
+			return;
+
+		saddr = &ipv6_hdr(skb)->saddr;
+		daddr = &ipv6_hdr(skb)->daddr;
+
+		ndoptlen = skb->tail - (skb->transport_header + offsetof(struct nd_msg, opt));
+		if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts))
+			return;
+
+		if (ndopts.nd_opts_src_lladdr) {
+			lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr, skb->dev);
+			if (!lladdr)
+				return;
+		}
+
+		size = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
+
+		spin_lock_irqsave(&npinfo->rx_lock, flags);
+		list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) {
+			if (memcmp(daddr, &np->local_ip, sizeof(*daddr)))
+				continue;
+
+			hlen = LL_RESERVED_SPACE(np->dev);
+			tlen = np->dev->needed_tailroom;
+			send_skb = find_skb(np, size + hlen + tlen, hlen);
+			if (!send_skb)
+				continue;
+
+			send_skb->protocol = htons(ETH_P_IPV6);
+			send_skb->dev = skb->dev;
+
+			skb_reset_network_header(send_skb);
+			skb_put(send_skb, sizeof(struct ipv6hdr));
+			hdr = ipv6_hdr(send_skb);
+
+			*(__be32*)hdr = htonl(0x60000000);
+
+			hdr->payload_len = htons(size);
+			hdr->nexthdr = IPPROTO_ICMPV6;
+			hdr->hop_limit = 255;
+			hdr->saddr = *saddr;
+			hdr->daddr = *daddr;
+
+			send_skb->transport_header = send_skb->tail;
+			skb_put(send_skb, size);
+
+			icmp6h = (struct icmp6hdr *)skb_transport_header(skb);
+			icmp6h->icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
+			icmp6h->icmp6_router = 0;
+			icmp6h->icmp6_solicited = 1;
+			target = (struct in6_addr *)skb_transport_header(send_skb) + sizeof(struct icmp6hdr);
+			*target = msg->target;
+			icmp6h->icmp6_cksum = csum_ipv6_magic(saddr, daddr, size,
+							      IPPROTO_ICMPV6,
+							      csum_partial(icmp6h,
+									   size, 0));
+
+			if (dev_hard_header(send_skb, skb->dev, ETH_P_IPV6,
+					    lladdr, np->dev->dev_addr,
+					    send_skb->len) < 0) {
+				kfree_skb(send_skb);
+				continue;
+			}
+
+			netpoll_send_skb(np, send_skb);
+
+			/* If there are several rx_hooks for the same address,
+			   we're fine by sending a single reply */
+			break;
+		}
+		spin_unlock_irqrestore(&npinfo->rx_lock, flags);
 	}
 }
 
+static bool pkt_is_ns(struct sk_buff *skb)
+{
+	struct nd_msg *msg;
+	struct ipv6hdr *hdr;
+
+	if (skb->protocol != htons(ETH_P_ARP))
+		return false;
+	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + sizeof(struct nd_msg)))
+		return false;
+
+	msg = (struct nd_msg *)skb_transport_header(skb);
+	__skb_push(skb, skb->data - skb_transport_header(skb));
+	hdr = ipv6_hdr(skb);
+
+	if (hdr->nexthdr != IPPROTO_ICMPV6)
+		return false;
+	if (hdr->hop_limit != 255)
+		return false;
+	if (msg->icmph.icmp6_code != 0)
+		return false;
+	if (msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION)
+		return false;
+
+	return true;
+}
+
 int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
 {
 	int proto, len, ulen;
 	int hits = 0;
 	const struct iphdr *iph;
+	const struct ipv6hdr *ip6h;
 	struct udphdr *uh;
 	struct netpoll *np, *tmp;
 
@@ -580,8 +739,10 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
 		goto out;
 
 	/* check if netpoll clients need ARP */
-	if (skb->protocol == htons(ETH_P_ARP) &&
-	    atomic_read(&trapped)) {
+	if (skb->protocol == htons(ETH_P_ARP) && atomic_read(&trapped)) {
+		skb_queue_tail(&npinfo->neigh_tx, skb);
+		return 1;
+	} else if (pkt_is_ns(skb) && atomic_read(&trapped)) {
 		skb_queue_tail(&npinfo->neigh_tx, skb);
 		return 1;
 	}
@@ -648,6 +809,41 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
 				       ulen - sizeof(struct udphdr));
 			hits++;
 		}
+	} else {
+		if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+			goto out;
+		ip6h = (struct ipv6hdr *)skb->data;
+		if (ip6h->version != 6)
+			goto out;
+		len = ntohs(ip6h->payload_len);
+		if (!len)
+			goto out;
+		if (len + sizeof(struct ipv6hdr) > skb->len)
+			goto out;
+		if (pskb_trim_rcsum(skb, len + sizeof(struct ipv6hdr)))
+			goto out;
+		ip6h = ipv6_hdr(skb);
+		if (!pskb_may_pull(skb, sizeof(struct udphdr)))
+			goto out;
+		uh = udp_hdr(skb);
+		ulen = ntohs(uh->len);
+		if (ulen != skb->len)
+			goto out;
+		if (udp6_csum_init(skb, uh, IPPROTO_UDP))
+			goto out;
+		list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) {
+			if (memcmp(&np->local_ip.in6, &ip6h->daddr, sizeof(struct in6_addr)) != 0)
+				continue;
+			if (memcmp(&np->remote_ip.in6, &ip6h->saddr, sizeof(struct in6_addr)) != 0)
+				continue;
+			if (np->local_port && np->local_port != ntohs(uh->dest))
+				continue;
+
+			np->rx_hook(np, ntohs(uh->source),
+				       (char *)(uh+1),
+				       ulen - sizeof(struct udphdr));
+			hits++;
+		}
 	}
 
 	if (!hits)
@@ -668,11 +864,15 @@ out:
 void netpoll_print_options(struct netpoll *np)
 {
 	np_info(np, "local port %d\n", np->local_port);
-	if (!np->ipv6)
+	if (np->ipv6)
+		np_info(np, "local IPv6 address %pI6c\n", &np->local_ip.in6);
+	else
 		np_info(np, "local IPv4 address %pI4\n", &np->local_ip.ip);
 	np_info(np, "interface '%s'\n", np->dev_name);
 	np_info(np, "remote port %d\n", np->remote_port);
-	if (!np->ipv6)
+	if (np->ipv6)
+		np_info(np, "remote IPv6 address %pI6c\n", &np->remote_ip.in6);
+	else
 		np_info(np, "remote IPv4 address %pI4\n", &np->remote_ip.ip);
 	np_info(np, "remote ethernet address %pM\n", np->remote_mac);
 }
@@ -912,6 +1112,32 @@ int netpoll_setup(struct netpoll *np)
 			np->local_ip.ip = in_dev->ifa_list->ifa_local;
 			rcu_read_unlock();
 			np_info(np, "local IP %pI4\n", &np->local_ip.ip);
+		} else {
+			struct inet6_dev *idev;
+
+			err = -EDESTADDRREQ;
+			rcu_read_lock();
+			idev = __in6_dev_get(ndev);
+			if (idev) {
+				struct inet6_ifaddr *ifp;
+
+				read_lock_bh(&idev->lock);
+				list_for_each_entry(ifp, &idev->addr_list, if_list) {
+					if (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)
+						continue;
+					np->local_ip.in6 = ifp->addr;
+					err = 0;
+					break;
+				}
+				read_unlock_bh(&idev->lock);
+			}
+			rcu_read_unlock();
+			if (err) {
+				np_err(np, "no IPv6 address for %s, aborting\n",
+				       np->dev_name);
+				goto put;
+			} else
+				np_info(np, "local IPv6 %pI6c\n", &np->local_ip.in6);
 		}
 	}
 
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index dfaa29b..285754c 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -752,8 +752,7 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,
 	return 0;
 }
 
-static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh,
-				 int proto)
+int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto)
 {
 	int err;
 
-- 
1.7.7.6

^ permalink raw reply related

* Re: [PATCH] vxlan: allow live mac address change
From: Jiri Pirko @ 2013-01-01  8:19 UTC (permalink / raw)
  To: Stephen Hemminger; +Cc: David Miller, netdev
In-Reply-To: <20121231140021.5ec82f3a@nehalam.linuxnetplumber.net>

Mon, Dec 31, 2012 at 11:00:21PM CET, shemminger@vyatta.com wrote:
>The VXLAN pseudo-device doesn't care if the mac address changes
>when device is up.
>
>Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
>
>
>--- a/drivers/net/vxlan.c	2012-12-27 22:30:53.630796042 -0800
>+++ b/drivers/net/vxlan.c	2012-12-31 10:46:25.435321912 -0800
>@@ -1191,6 +1191,7 @@ static void vxlan_setup(struct net_devic
> 
> 	dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
> 	dev->priv_flags	&= ~IFF_XMIT_DST_RELEASE;
>+	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
> 
> 	spin_lock_init(&vxlan->hash_lock);
> 

Reviewed-by: Jiri Pirko <jiri@resnulli.us>


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

* [PATCH] ipv6: document ndisc_notify in networking/ip-sysctl.txt
From: Hannes Frederic Sowa @ 2013-01-01 10:35 UTC (permalink / raw)
  To: netdev

I slipped in a new sysctl without proper documentation. I would like to
make up for this now.

Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
---
 Documentation/networking/ip-sysctl.txt | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index 614320f..3f24319 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1344,6 +1344,12 @@ force_tllao - BOOLEAN
 	race condition where the sender deletes the cached link-layer address
 	prior to receiving a response to a previous solicitation."
 
+ndisc_notify - BOOLEAN
+	Define mode for notification of address and device changes.
+	0 - (default): do nothing
+	1 - Generate unsolicited neighbour advertisements when device is brought
+	    up or hardware address changes.
+
 icmp/*:
 ratelimit - INTEGER
 	Limit the maximal rates for sending ICMPv6 packets.

^ permalink raw reply related

* [patch net-next 0/7] fix dev->addr_assign_type setting and related code
From: Jiri Pirko @ 2013-01-01 13:30 UTC (permalink / raw)
  To: netdev; +Cc: davem, edumazet, bhutchings, shemminger, sassmann, kaber, richard

commit c1f79426e2df5ef96fe3e76de6c7606d15bf390b introduced addr_assign_type,
but incorrectly works with the value as if it was a bitfield. This patch corrects this.

Also, new "assign_type" is added to track that the address was changed by
dev_set_mac_address().

Jiri Pirko (7):
  rtnl: use dev_set_mac_address() instead of plain ndo_
  net: call add_device_randomness() only after successful mac change
  net: set dev->addr_assign_type correctly
  net: add address assign type "SET"
  net: remove unnecessary NET_ADDR_RANDOM "bitclean"
  um: net: use eth_hw_addr_random() to generate random mac
  ll_temac: fix mac address setting

 arch/um/drivers/net_kern.c                      | 22 +++++++-----------
 arch/um/include/shared/net_kern.h               |  1 -
 drivers/net/ethernet/adi/bfin_mac.c             |  1 -
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c |  3 +--
 drivers/net/ethernet/atheros/atlx/atl1.c        |  2 +-
 drivers/net/ethernet/atheros/atlx/atlx.c        |  1 -
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c |  1 -
 drivers/net/ethernet/calxeda/xgmac.c            |  1 -
 drivers/net/ethernet/cisco/enic/enic_main.c     |  1 -
 drivers/net/ethernet/ethoc.c                    |  3 +--
 drivers/net/ethernet/intel/igbvf/netdev.c       |  1 -
 drivers/net/ethernet/lantiq_etop.c              |  2 +-
 drivers/net/ethernet/marvell/pxa168_eth.c       |  1 -
 drivers/net/ethernet/micrel/ks8842.c            |  1 -
 drivers/net/ethernet/micrel/ks8851.c            |  1 -
 drivers/net/ethernet/micrel/ks8851_mll.c        |  1 -
 drivers/net/ethernet/microchip/enc28j60.c       |  1 -
 drivers/net/ethernet/nvidia/forcedeth.c         |  1 -
 drivers/net/ethernet/octeon/octeon_mgmt.c       |  6 ++---
 drivers/net/ethernet/smsc/smsc911x.c            |  1 -
 drivers/net/ethernet/ti/davinci_emac.c          |  1 -
 drivers/net/ethernet/tile/tilepro.c             |  1 -
 drivers/net/ethernet/wiznet/w5100.c             |  1 -
 drivers/net/ethernet/wiznet/w5300.c             |  1 -
 drivers/net/ethernet/xilinx/ll_temac_main.c     | 31 ++++++++++++++-----------
 drivers/net/macvlan.c                           |  1 -
 drivers/net/team/team.c                         |  2 --
 drivers/staging/octeon/ethernet.c               |  6 ++---
 include/linux/etherdevice.h                     |  2 +-
 include/linux/netdevice.h                       |  2 ++
 net/batman-adv/soft-interface.c                 |  1 -
 net/bridge/br_device.c                          |  1 -
 net/core/dev.c                                  |  8 ++++---
 net/core/rtnetlink.c                            | 20 ++--------------
 net/ethernet/eth.c                              |  2 --
 net/openvswitch/vport-internal_dev.c            |  1 -
 36 files changed, 43 insertions(+), 90 deletions(-)

-- 
1.8.0

^ permalink raw reply

* [patch net-next 1/7] rtnl: use dev_set_mac_address() instead of plain ndo_
From: Jiri Pirko @ 2013-01-01 13:30 UTC (permalink / raw)
  To: netdev; +Cc: davem, edumazet, bhutchings, shemminger, sassmann, kaber, richard
In-Reply-To: <1357047019-1037-1-git-send-email-jiri@resnulli.us>

Benefit from existence of dev_set_mac_address() and remove duplicate
code.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 net/core/rtnetlink.c | 20 ++------------------
 1 file changed, 2 insertions(+), 18 deletions(-)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 2ef7a56..78d05a9 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1310,7 +1310,6 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 		      struct nlattr **tb, char *ifname, int modified)
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
-	int send_addr_notify = 0;
 	int err;
 
 	if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD]) {
@@ -1363,16 +1362,6 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 		struct sockaddr *sa;
 		int len;
 
-		if (!ops->ndo_set_mac_address) {
-			err = -EOPNOTSUPP;
-			goto errout;
-		}
-
-		if (!netif_device_present(dev)) {
-			err = -ENODEV;
-			goto errout;
-		}
-
 		len = sizeof(sa_family_t) + dev->addr_len;
 		sa = kmalloc(len, GFP_KERNEL);
 		if (!sa) {
@@ -1382,13 +1371,11 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 		sa->sa_family = dev->type;
 		memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
 		       dev->addr_len);
-		err = ops->ndo_set_mac_address(dev, sa);
+		err = dev_set_mac_address(dev, sa);
 		kfree(sa);
 		if (err)
 			goto errout;
-		send_addr_notify = 1;
 		modified = 1;
-		add_device_randomness(dev->dev_addr, dev->addr_len);
 	}
 
 	if (tb[IFLA_MTU]) {
@@ -1425,7 +1412,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 
 	if (tb[IFLA_BROADCAST]) {
 		nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len);
-		send_addr_notify = 1;
+		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
 	}
 
 	if (ifm->ifi_flags || ifm->ifi_change) {
@@ -1546,9 +1533,6 @@ errout:
 		net_warn_ratelimited("A link change request failed with some changes committed already. Interface %s may have been left with an inconsistent configuration, please check.\n",
 				     dev->name);
 
-	if (send_addr_notify)
-		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
-
 	return err;
 }
 
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 2/7] net: call add_device_randomness() only after successful mac change
From: Jiri Pirko @ 2013-01-01 13:30 UTC (permalink / raw)
  To: netdev; +Cc: davem, edumazet, bhutchings, shemminger, sassmann, kaber, richard
In-Reply-To: <1357047019-1037-1-git-send-email-jiri@resnulli.us>

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 net/core/dev.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 21c5b97..c85e32b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5020,10 +5020,11 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
 	if (!netif_device_present(dev))
 		return -ENODEV;
 	err = ops->ndo_set_mac_address(dev, sa);
-	if (!err)
-		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+	if (err)
+		return err;
+	call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
 	add_device_randomness(dev->dev_addr, dev->addr_len);
-	return err;
+	return 0;
 }
 EXPORT_SYMBOL(dev_set_mac_address);
 
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 3/7] net: set dev->addr_assign_type correctly
From: Jiri Pirko @ 2013-01-01 13:30 UTC (permalink / raw)
  To: netdev; +Cc: davem, edumazet, bhutchings, shemminger, sassmann, kaber, richard
In-Reply-To: <1357047019-1037-1-git-send-email-jiri@resnulli.us>

Not a bitfield, but a plain value.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 2 +-
 drivers/net/ethernet/atheros/atlx/atl1.c        | 2 +-
 drivers/net/ethernet/ethoc.c                    | 2 +-
 drivers/net/ethernet/lantiq_etop.c              | 2 +-
 include/linux/etherdevice.h                     | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 56d3f69..17651c7 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -2540,7 +2540,7 @@ static int atl1c_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	}
 	if (atl1c_read_mac_addr(&adapter->hw)) {
 		/* got a random MAC address, set NET_ADDR_RANDOM to netdev */
-		netdev->addr_assign_type |= NET_ADDR_RANDOM;
+		netdev->addr_assign_type = NET_ADDR_RANDOM;
 	}
 	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
 	memcpy(netdev->perm_addr, adapter->hw.mac_addr, netdev->addr_len);
diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c
index 71b3d7d..5b0d993 100644
--- a/drivers/net/ethernet/atheros/atlx/atl1.c
+++ b/drivers/net/ethernet/atheros/atlx/atl1.c
@@ -3053,7 +3053,7 @@ static int atl1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	/* copy the MAC address out of the EEPROM */
 	if (atl1_read_mac_addr(&adapter->hw)) {
 		/* mark random mac */
-		netdev->addr_assign_type |= NET_ADDR_RANDOM;
+		netdev->addr_assign_type = NET_ADDR_RANDOM;
 	}
 	memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
 
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index 8db1c06..f380bb7 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -1068,7 +1068,7 @@ static int ethoc_probe(struct platform_device *pdev)
 	}
 
 	if (random_mac)
-		netdev->addr_assign_type |= NET_ADDR_RANDOM;
+		netdev->addr_assign_type = NET_ADDR_RANDOM;
 
 	/* register MII bus */
 	priv->mdio = mdiobus_alloc();
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index c124e67..cd3d2c0 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -655,7 +655,7 @@ ltq_etop_init(struct net_device *dev)
 
 	/* Set addr_assign_type here, ltq_etop_set_mac_address would reset it. */
 	if (random_mac)
-		dev->addr_assign_type |= NET_ADDR_RANDOM;
+		dev->addr_assign_type = NET_ADDR_RANDOM;
 
 	ltq_etop_set_multicast_list(dev);
 	err = ltq_etop_mdio_init(dev);
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 243eea1..1a43e1b 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -192,7 +192,7 @@ static inline void eth_zero_addr(u8 *addr)
  */
 static inline void eth_hw_addr_random(struct net_device *dev)
 {
-	dev->addr_assign_type |= NET_ADDR_RANDOM;
+	dev->addr_assign_type = NET_ADDR_RANDOM;
 	eth_random_addr(dev->dev_addr);
 }
 
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 4/7] net: add address assign type "SET"
From: Jiri Pirko @ 2013-01-01 13:30 UTC (permalink / raw)
  To: netdev; +Cc: davem, edumazet, bhutchings, shemminger, sassmann, kaber, richard
In-Reply-To: <1357047019-1037-1-git-send-email-jiri@resnulli.us>

This is the way to indicate that mac address of a device has been set by
dev_set_mac_address()

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 include/linux/netdevice.h | 2 ++
 net/core/dev.c            | 1 +
 2 files changed, 3 insertions(+)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 6835b58..c5031a4 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -64,6 +64,8 @@ struct wireless_dev;
 #define NET_ADDR_PERM		0	/* address is permanent (default) */
 #define NET_ADDR_RANDOM		1	/* address is generated randomly */
 #define NET_ADDR_STOLEN		2	/* address is stolen from other device */
+#define NET_ADDR_SET		3	/* address is set using
+					 * dev_set_mac_address() */
 
 /* Backlog congestion levels */
 #define NET_RX_SUCCESS		0	/* keep 'em coming, baby */
diff --git a/net/core/dev.c b/net/core/dev.c
index c85e32b..bddb2f2 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5022,6 +5022,7 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
 	err = ops->ndo_set_mac_address(dev, sa);
 	if (err)
 		return err;
+	dev->addr_assign_type = NET_ADDR_SET;
 	call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
 	add_device_randomness(dev->dev_addr, dev->addr_len);
 	return 0;
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 5/7] net: remove unnecessary NET_ADDR_RANDOM "bitclean"
From: Jiri Pirko @ 2013-01-01 13:30 UTC (permalink / raw)
  To: netdev; +Cc: davem, edumazet, bhutchings, shemminger, sassmann, kaber, richard
In-Reply-To: <1357047019-1037-1-git-send-email-jiri@resnulli.us>

NET_ADDR_SET is set in dev_set_mac_address() no need to alter
dev->addr_assign_type value in drivers.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 drivers/net/ethernet/adi/bfin_mac.c             | 1 -
 drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 1 -
 drivers/net/ethernet/atheros/atlx/atlx.c        | 1 -
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 1 -
 drivers/net/ethernet/calxeda/xgmac.c            | 1 -
 drivers/net/ethernet/cisco/enic/enic_main.c     | 1 -
 drivers/net/ethernet/ethoc.c                    | 1 -
 drivers/net/ethernet/intel/igbvf/netdev.c       | 1 -
 drivers/net/ethernet/marvell/pxa168_eth.c       | 1 -
 drivers/net/ethernet/micrel/ks8842.c            | 1 -
 drivers/net/ethernet/micrel/ks8851.c            | 1 -
 drivers/net/ethernet/micrel/ks8851_mll.c        | 1 -
 drivers/net/ethernet/microchip/enc28j60.c       | 1 -
 drivers/net/ethernet/nvidia/forcedeth.c         | 1 -
 drivers/net/ethernet/octeon/octeon_mgmt.c       | 6 ++----
 drivers/net/ethernet/smsc/smsc911x.c            | 1 -
 drivers/net/ethernet/ti/davinci_emac.c          | 1 -
 drivers/net/ethernet/tile/tilepro.c             | 1 -
 drivers/net/ethernet/wiznet/w5100.c             | 1 -
 drivers/net/ethernet/wiznet/w5300.c             | 1 -
 drivers/net/macvlan.c                           | 1 -
 drivers/net/team/team.c                         | 2 --
 drivers/staging/octeon/ethernet.c               | 6 ++----
 net/batman-adv/soft-interface.c                 | 1 -
 net/bridge/br_device.c                          | 1 -
 net/ethernet/eth.c                              | 2 --
 net/openvswitch/vport-internal_dev.c            | 1 -
 27 files changed, 4 insertions(+), 35 deletions(-)

diff --git a/drivers/net/ethernet/adi/bfin_mac.c b/drivers/net/ethernet/adi/bfin_mac.c
index c1fdb8b..8c3c9cf 100644
--- a/drivers/net/ethernet/adi/bfin_mac.c
+++ b/drivers/net/ethernet/adi/bfin_mac.c
@@ -647,7 +647,6 @@ static int bfin_mac_set_mac_address(struct net_device *dev, void *p)
 	if (netif_running(dev))
 		return -EBUSY;
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 	setup_mac_addr(dev->dev_addr);
 	return 0;
 }
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 17651c7..7af95ce 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -472,7 +472,6 @@ static int atl1c_set_mac_addr(struct net_device *netdev, void *p)
 
 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
 	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
-	netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
 
 	atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr);
 
diff --git a/drivers/net/ethernet/atheros/atlx/atlx.c b/drivers/net/ethernet/atheros/atlx/atlx.c
index 77ffbc4..f82eb16 100644
--- a/drivers/net/ethernet/atheros/atlx/atlx.c
+++ b/drivers/net/ethernet/atheros/atlx/atlx.c
@@ -84,7 +84,6 @@ static int atlx_set_mac(struct net_device *netdev, void *p)
 
 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
 	memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len);
-	netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
 
 	atlx_set_mac_addr(&adapter->hw);
 	return 0;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 01588b6..072669d 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -3542,7 +3542,6 @@ int bnx2x_change_mac_addr(struct net_device *dev, void *p)
 			return rc;
 	}
 
-	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 
 	if (netif_running(dev))
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index b407043..a345e24 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -1459,7 +1459,6 @@ static int xgmac_set_mac_address(struct net_device *dev, void *p)
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 
-	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 
 	xgmac_set_mac_addr(ioaddr, dev->dev_addr, 0);
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 64866ff..ebccebf 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -865,7 +865,6 @@ static int enic_set_mac_addr(struct net_device *netdev, char *addr)
 	}
 
 	memcpy(netdev->dev_addr, addr, netdev->addr_len);
-	netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index f380bb7..b93062d 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -784,7 +784,6 @@ static int ethoc_set_mac_address(struct net_device *dev, void *addr)
 	ethoc_write(priv, MAC_ADDR1, (mac[0] <<  8) | (mac[1] <<  0));
 
 	memcpy(dev->dev_addr, mac, ETH_ALEN);
-	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c
index 277f5df..53281ff 100644
--- a/drivers/net/ethernet/intel/igbvf/netdev.c
+++ b/drivers/net/ethernet/intel/igbvf/netdev.c
@@ -1738,7 +1738,6 @@ static int igbvf_set_mac(struct net_device *netdev, void *p)
 		return -EADDRNOTAVAIL;
 
 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-	netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c
index 10d678d..aa037ca 100644
--- a/drivers/net/ethernet/marvell/pxa168_eth.c
+++ b/drivers/net/ethernet/marvell/pxa168_eth.c
@@ -627,7 +627,6 @@ static int pxa168_eth_set_mac_address(struct net_device *dev, void *addr)
 	if (!is_valid_ether_addr(sa->sa_data))
 		return -EADDRNOTAVAIL;
 	memcpy(oldMac, dev->dev_addr, ETH_ALEN);
-	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 	memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
 	netif_addr_lock_bh(dev);
 	update_hash_table_mac_address(pep, oldMac, dev->dev_addr);
diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c
index b71eb39..fbcb9e7 100644
--- a/drivers/net/ethernet/micrel/ks8842.c
+++ b/drivers/net/ethernet/micrel/ks8842.c
@@ -1080,7 +1080,6 @@ static int ks8842_set_mac(struct net_device *netdev, void *p)
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 
-	netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
 	memcpy(netdev->dev_addr, mac, netdev->addr_len);
 
 	ks8842_write_mac_addr(adapter, mac);
diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c
index 286816a..d59bc0e 100644
--- a/drivers/net/ethernet/micrel/ks8851.c
+++ b/drivers/net/ethernet/micrel/ks8851.c
@@ -1052,7 +1052,6 @@ static int ks8851_set_mac_address(struct net_device *dev, void *addr)
 	if (!is_valid_ether_addr(sa->sa_data))
 		return -EADDRNOTAVAIL;
 
-	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 	memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
 	return ks8851_write_mac_addr(dev);
 }
diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c
index ef8f9f9..a343066 100644
--- a/drivers/net/ethernet/micrel/ks8851_mll.c
+++ b/drivers/net/ethernet/micrel/ks8851_mll.c
@@ -1237,7 +1237,6 @@ static int ks_set_mac_address(struct net_device *netdev, void *paddr)
 	struct sockaddr *addr = paddr;
 	u8 *da;
 
-	netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
 
 	da = (u8 *)netdev->dev_addr;
diff --git a/drivers/net/ethernet/microchip/enc28j60.c b/drivers/net/ethernet/microchip/enc28j60.c
index a99456c..5d98a9f 100644
--- a/drivers/net/ethernet/microchip/enc28j60.c
+++ b/drivers/net/ethernet/microchip/enc28j60.c
@@ -527,7 +527,6 @@ static int enc28j60_set_mac_address(struct net_device *dev, void *addr)
 	if (!is_valid_ether_addr(address->sa_data))
 		return -EADDRNOTAVAIL;
 
-	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 	memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
 	return enc28j60_set_hw_macaddr(dev);
 }
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 653487d..b53bf9d 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -3025,7 +3025,6 @@ static int nv_set_mac_address(struct net_device *dev, void *addr)
 
 	/* synchronized against open : rtnl_lock() held by caller */
 	memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN);
-	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 
 	if (netif_running(dev)) {
 		netif_tx_lock_bh(dev);
diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c
index b549919..b4a842c 100644
--- a/drivers/net/ethernet/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/octeon/octeon_mgmt.c
@@ -1534,12 +1534,10 @@ static int octeon_mgmt_probe(struct platform_device *pdev)
 
 	mac = of_get_mac_address(pdev->dev.of_node);
 
-	if (mac && is_valid_ether_addr(mac)) {
+	if (mac && is_valid_ether_addr(mac))
 		memcpy(netdev->dev_addr, mac, ETH_ALEN);
-		netdev->addr_assign_type &= ~NET_ADDR_RANDOM;
-	} else {
+	else
 		eth_hw_addr_random(netdev);
-	}
 
 	p->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
 
diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c
index e112877..04ff63c 100644
--- a/drivers/net/ethernet/smsc/smsc911x.c
+++ b/drivers/net/ethernet/smsc/smsc911x.c
@@ -1831,7 +1831,6 @@ static int smsc911x_set_mac_address(struct net_device *dev, void *p)
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 
-	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
 
 	spin_lock_irq(&pdata->mac_lock);
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 2a3e2c5..6841a22 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1264,7 +1264,6 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr)
 	/* Store mac addr in priv and rx channel and set it in EMAC hw */
 	memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len);
 	memcpy(ndev->dev_addr, sa->sa_data, ndev->addr_len);
-	ndev->addr_assign_type &= ~NET_ADDR_RANDOM;
 
 	/* MAC address is configured only after the interface is enabled. */
 	if (netif_running(ndev)) {
diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c
index 96070e9..3643549 100644
--- a/drivers/net/ethernet/tile/tilepro.c
+++ b/drivers/net/ethernet/tile/tilepro.c
@@ -2195,7 +2195,6 @@ static int tile_net_set_mac_address(struct net_device *dev, void *p)
 
 	/* ISSUE: Note that "dev_addr" is now a pointer. */
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 
 	return 0;
 }
diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c
index 3523838..545043c 100644
--- a/drivers/net/ethernet/wiznet/w5100.c
+++ b/drivers/net/ethernet/wiznet/w5100.c
@@ -570,7 +570,6 @@ static int w5100_set_macaddr(struct net_device *ndev, void *addr)
 	if (!is_valid_ether_addr(sock_addr->sa_data))
 		return -EADDRNOTAVAIL;
 	memcpy(ndev->dev_addr, sock_addr->sa_data, ETH_ALEN);
-	ndev->addr_assign_type &= ~NET_ADDR_RANDOM;
 	w5100_write_macaddr(priv);
 	return 0;
 }
diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c
index 9d1d986..7cbd0e6 100644
--- a/drivers/net/ethernet/wiznet/w5300.c
+++ b/drivers/net/ethernet/wiznet/w5300.c
@@ -490,7 +490,6 @@ static int w5300_set_macaddr(struct net_device *ndev, void *addr)
 	if (!is_valid_ether_addr(sock_addr->sa_data))
 		return -EADDRNOTAVAIL;
 	memcpy(ndev->dev_addr, sock_addr->sa_data, ETH_ALEN);
-	ndev->addr_assign_type &= ~NET_ADDR_RANDOM;
 	w5300_write_macaddr(priv);
 	return 0;
 }
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 68a43fe..80c6f92 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -375,7 +375,6 @@ static int macvlan_set_mac_address(struct net_device *dev, void *p)
 
 	if (!(dev->flags & IFF_UP)) {
 		/* Just copy in the new address */
-		dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 		memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
 	} else {
 		/* Rehash and update the device filters */
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 918a901..04638bd 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1502,7 +1502,6 @@ static int team_set_mac_address(struct net_device *dev, void *p)
 	if (dev->type == ARPHRD_ETHER && !is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
-	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 	rcu_read_lock();
 	list_for_each_entry_rcu(port, &team->port_list, list)
 		if (team->ops.port_change_dev_addr)
@@ -1772,7 +1771,6 @@ static void team_setup_by_port(struct net_device *dev,
 	dev->mtu = port_dev->mtu;
 	memcpy(dev->broadcast, port_dev->broadcast, port_dev->addr_len);
 	memcpy(dev->dev_addr, port_dev->dev_addr, port_dev->addr_len);
-	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 }
 
 static int team_dev_type_check_change(struct net_device *dev,
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index ef32dc1..9a2ec25 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -453,12 +453,10 @@ int cvm_oct_common_init(struct net_device *dev)
 	if (priv->of_node)
 		mac = of_get_mac_address(priv->of_node);
 
-	if (mac && is_valid_ether_addr(mac)) {
+	if (mac && is_valid_ether_addr(mac))
 		memcpy(dev->dev_addr, mac, ETH_ALEN);
-		dev->addr_assign_type &= ~NET_ADDR_RANDOM;
-	} else {
+	else
 		eth_hw_addr_random(dev);
-	}
 
 	/*
 	 * Force the interface to use the POW send if always_use_pow
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index 6b548fd..fa388b2 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -124,7 +124,6 @@ static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
 		batadv_tt_local_add(dev, addr->sa_data, BATADV_NULL_IFINDEX);
 	}
 
-	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 	return 0;
 }
 
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 7c78e26..38974f7 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -172,7 +172,6 @@ static int br_set_mac_address(struct net_device *dev, void *p)
 
 	spin_lock_bh(&br->lock);
 	if (!ether_addr_equal(dev->dev_addr, addr->sa_data)) {
-		dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 		memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
 		br_fdb_change_mac_address(br, addr->sa_data);
 		br_stp_change_bridge_id(br, addr->sa_data);
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 4efad53..bc39c8c 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -290,8 +290,6 @@ int eth_mac_addr(struct net_device *dev, void *p)
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
-	/* if device marked as NET_ADDR_RANDOM, reset it */
-	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 	return 0;
 }
 EXPORT_SYMBOL(eth_mac_addr);
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 5d460c3..44cd5c3 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -69,7 +69,6 @@ static int internal_dev_mac_addr(struct net_device *dev, void *p)
 
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
-	dev->addr_assign_type &= ~NET_ADDR_RANDOM;
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 	return 0;
 }
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 6/7] um: net: use eth_hw_addr_random() to generate random mac
From: Jiri Pirko @ 2013-01-01 13:30 UTC (permalink / raw)
  To: netdev; +Cc: davem, edumazet, bhutchings, shemminger, sassmann, kaber, richard
In-Reply-To: <1357047019-1037-1-git-send-email-jiri@resnulli.us>

Also remove unused "mac" from uml_net struct.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 arch/um/drivers/net_kern.c        | 22 ++++++++--------------
 arch/um/include/shared/net_kern.h |  1 -
 2 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index b1314eb..fd9090d 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -293,8 +293,9 @@ static void uml_net_user_timer_expire(unsigned long _conn)
 #endif
 }
 
-static int setup_etheraddr(char *str, unsigned char *addr, char *name)
+static void setup_etheraddr(struct net_device *dev, char *str)
 {
+	unsigned char *addr = dev->dev_addr;
 	char *end;
 	int i;
 
@@ -334,13 +335,12 @@ static int setup_etheraddr(char *str, unsigned char *addr, char *name)
 		       addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4],
 		       addr[5]);
 	}
-	return 0;
+	return;
 
 random:
 	printk(KERN_INFO
-	       "Choosing a random ethernet address for device %s\n", name);
-	eth_random_addr(addr);
-	return 1;
+	       "Choosing a random ethernet address for device %s\n", dev->name);
+	eth_hw_addr_random(dev);
 }
 
 static DEFINE_SPINLOCK(devices_lock);
@@ -392,7 +392,6 @@ static void eth_configure(int n, void *init, char *mac,
 	struct net_device *dev;
 	struct uml_net_private *lp;
 	int err, size;
-	int random_mac;
 
 	size = transport->private_size + sizeof(struct uml_net_private);
 
@@ -419,9 +418,9 @@ static void eth_configure(int n, void *init, char *mac,
 	 */
 	snprintf(dev->name, sizeof(dev->name), "eth%d", n);
 
-	random_mac = setup_etheraddr(mac, device->mac, dev->name);
+	setup_etheraddr(dev, mac);
 
-	printk(KERN_INFO "Netdevice %d (%pM) : ", n, device->mac);
+	printk(KERN_INFO "Netdevice %d (%pM) : ", n, dev->dev_addr);
 
 	lp = netdev_priv(dev);
 	/* This points to the transport private data. It's still clear, but we
@@ -468,17 +467,12 @@ static void eth_configure(int n, void *init, char *mac,
 	init_timer(&lp->tl);
 	spin_lock_init(&lp->lock);
 	lp->tl.function = uml_net_user_timer_expire;
-	memcpy(lp->mac, device->mac, sizeof(lp->mac));
+	memcpy(lp->mac, dev->dev_addr, sizeof(lp->mac));
 
 	if ((transport->user->init != NULL) &&
 	    ((*transport->user->init)(&lp->user, dev) != 0))
 		goto out_unregister;
 
-	/* don't use eth_mac_addr, it will not work here */
-	memcpy(dev->dev_addr, device->mac, ETH_ALEN);
-	if (random_mac)
-		dev->addr_assign_type |= NET_ADDR_RANDOM;
-
 	dev->mtu = transport->user->mtu;
 	dev->netdev_ops = &uml_netdev_ops;
 	dev->ethtool_ops = &uml_net_ethtool_ops;
diff --git a/arch/um/include/shared/net_kern.h b/arch/um/include/shared/net_kern.h
index 5c367f2..012ac87 100644
--- a/arch/um/include/shared/net_kern.h
+++ b/arch/um/include/shared/net_kern.h
@@ -18,7 +18,6 @@ struct uml_net {
 	struct net_device *dev;
 	struct platform_device pdev;
 	int index;
-	unsigned char mac[ETH_ALEN];
 };
 
 struct uml_net_private {
-- 
1.8.0

^ permalink raw reply related

* [patch net-next 7/7] ll_temac: fix mac address setting
From: Jiri Pirko @ 2013-01-01 13:30 UTC (permalink / raw)
  To: netdev; +Cc: davem, edumazet, bhutchings, shemminger, sassmann, kaber, richard
In-Reply-To: <1357047019-1037-1-git-send-email-jiri@resnulli.us>

Previously, when invalid address was passed to ndo_set_mac_address,
random mac was generated and set. Fix this by returning -EADDRNOTAVAIL
in this situation.

Also polish the code around a bit.

Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
 drivers/net/ethernet/xilinx/ll_temac_main.c | 31 ++++++++++++++++-------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
index aad909d..5022093 100644
--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
+++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
@@ -319,18 +319,10 @@ out:
  * net_device_ops
  */
 
-static int temac_set_mac_address(struct net_device *ndev, void *address)
+static void temac_do_set_mac_address(struct net_device *ndev)
 {
 	struct temac_local *lp = netdev_priv(ndev);
 
-	if (address)
-		memcpy(ndev->dev_addr, address, ETH_ALEN);
-
-	if (!is_valid_ether_addr(ndev->dev_addr))
-		eth_hw_addr_random(ndev);
-	else
-		ndev->addr_assign_type &= ~NET_ADDR_RANDOM;
-
 	/* set up unicast MAC address filter set its mac address */
 	mutex_lock(&lp->indirect_mutex);
 	temac_indirect_out32(lp, XTE_UAW0_OFFSET,
@@ -344,15 +336,26 @@ static int temac_set_mac_address(struct net_device *ndev, void *address)
 			     (ndev->dev_addr[4] & 0x000000ff) |
 			     (ndev->dev_addr[5] << 8));
 	mutex_unlock(&lp->indirect_mutex);
+}
 
+static int temac_init_mac_address(struct net_device *ndev, void *address)
+{
+	memcpy(ndev->dev_addr, address, ETH_ALEN);
+	if (!is_valid_ether_addr(ndev->dev_addr))
+		eth_hw_addr_random(ndev);
+	temac_do_set_mac_address(ndev);
 	return 0;
 }
 
-static int netdev_set_mac_address(struct net_device *ndev, void *p)
+static int temac_set_mac_address(struct net_device *ndev, void *p)
 {
 	struct sockaddr *addr = p;
 
-	return temac_set_mac_address(ndev, addr->sa_data);
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+	memcpy(ndev->dev_addr, addr->sa_data, ETH_ALEN);
+	temac_do_set_mac_address(ndev);
+	return 0;
 }
 
 static void temac_set_multicast_list(struct net_device *ndev)
@@ -579,7 +582,7 @@ static void temac_device_reset(struct net_device *ndev)
 	temac_setoptions(ndev,
 			 lp->options & ~(XTE_OPTION_TXEN | XTE_OPTION_RXEN));
 
-	temac_set_mac_address(ndev, NULL);
+	temac_do_set_mac_address(ndev);
 
 	/* Set address filter table */
 	temac_set_multicast_list(ndev);
@@ -938,7 +941,7 @@ static const struct net_device_ops temac_netdev_ops = {
 	.ndo_open = temac_open,
 	.ndo_stop = temac_stop,
 	.ndo_start_xmit = temac_start_xmit,
-	.ndo_set_mac_address = netdev_set_mac_address,
+	.ndo_set_mac_address = temac_set_mac_address,
 	.ndo_validate_addr = eth_validate_addr,
 	.ndo_do_ioctl = temac_ioctl,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1106,7 +1109,7 @@ static int temac_of_probe(struct platform_device *op)
 		rc = -ENODEV;
 		goto err_iounmap_2;
 	}
-	temac_set_mac_address(ndev, (void *)addr);
+	temac_init_mac_address(ndev, (void *)addr);
 
 	rc = temac_mdio_setup(lp, op->dev.of_node);
 	if (rc)
-- 
1.8.0

^ 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