* Re: [PATCH] gianfar: Fix possible overrun and simplify interrupt name field creation
From: Paul Gortmaker @ 2012-03-23 23:37 UTC (permalink / raw)
To: David Miller; +Cc: joe, netdev, linux-kernel, sandeep.kumar
In-Reply-To: <20120322.233426.51094636300419378.davem@davemloft.net>
On Thu, Mar 22, 2012 at 11:34 PM, David Miller <davem@davemloft.net> wrote:
> From: David Miller <davem@davemloft.net>
> Date: Wed, 21 Mar 2012 22:34:57 -0400 (EDT)
>
>> From: Joe Perches <joe@perches.com>
>> Date: Sat, 17 Mar 2012 12:05:38 -0700
>>
>>> Space allocated for int_name_<foo> is unsufficient for
>>> maximal device name, expand it.
>>>
>>> Code to create int_name_<foo> is obscure, simplify it
>>> by using sprintf.
>>>
>>> Found by looking for unnecessary \ line continuations.
>>> Uncompiled, untested.
>>>
>>> Signed-off-by: Joe Perches <joe@perches.com>
>>
>> Can a gianfar expert please review and test this patch?
>
> If you gianfar guys don't show a sign of life in the next 24 hours I'm
> just going to apply Joe's patch as-is. I refuse to just let it rot in
> patchwork like this.
>
> And then you don't get to complain if his change breaks your driver
> because I asked multiple times for testing and/or review.
I don't claim to be a giant fart expert, but the sbc8641D has 4 of
the gianfar ports, and so I can use that hardware to look into
testing this on a real board and check that a cat /proc/interrupts
doesn't do something evil this weekend. The patch looks sane in
that it culls lines of open coded junk... FWIW.
Paul.
^ permalink raw reply
* Re: [RFC PATCH 1/1] NUMA aware scheduling per cpu vhost thread
From: David Ahern @ 2012-03-23 23:45 UTC (permalink / raw)
To: Thomas Lendacky; +Cc: Shirley Ma, Michael S. Tsirkin, netdev, kvm
In-Reply-To: <1510318.F8gXLSD366@tomlt1.ibmoffice.com>
On 3/23/12 12:32 PM, Thomas Lendacky wrote:
> Quick description of the tests:
> TCP_RR and UDP_RR using 256 byte request/response size in 1, 10, 30
> and 60 instances
> TCP_STREAM and TCP_MAERTS using 256, 1K, 4K and 16K message sizes
> and 1 and 4 instances
>
> Remote host to VM using 1, 4, 12 and 24 VMs (2 vCPUs) with the tests
> running between an external host and each VM.
>
> Local VM to VM using 2, 4, 12 and 24 VMs (2 vCPUs) with the tests
> running between VM pairs on the same host (no TCP_MAERTS done in
> this situation).
>
> For TCP_RR and UDP_RR tests I report the transaction rate as the
> score and the transaction rate / KVMhost CPU% as the efficiency.
>
> For TCP_STREAM and TCP_MAERTS tests I report the throughput in Mbps
> as the score and the throughput / KVMhost CPU% as the efficiency.
Would you mind sharing the netperf commands you are running and an
example of the math done to arrive at the summaries presented?
David
^ permalink raw reply
* [GIT PULL] sysctl updates for 3.4-rc1
From: Eric W. Biederman @ 2012-03-23 23:48 UTC (permalink / raw)
To: Linus Torvalds
Cc: linux-kernel, linux-fsdevel, netdev, Lucian Adrian Grijincu
Linus,
please pull sysctl updates for v3.4-rc1 from:
git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/sysctl.git master
This tree is against v3.3-rc1 aka dcd6c92267155e70a94b3927bce681ce74b80d1f
The topmost commit is 4e474a00d7ff746ed177ddae14fa8b2d4bad7a00
Highlights:
- Rewrite of sysctl for speed and clarity.
Insert/remove/Lookup in sysctl are all now O(NlogN) operations, and
are no longer bottlenecks in the process of adding and removing
network devices.
sysctl is now focused on being a filesystem instead of system call
and the code can all be found in fs/proc/proc_sysctl.c. Hopefully
this means the code is now approachable.
Much thanks is owed to Lucian Grinjincu for keeping at this until
something was found that was usable.
- The recent proc_sys_poll oops found by the fuzzer during hibernation
is fixed.
Dan Carpenter (2):
sysctl: remove an unused variable
sysctl: fix memset parameters in setup_sysctl_set()
Eric W. Biederman (32):
sysctl: Consolidate !CONFIG_SYSCTL handling
sysctl: Register the base sysctl table like any other sysctl table.
sysctl: Move the implementation into fs/proc/proc_sysctl.c
sysctl: Make the directories have nlink == 1
sysctl: Implement retire_sysctl_set
sysctl: Remove the unnecessary sysctl_set parent concept.
sysctl: Create local copies of directory names used in paths
sysctl: Add support for register sysctl tables with a normal cstring path.
sysctl: Add ctl_table chains into cstring paths
sysctl: register only tables of sysctl files
sysctl: Improve the sysctl sanity checks
sysctl: Remove the now unused ctl_table parent field.
sysctl: A more obvious version of grab_header.
sysctl: Initial support for auto-unregistering sysctl tables.
sysctl: Factor out init_header from __register_sysctl_paths
sysctl: Factor out insert_header and erase_header
sysctl: Normalize the root_table data structure.
sysctl: Rewrite proc_sys_lookup introducing find_entry and lookup_entry.
sysctl: Rewrite proc_sys_readdir in terms of first_entry and next_entry
sysctl: Add a root pointer to ctl_table_set
sysctl: Stop requiring explicit management of sysctl directories
sysctl: Add sysctl_print_dir and use it in get_subdir
sysctl: Replace root_list with links between sysctl_table_sets.
sysctl: Modify __register_sysctl_paths to take a set instead of a root and an nsproxy
sysctl: Move sysctl_check_dups into insert_header
sysctl: Make the header lists per directory.
sysctl: Index sysctl directories with rbtrees.
sysctl: Add register_sysctl for normal sysctl users
sysctl: An easier to read version of find_subdir
sysctl: Correct error return from get_subdir
sysctl: Comments to make the code clearer.
sysctl: Don't call sysctl_follow_link unless we are a link.
Lucas De Marchi (2):
sysctl: remove impossible condition check
sysctl: protect poll() in entries that may go away
fs/proc/internal.h | 3 +
fs/proc/proc_sysctl.c | 1274 +++++++++++++++++++++++++++++++++++++++++++++---
include/linux/sysctl.h | 106 +++--
kernel/Makefile | 1 -
kernel/sysctl.c | 501 +-------------------
kernel/sysctl_check.c | 160 ------
lib/Kconfig.debug | 8 -
net/sysctl_net.c | 24 +-
8 files changed, 1280 insertions(+), 797 deletions(-)
^ permalink raw reply
* [PATCH] iwlwifi: fix skb truesize underestimation
From: Eric Dumazet @ 2012-03-24 0:05 UTC (permalink / raw)
To: David Miller; +Cc: netdev, wey-yi.w.guy, Neal Cardwell, John W. Linville
In-Reply-To: <1332528919.2516.2.camel@edumazet-glaptop>
By default, iwlwifi uses order-1 pages (8 KB) to store incoming frames,
but doesnt say so in skb->truesize.
This makes very possible to exhaust kernel memory since these skb evade
normal socket memory accounting.
As struct ieee80211_hdr is going to be pulled before calling IP stack,
there is no need to use dev_alloc_skb() to reserve NET_SKB_PAD bytes.
alloc_skb() is ok in this driver, allowing more tailroom.
Pull beginning of frame in skb header, in the hope we can reuse order-1
pages in the driver immediately for small frames and reduce their
truesize to the minimum (linear skbs)
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Cc: "John W. Linville" <linville@tuxdriver.com>
Cc: Neal Cardwell <ncardwell@google.com>
---
Depends on the "net: add a truesize parameter to skb_add_rx_frag()"
prior patch.
drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 25 ++++++++-----
drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 3 +
drivers/net/wireless/iwlwifi/iwl-trans.h | 1
3 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index f4b84d1..9ecd768f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -773,8 +773,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
struct sk_buff *skb;
__le16 fc = hdr->frame_control;
struct iwl_rxon_context *ctx;
- struct page *p;
- int offset;
+ unsigned int hdrlen;
/* We only process data packets if the interface is open */
if (unlikely(!priv->is_open)) {
@@ -788,16 +787,24 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
iwlagn_set_decrypted_flag(priv, hdr, ampdu_status, stats))
return;
- skb = dev_alloc_skb(128);
+ /* Dont use dev_alloc_skb(), we'll have enough headroom once
+ * ieee80211_hdr pulled.
+ */
+ skb = alloc_skb(128);
if (!skb) {
- IWL_ERR(priv, "dev_alloc_skb failed\n");
+ IWL_ERR(priv, "alloc_skb failed\n");
return;
}
-
- offset = (void *)hdr - rxb_addr(rxb);
- p = rxb_steal_page(rxb);
- skb_add_rx_frag(skb, 0, p, offset, len, len);
-
+ hdrlen = min_t(unsigned int, len, skb_tailroom(skb));
+ memcpy(skb_put(skb, hdrlen), hdr, hdrlen);
+ len -= hdrlen;
+
+ if (len) {
+ int offset = (void *)hdr + hdrlen - rxb_addr(rxb);
+
+ skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset,
+ len, rxb->truesize);
+ }
iwl_update_stats(priv, false, fc, len);
/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
index 8b1a798..aa7aea1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
@@ -374,8 +374,9 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
if (WARN_ON(!rxb))
return;
+ rxcb.truesize = PAGE_SIZE << hw_params(trans).rx_page_order;
dma_unmap_page(trans->dev, rxb->page_dma,
- PAGE_SIZE << hw_params(trans).rx_page_order,
+ rxcb.truesize,
DMA_FROM_DEVICE);
rxcb._page = rxb->page;
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 0c81cba..fdf9788 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -260,6 +260,7 @@ static inline void iwl_free_resp(struct iwl_host_cmd *cmd)
struct iwl_rx_cmd_buffer {
struct page *_page;
+ unsigned int truesize;
};
static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r)
^ permalink raw reply related
* Re: [PATCH] iwlwifi: fix skb truesize underestimation
From: Eric Dumazet @ 2012-03-24 0:22 UTC (permalink / raw)
To: David Miller; +Cc: netdev, wey-yi.w.guy, Neal Cardwell, John W. Linville
In-Reply-To: <1332547547.2516.132.camel@edumazet-glaptop>
On Fri, 2012-03-23 at 17:05 -0700, Eric Dumazet wrote:
> + if (len) {
> + int offset = (void *)hdr + hdrlen - rxb_addr(rxb);
> +
> + skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset,
> + len, rxb->truesize);
> + }
> iwl_update_stats(priv, false, fc, len);
>
Please delete this patch, I'll send a v2 : iwl_update_stats() should be
called with original "len", not "len - hdrlen"
^ permalink raw reply
* [PATCH v2] iwlwifi: fix skb truesize underestimation
From: Eric Dumazet @ 2012-03-24 0:29 UTC (permalink / raw)
To: David Miller; +Cc: netdev, wey-yi.w.guy, Neal Cardwell, John W. Linville
In-Reply-To: <1332548545.2516.134.camel@edumazet-glaptop>
By default, iwlwifi uses order-1 pages (8 KB) to store incoming frames,
but doesnt say so in skb->truesize.
This makes very possible to exhaust kernel memory since these skb evade
normal socket memory accounting.
As struct ieee80211_hdr is going to be pulled before calling IP stack,
there is no need to use dev_alloc_skb() to reserve NET_SKB_PAD bytes.
alloc_skb() is ok in this driver, allowing more tailroom.
Pull beginning of frame in skb header, in the hope we can reuse order-1
pages in the driver immediately for small frames and reduce their
truesize to the minimum (linear skbs)
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Cc: "John W. Linville" <linville@tuxdriver.com>
Cc: Neal Cardwell <ncardwell@google.com>
---
Depends on the "net: add a truesize parameter to skb_add_rx_frag()"
prior patch.
v2: fix the iwl_update_stats() call
drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 25 ++++++++-----
drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 3 +
drivers/net/wireless/iwlwifi/iwl-trans.h | 1
3 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index f4b84d1..19a9499 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -773,8 +773,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
struct sk_buff *skb;
__le16 fc = hdr->frame_control;
struct iwl_rxon_context *ctx;
- struct page *p;
- int offset;
+ unsigned int hdrlen, fraglen;
/* We only process data packets if the interface is open */
if (unlikely(!priv->is_open)) {
@@ -788,16 +787,24 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
iwlagn_set_decrypted_flag(priv, hdr, ampdu_status, stats))
return;
- skb = dev_alloc_skb(128);
+ /* Dont use dev_alloc_skb(), we'll have enough headroom once
+ * ieee80211_hdr pulled.
+ */
+ skb = alloc_skb(128, GFP_ATOMIC);
if (!skb) {
- IWL_ERR(priv, "dev_alloc_skb failed\n");
+ IWL_ERR(priv, "alloc_skb failed\n");
return;
}
-
- offset = (void *)hdr - rxb_addr(rxb);
- p = rxb_steal_page(rxb);
- skb_add_rx_frag(skb, 0, p, offset, len, len);
-
+ hdrlen = min_t(unsigned int, len, skb_tailroom(skb));
+ memcpy(skb_put(skb, hdrlen), hdr, hdrlen);
+ fraglen = len - hdrlen;
+
+ if (fraglen) {
+ int offset = (void *)hdr + hdrlen - rxb_addr(rxb);
+
+ skb_add_rx_frag(skb, 0, rxb_steal_page(rxb), offset,
+ fraglen, rxb->truesize);
+ }
iwl_update_stats(priv, false, fc, len);
/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
index 8b1a798..aa7aea1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
@@ -374,8 +374,9 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
if (WARN_ON(!rxb))
return;
+ rxcb.truesize = PAGE_SIZE << hw_params(trans).rx_page_order;
dma_unmap_page(trans->dev, rxb->page_dma,
- PAGE_SIZE << hw_params(trans).rx_page_order,
+ rxcb.truesize,
DMA_FROM_DEVICE);
rxcb._page = rxb->page;
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 0c81cba..fdf9788 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -260,6 +260,7 @@ static inline void iwl_free_resp(struct iwl_host_cmd *cmd)
struct iwl_rx_cmd_buffer {
struct page *_page;
+ unsigned int truesize;
};
static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r)
^ permalink raw reply related
* Re: [PATCH linux-next] dmaengine: add context parameter fixups
From: Mark Brown @ 2012-03-24 0:53 UTC (permalink / raw)
To: Alexandre Bounine
Cc: fabio.estevam, alsa-devel, samuel, vinod.koul, netdev,
linux-kernel, paul.gortmaker, linux-next, tiwai, dan.j.williams,
lrg
In-Reply-To: <1332511242-30241-1-git-send-email-alexandre.bounine@idt.com>
[-- Attachment #1.1: Type: text/plain, Size: 326 bytes --]
On Fri, Mar 23, 2012 at 10:00:42AM -0400, Alexandre Bounine wrote:
> This patch fixes drivers that use device_prep_slave_sg() and
> device_prep_dma_cyclic() interfaces and have been missed during the initial
> release of interface changing patches.
Can you please send a separate patch for the ASoC (sound/soc) bits of
this?
[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply
* Re: [PATCH net V4 2/2] igb: offer a PTP Hardware Clock instead of the timecompare method
From: Richard Cochran @ 2012-03-24 6:51 UTC (permalink / raw)
To: chetan loke
Cc: e1000-devel@lists.sourceforge.net, netdev@vger.kernel.org,
Ronciak, John, john.stultz@linaro.org, Keller, Jacob E,
tglx@linutronix.de
In-Reply-To: <CAAsGZS460uazL5n=oc3DwWKqeuTtNdQROGXQrPbs=Qh92TpnDg@mail.gmail.com>
On Fri, Mar 23, 2012 at 03:39:08PM -0400, chetan loke wrote:
>
> So, how is it working today? Because we could have tx and rx
> completions on different CPUs. Is it not possible to have the
> following race today - between timecompare_update->timecompare_offset
> -> timecounter_readdelta of say Rx and timecounter_cyc2time from Tx?
I works (in the igb) because of the spinlock. You know, that thing
that you are so against using.
> So yes, rate limiting ioctls seems like a good idea.
No, that is a terrible idea.
> How about rate limiting at the PHC class driver level? And then it
> will work across the board for all the adapters at the device level.
No, don't go there. Enough bikeshedding already. If you have a serious
performance issue, please post a test case, and we will look for a
solution.
Thanks,
Richard
------------------------------------------------------------------------------
This SF email is sponsosred by:
Try Windows Azure free for 90 days Click Here
http://p.sf.net/sfu/sfd2d-msazure
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired
^ permalink raw reply
* Re: [PATCH] e1000e: clear REQ and GNT in EECD (82571 && 82572)
From: Jeff Kirsher @ 2012-03-24 9:13 UTC (permalink / raw)
To: Richard Alpe
Cc: jesse.brandeburg, bruce.w.allan, carolyn.wyborny,
donald.c.skidmore, gregory.v.rose, peter.p.waskiewicz.jr,
alexander.h.duyck, john.ronciak, e1000-devel, netdev,
linux-kernel
In-Reply-To: <1332507320-19902-1-git-send-email-richard.alpe@ericsson.com>
[-- Attachment #1: Type: text/plain, Size: 834 bytes --]
On Fri, 2012-03-23 at 13:55 +0100, Richard Alpe wrote:
> Clear the REQ and GNT bit in the eeprom control register (EECD).
> This is required if the eeprom is to be accessed with auto read
> EERD register.
>
> After a cold reset this doesn't matter but if PBIST MAC test was
> executed before booting, the register was left in a dirty state
> (the 2 bits where set), which caused the read operation to time out
> and returning 0.
>
> Reference (page 312):
> http://download.intel.com/design/network/manuals/316080.pdf
>
> Reported-by: Aleksandar Igic <aleksandar.igic@dektech.com.au>
> Signed-off-by: Richard Alpe <richard.alpe@ericsson.com>
> ---
> drivers/net/ethernet/intel/e1000e/82571.c | 11 +++++++++++
> 1 files changed, 11 insertions(+), 0 deletions(-)
Thank you, I will add the patch to my queue.
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [PATCH 03/10] stmmac: sanitize the rx coe and add the type-1 csum
From: deepaksi @ 2012-03-24 9:21 UTC (permalink / raw)
To: Giuseppe CAVALLARO
Cc: netdev@vger.kernel.org, davem@davemloft.net, Srinivas KANDAGATLA,
spear-devel, Shiraz HASHIM, Viresh KUMAR,
bhutchings@solarflare.com
In-Reply-To: <1332493721-28309-4-git-send-email-peppe.cavallaro@st.com>
On 3/23/2012 2:38 PM, Giuseppe CAVALLARO wrote:
> [snip]
>
>
> - priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
> - if (priv->rx_coe)
> - pr_info(" RX Checksum Offload Engine supported\n");
> + if (priv->plat->rx_coe)
> + pr_info(" RX Checksum Offload Engine supported (type %d)\n",
> + priv->plat->rx_coe);
> if (priv->plat->tx_coe)
> pr_info(" TX Checksum insertion supported\n");
>
rx_coe needs to be enabled. Earlier it was being done. Any specific
reasons to remove this.
Instead this code needs to be moved post mac reset has been done.
Regards
Deepak
^ permalink raw reply
* Re: [PATCH] net: add a truesize parameter to skb_add_rx_frag()
From: Eric Dumazet @ 2012-03-24 9:57 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Wey-Yi Guy
In-Reply-To: <1332508626.4858.20.camel@edumazet-laptop>
Le vendredi 23 mars 2012 à 06:17 -0700, Eric Dumazet a écrit :
> skb_add_rx_frag() API is misleading.
>
> Network skbs built with this helper can use uncharged kernel memory and
> eventually stress/crash machine in OOM.
>
> Add a 'truesize' parameter and then fix drivers in followup patches.
>
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
> Cc: Wey-Yi Guy <wey-yi.w.guy@intel.com>
> ---
> drivers/net/usb/cdc-phonet.c | 6 ++++--
> drivers/net/wireless/iwlegacy/3945.c | 3 ++-
> drivers/net/wireless/iwlegacy/4965-mac.c | 3 ++-
> drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 2 +-
> include/linux/skbuff.h | 2 +-
> net/core/skbuff.c | 4 ++--
> 6 files changed, 12 insertions(+), 8 deletions(-)
Oh well I missed drivers/usb/gadget/f_phonet.c change, I'll send a v2
^ permalink raw reply
* [PATCH v2] net: add a truesize parameter to skb_add_rx_frag()
From: Eric Dumazet @ 2012-03-24 9:59 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Wey-Yi Guy
In-Reply-To: <1332508626.4858.20.camel@edumazet-laptop>
skb_add_rx_frag() API is misleading.
Network skbs built with this helper can use uncharged kernel memory and
eventually stress/crash machine in OOM.
Add a 'truesize' parameter and then fix drivers in followup patches.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Wey-Yi Guy <wey-yi.w.guy@intel.com>
---
drivers/net/usb/cdc-phonet.c | 6 ++++--
drivers/net/wireless/iwlegacy/3945.c | 3 ++-
drivers/net/wireless/iwlegacy/4965-mac.c | 3 ++-
drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 2 +-
drivers/usb/gadget/f_phonet.c | 2 +-
include/linux/skbuff.h | 2 +-
net/core/skbuff.c | 4 ++--
7 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c
index 790cbde..3886b30 100644
--- a/drivers/net/usb/cdc-phonet.c
+++ b/drivers/net/usb/cdc-phonet.c
@@ -164,12 +164,14 @@ static void rx_complete(struct urb *req)
/* Can't use pskb_pull() on page in IRQ */
memcpy(skb_put(skb, 1), page_address(page), 1);
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
- page, 1, req->actual_length);
+ page, 1, req->actual_length,
+ req->actual_length);
page = NULL;
}
} else {
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
- page, 0, req->actual_length);
+ page, 0, req->actual_length,
+ req->actual_length);
page = NULL;
}
if (req->actual_length < PAGE_SIZE)
diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c
index c5b1d19..b25c01b 100644
--- a/drivers/net/wireless/iwlegacy/3945.c
+++ b/drivers/net/wireless/iwlegacy/3945.c
@@ -499,7 +499,8 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,
le32_to_cpu(rx_end->status), stats);
skb_add_rx_frag(skb, 0, rxb->page,
- (void *)rx_hdr->payload - (void *)pkt, len);
+ (void *)rx_hdr->payload - (void *)pkt, len,
+ len);
il_update_stats(il, false, fc, len);
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index 7b54dbb..17f1c68 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -596,7 +596,8 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr,
return;
}
- skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
+ skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len,
+ len);
il_update_stats(il, false, fc, len);
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
index 44c6f71..f4b84d1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
@@ -796,7 +796,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
offset = (void *)hdr - rxb_addr(rxb);
p = rxb_steal_page(rxb);
- skb_add_rx_frag(skb, 0, p, offset, len);
+ skb_add_rx_frag(skb, 0, p, offset, len, len);
iwl_update_stats(priv, false, fc, len);
diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c
index 7cdcb63..85a5ceb 100644
--- a/drivers/usb/gadget/f_phonet.c
+++ b/drivers/usb/gadget/f_phonet.c
@@ -345,7 +345,7 @@ static void pn_rx_complete(struct usb_ep *ep, struct usb_request *req)
}
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
- skb->len <= 1, req->actual);
+ skb->len <= 1, req->actual, req->actual);
page = NULL;
if (req->actual < req->length) { /* Last fragment */
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index a2b9953..681a187 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1244,7 +1244,7 @@ static inline void skb_fill_page_desc(struct sk_buff *skb, int i,
}
extern void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page,
- int off, int size);
+ int off, int size, unsigned int truesize);
#define SKB_PAGE_ASSERT(skb) BUG_ON(skb_shinfo(skb)->nr_frags)
#define SKB_FRAG_ASSERT(skb) BUG_ON(skb_has_frag_list(skb))
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 6eb656a..a690cae 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -321,12 +321,12 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev,
EXPORT_SYMBOL(__netdev_alloc_skb);
void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off,
- int size)
+ int size, unsigned int truesize)
{
skb_fill_page_desc(skb, i, page, off, size);
skb->len += size;
skb->data_len += size;
- skb->truesize += size;
+ skb->truesize += truesize;
}
EXPORT_SYMBOL(skb_add_rx_frag);
^ permalink raw reply related
* [PATCH v3] Ethernet driver for the WIZnet W5300 chip
From: Mike Sinkovsky @ 2012-03-24 11:02 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: msink
In-Reply-To: <1332149037-12025-1-git-send-email-msink@permonline.ru>
Based on original driver from chip manufacturer, but nearly full rewite.
Tested and used in production with Blackfin BF531 embedded processor.
Signed-off-by: Mike Sinkovsky <msink@permonline.ru>
---
v3:
- reading macaddr from platform_data
- ethtool: get_link, get_msglevel, set_msglevel
- more cleanups
v2:
- corrected handling of NET_ADDR_RANDOM flag
- support for WIZNET_BUS_ANY mode
- link detection using gpio
- registers read using ethtool
- more cleanups
drivers/net/ethernet/Kconfig | 1 +
drivers/net/ethernet/Makefile | 1 +
drivers/net/ethernet/wiznet/Kconfig | 61 +++
drivers/net/ethernet/wiznet/Makefile | 1 +
drivers/net/ethernet/wiznet/w5300.c | 707 ++++++++++++++++++++++++++++++++++
include/linux/platform_data/wiznet.h | 16 +
6 files changed, 787 insertions(+), 0 deletions(-)
create mode 100644 drivers/net/ethernet/wiznet/Kconfig
create mode 100644 drivers/net/ethernet/wiznet/Makefile
create mode 100644 drivers/net/ethernet/wiznet/w5300.c
create mode 100644 include/linux/platform_data/wiznet.h
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index c63a64c..a11af5c 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -174,6 +174,7 @@ source "drivers/net/ethernet/tile/Kconfig"
source "drivers/net/ethernet/toshiba/Kconfig"
source "drivers/net/ethernet/tundra/Kconfig"
source "drivers/net/ethernet/via/Kconfig"
+source "drivers/net/ethernet/wiznet/Kconfig"
source "drivers/net/ethernet/xilinx/Kconfig"
source "drivers/net/ethernet/xircom/Kconfig"
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index 9676a51..878ad32 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -73,5 +73,6 @@ obj-$(CONFIG_TILE_NET) += tile/
obj-$(CONFIG_NET_VENDOR_TOSHIBA) += toshiba/
obj-$(CONFIG_NET_VENDOR_TUNDRA) += tundra/
obj-$(CONFIG_NET_VENDOR_VIA) += via/
+obj-$(CONFIG_NET_VENDOR_WIZNET) += wiznet/
obj-$(CONFIG_NET_VENDOR_XILINX) += xilinx/
obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/
diff --git a/drivers/net/ethernet/wiznet/Kconfig b/drivers/net/ethernet/wiznet/Kconfig
new file mode 100644
index 0000000..7ca5c95
--- /dev/null
+++ b/drivers/net/ethernet/wiznet/Kconfig
@@ -0,0 +1,61 @@
+#
+# WIZnet device configuration
+#
+
+config NET_VENDOR_WIZNET
+ bool "WIZnet devices"
+ default y
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+ <http://www.tldp.org/docs.html#howto>.
+
+ Note that the answer to this question doesn't directly affect the
+ kernel: saying N will just cause the configurator to skip all
+ the questions about WIZnet devices. If you say Y, you will be asked
+ for your specific card in the following questions.
+
+if NET_VENDOR_WIZNET
+
+config WIZNET_W5300
+ tristate "WIZnet W5300 Ethernet support"
+ depends on ARM || BLACKFIN
+ ---help---
+ Support for WIZnet W5300 chips.
+
+ W5300 is a single chip with integrated 10/100 Ethernet MAC,
+ PHY and hardware TCP/IP stack, but this driver is limited to
+ the MAC and PHY functions only, onchip TCP/IP is unused.
+
+ To compile this driver as a module, choose M here: the module
+ will be called w5300.
+
+choice
+ prompt "WIZnet interface mode"
+ depends on NET_VENDOR_WIZNET
+ default WIZNET_BUS_ANY
+
+config WIZNET_BUS_DIRECT
+ bool "Direct address bus mode"
+ ---help---
+ In direct address mode host system can directly access W5300 registers
+ after mapping to Memory-mapped I/O Space.
+ 0x400 bytes are required for memory space.
+
+config WIZNET_BUS_INDIRECT
+ bool "Indirect address bus mode"
+ ---help---
+ In indirect address mode host system indirectly accesses registers by
+ using Indirect Mode Address Register (IDM_AR) and Indirect Mode Data
+ Register (IDM_DR), which are directly mapped to Memory-mapped I/O Space.
+ Only 0x06 bytes are required for memory space.
+
+config WIZNET_BUS_ANY
+ bool "Select interface mode in runtime"
+ ---help---
+ If interface mode is unknown in compile time, you can selectied it
+ in runtime.
+ Performance may decrease compared to explicitly selected bus mode.
+endchoice
+
+endif # NET_VENDOR_WIZNET
diff --git a/drivers/net/ethernet/wiznet/Makefile b/drivers/net/ethernet/wiznet/Makefile
new file mode 100644
index 0000000..88e0a3e
--- /dev/null
+++ b/drivers/net/ethernet/wiznet/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_WIZNET_W5300) += w5300.o
diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c
new file mode 100644
index 0000000..d982407
--- /dev/null
+++ b/drivers/net/ethernet/wiznet/w5300.c
@@ -0,0 +1,707 @@
+/*
+ * Ethernet driver for the WIZnet W5300 chip.
+ *
+ * Copyright (C) 2008-2009 WIZnet Co.,Ltd.
+ * Copyright (C) 2011 Taehun Kim <kth3321 <at> gmail.com>
+ * Copyright (C) 2012 Mike Sinkovsky <msink@permonline.ru>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/wiznet.h>
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+
+#define DRV_NAME "WIZnet W5300"
+#define DRV_VERSION "2012-03-24"
+
+MODULE_DESCRIPTION(DRV_NAME" Ethernet driver v"DRV_VERSION);
+MODULE_AUTHOR("Mike Sinkovsky <msink@permonline.ru>");
+MODULE_ALIAS("platform:"KBUILD_MODNAME);
+MODULE_LICENSE("GPL");
+
+/*
+ * Registers
+ */
+#define W5300_MR 0x0000 /* Mode Register */
+#define MR_DBW (1 << 15) /* Data bus width */
+#define MR_MPF (1 << 14) /* Mac layer pause frame */
+#define MR_WDF(n) (((n)&7)<<11) /* Write data fetch time */
+#define MR_RDH (1 << 10) /* Read data hold time */
+#define MR_FS (1 << 8) /* FIFO swap */
+#define MR_RST (1 << 7) /* S/W reset */
+#define MR_PB (1 << 4) /* Ping block */
+#define MR_DBS (1 << 2) /* Data bus swap */
+#define MR_IND (1 << 0) /* Indirect mode */
+#define W5300_IR 0x0002 /* Interrupt Register */
+#define W5300_IMR 0x0004 /* Interrupt Mask Register */
+#define IR_S0 0x0001 /* S0 interrupt */
+#define W5300_SHARL 0x0008 /* Source MAC address (0123) */
+#define W5300_SHARH 0x000c /* Source MAC address (45) */
+#define W5300_TMSRL 0x0020 /* Transmit Memory Size (0123) */
+#define W5300_TMSRH 0x0024 /* Transmit Memory Size (4567) */
+#define W5300_RMSRL 0x0028 /* Receive Memory Size (0123) */
+#define W5300_RMSRH 0x002c /* Receive Memory Size (4567) */
+#define W5300_MTYPE 0x0030 /* Memory Type */
+#define W5300_IDR 0x00fe /* Chip ID register */
+#define IDR_W5300 0x5300 /* =0x5300 for WIZnet W5300 */
+#define W5300_S0_MR 0x0200 /* S0 Mode Register */
+#define S0_MR_CLOSE 0x0000 /* Close mode */
+#define S0_MR_MACRAW 0x0004 /* MAC RAW mode (promiscous) */
+#define S0_MR_MACRAW_MF 0x0044 /* MAC RAW mode (filtered) */
+#define W5300_S0_CR 0x0202 /* S0 Command Register */
+#define S0_CR_OPEN 0x0001 /* OPEN command */
+#define S0_CR_CLOSE 0x0010 /* CLOSE command */
+#define S0_CR_SEND 0x0020 /* SEND command */
+#define S0_CR_RECV 0x0040 /* RECV command */
+#define W5300_S0_IMR 0x0204 /* S0 Interrupt Mask Register */
+#define W5300_S0_IR 0x0206 /* S0 Interrupt Register */
+#define S0_IR_RECV 0x0004 /* Receive interrupt */
+#define W5300_S0_SSR 0x0208 /* S0 Socket Status Register */
+#define W5300_S0_TX_WRSR 0x0220 /* S0 TX Write Size Register */
+#define W5300_S0_TX_FSR 0x0224 /* S0 TX Free Size Register */
+#define W5300_S0_RX_RSR 0x0228 /* S0 Received data Size */
+#define W5300_S0_TX_FIFO 0x022e /* S0 Transmit FIFO */
+#define W5300_S0_RX_FIFO 0x0230 /* S0 Receive FIFO */
+#define W5300_REGS_LEN 0x0400
+
+/*
+ * Frame size is hardwired to 1514 bytes (including header),
+ * => MTU for 802.1Q frames must me set to 1500-4 = 1496
+ */
+#define W5300_HARD_MTU 1500
+
+/*
+ * Device driver private data structure
+ */
+struct w5300_private {
+ void __iomem *base;
+ int irq;
+ int link_irq;
+ int link_gpio;
+
+ u16 (*read) (struct w5300_private *priv, u16 addr);
+ void (*write)(struct w5300_private *priv, u16 addr, u16 data);
+ spinlock_t reg_lock;
+ bool indirect;
+ bool promisc;
+
+ struct napi_struct napi;
+ struct net_device *ndev;
+ u32 msg_enable;
+};
+
+/************************************************************************
+ *
+ * Lowlevel I/O functions
+ *
+ ***********************************************************************/
+
+/*
+ * In direct address mode host system can directly access W5300 registers
+ * after mapping to Memory-mapped I/O Space.
+ *
+ * 0x400 bytes are required for memory space.
+ */
+static inline u16
+w5300_read_direct(struct w5300_private *priv, u16 addr)
+{
+ return ioread16(priv->base + addr);
+}
+
+static inline void
+w5300_write_direct(struct w5300_private *priv, u16 addr, u16 data)
+{
+ iowrite16(data, priv->base + addr);
+ mmiowb();
+}
+
+/*
+ * In indirect address mode host system indirectly accesses registers by
+ * using Indirect Mode Address Register (IDM_AR) and Indirect Mode Data
+ * Register (IDM_DR), which are directly mapped to Memory-mapped I/O Space.
+ * Mode Register (MR) is directly accessible.
+ *
+ * Only 0x06 bytes are required for memory space.
+ */
+#define W5300_IDM_AR 0x002 /* Indirect Mode Address Register */
+#define W5300_IDM_DR 0x004 /* Indirect Mode Data Register */
+
+static inline u16
+w5300_read_indirect(struct w5300_private *priv, u16 addr)
+{
+ unsigned long flags;
+ u16 data;
+
+ spin_lock_irqsave(&priv->reg_lock, flags);
+ w5300_write_direct(priv, W5300_IDM_AR, addr);
+ data = w5300_read_direct(priv, W5300_IDM_DR);
+ spin_unlock_irqrestore(&priv->reg_lock, flags);
+
+ return data;
+}
+
+static inline void
+w5300_write_indirect(struct w5300_private *priv, u16 addr, u16 data)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->reg_lock, flags);
+ w5300_write_direct(priv, W5300_IDM_AR, addr);
+ w5300_write_direct(priv, W5300_IDM_DR, data);
+ spin_unlock_irqrestore(&priv->reg_lock, flags);
+}
+
+#if defined(CONFIG_WIZNET_BUS_DIRECT)
+#define w5300_read w5300_read_direct
+#define w5300_write w5300_write_direct
+
+#elif defined(CONFIG_WIZNET_BUS_INDIRECT)
+#define w5300_read w5300_read_indirect
+#define w5300_write w5300_write_indirect
+
+#else /* CONFIG_WIZNET_BUS_ANY */
+#define w5300_read priv->read
+#define w5300_write priv->write
+#endif
+
+static inline u32
+w5300_read32(struct w5300_private *priv, u16 addr)
+{
+ u32 data;
+ data = w5300_read(priv, addr) << 16;
+ data |= w5300_read(priv, addr + 2);
+ return data;
+}
+
+static inline void
+w5300_write32(struct w5300_private *priv, u16 addr, u32 data)
+{
+ w5300_write(priv, addr, data >> 16);
+ w5300_write(priv, addr + 2, data);
+}
+
+static inline int w5300_command(struct w5300_private *priv, u16 cmd)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(100);
+
+ w5300_write(priv, W5300_S0_CR, cmd);
+
+ while (w5300_read(priv, W5300_S0_CR) != 0) {
+ if (time_after(jiffies, timeout))
+ return -EIO;
+ cpu_relax();
+ }
+
+ return 0;
+}
+
+static void w5300_read_frame(struct w5300_private *priv, u8 *data, int len)
+{
+ u16 fifo;
+ int i;
+
+ for (i = 0; i < len; i += 2) {
+ fifo = w5300_read(priv, W5300_S0_RX_FIFO);
+ *data++ = fifo >> 8;
+ *data++ = fifo;
+ }
+ fifo = w5300_read(priv, W5300_S0_RX_FIFO);
+ fifo = w5300_read(priv, W5300_S0_RX_FIFO);
+}
+
+static void w5300_write_frame(struct w5300_private *priv, u8 *data, int len)
+{
+ u16 fifo;
+ int i;
+
+ for (i = 0; i < len; i += 2) {
+ fifo = *data++ << 8;
+ fifo |= *data++;
+ w5300_write(priv, W5300_S0_TX_FIFO, fifo);
+ }
+ w5300_write32(priv, W5300_S0_TX_WRSR, len);
+ w5300_command(priv, S0_CR_SEND);
+}
+
+static void w5300_write_macaddr(struct w5300_private *priv)
+{
+ struct net_device *ndev = priv->ndev;
+ w5300_write32(priv, W5300_SHARL,
+ ndev->dev_addr[0] << 24 |
+ ndev->dev_addr[1] << 16 |
+ ndev->dev_addr[2] << 8 |
+ ndev->dev_addr[3]);
+ w5300_write(priv, W5300_SHARH,
+ ndev->dev_addr[4] << 8 |
+ ndev->dev_addr[5]);
+}
+
+static void w5300_hw_reset(struct w5300_private *priv)
+{
+ w5300_write_direct(priv, W5300_MR, MR_RST);
+ mdelay(5);
+ w5300_write_direct(priv, W5300_MR, priv->indirect ?
+ MR_WDF(7) | MR_PB | MR_IND :
+ MR_WDF(7) | MR_PB);
+ w5300_write(priv, W5300_IMR, 0);
+
+ /*
+ * Configure 128K of internal memory
+ * as 64K RX fifo and 64K TX fifo
+ */
+ w5300_write32(priv, W5300_RMSRL, 64 << 24);
+ w5300_write32(priv, W5300_RMSRH, 0);
+ w5300_write32(priv, W5300_TMSRL, 64 << 24);
+ w5300_write32(priv, W5300_TMSRH, 0);
+ w5300_write(priv, W5300_MTYPE, 0x00ff);
+
+ w5300_write_macaddr(priv);
+}
+
+static void w5300_hw_start(struct w5300_private *priv)
+{
+ w5300_write(priv, W5300_S0_MR, priv->promisc ?
+ S0_MR_MACRAW :
+ S0_MR_MACRAW_MF);
+ w5300_command(priv, S0_CR_OPEN);
+ w5300_write(priv, W5300_S0_IMR, S0_IR_RECV);
+ w5300_write(priv, W5300_IMR, IR_S0);
+}
+
+/***********************************************************************
+ *
+ * Device driver functions / callbacks
+ *
+ ***********************************************************************/
+
+static void w5300_get_drvinfo(struct net_device *ndev,
+ struct ethtool_drvinfo *info)
+{
+ strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+ strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+ strlcpy(info->bus_info, dev_name(ndev->dev.parent),
+ sizeof(info->bus_info));
+}
+
+static u32 w5300_get_link(struct net_device *ndev)
+{
+ struct w5300_private *priv = netdev_priv(ndev);
+
+ if (priv->link_gpio < 0)
+ return 1;
+
+ return !!gpio_get_value(priv->link_gpio);
+}
+
+static u32 w5300_get_msglevel(struct net_device *ndev)
+{
+ struct w5300_private *priv = netdev_priv(ndev);
+
+ return priv->msg_enable;
+}
+
+static void w5300_set_msglevel(struct net_device *ndev, u32 value)
+{
+ struct w5300_private *priv = netdev_priv(ndev);
+
+ priv->msg_enable = value;
+}
+
+static int w5300_get_regs_len(struct net_device *ndev)
+{
+ return W5300_REGS_LEN;
+}
+
+static void w5300_get_regs(struct net_device *ndev,
+ struct ethtool_regs *regs, void *_buf)
+{
+ struct w5300_private *priv = netdev_priv(ndev);
+ u8 *buf = _buf;
+ u16 addr;
+ u16 data;
+
+ regs->version = 1;
+ for (addr = 0; addr < W5300_REGS_LEN; addr += 2) {
+ switch (addr & 0x23f) {
+ case W5300_S0_TX_FIFO: /* cannot read TX_FIFO */
+ case W5300_S0_RX_FIFO: /* cannot read RX_FIFO */
+ data = 0xffff;
+ break;
+ default:
+ data = w5300_read(priv, addr);
+ break;
+ }
+ *buf++ = data >> 8;
+ *buf++ = data;
+ }
+}
+
+static void w5300_tx_timeout(struct net_device *ndev)
+{
+ struct w5300_private *priv = netdev_priv(ndev);
+
+ if (netif_msg_timer(priv))
+ netdev_err(ndev, "transmit timeout\n");
+
+ netif_stop_queue(ndev);
+ w5300_hw_reset(priv);
+ w5300_hw_start(priv);
+ ndev->stats.tx_errors++;
+ ndev->trans_start = jiffies;
+ netif_wake_queue(ndev);
+}
+
+static int w5300_start_tx(struct sk_buff *skb, struct net_device *ndev)
+{
+ struct w5300_private *priv = netdev_priv(ndev);
+
+ if (unlikely(w5300_read32(priv, W5300_S0_TX_FSR) < skb->len)) {
+ ndev->stats.tx_dropped++;
+ return NETDEV_TX_BUSY;
+ }
+
+ w5300_write_frame(priv, skb->data, skb->len);
+ ndev->stats.tx_packets++;
+ ndev->stats.tx_bytes += skb->len;
+ dev_kfree_skb(skb);
+
+ return NETDEV_TX_OK;
+}
+
+static int w5300_napi_poll(struct napi_struct *napi, int budget)
+{
+ struct w5300_private *priv =
+ container_of(napi, struct w5300_private, napi);
+ struct net_device *ndev = priv->ndev;
+ struct sk_buff *skb;
+ int rx_count;
+ u16 rx_size;
+
+ for (rx_count = 0; rx_count < budget; rx_count++) {
+ u32 rx_fifo_size = w5300_read32(priv, W5300_S0_RX_RSR);
+ if (rx_fifo_size == 0)
+ break;
+
+ rx_size = w5300_read(priv, W5300_S0_RX_FIFO);
+
+ skb = netdev_alloc_skb_ip_align(ndev, roundup(rx_size, 2));
+ if (unlikely(!skb)) {
+ u32 i;
+ for (i = 0; i < rx_fifo_size; i += 2)
+ w5300_read(priv, W5300_S0_RX_FIFO);
+ ndev->stats.rx_dropped++;
+ return -ENOMEM;
+ }
+
+ skb_put(skb, rx_size);
+ w5300_read_frame(priv, skb->data, rx_size);
+ skb->protocol = eth_type_trans(skb, ndev);
+
+ netif_receive_skb(skb);
+ ndev->stats.rx_packets++;
+ ndev->stats.rx_bytes += rx_size;
+ }
+
+ if (rx_count < budget) {
+ w5300_write(priv, W5300_IMR, IR_S0);
+ napi_complete(napi);
+ }
+
+ return rx_count;
+}
+
+static irqreturn_t w5300_start_rx(int irq, void *ndev_instance)
+{
+ struct net_device *ndev = ndev_instance;
+ struct w5300_private *priv = netdev_priv(ndev);
+
+ w5300_write(priv, W5300_S0_IR, S0_IR_RECV);
+
+ if (napi_schedule_prep(&priv->napi)) {
+ w5300_write(priv, W5300_IMR, 0);
+ __napi_schedule(&priv->napi);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t w5300_detect_link(int irq, void *ndev_instance)
+{
+ struct net_device *ndev = ndev_instance;
+ struct w5300_private *priv = netdev_priv(ndev);
+
+ if (netif_running(ndev)) {
+ if (gpio_get_value(priv->link_gpio) != 0) {
+ if (netif_msg_link(priv))
+ netdev_info(ndev, "link is Up\n");
+ netif_carrier_on(ndev);
+ } else {
+ if (netif_msg_link(priv))
+ netdev_info(ndev, "link is Down\n");
+ netif_carrier_off(ndev);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void w5300_set_rx_mode(struct net_device *ndev)
+{
+ struct w5300_private *priv = netdev_priv(ndev);
+ bool set_promisc = (ndev->flags & IFF_PROMISC) != 0;
+
+ if (priv->promisc != set_promisc) {
+ priv->promisc = set_promisc;
+ w5300_hw_start(priv);
+ }
+}
+
+static int w5300_set_macaddr(struct net_device *ndev, void *addr)
+{
+ struct w5300_private *priv = netdev_priv(ndev);
+ struct sockaddr *sock_addr = 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;
+}
+
+static int w5300_open(struct net_device *ndev)
+{
+ struct w5300_private *priv = netdev_priv(ndev);
+
+ if (netif_msg_ifup(priv))
+ netdev_dbg(ndev, "enabling\n");
+
+ if (!is_valid_ether_addr(ndev->dev_addr))
+ return -EINVAL;
+
+ w5300_hw_start(priv);
+
+ napi_enable(&priv->napi);
+ netif_start_queue(ndev);
+ if (priv->link_gpio < 0 || gpio_get_value(priv->link_gpio))
+ netif_carrier_on(ndev);
+ return 0;
+}
+
+static int w5300_stop(struct net_device *ndev)
+{
+ struct w5300_private *priv = netdev_priv(ndev);
+
+ if (netif_msg_ifdown(priv))
+ netdev_dbg(ndev, "shutting down\n");
+
+ w5300_write(priv, W5300_IMR, 0);
+ w5300_write(priv, W5300_S0_CR, S0_CR_CLOSE);
+
+ netif_carrier_off(ndev);
+ netif_stop_queue(ndev);
+ napi_disable(&priv->napi);
+ return 0;
+}
+
+static const struct ethtool_ops w5300_ethtool_ops = {
+ .get_drvinfo = w5300_get_drvinfo,
+ .get_msglevel = w5300_get_msglevel,
+ .set_msglevel = w5300_set_msglevel,
+ .get_link = w5300_get_link,
+ .get_regs_len = w5300_get_regs_len,
+ .get_regs = w5300_get_regs,
+};
+
+static const struct net_device_ops w5300_netdev_ops = {
+ .ndo_open = w5300_open,
+ .ndo_stop = w5300_stop,
+ .ndo_start_xmit = w5300_start_tx,
+ .ndo_tx_timeout = w5300_tx_timeout,
+ .ndo_set_rx_mode = w5300_set_rx_mode,
+ .ndo_set_mac_address = w5300_set_macaddr,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+};
+
+static int __devinit w5300_hw_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct w5300_private *priv = netdev_priv(ndev);
+ const char *name = netdev_name(ndev);
+ struct resource *link;
+ struct resource *mem;
+ int mem_size;
+ int irq;
+ int ret;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!mem)
+ return -ENXIO;
+ mem_size = resource_size(mem);
+ if (!devm_request_mem_region(dev, mem->start, mem_size, name))
+ return -EBUSY;
+ priv->base = devm_ioremap(dev, mem->start, mem_size);
+ if (!priv->base)
+ return -EBUSY;
+
+ spin_lock_init(&priv->reg_lock);
+ priv->indirect = mem_size < 0x400;
+ if (priv->indirect) {
+ priv->read = w5300_read_indirect;
+ priv->write = w5300_write_indirect;
+ } else {
+ priv->read = w5300_read_direct;
+ priv->write = w5300_write_direct;
+ }
+ w5300_hw_reset(priv);
+ if (w5300_read(priv, W5300_IDR) != IDR_W5300)
+ return -ENODEV;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+ ret = devm_request_irq(dev, irq, w5300_start_rx,
+ IRQ_TYPE_LEVEL_LOW, name, ndev);
+ if (ret < 0)
+ return ret;
+ priv->irq = irq;
+
+ link = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!link) {
+ priv->link_gpio = -1;
+ } else {
+ char *link_name = devm_kzalloc(dev, 16, GFP_KERNEL);
+ if (!link_name)
+ return -ENOMEM;
+ snprintf(link_name, 16, "%s-link", name);
+ priv->link_gpio = link->start;
+ priv->link_irq = gpio_to_irq(priv->link_gpio);
+ if (request_irq(priv->link_irq, w5300_detect_link,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ link_name, priv->ndev) < 0)
+ priv->link_gpio = -1;
+ }
+
+ netdev_info(ndev, "at 0x%llx irq %d\n", (u64)mem->start, irq);
+ return 0;
+}
+
+static int __devinit w5300_probe(struct platform_device *pdev)
+{
+ struct wiznet_platform_data *data = pdev->dev.platform_data;
+ struct w5300_private *priv;
+ struct net_device *ndev;
+ int ret;
+
+ ndev = alloc_etherdev(sizeof(*priv));
+ if (!ndev)
+ return -ENOMEM;
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+ platform_set_drvdata(pdev, ndev);
+ priv = netdev_priv(ndev);
+ priv->ndev = ndev;
+
+ ether_setup(ndev);
+ ndev->netdev_ops = &w5300_netdev_ops;
+ ndev->ethtool_ops = &w5300_ethtool_ops;
+ ndev->watchdog_timeo = 2 * HZ;
+ netif_napi_add(ndev, &priv->napi, w5300_napi_poll, 16);
+ ret = register_netdev(ndev);
+ if (ret < 0)
+ goto fail;
+
+ if (data && is_valid_ether_addr(data->mac_addr)) {
+ memcpy(ndev->dev_addr, data->mac_addr, ETH_ALEN);
+ } else {
+ random_ether_addr(ndev->dev_addr);
+ ndev->addr_assign_type |= NET_ADDR_RANDOM;
+ }
+ ret = w5300_hw_probe(pdev);
+ if (ret < 0)
+ goto fail;
+
+ return 0;
+
+fail: netdev_info(ndev, "probe failed (%d)\n", ret);
+ unregister_netdev(ndev);
+ free_netdev(ndev);
+ platform_set_drvdata(pdev, NULL);
+ return ret;
+}
+
+static int __devexit w5300_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+
+ unregister_netdev(ndev);
+ free_netdev(ndev);
+ platform_set_drvdata(pdev, NULL);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int w5300_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct w5300_private *priv = netdev_priv(ndev);
+
+ if (netif_running(ndev)) {
+ netif_carrier_off(ndev);
+ netif_device_detach(ndev);
+
+ w5300_write(priv, W5300_IMR, 0);
+ w5300_command(priv, S0_CR_CLOSE);
+ }
+ return 0;
+}
+
+static int w5300_resume(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct w5300_private *priv = netdev_priv(ndev);
+
+ if (netif_running(ndev)) {
+ w5300_hw_reset(priv);
+ w5300_hw_start(priv);
+
+ netif_device_attach(ndev);
+ if (priv->link_gpio < 0 || gpio_get_value(priv->link_gpio))
+ netif_carrier_on(ndev);
+ }
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+static SIMPLE_DEV_PM_OPS(w5300_pm_ops, w5300_suspend, w5300_resume);
+
+static struct platform_driver w5300_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .owner = THIS_MODULE,
+ .pm = &w5300_pm_ops,
+ },
+ .probe = w5300_probe,
+ .remove = __devexit_p(w5300_remove),
+};
+
+module_platform_driver(w5300_driver);
diff --git a/include/linux/platform_data/wiznet.h b/include/linux/platform_data/wiznet.h
new file mode 100644
index 0000000..402a493
--- /dev/null
+++ b/include/linux/platform_data/wiznet.h
@@ -0,0 +1,16 @@
+/*
+ * Ethernet driver for the WIZnet W5300 chip.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef PLATFORM_DATA_WIZNET_H
+#define PLATFORM_DATA_WIZNET_H
+
+#include <linux/if_ether.h>
+
+struct wiznet_platform_data {
+ u8 mac_addr[ETH_ALEN];
+};
+
+#endif /* PLATFORM_DATA_WIZNET_H */
^ permalink raw reply related
* iproute2 does not enumerate vf's properly (ixgbe)
From: Scott @ 2012-03-24 13:44 UTC (permalink / raw)
To: netdev
When loading the module ixgbe with sr-iov enabled (max_vfs), enumeration of the interfaces' VFs is inconsistent using the iproute2 utility.
Server Information:HP Product Name: ProLiant DL165 G7
Ethernet Card Information: Intel 82599EB 10-Gigabit SFI/SFP+
uname: Linux 3.0.0-16-server x86_64 GNU/Linux
OS Release: Ubuntu 11.10
Using a freshly compiled git pull:
# ./ip -V
ip utility, iproute2-ss120319
Steps to reproduce:
1. Determine the ethernet interface IDs:
# dmesg |grep ixgbe\ 0000:05:00.[0-9].*detected|head -n 2
[ 8.448031] ixgbe 0000:05:00.0: eth4: detected SFP+: 5
[ 8.816035] ixgbe 0000:05:00.1: eth5: detected SFP+: 6
2. Load the module w/40 VFs:
# modprobe ixgbe max_vfs=40
3. Sanity checks:
# lsmod |grep ixgbe
ixgbe 206156 0
dca 15179 2 ixgbe,igb
# modinfo ixgbe|grep version
version: 3.6.7-NAPI
srcversion: 119ADBD2B16B0E40668FB9A
vermagic: 3.0.0-16-server SMP mod_unload modversions
(this is the latest too)
# lspci |grep 05:1[0-9]|perl -lane 'delete @F[1,2,3,4,10,11];print "@F"'
05:10.0 82599 Ethernet Controller Virtual Function
05:10.2 82599 Ethernet Controller Virtual Function
05:10.4 82599 Ethernet Controller Virtual Function
05:10.6 82599 Ethernet Controller Virtual Function
05:11.0 82599 Ethernet Controller Virtual Function
(suppressing output of all 40 VFs)
# lspci |grep 05:1[0-9]|wc -l
40
(showing that there are actually 40)
# ls -l /sys/class/net/eth4/device/|grep virt|awk '{print $10" "$8}'|sort|head -5
../0000:05:10.0 virtfn0
../0000:05:10.2 virtfn1
../0000:05:10.4 virtfn2
../0000:05:10.6 virtfn3
../0000:05:11.0 virtfn4
(suppressing output of all 40 VFs)
5. Run ip link show:
# ./ip link show|grep -e eth[45] -e vf
(null output!)
6. Load the module with fewer VFs
# rmmod ixgbe
# modprobe ixgbe max_vfs=5
# lspci |grep 05:1[0-9]|perl -lane 'delete @F[1,2,3,4,10,11];print "@F"'
05:10.0 82599 Ethernet Controller Virtual Function
05:10.2 82599 Ethernet Controller Virtual Function
05:10.4 82599 Ethernet Controller Virtual Function
05:10.6 82599 Ethernet Controller Virtual Function
05:11.0 82599 Ethernet Controller Virtual Function
# ls -l /sys/class/net/eth4/device/|grep virt|awk '{print $10" "$8}'|sort
../0000:05:10.0 virtfn0
../0000:05:10.2 virtfn1
../0000:05:10.4 virtfn2
../0000:05:10.6 virtfn3
../0000:05:11.0 virtfn4
7. Run ip link show
# ./ip link show|grep -e eth[45] -e vf
57: eth4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
vf 0 MAC 52:a0:59:03:20:a8
vf 1 MAC 82:5f:55:a5:1f:be
vf 2 MAC 0a:ab:86:0c:02:b3
vf 3 MAC 22:a7:28:ce:9c:23
vf 4 MAC 26:ea:6c:1b:ca:57
58: eth5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
(no vfs displayed for eth5!)
Patrick Kutch over at Intel suggested that there may be a patch to fix this problem, but I was not able to locate it.
http://communities.intel.com/thread/28411?tstart=0
There is also Launchpad bug #960497 for this issue.
Thanks in advance for any suggestions.
-SP
^ permalink raw reply
* Re: [PATCH linux-next] dmaengine: add context parameter fixups
From: Fabio Estevam @ 2012-03-24 15:23 UTC (permalink / raw)
To: Alexandre Bounine
Cc: fabio.estevam, alsa-devel, samuel, vinod.koul, netdev, broonie,
linux-kernel, paul.gortmaker, linux-next, tiwai, dan.j.williams,
lrg
In-Reply-To: <1332511242-30241-1-git-send-email-alexandre.bounine@idt.com>
On Fri, Mar 23, 2012 at 11:00 AM, Alexandre Bounine
<alexandre.bounine@idt.com> wrote:
> This patch fixes drivers that use device_prep_slave_sg() and
> device_prep_dma_cyclic() interfaces and have been missed during the initial
> release of interface changing patches.
>
> This patch is based on linux-next-20120322 code tree.
> See https://lkml.org/lkml/2012/3/22/339 for build failure report.
>
> Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
> Reported-by: Paul Gortmaker <paul.gortmaker@windriver.com>
> ---
> drivers/dma/sa11x0-dma.c | 2 +-
> drivers/net/irda/sa1100_ir.c | 2 +-
> sound/soc/sh/fsi.c | 7 +++----
> sound/soc/soc-dmaengine-pcm.c | 2 +-
I have already taken care of sound/soc/soc-dmaengine-pcm.c:
http://permalink.gmane.org/gmane.linux.alsa.devel/96215
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
^ permalink raw reply
* Re: [PATCH v2] iwlwifi: fix skb truesize underestimation
From: Guy, Wey-Yi @ 2012-03-24 15:35 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev, Neal Cardwell, John W. Linville
In-Reply-To: <1332548986.2516.139.camel@edumazet-glaptop>
Hi Eric,
On Fri, 2012-03-23 at 17:29 -0700, Eric Dumazet wrote:
> By default, iwlwifi uses order-1 pages (8 KB) to store incoming frames,
> but doesnt say so in skb->truesize.
>
> This makes very possible to exhaust kernel memory since these skb evade
> normal socket memory accounting.
>
> As struct ieee80211_hdr is going to be pulled before calling IP stack,
> there is no need to use dev_alloc_skb() to reserve NET_SKB_PAD bytes.
> alloc_skb() is ok in this driver, allowing more tailroom.
>
> Pull beginning of frame in skb header, in the hope we can reuse order-1
> pages in the driver immediately for small frames and reduce their
> truesize to the minimum (linear skbs)
>
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
> Cc: Wey-Yi Guy <wey-yi.w.guy@intel.com>
> Cc: "John W. Linville" <linville@tuxdriver.com>
> Cc: Neal Cardwell <ncardwell@google.com>
> ---
Is it ok I pull your patch into our internal tree first for regression
testing, once the test is done, I will push your patch along with all
our other patches together to wireless-next(John Linville).
By doing so, first, we know the patch is not breaking any functionality
for all the devices(legacy/new), second, it is easier for us to sync-up
with all the other changes we are making now.
Thanks
Wey
^ permalink raw reply
* Re: [PATCH v3] Ethernet driver for the WIZnet W5300 chip
From: Joe Perches @ 2012-03-24 15:53 UTC (permalink / raw)
To: Mike Sinkovsky; +Cc: netdev, linux-kernel
In-Reply-To: <1332586938-2804-1-git-send-email-msink@permonline.ru>
On Sat, 2012-03-24 at 16:02 +0500, Mike Sinkovsky wrote:
> Based on original driver from chip manufacturer, but nearly full rewite.
> Tested and used in production with Blackfin BF531 embedded processor.
Hi Mike.
Just a trivial comment. Instead of:
if (netif_<test>(priv))
netdev_<level>(ndev, ...)
you can use
netif_<level>(priv, <test>, ndev, ,...)
> diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c
[]
> +static irqreturn_t w5300_detect_link(int irq, void *ndev_instance)
> +{
> + struct net_device *ndev = ndev_instance;
> + struct w5300_private *priv = netdev_priv(ndev);
> +
> + if (netif_running(ndev)) {
> + if (gpio_get_value(priv->link_gpio) != 0) {
[]
> + if (netif_msg_link(priv))
> + netdev_info(ndev, "link is Up\n");
like:
netif_info(priv, link, ndev, "link is up\n");
> + netif_carrier_on(ndev);
> + } else {
> + if (netif_msg_link(priv))
> + netdev_info(ndev, "link is Down\n");
netif_info(priv, link, ndev, "link is down\n");
> +static int w5300_stop(struct net_device *ndev)
> +{
> + struct w5300_private *priv = netdev_priv(ndev);
> +
> + if (netif_msg_ifdown(priv))
> + netdev_dbg(ndev, "shutting down\n");
netif_dbg(priv, ifdown, ndev, "shutting down\n");
^ permalink raw reply
* Re: [PATCH v3] Ethernet driver for the WIZnet W5300 chip
From: Eric Dumazet @ 2012-03-24 16:10 UTC (permalink / raw)
To: Mike Sinkovsky; +Cc: netdev, linux-kernel
In-Reply-To: <1332586938-2804-1-git-send-email-msink@permonline.ru>
Le samedi 24 mars 2012 à 16:02 +0500, Mike Sinkovsky a écrit :
> Based on original driver from chip manufacturer, but nearly full rewite.
>
> Tested and used in production with Blackfin BF531 embedded processor.
>
> Signed-off-by: Mike Sinkovsky <msink@permonline.ru>
> ---
> +
> +static int w5300_start_tx(struct sk_buff *skb, struct net_device *ndev)
> +{
> + struct w5300_private *priv = netdev_priv(ndev);
> +
> + if (unlikely(w5300_read32(priv, W5300_S0_TX_FSR) < skb->len)) {
> + ndev->stats.tx_dropped++;
> + return NETDEV_TX_BUSY;
> + }
> +
> + w5300_write_frame(priv, skb->data, skb->len);
> + ndev->stats.tx_packets++;
> + ndev->stats.tx_bytes += skb->len;
> + dev_kfree_skb(skb);
> +
> + return NETDEV_TX_OK;
> +}
> +
As there is no tx interrupt at the end of transmit to eventually XON the
queue, you cant XOFF it when there it no room in transmit queue.
Of course, this means qdisc will never have a backlog, since we never
stop the dequeue process.
Returning NETDEV_TX_BUSY essentialy is going to burn cpu cycles,
spinning there is enough room in NIC.
So you must drop the frame, and return NETDEV_TX_OK instead.
static int w5300_start_tx(struct sk_buff *skb, struct net_device *ndev)
{
struct w5300_private *priv = netdev_priv(ndev);
if (unlikely(w5300_read32(priv, W5300_S0_TX_FSR) < skb->len)) {
ndev->stats.tx_dropped++;
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
Rule to use NETDEV_TX_BUSY is :
Before returning NETDEV_TX_BUSY, qdisc must have been stopped by
netif_stop_queue(ndev) (and tx completion might call netif_wake_queue()
later)
^ permalink raw reply
* Re: [PATCH v2] iwlwifi: fix skb truesize underestimation
From: Eric Dumazet @ 2012-03-24 16:12 UTC (permalink / raw)
To: Guy, Wey-Yi; +Cc: David Miller, netdev, Neal Cardwell, John W. Linville
In-Reply-To: <1332603328.27767.11.camel@wwguy-huron>
Le samedi 24 mars 2012 à 08:35 -0700, Guy, Wey-Yi a écrit :
> Hi Eric,
>
> On Fri, 2012-03-23 at 17:29 -0700, Eric Dumazet wrote:
> > By default, iwlwifi uses order-1 pages (8 KB) to store incoming frames,
> > but doesnt say so in skb->truesize.
> >
> > This makes very possible to exhaust kernel memory since these skb evade
> > normal socket memory accounting.
> >
> > As struct ieee80211_hdr is going to be pulled before calling IP stack,
> > there is no need to use dev_alloc_skb() to reserve NET_SKB_PAD bytes.
> > alloc_skb() is ok in this driver, allowing more tailroom.
> >
> > Pull beginning of frame in skb header, in the hope we can reuse order-1
> > pages in the driver immediately for small frames and reduce their
> > truesize to the minimum (linear skbs)
> >
> > Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
> > Cc: Wey-Yi Guy <wey-yi.w.guy@intel.com>
> > Cc: "John W. Linville" <linville@tuxdriver.com>
> > Cc: Neal Cardwell <ncardwell@google.com>
> > ---
>
> Is it ok I pull your patch into our internal tree first for regression
> testing, once the test is done, I will push your patch along with all
> our other patches together to wireless-next(John Linville).
>
> By doing so, first, we know the patch is not breaking any functionality
> for all the devices(legacy/new), second, it is easier for us to sync-up
> with all the other changes we are making now.
>
I am absolutely fine with this plan, thanks a lot !
BTW, why order-1 pages are the default on this driver ?
^ permalink raw reply
* Re: IPv6 flapping with kernel 3.3 (regression from 3.2.9)
From: Maciej Rutecki @ 2012-03-25 6:43 UTC (permalink / raw)
To: Marc Haber; +Cc: linux-kernel, netdev
In-Reply-To: <20120322073428.GA11510@torres.zugschlus.de>
On czwartek, 22 marca 2012 o 08:34:28 Marc Haber wrote:
> Hi,
>
> I have a host which has IPv6 misbehaving when running with Linux 3.3.
> It is flawlessly working with Linux 3.2.9.
>
> The host
> - is running Debian stable (x64_64) with a few locally built and/or
> backported packages, including the kernel.
> - has native IPv6 connectivity on eth0
> - is not doing SLAAC on eth0, both IP address (from 2a01/16) and
> default gateway (fe80::1) are statically configured
> - is running a handful of VMs using KVM/libvirt
> - has IPv6 forwarding enabled
> - does IPv4 NAT
> - has a handful of iptables rules, both for v4 and v6. ICMP and ICMPv6
> are fully open
>
> - the gateway is not under my control
> - the VMs are either bridged to br0 or to br1
> - both br0 and br1 have an IPv6 /64 and radvd running to provide IPv6
> to the VMs
>
> This setup is unique in my machine list, my other machines either are
> no KVM hosts or do only have IPv6 tunneled.
>
> When I run the box with kernel 3.3, it drops off the IPv6 network
> every few minutes and is not responding to pings any more. This state
> stays like 30 seconds to a minute and then IPv6 resumes. It looks to
> me that the box does not lose its default route though. Once in a
> while, I see "fe80::1 dev eth0 router FAILED" in the ip neigh output.
>
> Running a continuous ping in either direction doesn't seem to help.
>
> Booting the box back to 3.2.9 immediately fixes the issue.
>
> I have not yet re-tried going back to 3.3 since a few of the VMs are
> too important to reboot again today. I tried running tcpdump on eth0
> over night but hit br1 instead, so I don't have any packet dumps to
> show.
>
> I guess that something goes wrong with neighbor detection regarding
> the IPv6 gateway.
>
> Was there a relevant change between 3.2.9 and 3.3? Where do I look for
> the issue?
>
> Greetings
> Marc
I created a Bugzilla entry at
https://bugzilla.kernel.org/show_bug.cgi?id=42991
for your bug/regression report, please add your address to the CC list in
there, thanks!
--
Maciej Rutecki
http://www.mrutecki.pl
^ permalink raw reply
* Re: [PATCH v15 06/13] seccomp: add system call filtering using BPF
From: Vladimir Murzin @ 2012-03-25 7:31 UTC (permalink / raw)
To: Will Drewry
Cc: linux-kernel, linux-arch, linux-doc, kernel-hardening, netdev,
x86, arnd, davem, hpa, mingo, oleg, peterz, rdunlap, mcgrathr,
tglx, luto, eparis, serge.hallyn, djm, scarybeasts, indan, pmoore,
akpm, corbet, eric.dumazet, markus, coreyb, keescook
In-Reply-To: <1331781125-15658-7-git-send-email-wad@chromium.org>
On Wed, Mar 14, 2012 at 10:11:58PM -0500, Will Drewry wrote:
> [This patch depends on luto@mit.edu's no_new_privs patch:
> https://lkml.org/lkml/2012/1/30/264
> The whole series including Andrew's patches can be found here:
> https://github.com/redpig/linux/tree/seccomp
> Complete diff here:
> https://github.com/redpig/linux/compare/1dc65fed...seccomp
> A GPG signed tag 'seccomp/v14/posted' will be pushed shortly.
> ]
>
> This patch adds support for seccomp mode 2. Mode 2 introduces the
> ability for unprivileged processes to install system call filtering
> policy expressed in terms of a Berkeley Packet Filter (BPF) program.
> This program will be evaluated in the kernel for each system call
> the task makes and computes a result based on data in the format
> of struct seccomp_data.
>
> A filter program may be installed by calling:
> struct sock_fprog fprog = { ... };
> ...
> prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &fprog);
>
> The return value of the filter program determines if the system call is
> allowed to proceed or denied. If the first filter program installed
> allows prctl(2) calls, then the above call may be made repeatedly
> by a task to further reduce its access to the kernel. All attached
> programs must be evaluated before a system call will be allowed to
> proceed.
>
> Filter programs will be inherited across fork/clone and execve.
> However, if the task attaching the filter is unprivileged
> (!CAP_SYS_ADMIN) the no_new_privs bit will be set on the task. This
> ensures that unprivileged tasks cannot attach filters that affect
> privileged tasks (e.g., setuid binary).
>
> There are a number of benefits to this approach. A few of which are
> as follows:
> - BPF has been exposed to userland for a long time
> - BPF optimization (and JIT'ing) are well understood
> - Userland already knows its ABI: system call numbers and desired
> arguments
> - No time-of-check-time-of-use vulnerable data accesses are possible.
> - system call arguments are loaded on access only to minimize copying
> required for system call policy decisions.
>
> Mode 2 support is restricted to architectures that enable
> HAVE_ARCH_SECCOMP_FILTER. In this patch, the primary dependency is on
> syscall_get_arguments(). The full desired scope of this feature will
> add a few minor additional requirements expressed later in this series.
> Based on discussion, SECCOMP_RET_ERRNO and SECCOMP_RET_TRACE seem to be
> the desired additional functionality.
>
> No architectures are enabled in this patch.
>
> v15: - add a 4 instr penalty when counting a path to account for seccomp_filter
> size (indan@nul.nu)
> - drop the max insns to 256KB (indan@nul.nu)
> - return ENOMEM if the max insns limit has been hit (indan@nul.nu)
> - move IP checks after args (indan@nul.nu)
> - drop !user_filter check (indan@nul.nu)
> - only allow explicit bpf codes (indan@nul.nu)
> - exit_code -> exit_sig
> v14: - put/get_seccomp_filter takes struct task_struct
> (indan@nul.nu,keescook@chromium.org)
> - adds seccomp_chk_filter and drops general bpf_run/chk_filter user
> - add seccomp_bpf_load for use by net/core/filter.c
> - lower max per-process/per-hierarchy: 1MB
> - moved nnp/capability check prior to allocation
> (all of the above: indan@nul.nu)
> v13: - rebase on to 88ebdda6159ffc15699f204c33feb3e431bf9bdc
> v12: - added a maximum instruction count per path (indan@nul.nu,oleg@redhat.com)
> - removed copy_seccomp (keescook@chromium.org,indan@nul.nu)
> - reworded the prctl_set_seccomp comment (indan@nul.nu)
> v11: - reorder struct seccomp_data to allow future args expansion (hpa@zytor.com)
> - style clean up, @compat dropped, compat_sock_fprog32 (indan@nul.nu)
> - do_exit(SIGSYS) (keescook@chromium.org, luto@mit.edu)
> - pare down Kconfig doc reference.
> - extra comment clean up
> v10: - seccomp_data has changed again to be more aesthetically pleasing
> (hpa@zytor.com)
> - calling convention is noted in a new u32 field using syscall_get_arch.
> This allows for cross-calling convention tasks to use seccomp filters.
> (hpa@zytor.com)
> - lots of clean up (thanks, Indan!)
> v9: - n/a
> v8: - use bpf_chk_filter, bpf_run_filter. update load_fns
> - Lots of fixes courtesy of indan@nul.nu:
> -- fix up load behavior, compat fixups, and merge alloc code,
> -- renamed pc and dropped __packed, use bool compat.
> -- Added a hidden CONFIG_SECCOMP_FILTER to synthesize non-arch
> dependencies
> v7: (massive overhaul thanks to Indan, others)
> - added CONFIG_HAVE_ARCH_SECCOMP_FILTER
> - merged into seccomp.c
> - minimal seccomp_filter.h
> - no config option (part of seccomp)
> - no new prctl
> - doesn't break seccomp on systems without asm/syscall.h
> (works but arg access always fails)
> - dropped seccomp_init_task, extra free functions, ...
> - dropped the no-asm/syscall.h code paths
> - merges with network sk_run_filter and sk_chk_filter
> v6: - fix memory leak on attach compat check failure
> - require no_new_privs || CAP_SYS_ADMIN prior to filter
> installation. (luto@mit.edu)
> - s/seccomp_struct_/seccomp_/ for macros/functions (amwang@redhat.com)
> - cleaned up Kconfig (amwang@redhat.com)
> - on block, note if the call was compat (so the # means something)
> v5: - uses syscall_get_arguments
> (indan@nul.nu,oleg@redhat.com, mcgrathr@chromium.org)
> - uses union-based arg storage with hi/lo struct to
> handle endianness. Compromises between the two alternate
> proposals to minimize extra arg shuffling and account for
> endianness assuming userspace uses offsetof().
> (mcgrathr@chromium.org, indan@nul.nu)
> - update Kconfig description
> - add include/seccomp_filter.h and add its installation
> - (naive) on-demand syscall argument loading
> - drop seccomp_t (eparis@redhat.com)
> v4: - adjusted prctl to make room for PR_[SG]ET_NO_NEW_PRIVS
> - now uses current->no_new_privs
> (luto@mit.edu,torvalds@linux-foundation.com)
> - assign names to seccomp modes (rdunlap@xenotime.net)
> - fix style issues (rdunlap@xenotime.net)
> - reworded Kconfig entry (rdunlap@xenotime.net)
> v3: - macros to inline (oleg@redhat.com)
> - init_task behavior fixed (oleg@redhat.com)
> - drop creator entry and extra NULL check (oleg@redhat.com)
> - alloc returns -EINVAL on bad sizing (serge.hallyn@canonical.com)
> - adds tentative use of "always_unprivileged" as per
> torvalds@linux-foundation.org and luto@mit.edu
> v2: - (patch 2 only)
>
> Reviewed-by: Indan Zupancic <indan@nul.nu>
> Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
>
> Signed-off-by: Will Drewry <wad@chromium.org>
> ---
> arch/Kconfig | 17 ++
> include/linux/Kbuild | 1 +
> include/linux/seccomp.h | 76 +++++++++-
> kernel/fork.c | 3 +
> kernel/seccomp.c | 391 ++++++++++++++++++++++++++++++++++++++++++++---
> kernel/sys.c | 2 +-
> 6 files changed, 467 insertions(+), 23 deletions(-)
>
> diff --git a/arch/Kconfig b/arch/Kconfig
> index 4f55c73..7c6bd48 100644
> --- a/arch/Kconfig
> +++ b/arch/Kconfig
> @@ -199,4 +199,21 @@ config HAVE_CMPXCHG_LOCAL
> config HAVE_CMPXCHG_DOUBLE
> bool
>
> +config HAVE_ARCH_SECCOMP_FILTER
> + bool
> + help
> + This symbol should be selected by an architecure if it provides
> + asm/syscall.h, specifically syscall_get_arguments() and
> + syscall_get_arch().
> +
> +config SECCOMP_FILTER
> + def_bool y
> + depends on HAVE_ARCH_SECCOMP_FILTER && SECCOMP && NET
> + help
> + Enable tasks to build secure computing environments defined
> + in terms of Berkeley Packet Filter programs which implement
> + task-defined system call filtering polices.
> +
> + See Documentation/prctl/seccomp_filter.txt for details.
> +
> source "kernel/gcov/Kconfig"
> diff --git a/include/linux/Kbuild b/include/linux/Kbuild
> index c94e717..d41ba12 100644
> --- a/include/linux/Kbuild
> +++ b/include/linux/Kbuild
> @@ -330,6 +330,7 @@ header-y += scc.h
> header-y += sched.h
> header-y += screen_info.h
> header-y += sdla.h
> +header-y += seccomp.h
> header-y += securebits.h
> header-y += selinux_netlink.h
> header-y += sem.h
> diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
> index d61f27f..ce980a8 100644
> --- a/include/linux/seccomp.h
> +++ b/include/linux/seccomp.h
> @@ -1,14 +1,67 @@
> #ifndef _LINUX_SECCOMP_H
> #define _LINUX_SECCOMP_H
>
> +#include <linux/compiler.h>
> +#include <linux/types.h>
> +
> +
> +/* Valid values for seccomp.mode and prctl(PR_SET_SECCOMP, <mode>) */
> +#define SECCOMP_MODE_DISABLED 0 /* seccomp is not in use. */
> +#define SECCOMP_MODE_STRICT 1 /* uses hard-coded filter. */
> +#define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */
> +
> +/*
> + * All BPF programs must return a 32-bit value.
> + * The bottom 16-bits are reserved for future use.
> + * The upper 16-bits are ordered from least permissive values to most.
> + *
> + * The ordering ensures that a min_t() over composed return values always
> + * selects the least permissive choice.
> + */
> +#define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
> +#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
> +
> +/* Masks for the return value sections. */
> +#define SECCOMP_RET_ACTION 0xffff0000U
> +#define SECCOMP_RET_DATA 0x0000ffffU
> +
> +/**
> + * struct seccomp_data - the format the BPF program executes over.
> + * @nr: the system call number
> + * @arch: indicates system call convention as an AUDIT_ARCH_* value
> + * as defined in <linux/audit.h>.
> + * @instruction_pointer: at the time of the system call.
> + * @args: up to 6 system call arguments always stored as 64-bit values
> + * regardless of the architecture.
> + */
> +struct seccomp_data {
> + int nr;
> + __u32 arch;
> + __u64 instruction_pointer;
> + __u64 args[6];
> +};
>
> +#ifdef __KERNEL__
> #ifdef CONFIG_SECCOMP
>
> #include <linux/thread_info.h>
> #include <asm/seccomp.h>
>
> +struct seccomp_filter;
> +/**
> + * struct seccomp - the state of a seccomp'ed process
> + *
> + * @mode: indicates one of the valid values above for controlled
> + * system calls available to a process.
> + * @filter: The metadata and ruleset for determining what system calls
> + * are allowed for a task.
> + *
> + * @filter must only be accessed from the context of current as there
> + * is no locking.
> + */
> struct seccomp {
> int mode;
> + struct seccomp_filter *filter;
> };
>
> extern void __secure_computing(int);
> @@ -19,7 +72,7 @@ static inline void secure_computing(int this_syscall)
> }
>
> extern long prctl_get_seccomp(void);
> -extern long prctl_set_seccomp(unsigned long);
> +extern long prctl_set_seccomp(unsigned long, char __user *);
>
> static inline int seccomp_mode(struct seccomp *s)
> {
> @@ -31,15 +84,16 @@ static inline int seccomp_mode(struct seccomp *s)
> #include <linux/errno.h>
>
> struct seccomp { };
> +struct seccomp_filter { };
>
> -#define secure_computing(x) do { } while (0)
> +#define secure_computing(x) 0
>
> static inline long prctl_get_seccomp(void)
> {
> return -EINVAL;
> }
>
> -static inline long prctl_set_seccomp(unsigned long arg2)
> +static inline long prctl_set_seccomp(unsigned long arg2, char __user *arg3)
> {
> return -EINVAL;
> }
> @@ -48,7 +102,21 @@ static inline int seccomp_mode(struct seccomp *s)
> {
> return 0;
> }
> -
> #endif /* CONFIG_SECCOMP */
>
> +#ifdef CONFIG_SECCOMP_FILTER
> +extern void put_seccomp_filter(struct task_struct *tsk);
> +extern void get_seccomp_filter(struct task_struct *tsk);
> +extern u32 seccomp_bpf_load(int off);
> +#else /* CONFIG_SECCOMP_FILTER */
> +static inline void put_seccomp_filter(struct task_struct *tsk)
> +{
> + return;
> +}
> +static inline void get_seccomp_filter(struct task_struct *tsk)
> +{
> + return;
> +}
> +#endif /* CONFIG_SECCOMP_FILTER */
> +#endif /* __KERNEL__ */
> #endif /* _LINUX_SECCOMP_H */
> diff --git a/kernel/fork.c b/kernel/fork.c
> index 26a7a67..4f7a186 100644
> --- a/kernel/fork.c
> +++ b/kernel/fork.c
> @@ -34,6 +34,7 @@
> #include <linux/cgroup.h>
> #include <linux/security.h>
> #include <linux/hugetlb.h>
> +#include <linux/seccomp.h>
> #include <linux/swap.h>
> #include <linux/syscalls.h>
> #include <linux/jiffies.h>
> @@ -170,6 +171,7 @@ void free_task(struct task_struct *tsk)
> free_thread_info(tsk->stack);
> rt_mutex_debug_task_free(tsk);
> ftrace_graph_exit_task(tsk);
> + put_seccomp_filter(tsk);
> free_task_struct(tsk);
> }
> EXPORT_SYMBOL(free_task);
> @@ -1143,6 +1145,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
> goto fork_out;
>
> ftrace_graph_init_task(p);
> + get_seccomp_filter(p);
>
> rt_mutex_init_task(p);
>
> diff --git a/kernel/seccomp.c b/kernel/seccomp.c
> index e8d76c5..9e50174 100644
> --- a/kernel/seccomp.c
> +++ b/kernel/seccomp.c
> @@ -3,16 +3,338 @@
> *
> * Copyright 2004-2005 Andrea Arcangeli <andrea@cpushare.com>
> *
> - * This defines a simple but solid secure-computing mode.
> + * Copyright (C) 2012 Google, Inc.
> + * Will Drewry <wad@chromium.org>
> + *
> + * This defines a simple but solid secure-computing facility.
> + *
> + * Mode 1 uses a fixed list of allowed system calls.
> + * Mode 2 allows user-defined system call filters in the form
> + * of Berkeley Packet Filters/Linux Socket Filters.
> */
>
> +#include <linux/atomic.h>
> #include <linux/audit.h>
> -#include <linux/seccomp.h>
> -#include <linux/sched.h>
> #include <linux/compat.h>
> +#include <linux/filter.h>
> +#include <linux/sched.h>
> +#include <linux/seccomp.h>
> +#include <linux/security.h>
> +#include <linux/slab.h>
> +#include <linux/uaccess.h>
> +
> +#include <linux/tracehook.h>
> +#include <asm/syscall.h>
>
> /* #define SECCOMP_DEBUG 1 */
> -#define NR_SECCOMP_MODES 1
> +
> +#ifdef CONFIG_SECCOMP_FILTER
> +/**
> + * struct seccomp_filter - container for seccomp BPF programs
> + *
> + * @usage: reference count to manage the object liftime.
> + * get/put helpers should be used when accessing an instance
> + * outside of a lifetime-guarded section. In general, this
> + * is only needed for handling filters shared across tasks.
> + * @prev: points to a previously installed, or inherited, filter
> + * @len: the number of instructions in the program
> + * @insns: the BPF program instructions to evaluate
> + *
> + * seccomp_filter objects are organized in a tree linked via the @prev
> + * pointer. For any task, it appears to be a singly-linked list starting
> + * with current->seccomp.filter, the most recently attached or inherited filter.
> + * However, multiple filters may share a @prev node, by way of fork(), which
> + * results in a unidirectional tree existing in memory. This is similar to
> + * how namespaces work.
> + *
> + * seccomp_filter objects should never be modified after being attached
> + * to a task_struct (other than @usage).
> + */
> +struct seccomp_filter {
> + atomic_t usage;
> + struct seccomp_filter *prev;
> + unsigned short len; /* Instruction count */
> + struct sock_filter insns[];
> +};
> +
> +/* Limit any path through the tree to 256KB worth of instructions. */
> +#define MAX_INSNS_PER_PATH ((1 << 18) / sizeof(struct sock_filter))
> +
> +static void seccomp_filter_log_failure(int syscall)
> +{
> + int compat = 0;
> +#ifdef CONFIG_COMPAT
> + compat = is_compat_task();
> +#endif
> + pr_info("%s[%d]: %ssystem call %d blocked at 0x%lx\n",
> + current->comm, task_pid_nr(current),
> + (compat ? "compat " : ""),
> + syscall, KSTK_EIP(current));
> +}
> +
Do we really need to surround is_compat_task() with CNFIG_COMPAT?
It seems that this case has already handled in include/linux/compat.h [1]
> +/**
> + * get_u32 - returns a u32 offset into data
> + * @data: a unsigned 64 bit value
> + * @index: 0 or 1 to return the first or second 32-bits
> + *
> + * This inline exists to hide the length of unsigned long.
> + * If a 32-bit unsigned long is passed in, it will be extended
> + * and the top 32-bits will be 0. If it is a 64-bit unsigned
> + * long, then whatever data is resident will be properly returned.
> + */
> +static inline u32 get_u32(u64 data, int index)
> +{
> + return ((u32 *)&data)[index];
> +}
> +
> +/* Helper for bpf_load below. */
> +#define BPF_DATA(_name) offsetof(struct seccomp_data, _name)
> +/**
> + * bpf_load: checks and returns a pointer to the requested offset
> + * @off: offset into struct seccomp_data to load from
> + *
> + * Returns the requested 32-bits of data.
> + * seccomp_chk_filter() should assure that @off is 32-bit aligned
> + * and not out of bounds. Failure to do so is a BUG.
> + */
> +u32 seccomp_bpf_load(int off)
> +{
> + struct pt_regs *regs = task_pt_regs(current);
> + if (off == BPF_DATA(nr))
> + return syscall_get_nr(current, regs);
> + if (off == BPF_DATA(arch))
> + return syscall_get_arch(current, regs);
> + if (off >= BPF_DATA(args[0]) && off < BPF_DATA(args[6])) {
> + unsigned long value;
> + int arg = (off - BPF_DATA(args[0])) / sizeof(u64);
> + int index = !!(off % sizeof(u64));
> + syscall_get_arguments(current, regs, arg, 1, &value);
> + return get_u32(value, index);
> + }
> + if (off == BPF_DATA(instruction_pointer))
> + return get_u32(KSTK_EIP(current), 0);
> + if (off == BPF_DATA(instruction_pointer) + sizeof(u32))
> + return get_u32(KSTK_EIP(current), 1);
> + /* seccomp_chk_filter should make this impossible. */
> + BUG();
> +}
> +
> +/**
> + * seccomp_chk_filter - verify seccomp filter code
> + * @filter: filter to verify
> + * @flen: length of filter
> + *
> + * Takes a previously checked filter (by sk_chk_filter) and
> + * redirects all filter code that loads struct sk_buff data
> + * and related data through seccomp_bpf_load. It also
> + * enforces length and alignment checking of those loads.
> + *
> + * Returns 0 if the rule set is legal or -EINVAL if not.
> + */
> +static int seccomp_chk_filter(struct sock_filter *filter, unsigned int flen)
> +{
> + int pc;
> + for (pc = 0; pc < flen; pc++) {
> + struct sock_filter *ftest = &filter[pc];
> + u16 code = ftest->code;
> + u32 k = ftest->k;
> + switch (code) {
> + case BPF_S_LD_W_ABS:
> + ftest->code = BPF_S_ANC_SECCOMP_LD_W;
> + /* 32-bit aligned and not out of bounds. */
> + if (k >= sizeof(struct seccomp_data) || k & 3)
> + return -EINVAL;
> + continue;
> + case BPF_S_LD_W_LEN:
> + ftest->code = BPF_S_LD_IMM;
> + ftest->k = sizeof(struct seccomp_data);
> + continue;
> + case BPF_S_LDX_W_LEN:
> + ftest->code = BPF_S_LDX_IMM;
> + ftest->k = sizeof(struct seccomp_data);
> + continue;
> + /* Explicitly include allowed calls. */
> + case BPF_S_RET_K:
> + case BPF_S_RET_A:
> + case BPF_S_ALU_ADD_K:
> + case BPF_S_ALU_ADD_X:
> + case BPF_S_ALU_SUB_K:
> + case BPF_S_ALU_SUB_X:
> + case BPF_S_ALU_MUL_K:
> + case BPF_S_ALU_MUL_X:
> + case BPF_S_ALU_DIV_X:
> + case BPF_S_ALU_AND_K:
> + case BPF_S_ALU_AND_X:
> + case BPF_S_ALU_OR_K:
> + case BPF_S_ALU_OR_X:
> + case BPF_S_ALU_LSH_K:
> + case BPF_S_ALU_LSH_X:
> + case BPF_S_ALU_RSH_K:
> + case BPF_S_ALU_RSH_X:
> + case BPF_S_ALU_NEG:
> + case BPF_S_LD_IMM:
> + case BPF_S_LDX_IMM:
> + case BPF_S_MISC_TAX:
> + case BPF_S_MISC_TXA:
> + case BPF_S_ALU_DIV_K:
> + case BPF_S_LD_MEM:
> + case BPF_S_LDX_MEM:
> + case BPF_S_ST:
> + case BPF_S_STX:
> + case BPF_S_JMP_JA:
> + case BPF_S_JMP_JEQ_K:
> + case BPF_S_JMP_JEQ_X:
> + case BPF_S_JMP_JGE_K:
> + case BPF_S_JMP_JGE_X:
> + case BPF_S_JMP_JGT_K:
> + case BPF_S_JMP_JGT_X:
> + case BPF_S_JMP_JSET_K:
> + case BPF_S_JMP_JSET_X:
> + continue;
> + default:
> + return -EINVAL;
> + }
> + }
> + return 0;
> +}
> +
> +/**
> + * seccomp_run_filters - evaluates all seccomp filters against @syscall
> + * @syscall: number of the current system call
> + *
> + * Returns valid seccomp BPF response codes.
> + */
> +static u32 seccomp_run_filters(int syscall)
> +{
> + struct seccomp_filter *f;
> + u32 ret = SECCOMP_RET_KILL;
> + /*
> + * All filters are evaluated in order of youngest to oldest. The lowest
> + * BPF return value always takes priority.
> + */
> + for (f = current->seccomp.filter; f; f = f->prev) {
> + ret = sk_run_filter(NULL, f->insns);
> + if (ret != SECCOMP_RET_ALLOW)
> + break;
> + }
> + return ret;
> +}
> +
> +/**
> + * seccomp_attach_filter: Attaches a seccomp filter to current.
> + * @fprog: BPF program to install
> + *
> + * Returns 0 on success or an errno on failure.
> + */
> +static long seccomp_attach_filter(struct sock_fprog *fprog)
> +{
> + struct seccomp_filter *filter;
> + unsigned long fp_size = fprog->len * sizeof(struct sock_filter);
> + unsigned long total_insns = fprog->len;
> + long ret;
> +
> + if (fprog->len == 0 || fprog->len > BPF_MAXINSNS)
> + return -EINVAL;
> +
> + for (filter = current->seccomp.filter; filter; filter = filter->prev)
> + total_insns += filter->len + 4; /* include a 4 instr penalty */
> + if (total_insns > MAX_INSNS_PER_PATH)
> + return -ENOMEM;
> +
> + /*
> + * Installing a seccomp filter requires that the task have
> + * CAP_SYS_ADMIN in its namespace or be running with no_new_privs.
> + * This avoids scenarios where unprivileged tasks can affect the
> + * behavior of privileged children.
> + */
> + if (!current->no_new_privs &&
> + security_capable_noaudit(current_cred(), current_user_ns(),
> + CAP_SYS_ADMIN) != 0)
> + return -EACCES;
> +
> + /* Allocate a new seccomp_filter */
> + filter = kzalloc(sizeof(struct seccomp_filter) + fp_size, GFP_KERNEL);
> + if (!filter)
> + return -ENOMEM;
> + atomic_set(&filter->usage, 1);
> + filter->len = fprog->len;
> +
> + /* Copy the instructions from fprog. */
> + ret = -EFAULT;
> + if (copy_from_user(filter->insns, fprog->filter, fp_size))
> + goto fail;
> +
> + /* Check and rewrite the fprog via the skb checker */
> + ret = sk_chk_filter(filter->insns, filter->len);
> + if (ret)
> + goto fail;
> +
> + /* Check and rewrite the fprog for seccomp use */
> + ret = seccomp_chk_filter(filter->insns, filter->len);
> + if (ret)
> + goto fail;
> +
> + /*
> + * If there is an existing filter, make it the prev and don't drop its
> + * task reference.
> + */
> + filter->prev = current->seccomp.filter;
> + current->seccomp.filter = filter;
> + return 0;
> +fail:
> + kfree(filter);
> + return ret;
> +}
> +
> +/**
> + * seccomp_attach_user_filter - attaches a user-supplied sock_fprog
> + * @user_filter: pointer to the user data containing a sock_fprog.
> + *
> + * Returns 0 on success and non-zero otherwise.
> + */
> +long seccomp_attach_user_filter(char __user *user_filter)
> +{
> + struct sock_fprog fprog;
> + long ret = -EFAULT;
> +
> +#ifdef CONFIG_COMPAT
> + if (is_compat_task()) {
> + struct compat_sock_fprog fprog32;
> + if (copy_from_user(&fprog32, user_filter, sizeof(fprog32)))
> + goto out;
> + fprog.len = fprog32.len;
> + fprog.filter = compat_ptr(fprog32.filter);
> + } else /* falls through to the if below. */
> +#endif
> + if (copy_from_user(&fprog, user_filter, sizeof(fprog)))
> + goto out;
> + ret = seccomp_attach_filter(&fprog);
> +out:
> + return ret;
> +}
The same note about CONFIG_COMPAT as above.
> +
> +/* get_seccomp_filter - increments the reference count of the filter on @tsk */
> +void get_seccomp_filter(struct task_struct *tsk)
> +{
> + struct seccomp_filter *orig = tsk->seccomp.filter;
> + if (!orig)
> + return;
> + /* Reference count is bounded by the number of total processes. */
> + atomic_inc(&orig->usage);
> +}
> +
> +/* put_seccomp_filter - decrements the ref count of tsk->seccomp.filter */
> +void put_seccomp_filter(struct task_struct *tsk)
> +{
> + struct seccomp_filter *orig = tsk->seccomp.filter;
> + /* Clean up single-reference branches iteratively. */
> + while (orig && atomic_dec_and_test(&orig->usage)) {
> + struct seccomp_filter *freeme = orig;
> + orig = orig->prev;
> + kfree(freeme);
> + }
> +}
> +#endif /* CONFIG_SECCOMP_FILTER */
>
> /*
> * Secure computing mode 1 allows only read/write/exit/sigreturn.
> @@ -34,10 +356,11 @@ static int mode1_syscalls_32[] = {
> void __secure_computing(int this_syscall)
> {
> int mode = current->seccomp.mode;
> - int * syscall;
> + int exit_sig = 0;
> + int *syscall;
>
> switch (mode) {
> - case 1:
> + case SECCOMP_MODE_STRICT:
> syscall = mode1_syscalls;
> #ifdef CONFIG_COMPAT
> if (is_compat_task())
> @@ -47,7 +370,16 @@ void __secure_computing(int this_syscall)
> if (*syscall == this_syscall)
> return;
> } while (*++syscall);
> + exit_sig = SIGKILL;
> + break;
> +#ifdef CONFIG_SECCOMP_FILTER
> + case SECCOMP_MODE_FILTER:
> + if (seccomp_run_filters(this_syscall) == SECCOMP_RET_ALLOW)
> + return;
> + seccomp_filter_log_failure(this_syscall);
> + exit_sig = SIGSYS;
> break;
> +#endif
> default:
> BUG();
> }
> @@ -56,7 +388,7 @@ void __secure_computing(int this_syscall)
> dump_stack();
> #endif
> audit_seccomp(this_syscall);
> - do_exit(SIGKILL);
> + do_exit(exit_sig);
> }
>
> long prctl_get_seccomp(void)
> @@ -64,25 +396,48 @@ long prctl_get_seccomp(void)
> return current->seccomp.mode;
> }
>
> -long prctl_set_seccomp(unsigned long seccomp_mode)
> +/**
> + * prctl_set_seccomp: configures current->seccomp.mode
> + * @seccomp_mode: requested mode to use
> + * @filter: optional struct sock_fprog for use with SECCOMP_MODE_FILTER
> + *
> + * This function may be called repeatedly with a @seccomp_mode of
> + * SECCOMP_MODE_FILTER to install additional filters. Every filter
> + * successfully installed will be evaluated (in reverse order) for each system
> + * call the task makes.
> + *
> + * Once current->seccomp.mode is non-zero, it may not be changed.
> + *
> + * Returns 0 on success or -EINVAL on failure.
> + */
> +long prctl_set_seccomp(unsigned long seccomp_mode, char __user *filter)
> {
> - long ret;
> + long ret = -EINVAL;
>
> - /* can set it only once to be even more secure */
> - ret = -EPERM;
> - if (unlikely(current->seccomp.mode))
> + if (current->seccomp.mode &&
> + current->seccomp.mode != seccomp_mode)
> goto out;
>
> - ret = -EINVAL;
> - if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
> - current->seccomp.mode = seccomp_mode;
> - set_thread_flag(TIF_SECCOMP);
> + switch (seccomp_mode) {
> + case SECCOMP_MODE_STRICT:
> + ret = 0;
> #ifdef TIF_NOTSC
> disable_TSC();
> #endif
> - ret = 0;
> + break;
> +#ifdef CONFIG_SECCOMP_FILTER
> + case SECCOMP_MODE_FILTER:
> + ret = seccomp_attach_user_filter(filter);
> + if (ret)
> + goto out;
> + break;
> +#endif
> + default:
> + goto out;
> }
>
> - out:
> + current->seccomp.mode = seccomp_mode;
> + set_thread_flag(TIF_SECCOMP);
> +out:
> return ret;
> }
> diff --git a/kernel/sys.c b/kernel/sys.c
> index 12e862a..038e6b7 100644
> --- a/kernel/sys.c
> +++ b/kernel/sys.c
> @@ -1899,7 +1899,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
> error = prctl_get_seccomp();
> break;
> case PR_SET_SECCOMP:
> - error = prctl_set_seccomp(arg2);
> + error = prctl_set_seccomp(arg2, (char __user *)arg3);
> break;
> case PR_GET_TSC:
> error = GET_TSC_CTL(arg2);
> --
> 1.7.5.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arch" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
[1] http://lxr.linux.no/#linux+v3.3/include/linux/compat.h#L566
Best wishes
Vladimir Murzin
^ permalink raw reply
* Linux 3.2 and 3.3 not doing IPv6 ND when it should
From: Marc Haber @ 2012-03-25 7:39 UTC (permalink / raw)
To: linux-kernel, netdev
Hi,
it's me again. I have nailed down my issue a little more. First, I now
see the issue happening with Linux 3.2.9 as well. Unfortunately, it is
still only a single box; the two other Linux hosts that have a
similiar setup (with native IPv6 on an Ethernet interface) are working
flawlessly.
To me, this looks like the ND entry for the default gateway expires
from the neighbour table and Linux doesn't bother to do a new Neighbor
Discovery, but allows the STALE neighbour entry to remain in the
table. Eventually, it feels like doing ND again and everything is fine.
In a packet dump (sorry for the long lines), this looks like
No. Time Source Destination Packet length Protocol Info
2937 15:48:39.725721 2001:db8:1320:0:718f:6a5a:5b60:5632 2001:db8:40b7:9102::200:100 118 ICMPv6 Echo (ping) request id=0x2887, seq=263
2938 15:48:39.725870 2001:db8:40b7:9102::200:100 2001:db8:1320:0:718f:6a5a:5b60:5632 118 ICMPv6 Echo (ping) reply id=0x2887, seq=263
2975 15:48:40.641202 2001:db8:1320:0:718f:6a5a:5b60:5632 2001:db8:40b7:9101::1 118 ICMPv6 Echo (ping) request id=0x2887, seq=271
2976 15:48:40.641302 2001:db8:40b7:9101::1 2001:db8:1320:0:718f:6a5a:5b60:5632 118 ICMPv6 Echo (ping) reply id=0x2887, seq=271
2982 15:48:40.703167 2001:db8:1320:0:718f:6a5a:5b60:5632 2001:db8:40b7:9100::100:100 118 ICMPv6 Echo (ping) request id=0x2887, seq=275
2983 15:48:40.703184 2001:db8:40b7:9100::100:100 2001:db8:1320:0:718f:6a5a:5b60:5632 118 ICMPv6 Echo (ping) reply id=0x2887, seq=275
2984 15:48:40.727155 2001:db8:1320:0:718f:6a5a:5b60:5632 2001:db8:40b7:9102::200:100 118 ICMPv6 Echo (ping) request id=0x2887, seq=277
2985 15:48:40.727284 2001:db8:40b7:9102::200:100 2001:db8:1320:0:718f:6a5a:5b60:5632 118 ICMPv6 Echo (ping) reply id=0x2887, seq=277
3006 15:48:40.944032 2001:db8:4071:3202::1f 2001:db8:40b7:9102::200:100 130 ICMPv6 Echo (ping) request id=0x1932, seq=0
3007 15:48:40.944114 2001:db8:40b7:9102::200:100 2001:db8:4071:3202::1f 130 ICMPv6 Echo (ping) reply id=0x1932, seq=0
3008 15:48:40.974015 2001:db8:4071:3202::1f 2001:db8:40b7:9101::1 130 ICMPv6 Echo (ping) request id=0x1932, seq=1
3009 15:48:40.974091 2001:db8:40b7:9101::1 2001:db8:4071:3202::1f 130 ICMPv6 Echo (ping) reply id=0x1932, seq=1
3010 15:48:41.000000 2001:db8:4071:3202::1f 2001:db8:40b7:9100::100:100 130 ICMPv6 Echo (ping) request id=0x1932, seq=2
3011 15:48:41.000009 2001:db8:40b7:9100::100:100 2001:db8:4071:3202::1f 130 ICMPv6 Echo (ping) reply id=0x1932, seq=2
3035 15:48:43.085816 2001:db8:4071:3202::1f 2001:db8:40b7:9102::200:100 130 ICMPv6 Echo (ping) request id=0x1936, seq=0
3036 15:48:43.085890 2001:db8:40b7:9102::200:100 2001:db8:4071:3202::1f 130 ICMPv6 Echo (ping) reply id=0x1936, seq=0
3037 15:48:43.115797 2001:db8:4071:3202::1f 2001:db8:40b7:9101::1 130 ICMPv6 Echo (ping) request id=0x1936, seq=1
3038 15:48:43.115901 2001:db8:40b7:9101::1 2001:db8:4071:3202::1f 130 ICMPv6 Echo (ping) reply id=0x1936, seq=1
3039 15:48:43.148781 2001:db8:4071:3202::1f 2001:db8:40b7:9100::100:100 130 ICMPv6 Echo (ping) request id=0x1936, seq=2
3040 15:48:43.148792 2001:db8:40b7:9100::100:100 2001:db8:4071:3202::1f 130 ICMPv6 Echo (ping) reply id=0x1936, seq=2
3062 15:48:45.232600 2001:db8:4071:3202::1f 2001:db8:40b7:9102::200:100 130 ICMPv6 Echo (ping) request id=0x193a, seq=0
3063 15:48:45.269577 2001:db8:4071:3202::1f 2001:db8:40b7:9101::1 130 ICMPv6 Echo (ping) request id=0x193a, seq=1
3064 15:48:45.297561 2001:db8:4071:3202::1f 2001:db8:40b7:9100::100:100 130 ICMPv6 Echo (ping) request id=0x193a, seq=2
3080 15:48:47.378381 2001:db8:4071:3202::1f 2001:db8:40b7:9102::200:100 130 ICMPv6 Echo (ping) request id=0x193e, seq=0
3081 15:48:47.409363 2001:db8:4071:3202::1f 2001:db8:40b7:9101::1 130 ICMPv6 Echo (ping) request id=0x193e, seq=1
3082 15:48:47.439346 2001:db8:4071:3202::1f 2001:db8:40b7:9100::100:100 130 ICMPv6 Echo (ping) request id=0x193e, seq=2
3098 15:48:49.528161 2001:db8:4071:3202::1f 2001:db8:40b7:9102::200:100 130 ICMPv6 Echo (ping) request id=0x1942, seq=0
3099 15:48:49.559143 2001:db8:4071:3202::1f 2001:db8:40b7:9101::1 130 ICMPv6 Echo (ping) request id=0x1942, seq=1
3100 15:48:49.589126 2001:db8:4071:3202::1f 2001:db8:40b7:9100::100:100 130 ICMPv6 Echo (ping) request id=0x1942, seq=2
3118 15:48:51.678941 2001:db8:4071:3202::1f 2001:db8:40b7:9102::200:100 130 ICMPv6 Echo (ping) request id=0x1946, seq=0
3119 15:48:51.709923 2001:db8:4071:3202::1f 2001:db8:40b7:9101::1 130 ICMPv6 Echo (ping) request id=0x1946, seq=1
3120 15:48:51.739905 2001:db8:4071:3202::1f 2001:db8:40b7:9100::100:100 130 ICMPv6 Echo (ping) request id=0x1946, seq=2
<snip table part without packets originating at 2001:db8:40b7:9102::200:100>
3647 15:49:43.319631 2001:db8:4071:3202::1f 2001:db8:40b7:9100::100:100 130 ICMPv6 Echo (ping) request id=0x19bb, seq=2
3693 15:49:45.469414 2001:db8:4071:3202::1f 2001:db8:40b7:9102::200:100 130 ICMPv6 Echo (ping) request id=0x19bf, seq=0
3694 15:49:45.469438 2001:db8:4071:3202::1f 2001:db8:40b7:9101::1 130 ICMPv6 Echo (ping) request id=0x19bf, seq=1
3695 15:49:45.469446 2001:db8:4071:3202::1f 2001:db8:40b7:9100::100:100 130 ICMPv6 Echo (ping) request id=0x19bf, seq=2
3696 15:49:45.469477 2001:db8:40b7:9100::100:100 ff02::1:ff00:1 86 ICMPv6 Neighbor Solicitation
3697 15:49:45.546365 fe80::1 2001:db8:40b7:9100::100:100 86 ICMPv6 Neighbor Advertisement
3698 15:49:45.546372 2001:db8:40b7:9100::100:100 2001:db8:4071:3202::1f 130 ICMPv6 Echo (ping) reply id=0x19bf, seq=2
3699 15:49:45.546373 2001:db8:40b7:9102::200:100 2001:db8:4071:3202::1f 130 ICMPv6 Echo (ping) reply id=0x19bf, seq=0
3700 15:49:45.546375 2001:db8:40b7:9101::1 2001:db8:4071:3202::1f 130 ICMPv6 Echo (ping) reply id=0x19bf, seq=1
3708 15:49:47.620190 2001:db8:4071:3202::1f 2001:db8:40b7:9102::200:100 130 ICMPv6 Echo (ping) request id=0x19c3, seq=0
3709 15:49:47.620200 2001:db8:4071:3202::1f 2001:db8:40b7:9101::1 130 ICMPv6 Echo (ping) request id=0x19c3, seq=1
3710 15:49:47.620280 2001:db8:40b7:9102::200:100 2001:db8:4071:3202::1f 130 ICMPv6 Echo (ping) reply id=0x19c3, seq=0
3711 15:49:47.620304 2001:db8:40b7:9101::1 2001:db8:4071:3202::1f 130 ICMPv6 Echo (ping) reply id=0x19c3, seq=1
2001:db8:40b7:9102::200:100/64 is a local IPv6 address of my host (bound to br1)
2001:db8:40b7:9102::/64 has a number of KVM VMs running on the host (connected via br1)
2001:db8:40b7:9101::/64 has a number of KVM VMs running on the host (connected via br0)
2001:db8:3202::1f is my notebook which was running a ping for a number of IP addresses
2001:db8:1320:0:718f:6a5a:5b60:5632 is a smokeping host checking reachability
To confirm that this is indeed an ND issue, setting a static neighbor
entry for fe80::1 to the link level address of the current gateway
immediately fixed the issue. This is, unfortunately, not a permanent
solution since I don't want to rely on the hoster to keep their link
level addresses static.
If you need more information, please say so.
I'm going to post a similiar ND issue to a new thread soon. This may
be the same issue.
Greetings
Marc
--
-----------------------------------------------------------------------------
Marc Haber | "I don't trust Computers. They | Mailadresse im Header
Mannheim, Germany | lose things." Winona Ryder | Fon: *49 621 31958061
Nordisch by Nature | How to make an American Quilt | Fax: *49 621 31958062
^ permalink raw reply
* Linux 3.2 and 3.3 - "network is down" when pinging IPv6.
From: Marc Haber @ 2012-03-25 8:37 UTC (permalink / raw)
To: linux-kernel, netdev
Hi,
it's me again with a different issue regarding IPv6. This may be
related to the issue I reported in http://lkml.org/lkml/2012/3/22/59
and http://lkml.org/lkml/2012/3/25/8, but not necessarily. This was
really bizarrely fixed.
Again, this is seen on a single box with native IPv6 on eth0, routing
IPv4 and IPv6 to two bridges where KVM VMs are attached to. Setup:
myhost$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:24:21:af:8f:cb brd ff:ff:ff:ff:ff:ff
inet 172.24.53.218/32 scope global eth0
inet6 2001:db8:40b7:9100::100:100/128 scope global
valid_lft forever preferred_lft forever
inet6 2001:db8:40b7:9100:6686:29f:cdfc:9713/128 scope global deprecated
valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
link/ether 00:24:21:af:8f:cc brd ff:ff:ff:ff:ff:ff
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether fe:54:00:23:47:46 brd ff:ff:ff:ff:ff:ff
inet 192.168.145.254/24 brd 192.168.145.255 scope global br0
inet6 2001:db8:40b7:9101::100:153/64 scope global deprecated
valid_lft forever preferred_lft forever
inet6 2001:db8:40b7:9101::100:100/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::1/64 scope link
valid_lft forever preferred_lft forever
inet6 fe80::c091:aaff:fe67:fd99/64 scope link
valid_lft forever preferred_lft forever
5: br1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether fe:54:00:fa:de:7d brd ff:ff:ff:ff:ff:ff
inet 192.168.146.254/24 brd 192.168.146.255 scope global br1
inet6 2001:db8:40b7:9102::100:153/64 scope global deprecated
valid_lft forever preferred_lft forever
inet6 2001:db8:40b7:9102::100:100/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::1/64 scope link
valid_lft forever preferred_lft forever
inet6 fe80::2c46:f8ff:feb9:16bf/64 scope link
valid_lft forever preferred_lft forever
7: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UNKNOWN qlen 500
link/ether fe:54:00:23:47:46 brd ff:ff:ff:ff:ff:ff
inet6 fe80::fc54:ff:fe23:4746/64 scope link
valid_lft forever preferred_lft forever
8: vnet1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UNKNOWN qlen 500
link/ether fe:54:00:67:86:fb brd ff:ff:ff:ff:ff:ff
inet6 fe80::fc54:ff:fe67:86fb/64 scope link
valid_lft forever preferred_lft forever
9: vnet2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br1 state UNKNOWN qlen 500
link/ether fe:54:00:fa:de:7d brd ff:ff:ff:ff:ff:ff
inet6 fe80::fc54:ff:fefa:de7d/64 scope link
valid_lft forever preferred_lft forever
myhost$ ip r
default via 172.29.179.1 dev eth0
172.29.179.1 dev eth0 scope link
172.29.179.176 dev br0 scope link
192.168.145.0/24 dev br0 proto kernel scope link src 192.168.145.254
192.168.146.0/24 dev br1 proto kernel scope link src 192.168.146.254
myhost$ ip -6 r
2001:db8:40b7:9100::100:100 dev eth0 proto kernel metric 256
2001:db8:40b7:9100:6686:29f:cdfc:9713 dev eth0 proto kernel metric 256
2001:db8:40b7:9101::/64 dev br0 proto kernel metric 256
2001:db8:40b7:9102::/64 dev br1 proto kernel metric 256
fe80::/64 dev br0 proto kernel metric 256
fe80::/64 dev br1 proto kernel metric 256
fe80::/64 dev eth0 proto kernel metric 256
fe80::/64 dev vnet0 proto kernel metric 256
fe80::/64 dev vnet1 proto kernel metric 256
fe80::/64 dev vnet2 proto kernel metric 256
default via fe80::1 dev eth0 metric 1024
myhost$ sudo brctl show
bridge name bridge id STP enabled interfaces
br0 8000.fe5400234746 no vnet0
vnet1
br1 8000.fe5400fade7d no vnet2
myhost$
On br0/vnet0, there is a Linux VM with the following IP configuration:
myvm$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 52:54:00:23:47:46 brd ff:ff:ff:ff:ff:ff
inet 172.29.179.176 peer 192.168.145.254/32 scope global eth0
inet6 2001:db8:40b7:9101::2:53/64 scope global deprecated
valid_lft forever preferred_lft forever
inet6 2001:db8:40b7:9101::1:53/64 scope global deprecated
valid_lft forever preferred_lft forever
inet6 2001:db8:40b7:9101::6667/64 scope global deprecated
valid_lft forever preferred_lft forever
inet6 2001:db8:40b7:9101::1/64 scope global
valid_lft forever preferred_lft forever
inet6 2001:db8:40b7:9101:5054:ff:fe23:4746/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe23:4746/64 scope link
valid_lft forever preferred_lft forever
3: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 100
link/none
inet 10.11.12.1 peer 10.11.12.2/32 scope global tun0
4: tun1: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1498 qdisc pfifo_fast state UNKNOWN qlen 100
link/none
inet 10.11.25.1 peer 10.11.25.2/32 scope global tun1
myvm$ ip r
default via 192.168.145.254 dev eth0
10.11.12.0/24 via 10.11.12.2 dev tun0
10.11.12.2 dev tun0 proto kernel scope link src 10.11.12.1
10.11.25.0/24 via 10.11.25.2 dev tun1
10.11.25.2 dev tun1 proto kernel scope link src 10.11.25.1
192.168.145.254 dev eth0 proto kernel scope link src 172.29.179.176
myvm$ ip -6 r
2001:db8:40b7:9101::/64 dev eth0 proto kernel metric 256
fe80::/64 dev eth0 proto kernel metric 256
default via fe80::c091:aaff:fe67:fd99 dev eth0 proto kernel metric 1024 expires 1435sec
myvm$
Please note that myvm has both 2001:db8:40b7:9101::1/64 and
2001:db8:40b7:9101::1:53/64 configured.
Most of the time (but not always!), myhost does not even try to send
out a packet when I ping6 2001:db8:40b7:9101::1. Instead, ping6 says
that sendmsg cannot send the packet ("network is down").
2001:db8:40b7:9101::1 is not in the neighbor table, and myhost does not
send out a neighbor solicitation. It simple immediately claims that
the network is down.
At the same time, ping6'ing 2001:db8:40b7:9101::1:53 works just fine.
IPv4 is not affected as well.
I can see similiar behavior with other VMs as well, on both br0 and br1.
Now for the real bizarre solution: Setting a more specific route for
2a01:238:40b7:9101::/65 immediately fixes the issue. Same holds for
br1 and the route 2a01:238:40b7:9102::/65.
The IPv6 routing table on myhost now looks like
myhost$ ip -6 r
2001:db8:40b7:9100::100:100 dev eth0 proto kernel metric 256
2001:db8:40b7:9100:6686:29f:cdfc:9713 dev eth0 proto kernel metric 256
2001:db8:40b7:9101::/65 dev br0 metric 1024
2001:db8:40b7:9101::/64 dev br0 proto kernel metric 256
2001:db8:40b7:9102::/65 dev br1 metric 1024
2001:db8:40b7:9102::/64 dev br1 proto kernel metric 256
fe80::/64 dev br0 proto kernel metric 256
fe80::/64 dev br1 proto kernel metric 256
fe80::/64 dev eth0 proto kernel metric 256
fe80::/64 dev vnet0 proto kernel metric 256
fe80::/64 dev vnet1 proto kernel metric 256
fe80::/64 dev vnet2 proto kernel metric 256
default via fe80::1 dev eth0 metric 1024
and everything works as designed.
Why do I need the /65 route? Why can I ping one address from the /64
network and not another?
If you need more information, please say so.
Greetings
Marc
--
-----------------------------------------------------------------------------
Marc Haber | "I don't trust Computers. They | Mailadresse im Header
Mannheim, Germany | lose things." Winona Ryder | Fon: *49 621 31958061
Nordisch by Nature | How to make an American Quilt | Fax: *49 621 31958062
^ permalink raw reply
* Re: [PATCH] e1000: Silence sparse warnings by correcting type
From: Jeff Kirsher @ 2012-03-25 9:45 UTC (permalink / raw)
To: Andrei Emeltchenko; +Cc: netdev
In-Reply-To: <1332233951-31129-1-git-send-email-Andrei.Emeltchenko.news@gmail.com>
On 03/20/2012 01:59 AM, Andrei Emeltchenko wrote:
> From: Andrei Emeltchenko<andrei.emeltchenko@intel.com>
>
> Silence sparse warnings shown below:
> ...
> drivers/net/ethernet/intel/e1000/e1000_main.c:3435:17: warning:
> cast to restricted __le64
> drivers/net/ethernet/intel/e1000/e1000_main.c:3435:17: warning:
> cast to restricted __le64
> ...
>
> Signed-off-by: Andrei Emeltchenko<andrei.emeltchenko@intel.com>
> ---
> drivers/net/ethernet/intel/e1000/e1000_main.c | 4 ++--
> 1 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
> index 6419a88..1bf73cf 100644
> --- a/drivers/net/ethernet/intel/e1000/e1000_main.c
> +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
> @@ -3377,7 +3377,7 @@ static void e1000_dump(struct e1000_adapter *adapter)
> for (i = 0; tx_ring->desc&& (i< tx_ring->count); i++) {
> struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i);
> struct e1000_buffer *buffer_info =&tx_ring->buffer_info[i];
> - struct my_u { u64 a; u64 b; };
> + struct my_u { __le64 a; __le64 b; };
> struct my_u *u = (struct my_u *)tx_desc;
> const char *type;
>
> @@ -3421,7 +3421,7 @@ rx_ring_summary:
> for (i = 0; rx_ring->desc&& (i< rx_ring->count); i++) {
> struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i);
> struct e1000_buffer *buffer_info =&rx_ring->buffer_info[i];
> - struct my_u { u64 a; u64 b; };
> + struct my_u { __le64 a; __le64 b; };
> struct my_u *u = (struct my_u *)rx_desc;
> const char *type;
>
Helps if you CC the maintainers (i.e. me)
Thanks, I will add it to my queue of e1000 patches.
^ permalink raw reply
* Re: [PATCH v8 RESEND] ARM: net: JIT compiler for packet filters
From: Mircea Gherzan @ 2012-03-25 9:51 UTC (permalink / raw)
To: David Miller; +Cc: linux, netdev, linux-arm-kernel, eric.dumazet
In-Reply-To: <20120319.172005.1889334604020296555.davem@davemloft.net>
Am 19.03.2012 22:20, schrieb David Miller:
> I would like to see this merged however is feasible, this has been in
> a catatonic state for two releases and waiting longer isn't going to
> improve things enough to justify any further delay.
It has been merged into the ARM tree more than a week ago, but
unfortunately it seems it will not make it into 3.4.
Mircea
^ 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