* Re: [PATCH 08/36] aio: implement io_pgetevents
From: Christoph Hellwig @ 2018-03-20 15:22 UTC (permalink / raw)
To: Darrick J. Wong
Cc: Christoph Hellwig, viro, Avi Kivity, linux-aio, linux-fsdevel,
netdev, linux-api, linux-kernel
In-Reply-To: <20180320021241.GE7282@magnolia>
On Mon, Mar 19, 2018 at 07:12:41PM -0700, Darrick J. Wong wrote:
> > Note that unlike many other signal related calls we do not pass a sigmask
> > size, as that would get us to 7 arguments, which aren't easily supported
> > by the syscall infrastructure. It seems a lot less painful to just add a
> > new syscall variant in the unlikely case we're going to increase the
> > sigset size.
>
> I'm assuming there's a proposed manpage update for this somewhere? :)
In this commit:
http://git.infradead.org/users/hch/libaio.git/commitdiff/49f77d595210393ce7b125cb00233cf737402f56
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* Re: [PATCH net-next 0/4] net: dsa: Plug in PHYLINK support
From: David Miller @ 2018-03-20 15:28 UTC (permalink / raw)
To: f.fainelli
Cc: netdev, privat, andrew, vivien.didelot, rmk+kernel, sean.wang,
Woojung.Huh, john, cphealy
In-Reply-To: <20180318185246.19311-1-f.fainelli@gmail.com>
From: Florian Fainelli <f.fainelli@gmail.com>
Date: Sun, 18 Mar 2018 11:52:42 -0700
> This patch series adds PHYLINK support to DSA which is necessary to
> support more complex PHY and pluggable modules setups.
This series is kinda stuck in the mud because of the discussion about
putting a phylink reference into netdevice.
I think the only way to move forward is for Russell to submit his
patches again, that way we can see the requirements and discuss
them properly.
Thanks.
^ permalink raw reply
* Re: [PATCH iproute2 net-next] bridge: add option extern_learn to set NTF_EXT_LEARNED on fdb entries
From: David Ahern @ 2018-03-20 15:30 UTC (permalink / raw)
To: Roopa Prabhu; +Cc: Stephen Hemminger, netdev, Nikolay Aleksandrov
In-Reply-To: <CAJieiUi39DnWpqpu_Y38uBvB8zGEZv23AkwVxoefJQ+nFX7zLg@mail.gmail.com>
On 3/19/18 12:05 PM, Roopa Prabhu wrote:
> On Mon, Mar 19, 2018 at 10:56 AM, David Ahern <dsahern@gmail.com> wrote:
>> On 3/19/18 11:54 AM, Stephen Hemminger wrote:
>>> On Mon, 19 Mar 2018 10:20:10 -0700
>>> Roopa Prabhu <roopa@cumulusnetworks.com> wrote:
>>>
>>>> From: Roopa Prabhu <roopa@cumulusnetworks.com>
>>>>
>>>> NTF_EXT_LEARNED can be set by a user on bridge fdb entry.
>>>> Provide a bridge command option to allow a user to set
>>>> NTF_EXT_LEARNED on a bridge fdb entry.
>>>>
>>>> Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
>>>> ---
>>>> bridge/fdb.c | 4 +++-
>>>> man/man8/bridge.8 | 8 +++++++-
>>>> 2 files changed, 10 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/bridge/fdb.c b/bridge/fdb.c
>>>> index 205b4fa..4dbc894 100644
>>>> --- a/bridge/fdb.c
>>>> +++ b/bridge/fdb.c
>>>> @@ -36,7 +36,7 @@ static void usage(void)
>>>> {
>>>> fprintf(stderr,
>>>> "Usage: bridge fdb { add | append | del | replace } ADDR dev DEV\n"
>>>> - " [ self ] [ master ] [ use ] [ router ]\n"
>>>> + " [ self ] [ master ] [ use ] [ router ] [ extern_learn ]\n"
>>>> " [ local | static | dynamic ] [ dst IPADDR ] [ vlan VID ]\n"
>>>> " [ port PORT] [ vni VNI ] [ via DEV ]\n"
>>>> " bridge fdb [ show [ br BRDEV ] [ brport DEV ] [ vlan VID ] [ state STATE ] ]\n");
>>>> @@ -412,6 +412,8 @@ static int fdb_modify(int cmd, int flags, int argc, char **argv)
>>>> vid = atoi(*argv);
>>>> } else if (matches(*argv, "use") == 0) {
>>>> req.ndm.ndm_flags |= NTF_USE;
>>>> + } else if (matches(*argv, "extern_learn") == 0) {
>>>> + req.ndm.ndm_flags |= NTF_EXT_LEARNED;
>>>> } else {
>>>> if (strcmp(*argv, "to") == 0)
>>>> NEXT_ARG();
>>>> diff --git a/man/man8/bridge.8 b/man/man8/bridge.8
>>>> index 05512b0..e7f7148 100644
>>>> --- a/man/man8/bridge.8
>>>> +++ b/man/man8/bridge.8
>>>> @@ -61,7 +61,7 @@ bridge \- show / manipulate bridge addresses and devices
>>>> .B dev
>>>> .IR DEV " { "
>>>> .BR local " | " static " | " dynamic " } [ "
>>>> -.BR self " ] [ " master " ] [ " router " ] [ " use " ] [ "
>>>> +.BR self " ] [ " master " ] [ " router " ] [ " use " ] [ " extern_learn " ] [ "
>>>> .B dst
>>>> .IR IPADDR " ] [ "
>>>> .B vni
>>>> @@ -414,6 +414,12 @@ route shortcircuit enabled.
>>>> indicate to the kernel that the fdb entry is in use.
>>>> .sp
>>>>
>>>> +.B extern_learn
>>>> +- this entry was learned externally. This option can be used to
>>>> +indicate to the kernel that an entry was hardware or user-space
>>>> +controller learnt dynamic entry. Kernel will not age such an entry.
>>>> +.sp
>>>> +
>>>> .in -8
>>>> The next command line parameters apply only
>>>> when the specified device
>>>
>>>
>>> What about displaying the flag as well?
>>>
>>
>> Also, I believe other commands have converged on 'external' for the keyword.
>
>
> There is already code to display it and it displays it as
> 'extern_learn' (hence the choice of extern_learn)
>
> static void fdb_print_flags(FILE *fp, unsigned int flags)
>
> {
>
> ....
>
>
> if (flags & NTF_EXT_LEARNED)
>
> print_string(PRINT_ANY, NULL, "%s ", "extern_learn");
>
> ....
> }
>
ok. Applied to iproute2-next
^ permalink raw reply
* Re: [PATCH 08/36] aio: implement io_pgetevents
From: Jeff Moyer @ 2018-03-20 15:30 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Darrick J. Wong, viro, Avi Kivity, linux-aio, linux-fsdevel,
netdev, linux-api, linux-kernel
In-Reply-To: <20180320152220.GC23920@lst.de>
Christoph Hellwig <hch@lst.de> writes:
> On Mon, Mar 19, 2018 at 07:12:41PM -0700, Darrick J. Wong wrote:
>> > Note that unlike many other signal related calls we do not pass a sigmask
>> > size, as that would get us to 7 arguments, which aren't easily supported
>> > by the syscall infrastructure. It seems a lot less painful to just add a
>> > new syscall variant in the unlikely case we're going to increase the
>> > sigset size.
>>
>> I'm assuming there's a proposed manpage update for this somewhere? :)
>
> In this commit:
>
> http://git.infradead.org/users/hch/libaio.git/commitdiff/49f77d595210393ce7b125cb00233cf737402f56
BTW, the man pages are shipped in the man-pages package, now.
Christoph, I can forward the change to Michael after this series goes
in. Just let me know what's easiest for you.
Cheers,
Jeff
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* Re: [PATCH 08/36] aio: implement io_pgetevents
From: Christoph Hellwig @ 2018-03-20 15:31 UTC (permalink / raw)
To: Jeff Moyer
Cc: Christoph Hellwig, Darrick J. Wong, viro, Avi Kivity, linux-aio,
linux-fsdevel, netdev, linux-api, linux-kernel
In-Reply-To: <x49muz2pxwq.fsf@segfault.boston.devel.redhat.com>
On Tue, Mar 20, 2018 at 11:30:29AM -0400, Jeff Moyer wrote:
> > In this commit:
> >
> > http://git.infradead.org/users/hch/libaio.git/commitdiff/49f77d595210393ce7b125cb00233cf737402f56
>
> BTW, the man pages are shipped in the man-pages package, now.
> Christoph, I can forward the change to Michael after this series goes
> in. Just let me know what's easiest for you.
I'd be more than happy to send patch to Michael if we get these
patches merged finally :)
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* [PATCH net-next] net: mvpp2: Don't use dynamic allocs for local variables
From: Maxime Chevallier @ 2018-03-20 15:34 UTC (permalink / raw)
To: davem
Cc: Maxime Chevallier, netdev, linux-kernel, Antoine Tenart,
thomas.petazzoni, gregory.clement, miquel.raynal, nadavh, stefanc,
ymarkman, mw
Some helper functions that search for given entries in the TCAM filter
on PPv2 controller make use of dynamically alloced temporary variables,
allocated with GFP_KERNEL. These functions can be called in atomic
context, and dynamic alloc is not really needed in these cases anyways.
This commit gets rid of dynamic allocs and use stack allocation in the
following functions, and where they're used :
- mvpp2_prs_flow_find
- mvpp2_prs_vlan_find
- mvpp2_prs_double_vlan_find
- mvpp2_prs_mac_da_range_find
For all these functions, instead of returning an temporary object
representing the TCAM entry, we simply return the TCAM id that matches
the requested entry.
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
---
drivers/net/ethernet/marvell/mvpp2.c | 282 +++++++++++++++--------------------
1 file changed, 124 insertions(+), 158 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 9bd35f2291d6..2c4f096b21c3 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -1913,16 +1913,11 @@ static void mvpp2_prs_sram_offset_set(struct mvpp2_prs_entry *pe,
}
/* Find parser flow entry */
-static struct mvpp2_prs_entry *mvpp2_prs_flow_find(struct mvpp2 *priv, int flow)
+static int mvpp2_prs_flow_find(struct mvpp2 *priv, int flow)
{
- struct mvpp2_prs_entry *pe;
+ struct mvpp2_prs_entry pe;
int tid;
- pe = kzalloc(sizeof(*pe), GFP_KERNEL);
- if (!pe)
- return NULL;
- mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_FLOWS);
-
/* Go through the all entires with MVPP2_PRS_LU_FLOWS */
for (tid = MVPP2_PRS_TCAM_SRAM_SIZE - 1; tid >= 0; tid--) {
u8 bits;
@@ -1931,17 +1926,16 @@ static struct mvpp2_prs_entry *mvpp2_prs_flow_find(struct mvpp2 *priv, int flow)
priv->prs_shadow[tid].lu != MVPP2_PRS_LU_FLOWS)
continue;
- pe->index = tid;
- mvpp2_prs_hw_read(priv, pe);
- bits = mvpp2_prs_sram_ai_get(pe);
+ pe.index = tid;
+ mvpp2_prs_hw_read(priv, &pe);
+ bits = mvpp2_prs_sram_ai_get(&pe);
/* Sram store classification lookup ID in AI bits [5:0] */
if ((bits & MVPP2_PRS_FLOW_ID_MASK) == flow)
- return pe;
+ return tid;
}
- kfree(pe);
- return NULL;
+ return -ENOENT;
}
/* Return first free tcam index, seeking from start to end */
@@ -2189,16 +2183,12 @@ static void mvpp2_prs_dsa_tag_ethertype_set(struct mvpp2 *priv, int port,
}
/* Search for existing single/triple vlan entry */
-static struct mvpp2_prs_entry *mvpp2_prs_vlan_find(struct mvpp2 *priv,
- unsigned short tpid, int ai)
+static int mvpp2_prs_vlan_find(struct mvpp2 *priv, unsigned short tpid, int ai)
{
- struct mvpp2_prs_entry *pe;
+ struct mvpp2_prs_entry pe;
int tid;
- pe = kzalloc(sizeof(*pe), GFP_KERNEL);
- if (!pe)
- return NULL;
- mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
+ memset(&pe, 0, sizeof(pe));
/* Go through the all entries with MVPP2_PRS_LU_VLAN */
for (tid = MVPP2_PE_FIRST_FREE_TID;
@@ -2210,19 +2200,19 @@ static struct mvpp2_prs_entry *mvpp2_prs_vlan_find(struct mvpp2 *priv,
priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
continue;
- pe->index = tid;
+ pe.index = tid;
- mvpp2_prs_hw_read(priv, pe);
- match = mvpp2_prs_tcam_data_cmp(pe, 0, swab16(tpid));
+ mvpp2_prs_hw_read(priv, &pe);
+ match = mvpp2_prs_tcam_data_cmp(&pe, 0, swab16(tpid));
if (!match)
continue;
/* Get vlan type */
- ri_bits = mvpp2_prs_sram_ri_get(pe);
+ ri_bits = mvpp2_prs_sram_ri_get(&pe);
ri_bits &= MVPP2_PRS_RI_VLAN_MASK;
/* Get current ai value from tcam */
- ai_bits = mvpp2_prs_tcam_ai_get(pe);
+ ai_bits = mvpp2_prs_tcam_ai_get(&pe);
/* Clear double vlan bit */
ai_bits &= ~MVPP2_PRS_DBL_VLAN_AI_BIT;
@@ -2231,33 +2221,30 @@ static struct mvpp2_prs_entry *mvpp2_prs_vlan_find(struct mvpp2 *priv,
if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE ||
ri_bits == MVPP2_PRS_RI_VLAN_TRIPLE)
- return pe;
+ return tid;
}
- kfree(pe);
- return NULL;
+ return -ENOENT;
}
/* Add/update single/triple vlan entry */
static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
unsigned int port_map)
{
- struct mvpp2_prs_entry *pe;
+ struct mvpp2_prs_entry pe;
int tid_aux, tid;
int ret = 0;
- pe = mvpp2_prs_vlan_find(priv, tpid, ai);
+ tid = mvpp2_prs_vlan_find(priv, tpid, ai);
- if (!pe) {
+ if (tid < 0) {
/* Create new tcam entry */
tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_LAST_FREE_TID,
MVPP2_PE_FIRST_FREE_TID);
if (tid < 0)
return tid;
- pe = kzalloc(sizeof(*pe), GFP_KERNEL);
- if (!pe)
- return -ENOMEM;
+ memset(&pe, 0, sizeof(pe));
/* Get last double vlan tid */
for (tid_aux = MVPP2_PE_LAST_FREE_TID;
@@ -2268,49 +2255,47 @@ static int mvpp2_prs_vlan_add(struct mvpp2 *priv, unsigned short tpid, int ai,
priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
continue;
- pe->index = tid_aux;
- mvpp2_prs_hw_read(priv, pe);
- ri_bits = mvpp2_prs_sram_ri_get(pe);
+ pe.index = tid_aux;
+ mvpp2_prs_hw_read(priv, &pe);
+ ri_bits = mvpp2_prs_sram_ri_get(&pe);
if ((ri_bits & MVPP2_PRS_RI_VLAN_MASK) ==
MVPP2_PRS_RI_VLAN_DOUBLE)
break;
}
- if (tid <= tid_aux) {
- ret = -EINVAL;
- goto free_pe;
- }
+ if (tid <= tid_aux)
+ return -EINVAL;
- memset(pe, 0, sizeof(*pe));
- mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
- pe->index = tid;
+ memset(&pe, 0, sizeof(pe));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VLAN);
+ pe.index = tid;
- mvpp2_prs_match_etype(pe, 0, tpid);
+ mvpp2_prs_match_etype(&pe, 0, tpid);
/* VLAN tag detected, proceed with VID filtering */
- mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_VID);
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VID);
/* Clear all ai bits for next iteration */
- mvpp2_prs_sram_ai_update(pe, 0, MVPP2_PRS_SRAM_AI_MASK);
+ mvpp2_prs_sram_ai_update(&pe, 0, MVPP2_PRS_SRAM_AI_MASK);
if (ai == MVPP2_PRS_SINGLE_VLAN_AI) {
- mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_SINGLE,
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_SINGLE,
MVPP2_PRS_RI_VLAN_MASK);
} else {
ai |= MVPP2_PRS_DBL_VLAN_AI_BIT;
- mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_TRIPLE,
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_TRIPLE,
MVPP2_PRS_RI_VLAN_MASK);
}
- mvpp2_prs_tcam_ai_update(pe, ai, MVPP2_PRS_SRAM_AI_MASK);
+ mvpp2_prs_tcam_ai_update(&pe, ai, MVPP2_PRS_SRAM_AI_MASK);
- mvpp2_prs_shadow_set(priv, pe->index, MVPP2_PRS_LU_VLAN);
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN);
+ } else {
+ mvpp2_prs_hw_read(priv, &pe);
}
/* Update ports' mask */
- mvpp2_prs_tcam_port_map_set(pe, port_map);
+ mvpp2_prs_tcam_port_map_set(&pe, port_map);
- mvpp2_prs_hw_write(priv, pe);
-free_pe:
- kfree(pe);
+ mvpp2_prs_hw_write(priv, &pe);
return ret;
}
@@ -2329,17 +2314,14 @@ static int mvpp2_prs_double_vlan_ai_free_get(struct mvpp2 *priv)
}
/* Search for existing double vlan entry */
-static struct mvpp2_prs_entry *mvpp2_prs_double_vlan_find(struct mvpp2 *priv,
- unsigned short tpid1,
- unsigned short tpid2)
+static int mvpp2_prs_double_vlan_find(struct mvpp2 *priv, unsigned short tpid1,
+ unsigned short tpid2)
{
- struct mvpp2_prs_entry *pe;
+ struct mvpp2_prs_entry pe;
int tid;
- pe = kzalloc(sizeof(*pe), GFP_KERNEL);
- if (!pe)
- return NULL;
- mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
+ memset(&pe, 0, sizeof(pe));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VLAN);
/* Go through the all entries with MVPP2_PRS_LU_VLAN */
for (tid = MVPP2_PE_FIRST_FREE_TID;
@@ -2351,22 +2333,21 @@ static struct mvpp2_prs_entry *mvpp2_prs_double_vlan_find(struct mvpp2 *priv,
priv->prs_shadow[tid].lu != MVPP2_PRS_LU_VLAN)
continue;
- pe->index = tid;
- mvpp2_prs_hw_read(priv, pe);
+ pe.index = tid;
+ mvpp2_prs_hw_read(priv, &pe);
- match = mvpp2_prs_tcam_data_cmp(pe, 0, swab16(tpid1))
- && mvpp2_prs_tcam_data_cmp(pe, 4, swab16(tpid2));
+ match = mvpp2_prs_tcam_data_cmp(&pe, 0, swab16(tpid1)) &&
+ mvpp2_prs_tcam_data_cmp(&pe, 4, swab16(tpid2));
if (!match)
continue;
- ri_mask = mvpp2_prs_sram_ri_get(pe) & MVPP2_PRS_RI_VLAN_MASK;
+ ri_mask = mvpp2_prs_sram_ri_get(&pe) & MVPP2_PRS_RI_VLAN_MASK;
if (ri_mask == MVPP2_PRS_RI_VLAN_DOUBLE)
- return pe;
+ return tid;
}
- kfree(pe);
- return NULL;
+ return -ENOENT;
}
/* Add or update double vlan entry */
@@ -2374,28 +2355,24 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
unsigned short tpid2,
unsigned int port_map)
{
- struct mvpp2_prs_entry *pe;
+ struct mvpp2_prs_entry pe;
int tid_aux, tid, ai, ret = 0;
- pe = mvpp2_prs_double_vlan_find(priv, tpid1, tpid2);
+ tid = mvpp2_prs_double_vlan_find(priv, tpid1, tpid2);
- if (!pe) {
+ if (tid < 0) {
/* Create new tcam entry */
tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID,
MVPP2_PE_LAST_FREE_TID);
if (tid < 0)
return tid;
- pe = kzalloc(sizeof(*pe), GFP_KERNEL);
- if (!pe)
- return -ENOMEM;
+ memset(&pe, 0, sizeof(pe));
/* Set ai value for new double vlan entry */
ai = mvpp2_prs_double_vlan_ai_free_get(priv);
- if (ai < 0) {
- ret = ai;
- goto free_pe;
- }
+ if (ai < 0)
+ return ai;
/* Get first single/triple vlan tid */
for (tid_aux = MVPP2_PE_FIRST_FREE_TID;
@@ -2406,9 +2383,9 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
priv->prs_shadow[tid_aux].lu != MVPP2_PRS_LU_VLAN)
continue;
- pe->index = tid_aux;
- mvpp2_prs_hw_read(priv, pe);
- ri_bits = mvpp2_prs_sram_ri_get(pe);
+ pe.index = tid_aux;
+ mvpp2_prs_hw_read(priv, &pe);
+ ri_bits = mvpp2_prs_sram_ri_get(&pe);
ri_bits &= MVPP2_PRS_RI_VLAN_MASK;
if (ri_bits == MVPP2_PRS_RI_VLAN_SINGLE ||
ri_bits == MVPP2_PRS_RI_VLAN_TRIPLE)
@@ -2416,36 +2393,36 @@ static int mvpp2_prs_double_vlan_add(struct mvpp2 *priv, unsigned short tpid1,
}
if (tid >= tid_aux) {
- ret = -ERANGE;
- goto free_pe;
+ return -ERANGE;
}
- memset(pe, 0, sizeof(*pe));
- mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_VLAN);
- pe->index = tid;
+ memset(&pe, 0, sizeof(pe));
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_VLAN);
+ pe.index = tid;
priv->prs_double_vlans[ai] = true;
- mvpp2_prs_match_etype(pe, 0, tpid1);
- mvpp2_prs_match_etype(pe, 4, tpid2);
+ mvpp2_prs_match_etype(&pe, 0, tpid1);
+ mvpp2_prs_match_etype(&pe, 4, tpid2);
- mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_VLAN);
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_VLAN);
/* Shift 4 bytes - skip outer vlan tag */
- mvpp2_prs_sram_shift_set(pe, MVPP2_VLAN_TAG_LEN,
+ mvpp2_prs_sram_shift_set(&pe, MVPP2_VLAN_TAG_LEN,
MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
- mvpp2_prs_sram_ri_update(pe, MVPP2_PRS_RI_VLAN_DOUBLE,
+ mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_VLAN_DOUBLE,
MVPP2_PRS_RI_VLAN_MASK);
- mvpp2_prs_sram_ai_update(pe, ai | MVPP2_PRS_DBL_VLAN_AI_BIT,
+ mvpp2_prs_sram_ai_update(&pe, ai | MVPP2_PRS_DBL_VLAN_AI_BIT,
MVPP2_PRS_SRAM_AI_MASK);
- mvpp2_prs_shadow_set(priv, pe->index, MVPP2_PRS_LU_VLAN);
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_VLAN);
+ } else {
+ mvpp2_prs_hw_read(priv, &pe);
}
/* Update ports' mask */
- mvpp2_prs_tcam_port_map_set(pe, port_map);
- mvpp2_prs_hw_write(priv, pe);
-free_pe:
- kfree(pe);
+ mvpp2_prs_tcam_port_map_set(&pe, port_map);
+ mvpp2_prs_hw_write(priv, &pe);
+
return ret;
}
@@ -3528,7 +3505,7 @@ static int mvpp2_prs_vid_range_find(struct mvpp2 *priv, int pmap, u16 vid,
return tid;
}
- return 0;
+ return -ENOENT;
}
/* Write parser entry for VID filtering */
@@ -3551,7 +3528,7 @@ static int mvpp2_prs_vid_entry_add(struct mvpp2_port *port, u16 vid)
shift = MVPP2_VLAN_TAG_LEN;
/* No such entry */
- if (!tid) {
+ if (tid < 0) {
memset(&pe, 0, sizeof(pe));
/* Go through all entries from first to last in vlan range */
@@ -3604,7 +3581,7 @@ static void mvpp2_prs_vid_entry_remove(struct mvpp2_port *port, u16 vid)
tid = mvpp2_prs_vid_range_find(priv, (1 << port->id), vid, 0xfff);
/* No such entry */
- if (tid)
+ if (tid < 0)
return;
mvpp2_prs_hw_inv(priv, tid);
@@ -3771,18 +3748,13 @@ static bool mvpp2_prs_mac_range_equals(struct mvpp2_prs_entry *pe,
}
/* Find tcam entry with matched pair <MAC DA, port> */
-static struct mvpp2_prs_entry *
+static int
mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
unsigned char *mask, int udf_type)
{
- struct mvpp2_prs_entry *pe;
+ struct mvpp2_prs_entry pe;
int tid;
- pe = kzalloc(sizeof(*pe), GFP_ATOMIC);
- if (!pe)
- return NULL;
- mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC);
-
/* Go through the all entires with MVPP2_PRS_LU_MAC */
for (tid = MVPP2_PE_MAC_RANGE_START;
tid <= MVPP2_PE_MAC_RANGE_END; tid++) {
@@ -3793,17 +3765,16 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
(priv->prs_shadow[tid].udf != udf_type))
continue;
- pe->index = tid;
- mvpp2_prs_hw_read(priv, pe);
- entry_pmap = mvpp2_prs_tcam_port_map_get(pe);
+ pe.index = tid;
+ mvpp2_prs_hw_read(priv, &pe);
+ entry_pmap = mvpp2_prs_tcam_port_map_get(&pe);
- if (mvpp2_prs_mac_range_equals(pe, da, mask) &&
+ if (mvpp2_prs_mac_range_equals(&pe, da, mask) &&
entry_pmap == pmap)
- return pe;
+ return tid;
}
- kfree(pe);
- return NULL;
+ return -ENOENT;
}
/* Update parser's mac da entry */
@@ -3813,15 +3784,15 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da,
unsigned char mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
struct mvpp2 *priv = port->priv;
unsigned int pmap, len, ri;
- struct mvpp2_prs_entry *pe;
+ struct mvpp2_prs_entry pe;
int tid;
/* Scan TCAM and see if entry with this <MAC DA, port> already exist */
- pe = mvpp2_prs_mac_da_range_find(priv, BIT(port->id), da, mask,
- MVPP2_PRS_UDF_MAC_DEF);
+ tid = mvpp2_prs_mac_da_range_find(priv, BIT(port->id), da, mask,
+ MVPP2_PRS_UDF_MAC_DEF);
/* No such entry */
- if (!pe) {
+ if (tid < 0) {
if (!add)
return 0;
@@ -3833,39 +3804,39 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da,
if (tid < 0)
return tid;
- pe = kzalloc(sizeof(*pe), GFP_ATOMIC);
- if (!pe)
- return -ENOMEM;
- mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC);
- pe->index = tid;
+ memset(&pe, 0, sizeof(pe));
+
+ pe.index = tid;
/* Mask all ports */
- mvpp2_prs_tcam_port_map_set(pe, 0);
+ mvpp2_prs_tcam_port_map_set(&pe, 0);
+ } else {
+ mvpp2_prs_hw_read(priv, &pe);
}
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC);
+
/* Update port mask */
- mvpp2_prs_tcam_port_set(pe, port->id, add);
+ mvpp2_prs_tcam_port_set(&pe, port->id, add);
/* Invalidate the entry if no ports are left enabled */
- pmap = mvpp2_prs_tcam_port_map_get(pe);
+ pmap = mvpp2_prs_tcam_port_map_get(&pe);
if (pmap == 0) {
if (add) {
- kfree(pe);
return -EINVAL;
}
- mvpp2_prs_hw_inv(priv, pe->index);
- priv->prs_shadow[pe->index].valid = false;
- kfree(pe);
+ mvpp2_prs_hw_inv(priv, pe.index);
+ priv->prs_shadow[pe.index].valid = false;
return 0;
}
/* Continue - set next lookup */
- mvpp2_prs_sram_next_lu_set(pe, MVPP2_PRS_LU_DSA);
+ mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_DSA);
/* Set match on DA */
len = ETH_ALEN;
while (len--)
- mvpp2_prs_tcam_data_byte_set(pe, len, da[len], 0xff);
+ mvpp2_prs_tcam_data_byte_set(&pe, len, da[len], 0xff);
/* Set result info bits */
if (is_broadcast_ether_addr(da)) {
@@ -3879,21 +3850,19 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2_port *port, const u8 *da,
ri |= MVPP2_PRS_RI_MAC_ME_MASK;
}
- mvpp2_prs_sram_ri_update(pe, ri, MVPP2_PRS_RI_L2_CAST_MASK |
+ mvpp2_prs_sram_ri_update(&pe, ri, MVPP2_PRS_RI_L2_CAST_MASK |
MVPP2_PRS_RI_MAC_ME_MASK);
- mvpp2_prs_shadow_ri_set(priv, pe->index, ri, MVPP2_PRS_RI_L2_CAST_MASK |
+ mvpp2_prs_shadow_ri_set(priv, pe.index, ri, MVPP2_PRS_RI_L2_CAST_MASK |
MVPP2_PRS_RI_MAC_ME_MASK);
/* Shift to ethertype */
- mvpp2_prs_sram_shift_set(pe, 2 * ETH_ALEN,
+ mvpp2_prs_sram_shift_set(&pe, 2 * ETH_ALEN,
MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD);
/* Update shadow table and hw entry */
- priv->prs_shadow[pe->index].udf = MVPP2_PRS_UDF_MAC_DEF;
- mvpp2_prs_shadow_set(priv, pe->index, MVPP2_PRS_LU_MAC);
- mvpp2_prs_hw_write(priv, pe);
-
- kfree(pe);
+ priv->prs_shadow[pe.index].udf = MVPP2_PRS_UDF_MAC_DEF;
+ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC);
+ mvpp2_prs_hw_write(priv, &pe);
return 0;
}
@@ -4014,13 +3983,13 @@ static int mvpp2_prs_tag_mode_set(struct mvpp2 *priv, int port, int type)
/* Set prs flow for the port */
static int mvpp2_prs_def_flow(struct mvpp2_port *port)
{
- struct mvpp2_prs_entry *pe;
+ struct mvpp2_prs_entry pe;
int tid;
- pe = mvpp2_prs_flow_find(port->priv, port->id);
+ tid = mvpp2_prs_flow_find(port->priv, port->id);
/* Such entry not exist */
- if (!pe) {
+ if (tid < 0) {
/* Go through the all entires from last to first */
tid = mvpp2_prs_tcam_first_free(port->priv,
MVPP2_PE_LAST_FREE_TID,
@@ -4028,24 +3997,21 @@ static int mvpp2_prs_def_flow(struct mvpp2_port *port)
if (tid < 0)
return tid;
- pe = kzalloc(sizeof(*pe), GFP_KERNEL);
- if (!pe)
- return -ENOMEM;
-
- mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_FLOWS);
- pe->index = tid;
+ pe.index = tid;
/* Set flow ID*/
- mvpp2_prs_sram_ai_update(pe, port->id, MVPP2_PRS_FLOW_ID_MASK);
- mvpp2_prs_sram_bits_set(pe, MVPP2_PRS_SRAM_LU_DONE_BIT, 1);
+ mvpp2_prs_sram_ai_update(&pe, port->id, MVPP2_PRS_FLOW_ID_MASK);
+ mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_DONE_BIT, 1);
/* Update shadow table */
- mvpp2_prs_shadow_set(port->priv, pe->index, MVPP2_PRS_LU_FLOWS);
+ mvpp2_prs_shadow_set(port->priv, pe.index, MVPP2_PRS_LU_FLOWS);
+ } else {
+ mvpp2_prs_hw_read(port->priv, &pe);
}
- mvpp2_prs_tcam_port_map_set(pe, (1 << port->id));
- mvpp2_prs_hw_write(port->priv, pe);
- kfree(pe);
+ mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_FLOWS);
+ mvpp2_prs_tcam_port_map_set(&pe, (1 << port->id));
+ mvpp2_prs_hw_write(port->priv, &pe);
return 0;
}
--
2.11.0
^ permalink raw reply related
* Re: [PATCH 08/36] aio: implement io_pgetevents
From: Jeff Moyer @ 2018-03-20 15:34 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Darrick J. Wong, viro, Avi Kivity, linux-aio, linux-fsdevel,
netdev, linux-api, linux-kernel
In-Reply-To: <20180320153145.GA24313@lst.de>
Christoph Hellwig <hch@lst.de> writes:
> On Tue, Mar 20, 2018 at 11:30:29AM -0400, Jeff Moyer wrote:
>> > In this commit:
>> >
>> > http://git.infradead.org/users/hch/libaio.git/commitdiff/49f77d595210393ce7b125cb00233cf737402f56
>>
>> BTW, the man pages are shipped in the man-pages package, now.
>> Christoph, I can forward the change to Michael after this series goes
>> in. Just let me know what's easiest for you.
>
> I'd be more than happy to send patch to Michael if we get these
> patches merged finally :)
hahaha, least of your problems, I know. :)
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* Re: [PATCH] net: dev_forward_skb(): Scrub packet's per-netns info only when crossing netns
From: Liran Alon @ 2018-03-20 15:34 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-kernel, idan.brown, yuval.shaia
In-Reply-To: <20180320.104759.796804827689233281.davem@davemloft.net>
On 20/03/18 16:47, David Miller wrote:
> From: Liran Alon <liran.alon@oracle.com>
> Date: Tue, 13 Mar 2018 17:07:22 +0200
>
>> Before this commit, dev_forward_skb() always cleared packet's
>> per-network-namespace info. Even if the packet doesn't cross
>> network namespaces.
>
> There was a lot of discussion about this patch.
>
> Particularly whether it could potentially break current
> users or not.
>
> If this is resolved and the patch should still be applied,
> please repost and the folks involved in this dicussion should
> add their ACKs.
>
> Thanks.
>
The problem is that I don't think we have reached an agreement.
I would be happy to here your opinion on the issue at hand here.
I personally don't understand why we should maintain
backwards-comparability to this behaviour. How would a user rely on the
fact that skb->mark is scrubbed when it is passed between 2 netdevs on
the same netns but only when it is passed between very specific netdev
type (one of them being veth-peers).
This behaviour seems to have been created by mistake.
This feature is not documented to user-mode and I don't see why it is
legit for the user to rely on it.
In addition, even if we do want to maintain backwards-comparability to
this behaviour, I think it is enough to have an opt-in flag in
/proc/sys/net/core/ that when set to 1 will activate the fix in
dev_forward_skb() provided by this patch. That would also be a very
simple change to the patch provided here.
Do you agree? Or do you think we should have a flag per netdev like
suggested in other replies to this thread?
Thanks,
-Liran
^ permalink raw reply
* Re: Fw: [Bug 199109] New: pptp: kernel printk "recursion detected", and then reboot itself
From: Guillaume Nault @ 2018-03-20 15:38 UTC (permalink / raw)
To: xu heng; +Cc: Stephen Hemminger, xeb, netdev
In-Reply-To: <20180316200240.GK1351@alphalink.fr>
On Fri, Mar 16, 2018 at 09:02:40PM +0100, Guillaume Nault wrote:
> On Fri, Mar 16, 2018 at 02:49:40PM +0800, xu heng wrote:
> >
> > For testing, in __ppp_channel_push(), disable sending anything from the attached unit, just disable __ppp_xmit_process(ppp) in __ppp_channel_push(). In my opinion, __ppp_xmit_process() should only called by ppp_xmit_process(), because of ppp->xmit_recursion __percpu.
> >
> ppp_channel_push() needs to call __ppp_xmit_process() because some
> drivers (like ppp_async) need to notify ppp_generic when they can
> accept new packets. This is done by ppp_output_wakeup() which then
> calls ppp_channel_push(). So we have to handle the unit backlog there.
>
>
> Please try the following patch (untested).
>
FYI, I've now fully tested the patch. I'm going to send it formally.
> diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
> index b883af93929c..af22eb11bbaa 100644
> --- a/drivers/net/ppp/ppp_generic.c
> +++ b/drivers/net/ppp/ppp_generic.c
> @@ -255,7 +255,7 @@ struct ppp_net {
> /* Prototypes. */
> static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
> struct file *file, unsigned int cmd, unsigned long arg);
> -static void ppp_xmit_process(struct ppp *ppp);
> +static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb);
> static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb);
> static void ppp_push(struct ppp *ppp);
> static void ppp_channel_push(struct channel *pch);
> @@ -511,13 +511,12 @@ static ssize_t ppp_write(struct file *file, const char __user *buf,
> goto out;
> }
>
> - skb_queue_tail(&pf->xq, skb);
> -
> switch (pf->kind) {
> case INTERFACE:
> - ppp_xmit_process(PF_TO_PPP(pf));
> + ppp_xmit_process(PF_TO_PPP(pf), skb);
> break;
> case CHANNEL:
> + skb_queue_tail(&pf->xq, skb);
> ppp_channel_push(PF_TO_CHANNEL(pf));
> break;
> }
> @@ -1260,8 +1259,8 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
> put_unaligned_be16(proto, pp);
>
> skb_scrub_packet(skb, !net_eq(ppp->ppp_net, dev_net(dev)));
> - skb_queue_tail(&ppp->file.xq, skb);
> - ppp_xmit_process(ppp);
> + ppp_xmit_process(ppp, skb);
> +
> return NETDEV_TX_OK;
>
> outf:
> @@ -1415,13 +1414,14 @@ static void ppp_setup(struct net_device *dev)
> */
>
> /* Called to do any work queued up on the transmit side that can now be done */
> -static void __ppp_xmit_process(struct ppp *ppp)
> +static void __ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb)
> {
> - struct sk_buff *skb;
> -
> ppp_xmit_lock(ppp);
> if (!ppp->closing) {
> ppp_push(ppp);
> +
> + if (skb)
> + skb_queue_tail(&ppp->file.xq, skb);
> while (!ppp->xmit_pending &&
> (skb = skb_dequeue(&ppp->file.xq)))
> ppp_send_frame(ppp, skb);
> @@ -1435,7 +1435,7 @@ static void __ppp_xmit_process(struct ppp *ppp)
> ppp_xmit_unlock(ppp);
> }
>
> -static void ppp_xmit_process(struct ppp *ppp)
> +static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb)
> {
> local_bh_disable();
>
> @@ -1443,7 +1443,7 @@ static void ppp_xmit_process(struct ppp *ppp)
> goto err;
>
> (*this_cpu_ptr(ppp->xmit_recursion))++;
> - __ppp_xmit_process(ppp);
> + __ppp_xmit_process(ppp, skb);
> (*this_cpu_ptr(ppp->xmit_recursion))--;
>
> local_bh_enable();
> @@ -1452,6 +1452,7 @@ static void ppp_xmit_process(struct ppp *ppp)
>
> err:
> local_bh_enable();
> + kfree_skb(skb);
>
> if (net_ratelimit())
> netdev_err(ppp->dev, "recursion detected\n");
> @@ -1937,7 +1938,7 @@ static void __ppp_channel_push(struct channel *pch)
> if (skb_queue_empty(&pch->file.xq)) {
> ppp = pch->ppp;
> if (ppp)
> - __ppp_xmit_process(ppp);
> + __ppp_xmit_process(ppp, NULL);
> }
> }
>
>
^ permalink raw reply
* Re: [PATCH 13/36] fs: introduce new ->get_poll_head and ->poll_mask methods
From: Christoph Hellwig @ 2018-03-20 15:39 UTC (permalink / raw)
To: Darrick J. Wong
Cc: Christoph Hellwig, viro, Avi Kivity, linux-aio, linux-fsdevel,
netdev, linux-api, linux-kernel
In-Reply-To: <20180320032938.GK7282@magnolia>
On Mon, Mar 19, 2018 at 08:29:38PM -0700, Darrick J. Wong wrote:
> On Mon, Mar 05, 2018 at 01:27:20PM -0800, Christoph Hellwig wrote:
> > ->get_poll_head returns the waitqueue that the poll operation is going
> > to sleep on. Note that this means we can only use a single waitqueue
> > for the poll, unlike some current drivers that use two waitqueues for
> > different events. But now that we have keyed wakeups and heavily use
> > those for poll there aren't that many good reason left to keep the
> > multiple waitqueues, and if there are any ->poll is still around, the
> > driver just won't support aio poll.
> >
> > Signed-off-by: Christoph Hellwig <hch@lst.de>
>
> I've been wondering, how does a regular filesystem connect with this?
In general, it doesn't. In Unix regular files aren't pollable.
> Also, does anything implement get_poll_head? It looks to me like an aio
> poll provider has to provide both...
Yes. Everyone who implements ->poll_mask also needs to implement
get_poll_head. For sockets we just happen to be able to use a generic
implementation in net/socket.c for most of them.
--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org. For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>
^ permalink raw reply
* Re: [RFC] ethtool: Support ETHTOOL_GSTATS2 command.
From: Ben Greear @ 2018-03-20 15:39 UTC (permalink / raw)
To: Michal Kubecek
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
ath10k-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20180320103747.7kcfdu4yzof6bwxw-OEaqT8BN2ewCVLCxKZUutA@public.gmane.org>
On 03/20/2018 03:37 AM, Michal Kubecek wrote:
> On Wed, Mar 07, 2018 at 11:51:29AM -0800, greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org wrote:
>> From: Ben Greear <greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org>
>>
>> This is similar to ETHTOOL_GSTATS, but it allows you to specify
>> a 'level'. This level can be used by the driver to decrease the
>> amount of stats refreshed. In particular, this helps with ath10k
>> since getting the firmware stats can be slow.
>>
>> Signed-off-by: Ben Greear <greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org>
>> ---
>>
>> NOTE: I know to make it upstream I would need to split the patch and
>> remove the #define for 'backporting' that I added. But, is the
>> feature in general wanted? If so, I'll do the patch split and
>> other tweaks that might be suggested.
>
> I'm not familiar enough with the technical background of stats
> collecting to comment on usefulness and desirability of this feature.
> Adding a new command just to add a numeric parameter certainly doesn't
> feel right but it's how the ioctl interface works. I take it as
> a reminder to find some time to get back to the netlink interface.
>
>> diff --git a/net/core/ethtool.c b/net/core/ethtool.c
>> index 674b6c9..d3b709f 100644
>> --- a/net/core/ethtool.c
>> +++ b/net/core/ethtool.c
>> @@ -1947,6 +1947,54 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
>> return ret;
>> }
>>
>> +static int ethtool_get_stats2(struct net_device *dev, void __user *useraddr)
>> +{
>> + struct ethtool_stats stats;
>> + const struct ethtool_ops *ops = dev->ethtool_ops;
>> + u64 *data;
>> + int ret, n_stats;
>> + u32 stats_level = 0;
>> +
>> + if (!ops->get_ethtool_stats2 || !ops->get_sset_count)
>> + return -EOPNOTSUPP;
>> +
>> + n_stats = ops->get_sset_count(dev, ETH_SS_STATS);
>> + if (n_stats < 0)
>> + return n_stats;
>> + if (n_stats > S32_MAX / sizeof(u64))
>> + return -ENOMEM;
>> + WARN_ON_ONCE(!n_stats);
>> + if (copy_from_user(&stats, useraddr, sizeof(stats)))
>> + return -EFAULT;
>> +
>> + /* User can specify the level of stats to query. How the
>> + * level value is used is up to the driver, but in general,
>> + * 0 means 'all', 1 means least, and higher means more.
>> + * The idea is that some stats may be expensive to query, so user
>> + * space could just ask for the cheap ones...
>> + */
>> + stats_level = stats.n_stats;
>> +
>> + stats.n_stats = n_stats;
>> + data = vzalloc(n_stats * sizeof(u64));
>> + if (n_stats && !data)
>> + return -ENOMEM;
>> +
>> + ops->get_ethtool_stats2(dev, &stats, data, stats_level);
>> +
>> + ret = -EFAULT;
>> + if (copy_to_user(useraddr, &stats, sizeof(stats)))
>> + goto out;
>> + useraddr += sizeof(stats);
>> + if (n_stats && copy_to_user(useraddr, data, n_stats * sizeof(u64)))
>> + goto out;
>> + ret = 0;
>> +
>> + out:
>> + vfree(data);
>> + return ret;
>> +}
>> +
>> static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr)
>> {
>> struct ethtool_stats stats;
>
> IMHO it would be more practical to set "0 means same as GSTATS" as a
> rule and make ethtool_get_stats() a wrapper for ethtool_get_stats2() to
> avoid code duplication (or perhaps a use fall-through in the switch). It
> would also allow drivers to provide only one of the callbacks.
Yes, but that would require changing all drivers at once, and would make backporting
and out-of-tree drivers harder to manage. I had low hopes that this feature would
make it upstream, so I didn't want to propose any large changes up front.
Thanks,
Ben
--
Ben Greear <greearb-my8/4N5VtI7c+919tysfdA@public.gmane.org>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: [PATCH iproute2 1/5] ip: use strlcpy() to avoid truncation
From: David Ahern @ 2018-03-20 15:44 UTC (permalink / raw)
To: Stephen Hemminger, netdev
In-Reply-To: <20180319165638.30166-2-stephen@networkplumber.org>
On 3/19/18 10:56 AM, Stephen Hemminger wrote:
> diff --git a/lib/namespace.c b/lib/namespace.c
> index 6f3356d0fa08..682634028587 100644
> --- a/lib/namespace.c
> +++ b/lib/namespace.c
> @@ -23,7 +23,8 @@ static void bind_etc(const char *name)
> struct dirent *entry;
> DIR *dir;
>
> - snprintf(etc_netns_path, sizeof(etc_netns_path), "%s/%s", NETNS_ETC_DIR, name);
> + snprintf(etc_netns_path, sizeof(etc_netns_path), "%s/%s",
> + NETNS_ETC_DIR, name);
> dir = opendir(etc_netns_path);
> if (!dir)
> return;
> @@ -33,7 +34,8 @@ static void bind_etc(const char *name)
> continue;
> if (strcmp(entry->d_name, "..") == 0)
> continue;
> - snprintf(netns_name, sizeof(netns_name), "%s/%s", etc_netns_path, entry->d_name);
> + snprintf(netns_name, sizeof(netns_name),
> + "%s/%s", etc_netns_path, entry->d_name);
> snprintf(etc_name, sizeof(etc_name), "/etc/%s", entry->d_name);
> if (mount(netns_name, etc_name, "none", MS_BIND, NULL) < 0) {
> fprintf(stderr, "Bind %s -> %s failed: %s\n",
above is unrelated to strncpy -> strlcpy change And pretty much
everything below as well.
> diff --git a/misc/nstat.c b/misc/nstat.c
> index a4dd405d43a9..433a1f483be3 100644
> --- a/misc/nstat.c
> +++ b/misc/nstat.c
> @@ -178,12 +178,12 @@ static int count_spaces(const char *line)
>
> static void load_ugly_table(FILE *fp)
> {
> - char buf[4096];
> + char buf[2048];
> struct nstat_ent *db = NULL;
> struct nstat_ent *n;
>
> while (fgets(buf, sizeof(buf), fp) != NULL) {
> - char idbuf[sizeof(buf)];
> + char idbuf[4096];
Also, I don't understand why you flipped the sizes with idbuf twice as
large as buf.
> int off;
> char *p;
> int count1, count2, skip = 0;
> diff --git a/misc/ss.c b/misc/ss.c
> index e087bef739b0..a03fa4a7c174 100644
> --- a/misc/ss.c
> +++ b/misc/ss.c
> @@ -4032,7 +4032,7 @@ static int netlink_show_one(struct filter *f,
>
> if (!pid) {
> done = 1;
> - strncpy(procname, "kernel", 6);
> + strncpy(procname, "kernel", 7);
> } else if (pid > 0) {
> FILE *fp;
>
> diff --git a/tc/m_ematch.c b/tc/m_ematch.c
> index d2bb5c380382..ee8981f0146c 100644
> --- a/tc/m_ematch.c
> +++ b/tc/m_ematch.c
> @@ -161,7 +161,7 @@ static struct ematch_util *get_ematch_kind(char *kind)
>
> static struct ematch_util *get_ematch_kind_num(__u16 kind)
> {
> - char name[32];
> + char name[512];
why the size bump?
>
> if (lookup_map(kind, name, sizeof(name), EMATCH_MAP) < 0)
> return NULL;
> diff --git a/tc/tc_class.c b/tc/tc_class.c
> index 1b214b82c702..91802518bb27 100644
> --- a/tc/tc_class.c
> +++ b/tc/tc_class.c
> @@ -219,7 +219,7 @@ static void graph_cls_show(FILE *fp, char *buf, struct hlist_head *root_list,
> char cls_id_str[256] = {};
> struct rtattr *tb[TCA_MAX + 1];
> struct qdisc_util *q;
> - char str[100] = {};
> + char str[300] = {};
and here.
>
> hlist_for_each_safe(n, tmp_cls, root_list) {
> struct hlist_node *c, *tmp_chld;
> @@ -242,7 +242,8 @@ static void graph_cls_show(FILE *fp, char *buf, struct hlist_head *root_list,
> graph_indent(buf, cls, 0, 0);
>
> print_tc_classid(cls_id_str, sizeof(cls_id_str), cls->id);
> - sprintf(str, "+---(%s)", cls_id_str);
> + snprintf(str, sizeof(str),
> + "+---(%s)", cls_id_str);
That can all fit on one line.
> strcat(buf, str);
>
> parse_rtattr(tb, TCA_MAX, (struct rtattr *)cls->data,
>
^ permalink raw reply
* Re: [PATCH iproute2 2/5] tunnel: use strlcpy to avoid strncpy warnings
From: David Ahern @ 2018-03-20 15:47 UTC (permalink / raw)
To: Stephen Hemminger, netdev
In-Reply-To: <20180319165638.30166-3-stephen@networkplumber.org>
On 3/19/18 10:56 AM, Stephen Hemminger wrote:
> Fixes warnings about strncpy size by using strlcpy.
>
> tunnel.c: In function ‘tnl_gen_ioctl’:
> tunnel.c:145:2: warning: ‘strncpy’ specified bound 16 equals destination size [-Wstringop-truncation]
> strncpy(ifr.ifr_name, name, IFNAMSIZ);
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
> ip/tunnel.c | 12 ++++++------
> 1 file changed, 6 insertions(+), 6 deletions(-)
>
Acked-by: David Ahern <dsahern@gmail.com>
^ permalink raw reply
* Re: [PATCH iproute2 3/5] bridge: avoid snprint truncation on time
From: David Ahern @ 2018-03-20 15:47 UTC (permalink / raw)
To: Stephen Hemminger, netdev
In-Reply-To: <20180319165638.30166-4-stephen@networkplumber.org>
On 3/19/18 10:56 AM, Stephen Hemminger wrote:
> This fixes new gcc warning about possible string overflow.
>
> mdb.c: In function ‘__print_router_port_stats’:
> mdb.c:61:11: warning: ‘%.2i’ directive output may be truncated writing between 2 and 7 bytes into a region of size between 0 and 4 [-Wformat-truncation=]
> "%4i.%.2i", (int)tv.tv_sec,
> ^~~~
>
> Note: already fixed in iproute2-next.
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
> bridge/mdb.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
Acked-by: David Ahern <dsahern@gmail.com>
^ permalink raw reply
* Re: [PATCH iproute2 4/5] pedit: fix strncpy warning
From: David Ahern @ 2018-03-20 15:48 UTC (permalink / raw)
To: Stephen Hemminger, netdev
In-Reply-To: <20180319165638.30166-5-stephen@networkplumber.org>
On 3/19/18 10:56 AM, Stephen Hemminger wrote:
> Newer versions of Gcc warn about string truncation.
> Fix by using strlcpy.
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
> tc/m_pedit.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
Acked-by: David Ahern <dsahern@gmail.com>
^ permalink raw reply
* Re: linux-next: ip6tables *broken* - last base chain position %u doesn't match underflow %u (hook %u
From: Florian Westphal @ 2018-03-20 15:48 UTC (permalink / raw)
To: valdis.kletnieks
Cc: Florian Westphal, Pablo Neira Ayuso, netdev, linux-kernel
In-Reply-To: <24374.1521559053@turing-police.cc.vt.edu>
valdis.kletnieks@vt.edu <valdis.kletnieks@vt.edu> wrote:
> (Resending because I haven't heard anything)
[ ip6tables broken ]
Sorry, did not see this email before.
I'll investigate asap, thanks for the detailed report.
^ permalink raw reply
* [PATCH net] ppp: avoid loop in xmit recursion detection code
From: Guillaume Nault @ 2018-03-20 15:49 UTC (permalink / raw)
To: netdev; +Cc: Paul Mackerras, xu heng, xeb, Stephen Hemminger
We already detect situations where a PPP channel sends packets back to
its upper PPP device. While this is enough to avoid deadlocking on xmit
locks, this doesn't prevent packets from looping between the channel
and the unit.
The problem is that ppp_start_xmit() enqueues packets in ppp->file.xq
before checking for xmit recursion. Therefore, __ppp_xmit_process()
might dequeue a packet from ppp->file.xq and send it on the channel
which, in turn, loops it back on the unit. Then ppp_start_xmit()
queues the packet back to ppp->file.xq and __ppp_xmit_process() picks
it up and sends it again through the channel. Therefore, the packet
will loop between __ppp_xmit_process() and ppp_start_xmit() until some
other part of the xmit path drops it.
For L2TP, we rapidly fill the skb's headroom and pppol2tp_xmit() drops
the packet after a few iterations. But PPTP reallocates the headroom
if necessary, letting the loop run and exhaust the machine resources
(as reported in https://bugzilla.kernel.org/show_bug.cgi?id=199109).
Fix this by letting __ppp_xmit_process() enqueue the skb to
ppp->file.xq, so that we can check for recursion before adding it to
the queue. Now ppp_xmit_process() can drop the packet when recursion is
detected.
__ppp_channel_push() is a bit special. It calls __ppp_xmit_process()
without having any actual packet to send. This is used by
ppp_output_wakeup() to re-enable transmission on the parent unit (for
implementations like ppp_async.c, where the .start_xmit() function
might not consume the skb, leaving it in ppp->xmit_pending and
disabling transmission).
Therefore, __ppp_xmit_process() needs to handle the case where skb is
NULL, dequeuing as many packets as possible from ppp->file.xq.
Reported-by: xu heng <xuheng333@zoho.com>
Fixes: 55454a565836 ("ppp: avoid dealock on recursive xmit")
Signed-off-by: Guillaume Nault <g.nault@alphalink.fr>
---
drivers/net/ppp/ppp_generic.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index fa2a9bdd1866..da1937832c99 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -257,7 +257,7 @@ struct ppp_net {
/* Prototypes. */
static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
struct file *file, unsigned int cmd, unsigned long arg);
-static void ppp_xmit_process(struct ppp *ppp);
+static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb);
static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb);
static void ppp_push(struct ppp *ppp);
static void ppp_channel_push(struct channel *pch);
@@ -513,13 +513,12 @@ static ssize_t ppp_write(struct file *file, const char __user *buf,
goto out;
}
- skb_queue_tail(&pf->xq, skb);
-
switch (pf->kind) {
case INTERFACE:
- ppp_xmit_process(PF_TO_PPP(pf));
+ ppp_xmit_process(PF_TO_PPP(pf), skb);
break;
case CHANNEL:
+ skb_queue_tail(&pf->xq, skb);
ppp_channel_push(PF_TO_CHANNEL(pf));
break;
}
@@ -1267,8 +1266,8 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
put_unaligned_be16(proto, pp);
skb_scrub_packet(skb, !net_eq(ppp->ppp_net, dev_net(dev)));
- skb_queue_tail(&ppp->file.xq, skb);
- ppp_xmit_process(ppp);
+ ppp_xmit_process(ppp, skb);
+
return NETDEV_TX_OK;
outf:
@@ -1420,13 +1419,14 @@ static void ppp_setup(struct net_device *dev)
*/
/* Called to do any work queued up on the transmit side that can now be done */
-static void __ppp_xmit_process(struct ppp *ppp)
+static void __ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb)
{
- struct sk_buff *skb;
-
ppp_xmit_lock(ppp);
if (!ppp->closing) {
ppp_push(ppp);
+
+ if (skb)
+ skb_queue_tail(&ppp->file.xq, skb);
while (!ppp->xmit_pending &&
(skb = skb_dequeue(&ppp->file.xq)))
ppp_send_frame(ppp, skb);
@@ -1440,7 +1440,7 @@ static void __ppp_xmit_process(struct ppp *ppp)
ppp_xmit_unlock(ppp);
}
-static void ppp_xmit_process(struct ppp *ppp)
+static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb)
{
local_bh_disable();
@@ -1448,7 +1448,7 @@ static void ppp_xmit_process(struct ppp *ppp)
goto err;
(*this_cpu_ptr(ppp->xmit_recursion))++;
- __ppp_xmit_process(ppp);
+ __ppp_xmit_process(ppp, skb);
(*this_cpu_ptr(ppp->xmit_recursion))--;
local_bh_enable();
@@ -1458,6 +1458,8 @@ static void ppp_xmit_process(struct ppp *ppp)
err:
local_bh_enable();
+ kfree_skb(skb);
+
if (net_ratelimit())
netdev_err(ppp->dev, "recursion detected\n");
}
@@ -1942,7 +1944,7 @@ static void __ppp_channel_push(struct channel *pch)
if (skb_queue_empty(&pch->file.xq)) {
ppp = pch->ppp;
if (ppp)
- __ppp_xmit_process(ppp);
+ __ppp_xmit_process(ppp, NULL);
}
}
--
2.16.2
^ permalink raw reply related
* Re: [PATCH iproute2 5/5] namespace: limit length of network namespace
From: David Ahern @ 2018-03-20 15:50 UTC (permalink / raw)
To: Stephen Hemminger, netdev
In-Reply-To: <20180319165638.30166-6-stephen@networkplumber.org>
On 3/19/18 10:56 AM, Stephen Hemminger wrote:
> Avoid running into buffer overflows with excessively long network
> namespace. Fixes Gcc-8 warning about possible snprintf truncation.
>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> ---
> lib/namespace.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/lib/namespace.c b/lib/namespace.c
> index 682634028587..ce5683a5f4e6 100644
> --- a/lib/namespace.c
> +++ b/lib/namespace.c
> @@ -18,7 +18,7 @@
> static void bind_etc(const char *name)
> {
> char etc_netns_path[PATH_MAX];
> - char netns_name[PATH_MAX];
> + char netns_name[2*PATH_MAX];
> char etc_name[PATH_MAX];
> struct dirent *entry;
> DIR *dir;
> @@ -52,6 +52,12 @@ int netns_switch(char *name)
> unsigned long mountflags = 0;
> struct statvfs fsstat;
>
> + if (strlen(name) >= NAME_MAX) {
> + fprintf(stderr, "Network namespace name too long\"%s\"\n",
> + name);
> + return -1;
> + }
> +
> snprintf(net_path, sizeof(net_path), "%s/%s", NETNS_RUN_DIR, name);
> netns = open(net_path, O_RDONLY | O_CLOEXEC);
> if (netns < 0) {
>
Since PATH_MAX is a Linux limit for file paths, why not ensure
strlen(name) + strlen(NETNS_RUN_DIR) + 2 <= PATH_MAX
^ permalink raw reply
* Re: [PATCH net-next 0/4] net: dsa: Plug in PHYLINK support
From: Andrew Lunn @ 2018-03-20 15:51 UTC (permalink / raw)
To: David Miller
Cc: f.fainelli, netdev, privat, vivien.didelot, rmk+kernel, sean.wang,
Woojung.Huh, john, cphealy
In-Reply-To: <20180320.112842.2181273000289842954.davem@davemloft.net>
On Tue, Mar 20, 2018 at 11:28:42AM -0400, David Miller wrote:
> From: Florian Fainelli <f.fainelli@gmail.com>
> Date: Sun, 18 Mar 2018 11:52:42 -0700
>
> > This patch series adds PHYLINK support to DSA which is necessary to
> > support more complex PHY and pluggable modules setups.
>
> This series is kinda stuck in the mud because of the discussion about
> putting a phylink reference into netdevice.
It is only partially stuck. I've run some tests with the current
patches and found some regressions. I'm working on the Marvell switch
support to fix this.
However, i agree, it would be good to have a repost of Russells
patches.
Andrew
^ permalink raw reply
* [PATCH net-next 0/1] net/ipv4: SMC and SYN Cookies
From: Ursula Braun @ 2018-03-20 15:53 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, schwidefsky, heiko.carstens, raspl, ubraun
Dave,
net/smc code is based on the SMC TCP experimental option.
Please apply Hans' patch to fix an inconsistency when SYN cookies
are active.
Thanks, Ursula
Hans Wippel (1):
net/ipv4: disable SMC TCP option with SYN Cookies
net/ipv4/tcp_output.c | 2 ++
1 file changed, 2 insertions(+)
--
2.13.5
^ permalink raw reply
* [PATCH net-next 1/1] net/ipv4: disable SMC TCP option with SYN Cookies
From: Ursula Braun @ 2018-03-20 15:53 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, schwidefsky, heiko.carstens, raspl, ubraun
In-Reply-To: <20180320155340.18017-1-ubraun@linux.vnet.ibm.com>
From: Hans Wippel <hwippel@linux.vnet.ibm.com>
Currently, the SMC experimental TCP option in a SYN packet is lost on
the server side when SYN Cookies are active. However, the corresponding
SYNACK sent back to the client contains the SMC option. This causes an
inconsistent view of the SMC capabilities on the client and server.
This patch disables the SMC option in the SYNACK when SYN Cookies are
active to avoid this issue.
Signed-off-by: Hans Wippel <hwippel@linux.vnet.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com>
---
net/ipv4/tcp_output.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 383cac0ff0ec..22894514feae 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -3199,6 +3199,8 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst,
/* Under synflood, we do not attach skb to a socket,
* to avoid false sharing.
*/
+ if (IS_ENABLED(CONFIG_SMC))
+ ireq->smc_ok = 0;
break;
case TCP_SYNACK_FASTOPEN:
/* sk is a const pointer, because we want to express multiple
--
2.13.5
^ permalink raw reply related
* [PATCH net-next v2 2/2] net: bpf: add a test for skb_segment in test_bpf module
From: Yonghong Song @ 2018-03-20 15:55 UTC (permalink / raw)
To: edumazet, ast, daniel, diptanu, netdev; +Cc: kernel-team
In-Reply-To: <20180320155501.1370612-1-yhs@fb.com>
Without the previous commit,
"modprobe test_bpf" will have the following errors:
...
[ 98.149165] ------------[ cut here ]------------
[ 98.159362] kernel BUG at net/core/skbuff.c:3667!
[ 98.169756] invalid opcode: 0000 [#1] SMP PTI
[ 98.179370] Modules linked in:
[ 98.179371] test_bpf(+)
...
which triggers the bug the previous commit intends to fix.
The skbs are constructed to mimic what mlx5 may generate.
The packet size/header may not mimic real cases in production. But
the processing flow is similar.
Signed-off-by: Yonghong Song <yhs@fb.com>
---
lib/test_bpf.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 70 insertions(+), 1 deletion(-)
diff --git a/lib/test_bpf.c b/lib/test_bpf.c
index 2efb213..045d7d3 100644
--- a/lib/test_bpf.c
+++ b/lib/test_bpf.c
@@ -6574,6 +6574,72 @@ static bool exclude_test(int test_id)
return test_id < test_range[0] || test_id > test_range[1];
}
+static struct sk_buff *build_test_skb(void *page)
+{
+ u32 headroom = NET_SKB_PAD + NET_IP_ALIGN + ETH_HLEN;
+ struct sk_buff *skb[2];
+ int i, data_size = 8;
+
+ for (i = 0; i < 2; i++) {
+ /* this will set skb[i]->head_frag */
+ skb[i] = build_skb(page, headroom);
+ if (!skb[i])
+ return NULL;
+
+ skb_reserve(skb[i], headroom);
+ skb_put(skb[i], data_size);
+ skb[i]->protocol = htons(ETH_P_IP);
+ skb_reset_network_header(skb[i]);
+ skb_set_mac_header(skb[i], -ETH_HLEN);
+
+ skb_add_rx_frag(skb[i], skb_shinfo(skb[i])->nr_frags,
+ page, 0, 64, 64);
+ // skb: skb_headlen(skb[i]): 8, skb[i]->head_frag = 1
+ }
+
+ /* setup shinfo */
+ skb_shinfo(skb[0])->gso_size = 1448;
+ skb_shinfo(skb[0])->gso_type = SKB_GSO_TCPV4;
+ skb_shinfo(skb[0])->gso_type |= SKB_GSO_DODGY;
+ skb_shinfo(skb[0])->gso_segs = 0;
+ skb_shinfo(skb[0])->frag_list = skb[1];
+
+ /* adjust skb[0]'s len */
+ skb[0]->len += skb[1]->len;
+ skb[0]->data_len += skb[1]->data_len;
+ skb[0]->truesize += skb[1]->truesize;
+
+ return skb[0];
+}
+
+static __init int test_skb_segment(void)
+{
+ netdev_features_t features;
+ struct sk_buff *skb;
+ void *page;
+ int ret = -1;
+
+ page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+ if (!page) {
+ pr_info("%s: failed to get_free_page!", __func__);
+ return ret;
+ }
+
+ features = NETIF_F_SG | NETIF_F_GSO_PARTIAL | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+ features |= NETIF_F_RXCSUM;
+ skb = build_test_skb(page);
+ if (!skb) {
+ pr_info("%s: failed to build_test_skb", __func__);
+ } else if (skb_segment(skb, features)) {
+ ret = 0;
+ pr_info("%s: success in skb_segment!", __func__);
+ } else {
+ pr_info("%s: failed in skb_segment!", __func__);
+ }
+ free_page((unsigned long)page);
+ return ret;
+}
+
static __init int test_bpf(void)
{
int i, err_cnt = 0, pass_cnt = 0;
@@ -6632,8 +6698,11 @@ static int __init test_bpf_init(void)
return ret;
ret = test_bpf();
-
destroy_bpf_tests();
+ if (ret)
+ return ret;
+
+ ret = test_skb_segment();
return ret;
}
--
2.9.5
^ permalink raw reply related
* [PATCH net-next v2 1/2] net: permit skb_segment on head_frag frag_list skb
From: Yonghong Song @ 2018-03-20 15:55 UTC (permalink / raw)
To: edumazet, ast, daniel, diptanu, netdev; +Cc: kernel-team
In-Reply-To: <20180320155501.1370612-1-yhs@fb.com>
One of our in-house projects, bpf-based NAT, hits a kernel BUG_ON at
function skb_segment(), line 3667. The bpf program attaches to
clsact ingress, calls bpf_skb_change_proto to change protocol
from ipv4 to ipv6 or from ipv6 to ipv4, and then calls bpf_redirect
to send the changed packet out.
3472 struct sk_buff *skb_segment(struct sk_buff *head_skb,
3473 netdev_features_t features)
3474 {
3475 struct sk_buff *segs = NULL;
3476 struct sk_buff *tail = NULL;
...
3665 while (pos < offset + len) {
3666 if (i >= nfrags) {
3667 BUG_ON(skb_headlen(list_skb));
3668
3669 i = 0;
3670 nfrags = skb_shinfo(list_skb)->nr_frags;
3671 frag = skb_shinfo(list_skb)->frags;
3672 frag_skb = list_skb;
...
call stack:
...
#1 [ffff883ffef03558] __crash_kexec at ffffffff8110c525
#2 [ffff883ffef03620] crash_kexec at ffffffff8110d5cc
#3 [ffff883ffef03640] oops_end at ffffffff8101d7e7
#4 [ffff883ffef03668] die at ffffffff8101deb2
#5 [ffff883ffef03698] do_trap at ffffffff8101a700
#6 [ffff883ffef036e8] do_error_trap at ffffffff8101abfe
#7 [ffff883ffef037a0] do_invalid_op at ffffffff8101acd0
#8 [ffff883ffef037b0] invalid_op at ffffffff81a00bab
[exception RIP: skb_segment+3044]
RIP: ffffffff817e4dd4 RSP: ffff883ffef03860 RFLAGS: 00010216
RAX: 0000000000002bf6 RBX: ffff883feb7aaa00 RCX: 0000000000000011
RDX: ffff883fb87910c0 RSI: 0000000000000011 RDI: ffff883feb7ab500
RBP: ffff883ffef03928 R8: 0000000000002ce2 R9: 00000000000027da
R10: 000001ea00000000 R11: 0000000000002d82 R12: ffff883f90a1ee80
R13: ffff883fb8791120 R14: ffff883feb7abc00 R15: 0000000000002ce2
ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018
#9 [ffff883ffef03930] tcp_gso_segment at ffffffff818713e7
--- <IRQ stack> ---
...
The triggering input skb has the following properties:
list_skb = skb->frag_list;
skb->nfrags != NULL && skb_headlen(list_skb) != 0
and skb_segment() is not able to handle a frag_list skb
if its headlen (list_skb->len - list_skb->data_len) is not 0.
This patch addressed the issue by handling skb_headlen(list_skb) != 0
case properly if list_skb->head_frag is true, which is expected in
most cases. A one-element frag array is created for the list_skb head
and processed before list_skb->frags are processed.
Reported-by: Diptanu Gon Choudhury <diptanu@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
---
net/core/skbuff.c | 42 +++++++++++++++++++++++++++++-------------
1 file changed, 29 insertions(+), 13 deletions(-)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 715c134..0ad4cda 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3475,9 +3475,10 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
struct sk_buff *segs = NULL;
struct sk_buff *tail = NULL;
struct sk_buff *list_skb = skb_shinfo(head_skb)->frag_list;
- skb_frag_t *frag = skb_shinfo(head_skb)->frags;
+ skb_frag_t *frag = skb_shinfo(head_skb)->frags, head_frag;
unsigned int mss = skb_shinfo(head_skb)->gso_size;
unsigned int doffset = head_skb->data - skb_mac_header(head_skb);
+ struct sk_buff *check_list_skb = list_skb;
struct sk_buff *frag_skb = head_skb;
unsigned int offset = doffset;
unsigned int tnl_hlen = skb_tnl_header_len(head_skb);
@@ -3590,6 +3591,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
nskb = skb_clone(list_skb, GFP_ATOMIC);
list_skb = list_skb->next;
+ check_list_skb = list_skb;
if (unlikely(!nskb))
goto err;
@@ -3664,21 +3666,35 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
while (pos < offset + len) {
if (i >= nfrags) {
- BUG_ON(skb_headlen(list_skb));
-
- i = 0;
- nfrags = skb_shinfo(list_skb)->nr_frags;
- frag = skb_shinfo(list_skb)->frags;
- frag_skb = list_skb;
+ if (skb_headlen(list_skb) && check_list_skb == list_skb) {
+ struct page *page;
+
+ BUG_ON(!list_skb->head_frag);
+
+ i = 0;
+ nfrags = 1;
+ page = virt_to_head_page(list_skb->head);
+ head_frag.page.p = page;
+ head_frag.page_offset = list_skb->data -
+ (unsigned char *)page_address(page);
+ head_frag.size = skb_headlen(list_skb);
+ frag = &head_frag;
+ check_list_skb = list_skb->next;
+ } else {
+ i = 0;
+ nfrags = skb_shinfo(list_skb)->nr_frags;
+ frag = skb_shinfo(list_skb)->frags;
+ frag_skb = list_skb;
- BUG_ON(!nfrags);
+ BUG_ON(!nfrags);
- if (skb_orphan_frags(frag_skb, GFP_ATOMIC) ||
- skb_zerocopy_clone(nskb, frag_skb,
- GFP_ATOMIC))
- goto err;
+ if (skb_orphan_frags(frag_skb, GFP_ATOMIC) ||
+ skb_zerocopy_clone(nskb, frag_skb, GFP_ATOMIC))
+ goto err;
- list_skb = list_skb->next;
+ list_skb = list_skb->next;
+ check_list_skb = list_skb;
+ }
}
if (unlikely(skb_shinfo(nskb)->nr_frags >=
--
2.9.5
^ permalink raw reply related
* [PATCH net-next v2 0/2] net: permit skb_segment on head_frag frag_list skb
From: Yonghong Song @ 2018-03-20 15:54 UTC (permalink / raw)
To: edumazet, ast, daniel, diptanu, netdev; +Cc: kernel-team
One of our in-house projects, bpf-based NAT, hits a kernel BUG_ON at
function skb_segment(), line 3667. The bpf program attaches to
clsact ingress, calls bpf_skb_change_proto to change protocol
from ipv4 to ipv6 or from ipv6 to ipv4, and then calls bpf_redirect
to send the changed packet out.
...
3665 while (pos < offset + len) {
3666 if (i >= nfrags) {
3667 BUG_ON(skb_headlen(list_skb));
...
The triggering input skb has the following properties:
list_skb = skb->frag_list;
skb->nfrags != NULL && skb_headlen(list_skb) != 0
and skb_segment() is not able to handle a frag_list skb
if its headlen (list_skb->len - list_skb->data_len) is not 0.
Patch #1 provides a simple solution to avoid BUG_ON. If
list_skb->head_frag is true, its page-backed frag will
be processed before the list_skb->frags.
Patch #2 provides a test case in test_bpf module which
constructs a skb and calls skb_segment() directly. The test
case is able to trigger the BUG_ON without Patch #1.
Changelog:
v1 -> v2:
. Removed never-hit BUG_ON, spotted by Linyu Yuan.
Yonghong Song (2):
net: permit skb_segment on head_frag frag_list skb
net: bpf: add a test for skb_segment in test_bpf module
lib/test_bpf.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
net/core/skbuff.c | 42 ++++++++++++++++++++++----------
2 files changed, 99 insertions(+), 14 deletions(-)
--
2.9.5
^ permalink raw reply
* Re: linux-next: ip6tables *broken* - last base chain position %u doesn't match underflow %u (hook %u
From: valdis.kletnieks @ 2018-03-20 15:57 UTC (permalink / raw)
To: Florian Westphal; +Cc: Pablo Neira Ayuso, netdev, linux-kernel
In-Reply-To: <20180320154842.GC24075@breakpoint.cc>
[-- Attachment #1: Type: text/plain, Size: 477 bytes --]
On Tue, 20 Mar 2018 16:48:42 +0100, Florian Westphal said:
> valdis.kletnieks@vt.edu <valdis.kletnieks@vt.edu> wrote:
> > (Resending because I haven't heard anything)
> [ ip6tables broken ]
>
> Sorry, did not see this email before.
>
> I'll investigate asap, thanks for the detailed report.
No problem, it reverts cleanly and looks like it's 4.17 material,
and finding stuff like this is why I build linux-next kernels :)
Just remember to stick a Reported-By: on the fix :)
[-- Attachment #2: Type: application/pgp-signature, Size: 486 bytes --]
^ 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