* [PATCH V2 1/3] tuntap: switch to use rtnl_dereference()
From: Jason Wang @ 2013-01-12 2:59 UTC (permalink / raw)
To: davem, mst, netdev, linux-kernel; +Cc: edumazet, stefanha, Jason Wang
In-Reply-To: <1357959574-13113-1-git-send-email-jasowang@redhat.com>
Switch to use rtnl_dereference() instead of the open code, suggested by Eric.
Cc: Eric Dumazet <edumazet@google.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/net/tun.c | 27 ++++++++++-----------------
1 files changed, 10 insertions(+), 17 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 99b58d8..aa963c4 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -404,8 +404,8 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
struct tun_struct *tun;
struct net_device *dev;
- tun = rcu_dereference_protected(tfile->tun,
- lockdep_rtnl_is_held());
+ tun = rtnl_dereference(tfile->tun);
+
if (tun) {
u16 index = tfile->queue_index;
BUG_ON(index >= tun->numqueues);
@@ -414,8 +414,7 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
rcu_assign_pointer(tun->tfiles[index],
tun->tfiles[tun->numqueues - 1]);
rcu_assign_pointer(tfile->tun, NULL);
- ntfile = rcu_dereference_protected(tun->tfiles[index],
- lockdep_rtnl_is_held());
+ ntfile = rtnl_dereference(tun->tfiles[index]);
ntfile->queue_index = index;
--tun->numqueues;
@@ -458,8 +457,7 @@ static void tun_detach_all(struct net_device *dev)
int i, n = tun->numqueues;
for (i = 0; i < n; i++) {
- tfile = rcu_dereference_protected(tun->tfiles[i],
- lockdep_rtnl_is_held());
+ tfile = rtnl_dereference(tun->tfiles[i]);
BUG_ON(!tfile);
wake_up_all(&tfile->wq.wait);
rcu_assign_pointer(tfile->tun, NULL);
@@ -469,8 +467,7 @@ static void tun_detach_all(struct net_device *dev)
synchronize_net();
for (i = 0; i < n; i++) {
- tfile = rcu_dereference_protected(tun->tfiles[i],
- lockdep_rtnl_is_held());
+ tfile = rtnl_dereference(tun->tfiles[i]);
/* Drop read queue */
skb_queue_purge(&tfile->sk.sk_receive_queue);
sock_put(&tfile->sk);
@@ -489,7 +486,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file)
int err;
err = -EINVAL;
- if (rcu_dereference_protected(tfile->tun, lockdep_rtnl_is_held()))
+ if (rtnl_dereference(tfile->tun))
goto out;
if (tfile->detached && tun != tfile->detached)
goto out;
@@ -1740,8 +1737,7 @@ static void tun_detach_filter(struct tun_struct *tun, int n)
struct tun_file *tfile;
for (i = 0; i < n; i++) {
- tfile = rcu_dereference_protected(tun->tfiles[i],
- lockdep_rtnl_is_held());
+ tfile = rtnl_dereference(tun->tfiles[i]);
sk_detach_filter(tfile->socket.sk);
}
@@ -1754,8 +1750,7 @@ static int tun_attach_filter(struct tun_struct *tun)
struct tun_file *tfile;
for (i = 0; i < tun->numqueues; i++) {
- tfile = rcu_dereference_protected(tun->tfiles[i],
- lockdep_rtnl_is_held());
+ tfile = rtnl_dereference(tun->tfiles[i]);
ret = sk_attach_filter(&tun->fprog, tfile->socket.sk);
if (ret) {
tun_detach_filter(tun, i);
@@ -1773,8 +1768,7 @@ static void tun_set_sndbuf(struct tun_struct *tun)
int i;
for (i = 0; i < tun->numqueues; i++) {
- tfile = rcu_dereference_protected(tun->tfiles[i],
- lockdep_rtnl_is_held());
+ tfile = rtnl_dereference(tun->tfiles[i]);
tfile->socket.sk->sk_sndbuf = tun->sndbuf;
}
}
@@ -1794,8 +1788,7 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)
else
ret = tun_attach(tun, file);
} else if (ifr->ifr_flags & IFF_DETACH_QUEUE) {
- tun = rcu_dereference_protected(tfile->tun,
- lockdep_rtnl_is_held());
+ tun = rtnl_dereference(tfile->tun);
if (!tun || !(tun->flags & TUN_TAP_MQ))
ret = -EINVAL;
else
--
1.7.1
^ permalink raw reply related
* [PATCH V2 3/3] tuntap: fix leaking reference count
From: Jason Wang @ 2013-01-12 2:59 UTC (permalink / raw)
To: davem, mst, netdev, linux-kernel; +Cc: edumazet, stefanha, Jason Wang
In-Reply-To: <1357959574-13113-1-git-send-email-jasowang@redhat.com>
Reference count leaking of both module and sock were found:
- When a detached file were closed, its sock refcnt from device were not
released, solving this by add the sock_put().
- The module were hold or drop unconditionally in TUNSETPERSIST, which means we
if we set the persist flag for N times, we need unset it for another N
times. Solving this by only hold or drop an reference when there's a flag
change and also drop the reference count when the persist device is deleted.
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/net/tun.c | 12 +++++++++---
1 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index a36b56f..af372d0 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -428,8 +428,10 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
/* Drop read queue */
skb_queue_purge(&tfile->sk.sk_receive_queue);
tun_set_real_num_queues(tun);
- } else if (tfile->detached && clean)
+ } else if (tfile->detached && clean) {
tun = tun_enable_queue(tfile);
+ sock_put(&tfile->sk);
+ }
if (clean) {
if (tun && tun->numqueues == 0 && tun->numdisabled == 0 &&
@@ -478,6 +480,9 @@ static void tun_detach_all(struct net_device *dev)
sock_put(&tfile->sk);
}
BUG_ON(tun->numdisabled != 0);
+
+ if (tun->flags & TUN_PERSIST)
+ module_put(THIS_MODULE);
}
static int tun_attach(struct tun_struct *tun, struct file *file)
@@ -1874,10 +1879,11 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
/* Disable/Enable persist mode. Keep an extra reference to the
* module to prevent the module being unprobed.
*/
- if (arg) {
+ if (arg && !(tun->flags & TUN_PERSIST)) {
tun->flags |= TUN_PERSIST;
__module_get(THIS_MODULE);
- } else {
+ }
+ if (!arg && (tun->flags & TUN_PERSIST)) {
tun->flags &= ~TUN_PERSIST;
module_put(THIS_MODULE);
}
--
1.7.1
^ permalink raw reply related
* [PATCH V2 2/3] tuntap: forbid calling TUNSETIFF when detached
From: Jason Wang @ 2013-01-12 2:59 UTC (permalink / raw)
To: davem, mst, netdev, linux-kernel; +Cc: edumazet, stefanha, Jason Wang
In-Reply-To: <1357959574-13113-1-git-send-email-jasowang@redhat.com>
Michael points out that even after Stefan's fix the TUNSETIFF is still allowed
to create a new tap device. This because we only check tfile->tun but the
tfile->detached were introduced. Fix this by failing early in tun_set_iff() if
the file is detached. After this fix, there's no need to do the check again in
tun_set_iff(), so this patch removes it.
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
drivers/net/tun.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index aa963c4..a36b56f 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -488,8 +488,6 @@ static int tun_attach(struct tun_struct *tun, struct file *file)
err = -EINVAL;
if (rtnl_dereference(tfile->tun))
goto out;
- if (tfile->detached && tun != tfile->detached)
- goto out;
err = -EBUSY;
if (!(tun->flags & TUN_TAP_MQ) && tun->numqueues == 1)
@@ -1543,6 +1541,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
struct net_device *dev;
int err;
+ if (tfile->detached)
+ return -EINVAL;
+
dev = __dev_get_by_name(net, ifr->ifr_name);
if (dev) {
if (ifr->ifr_flags & IFF_TUN_EXCL)
--
1.7.1
^ permalink raw reply related
* Re: [PATCH V2 0/3] some fixes of tuntap
From: David Miller @ 2013-01-12 3:42 UTC (permalink / raw)
To: jasowang; +Cc: mst, netdev, linux-kernel, edumazet, stefanha
In-Reply-To: <1357959574-13113-1-git-send-email-jasowang@redhat.com>
From: Jason Wang <jasowang@redhat.com>
Date: Sat, 12 Jan 2013 10:59:31 +0800
> There series fixes two issues:
> - Don't allow calling TUNSETIFF when a file is detached which may cause kernel
> data structure corrupt.
> - Fix the reference count leaking of sock and module.
>
> Plus a suggestion from Eric to use rtnl_dereference() instead of the open code.
>
> Changes from v1:
> - don't use rcu to dereference tfile->detached as it was already protected by
> rtnl lock.
> - add a patch of switching to use rtnl_dereference().
All applied, thanks Jason.
^ permalink raw reply
* rds doing huge allocations
From: Dave Jones @ 2013-01-12 3:44 UTC (permalink / raw)
To: netdev; +Cc: Venkat Venkatsubra
WARNING: at mm/page_alloc.c:2372 __alloc_pages_nodemask+0x9bf/0xba0()
Hardware name: GA-MA78GM-S2H
Modules linked in: bnep fuse rfcomm hidp dlci 8021q garp bridge stp netrom caif_socket caif af_rxrpc af_key llc2 rose phonet binfmt_misc l2tp_ppp l2tp_core pppoe pppox ppp_generic slhc nfnetlink can_raw scsi_transport_iscsi can_bcm can appletalk ipt_ULOG ax25 decnet nfc irda atm rds crc_ccitt x25 ipx p8023 psnap p8022 llc lockd sunrpc ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 xt_conntrack nf_conntrack ip6table_filter ip6_tables btusb bluetooth snd_hda_codec_realtek snd_hda_intel usb_debug snd_hda_codec microcode rfkill snd_pcm serio_raw snd_page_alloc pcspkr snd_timer edac_core snd soundcore r8169 mii vhost_net tun macvtap macvlan kvm_amd kvm
Pid: 21055, comm: trinity-child1 Not tainted 3.8.0-rc3+ #51
Call Trace:
[<ffffffff81044d5f>] warn_slowpath_common+0x7f/0xc0
[<ffffffff81044dba>] warn_slowpath_null+0x1a/0x20
[<ffffffff8114138f>] __alloc_pages_nodemask+0x9bf/0xba0
[<ffffffff810b2858>] ? trace_hardirqs_off_caller+0x28/0xc0
[<ffffffff810b28fd>] ? trace_hardirqs_off+0xd/0x10
[<ffffffff81182e88>] alloc_pages_current+0xb8/0x180
[<ffffffff8113b7d1>] __get_free_pages+0x21/0x80
[<ffffffff8118fb0e>] kmalloc_order_trace+0x3e/0x1a0
[<ffffffff8104e2dc>] ? local_bh_enable_ip+0x7c/0xf0
[<ffffffff8119073d>] __kmalloc+0x30d/0x3b0
[<ffffffff810b8c6d>] ? trace_hardirqs_on+0xd/0x10
[<ffffffff8104e2dc>] ? local_bh_enable_ip+0x7c/0xf0
[<ffffffffa02ab703>] rds_message_alloc+0x23/0xb0 [rds]
[<ffffffffa02ae001>] rds_sendmsg+0x2b1/0x990 [rds]
[<ffffffff812cae15>] ? sock_has_perm+0x5/0x230
[<ffffffff81547d50>] sock_sendmsg+0xb0/0xe0
[<ffffffff810b2782>] ? get_lock_stats+0x22/0x70
[<ffffffff810b2bee>] ? put_lock_stats.isra.23+0xe/0x40
[<ffffffff8154b660>] sys_sendto+0x130/0x180
[<ffffffff810b8c6d>] ? trace_hardirqs_on+0xd/0x10
[<ffffffff8169f21b>] ? _raw_spin_unlock_irq+0x3b/0x60
[<ffffffff816a7227>] ? sysret_check+0x1b/0x56
[<ffffffff810b8bd5>] ? trace_hardirqs_on_caller+0x115/0x1a0
[<ffffffff81334cce>] ? trace_hardirqs_on_thunk+0x3a/0x3f
[<ffffffff816a7202>] system_call_fastpath+0x16/0x1b
---[ end trace 59e8c396ac893aa3 ]---
That's this..
2371 if (order >= MAX_ORDER) {
2372 WARN_ON_ONCE(!(gfp_mask & __GFP_NOWARN));
2373 return NULL;
2374 }
So 'order' had ended up being huge somehow, after trusting
whatever came in from userspace via sendmsg.
Dave
^ permalink raw reply
* Re: [RFC PATCH] net: phy: remove flags argument from phy_{attach,connect,connect_direct}
From: David Miller @ 2013-01-12 3:47 UTC (permalink / raw)
To: florian; +Cc: netdev, konszert, afleming
In-Reply-To: <1357903907-16049-1-git-send-email-florian@openwrt.org>
From: Florian Fainelli <florian@openwrt.org>
Date: Fri, 11 Jan 2013 12:31:47 +0100
> The flags argument of the phy_{attach,connect,connect_direct} functions
> is used to assign a struct phy_device dev_flags with the value passed.
> All callers but the tg3 driver pass the flag 0, which results in the
> underlying PHY drivers in drivers/net/phy/ not being able to actually
> use any of the flags they would check in dev_flags. This patch gets rid of
> the flags argument, and passes phydev->dev_flags to the internal PHY
> library call phy_attach_direct() such that drivers which actually modify
> a phy device dev_flags get the value preserved for use by the underly
> phy driver.
>
> Signed-off-by: Florian Fainelli <florian@openwrt.org>
This change is fine, except for this part:
> diff --git a/include/linux/version.h b/include/linux/version.h
> new file mode 100644
> index 0000000..0c8c321
> --- /dev/null
> +++ b/include/linux/version.h
> @@ -0,0 +1,2 @@
> +#define LINUX_VERSION_CODE 197120
> +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
^ permalink raw reply
* Re: IPv6 over firewire
From: Stefan Richter @ 2013-01-12 8:27 UTC (permalink / raw)
To: stephan.gatzka; +Cc: YOSHIFUJI Hideaki, linux1394-devel, netdev
In-Reply-To: <50F10C53.4000803@gmail.com>
On Jan 12 Stephan Gatzka wrote:
>
> > And, last but big issue is, well, packet inspection at
> > driver level. For example, you use ndisc_parse_options()
> > and code depends on CONFIG_IPV6=y.
>
> Good point. Of course I can make firewire-net dependent from IPv6.
>
> The other option is to build a separate firewire_ipv6 module.
> Implementing that looks easy enough. From the original firewire net
> driver I just need a hook to register a function that investigates
> incoming packets for IPv6 link layer option. In addition,
> fwnet_peer_find_by_guid must be exported.
>
> Stefan, what is your opinion on that?
>From your previous patch it looks like that the RFC 3146 related parts in
drivers/firewire/net.c are just a few places that can be enclosed into
#if/#endif blocks. That way, firewire-net will be built according to the
same Kconfig switches as before, and gets RFC 3146 capability if
CONFIG_IPV6=y or =m.
#if/#endif are generally not very nice, but in this case I think they can
be kept localized and thus are more beneficial than hurtful.
There is a catch: Since both net/ipv6/Kconfig::IPV6 and
drivers/firewire/Kconfig::FIREWIRE_NET are tristate variables, we need to
prevent CONFIG_FIREWIRE_NET=y while CONFIG_IPV6=m. One way to do that
would be like it was done for the infrared remote control support in the
firedtv driver which depends on the CONFIG_INPUT tristate variable. This
was solved like this:
- The helper variable drivers/media/firewire/Kconfig::DVB_FIREDTV_INPUT
was added.
- This variable is true if CONFIG_INPUT=y,
or if CONFIG_DVB_FIREDTV=m and CONFIG_INPUT=m.
In other words, if CONFIG_INPUT=m and CONFIG_DVB_FIREDTV=y, firedtv
silently loses support for remote control input.
- The respective firedtv parts are of course made dependent on
CONFIG_DVB_FIREDTV. In this case, only
drivers/media/firewire/firedtv.h and drivers/media/firewire/Makefile
are minimally affected.
So, if implemented like that, the special case of CONFIG_FIREWIRE_NET=y &&
CONFIG_IPV6=m would mean that firewire-net would be built but would lack
RFC 3146 support.
With a little bit more Kconfig related effort one could solve it such that
CONFIG_FIREWIRE_NET=y && CONFIG_IPV6=m would actually put RFC 3146 support
into firewire-net but would force it to be built modular instead of
statically.
Not sure which way is preferrable. Cc'ing netdev.
In case of CONFIG_IPV6=n however, people should still be able to build
firewire-net with its current RFC 2734-only feature set.
--
Stefan Richter
-=====-===-= ---= -==--
http://arcgraph.de/sr/
^ permalink raw reply
* [PATCH net-next] be2net: fix unconditionally returning IRQ_HANDLED in INTx
From: Sathya Perla @ 2013-01-12 8:47 UTC (permalink / raw)
To: netdev; +Cc: Sathya Perla
commit e49cc34f introduced an unconditional IRQ_HANDLED return in be_intx()
to workaround Lancer and BE2 HW issues. This is bad as it prevents the kernel
from detecting interrupt storms due to broken HW.
The BE2/Lancer HW issues are:
1) In Lancer, there is no means for the driver to detect if the interrupt
belonged to device, other than counting and notifying events.
2) In Lancer de-asserting INTx takes a while, causing the INTx irq handler
to be called multiple times till the de-assert happens.
3) In BE2, we see an occasional interrupt even when EQs are unarmed.
Issue (1) can cause the notified events to be orphaned, if NAPI was already
running.
This patch fixes this issue by scheduling NAPI only if it is not scheduled
already. Doing this also takes care of possible events_get() race that may be
caused due to issue (2) and (3). Also, IRQ_HANDLED is returned only the first
time zero events are detected.
(Thanks Ben H. for the feedback and suggestions.)
Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
---
drivers/net/ethernet/emulex/benet/be.h | 1 +
drivers/net/ethernet/emulex/benet/be_main.c | 29 ++++++++++++++++++--------
2 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 3bc1912..4eba17b 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -190,6 +190,7 @@ struct be_eq_obj {
u8 idx; /* array index */
u16 tx_budget;
+ u16 spurious_intr;
struct napi_struct napi;
struct be_adapter *adapter;
} ____cacheline_aligned_in_smp;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 9dca22b..5c99570 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -2026,19 +2026,30 @@ static irqreturn_t be_intx(int irq, void *dev)
struct be_adapter *adapter = eqo->adapter;
int num_evts = 0;
- /* On Lancer, clear-intr bit of the EQ DB does not work.
- * INTx is de-asserted only on notifying num evts.
+ /* IRQ is not expected when NAPI is scheduled as the EQ
+ * will not be armed.
+ * But, this can happen on Lancer INTx where it takes
+ * a while to de-assert INTx or in BE2 where occasionaly
+ * an interrupt may be raised even when EQ is unarmed.
+ * If NAPI is already scheduled, then counting & notifying
+ * events will orphan them.
*/
- if (lancer_chip(adapter))
+ if (napi_schedule_prep(&eqo->napi)) {
num_evts = events_get(eqo);
+ __napi_schedule(&eqo->napi);
+ if (num_evts)
+ eqo->spurious_intr = 0;
+ }
+ be_eq_notify(adapter, eqo->q.id, false, true, num_evts);
- /* The EQ-notify may not de-assert INTx rightaway, causing
- * the ISR to be invoked again. So, return HANDLED even when
- * num_evts is zero.
+ /* Return IRQ_HANDLED only for the the first spurious intr
+ * after a valid intr to stop the kernel from branding
+ * this irq as a bad one!
*/
- be_eq_notify(adapter, eqo->q.id, false, true, num_evts);
- napi_schedule(&eqo->napi);
- return IRQ_HANDLED;
+ if (num_evts || eqo->spurious_intr++ == 0)
+ return IRQ_HANDLED;
+ else
+ return IRQ_NONE;
}
static irqreturn_t be_msix(int irq, void *dev)
--
1.7.1
^ permalink raw reply related
* Re: [PATCH net-next] be2net: fix unconditionally returning IRQ_HANDLED in INTx
From: David Miller @ 2013-01-12 9:21 UTC (permalink / raw)
To: sathya.perla; +Cc: netdev
In-Reply-To: <ac9920f8-3e7c-4920-8323-510e648822c8@CMEXHTCAS2.ad.emulex.com>
From: Sathya Perla <sathya.perla@emulex.com>
Date: Sat, 12 Jan 2013 14:17:02 +0530
> commit e49cc34f introduced an unconditional IRQ_HANDLED return in be_intx()
> to workaround Lancer and BE2 HW issues. This is bad as it prevents the kernel
> from detecting interrupt storms due to broken HW.
>
> The BE2/Lancer HW issues are:
> 1) In Lancer, there is no means for the driver to detect if the interrupt
> belonged to device, other than counting and notifying events.
> 2) In Lancer de-asserting INTx takes a while, causing the INTx irq handler
> to be called multiple times till the de-assert happens.
> 3) In BE2, we see an occasional interrupt even when EQs are unarmed.
>
> Issue (1) can cause the notified events to be orphaned, if NAPI was already
> running.
> This patch fixes this issue by scheduling NAPI only if it is not scheduled
> already. Doing this also takes care of possible events_get() race that may be
> caused due to issue (2) and (3). Also, IRQ_HANDLED is returned only the first
> time zero events are detected.
> (Thanks Ben H. for the feedback and suggestions.)
>
> Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
Any particular reason why we shouldn't put this fix into 'net' instead
of 'net-next'?
^ permalink raw reply
* Re: IPv6 over firewire
From: Stefan Richter @ 2013-01-12 9:24 UTC (permalink / raw)
To: stephan.gatzka; +Cc: linux1394-devel, yoshfuji, netdev
In-Reply-To: <50F10E94.9090302@gmail.com>
[Cc'ing netdev. This is about
http://marc.info/?l=linux1394-devel&m=135723690427469]
On Jan 12 Stephan Gatzka wrote:
> On Jan 10 Stefan Richter wrote:
> > Relative to mentioned preliminary patch, there need to be some cleanups
> > done, in my opinion:
> > - The move of struct fwnet_device from drivers/firewire/net.c into
> > include/linux/firewire.h, the inclusion of <linux/firewire.h> into
> > net/ipv6/ndisc.c, and the use of <linux/firewire.h> definitions in
> > net/ipv6/ndisc.c need to be undone.
> > - Instead, the dependencies should be solved such that
> > include/net/ndisc.h (or whatever net header would be appropriate
> > for these kinds of definitions) defines RFC 3146 specific structs
> > or/and functions (or extensions of existing functions by additional
> > arguments) or/and driver ops (alias methods alias callbacks, in the
> > style of net_device.header_ops and the likes). Then, both
> > net/ipv6/ndisc.c and drivers/firewire/net.c would use these new RFC
> > 3146 related definitions but net/ipv6/ndisc.c would not become a
> > user of any <linux/firewire.h> definitions.
>
>
> Just to know if I understood you correctly. You want to have a function
> pointer in struct net_device like fill_link_layer_option(). This
> function pointer has to be set when allocating a struct net_device object.
>
> This is certainly possible, but if I do so, I'd assume that then _every_
> network device (ethernet, infiniband, ...) in linux has to implement
> such a function. Otherwise, I think the ndisc code only for a firewire
> net device will call the callback function. So I would introduce a
> callback routine in struct net_device just for firewire.
>
> The problem is, that right now, firewire is the _only_ device that
> requires this special link layer option format. All other network device
> do not require this right now. So I ask myself if its worth to introduce
> this callback routine just for firewire.
I haven't looked in detail into what is really required here. Maybe a new
driver op (callback) isn't actually needed.
But if a new callback is needed, it doesn't have to burden the kernel much:
- In the linux-kernel OOP model, there are mandatory methods as well
as optional methods. A new method for RFC 3146 Neighbor Discovery
should of course be an optional one.
- There is a downside to optional methods: The core code which may
have to use the method first needs to do a NULL check of the
method's function pointer or needs to check a correlated
capabilities flag or something like that. Such additional checks
are undesirable in hot paths, but I suppose IPv6 Neighbor Discovery
is not a particularly hot path.
- There is another downside: Each new driver method increases the
memory footprint of instances of respective function pointer tables
by 4 or 8 bytes.
Both downsides can be countered somewhat by enclosing the respective
code into #ifdef CONFIG_RFC3146_NDISC...#endif and have something like
select RFC3146_NDISC if IPV6 = y || (IPV6 = m && FIREWIRE_NET = m)
in the "config FIREWIRE_NET" section.
But the new callback (if one is really needed) doesn't have to be a driver
method. It could also look about like this:
include/net/ndisc.h:
-extern struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
- struct ndisc_options *ndopts);
+extern struct ndisc_options *__ndisc_parse_options(u8 *opt,
+ int opt_len, struct ndisc_options *ndopts,
+ whatever_type *callback);
+
+static inline struct ndisc_options *ndisc_parse_options(u8 *opt,
+ int opt_len, struct ndisc_options *ndopts)
+{
+ return __ndisc_parse_options(opt, len, ndopts, NULL);
+}
net/ipv6/ndisc.c:
-struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
- struct ndisc_options *ndopts)
+struct ndisc_options *__ndisc_parse_options(u8 *opt, int opt_len,
+ struct ndisc_options *ndopts, whatever_type *callback)
{
Or the (optional!) callback could be a new member of struct ndisc_options.
However, does net/ipv6/ndisc.c really need to be aware of the RFC 3146
Neighbor Discovery related packet header layouts? Isn't it possible to
rewrite these headers in-place in drivers/firewire/net.c?
--
Stefan Richter
-=====-===-= ---= -==--
http://arcgraph.de/sr/
^ permalink raw reply
* Re: IPv6 over firewire
From: Stephan Gatzka @ 2013-01-12 10:54 UTC (permalink / raw)
To: Stefan Richter; +Cc: linux1394-devel, yoshfuji, netdev
In-Reply-To: <20130112102452.13babc65@stein>
> But if a new callback is needed, it doesn't have to burden the kernel much:
>
> - In the linux-kernel OOP model, there are mandatory methods as well
> as optional methods. A new method for RFC 3146 Neighbor Discovery
> should of course be an optional one.
>
> - There is a downside to optional methods: The core code which may
> have to use the method first needs to do a NULL check of the
> method's function pointer or needs to check a correlated
> capabilities flag or something like that. Such additional checks
> are undesirable in hot paths, but I suppose IPv6 Neighbor Discovery
> is not a particularly hot path.
Yes, that should be true.
>
> - There is another downside: Each new driver method increases the
> memory footprint of instances of respective function pointer tables
> by 4 or 8 bytes.
I can't imagine that this is a show stopper. How many instances of
struct netdev do we have o a typical system? I guess not the much.
>
> Both downsides can be countered somewhat by enclosing the respective
> code into #ifdef CONFIG_RFC3146_NDISC...#endif and have something like
> select RFC3146_NDISC if IPV6 = y || (IPV6 = m && FIREWIRE_NET = m)
> in the "config FIREWIRE_NET" section.
>
> But the new callback (if one is really needed) doesn't have to be a driver
> method. It could also look about like this:
>
> include/net/ndisc.h:
> -extern struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
> - struct ndisc_options *ndopts);
> +extern struct ndisc_options *__ndisc_parse_options(u8 *opt,
> + int opt_len, struct ndisc_options *ndopts,
> + whatever_type *callback);
> +
> +static inline struct ndisc_options *ndisc_parse_options(u8 *opt,
> + int opt_len, struct ndisc_options *ndopts)
> +{
> + return __ndisc_parse_options(opt, len, ndopts, NULL);
> +}
>
> net/ipv6/ndisc.c:
> -struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len,
> - struct ndisc_options *ndopts)
> +struct ndisc_options *__ndisc_parse_options(u8 *opt, int opt_len,
> + struct ndisc_options *ndopts, whatever_type *callback)
> {
>
> Or the (optional!) callback could be a new member of struct ndisc_options.
Hm, right now I have no opinion on that. Where does
whatever_type *callback comes from? Is it an exported method of the
firewire net driver or the new function pointer in struct netdevice?
> However, does net/ipv6/ndisc.c really need to be aware of the RFC 3146
> Neighbor Discovery related packet header layouts? Isn't it possible to
> rewrite these headers in-place in drivers/firewire/net.c?
Yes, it it possible, but yoshfuji strongly voted against rewriting ndisc
packets in firewire net driver to maintain extensibility to protocols.
Especially IPSEC can just not work if I rewrite the packets in the driver.
Regards,
Stephan
--
Welchen Unterschied gibt es zwischen einem toten Hund auf der
Straße und einer überfahrenen Bratsche auf der Straße? Vor dem
toten Hund gibt es Bremsspuren.
^ permalink raw reply
* [PATCH] CDC_NCM adding support IFF_NOARP for infineon modem platform
From: Wei Shuai @ 2013-01-12 11:34 UTC (permalink / raw)
To: gregkh, alexey.orishko, bjorn; +Cc: linux-usb, netdev, Wei Shuai
Infineon(now Intel) HSPA Modem platform NCM cannot support ARP. so I introduce a flag CDC_NCM_DRIVER_DATA_NOARP which is defined in driver_info:data. so later on, if more such buggy devices are found, they could use same flag to handle.
Signed-off-by: Wei Shuai <cpuwolf@gmail.com>
---
drivers/net/usb/cdc_ncm.c | 29 +++++++++++++++++++++++++++++
1 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 71b6e92..6093e07 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -55,6 +55,9 @@
#define DRIVER_VERSION "14-Mar-2012"
+/* Flags for driver_info::data */
+#define CDC_NCM_DRIVER_DATA_NOARP 1
+
static void cdc_ncm_txpath_bh(unsigned long param);
static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx);
static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer);
@@ -573,6 +576,10 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
return -ENODEV;
#endif
+ if (dev->driver_info->data & CDC_NCM_DRIVER_DATA_NOARP) {
+ /* some buggy device cannot do ARP*/
+ dev->net->flags |= IFF_NOARP;
+ }
/* NCM data altsetting is always 1 */
ret = cdc_ncm_bind_common(dev, intf, 1);
@@ -1155,6 +1162,21 @@ static const struct driver_info wwan_info = {
.tx_fixup = cdc_ncm_tx_fixup,
};
+/* Same as wwan_info, but with IFF_NOARP */
+static const struct driver_info wwan_noarp_info = {
+ .description = "Mobile Broadband Network Device (NO ARP)",
+ .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET
+ | FLAG_WWAN,
+ .data = CDC_NCM_DRIVER_DATA_NOARP,
+ .bind = cdc_ncm_bind,
+ .unbind = cdc_ncm_unbind,
+ .check_connect = cdc_ncm_check_connect,
+ .manage_power = usbnet_manage_power,
+ .status = cdc_ncm_status,
+ .rx_fixup = cdc_ncm_rx_fixup,
+ .tx_fixup = cdc_ncm_tx_fixup,
+};
+
static const struct usb_device_id cdc_devs[] = {
/* Ericsson MBM devices like F5521gw */
{ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
@@ -1194,6 +1216,13 @@ static const struct usb_device_id cdc_devs[] = {
.driver_info = (unsigned long)&wwan_info,
},
+ /* Infineon(now Intel) HSPA Modem platform */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1519, 0x0443,
+ USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long)&wwan_noarp_info,
+ },
+
/* Generic CDC-NCM devices */
{ USB_INTERFACE_INFO(USB_CLASS_COMM,
USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
--
1.7.6.5
^ permalink raw reply related
* Re: qmi_wwan on Huawei E398
From: Cedric Jehasse @ 2013-01-12 12:22 UTC (permalink / raw)
To: Marius Kotsbak; +Cc: Bjørn Mork, netdev
In-Reply-To: <CAGOautsU-Hen5EP-Y3Xp+jzGYRJZQFCGRk=mt0MvH2GfpTQe4g@mail.gmail.com>
>
> Have you tried if the same happens with modemmanager?
>
No, i haven`t. And it's not really relevant for me, as modemmanager
might match interfaces in a different way.
It looked weird to me to have a single parent interface for both the
cdc_dwm device and the wwan device, while there are separate
usb_interfaces for control and data.
From Bjørn's explanation, i understand why this was done. And i will
take a look at how this can be changed in ofono.
Thanks,
Cedric
^ permalink raw reply
* [PATCH] {cfg,mac}80211.h: fix some kernel-doc warnings
From: Yacine Belkadi @ 2013-01-12 12:54 UTC (permalink / raw)
To: Johannes Berg
Cc: David S. Miller, linux-wireless, netdev, linux-doc, linux-kernel,
Yacine Belkadi
When building the 80211 DocBook, scripts/kernel-doc reports the following type
of warnings:
Warning(include/net/cfg80211.h:334): No description found for return value of 'cfg80211_get_chandef_type'
These warnings are only reported when scripts/kernel-doc runs in verbose mode.
Fix:
In comments, use "Return:" to describe function return values.
Signed-off-by: Yacine Belkadi <yacine.belkadi.1@gmail.com>
---
include/net/cfg80211.h | 154 ++++++++++++++++++++++++++++--------------------
include/net/mac80211.h | 74 ++++++++++++++++++-----
2 files changed, 151 insertions(+), 77 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 8e6a6b7..9f2f585 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -326,7 +326,7 @@ struct cfg80211_chan_def {
* cfg80211_get_chandef_type - return old channel type from chandef
* @chandef: the channel definition
*
- * Returns the old channel type (NOHT, HT20, HT40+/-) from a given
+ * Return: The old channel type (NOHT, HT20, HT40+/-) from a given
* chandef, which must have a bandwidth allowing this conversion.
*/
static inline enum nl80211_channel_type
@@ -364,7 +364,7 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
* @chandef1: first channel definition
* @chandef2: second channel definition
*
- * Returns %true if the channels defined by the channel definitions are
+ * Return: %true if the channels defined by the channel definitions are
* identical, %false otherwise.
*/
static inline bool
@@ -382,7 +382,7 @@ cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1,
* @chandef1: first channel definition
* @chandef2: second channel definition
*
- * Returns %NULL if the given channel definitions are incompatible,
+ * Return: %NULL if the given channel definitions are incompatible,
* chandef1 or chandef2 otherwise.
*/
const struct cfg80211_chan_def *
@@ -392,6 +392,7 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1,
/**
* cfg80211_chandef_valid - check if a channel definition is valid
* @chandef: the channel definition to check
+ * Return: %true if the channel definition is valid. %false otherwise.
*/
bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef);
@@ -399,7 +400,8 @@ bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef);
* cfg80211_chandef_usable - check if secondary channels can be used
* @wiphy: the wiphy to validate against
* @chandef: the channel definition to check
- * @prohibited_flags: the regulatory chanenl flags that must not be set
+ * @prohibited_flags: the regulatory channel flags that must not be set
+ * Return: %true if secondary channels are usable. %false otherwise.
*/
bool cfg80211_chandef_usable(struct wiphy *wiphy,
const struct cfg80211_chan_def *chandef,
@@ -1266,7 +1268,7 @@ struct cfg80211_bss {
*
* Note that the return value is an RCU-protected pointer, so
* rcu_read_lock() must be held when calling this function.
- * Returns %NULL if not found.
+ * Return: %NULL if not found.
*/
const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
@@ -2409,6 +2411,7 @@ static inline void wiphy_net_set(struct wiphy *wiphy, struct net *net)
* wiphy_priv - return priv from wiphy
*
* @wiphy: the wiphy whose priv pointer to return
+ * Return: The priv of @wiphy.
*/
static inline void *wiphy_priv(struct wiphy *wiphy)
{
@@ -2420,6 +2423,7 @@ static inline void *wiphy_priv(struct wiphy *wiphy)
* priv_to_wiphy - return the wiphy containing the priv
*
* @priv: a pointer previously returned by wiphy_priv
+ * Return: The wiphy of @priv.
*/
static inline struct wiphy *priv_to_wiphy(void *priv)
{
@@ -2442,6 +2446,7 @@ static inline void set_wiphy_dev(struct wiphy *wiphy, struct device *dev)
* wiphy_dev - get wiphy dev pointer
*
* @wiphy: The wiphy whose device struct to look up
+ * Return: The dev of @wiphy.
*/
static inline struct device *wiphy_dev(struct wiphy *wiphy)
{
@@ -2452,6 +2457,7 @@ static inline struct device *wiphy_dev(struct wiphy *wiphy)
* wiphy_name - get wiphy name
*
* @wiphy: The wiphy whose name to return
+ * Return: The name of @wiphy.
*/
static inline const char *wiphy_name(const struct wiphy *wiphy)
{
@@ -2467,8 +2473,8 @@ static inline const char *wiphy_name(const struct wiphy *wiphy)
* Create a new wiphy and associate the given operations with it.
* @sizeof_priv bytes are allocated for private use.
*
- * The returned pointer must be assigned to each netdev's
- * ieee80211_ptr for proper operation.
+ * Return: A pointer to the new wiphy. This pointer must be
+ * assigned to each netdev's ieee80211_ptr for proper operation.
*/
struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv);
@@ -2477,7 +2483,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv);
*
* @wiphy: The wiphy to register.
*
- * Returns a non-negative wiphy index or a negative error code.
+ * Return: A non-negative wiphy index or a negative error code.
*/
extern int wiphy_register(struct wiphy *wiphy);
@@ -2626,6 +2632,7 @@ static inline u8 *wdev_address(struct wireless_dev *wdev)
* wdev_priv - return wiphy priv from wireless_dev
*
* @wdev: The wireless device whose wiphy's priv pointer to return
+ * Return: The wiphy priv of @wdev.
*/
static inline void *wdev_priv(struct wireless_dev *wdev)
{
@@ -2643,12 +2650,14 @@ static inline void *wdev_priv(struct wireless_dev *wdev)
* ieee80211_channel_to_frequency - convert channel number to frequency
* @chan: channel number
* @band: band, necessary due to channel number overlap
+ * Return: The corresponding frequency (in MHz), or 0 if the conversion failed.
*/
extern int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band);
/**
* ieee80211_frequency_to_channel - convert frequency to channel number
* @freq: center frequency
+ * Return: The corresponding channel, or 0 if the conversion failed.
*/
extern int ieee80211_frequency_to_channel(int freq);
@@ -2665,6 +2674,7 @@ extern struct ieee80211_channel *__ieee80211_get_channel(struct wiphy *wiphy,
* ieee80211_get_channel - get channel struct from wiphy for specified frequency
* @wiphy: the struct wiphy to get the channel for
* @freq: the center frequency of the channel
+ * Return: The channel struct from @wiphy at @freq.
*/
static inline struct ieee80211_channel *
ieee80211_get_channel(struct wiphy *wiphy, int freq)
@@ -2679,10 +2689,10 @@ ieee80211_get_channel(struct wiphy *wiphy, int freq)
* @basic_rates: bitmap of basic rates
* @bitrate: the bitrate for which to find the basic rate
*
- * This function returns the basic rate corresponding to a given
- * bitrate, that is the next lower bitrate contained in the basic
- * rate map, which is, for this function, given as a bitmap of
- * indices of rates in the band's bitrate table.
+ * Return: The basic rate corresponding to a given bitrate, that
+ * is the next lower bitrate contained in the basic rate map,
+ * which is, for this function, given as a bitmap of indices of
+ * rates in the band's bitrate table.
*/
struct ieee80211_rate *
ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
@@ -2775,18 +2785,21 @@ extern const unsigned char bridge_tunnel_header[6];
/**
* ieee80211_get_hdrlen_from_skb - get header length from data
*
+ * @skb: the frame
+ *
* Given an skb with a raw 802.11 header at the data pointer this function
- * returns the 802.11 header length in bytes (not including encryption
- * headers). If the data in the sk_buff is too short to contain a valid 802.11
- * header the function returns 0.
+ * returns the 802.11 header length.
*
- * @skb: the frame
+ * Return: The 802.11 header length in bytes (not including encryption
+ * headers). Or 0 if the data in the sk_buff is too short to contain a valid
+ * 802.11 header.
*/
unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
/**
* ieee80211_hdrlen - get header length in bytes from frame control
* @fc: frame control field in little-endian format
+ * Return: The header length in bytes.
*/
unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc);
@@ -2794,7 +2807,7 @@ unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc);
* ieee80211_get_mesh_hdrlen - get mesh extension header length
* @meshhdr: the mesh extension header, only the flags field
* (first byte) will be accessed
- * Returns the length of the extension header, which is always at
+ * Return: The length of the extension header, which is always at
* least 6 bytes and at most 18 if address 5 and 6 are present.
*/
unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
@@ -2812,6 +2825,7 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
* @skb: the 802.11 data frame
* @addr: the device MAC address
* @iftype: the virtual interface type
+ * Return: 0 on success. Non-zero on error.
*/
int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
enum nl80211_iftype iftype);
@@ -2823,6 +2837,7 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
* @iftype: the virtual interface type
* @bssid: the network bssid (used only for iftype STATION and ADHOC)
* @qos: build 802.11 QoS data frame
+ * Return: 0 on success, or a negative error code.
*/
int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
enum nl80211_iftype iftype, u8 *bssid, bool qos);
@@ -2850,6 +2865,7 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
/**
* cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
* @skb: the data frame
+ * Return: The 802.1p/1d tag.
*/
unsigned int cfg80211_classify8021d(struct sk_buff *skb);
@@ -2860,12 +2876,13 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb);
* @ies: data consisting of IEs
* @len: length of data
*
- * This function will return %NULL if the element ID could
- * not be found or if the element is invalid (claims to be
- * longer than the given data), or a pointer to the first byte
- * of the requested element, that is the byte containing the
- * element ID. There are no checks on the element length
- * other than having to fit into the given data.
+ * Return: %NULL if the element ID could not be found or if
+ * the element is invalid (claims to be longer than the given
+ * data), or a pointer to the first byte of the requested
+ * element, that is the byte containing the element ID.
+ *
+ * Note: There are no checks on the element length other than
+ * having to fit into the given data.
*/
const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len);
@@ -2877,12 +2894,13 @@ const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len);
* @ies: data consisting of IEs
* @len: length of data
*
- * This function will return %NULL if the vendor specific element ID
- * could not be found or if the element is invalid (claims to be
- * longer than the given data), or a pointer to the first byte
- * of the requested element, that is the byte containing the
- * element ID. There are no checks on the element length
- * other than having to fit into the given data.
+ * Return: %NULL if the vendor specific element ID could not be found or if the
+ * element is invalid (claims to be longer than the given data), or a pointer to
+ * the first byte of the requested element, that is the byte containing the
+ * element ID.
+ *
+ * Note: There are no checks on the element length other than having to fit into
+ * the given data.
*/
const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type,
const u8 *ies, int len);
@@ -2915,6 +2933,8 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type,
*
* Drivers should check the return value, its possible you can get
* an -ENOMEM.
+ *
+ * Return: 0 on success. -ENOMEM.
*/
extern int regulatory_hint(struct wiphy *wiphy, const char *alpha2);
@@ -2949,12 +2969,13 @@ extern void wiphy_apply_custom_regulatory(
* it wants to follow we respect that unless a country IE has been received
* and processed already.
*
- * Returns 0 if it was able to find a valid regulatory rule which does
- * apply to the given center_freq otherwise it returns non-zero. It will
- * also return -ERANGE if we determine the given center_freq does not even have
- * a regulatory rule for a frequency range in the center_freq's band. See
+ * Return: 0 if it was able to find a valid regulatory rule which does apply
+ * to the given center_freq.
+ * -ERANGE if we determine the given center_freq does not even have a
+ * regulatory rule for a frequency range in the center_freq's band. See
* freq_in_rule_band() for our current definition of a band -- this is purely
* subjective and right now its 802.11 specific.
+ * Non-zero otherwise.
*/
extern int freq_reg_info(struct wiphy *wiphy,
u32 center_freq,
@@ -3006,7 +3027,8 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy);
* This informs cfg80211 that BSS information was found and
* the BSS should be updated/added.
*
- * NOTE: Returns a referenced struct, must be released with cfg80211_put_bss()!
+ * Return: A referenced struct, must be released with cfg80211_put_bss()!
+ * Or %NULL on error.
*/
struct cfg80211_bss * __must_check
cfg80211_inform_bss_frame(struct wiphy *wiphy,
@@ -3031,7 +3053,8 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
* This informs cfg80211 that BSS information was found and
* the BSS should be updated/added.
*
- * NOTE: Returns a referenced struct, must be released with cfg80211_put_bss()!
+ * Return: A referenced struct, must be released with cfg80211_put_bss()!
+ * Or %NULL on error.
*/
struct cfg80211_bss * __must_check
cfg80211_inform_bss(struct wiphy *wiphy,
@@ -3308,16 +3331,18 @@ void wiphy_rfkill_stop_polling(struct wiphy *wiphy);
* the testmode command. Since it is intended for a reply, calling
* it outside of the @testmode_cmd operation is invalid.
*
- * The returned skb (or %NULL if any errors happen) is pre-filled
- * with the wiphy index and set up in a way that any data that is
- * put into the skb (with skb_put(), nla_put() or similar) will end
- * up being within the %NL80211_ATTR_TESTDATA attribute, so all that
- * needs to be done with the skb is adding data for the corresponding
- * userspace tool which can then read that data out of the testdata
- * attribute. You must not modify the skb in any other way.
+ * The returned skb is pre-filled with the wiphy index and set up in
+ * a way that any data that is put into the skb (with skb_put(),
+ * nla_put() or similar) will end up being within the
+ * %NL80211_ATTR_TESTDATA attribute, so all that needs to be done
+ * with the skb is adding data for the corresponding userspace tool
+ * which can then read that data out of the testdata attribute. You
+ * must not modify the skb in any other way.
*
* When done, call cfg80211_testmode_reply() with the skb and return
* its error code as the result of the @testmode_cmd operation.
+ *
+ * Return: An allocated and pre-filled skb. %NULL if any errors happen.
*/
struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
int approxlen);
@@ -3327,11 +3352,12 @@ struct sk_buff *cfg80211_testmode_alloc_reply_skb(struct wiphy *wiphy,
* @skb: The skb, must have been allocated with
* cfg80211_testmode_alloc_reply_skb()
*
- * Returns an error code or 0 on success, since calling this
- * function will usually be the last thing before returning
- * from the @testmode_cmd you should return the error code.
- * Note that this function consumes the skb regardless of the
- * return value.
+ * Since calling this function will usually be the last thing
+ * before returning from the @testmode_cmd you should return
+ * the error code. Note that this function consumes the skb
+ * regardless of the return value.
+ *
+ * Return: An error code or 0 on success.
*/
int cfg80211_testmode_reply(struct sk_buff *skb);
@@ -3345,14 +3371,16 @@ int cfg80211_testmode_reply(struct sk_buff *skb);
* This function allocates and pre-fills an skb for an event on the
* testmode multicast group.
*
- * The returned skb (or %NULL if any errors happen) is set up in the
- * same way as with cfg80211_testmode_alloc_reply_skb() but prepared
- * for an event. As there, you should simply add data to it that will
- * then end up in the %NL80211_ATTR_TESTDATA attribute. Again, you must
- * not modify the skb in any other way.
+ * The returned skb is set up in the same way as with
+ * cfg80211_testmode_alloc_reply_skb() but prepared for an event. As
+ * there, you should simply add data to it that will then end up in the
+ * %NL80211_ATTR_TESTDATA attribute. Again, you must not modify the skb
+ * in any other way.
*
* When done filling the skb, call cfg80211_testmode_event() with the
* skb to send the event.
+ *
+ * Return: An allocated and pre-filled skb. %NULL if any errors happen.
*/
struct sk_buff *cfg80211_testmode_alloc_event_skb(struct wiphy *wiphy,
int approxlen, gfp_t gfp);
@@ -3533,13 +3561,13 @@ void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
* @len: length of the frame data
* @gfp: context flags
*
- * Returns %true if a user space application has registered for this frame.
+ * This function is called whenever an Action frame is received for a station
+ * mode interface, but is not processed in kernel.
+ *
+ * Return: %true if a user space application has registered for this frame.
* For action frames, that makes it responsible for rejecting unrecognized
* action frames; %false otherwise, in which case for action frames the
* driver is responsible for rejecting the frame.
- *
- * This function is called whenever an Action frame is received for a station
- * mode interface, but is not processed in kernel.
*/
bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_dbm,
const u8 *buf, size_t len, gfp_t gfp);
@@ -3631,7 +3659,7 @@ void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
* This function is used in AP mode (only!) to inform userspace that
* a spurious class 3 frame was received, to be able to deauth the
* sender.
- * Returns %true if the frame was passed to userspace (or this failed
+ * Return: %true if the frame was passed to userspace (or this failed
* for a reason other than not having a subscription.)
*/
bool cfg80211_rx_spurious_frame(struct net_device *dev,
@@ -3647,7 +3675,7 @@ bool cfg80211_rx_spurious_frame(struct net_device *dev,
* an associated station sent a 4addr frame but that wasn't expected.
* It is allowed and desirable to send this event only once for each
* station to avoid event flooding.
- * Returns %true if the frame was passed to userspace (or this failed
+ * Return: %true if the frame was passed to userspace (or this failed
* for a reason other than not having a subscription.)
*/
bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
@@ -3685,8 +3713,8 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy,
* @wiphy: the wiphy
* @chandef: the channel definition
*
- * This function returns true if there is no secondary channel or the secondary
- * channel(s) can be used for beaconing (i.e. is not a radar channel etc.)
+ * Return: %true if there is no secondary channel or the secondary channel(s)
+ * can be used for beaconing (i.e. is not a radar channel etc.)
*/
bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef);
@@ -3756,9 +3784,9 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev);
* The function finds a given P2P attribute in the (vendor) IEs and
* copies its contents to the given buffer.
*
- * The return value is a negative error code (-%EILSEQ or -%ENOENT) if
- * the data is malformed or the attribute can't be found (respectively),
- * or the length of the found attribute (which can be zero).
+ * Return: A negative error code (-%EILSEQ or -%ENOENT) if the data is
+ * malformed or the attribute can't be found (respectively), or the
+ * length of the found attribute (which can be zero).
*/
int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
enum ieee80211_p2p_attr_id attr,
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index ee50c5e..dbea2ec 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1522,6 +1522,8 @@ struct ieee80211_hw {
* structure can then access it via hw->priv. Note that mac802111 drivers should
* not use wiphy_priv() to try to get their private driver structure as this
* is already used internally by mac80211.
+ *
+ * Return: The mac80211 driver hw struct of @wiphy.
*/
struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy);
@@ -2661,6 +2663,8 @@ struct ieee80211_ops {
*
* @priv_data_len: length of private data
* @ops: callbacks for this device
+ *
+ * Return: A pointer to the new hardware device, or %NULL on error.
*/
struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
const struct ieee80211_ops *ops);
@@ -2673,6 +2677,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
* need to fill the contained wiphy's information.
*
* @hw: the device to register as returned by ieee80211_alloc_hw()
+ *
+ * Return: 0 on success. An error code otherwise.
*/
int ieee80211_register_hw(struct ieee80211_hw *hw);
@@ -2719,6 +2725,8 @@ extern char *__ieee80211_create_tpt_led_trigger(
* of the trigger so you can automatically link the LED device.
*
* @hw: the hardware to get the LED trigger name for
+ *
+ * Return: The name of the LED trigger. %NULL if not configured for LEDs.
*/
static inline char *ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
{
@@ -2738,6 +2746,8 @@ static inline char *ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
* of the trigger so you can automatically link the LED device.
*
* @hw: the hardware to get the LED trigger name for
+ *
+ * Return: The name of the LED trigger. %NULL if not configured for LEDs.
*/
static inline char *ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
{
@@ -2757,6 +2767,8 @@ static inline char *ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
* of the trigger so you can automatically link the LED device.
*
* @hw: the hardware to get the LED trigger name for
+ *
+ * Return: The name of the LED trigger. %NULL if not configured for LEDs.
*/
static inline char *ieee80211_get_assoc_led_name(struct ieee80211_hw *hw)
{
@@ -2776,6 +2788,8 @@ static inline char *ieee80211_get_assoc_led_name(struct ieee80211_hw *hw)
* of the trigger so you can automatically link the LED device.
*
* @hw: the hardware to get the LED trigger name for
+ *
+ * Return: The name of the LED trigger. %NULL if not configured for LEDs.
*/
static inline char *ieee80211_get_radio_led_name(struct ieee80211_hw *hw)
{
@@ -2793,9 +2807,10 @@ static inline char *ieee80211_get_radio_led_name(struct ieee80211_hw *hw)
* @blink_table: the blink table -- needs to be ordered by throughput
* @blink_table_len: size of the blink table
*
- * This function returns %NULL (in case of error, or if no LED
- * triggers are configured) or the name of the new trigger.
- * This function must be called before ieee80211_register_hw().
+ * Return: %NULL (in case of error, or if no LED triggers are
+ * configured) or the name of the new trigger.
+ *
+ * Note: This function must be called before ieee80211_register_hw().
*/
static inline char *
ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw, unsigned int flags,
@@ -2928,10 +2943,10 @@ static inline void ieee80211_rx_ni(struct ieee80211_hw *hw,
* Calls to this function for a single hardware must be synchronized against
* each other.
*
- * The function returns -EINVAL when the requested PS mode is already set.
- *
* @sta: currently connected sta
* @start: start or stop PS
+ *
+ * Return: 0 on success. -EINVAL when the requested PS mode is already set.
*/
int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start);
@@ -2945,6 +2960,8 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start);
*
* @sta: currently connected sta
* @start: start or stop PS
+ *
+ * Return: Like ieee80211_sta_ps_transition().
*/
static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta,
bool start)
@@ -3082,6 +3099,8 @@ void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets);
* according to the current DTIM parameters/TIM bitmap.
*
* The driver is responsible for freeing the returned skb.
+ *
+ * Return: The beacon template. %NULL on error.
*/
struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -3093,6 +3112,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
*
* See ieee80211_beacon_get_tim().
+ *
+ * Return: See ieee80211_beacon_get_tim().
*/
static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
@@ -3109,6 +3130,8 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
* hardware. The destination address should be set by the caller.
*
* Can only be called in AP mode.
+ *
+ * Return: The Probe Response template. %NULL on error.
*/
struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
@@ -3124,6 +3147,8 @@ struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw,
*
* Note: Caller (or hardware) is responsible for setting the
* &IEEE80211_FCTL_PM bit.
+ *
+ * Return: The PS Poll template. %NULL on error.
*/
struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
@@ -3139,6 +3164,8 @@ struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
*
* Note: Caller (or hardware) is responsible for setting the
* &IEEE80211_FCTL_PM bit as well as Duration and Sequence Control fields.
+ *
+ * Return: The nullfunc template. %NULL on error.
*/
struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
@@ -3153,6 +3180,8 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
*
* Creates a Probe Request template which can, for example, be uploaded to
* hardware.
+ *
+ * Return: The Probe Request template. %NULL on error.
*/
struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -3188,6 +3217,8 @@ void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
* If the RTS is generated in firmware, but the host system must provide
* the duration field, the low-level driver uses this function to receive
* the duration field value in little-endian byteorder.
+ *
+ * Return: The duration.
*/
__le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, size_t frame_len,
@@ -3223,6 +3254,8 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw,
* If the CTS-to-self is generated in firmware, but the host system must provide
* the duration field, the low-level driver uses this function to receive
* the duration field value in little-endian byteorder.
+ *
+ * Return: The duration.
*/
__le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -3239,6 +3272,8 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
*
* Calculate the duration field of some generic frame, given its
* length and transmission rate (in 100kbps).
+ *
+ * Return: The duration.
*/
__le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -3255,9 +3290,10 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
* hardware/firmware does not implement buffering of broadcast/multicast
* frames when power saving is used, 802.11 code buffers them in the host
* memory. The low-level driver uses this function to fetch next buffered
- * frame. In most cases, this is used when generating beacon frame. This
- * function returns a pointer to the next buffered skb or NULL if no more
- * buffered frames are available.
+ * frame. In most cases, this is used when generating beacon frame.
+ *
+ * Return: A pointer to the next buffered skb or NULL if no more buffered
+ * frames are available.
*
* Note: buffered frames are returned only after DTIM beacon frame was
* generated with ieee80211_beacon_get() and the low-level driver must thus
@@ -3437,6 +3473,8 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue);
* @queue: queue number (counted from zero).
*
* Drivers should use this function instead of netif_stop_queue.
+ *
+ * Return: %true if the queue is stopped. %false otherwise.
*/
int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue);
@@ -3634,7 +3672,9 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, const u8 *ra,
* @vif: virtual interface to look for station on
* @addr: station's address
*
- * This function must be called under RCU lock and the
+ * Return: The station, if found. %NULL otherwise.
+ *
+ * Note: This function must be called under RCU lock and the
* resulting pointer is only valid under RCU lock as well.
*/
struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
@@ -3647,7 +3687,9 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
* @addr: remote station's address
* @localaddr: local address (vif->sdata->vif.addr). Use NULL for 'any'.
*
- * This function must be called under RCU lock and the
+ * Return: The station, if found. %NULL otherwise.
+ *
+ * Note: This function must be called under RCU lock and the
* resulting pointer is only valid under RCU lock as well.
*
* NOTE: You may pass NULL for localaddr, but then you will just get
@@ -3772,7 +3814,9 @@ void ieee80211_iter_chan_contexts_atomic(
* information. This function must only be called from within the
* .bss_info_changed callback function and only in managed mode. The function
* is only useful when the interface is associated, otherwise it will return
- * NULL.
+ * %NULL.
+ *
+ * Return: The Probe Request template. %NULL on error.
*/
struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
@@ -4119,12 +4163,14 @@ void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif);
/**
- * ieee80211_ave_rssi - report the average rssi for the specified interface
+ * ieee80211_ave_rssi - report the average RSSI for the specified interface
*
* @vif: the specified virtual interface
*
- * This function return the average rssi value for the requested interface.
- * It assumes that the given vif is valid.
+ * Note: This function assumes that the given vif is valid.
+ *
+ * Return: The average RSSI value for the requested interface, or 0 if not
+ * applicable.
*/
int ieee80211_ave_rssi(struct ieee80211_vif *vif);
--
1.7.9.5
^ permalink raw reply related
* Re: [net-next] gianfar: use more portable i/o accessors
From: Tabi Timur-B04825 @ 2013-01-12 13:44 UTC (permalink / raw)
To: Phillips Kim-R1AAHA; +Cc: netdev@vger.kernel.org, David S. Miller
In-Reply-To: <20130111161821.d62a0a60ee8d1005fb14b4d5@freescale.com>
On Fri, Jan 11, 2013 at 4:18 PM, Kim Phillips
<kim.phillips@freescale.com> wrote:
> in/out_be32 accessors are Power arch centric whereas
> ioread/writebe32 are available in other arches. Also, unlike
> in/out_be32, ioread/writebe32 expect non-volatile address arguments.
I was under the impression that the "volatile" in in/out_be32() is so
that the functions can accept a volatile pointer, not that it expects
one. Otherwise, if you pass in a volatile, you'll get a compiler
warning.
>
> Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
> ---
> drivers/net/ethernet/freescale/gianfar.h | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
> index 1b6a67c..91bb2de 100644
> --- a/drivers/net/ethernet/freescale/gianfar.h
> +++ b/drivers/net/ethernet/freescale/gianfar.h
> @@ -1136,16 +1136,16 @@ static inline int gfar_has_errata(struct gfar_private *priv,
> return priv->errata & err;
> }
>
> -static inline u32 gfar_read(volatile unsigned __iomem *addr)
> +static inline u32 gfar_read(unsigned __iomem *addr)
> {
> u32 val;
> - val = in_be32(addr);
> + val = ioread32be(addr);
> return val;
> }
Can't we just get rid of these functions altogether? Or at least, get
rid of the local variable?
--
Timur Tabi
Linux kernel developer at Freescale
^ permalink raw reply
* [RFC davem] revert: net: Make skb->skb_iif always track skb->dev
From: Oliver Hartkopp @ 2013-01-12 13:48 UTC (permalink / raw)
To: David Miller; +Cc: Linux Netdev List
Hello Dave,
in your below patch from 23 Jul 2012 you removed the check for an already set
value of skb_iif in net/core/dev.c
I'm currently working on a solution to prevent some routed CAN frames to be
sent back onto the originating network device.
With your patch it is not possible anymore to check on which netdev the
CAN frame has originally been received, as for every routing the frame
goes through netif_receive_skb(), which hard sets
skb->skb_iif = skb->dev->ifindex
and therefore kills the original incoming interface index.
To me it is not clear why skb_iff is needed anyway as the value should
always be available via skb->dev->ifindex, right?
But if skb_iff has any right to exist it should contain the first incoming
interface on the host IMO.
Please correct my if i'm wrong and/or tell me what your commit message means
in respect to my request and why skb->dev->ifindex is not used instead of
skb_iif. I feel somehow lost about the skb_iif intention ...
Best regards,
Oliver
---
http://git.kernel.org/?p=linux/kernel/git/davem/net-next.git;a=commitdiff;h=b68581778cd0051a3fb9a2b614dee7eccb5127ff
net: Make skb->skb_iif always track skb->dev
Make it follow device decapsulation, from things such as VLAN and
bonding.
The stuff that actually cares about pre-demuxed device pointers, is
handled by the "orig_dev" variable in __netif_receive_skb(). And
the only consumer of that is the po->origdev feature of AF_PACKET
sockets.
Signed-off-by: David S. Miller <davem@davemloft.net>
---
diff --git a/net/core/dev.c b/net/core/dev.c
index cca02ae..0ebaea1 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3173,8 +3173,6 @@ static int __netif_receive_skb(struct sk_buff *skb)
if (netpoll_receive_skb(skb))
return NET_RX_DROP;
- if (!skb->skb_iif)
- skb->skb_iif = skb->dev->ifindex;
orig_dev = skb->dev;
skb_reset_network_header(skb);
@@ -3186,6 +3184,7 @@ static int __netif_receive_skb(struct sk_buff *skb)
rcu_read_lock();
another_round:
+ skb->skb_iif = skb->dev->ifindex;
__this_cpu_inc(softnet_data.processed);
^ permalink raw reply related
* Re: IPv6 over firewire
From: Stefan Richter @ 2013-01-12 13:57 UTC (permalink / raw)
To: stephan.gatzka; +Cc: linux1394-devel, yoshfuji, netdev
In-Reply-To: <50F140F7.60503@gmail.com>
On Jan 12 Stephan Gatzka wrote:
> > - There is another downside: Each new driver method increases the
> > memory footprint of instances of respective function pointer tables
> > by 4 or 8 bytes.
>
> I can't imagine that this is a show stopper. How many instances of
> struct netdev do we have o a typical system? I guess not the much.
There aren't many instances, but these instances are used in hot paths
where cache utilization matters. Of course such structures can be ordered
so that often used parts are located close to each other.
--
Stefan Richter
-=====-===-= ---= -==--
http://arcgraph.de/sr/
^ permalink raw reply
* [RFC PATCH 0/6] IPv6 over Firewire (PoC)
From: YOSHIFUJI Hideaki @ 2013-01-12 14:20 UTC (permalink / raw)
To: Stephan Gatzka, Stefan Richter; +Cc: netdev, linux1394-devel, yoshfuji
This is my proof of concept changes over the tree.
Code compiles, but untested.
Full changesets are also availble at:
http://www.linux-ipv6.org/gitweb/gitweb.cgi?p=gitroot/yoshfuji/linux-2.6-dev.git;a=shortlog;h=refs/heads/v3.7%2Bnet-next%2Bfirewire
I think firewire/net bits should be moved to firewire/net_core.c or something,
which is compiled statically even if FIREWIRE_NET = m.
YOSHIFUJI Hideaki (6):
ndisc: Move ndisc_opt_addr_space() to include/net/ndisc.h.
ndisc: Pass net_device to ndisc_fill_addr_option().
firewire net: Export fwnet_peerinfo structure for ieee1394-specific
peer information in ARP/NDP.
firewire net: Export peerinfo handlers.
firewire net: IPv6 support (RFC3146).
ipv6: IPv6 over IEEE1394 (RFC3146) support.
drivers/firewire/Kconfig | 8 +++
drivers/firewire/net.c | 125 ++++++++++++++++++++++++++++------------------
include/net/firewire.h | 21 ++++++++
include/net/ndisc.h | 20 +++++++-
net/ipv6/addrconf.c | 4 +-
net/ipv6/ndisc.c | 71 +++++++++++++++++++++-----
net/ipv6/route.c | 2 +
7 files changed, 188 insertions(+), 63 deletions(-)
create mode 100644 include/net/firewire.h
--
1.7.9.5
^ permalink raw reply
* [RFC PATCH 1/6] ndisc: Move ndisc_opt_addr_space() to include/net/ndisc.h.
From: YOSHIFUJI Hideaki @ 2013-01-12 14:21 UTC (permalink / raw)
To: Stephan Gatzka, Stefan Richter; +Cc: netdev, linux1394-devel, yoshfuji
ndisc_opt_addr_data() should use ndisc_opt_addr_space() and
centralizes calcuation of address space.
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
---
include/net/ndisc.h | 8 +++++++-
net/ipv6/ndisc.c | 5 -----
2 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 23b3a7c..3c53257 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -127,13 +127,19 @@ static int ndisc_addr_option_pad(unsigned short type)
}
}
+static inline int ndisc_opt_addr_space(struct net_device *dev)
+{
+ return NDISC_OPT_SPACE(dev->addr_len +
+ ndisc_addr_option_pad(dev->type));
+}
+
static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p,
struct net_device *dev)
{
u8 *lladdr = (u8 *)(p + 1);
int lladdrlen = p->nd_opt_len << 3;
int prepad = ndisc_addr_option_pad(dev->type);
- if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad))
+ if (lladdrlen != ndisc_opt_addr_space(dev))
return NULL;
return lladdr + prepad;
}
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 5733cd2..80c077c 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -143,11 +143,6 @@ struct neigh_table nd_tbl = {
.gc_thresh3 = 1024,
};
-static inline int ndisc_opt_addr_space(struct net_device *dev)
-{
- return NDISC_OPT_SPACE(dev->addr_len + ndisc_addr_option_pad(dev->type));
-}
-
static u8 *ndisc_fill_addr_option(u8 *opt, int type, void *data, int data_len,
unsigned short addr_type)
{
--
1.7.9.5
^ permalink raw reply related
* [RFC PATCH 2/6] ndisc: Pass net_device to ndisc_fill_addr_option().
From: YOSHIFUJI Hideaki @ 2013-01-12 14:21 UTC (permalink / raw)
To: Stephan Gatzka, Stefan Richter; +Cc: netdev, linux1394-devel, yoshfuji
In addition to reduction of number of arguments, this will be
used by upcoming IEEE1394 code.
CC: Stephan Gatzka <stephan.gatzka@gmail.com>
CC: Stefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
---
net/ipv6/ndisc.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 80c077c..99cd286 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -143,10 +143,11 @@ struct neigh_table nd_tbl = {
.gc_thresh3 = 1024,
};
-static u8 *ndisc_fill_addr_option(u8 *opt, int type, void *data, int data_len,
- unsigned short addr_type)
+static u8 *ndisc_fill_addr_option(u8 *opt, int type, void *data,
+ struct net_device *dev)
{
- int pad = ndisc_addr_option_pad(addr_type);
+ int pad = ndisc_addr_option_pad(dev->type);
+ int data_len = dev->addr_len;
int space = NDISC_OPT_SPACE(data_len + pad);
opt[0] = type;
@@ -415,8 +416,7 @@ static struct sk_buff *ndisc_build_skb(struct net_device *dev,
}
if (llinfo)
- ndisc_fill_addr_option(opt, llinfo, dev->dev_addr,
- dev->addr_len, dev->type);
+ ndisc_fill_addr_option(opt, llinfo, dev->dev_addr, dev);
hdr->icmp6_cksum = csum_ipv6_magic(saddr, daddr, len,
IPPROTO_ICMPV6,
@@ -1469,7 +1469,7 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
if (ha)
opt = ndisc_fill_addr_option(opt, ND_OPT_TARGET_LL_ADDR, ha,
- dev->addr_len, dev->type);
+ dev);
/*
* build redirect option and copy skb over to the new packet.
--
1.7.9.5
^ permalink raw reply related
* [RFC PATCH 3/6] firewire net: Export fwnet_peerinfo structure for ieee1394-specific peer information in ARP/NDP.
From: YOSHIFUJI Hideaki @ 2013-01-12 14:21 UTC (permalink / raw)
To: Stephan Gatzka, Stefan Richter; +Cc: netdev, linux1394-devel, yoshfuji
Peer information consists of max_rec, spd and unicast_FIFO and
the wire format is shared between IPv4 (RFC2734) and IPv6 (RFC3146).
CC: Stephan Gatzka <stephan.gatzka@gmail.com>
CC: Stefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
---
drivers/firewire/net.c | 24 ++++++++++++------------
include/net/firewire.h | 11 +++++++++++
2 files changed, 23 insertions(+), 12 deletions(-)
create mode 100644 include/net/firewire.h
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index e7a711f5..bd2d0de 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -28,6 +28,7 @@
#include <asm/unaligned.h>
#include <net/arp.h>
+#include <net/firewire.h>
/* rx limits */
#define FWNET_MAX_FRAGMENTS 30 /* arbitrary, > TX queue depth */
@@ -68,10 +69,8 @@ struct rfc2734_arp {
/* Above is exactly the same format as struct arphdr */
__be64 s_uniq_id; /* Sender's 64bit EUI */
- u8 max_rec; /* Sender's max packet size */
- u8 sspd; /* Sender's max speed */
- __be16 fifo_hi; /* hi 16bits of sender's FIFO addr */
- __be32 fifo_lo; /* lo 32bits of sender's FIFO addr */
+ struct fwnet_peerinfo info;
+
__be32 sip; /* Sender's IP Address */
__be32 tip; /* IP Address of requested hw addr */
} __packed;
@@ -547,17 +546,18 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
arp1394 = (struct rfc2734_arp *)skb->data;
arp = (struct arphdr *)skb->data;
arp_ptr = (unsigned char *)(arp + 1);
+
peer_guid = get_unaligned_be64(&arp1394->s_uniq_id);
- fifo_addr = (u64)get_unaligned_be16(&arp1394->fifo_hi) << 32
- | get_unaligned_be32(&arp1394->fifo_lo);
+ fifo_addr = (u64)get_unaligned_be16(&arp1394->info.fifo_hi) << 32
+ | get_unaligned_be32(&arp1394->info.fifo_lo);
- sspd = arp1394->sspd;
+ sspd = arp1394->info.sspd;
/* Sanity check. OS X 10.3 PPC reportedly sends 131. */
if (sspd > SCODE_3200) {
dev_notice(&net->dev, "sspd %x out of range\n", sspd);
sspd = SCODE_3200;
}
- max_payload = fwnet_max_payload(arp1394->max_rec, sspd);
+ max_payload = fwnet_max_payload(arp1394->info.max_rec, sspd);
spin_lock_irqsave(&dev->lock, flags);
peer = fwnet_peer_find_by_guid(dev, peer_guid);
@@ -1348,13 +1348,13 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
ipaddr = get_unaligned((__be32 *)(arp_ptr + FWNET_ALEN));
arp1394->hw_addr_len = RFC2734_HW_ADDR_LEN;
- arp1394->max_rec = dev->card->max_receive;
- arp1394->sspd = dev->card->link_speed;
+ arp1394->info.max_rec = dev->card->max_receive;
+ arp1394->info.sspd = dev->card->link_speed;
put_unaligned_be16(dev->local_fifo >> 32,
- &arp1394->fifo_hi);
+ &arp1394->info.fifo_hi);
put_unaligned_be32(dev->local_fifo & 0xffffffff,
- &arp1394->fifo_lo);
+ &arp1394->info.fifo_lo);
put_unaligned(ipaddr, &arp1394->sip);
}
diff --git a/include/net/firewire.h b/include/net/firewire.h
new file mode 100644
index 0000000..5e12b52
--- /dev/null
+++ b/include/net/firewire.h
@@ -0,0 +1,11 @@
+#ifndef _NET_FIREWIRE_H
+#define _NET_FIREWIRE_H
+
+struct fwnet_peerinfo {
+ u8 max_rec; /* Sender's max packet size */
+ u8 sspd; /* Sender's max speed */
+ __be16 fifo_hi; /* hi 16bits of sender's FIFO addr */
+ __be32 fifo_lo; /* lo 32bits of sender's FIFO addr */
+} __packed;
+
+#endif
--
1.7.9.5
^ permalink raw reply related
* [RFC PATCH 4/6] firewire net: Export peerinfo handlers.
From: YOSHIFUJI Hideaki @ 2013-01-12 14:21 UTC (permalink / raw)
To: Stephan Gatzka, Stefan Richter; +Cc: netdev, linux1394-devel, yoshfuji
Extract peerinfo related code into separate functions and export them.
CC: Stephan Gatzka <stephan.gatzka@gmail.com>
CC: Stefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
---
drivers/firewire/net.c | 106 ++++++++++++++++++++++++++++--------------------
include/net/firewire.h | 10 +++++
2 files changed, 73 insertions(+), 43 deletions(-)
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index bd2d0de..66c4f1c 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -506,6 +506,50 @@ static unsigned fwnet_max_payload(unsigned max_rec, unsigned speed)
return (1 << (max_rec + 1)) - RFC2374_FRAG_HDR_SIZE;
}
+struct fwnet_peer *fwnet_update_peerinfo(struct net_device *net,
+ __be64 *s_uniq_id,
+ const struct fwnet_peerinfo *info)
+{
+ struct fwnet_device *dev = netdev_priv(net);
+ u64 peer_guid;
+ u64 fifo_addr;
+ unsigned sspd;
+ u16 max_payload;
+ unsigned long flags;
+ struct fwnet_peer *peer;
+
+ peer_guid = get_unaligned_be64(s_uniq_id);
+ fifo_addr = (u64)get_unaligned_be16(&info->fifo_hi) << 32
+ | get_unaligned_be32(&info->fifo_lo);
+
+ sspd = info->sspd;
+ /* Sanity check. OS X 10.3 PPC reportedly sends 131. */
+ if (sspd > SCODE_3200) {
+ dev_notice(&net->dev, "sspd %x out of range\n", sspd);
+ sspd = SCODE_3200;
+ }
+ max_payload = fwnet_max_payload(info->max_rec, sspd);
+
+ spin_lock_irqsave(&dev->lock, flags);
+ peer = fwnet_peer_find_by_guid(dev, peer_guid);
+ if (peer) {
+ peer->fifo = fifo_addr;
+
+ if (peer->speed > sspd)
+ peer->speed = sspd;
+ if (peer->max_payload > max_payload)
+ peer->max_payload = max_payload;
+ }
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ if (!peer)
+ dev_notice(&net->dev,
+ "no peer for ARP packet from %016llx\n",
+ (unsigned long long)peer_guid);
+
+ return peer;
+}
+EXPORT_SYMBOL(fwnet_update_peerinfo);
static int fwnet_finish_incoming_packet(struct net_device *net,
struct sk_buff *skb, u16 source_node_id,
@@ -536,49 +580,16 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
struct rfc2734_arp *arp1394;
struct arphdr *arp;
unsigned char *arp_ptr;
- u64 fifo_addr;
- u64 peer_guid;
- unsigned sspd;
- u16 max_payload;
struct fwnet_peer *peer;
- unsigned long flags;
arp1394 = (struct rfc2734_arp *)skb->data;
arp = (struct arphdr *)skb->data;
arp_ptr = (unsigned char *)(arp + 1);
- peer_guid = get_unaligned_be64(&arp1394->s_uniq_id);
- fifo_addr = (u64)get_unaligned_be16(&arp1394->info.fifo_hi) << 32
- | get_unaligned_be32(&arp1394->info.fifo_lo);
-
- sspd = arp1394->info.sspd;
- /* Sanity check. OS X 10.3 PPC reportedly sends 131. */
- if (sspd > SCODE_3200) {
- dev_notice(&net->dev, "sspd %x out of range\n", sspd);
- sspd = SCODE_3200;
- }
- max_payload = fwnet_max_payload(arp1394->info.max_rec, sspd);
-
- spin_lock_irqsave(&dev->lock, flags);
- peer = fwnet_peer_find_by_guid(dev, peer_guid);
- if (peer) {
- peer->fifo = fifo_addr;
-
- if (peer->speed > sspd)
- peer->speed = sspd;
- if (peer->max_payload > max_payload)
- peer->max_payload = max_payload;
-
- peer->ip = arp1394->sip;
- }
- spin_unlock_irqrestore(&dev->lock, flags);
-
- if (!peer) {
- dev_notice(&net->dev,
- "no peer for ARP packet from %016llx\n",
- (unsigned long long)peer_guid);
+ peer = fwnet_update_peerinfo(net, &arp1394->s_uniq_id, &arp1394->info);
+ if (!peer)
goto no_peer;
- }
+ peer->ip = arp1394->sip;
/*
* Now that we're done with the 1394 specific stuff, we'll
@@ -1264,6 +1275,19 @@ static int fwnet_stop(struct net_device *net)
return 0;
}
+void fwnet_fill_peerinfo(const struct net_device *net, const __be64 *s_uniq_id,
+ struct fwnet_peerinfo *info)
+{
+ struct fwnet_device *dev = netdev_priv(net);
+
+ info->max_rec = dev->card->max_receive;
+ info->sspd = dev->card->link_speed;
+
+ put_unaligned_be16(dev->local_fifo >> 32, &info->fifo_hi);
+ put_unaligned_be32(dev->local_fifo & 0xffffffff, &info->fifo_lo);
+}
+EXPORT_SYMBOL(fwnet_fill_peerinfo);
+
static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
{
struct fwnet_header hdr_buf;
@@ -1347,14 +1371,10 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
ipaddr = get_unaligned((__be32 *)(arp_ptr + FWNET_ALEN));
- arp1394->hw_addr_len = RFC2734_HW_ADDR_LEN;
- arp1394->info.max_rec = dev->card->max_receive;
- arp1394->info.sspd = dev->card->link_speed;
+ arp1394->hw_addr_len = RFC2734_HW_ADDR_LEN;
+
+ fwnet_fill_peerinfo(net, NULL, &arp1394->info);
- put_unaligned_be16(dev->local_fifo >> 32,
- &arp1394->info.fifo_hi);
- put_unaligned_be32(dev->local_fifo & 0xffffffff,
- &arp1394->info.fifo_lo);
put_unaligned(ipaddr, &arp1394->sip);
}
diff --git a/include/net/firewire.h b/include/net/firewire.h
index 5e12b52..6f746d1 100644
--- a/include/net/firewire.h
+++ b/include/net/firewire.h
@@ -8,4 +8,14 @@ struct fwnet_peerinfo {
__be32 fifo_lo; /* lo 32bits of sender's FIFO addr */
} __packed;
+struct fwnet_peer;
+
+extern struct fwnet_peer *fwnet_update_peerinfo(struct net_device *net,
+ __be64 *s_uniq_id,
+ const struct fwnet_peerinfo *info);
+
+extern void fwnet_fill_peerinfo(const struct net_device *net,
+ const __be64 *s_uniq_id,
+ struct fwnet_peerinfo *info);
+
#endif
--
1.7.9.5
^ permalink raw reply related
* [RFC PATCH 5/6] firewire net: IPv6 support (RFC3146).
From: YOSHIFUJI Hideaki @ 2013-01-12 14:21 UTC (permalink / raw)
To: Stephan Gatzka, Stefan Richter; +Cc: netdev, linux1394-devel, yoshfuji
Send packets for IPv6 multicast via GASP.
CC: Stephan Gatzka <stephan.gatzka@gmail.com>
CC: Stefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
---
drivers/firewire/Kconfig | 8 ++++++++
drivers/firewire/net.c | 13 ++++++++++---
2 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig
index 7224533..2e3018b 100644
--- a/drivers/firewire/Kconfig
+++ b/drivers/firewire/Kconfig
@@ -51,9 +51,17 @@ config FIREWIRE_NET
other implementations of RFC 2734 as found on several operating
systems. Multicast support is currently limited.
+ Optional IPv6 support is available if you say Y here.
+
To compile this driver as a module, say M here: The module will be
called firewire-net.
+config FIREWIRE_NET_IPV6
+ bool "IPv6 networking over 1394"
+ depends on FIREWIRE_NET=y
+ help
+ This enabless IPv6 over IEEE 1394, based on RFC 3146.
+
config FIREWIRE_NOSY
tristate "Nosy - a FireWire traffic sniffer for PCILynx cards"
depends on PCI
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 66c4f1c..a21d2f9 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -27,6 +27,8 @@
#include <linux/spinlock.h>
#include <asm/unaligned.h>
+#include <linux/ipv6.h>
+#include <net/addrconf.h>
#include <net/arp.h>
#include <net/firewire.h>
@@ -1329,13 +1331,18 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
dg_size = skb->len;
/*
- * Set the transmission type for the packet. ARP packets and IP
- * broadcast packets are sent via GASP.
+ * Set the transmission type for the packet. ARP packets, IPv4
+ * broadcast packets, IPv6 multicast packets are sent via GASP.
*/
if (memcmp(hdr_buf.h_dest, net->broadcast, FWNET_ALEN) == 0
|| proto == htons(ETH_P_ARP)
|| (proto == htons(ETH_P_IP)
- && IN_MULTICAST(ntohl(ip_hdr(skb)->daddr)))) {
+ && IN_MULTICAST(ntohl(ip_hdr(skb)->daddr)))
+#if defined(CONFIG_FIREWIRE_NET_IPV6)
+ || (proto == htons(ETH_P_IPV6)
+ && ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr))
+#endif
+ ) {
max_payload = dev->broadcast_xmt_max_payload;
datagram_label_ptr = &dev->broadcast_xmt_datagramlabel;
--
1.7.9.5
^ permalink raw reply related
* [RFC PATCH 6/6] ipv6: IPv6 over IEEE1394 (RFC3146) support.
From: YOSHIFUJI Hideaki @ 2013-01-12 14:21 UTC (permalink / raw)
To: Stephan Gatzka, Stefan Richter; +Cc: netdev, linux1394-devel, yoshfuji
CC: Stephan Gatzka <stephan.gatzka@gmail.com>
CC: Stefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
---
include/net/ndisc.h | 14 +++++++++++-
net/ipv6/addrconf.c | 4 +++-
net/ipv6/ndisc.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++----
net/ipv6/route.c | 2 ++
4 files changed, 74 insertions(+), 6 deletions(-)
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 3c53257..1de4e0c 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -52,6 +52,7 @@ enum {
#include <linux/hash.h>
#include <net/neighbour.h>
+#include <net/firewire.h>
struct ctl_table;
struct inet6_dev;
@@ -127,10 +128,19 @@ static int ndisc_addr_option_pad(unsigned short type)
}
}
+static int ndisc_addr_option_postpad(unsigned short type)
+{
+ switch (type) {
+ case ARPHRD_IEEE1394: return sizeof(struct fwnet_peerinfo);
+ default: return 0;
+ }
+}
+
static inline int ndisc_opt_addr_space(struct net_device *dev)
{
return NDISC_OPT_SPACE(dev->addr_len +
- ndisc_addr_option_pad(dev->type));
+ ndisc_addr_option_pad(dev->type) +
+ ndisc_addr_option_postpad(dev->type));
}
static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p,
@@ -203,6 +213,8 @@ extern void ndisc_send_redirect(struct sk_buff *skb,
extern int ndisc_mc_map(const struct in6_addr *addr, char *buf,
struct net_device *dev, int dir);
+extern void ndisc_update_peerinfo(struct net_device *dev,
+ void *lladdr);
/*
* IGMP
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 408cac4a..9a0728a 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1729,6 +1729,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
case ARPHRD_IPGRE:
return addrconf_ifid_gre(eui, dev);
case ARPHRD_IEEE802154:
+ case ARPHRD_IEEE1394:
return addrconf_ifid_eui64(eui, dev);
}
return -1;
@@ -2571,7 +2572,8 @@ static void addrconf_dev_config(struct net_device *dev)
(dev->type != ARPHRD_FDDI) &&
(dev->type != ARPHRD_ARCNET) &&
(dev->type != ARPHRD_INFINIBAND) &&
- (dev->type != ARPHRD_IEEE802154)) {
+ (dev->type != ARPHRD_IEEE802154) &&
+ (dev->type != ARPHRD_IEEE1394)) {
/* Alas, we support only Ethernet autoconfiguration. */
return;
}
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 99cd286..9a0ba9c 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -72,6 +72,8 @@
#include <linux/netfilter.h>
#include <linux/netfilter_ipv6.h>
+#include <net/firewire.h>
+
/* Set to 3 to get tracing... */
#define ND_DEBUG 1
@@ -143,6 +145,22 @@ struct neigh_table nd_tbl = {
.gc_thresh3 = 1024,
};
+#if defined(CONFIG_FIREWIRE_NET)
+static u8 *__ndisc_fill_addr_option_firewire_postpad(u8 *opt, int space, void *data,
+ struct net_device *dev)
+{
+ if (likely(space >= sizeof(struct fwnet_peerinfo))) {
+ fwnet_fill_peerinfo(dev, (__be64 *)data, (struct fwnet_peerinfo *)opt);
+ opt += sizeof(struct fwnet_peerinfo);
+ space -= sizeof(struct fwnet_peerinfo);
+ }
+ if (space > 0)
+ memset(opt, 0, space);
+
+ return opt + space;
+}
+#endif
+
static u8 *ndisc_fill_addr_option(u8 *opt, int type, void *data,
struct net_device *dev)
{
@@ -160,9 +178,20 @@ static u8 *ndisc_fill_addr_option(u8 *opt, int type, void *data,
memcpy(opt+2, data, data_len);
data_len += 2;
opt += data_len;
- if ((space -= data_len) > 0)
- memset(opt, 0, space);
- return opt + space;
+
+ if ((space -= data_len) > 0) {
+ switch (dev->type) {
+#if defined(CONFIG_FIREWIRE_NET)
+ case ARPHRD_IEEE1394:
+ opt = __ndisc_fill_addr_option_firewire_postpad(opt, space,
+ data, dev);
+#endif
+ default:
+ memset(opt, 0, space);
+ opt += space;
+ }
+ }
+ return opt;
}
static struct nd_opt_hdr *ndisc_next_option(struct nd_opt_hdr *cur,
@@ -366,6 +395,19 @@ static void pndisc_destructor(struct pneigh_entry *n)
ipv6_dev_mc_dec(dev, &maddr);
}
+void ndisc_update_peerinfo(struct net_device *dev, void *lladdr)
+{
+#if defined(CONFIG_FIREWIRE_NET)
+ switch (dev->type) {
+ case ARPHRD_IEEE1394:
+ fwnet_update_peerinfo(dev, lladdr, (struct fwnet_peerinfo *)((__u64 *)lladdr + 1));
+ break;
+ default:
+ break;
+ }
+#endif
+}
+
static struct sk_buff *ndisc_build_skb(struct net_device *dev,
const struct in6_addr *daddr,
const struct in6_addr *saddr,
@@ -798,6 +840,9 @@ static void ndisc_recv_ns(struct sk_buff *skb)
neigh_update(neigh, lladdr, NUD_STALE,
NEIGH_UPDATE_F_WEAK_OVERRIDE|
NEIGH_UPDATE_F_OVERRIDE);
+
+ ndisc_update_peerinfo(dev, lladdr);
+
if (neigh || !dev->header_ops) {
ndisc_send_na(dev, neigh, saddr, &msg->target,
is_router,
@@ -905,6 +950,8 @@ static void ndisc_recv_na(struct sk_buff *skb)
NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
(msg->icmph.icmp6_router ? NEIGH_UPDATE_F_ISROUTER : 0));
+ ndisc_update_peerinfo(dev, lladdr);
+
if ((old_flags & ~neigh->flags) & NTF_ROUTER) {
/*
* Change: router to host
@@ -970,6 +1017,8 @@ static void ndisc_recv_rs(struct sk_buff *skb)
NEIGH_UPDATE_F_OVERRIDE|
NEIGH_UPDATE_F_OVERRIDE_ISROUTER);
neigh_release(neigh);
+
+ ndisc_update_peerinfo(skb->dev, lladdr);
}
out:
return;
@@ -1223,6 +1272,8 @@ skip_linkparms:
NEIGH_UPDATE_F_OVERRIDE|
NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
NEIGH_UPDATE_F_ISROUTER);
+
+ ndisc_update_peerinfo(skb->dev, lladdr);
}
if (!ipv6_accept_ra(in6_dev))
@@ -1405,7 +1456,8 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
if (!ret)
goto release;
- if (dev->addr_len) {
+ /* XXX* We have not idea about IEEE1394 peer infomation */
+ if (dev->addr_len && dev->type != ARPHRD_IEEE1394) {
struct neighbour *neigh = dst_neigh_lookup(skb_dst(skb), target);
if (!neigh) {
ND_PRINTK(2, warn,
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 621b68e..27c5127 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1795,6 +1795,8 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
NEIGH_UPDATE_F_ISROUTER))
);
+ ndisc_update_peerinfo(skb->dev, lladdr);
+
nrt = ip6_rt_copy(rt, &msg->dest);
if (!nrt)
goto out;
--
1.7.9.5
^ permalink raw reply related
* Re: IPv6 over firewire
From: Stefan Richter @ 2013-01-12 14:37 UTC (permalink / raw)
To: stephan.gatzka; +Cc: linux1394-devel, yoshfuji, netdev
In-Reply-To: <50F140F7.60503@gmail.com>
On Jan 12 Stephan Gatzka wrote:
> > Or the (optional!) callback could be a new member of struct ndisc_options.
>
> Hm, right now I have no opinion on that. Where does
> whatever_type *callback comes from? Is it an exported method of the
> firewire net driver or the new function pointer in struct netdevice?
The networking core or IPv6 core would never ever use an EXPORT() from an
interface driver like firewire-net or from a bus architecture driver like
firewire-core.
The interface driver uses definitions and declarations from the networking/
IP/ ARP... core:
- functions implemented in the core and EXPORTed from there,
- data types defined in core headers and filled with data by the
interface driver,
- callback function types defined in core headers, used in data types
which are defined in core headers; respective callbacks implemented in
interface drivers, pointers to the implementations filled in by the
interface drivers into respective data objects.
So the firewire-net bridge driver uses the firewire-core API below it and
the networking and IP APIs above it.
Whether a callback is needed at all is not obvious to me. If one is
needed, then it is not obvious to me whether it should be reachable via a
function pointer in struct net_device, or via a function pointer in one of
the pointer table structs that are appended to struct net_device, or via a
function pointer in e.g. struct ndisc_options, or via a function pointer
typed argument of a function which is EXPORTed by the networking/ IPv6
core.
> > However, does net/ipv6/ndisc.c really need to be aware of the RFC 3146
> > Neighbor Discovery related packet header layouts? Isn't it possible to
> > rewrite these headers in-place in drivers/firewire/net.c?
>
>
> Yes, it it possible, but yoshfuji strongly voted against rewriting ndisc
> packets in firewire net driver to maintain extensibility to protocols.
> Especially IPSEC can just not work if I rewrite the packets in the driver.
OK, then net/ipv6/ndisc.c shall be taught to write (and read?) those
packets, and drivers/firewire/net.c shall fill in all data that are going
to be needed by ndisc.c into new arguments of existing or new exported
core functions, or into new members of whichever networking struct
would be most suitable for that. Or the networking core gets to those
data indirectly by calling a callback.
Apparently the Linux IPv6 core needs to learn a little bit about RFC 3146.
But it doesn't need to (and should not) learn anything about the Linux
IEEE 1394 implementation, that's what I am trying to convey. :-)
--
Stefan Richter
-=====-===-= ---= -==--
http://arcgraph.de/sr/
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox