* Re: [PATCH net-next v7 02/10] bpf: Add eBPF program subtype and is_valid_subtype() verifier
From: James Morris @ 2017-08-28 3:46 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Mickaël Salaün, linux-kernel, Alexei Starovoitov,
Andy Lutomirski, Arnaldo Carvalho de Melo, Casey Schaufler,
Daniel Borkmann, David Drysdale, David S . Miller,
Eric W . Biederman, James Morris, Jann Horn, Jonathan Corbet,
Matthew Garrett, Michael Kerrisk, Kees Cook, Paul Moore,
Sargun Dhillon, Serge E . Hallyn, Shuah Khan
In-Reply-To: <20170823024452.zvizovwfd7xjucsx@ast-mbp>
On Tue, 22 Aug 2017, Alexei Starovoitov wrote:
> more general question: what is the status of security/ bits?
> I'm assuming they still need to be reviewed and explicitly acked by James, right?
Yep, along with other core security developers where possible.
--
James Morris
<jmorris@namei.org>
^ permalink raw reply
* Re: Re: [PATCH net-next v7 02/10] bpf: Add eBPF program subtype and is_valid_subtype() verifier
From: James Morris @ 2017-08-28 3:48 UTC (permalink / raw)
To: Mickaël Salaün
Cc: Alexei Starovoitov, linux-kernel, Alexei Starovoitov,
Andy Lutomirski, Arnaldo Carvalho de Melo, Casey Schaufler,
Daniel Borkmann, David Drysdale, David S . Miller,
Eric W . Biederman, James Morris, Jann Horn, Jonathan Corbet,
Matthew Garrett, Michael Kerrisk, Kees Cook, Paul Moore,
Sargun Dhillon, Serge E . Hallyn, Shuah Khan
In-Reply-To: <607ceb21-5aa5-678b-4438-0d8dcb69fc3c@digikod.net>
[-- Attachment #1: Type: text/plain, Size: 1583 bytes --]
On Wed, 23 Aug 2017, Mickaël Salaün wrote:
> >> + struct {
> >> + __u32 abi; /* minimal ABI version, cf. user doc */
> >
> > the concept of abi (version) sounds a bit weird to me.
> > Why bother with it at all?
> > Once the first set of patches lands the kernel as whole will have landlock feature
> > with a set of helpers, actions, event types.
> > Some future patches will extend the landlock feature step by step.
> > This abi concept assumes that anyone who adds new helper would need
> > to keep incrementing this 'abi'. What value does it give to user or to kernel?
> > The users will already know that landlock is present in kernel 4.14 or whatever
> > and the kernel 4.18 has more landlock features. Why bother with extra abi number?
>
> That's right for helpers and context fields, but we can't check the use
> of one field's content. The status field is intended to be a bitfield
> extendable in the future. For example, one use case is to set a flag to
> inform the eBPF program that it was already called with the same context
> and can skip most of its check (if not related to maps). Same goes for
> the FS action bitfield, one may want to add more of them. Another
> example may be the check for abilities. We may want to relax/remove the
> capability require to set one of them. With an ABI version, the user can
> easily check if the current kernel support that.
Don't call it an ABI, perhaps minimum policy version (similar to
what SELinux does). Changes need to be made so that any existing
userspace still works.
--
James Morris
<jmorris@namei.org>
^ permalink raw reply
* Re: [PATCH net-next v7 04/10] bpf: Define handle_fs and add a new helper bpf_handle_fs_get_mode()
From: James Morris @ 2017-08-28 4:09 UTC (permalink / raw)
To: Mickaël Salaün
Cc: linux-kernel, Alexei Starovoitov, Andy Lutomirski,
Arnaldo Carvalho de Melo, Casey Schaufler, Daniel Borkmann,
David Drysdale, David S . Miller, Eric W . Biederman,
James Morris, Jann Horn, Jonathan Corbet, Matthew Garrett,
Michael Kerrisk, Kees Cook, Paul Moore, Sargun Dhillon,
Serge E . Hallyn, Shuah Khan, Tejun Heo, Thomas Graf
In-Reply-To: <20170821000933.13024-5-mic@digikod.net>
[-- Attachment #1: Type: text/plain, Size: 348 bytes --]
On Mon, 21 Aug 2017, Mickaël Salaün wrote:
> @@ -85,6 +90,8 @@ enum bpf_arg_type {
>
> ARG_PTR_TO_CTX, /* pointer to context */
> ARG_ANYTHING, /* any (initialized) argument is ok */
> +
> + ARG_CONST_PTR_TO_HANDLE_FS, /* pointer to an abstract FS struct */
> };
Looks like a spurious empty line.
--
James Morris
<jmorris@namei.org>
^ permalink raw reply
* Re: [PATCH net-next v7 05/10] landlock: Add LSM hooks related to filesystem
From: Alexei Starovoitov @ 2017-08-28 5:26 UTC (permalink / raw)
To: Mickaël Salaün
Cc: linux-kernel, Alexei Starovoitov, Andy Lutomirski,
Arnaldo Carvalho de Melo, Casey Schaufler, Daniel Borkmann,
David Drysdale, David S . Miller, Eric W . Biederman,
James Morris, Jann Horn, Jonathan Corbet, Matthew Garrett,
Michael Kerrisk, Kees Cook, Paul Moore, Sargun Dhillon,
Serge E . Hallyn, Shuah Khan, Tejun Heo, Thomas Graf <tgr
In-Reply-To: <3325bd7d-f3d8-2f51-384c-b5e8cee5cb91@digikod.net>
On Sun, Aug 27, 2017 at 03:31:35PM +0200, Mickaël Salaün wrote:
>
> > How can you add 3rd argument? All FS events would have to get it,
> > but in some LSM hooks such argument will be meaningless, whereas
> > in other places it will carry useful info that rule can operate on.
> > Would that mean that we'll have FS_3 event type and only few LSM
> > hooks will be converted to it. That works, but then we'll lose
> > compatiblity with old rules written for FS event and that given hook.
> > Otherwise we'd need to have fancy logic to accept old FS event
> > into FS_3 LSM hook.
>
> If we want to add a third argument to the FS event, then it will become
> accessible because its type will be different than NOT_INIT. This keep
> the compatibility with old rules because this new field was then denied.
>
> If we want to add a new argument but only for a subset of the hooks used
> by the FS event, then we need to create a new event, like FS_FCNTL. For
> example, we may want to add a FS_RENAME event to be able to tie the
> source file and the destination file of a rename call.
that's exactly my point. To add another argument FS event
to a subset of hooks will require either new FS_FOO and
to be backwards compatible these hooks will call _both_ FS and FS_FOO
or some magic logic on kernel side that will allow old FS rules
to be attached to FS_FOO hooks?
Two calls doesn't scale and if we do 'magic logic' can we do it now
and avoid introducing events altogether?
Like all landlock programs can be landlock type and they would need
to declare what arg1, arg2, argN they expect. Then at attach
time the kernel only needs to verify that hook arg types match
what program requested.
> Anyway, I added the subtype/ABI version as a safeguard in case of
> unexpected future evolution.
I don't think that abi/version field adds anything in this context.
I still think it should simply be removed.
^ permalink raw reply
* [PATCH] net: stmmac: constify clk_div_table
From: Arvind Yadav @ 2017-08-28 5:52 UTC (permalink / raw)
To: khilman, carlo, alexandre.torgue, peppe.cavallaro, davem
Cc: linux-kernel, linux-amlogic, linux-arm-kernel, netdev
clk_div_table are not supposed to change at runtime.
meson8b_dwmac structure is working with const clk_div_table.
So mark the non-const structs as const.
Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
index 9685555..4404650b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
@@ -89,7 +89,7 @@ static int meson8b_init_clk(struct meson8b_dwmac *dwmac)
char clk_name[32];
const char *clk_div_parents[1];
const char *mux_parent_names[MUX_CLK_NUM_PARENTS];
- static struct clk_div_table clk_25m_div_table[] = {
+ static const struct clk_div_table clk_25m_div_table[] = {
{ .val = 0, .div = 5 },
{ .val = 1, .div = 10 },
{ /* sentinel */ },
--
1.9.1
^ permalink raw reply related
* Re: [PATCH] connector: Delete an error message for a failed memory allocation in cn_queue_alloc_callback_entry()
From: Dan Carpenter @ 2017-08-28 6:05 UTC (permalink / raw)
To: Waskiewicz Jr, Peter
Cc: SF Markus Elfring, netdev@vger.kernel.org, Evgeniy Polyakov, LKML,
kernel-janitors@vger.kernel.org
In-Reply-To: <E0D909EE5BB15A4699798539EA149D7F0779689E@ORSMSX103.amr.corp.intel.com>
On Sun, Aug 27, 2017 at 11:16:06PM +0000, Waskiewicz Jr, Peter wrote:
> On 8/27/17 3:26 PM, SF Markus Elfring wrote:
> > From: Markus Elfring <elfring@users.sourceforge.net>
> > Date: Sun, 27 Aug 2017 21:18:37 +0200
> >
> > Omit an extra message for a memory allocation failure in this function.
> >
> > This issue was detected by using the Coccinelle software.
>
> Did coccinelle trip on the message or the fact you weren't returning NULL?
>
You've misread the patch somehow. The existing code has a NULL return
and it's preserved in Markus's patch. This sort of patch is to fix a
checkpatch.pl warning. The error message from this kzalloc() isn't going
to get printed because it's a small allocation and small allocations
always succeed in current kernels. But probably the main reason
checkpatch complains is that kmalloc() already prints a stack trace and
a bunch of other information so the printk doesn't add anyting.
Removing it saves a little memory.
I'm mostly a fan of running checkpatch on new patches or staging and not
on old code...
regards,
dan carpenter
^ permalink raw reply
* [PATCH net-next v3 0/3] NCSI VLAN Filtering Support
From: Samuel Mendoza-Jonas @ 2017-08-28 6:18 UTC (permalink / raw)
To: David S . Miller, netdev, linux-kernel, OpenBMC Maillist
Cc: Samuel Mendoza-Jonas, Joel Stanley, Benjamin Herrenschmidt,
Gavin Shan, ratagupt
This series (mainly patch 2) adds VLAN filtering to the NCSI implementation.
A fair amount of code already exists in the NCSI stack for VLAN filtering but
none of it is actually hooked up. This goes the final mile and fixes a few
bugs in the existing code found along the way (patch 1).
Patch 3 adds the appropriate flag and callbacks to the ftgmac100 driver to
enable filtering as it's a large consumer of NCSI (and what I've been
testing on).
v3: - Add comment describing change to ncsi_find_filter()
- Catch NULL in clear_one_vid() from ncsi_get_filter()
- Simplify state changes when kicking updated channel
Samuel Mendoza-Jonas (3):
net/ncsi: Fix several packet definitions
net/ncsi: Configure VLAN tag filter
ftgmac100: Support NCSI VLAN filtering when available
drivers/net/ethernet/faraday/ftgmac100.c | 5 +
include/net/ncsi.h | 2 +
net/ncsi/internal.h | 11 ++
net/ncsi/ncsi-cmd.c | 10 +-
net/ncsi/ncsi-manage.c | 308 ++++++++++++++++++++++++++++++-
net/ncsi/ncsi-pkt.h | 2 +-
net/ncsi/ncsi-rsp.c | 12 +-
7 files changed, 339 insertions(+), 11 deletions(-)
--
2.14.0
^ permalink raw reply
* [PATCH net-next v3 1/3] net/ncsi: Fix several packet definitions
From: Samuel Mendoza-Jonas @ 2017-08-28 6:18 UTC (permalink / raw)
To: David S . Miller, netdev, linux-kernel, OpenBMC Maillist
Cc: Samuel Mendoza-Jonas, Joel Stanley, Benjamin Herrenschmidt,
Gavin Shan, ratagupt
In-Reply-To: <20170828061843.24349-1-sam@mendozajonas.com>
Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
---
v2: Rebased on latest net-next
net/ncsi/ncsi-cmd.c | 10 +++++-----
net/ncsi/ncsi-pkt.h | 2 +-
net/ncsi/ncsi-rsp.c | 3 ++-
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/net/ncsi/ncsi-cmd.c b/net/ncsi/ncsi-cmd.c
index 5e03ed190e18..7567ca63aae2 100644
--- a/net/ncsi/ncsi-cmd.c
+++ b/net/ncsi/ncsi-cmd.c
@@ -139,9 +139,9 @@ static int ncsi_cmd_handler_svf(struct sk_buff *skb,
struct ncsi_cmd_svf_pkt *cmd;
cmd = skb_put_zero(skb, sizeof(*cmd));
- cmd->vlan = htons(nca->words[0]);
- cmd->index = nca->bytes[2];
- cmd->enable = nca->bytes[3];
+ cmd->vlan = htons(nca->words[1]);
+ cmd->index = nca->bytes[6];
+ cmd->enable = nca->bytes[7];
ncsi_cmd_build_header(&cmd->cmd.common, nca);
return 0;
@@ -153,7 +153,7 @@ static int ncsi_cmd_handler_ev(struct sk_buff *skb,
struct ncsi_cmd_ev_pkt *cmd;
cmd = skb_put_zero(skb, sizeof(*cmd));
- cmd->mode = nca->bytes[0];
+ cmd->mode = nca->bytes[3];
ncsi_cmd_build_header(&cmd->cmd.common, nca);
return 0;
@@ -228,7 +228,7 @@ static struct ncsi_cmd_handler {
{ NCSI_PKT_CMD_AE, 8, ncsi_cmd_handler_ae },
{ NCSI_PKT_CMD_SL, 8, ncsi_cmd_handler_sl },
{ NCSI_PKT_CMD_GLS, 0, ncsi_cmd_handler_default },
- { NCSI_PKT_CMD_SVF, 4, ncsi_cmd_handler_svf },
+ { NCSI_PKT_CMD_SVF, 8, ncsi_cmd_handler_svf },
{ NCSI_PKT_CMD_EV, 4, ncsi_cmd_handler_ev },
{ NCSI_PKT_CMD_DV, 0, ncsi_cmd_handler_default },
{ NCSI_PKT_CMD_SMA, 8, ncsi_cmd_handler_sma },
diff --git a/net/ncsi/ncsi-pkt.h b/net/ncsi/ncsi-pkt.h
index 3ea49ed0a935..91b4b66438df 100644
--- a/net/ncsi/ncsi-pkt.h
+++ b/net/ncsi/ncsi-pkt.h
@@ -104,7 +104,7 @@ struct ncsi_cmd_svf_pkt {
unsigned char index; /* VLAN table index */
unsigned char enable; /* Enable or disable */
__be32 checksum; /* Checksum */
- unsigned char pad[14];
+ unsigned char pad[18];
};
/* Enable VLAN */
diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c
index 087db775b3dc..c1a191d790e2 100644
--- a/net/ncsi/ncsi-rsp.c
+++ b/net/ncsi/ncsi-rsp.c
@@ -354,7 +354,8 @@ static int ncsi_rsp_handler_svf(struct ncsi_request *nr)
/* Add or remove the VLAN filter */
if (!(cmd->enable & 0x1)) {
- ret = ncsi_remove_filter(nc, NCSI_FILTER_VLAN, cmd->index);
+ /* HW indexes from 1 */
+ ret = ncsi_remove_filter(nc, NCSI_FILTER_VLAN, cmd->index - 1);
} else {
vlan = ntohs(cmd->vlan);
ret = ncsi_add_filter(nc, NCSI_FILTER_VLAN, &vlan);
--
2.14.0
^ permalink raw reply related
* [PATCH net-next v3 2/3] net/ncsi: Configure VLAN tag filter
From: Samuel Mendoza-Jonas @ 2017-08-28 6:18 UTC (permalink / raw)
To: David S . Miller, netdev, linux-kernel, OpenBMC Maillist
Cc: Samuel Mendoza-Jonas, Joel Stanley, Benjamin Herrenschmidt,
Gavin Shan, ratagupt
In-Reply-To: <20170828061843.24349-1-sam@mendozajonas.com>
Make use of the ndo_vlan_rx_{add,kill}_vid callbacks to have the NCSI
stack process new VLAN tags and configure the channel VLAN filter
appropriately.
Several VLAN tags can be set and a "Set VLAN Filter" packet must be sent
for each one, meaning the ncsi_dev_state_config_svf state must be
repeated. An internal list of VLAN tags is maintained, and compared
against the current channel's ncsi_channel_filter in order to keep track
within the state. VLAN filters are removed in a similar manner, with the
introduction of the ncsi_dev_state_config_clear_vids state. The maximum
number of VLAN tag filters is determined by the "Get Capabilities"
response from the channel.
Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
---
v3: - Add comment describing change to ncsi_find_filter()
- Catch NULL in clear_one_vid() from ncsi_get_filter()
- Simplify state changes when kicking updated channel
include/net/ncsi.h | 2 +
net/ncsi/internal.h | 11 ++
net/ncsi/ncsi-manage.c | 308 ++++++++++++++++++++++++++++++++++++++++++++++++-
net/ncsi/ncsi-rsp.c | 9 +-
4 files changed, 326 insertions(+), 4 deletions(-)
diff --git a/include/net/ncsi.h b/include/net/ncsi.h
index 68680baac0fd..1f96af46df49 100644
--- a/include/net/ncsi.h
+++ b/include/net/ncsi.h
@@ -28,6 +28,8 @@ struct ncsi_dev {
};
#ifdef CONFIG_NET_NCSI
+int ncsi_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid);
+int ncsi_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid);
struct ncsi_dev *ncsi_register_dev(struct net_device *dev,
void (*notifier)(struct ncsi_dev *nd));
int ncsi_start_dev(struct ncsi_dev *nd);
diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h
index 1308a56f2591..af3d636534ef 100644
--- a/net/ncsi/internal.h
+++ b/net/ncsi/internal.h
@@ -180,6 +180,7 @@ struct ncsi_channel {
#define NCSI_CHANNEL_INACTIVE 1
#define NCSI_CHANNEL_ACTIVE 2
#define NCSI_CHANNEL_INVISIBLE 3
+ bool reconfigure_needed;
spinlock_t lock; /* Protect filters etc */
struct ncsi_package *package;
struct ncsi_channel_version version;
@@ -235,6 +236,9 @@ enum {
ncsi_dev_state_probe_dp,
ncsi_dev_state_config_sp = 0x0301,
ncsi_dev_state_config_cis,
+ ncsi_dev_state_config_clear_vids,
+ ncsi_dev_state_config_svf,
+ ncsi_dev_state_config_ev,
ncsi_dev_state_config_sma,
ncsi_dev_state_config_ebf,
#if IS_ENABLED(CONFIG_IPV6)
@@ -253,6 +257,12 @@ enum {
ncsi_dev_state_suspend_done
};
+struct vlan_vid {
+ struct list_head list;
+ __be16 proto;
+ u16 vid;
+};
+
struct ncsi_dev_priv {
struct ncsi_dev ndev; /* Associated NCSI device */
unsigned int flags; /* NCSI device flags */
@@ -276,6 +286,7 @@ struct ncsi_dev_priv {
struct work_struct work; /* For channel management */
struct packet_type ptype; /* NCSI packet Rx handler */
struct list_head node; /* Form NCSI device list */
+ struct list_head vlan_vids; /* List of active VLAN IDs */
};
struct ncsi_cmd_arg {
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index a3bd5fa8ad09..11904b3b702d 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -38,6 +38,25 @@ static inline int ncsi_filter_size(int table)
return sizes[table];
}
+u32 *ncsi_get_filter(struct ncsi_channel *nc, int table, int index)
+{
+ struct ncsi_channel_filter *ncf;
+ int size;
+
+ ncf = nc->filters[table];
+ if (!ncf)
+ return NULL;
+
+ size = ncsi_filter_size(table);
+ if (size < 0)
+ return NULL;
+
+ return ncf->data + size * index;
+}
+
+/* Find the first active filter in a filter table that matches the given
+ * data parameter. If data is NULL, this returns the first active filter.
+ */
int ncsi_find_filter(struct ncsi_channel *nc, int table, void *data)
{
struct ncsi_channel_filter *ncf;
@@ -58,7 +77,7 @@ int ncsi_find_filter(struct ncsi_channel *nc, int table, void *data)
index = -1;
while ((index = find_next_bit(bitmap, ncf->total, index + 1))
< ncf->total) {
- if (!memcmp(ncf->data + size * index, data, size)) {
+ if (!data || !memcmp(ncf->data + size * index, data, size)) {
spin_unlock_irqrestore(&nc->lock, flags);
return index;
}
@@ -639,6 +658,95 @@ static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp)
nd->state = ncsi_dev_state_functional;
}
+/* Check the VLAN filter bitmap for a set filter, and construct a
+ * "Set VLAN Filter - Disable" packet if found.
+ */
+static int clear_one_vid(struct ncsi_dev_priv *ndp, struct ncsi_channel *nc,
+ struct ncsi_cmd_arg *nca)
+{
+ int index;
+ u32 *data;
+ u16 vid;
+
+ index = ncsi_find_filter(nc, NCSI_FILTER_VLAN, NULL);
+ if (index < 0) {
+ /* Filter table empty */
+ return -1;
+ }
+
+ data = ncsi_get_filter(nc, NCSI_FILTER_VLAN, index);
+ if (!data) {
+ netdev_err(ndp->ndev.dev,
+ "ncsi: failed to retrieve filter %d\n", index);
+ /* Set the VLAN id to 0 - this will still disable the entry in
+ * the filter table, but we won't know what it was.
+ */
+ vid = 0;
+ } else {
+ vid = *(u16 *)data;
+ }
+
+ netdev_printk(KERN_DEBUG, ndp->ndev.dev,
+ "ncsi: removed vlan tag %u at index %d\n",
+ vid, index + 1);
+ ncsi_remove_filter(nc, NCSI_FILTER_VLAN, index);
+
+ nca->type = NCSI_PKT_CMD_SVF;
+ nca->words[1] = vid;
+ /* HW filter index starts at 1 */
+ nca->bytes[6] = index + 1;
+ nca->bytes[7] = 0x00;
+ return 0;
+}
+
+/* Find an outstanding VLAN tag and constuct a "Set VLAN Filter - Enable"
+ * packet.
+ */
+static int set_one_vid(struct ncsi_dev_priv *ndp, struct ncsi_channel *nc,
+ struct ncsi_cmd_arg *nca)
+{
+ struct vlan_vid *vlan = NULL;
+ int index = 0;
+
+ list_for_each_entry_rcu(vlan, &ndp->vlan_vids, list) {
+ index = ncsi_find_filter(nc, NCSI_FILTER_VLAN, &vlan->vid);
+ if (index < 0) {
+ /* New tag to add */
+ netdev_printk(KERN_DEBUG, ndp->ndev.dev,
+ "ncsi: new vlan id to set: %u\n",
+ vlan->vid);
+ break;
+ }
+ netdev_printk(KERN_DEBUG, ndp->ndev.dev,
+ "vid %u already at filter pos %d\n",
+ vlan->vid, index);
+ }
+
+ if (!vlan || index >= 0) {
+ netdev_printk(KERN_DEBUG, ndp->ndev.dev,
+ "no vlan ids left to set\n");
+ return -1;
+ }
+
+ index = ncsi_add_filter(nc, NCSI_FILTER_VLAN, &vlan->vid);
+ if (index < 0) {
+ netdev_err(ndp->ndev.dev,
+ "Failed to add new VLAN tag, error %d\n", index);
+ return -1;
+ }
+
+ netdev_printk(KERN_DEBUG, ndp->ndev.dev,
+ "ncsi: set vid %u in packet, index %u\n",
+ vlan->vid, index + 1);
+ nca->type = NCSI_PKT_CMD_SVF;
+ nca->words[1] = vlan->vid;
+ /* HW filter index starts at 1 */
+ nca->bytes[6] = index + 1;
+ nca->bytes[7] = 0x01;
+
+ return 0;
+}
+
static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
{
struct ncsi_dev *nd = &ndp->ndev;
@@ -683,8 +791,11 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
if (ret)
goto error;
- nd->state = ncsi_dev_state_config_sma;
+ nd->state = ncsi_dev_state_config_clear_vids;
break;
+ case ncsi_dev_state_config_clear_vids:
+ case ncsi_dev_state_config_svf:
+ case ncsi_dev_state_config_ev:
case ncsi_dev_state_config_sma:
case ncsi_dev_state_config_ebf:
#if IS_ENABLED(CONFIG_IPV6)
@@ -699,11 +810,40 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
nca.package = np->id;
nca.channel = nc->id;
+ /* Clear any active filters on the channel before setting */
+ if (nd->state == ncsi_dev_state_config_clear_vids) {
+ ret = clear_one_vid(ndp, nc, &nca);
+ if (ret) {
+ nd->state = ncsi_dev_state_config_svf;
+ schedule_work(&ndp->work);
+ break;
+ }
+ /* Repeat */
+ nd->state = ncsi_dev_state_config_clear_vids;
+ /* Add known VLAN tags to the filter */
+ } else if (nd->state == ncsi_dev_state_config_svf) {
+ ret = set_one_vid(ndp, nc, &nca);
+ if (ret) {
+ nd->state = ncsi_dev_state_config_ev;
+ schedule_work(&ndp->work);
+ break;
+ }
+ /* Repeat */
+ nd->state = ncsi_dev_state_config_svf;
+ /* Enable/Disable the VLAN filter */
+ } else if (nd->state == ncsi_dev_state_config_ev) {
+ if (list_empty(&ndp->vlan_vids)) {
+ nca.type = NCSI_PKT_CMD_DV;
+ } else {
+ nca.type = NCSI_PKT_CMD_EV;
+ nca.bytes[3] = NCSI_CAP_VLAN_NO;
+ }
+ nd->state = ncsi_dev_state_config_sma;
+ } else if (nd->state == ncsi_dev_state_config_sma) {
/* Use first entry in unicast filter table. Note that
* the MAC filter table starts from entry 1 instead of
* 0.
*/
- if (nd->state == ncsi_dev_state_config_sma) {
nca.type = NCSI_PKT_CMD_SMA;
for (index = 0; index < 6; index++)
nca.bytes[index] = dev->dev_addr[index];
@@ -751,6 +891,25 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
break;
case ncsi_dev_state_config_done:
spin_lock_irqsave(&nc->lock, flags);
+ if (nc->reconfigure_needed) {
+ /* This channel's configuration has been updated
+ * part-way during the config state - start the
+ * channel configuration over
+ */
+ nc->reconfigure_needed = false;
+ nc->state = NCSI_CHANNEL_INACTIVE;
+ spin_unlock_irqrestore(&nc->lock, flags);
+
+ spin_lock_irqsave(&ndp->lock, flags);
+ list_add_tail_rcu(&nc->link, &ndp->channel_queue);
+ spin_unlock_irqrestore(&ndp->lock, flags);
+
+ netdev_printk(KERN_DEBUG, dev,
+ "Dirty NCSI channel state reset\n");
+ ncsi_process_next_channel(ndp);
+ break;
+ }
+
if (nc->modes[NCSI_MODE_LINK].data[2] & 0x1) {
hot_nc = nc;
nc->state = NCSI_CHANNEL_ACTIVE;
@@ -1191,6 +1350,148 @@ static struct notifier_block ncsi_inet6addr_notifier = {
};
#endif /* CONFIG_IPV6 */
+static int ncsi_kick_channels(struct ncsi_dev_priv *ndp)
+{
+ struct ncsi_dev *nd = &ndp->ndev;
+ struct ncsi_channel *nc;
+ struct ncsi_package *np;
+ unsigned long flags;
+ unsigned int n = 0;
+
+ NCSI_FOR_EACH_PACKAGE(ndp, np) {
+ NCSI_FOR_EACH_CHANNEL(np, nc) {
+ spin_lock_irqsave(&nc->lock, flags);
+
+ /* Channels may be busy, mark dirty instead of
+ * kicking if;
+ * a) not ACTIVE (configured)
+ * b) in the channel_queue (to be configured)
+ * c) it's ndev is in the config state
+ */
+ if (nc->state != NCSI_CHANNEL_ACTIVE) {
+ if ((ndp->ndev.state & 0xff00) ==
+ ncsi_dev_state_config ||
+ !list_empty(&nc->link)) {
+ netdev_printk(KERN_DEBUG, nd->dev,
+ "ncsi: channel %p marked dirty\n",
+ nc);
+ nc->reconfigure_needed = true;
+ }
+ spin_unlock_irqrestore(&nc->lock, flags);
+ continue;
+ }
+
+ spin_unlock_irqrestore(&nc->lock, flags);
+
+ ncsi_stop_channel_monitor(nc);
+ spin_lock_irqsave(&nc->lock, flags);
+ nc->state = NCSI_CHANNEL_INACTIVE;
+ spin_unlock_irqrestore(&nc->lock, flags);
+
+ spin_lock_irqsave(&ndp->lock, flags);
+ list_add_tail_rcu(&nc->link, &ndp->channel_queue);
+ spin_unlock_irqrestore(&ndp->lock, flags);
+
+ netdev_printk(KERN_DEBUG, nd->dev,
+ "ncsi: kicked channel %p\n", nc);
+ n++;
+ }
+ }
+
+ return n;
+}
+
+int ncsi_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
+{
+ struct ncsi_channel_filter *ncf;
+ struct ncsi_dev_priv *ndp;
+ unsigned int n_vids = 0;
+ struct vlan_vid *vlan;
+ struct ncsi_dev *nd;
+ bool found = false;
+
+ if (vid == 0)
+ return 0;
+
+ nd = ncsi_find_dev(dev);
+ if (!nd) {
+ netdev_warn(dev, "ncsi: No net_device?\n");
+ return 0;
+ }
+
+ ndp = TO_NCSI_DEV_PRIV(nd);
+ ncf = ndp->hot_channel->filters[NCSI_FILTER_VLAN];
+
+ /* Add the VLAN id to our internal list */
+ list_for_each_entry_rcu(vlan, &ndp->vlan_vids, list) {
+ n_vids++;
+ if (vlan->vid == vid) {
+ netdev_printk(KERN_DEBUG, dev,
+ "vid %u already registered\n", vid);
+ return 0;
+ }
+ }
+
+ if (n_vids >= ncf->total) {
+ netdev_info(dev,
+ "NCSI Channel supports up to %u VLAN tags but %u are already set\n",
+ ncf->total, n_vids);
+ return -EINVAL;
+ }
+
+ vlan = kzalloc(sizeof(*vlan), GFP_KERNEL);
+ if (!vlan)
+ return -ENOMEM;
+
+ vlan->proto = proto;
+ vlan->vid = vid;
+ list_add_rcu(&vlan->list, &ndp->vlan_vids);
+
+ netdev_printk(KERN_DEBUG, dev, "Added new vid %u\n", vid);
+
+ found = ncsi_kick_channels(ndp) != 0;
+
+ return found ? ncsi_process_next_channel(ndp) : 0;
+}
+
+int ncsi_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
+{
+ struct vlan_vid *vlan, *tmp;
+ struct ncsi_dev_priv *ndp;
+ struct ncsi_dev *nd;
+ bool found = false;
+
+ if (vid == 0)
+ return 0;
+
+ nd = ncsi_find_dev(dev);
+ if (!nd) {
+ netdev_warn(dev, "ncsi: no net_device?\n");
+ return 0;
+ }
+
+ ndp = TO_NCSI_DEV_PRIV(nd);
+
+ /* Remove the VLAN id from our internal list */
+ list_for_each_entry_safe(vlan, tmp, &ndp->vlan_vids, list)
+ if (vlan->vid == vid) {
+ netdev_printk(KERN_DEBUG, dev,
+ "vid %u found, removing\n", vid);
+ list_del_rcu(&vlan->list);
+ found = true;
+ kfree(vlan);
+ }
+
+ if (!found) {
+ netdev_err(dev, "ncsi: vid %u wasn't registered!\n", vid);
+ return -EINVAL;
+ }
+
+ found = ncsi_kick_channels(ndp) != 0;
+
+ return found ? ncsi_process_next_channel(ndp) : 0;
+}
+
struct ncsi_dev *ncsi_register_dev(struct net_device *dev,
void (*handler)(struct ncsi_dev *ndev))
{
@@ -1215,6 +1516,7 @@ struct ncsi_dev *ncsi_register_dev(struct net_device *dev,
nd->handler = handler;
ndp->pending_req_num = 0;
INIT_LIST_HEAD(&ndp->channel_queue);
+ INIT_LIST_HEAD(&ndp->vlan_vids);
INIT_WORK(&ndp->work, ncsi_dev_work);
/* Initialize private NCSI device */
diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c
index c1a191d790e2..265b9a892d41 100644
--- a/net/ncsi/ncsi-rsp.c
+++ b/net/ncsi/ncsi-rsp.c
@@ -694,7 +694,14 @@ static int ncsi_rsp_handler_gc(struct ncsi_request *nr)
ncf->index = i;
ncf->total = cnt;
- ncf->bitmap = 0x0ul;
+ if (i == NCSI_FILTER_VLAN) {
+ /* Set VLAN filters active so they are cleared in
+ * first configuration state
+ */
+ ncf->bitmap = U64_MAX;
+ } else {
+ ncf->bitmap = 0x0ul;
+ }
nc->filters[i] = ncf;
}
--
2.14.0
^ permalink raw reply related
* [PATCH net-next v3 3/3] ftgmac100: Support NCSI VLAN filtering when available
From: Samuel Mendoza-Jonas @ 2017-08-28 6:18 UTC (permalink / raw)
To: David S . Miller, netdev, linux-kernel, OpenBMC Maillist
Cc: Samuel Mendoza-Jonas, Joel Stanley, Benjamin Herrenschmidt,
Gavin Shan, ratagupt
In-Reply-To: <20170828061843.24349-1-sam@mendozajonas.com>
Register the ndo_vlan_rx_{add,kill}_vid callbacks and set the
NETIF_F_HW_VLAN_CTAG_FILTER if NCSI is available.
This allows the VLAN core to notify the NCSI driver when changes occur
so that the remote NCSI channel can be properly configured to filter on
the set VLAN tags.
Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
---
v2: Moved ftgmac100 change into same patch and reordered
drivers/net/ethernet/faraday/ftgmac100.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 34dae51effd4..05fe7123d5ae 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1623,6 +1623,8 @@ static const struct net_device_ops ftgmac100_netdev_ops = {
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ftgmac100_poll_controller,
#endif
+ .ndo_vlan_rx_add_vid = ncsi_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = ncsi_vlan_rx_kill_vid,
};
static int ftgmac100_setup_mdio(struct net_device *netdev)
@@ -1837,6 +1839,9 @@ static int ftgmac100_probe(struct platform_device *pdev)
NETIF_F_GRO | NETIF_F_SG | NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_CTAG_TX;
+ if (priv->use_ncsi)
+ netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER;
+
/* AST2400 doesn't have working HW checksum generation */
if (np && (of_device_is_compatible(np, "aspeed,ast2400-mac")))
netdev->hw_features &= ~NETIF_F_HW_CSUM;
--
2.14.0
^ permalink raw reply related
* Re: [PATCH] DSA support for Micrel KSZ8895
From: Pavel Machek @ 2017-08-28 6:40 UTC (permalink / raw)
To: Andrew Lunn
Cc: Woojung.Huh, nathan.leigh.conrad, vivien.didelot, f.fainelli,
netdev, linux-kernel, Tristram.Ha
In-Reply-To: <20170827164434.GH13622@lunn.ch>
[-- Attachment #1: Type: text/plain, Size: 2959 bytes --]
Hi!
> > No, tag_ksz part probably is not acceptable. Do you see solution
> > better than just copying it into tag_ksz1 file?
>
> How about something like this, which needs further work to actually
> compile, but should give you the idea.
If that's acceptable, yes, I can do something similar. I don't think
CONFIG_NET_DSA_TAG_KSZ_8K / CONFIG_NET_DSA_TAG_KSZ_9K is suitable
naming (these will probably differ according to number of ports), what
about keeping CONFIG_NET_DSA_TAG_KSZ and adding
CONFIG_NET_DSA_TAG_KSZ_1B (for one byte)?
Thanks,
Pavel
> Andrew
>
> index 99e38af85fc5..843e77b7c270 100644
> --- a/net/dsa/dsa.c
> +++ b/net/dsa/dsa.c
> @@ -49,8 +49,11 @@ const struct dsa_device_ops *dsa_device_ops[DSA_TAG_LAST] = {
> #ifdef CONFIG_NET_DSA_TAG_EDSA
> [DSA_TAG_PROTO_EDSA] = &edsa_netdev_ops,
> #endif
> -#ifdef CONFIG_NET_DSA_TAG_KSZ
> - [DSA_TAG_PROTO_KSZ] = &ksz_netdev_ops,
> +#ifdef CONFIG_NET_DSA_TAG_KSZ_8K
> + [DSA_TAG_PROTO_KSZ8K] = &ksz8k_netdev_ops,
> +#endif
> +#ifdef CONFIG_NET_DSA_TAG_KSZ_9K
> + [DSA_TAG_PROTO_KSZ9K] = &ksz9k_netdev_ops,
> #endif
> #ifdef CONFIG_NET_DSA_TAG_LAN9303
> [DSA_TAG_PROTO_LAN9303] = &lan9303_netdev_ops,
> diff --git a/net/dsa/tag_ksz.c b/net/dsa/tag_ksz.c
> index de66ca8e6201..398b833889f1 100644
> --- a/net/dsa/tag_ksz.c
> +++ b/net/dsa/tag_ksz.c
> @@ -35,6 +35,9 @@
> static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev)
> {
> struct dsa_slave_priv *p = netdev_priv(dev);
> + struct dsa_port *dp = p->dp;
> + struct dsa_switch *ds = dp->ds;
> + struct dsa_switch_tree *dst = ds->dst;
> struct sk_buff *nskb;
> int padlen;
> u8 *tag;
> @@ -69,8 +72,14 @@ static struct sk_buff *ksz_xmit(struct sk_buff *skb, struct net_device *dev)
> }
>
> tag = skb_put(nskb, KSZ_INGRESS_TAG_LEN);
> - tag[0] = 0;
> - tag[1] = 1 << p->dp->index; /* destination port */
> + if (dst->tag_ops == ksz8k_netdev_ops) {
> + tag[0] = 1 << p->dp->index; /* destination port */0;
> + tag[1] = 0;
> + }
> +
> + if (dst->tag_ops == ksz9k_netdev_ops) {
> + tag[0] = 0;
> + tag[1] = 1 << p->dp->index; /* destination port */
>
> return nskb;
> }
> @@ -98,7 +107,12 @@ static struct sk_buff *ksz_rcv(struct sk_buff *skb, struct net_device *dev,
> return skb;
> }
>
> -const struct dsa_device_ops ksz_netdev_ops = {
> +const struct dsa_device_ops ksz8k_netdev_ops = {
> + .xmit = ksz_xmit,
> + .rcv = ksz_rcv,
> +};
> +
> +const struct dsa_device_ops ksz9k_netdev_ops = {
> .xmit = ksz_xmit,
> .rcv = ksz_rcv,
> };
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply
* [patch net-next 0/3] net/sched: Improve getting objects by indexes
From: Chris Mi @ 2017-08-28 6:41 UTC (permalink / raw)
To: netdev; +Cc: jhs, xiyou.wangcong, jiri, davem, mawilcox
Using current TC code, it is very slow to insert a lot of rules.
In order to improve the rules update rate in TC,
we introduced the following two changes:
1) changed cls_flower to use IDR to manage the filters.
2) changed all act_xxx modules to use IDR instead of
a small hash table
But IDR has a limitation that it uses int. TC handle uses u32.
To make sure there is no regression, we add several new IDR APIs
to support unsigned long.
Chris Mi (3):
idr: Add new APIs to support unsigned long
net/sched: Change cls_flower to use IDR
net/sched: Change act_api and act_xxx modules to use IDR
include/linux/idr.h | 16 +++
include/linux/radix-tree.h | 3 +
include/net/act_api.h | 76 +++++---------
lib/idr.c | 56 ++++++++++
lib/radix-tree.c | 73 +++++++++++++
net/sched/act_api.c | 251 ++++++++++++++++++++++-----------------------
net/sched/act_bpf.c | 17 ++-
net/sched/act_connmark.c | 16 ++-
net/sched/act_csum.c | 16 ++-
net/sched/act_gact.c | 16 ++-
net/sched/act_ife.c | 20 ++--
net/sched/act_ipt.c | 26 +++--
net/sched/act_mirred.c | 19 ++--
net/sched/act_nat.c | 16 ++-
net/sched/act_pedit.c | 18 ++--
net/sched/act_police.c | 18 ++--
net/sched/act_sample.c | 17 ++-
net/sched/act_simple.c | 20 ++--
net/sched/act_skbedit.c | 18 ++--
net/sched/act_skbmod.c | 18 ++--
net/sched/act_tunnel_key.c | 20 ++--
net/sched/act_vlan.c | 22 ++--
net/sched/cls_flower.c | 55 +++++-----
23 files changed, 450 insertions(+), 377 deletions(-)
--
1.8.3.1
^ permalink raw reply
* [patch net-next 1/3] idr: Add new APIs to support unsigned long
From: Chris Mi @ 2017-08-28 6:41 UTC (permalink / raw)
To: netdev; +Cc: jhs, xiyou.wangcong, jiri, davem, mawilcox
In-Reply-To: <1503902477-39829-1-git-send-email-chrism@mellanox.com>
The following new APIs are added:
int idr_alloc_ext(struct idr *idr, void *ptr, unsigned long *index,
unsigned long start, unsigned long end, gfp_t gfp);
static inline void *idr_remove_ext(struct idr *idr, unsigned long id);
static inline void *idr_find_ext(const struct idr *idr, unsigned long id);
void *idr_replace_ext(struct idr *idr, void *ptr, unsigned long id);
void *idr_get_next_ext(struct idr *idr, unsigned long *nextid);
Signed-off-by: Chris Mi <chrism@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/linux/idr.h | 16 ++++++++++
include/linux/radix-tree.h | 3 ++
lib/idr.c | 56 +++++++++++++++++++++++++++++++++++
lib/radix-tree.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 148 insertions(+)
diff --git a/include/linux/idr.h b/include/linux/idr.h
index bf70b3e..e0a030b 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -81,11 +81,15 @@ static inline void idr_set_cursor(struct idr *idr, unsigned int val)
void idr_preload(gfp_t gfp_mask);
int idr_alloc(struct idr *, void *entry, int start, int end, gfp_t);
+int idr_alloc_ext(struct idr *idr, void *ptr, unsigned long *index,
+ unsigned long start, unsigned long end, gfp_t gfp);
int idr_alloc_cyclic(struct idr *, void *entry, int start, int end, gfp_t);
int idr_for_each(const struct idr *,
int (*fn)(int id, void *p, void *data), void *data);
void *idr_get_next(struct idr *, int *nextid);
+void *idr_get_next_ext(struct idr *idr, unsigned long *nextid);
void *idr_replace(struct idr *, void *, int id);
+void *idr_replace_ext(struct idr *idr, void *ptr, unsigned long id);
void idr_destroy(struct idr *);
static inline void *idr_remove(struct idr *idr, int id)
@@ -93,6 +97,11 @@ static inline void *idr_remove(struct idr *idr, int id)
return radix_tree_delete_item(&idr->idr_rt, id, NULL);
}
+static inline void *idr_remove_ext(struct idr *idr, unsigned long id)
+{
+ return radix_tree_delete_item(&idr->idr_rt, id, NULL);
+}
+
static inline void idr_init(struct idr *idr)
{
INIT_RADIX_TREE(&idr->idr_rt, IDR_RT_MARKER);
@@ -133,6 +142,11 @@ static inline void *idr_find(const struct idr *idr, int id)
return radix_tree_lookup(&idr->idr_rt, id);
}
+static inline void *idr_find_ext(const struct idr *idr, unsigned long id)
+{
+ return radix_tree_lookup(&idr->idr_rt, id);
+}
+
/**
* idr_for_each_entry - iterate over an idr's elements of a given type
* @idr: idr handle
@@ -145,6 +159,8 @@ static inline void *idr_find(const struct idr *idr, int id)
*/
#define idr_for_each_entry(idr, entry, id) \
for (id = 0; ((entry) = idr_get_next(idr, &(id))) != NULL; ++id)
+#define idr_for_each_entry_ext(idr, entry, id) \
+ for (id = 0; ((entry) = idr_get_next_ext(idr, &(id))) != NULL; ++id)
/**
* idr_for_each_entry_continue - continue iteration over an idr's elements of a given type
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
index 3e57350..947299e 100644
--- a/include/linux/radix-tree.h
+++ b/include/linux/radix-tree.h
@@ -359,6 +359,9 @@ int radix_tree_join(struct radix_tree_root *, unsigned long index,
unsigned new_order, void *);
void __rcu **idr_get_free(struct radix_tree_root *, struct radix_tree_iter *,
gfp_t, int end);
+void __rcu **idr_get_free_ext(struct radix_tree_root *root,
+ struct radix_tree_iter *iter,
+ gfp_t gfp, unsigned long end);
enum {
RADIX_TREE_ITER_TAG_MASK = 0x0f, /* tag index in lower nybble */
diff --git a/lib/idr.c b/lib/idr.c
index b13682b..2a091b9 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -47,6 +47,29 @@ int idr_alloc(struct idr *idr, void *ptr, int start, int end, gfp_t gfp)
}
EXPORT_SYMBOL_GPL(idr_alloc);
+int idr_alloc_ext(struct idr *idr, void *ptr, unsigned long *index,
+ unsigned long start, unsigned long end, gfp_t gfp)
+{
+ void __rcu **slot;
+ struct radix_tree_iter iter;
+
+ if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr)))
+ return -EINVAL;
+
+ radix_tree_iter_init(&iter, start);
+ slot = idr_get_free_ext(&idr->idr_rt, &iter, gfp, end);
+ if (IS_ERR(slot))
+ return PTR_ERR(slot);
+
+ radix_tree_iter_replace(&idr->idr_rt, &iter, slot, ptr);
+ radix_tree_iter_tag_clear(&idr->idr_rt, &iter, IDR_FREE);
+
+ if (index)
+ *index = iter.index;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(idr_alloc_ext);
+
/**
* idr_alloc_cyclic - allocate new idr entry in a cyclical fashion
* @idr: idr handle
@@ -134,6 +157,20 @@ void *idr_get_next(struct idr *idr, int *nextid)
}
EXPORT_SYMBOL(idr_get_next);
+void *idr_get_next_ext(struct idr *idr, unsigned long *nextid)
+{
+ struct radix_tree_iter iter;
+ void __rcu **slot;
+
+ slot = radix_tree_iter_find(&idr->idr_rt, &iter, *nextid);
+ if (!slot)
+ return NULL;
+
+ *nextid = iter.index;
+ return rcu_dereference_raw(*slot);
+}
+EXPORT_SYMBOL(idr_get_next_ext);
+
/**
* idr_replace - replace pointer for given id
* @idr: idr handle
@@ -169,6 +206,25 @@ void *idr_replace(struct idr *idr, void *ptr, int id)
}
EXPORT_SYMBOL(idr_replace);
+void *idr_replace_ext(struct idr *idr, void *ptr, unsigned long id)
+{
+ struct radix_tree_node *node;
+ void __rcu **slot = NULL;
+ void *entry;
+
+ if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr)))
+ return ERR_PTR(-EINVAL);
+
+ entry = __radix_tree_lookup(&idr->idr_rt, id, &node, &slot);
+ if (!slot || radix_tree_tag_get(&idr->idr_rt, id, IDR_FREE))
+ return ERR_PTR(-ENOENT);
+
+ __radix_tree_replace(&idr->idr_rt, node, slot, ptr, NULL, NULL);
+
+ return entry;
+}
+EXPORT_SYMBOL(idr_replace_ext);
+
/**
* DOC: IDA description
*
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 898e879..06bfdbd 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -2208,6 +2208,79 @@ void __rcu **idr_get_free(struct radix_tree_root *root,
return slot;
}
+void __rcu **idr_get_free_ext(struct radix_tree_root *root,
+ struct radix_tree_iter *iter,
+ gfp_t gfp, unsigned long end)
+{
+ struct radix_tree_node *node = NULL, *child;
+ void __rcu **slot = (void __rcu **)&root->rnode;
+ unsigned long maxindex, start = iter->next_index;
+ unsigned long max = end - 1;
+ unsigned int shift, offset = 0;
+
+ grow:
+ shift = radix_tree_load_root(root, &child, &maxindex);
+ if (!radix_tree_tagged(root, IDR_FREE))
+ start = max(start, maxindex + 1);
+ if (start > max)
+ return ERR_PTR(-ENOSPC);
+
+ if (start > maxindex) {
+ int error = radix_tree_extend(root, gfp, start, shift);
+
+ if (error < 0)
+ return ERR_PTR(error);
+ shift = error;
+ child = rcu_dereference_raw(root->rnode);
+ }
+
+ while (shift) {
+ shift -= RADIX_TREE_MAP_SHIFT;
+ if (child == NULL) {
+ /* Have to add a child node. */
+ child = radix_tree_node_alloc(gfp, node, root, shift,
+ offset, 0, 0);
+ if (!child)
+ return ERR_PTR(-ENOMEM);
+ all_tag_set(child, IDR_FREE);
+ rcu_assign_pointer(*slot, node_to_entry(child));
+ if (node)
+ node->count++;
+ } else if (!radix_tree_is_internal_node(child))
+ break;
+
+ node = entry_to_node(child);
+ offset = radix_tree_descend(node, &child, start);
+ if (!tag_get(node, IDR_FREE, offset)) {
+ offset = radix_tree_find_next_bit(node, IDR_FREE,
+ offset + 1);
+ start = next_index(start, node, offset);
+ if (start > max)
+ return ERR_PTR(-ENOSPC);
+ while (offset == RADIX_TREE_MAP_SIZE) {
+ offset = node->offset + 1;
+ node = node->parent;
+ if (!node)
+ goto grow;
+ shift = node->shift;
+ }
+ child = rcu_dereference_raw(node->slots[offset]);
+ }
+ slot = &node->slots[offset];
+ }
+
+ iter->index = start;
+ if (node)
+ iter->next_index = 1 + min(max, (start | node_maxindex(node)));
+ else
+ iter->next_index = 1;
+ iter->node = node;
+ __set_iter_shift(iter, shift);
+ set_iter_tags(iter, node, offset, IDR_FREE);
+
+ return slot;
+}
+
/**
* idr_destroy - release all internal memory from an IDR
* @idr: idr handle
--
1.8.3.1
^ permalink raw reply related
* [patch net-next 2/3] net/sched: Change cls_flower to use IDR
From: Chris Mi @ 2017-08-28 6:41 UTC (permalink / raw)
To: netdev; +Cc: jhs, xiyou.wangcong, jiri, davem, mawilcox
In-Reply-To: <1503902477-39829-1-git-send-email-chrism@mellanox.com>
Currently, all filters with the same priority are linked in a doubly
linked list. Every filter should have a unique handle. To make the
handle unique, we need to iterate the list every time to see if the
handle exists or not when inserting a new filter. It is time-consuming.
For example, it takes about 5m3.169s to insert 64K rules.
This patch changes cls_flower to use IDR. With this patch, it
takes about 0m1.127s to insert 64K rules. The improvement is huge.
But please note that in this testing, all filters share the same action.
If every filter has a unique action, that is another bottleneck.
Follow-up patch in this patchset addresses that.
Signed-off-by: Chris Mi <chrism@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
net/sched/cls_flower.c | 55 +++++++++++++++++++++-----------------------------
1 file changed, 23 insertions(+), 32 deletions(-)
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index bd9dab4..3d041d2 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -68,7 +68,6 @@ struct cls_fl_head {
struct rhashtable ht;
struct fl_flow_mask mask;
struct flow_dissector dissector;
- u32 hgen;
bool mask_assigned;
struct list_head filters;
struct rhashtable_params ht_params;
@@ -76,6 +75,7 @@ struct cls_fl_head {
struct work_struct work;
struct rcu_head rcu;
};
+ struct idr handle_idr;
};
struct cls_fl_filter {
@@ -210,6 +210,7 @@ static int fl_init(struct tcf_proto *tp)
INIT_LIST_HEAD_RCU(&head->filters);
rcu_assign_pointer(tp->root, head);
+ idr_init(&head->handle_idr);
return 0;
}
@@ -295,6 +296,9 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
static void __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f)
{
+ struct cls_fl_head *head = rtnl_dereference(tp->root);
+
+ idr_remove_ext(&head->handle_idr, f->handle);
list_del_rcu(&f->list);
if (!tc_skip_hw(f->flags))
fl_hw_destroy_filter(tp, f);
@@ -327,6 +331,7 @@ static void fl_destroy(struct tcf_proto *tp)
list_for_each_entry_safe(f, next, &head->filters, list)
__fl_delete(tp, f);
+ idr_destroy(&head->handle_idr);
__module_get(THIS_MODULE);
call_rcu(&head->rcu, fl_destroy_rcu);
@@ -335,12 +340,8 @@ static void fl_destroy(struct tcf_proto *tp)
static void *fl_get(struct tcf_proto *tp, u32 handle)
{
struct cls_fl_head *head = rtnl_dereference(tp->root);
- struct cls_fl_filter *f;
- list_for_each_entry(f, &head->filters, list)
- if (f->handle == handle)
- return f;
- return NULL;
+ return idr_find_ext(&head->handle_idr, handle);
}
static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = {
@@ -859,27 +860,6 @@ static int fl_set_parms(struct net *net, struct tcf_proto *tp,
return 0;
}
-static u32 fl_grab_new_handle(struct tcf_proto *tp,
- struct cls_fl_head *head)
-{
- unsigned int i = 0x80000000;
- u32 handle;
-
- do {
- if (++head->hgen == 0x7FFFFFFF)
- head->hgen = 1;
- } while (--i > 0 && fl_get(tp, head->hgen));
-
- if (unlikely(i == 0)) {
- pr_err("Insufficient number of handles\n");
- handle = 0;
- } else {
- handle = head->hgen;
- }
-
- return handle;
-}
-
static int fl_change(struct net *net, struct sk_buff *in_skb,
struct tcf_proto *tp, unsigned long base,
u32 handle, struct nlattr **tca,
@@ -890,6 +870,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
struct cls_fl_filter *fnew;
struct nlattr **tb;
struct fl_flow_mask mask = {};
+ unsigned long idr_index;
int err;
if (!tca[TCA_OPTIONS])
@@ -920,13 +901,21 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
goto errout;
if (!handle) {
- handle = fl_grab_new_handle(tp, head);
- if (!handle) {
- err = -EINVAL;
+ err = idr_alloc_ext(&head->handle_idr, fnew, &idr_index,
+ 1, 0x80000000, GFP_KERNEL);
+ if (err)
goto errout;
- }
+ fnew->handle = idr_index;
+ }
+
+ /* user specifies a handle and it doesn't exist */
+ if (handle && !fold) {
+ err = idr_alloc_ext(&head->handle_idr, fnew, &idr_index,
+ handle, handle + 1, GFP_KERNEL);
+ if (err)
+ goto errout;
+ fnew->handle = idr_index;
}
- fnew->handle = handle;
if (tb[TCA_FLOWER_FLAGS]) {
fnew->flags = nla_get_u32(tb[TCA_FLOWER_FLAGS]);
@@ -980,6 +969,8 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
*arg = fnew;
if (fold) {
+ fnew->handle = handle;
+ idr_replace_ext(&head->handle_idr, fnew, fnew->handle);
list_replace_rcu(&fold->list, &fnew->list);
tcf_unbind_filter(tp, &fold->res);
call_rcu(&fold->rcu, fl_destroy_filter);
--
1.8.3.1
^ permalink raw reply related
* [patch net-next 3/3] net/sched: Change act_api and act_xxx modules to use IDR
From: Chris Mi @ 2017-08-28 6:41 UTC (permalink / raw)
To: netdev; +Cc: jhs, xiyou.wangcong, jiri, davem, mawilcox
In-Reply-To: <1503902477-39829-1-git-send-email-chrism@mellanox.com>
Typically, each TC filter has its own action. All the actions of the
same type are saved in its hash table. But the hash buckets are too
small that it degrades to a list. And the performance is greatly
affected. For example, it takes about 0m11.914s to insert 64K rules.
If we convert the hash table to IDR, it only takes about 0m1.500s.
The improvement is huge.
But please note that the test result is based on previous patch that
cls_flower uses IDR.
Signed-off-by: Chris Mi <chrism@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/act_api.h | 76 +++++---------
net/sched/act_api.c | 251 ++++++++++++++++++++++-----------------------
net/sched/act_bpf.c | 17 ++-
net/sched/act_connmark.c | 16 ++-
net/sched/act_csum.c | 16 ++-
net/sched/act_gact.c | 16 ++-
net/sched/act_ife.c | 20 ++--
net/sched/act_ipt.c | 26 +++--
net/sched/act_mirred.c | 19 ++--
net/sched/act_nat.c | 16 ++-
net/sched/act_pedit.c | 18 ++--
net/sched/act_police.c | 18 ++--
net/sched/act_sample.c | 17 ++-
net/sched/act_simple.c | 20 ++--
net/sched/act_skbedit.c | 18 ++--
net/sched/act_skbmod.c | 18 ++--
net/sched/act_tunnel_key.c | 20 ++--
net/sched/act_vlan.c | 22 ++--
18 files changed, 279 insertions(+), 345 deletions(-)
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 26ffd83..8f3d5d8 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -10,12 +10,9 @@
#include <net/net_namespace.h>
#include <net/netns/generic.h>
-
-struct tcf_hashinfo {
- struct hlist_head *htab;
- unsigned int hmask;
- spinlock_t lock;
- u32 index;
+struct tcf_idrinfo {
+ spinlock_t lock;
+ struct idr action_idr;
};
struct tc_action_ops;
@@ -25,9 +22,8 @@ struct tc_action {
__u32 type; /* for backward compat(TCA_OLD_COMPAT) */
__u32 order;
struct list_head list;
- struct tcf_hashinfo *hinfo;
+ struct tcf_idrinfo *idrinfo;
- struct hlist_node tcfa_head;
u32 tcfa_index;
int tcfa_refcnt;
int tcfa_bindcnt;
@@ -44,7 +40,6 @@ struct tc_action {
struct tc_cookie *act_cookie;
struct tcf_chain *goto_chain;
};
-#define tcf_head common.tcfa_head
#define tcf_index common.tcfa_index
#define tcf_refcnt common.tcfa_refcnt
#define tcf_bindcnt common.tcfa_bindcnt
@@ -57,27 +52,6 @@ struct tc_action {
#define tcf_lock common.tcfa_lock
#define tcf_rcu common.tcfa_rcu
-static inline unsigned int tcf_hash(u32 index, unsigned int hmask)
-{
- return index & hmask;
-}
-
-static inline int tcf_hashinfo_init(struct tcf_hashinfo *hf, unsigned int mask)
-{
- int i;
-
- spin_lock_init(&hf->lock);
- hf->index = 0;
- hf->hmask = mask;
- hf->htab = kzalloc((mask + 1) * sizeof(struct hlist_head),
- GFP_KERNEL);
- if (!hf->htab)
- return -ENOMEM;
- for (i = 0; i < mask + 1; i++)
- INIT_HLIST_HEAD(&hf->htab[i]);
- return 0;
-}
-
/* Update lastuse only if needed, to avoid dirtying a cache line.
* We use a temp variable to avoid fetching jiffies twice.
*/
@@ -126,53 +100,51 @@ struct tc_action_ops {
};
struct tc_action_net {
- struct tcf_hashinfo *hinfo;
+ struct tcf_idrinfo *idrinfo;
const struct tc_action_ops *ops;
};
static inline
int tc_action_net_init(struct tc_action_net *tn,
- const struct tc_action_ops *ops, unsigned int mask)
+ const struct tc_action_ops *ops)
{
int err = 0;
- tn->hinfo = kmalloc(sizeof(*tn->hinfo), GFP_KERNEL);
- if (!tn->hinfo)
+ tn->idrinfo = kmalloc(sizeof(*tn->idrinfo), GFP_KERNEL);
+ if (!tn->idrinfo)
return -ENOMEM;
tn->ops = ops;
- err = tcf_hashinfo_init(tn->hinfo, mask);
- if (err)
- kfree(tn->hinfo);
+ spin_lock_init(&tn->idrinfo->lock);
+ idr_init(&tn->idrinfo->action_idr);
return err;
}
-void tcf_hashinfo_destroy(const struct tc_action_ops *ops,
- struct tcf_hashinfo *hinfo);
+void tcf_idrinfo_destroy(const struct tc_action_ops *ops,
+ struct tcf_idrinfo *idrinfo);
static inline void tc_action_net_exit(struct tc_action_net *tn)
{
- tcf_hashinfo_destroy(tn->ops, tn->hinfo);
- kfree(tn->hinfo);
+ tcf_idrinfo_destroy(tn->ops, tn->idrinfo);
+ kfree(tn->idrinfo);
}
int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
struct netlink_callback *cb, int type,
const struct tc_action_ops *ops);
-int tcf_hash_search(struct tc_action_net *tn, struct tc_action **a, u32 index);
-u32 tcf_hash_new_index(struct tc_action_net *tn);
-bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
+int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index);
+bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
int bind);
-int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
- struct tc_action **a, const struct tc_action_ops *ops, int bind,
- bool cpustats);
-void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est);
-void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a);
+int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
+ struct tc_action **a, const struct tc_action_ops *ops,
+ int bind, bool cpustats);
+void tcf_idr_cleanup(struct tc_action *a, struct nlattr *est);
+void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a);
-int __tcf_hash_release(struct tc_action *a, bool bind, bool strict);
+int __tcf_idr_release(struct tc_action *a, bool bind, bool strict);
-static inline int tcf_hash_release(struct tc_action *a, bool bind)
+static inline int tcf_idr_release(struct tc_action *a, bool bind)
{
- return __tcf_hash_release(a, bind, false);
+ return __tcf_idr_release(a, bind, false);
}
int tcf_register_action(struct tc_action_ops *a, struct pernet_operations *ops);
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 02fcb0c..0eb545b 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -70,11 +70,11 @@ static void free_tcf(struct rcu_head *head)
kfree(p);
}
-static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *p)
+static void tcf_idr_remove(struct tcf_idrinfo *idrinfo, struct tc_action *p)
{
- spin_lock_bh(&hinfo->lock);
- hlist_del(&p->tcfa_head);
- spin_unlock_bh(&hinfo->lock);
+ spin_lock_bh(&idrinfo->lock);
+ idr_remove_ext(&idrinfo->action_idr, p->tcfa_index);
+ spin_unlock_bh(&idrinfo->lock);
gen_kill_estimator(&p->tcfa_rate_est);
/*
* gen_estimator est_timer() might access p->tcfa_lock
@@ -83,7 +83,7 @@ static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *p)
call_rcu(&p->tcfa_rcu, free_tcf);
}
-int __tcf_hash_release(struct tc_action *p, bool bind, bool strict)
+int __tcf_idr_release(struct tc_action *p, bool bind, bool strict)
{
int ret = 0;
@@ -97,64 +97,60 @@ int __tcf_hash_release(struct tc_action *p, bool bind, bool strict)
if (p->tcfa_bindcnt <= 0 && p->tcfa_refcnt <= 0) {
if (p->ops->cleanup)
p->ops->cleanup(p, bind);
- tcf_hash_destroy(p->hinfo, p);
+ tcf_idr_remove(p->idrinfo, p);
ret = ACT_P_DELETED;
}
}
return ret;
}
-EXPORT_SYMBOL(__tcf_hash_release);
+EXPORT_SYMBOL(__tcf_idr_release);
-static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
+static int tcf_dump_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
struct netlink_callback *cb)
{
- int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
+ int err = 0, index = -1, s_i = 0, n_i = 0;
u32 act_flags = cb->args[2];
unsigned long jiffy_since = cb->args[3];
struct nlattr *nest;
+ struct idr *idr = &idrinfo->action_idr;
+ struct tc_action *p;
+ unsigned long id = 1;
- spin_lock_bh(&hinfo->lock);
+ spin_lock_bh(&idrinfo->lock);
s_i = cb->args[0];
- for (i = 0; i < (hinfo->hmask + 1); i++) {
- struct hlist_head *head;
- struct tc_action *p;
-
- head = &hinfo->htab[tcf_hash(i, hinfo->hmask)];
-
- hlist_for_each_entry_rcu(p, head, tcfa_head) {
- index++;
- if (index < s_i)
- continue;
-
- if (jiffy_since &&
- time_after(jiffy_since,
- (unsigned long)p->tcfa_tm.lastuse))
- continue;
-
- nest = nla_nest_start(skb, n_i);
- if (nest == NULL)
- goto nla_put_failure;
- err = tcf_action_dump_1(skb, p, 0, 0);
- if (err < 0) {
- index--;
- nlmsg_trim(skb, nest);
- goto done;
- }
- nla_nest_end(skb, nest);
- n_i++;
- if (!(act_flags & TCA_FLAG_LARGE_DUMP_ON) &&
- n_i >= TCA_ACT_MAX_PRIO)
- goto done;
+ idr_for_each_entry_ext(idr, p, id) {
+ index++;
+ if (index < s_i)
+ continue;
+
+ if (jiffy_since &&
+ time_after(jiffy_since,
+ (unsigned long)p->tcfa_tm.lastuse))
+ continue;
+
+ nest = nla_nest_start(skb, n_i);
+ if (!nest)
+ goto nla_put_failure;
+ err = tcf_action_dump_1(skb, p, 0, 0);
+ if (err < 0) {
+ index--;
+ nlmsg_trim(skb, nest);
+ goto done;
}
+ nla_nest_end(skb, nest);
+ n_i++;
+ if (!(act_flags & TCA_FLAG_LARGE_DUMP_ON) &&
+ n_i >= TCA_ACT_MAX_PRIO)
+ goto done;
}
done:
if (index >= 0)
cb->args[0] = index + 1;
- spin_unlock_bh(&hinfo->lock);
+ spin_unlock_bh(&idrinfo->lock);
if (n_i) {
if (act_flags & TCA_FLAG_LARGE_DUMP_ON)
cb->args[1] = n_i;
@@ -166,31 +162,29 @@ static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
goto done;
}
-static int tcf_del_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
+static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
const struct tc_action_ops *ops)
{
struct nlattr *nest;
- int i = 0, n_i = 0;
+ int n_i = 0;
int ret = -EINVAL;
+ struct idr *idr = &idrinfo->action_idr;
+ struct tc_action *p;
+ unsigned long id = 1;
nest = nla_nest_start(skb, 0);
if (nest == NULL)
goto nla_put_failure;
if (nla_put_string(skb, TCA_KIND, ops->kind))
goto nla_put_failure;
- for (i = 0; i < (hinfo->hmask + 1); i++) {
- struct hlist_head *head;
- struct hlist_node *n;
- struct tc_action *p;
-
- head = &hinfo->htab[tcf_hash(i, hinfo->hmask)];
- hlist_for_each_entry_safe(p, n, head, tcfa_head) {
- ret = __tcf_hash_release(p, false, true);
- if (ret == ACT_P_DELETED) {
- module_put(p->ops->owner);
- n_i++;
- } else if (ret < 0)
- goto nla_put_failure;
+
+ idr_for_each_entry_ext(idr, p, id) {
+ ret = __tcf_idr_release(p, false, true);
+ if (ret == ACT_P_DELETED) {
+ module_put(p->ops->owner);
+ n_i++;
+ } else if (ret < 0) {
+ goto nla_put_failure;
}
}
if (nla_put_u32(skb, TCA_FCNT, n_i))
@@ -207,12 +201,12 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
struct netlink_callback *cb, int type,
const struct tc_action_ops *ops)
{
- struct tcf_hashinfo *hinfo = tn->hinfo;
+ struct tcf_idrinfo *idrinfo = tn->idrinfo;
if (type == RTM_DELACTION) {
- return tcf_del_walker(hinfo, skb, ops);
+ return tcf_del_walker(idrinfo, skb, ops);
} else if (type == RTM_GETACTION) {
- return tcf_dump_walker(hinfo, skb, cb);
+ return tcf_dump_walker(idrinfo, skb, cb);
} else {
WARN(1, "tcf_generic_walker: unknown action %d\n", type);
return -EINVAL;
@@ -220,40 +214,21 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
}
EXPORT_SYMBOL(tcf_generic_walker);
-static struct tc_action *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo)
+static struct tc_action *tcf_idr_lookup(u32 index, struct tcf_idrinfo *idrinfo)
{
struct tc_action *p = NULL;
- struct hlist_head *head;
- spin_lock_bh(&hinfo->lock);
- head = &hinfo->htab[tcf_hash(index, hinfo->hmask)];
- hlist_for_each_entry_rcu(p, head, tcfa_head)
- if (p->tcfa_index == index)
- break;
- spin_unlock_bh(&hinfo->lock);
+ spin_lock_bh(&idrinfo->lock);
+ p = idr_find_ext(&idrinfo->action_idr, index);
+ spin_unlock_bh(&idrinfo->lock);
return p;
}
-u32 tcf_hash_new_index(struct tc_action_net *tn)
-{
- struct tcf_hashinfo *hinfo = tn->hinfo;
- u32 val = hinfo->index;
-
- do {
- if (++val == 0)
- val = 1;
- } while (tcf_hash_lookup(val, hinfo));
-
- hinfo->index = val;
- return val;
-}
-EXPORT_SYMBOL(tcf_hash_new_index);
-
-int tcf_hash_search(struct tc_action_net *tn, struct tc_action **a, u32 index)
+int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index)
{
- struct tcf_hashinfo *hinfo = tn->hinfo;
- struct tc_action *p = tcf_hash_lookup(index, hinfo);
+ struct tcf_idrinfo *idrinfo = tn->idrinfo;
+ struct tc_action *p = tcf_idr_lookup(index, idrinfo);
if (p) {
*a = p;
@@ -261,15 +236,15 @@ int tcf_hash_search(struct tc_action_net *tn, struct tc_action **a, u32 index)
}
return 0;
}
-EXPORT_SYMBOL(tcf_hash_search);
+EXPORT_SYMBOL(tcf_idr_search);
-bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
- int bind)
+bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
+ int bind)
{
- struct tcf_hashinfo *hinfo = tn->hinfo;
- struct tc_action *p = NULL;
+ struct tcf_idrinfo *idrinfo = tn->idrinfo;
+ struct tc_action *p = tcf_idr_lookup(index, idrinfo);
- if (index && (p = tcf_hash_lookup(index, hinfo)) != NULL) {
+ if (index && p) {
if (bind)
p->tcfa_bindcnt++;
p->tcfa_refcnt++;
@@ -278,23 +253,25 @@ bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
}
return false;
}
-EXPORT_SYMBOL(tcf_hash_check);
+EXPORT_SYMBOL(tcf_idr_check);
-void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est)
+void tcf_idr_cleanup(struct tc_action *a, struct nlattr *est)
{
if (est)
gen_kill_estimator(&a->tcfa_rate_est);
call_rcu(&a->tcfa_rcu, free_tcf);
}
-EXPORT_SYMBOL(tcf_hash_cleanup);
+EXPORT_SYMBOL(tcf_idr_cleanup);
-int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
- struct tc_action **a, const struct tc_action_ops *ops,
- int bind, bool cpustats)
+int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
+ struct tc_action **a, const struct tc_action_ops *ops,
+ int bind, bool cpustats)
{
struct tc_action *p = kzalloc(ops->size, GFP_KERNEL);
- struct tcf_hashinfo *hinfo = tn->hinfo;
+ struct tcf_idrinfo *idrinfo = tn->idrinfo;
+ struct idr *idr = &idrinfo->action_idr;
int err = -ENOMEM;
+ unsigned long idr_index;
if (unlikely(!p))
return -ENOMEM;
@@ -317,8 +294,28 @@ int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
}
}
spin_lock_init(&p->tcfa_lock);
- INIT_HLIST_NODE(&p->tcfa_head);
- p->tcfa_index = index ? index : tcf_hash_new_index(tn);
+ /* user doesn't specify an index */
+ if (!index) {
+ spin_lock_bh(&idrinfo->lock);
+ err = idr_alloc_ext(idr, NULL, &idr_index, 1, 0,
+ GFP_KERNEL);
+ spin_unlock_bh(&idrinfo->lock);
+ if (err) {
+err3:
+ free_percpu(p->cpu_qstats);
+ goto err2;
+ }
+ p->tcfa_index = idr_index;
+ } else {
+ spin_lock_bh(&idrinfo->lock);
+ err = idr_alloc_ext(idr, NULL, NULL, index, index + 1,
+ GFP_KERNEL);
+ spin_unlock_bh(&idrinfo->lock);
+ if (err)
+ goto err3;
+ p->tcfa_index = index;
+ }
+
p->tcfa_tm.install = jiffies;
p->tcfa_tm.lastuse = jiffies;
p->tcfa_tm.firstuse = 0;
@@ -327,52 +324,46 @@ int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
&p->tcfa_rate_est,
&p->tcfa_lock, NULL, est);
if (err) {
- free_percpu(p->cpu_qstats);
- goto err2;
+ goto err3;
}
}
- p->hinfo = hinfo;
+ p->idrinfo = idrinfo;
p->ops = ops;
INIT_LIST_HEAD(&p->list);
*a = p;
return 0;
}
-EXPORT_SYMBOL(tcf_hash_create);
+EXPORT_SYMBOL(tcf_idr_create);
-void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a)
+void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a)
{
- struct tcf_hashinfo *hinfo = tn->hinfo;
- unsigned int h = tcf_hash(a->tcfa_index, hinfo->hmask);
+ struct tcf_idrinfo *idrinfo = tn->idrinfo;
- spin_lock_bh(&hinfo->lock);
- hlist_add_head(&a->tcfa_head, &hinfo->htab[h]);
- spin_unlock_bh(&hinfo->lock);
+ spin_lock_bh(&idrinfo->lock);
+ idr_replace_ext(&idrinfo->action_idr, a, a->tcfa_index);
+ spin_unlock_bh(&idrinfo->lock);
}
-EXPORT_SYMBOL(tcf_hash_insert);
+EXPORT_SYMBOL(tcf_idr_insert);
-void tcf_hashinfo_destroy(const struct tc_action_ops *ops,
- struct tcf_hashinfo *hinfo)
+void tcf_idrinfo_destroy(const struct tc_action_ops *ops,
+ struct tcf_idrinfo *idrinfo)
{
- int i;
-
- for (i = 0; i < hinfo->hmask + 1; i++) {
- struct tc_action *p;
- struct hlist_node *n;
-
- hlist_for_each_entry_safe(p, n, &hinfo->htab[i], tcfa_head) {
- int ret;
+ struct idr *idr = &idrinfo->action_idr;
+ struct tc_action *p;
+ int ret;
+ unsigned long id = 1;
- ret = __tcf_hash_release(p, false, true);
- if (ret == ACT_P_DELETED)
- module_put(ops->owner);
- else if (ret < 0)
- return;
- }
+ idr_for_each_entry_ext(idr, p, id) {
+ ret = __tcf_idr_release(p, false, true);
+ if (ret == ACT_P_DELETED)
+ module_put(ops->owner);
+ else if (ret < 0)
+ return;
}
- kfree(hinfo->htab);
+ idr_destroy(&idrinfo->action_idr);
}
-EXPORT_SYMBOL(tcf_hashinfo_destroy);
+EXPORT_SYMBOL(tcf_idrinfo_destroy);
static LIST_HEAD(act_base);
static DEFINE_RWLOCK(act_mod_lock);
@@ -524,7 +515,7 @@ int tcf_action_destroy(struct list_head *actions, int bind)
int ret = 0;
list_for_each_entry_safe(a, tmp, actions, list) {
- ret = __tcf_hash_release(a, bind, true);
+ ret = __tcf_idr_release(a, bind, true);
if (ret == ACT_P_DELETED)
module_put(a->ops->owner);
else if (ret < 0)
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index 9afe133..c0c707e 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -21,7 +21,6 @@
#include <linux/tc_act/tc_bpf.h>
#include <net/tc_act/tc_bpf.h>
-#define BPF_TAB_MASK 15
#define ACT_BPF_NAME_LEN 256
struct tcf_bpf_cfg {
@@ -295,9 +294,9 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
parm = nla_data(tb[TCA_ACT_BPF_PARMS]);
- if (!tcf_hash_check(tn, parm->index, act, bind)) {
- ret = tcf_hash_create(tn, parm->index, est, act,
- &act_bpf_ops, bind, true);
+ if (!tcf_idr_check(tn, parm->index, act, bind)) {
+ ret = tcf_idr_create(tn, parm->index, est, act,
+ &act_bpf_ops, bind, true);
if (ret < 0)
return ret;
@@ -307,7 +306,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
if (bind)
return 0;
- tcf_hash_release(*act, bind);
+ tcf_idr_release(*act, bind);
if (!replace)
return -EEXIST;
}
@@ -343,7 +342,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
rcu_assign_pointer(prog->filter, cfg.filter);
if (res == ACT_P_CREATED) {
- tcf_hash_insert(tn, *act);
+ tcf_idr_insert(tn, *act);
} else {
/* make sure the program being replaced is no longer executing */
synchronize_rcu();
@@ -353,7 +352,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
return res;
out:
if (res == ACT_P_CREATED)
- tcf_hash_cleanup(*act, est);
+ tcf_idr_cleanup(*act, est);
return ret;
}
@@ -379,7 +378,7 @@ static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, bpf_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_bpf_ops __read_mostly = {
@@ -399,7 +398,7 @@ static __net_init int bpf_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, bpf_net_id);
- return tc_action_net_init(tn, &act_bpf_ops, BPF_TAB_MASK);
+ return tc_action_net_init(tn, &act_bpf_ops);
}
static void __net_exit bpf_exit_net(struct net *net)
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 2155bc6..10b7a88 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -28,8 +28,6 @@
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_zones.h>
-#define CONNMARK_TAB_MASK 3
-
static unsigned int connmark_net_id;
static struct tc_action_ops act_connmark_ops;
@@ -119,9 +117,9 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
parm = nla_data(tb[TCA_CONNMARK_PARMS]);
- if (!tcf_hash_check(tn, parm->index, a, bind)) {
- ret = tcf_hash_create(tn, parm->index, est, a,
- &act_connmark_ops, bind, false);
+ if (!tcf_idr_check(tn, parm->index, a, bind)) {
+ ret = tcf_idr_create(tn, parm->index, est, a,
+ &act_connmark_ops, bind, false);
if (ret)
return ret;
@@ -130,13 +128,13 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
ci->net = net;
ci->zone = parm->zone;
- tcf_hash_insert(tn, *a);
+ tcf_idr_insert(tn, *a);
ret = ACT_P_CREATED;
} else {
ci = to_connmark(*a);
if (bind)
return 0;
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
/* replacing action and zone */
@@ -189,7 +187,7 @@ static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, connmark_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_connmark_ops = {
@@ -208,7 +206,7 @@ static __net_init int connmark_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, connmark_net_id);
- return tc_action_net_init(tn, &act_connmark_ops, CONNMARK_TAB_MASK);
+ return tc_action_net_init(tn, &act_connmark_ops);
}
static void __net_exit connmark_exit_net(struct net *net)
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 67afc12..1c40caa 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -37,8 +37,6 @@
#include <linux/tc_act/tc_csum.h>
#include <net/tc_act/tc_csum.h>
-#define CSUM_TAB_MASK 15
-
static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = {
[TCA_CSUM_PARMS] = { .len = sizeof(struct tc_csum), },
};
@@ -67,16 +65,16 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
return -EINVAL;
parm = nla_data(tb[TCA_CSUM_PARMS]);
- if (!tcf_hash_check(tn, parm->index, a, bind)) {
- ret = tcf_hash_create(tn, parm->index, est, a,
- &act_csum_ops, bind, false);
+ if (!tcf_idr_check(tn, parm->index, a, bind)) {
+ ret = tcf_idr_create(tn, parm->index, est, a,
+ &act_csum_ops, bind, false);
if (ret)
return ret;
ret = ACT_P_CREATED;
} else {
if (bind)/* dont override defaults */
return 0;
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
}
@@ -88,7 +86,7 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
spin_unlock_bh(&p->tcf_lock);
if (ret == ACT_P_CREATED)
- tcf_hash_insert(tn, *a);
+ tcf_idr_insert(tn, *a);
return ret;
}
@@ -609,7 +607,7 @@ static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, csum_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_csum_ops = {
@@ -628,7 +626,7 @@ static __net_init int csum_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, csum_net_id);
- return tc_action_net_init(tn, &act_csum_ops, CSUM_TAB_MASK);
+ return tc_action_net_init(tn, &act_csum_ops);
}
static void __net_exit csum_exit_net(struct net *net)
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 99afe8b..e29a48e 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -23,8 +23,6 @@
#include <linux/tc_act/tc_gact.h>
#include <net/tc_act/tc_gact.h>
-#define GACT_TAB_MASK 15
-
static unsigned int gact_net_id;
static struct tc_action_ops act_gact_ops;
@@ -92,16 +90,16 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
}
#endif
- if (!tcf_hash_check(tn, parm->index, a, bind)) {
- ret = tcf_hash_create(tn, parm->index, est, a,
- &act_gact_ops, bind, true);
+ if (!tcf_idr_check(tn, parm->index, a, bind)) {
+ ret = tcf_idr_create(tn, parm->index, est, a,
+ &act_gact_ops, bind, true);
if (ret)
return ret;
ret = ACT_P_CREATED;
} else {
if (bind)/* dont override defaults */
return 0;
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
}
@@ -122,7 +120,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
}
#endif
if (ret == ACT_P_CREATED)
- tcf_hash_insert(tn, *a);
+ tcf_idr_insert(tn, *a);
return ret;
}
@@ -214,7 +212,7 @@ static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, gact_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_gact_ops = {
@@ -234,7 +232,7 @@ static __net_init int gact_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, gact_net_id);
- return tc_action_net_init(tn, &act_gact_ops, GACT_TAB_MASK);
+ return tc_action_net_init(tn, &act_gact_ops);
}
static void __net_exit gact_exit_net(struct net *net)
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index c5dec30..770c5d9 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -34,8 +34,6 @@
#include <linux/etherdevice.h>
#include <net/ife.h>
-#define IFE_TAB_MASK 15
-
static unsigned int ife_net_id;
static int max_metacnt = IFE_META_MAX + 1;
static struct tc_action_ops act_ife_ops;
@@ -452,7 +450,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
parm = nla_data(tb[TCA_IFE_PARMS]);
- exists = tcf_hash_check(tn, parm->index, a, bind);
+ exists = tcf_idr_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;
@@ -462,20 +460,20 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
**/
if (!tb[TCA_IFE_TYPE]) {
if (exists)
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
pr_info("You MUST pass etherype for encoding\n");
return -EINVAL;
}
}
if (!exists) {
- ret = tcf_hash_create(tn, parm->index, est, a, &act_ife_ops,
- bind, false);
+ ret = tcf_idr_create(tn, parm->index, est, a, &act_ife_ops,
+ bind, false);
if (ret)
return ret;
ret = ACT_P_CREATED;
} else {
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
}
@@ -518,7 +516,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
if (err) {
metadata_parse_err:
if (exists)
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (ret == ACT_P_CREATED)
_tcf_ife_cleanup(*a, bind);
@@ -552,7 +550,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
spin_unlock_bh(&ife->tcf_lock);
if (ret == ACT_P_CREATED)
- tcf_hash_insert(tn, *a);
+ tcf_idr_insert(tn, *a);
return ret;
}
@@ -811,7 +809,7 @@ static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, ife_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_ife_ops = {
@@ -831,7 +829,7 @@ static __net_init int ife_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, ife_net_id);
- return tc_action_net_init(tn, &act_ife_ops, IFE_TAB_MASK);
+ return tc_action_net_init(tn, &act_ife_ops);
}
static void __net_exit ife_exit_net(struct net *net)
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 5417078..d9e399a 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -28,8 +28,6 @@
#include <linux/netfilter_ipv4/ip_tables.h>
-#define IPT_TAB_MASK 15
-
static unsigned int ipt_net_id;
static struct tc_action_ops act_ipt_ops;
@@ -118,33 +116,33 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
if (tb[TCA_IPT_INDEX] != NULL)
index = nla_get_u32(tb[TCA_IPT_INDEX]);
- exists = tcf_hash_check(tn, index, a, bind);
+ exists = tcf_idr_check(tn, index, a, bind);
if (exists && bind)
return 0;
if (tb[TCA_IPT_HOOK] == NULL || tb[TCA_IPT_TARG] == NULL) {
if (exists)
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
return -EINVAL;
}
td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]);
if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) {
if (exists)
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
return -EINVAL;
}
if (!exists) {
- ret = tcf_hash_create(tn, index, est, a, ops, bind,
- false);
+ ret = tcf_idr_create(tn, index, est, a, ops, bind,
+ false);
if (ret)
return ret;
ret = ACT_P_CREATED;
} else {
if (bind)/* dont override defaults */
return 0;
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
@@ -180,7 +178,7 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
ipt->tcfi_hook = hook;
spin_unlock_bh(&ipt->tcf_lock);
if (ret == ACT_P_CREATED)
- tcf_hash_insert(tn, *a);
+ tcf_idr_insert(tn, *a);
return ret;
err3:
@@ -189,7 +187,7 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
kfree(tname);
err1:
if (ret == ACT_P_CREATED)
- tcf_hash_cleanup(*a, est);
+ tcf_idr_cleanup(*a, est);
return err;
}
@@ -316,7 +314,7 @@ static int tcf_ipt_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, ipt_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_ipt_ops = {
@@ -336,7 +334,7 @@ static __net_init int ipt_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, ipt_net_id);
- return tc_action_net_init(tn, &act_ipt_ops, IPT_TAB_MASK);
+ return tc_action_net_init(tn, &act_ipt_ops);
}
static void __net_exit ipt_exit_net(struct net *net)
@@ -366,7 +364,7 @@ static int tcf_xt_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, xt_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_xt_ops = {
@@ -386,7 +384,7 @@ static __net_init int xt_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, xt_net_id);
- return tc_action_net_init(tn, &act_xt_ops, IPT_TAB_MASK);
+ return tc_action_net_init(tn, &act_xt_ops);
}
static void __net_exit xt_exit_net(struct net *net)
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 1b5549a..416627c 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -28,7 +28,6 @@
#include <linux/tc_act/tc_mirred.h>
#include <net/tc_act/tc_mirred.h>
-#define MIRRED_TAB_MASK 7
static LIST_HEAD(mirred_list);
static DEFINE_SPINLOCK(mirred_list_lock);
@@ -94,7 +93,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
return -EINVAL;
parm = nla_data(tb[TCA_MIRRED_PARMS]);
- exists = tcf_hash_check(tn, parm->index, a, bind);
+ exists = tcf_idr_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;
@@ -106,14 +105,14 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
break;
default:
if (exists)
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
return -EINVAL;
}
if (parm->ifindex) {
dev = __dev_get_by_index(net, parm->ifindex);
if (dev == NULL) {
if (exists)
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
return -ENODEV;
}
mac_header_xmit = dev_is_mac_header_xmit(dev);
@@ -124,13 +123,13 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
if (!exists) {
if (dev == NULL)
return -EINVAL;
- ret = tcf_hash_create(tn, parm->index, est, a,
- &act_mirred_ops, bind, true);
+ ret = tcf_idr_create(tn, parm->index, est, a,
+ &act_mirred_ops, bind, true);
if (ret)
return ret;
ret = ACT_P_CREATED;
} else {
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
}
@@ -152,7 +151,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
spin_lock_bh(&mirred_list_lock);
list_add(&m->tcfm_list, &mirred_list);
spin_unlock_bh(&mirred_list_lock);
- tcf_hash_insert(tn, *a);
+ tcf_idr_insert(tn, *a);
}
return ret;
@@ -283,7 +282,7 @@ static int tcf_mirred_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, mirred_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static int mirred_device_event(struct notifier_block *unused,
@@ -344,7 +343,7 @@ static __net_init int mirred_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, mirred_net_id);
- return tc_action_net_init(tn, &act_mirred_ops, MIRRED_TAB_MASK);
+ return tc_action_net_init(tn, &act_mirred_ops);
}
static void __net_exit mirred_exit_net(struct net *net)
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index 9016ab8..c365d01 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -29,8 +29,6 @@
#include <net/udp.h>
-#define NAT_TAB_MASK 15
-
static unsigned int nat_net_id;
static struct tc_action_ops act_nat_ops;
@@ -58,16 +56,16 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
return -EINVAL;
parm = nla_data(tb[TCA_NAT_PARMS]);
- if (!tcf_hash_check(tn, parm->index, a, bind)) {
- ret = tcf_hash_create(tn, parm->index, est, a,
- &act_nat_ops, bind, false);
+ if (!tcf_idr_check(tn, parm->index, a, bind)) {
+ ret = tcf_idr_create(tn, parm->index, est, a,
+ &act_nat_ops, bind, false);
if (ret)
return ret;
ret = ACT_P_CREATED;
} else {
if (bind)
return 0;
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
}
@@ -83,7 +81,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
spin_unlock_bh(&p->tcf_lock);
if (ret == ACT_P_CREATED)
- tcf_hash_insert(tn, *a);
+ tcf_idr_insert(tn, *a);
return ret;
}
@@ -290,7 +288,7 @@ static int tcf_nat_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, nat_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_nat_ops = {
@@ -309,7 +307,7 @@ static __net_init int nat_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, nat_net_id);
- return tc_action_net_init(tn, &act_nat_ops, NAT_TAB_MASK);
+ return tc_action_net_init(tn, &act_nat_ops);
}
static void __net_exit nat_exit_net(struct net *net)
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 7dc5892..491fe5de 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -24,8 +24,6 @@
#include <net/tc_act/tc_pedit.h>
#include <uapi/linux/tc_act/tc_pedit.h>
-#define PEDIT_TAB_MASK 15
-
static unsigned int pedit_net_id;
static struct tc_action_ops act_pedit_ops;
@@ -168,17 +166,17 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
if (IS_ERR(keys_ex))
return PTR_ERR(keys_ex);
- if (!tcf_hash_check(tn, parm->index, a, bind)) {
+ if (!tcf_idr_check(tn, parm->index, a, bind)) {
if (!parm->nkeys)
return -EINVAL;
- ret = tcf_hash_create(tn, parm->index, est, a,
- &act_pedit_ops, bind, false);
+ ret = tcf_idr_create(tn, parm->index, est, a,
+ &act_pedit_ops, bind, false);
if (ret)
return ret;
p = to_pedit(*a);
keys = kmalloc(ksize, GFP_KERNEL);
if (keys == NULL) {
- tcf_hash_cleanup(*a, est);
+ tcf_idr_cleanup(*a, est);
kfree(keys_ex);
return -ENOMEM;
}
@@ -186,7 +184,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
} else {
if (bind)
return 0;
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
p = to_pedit(*a);
@@ -214,7 +212,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
spin_unlock_bh(&p->tcf_lock);
if (ret == ACT_P_CREATED)
- tcf_hash_insert(tn, *a);
+ tcf_idr_insert(tn, *a);
return ret;
}
@@ -432,7 +430,7 @@ static int tcf_pedit_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, pedit_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_pedit_ops = {
@@ -452,7 +450,7 @@ static __net_init int pedit_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, pedit_net_id);
- return tc_action_net_init(tn, &act_pedit_ops, PEDIT_TAB_MASK);
+ return tc_action_net_init(tn, &act_pedit_ops);
}
static void __net_exit pedit_exit_net(struct net *net)
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index b062bc8..3bb2ebf 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -40,8 +40,6 @@ struct tcf_police {
#define to_police(pc) ((struct tcf_police *)pc)
-#define POL_TAB_MASK 15
-
/* old policer structure from before tc actions */
struct tc_police_compat {
u32 index;
@@ -101,18 +99,18 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
return -EINVAL;
parm = nla_data(tb[TCA_POLICE_TBF]);
- exists = tcf_hash_check(tn, parm->index, a, bind);
+ exists = tcf_idr_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;
if (!exists) {
- ret = tcf_hash_create(tn, parm->index, NULL, a,
- &act_police_ops, bind, false);
+ ret = tcf_idr_create(tn, parm->index, NULL, a,
+ &act_police_ops, bind, false);
if (ret)
return ret;
ret = ACT_P_CREATED;
} else {
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
}
@@ -188,7 +186,7 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
return ret;
police->tcfp_t_c = ktime_get_ns();
- tcf_hash_insert(tn, *a);
+ tcf_idr_insert(tn, *a);
return ret;
@@ -196,7 +194,7 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
qdisc_put_rtab(P_tab);
qdisc_put_rtab(R_tab);
if (ret == ACT_P_CREATED)
- tcf_hash_cleanup(*a, est);
+ tcf_idr_cleanup(*a, est);
return err;
}
@@ -310,7 +308,7 @@ static int tcf_police_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, police_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
MODULE_AUTHOR("Alexey Kuznetsov");
@@ -333,7 +331,7 @@ static __net_init int police_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, police_net_id);
- return tc_action_net_init(tn, &act_police_ops, POL_TAB_MASK);
+ return tc_action_net_init(tn, &act_police_ops);
}
static void __net_exit police_exit_net(struct net *net)
diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c
index 59d6645..ec986ae 100644
--- a/net/sched/act_sample.c
+++ b/net/sched/act_sample.c
@@ -25,7 +25,6 @@
#include <linux/if_arp.h>
-#define SAMPLE_TAB_MASK 7
static unsigned int sample_net_id;
static struct tc_action_ops act_sample_ops;
@@ -59,18 +58,18 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
parm = nla_data(tb[TCA_SAMPLE_PARMS]);
- exists = tcf_hash_check(tn, parm->index, a, bind);
+ exists = tcf_idr_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;
if (!exists) {
- ret = tcf_hash_create(tn, parm->index, est, a,
- &act_sample_ops, bind, false);
+ ret = tcf_idr_create(tn, parm->index, est, a,
+ &act_sample_ops, bind, false);
if (ret)
return ret;
ret = ACT_P_CREATED;
} else {
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
}
@@ -82,7 +81,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
psample_group = psample_group_get(net, s->psample_group_num);
if (!psample_group) {
if (ret == ACT_P_CREATED)
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
return -ENOMEM;
}
RCU_INIT_POINTER(s->psample_group, psample_group);
@@ -93,7 +92,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
}
if (ret == ACT_P_CREATED)
- tcf_hash_insert(tn, *a);
+ tcf_idr_insert(tn, *a);
return ret;
}
@@ -221,7 +220,7 @@ static int tcf_sample_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, sample_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_sample_ops = {
@@ -241,7 +240,7 @@ static __net_init int sample_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, sample_net_id);
- return tc_action_net_init(tn, &act_sample_ops, SAMPLE_TAB_MASK);
+ return tc_action_net_init(tn, &act_sample_ops);
}
static void __net_exit sample_exit_net(struct net *net)
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 43605e7..e7b57e5 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -24,8 +24,6 @@
#include <linux/tc_act/tc_defact.h>
#include <net/tc_act/tc_defact.h>
-#define SIMP_TAB_MASK 7
-
static unsigned int simp_net_id;
static struct tc_action_ops act_simp_ops;
@@ -102,28 +100,28 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
return -EINVAL;
parm = nla_data(tb[TCA_DEF_PARMS]);
- exists = tcf_hash_check(tn, parm->index, a, bind);
+ exists = tcf_idr_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;
if (tb[TCA_DEF_DATA] == NULL) {
if (exists)
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
return -EINVAL;
}
defdata = nla_data(tb[TCA_DEF_DATA]);
if (!exists) {
- ret = tcf_hash_create(tn, parm->index, est, a,
- &act_simp_ops, bind, false);
+ ret = tcf_idr_create(tn, parm->index, est, a,
+ &act_simp_ops, bind, false);
if (ret)
return ret;
d = to_defact(*a);
ret = alloc_defdata(d, defdata);
if (ret < 0) {
- tcf_hash_cleanup(*a, est);
+ tcf_idr_cleanup(*a, est);
return ret;
}
d->tcf_action = parm->action;
@@ -131,7 +129,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
} else {
d = to_defact(*a);
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
@@ -139,7 +137,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
}
if (ret == ACT_P_CREATED)
- tcf_hash_insert(tn, *a);
+ tcf_idr_insert(tn, *a);
return ret;
}
@@ -183,7 +181,7 @@ static int tcf_simp_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, simp_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_simp_ops = {
@@ -203,7 +201,7 @@ static __net_init int simp_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, simp_net_id);
- return tc_action_net_init(tn, &act_simp_ops, SIMP_TAB_MASK);
+ return tc_action_net_init(tn, &act_simp_ops);
}
static void __net_exit simp_exit_net(struct net *net)
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 6b3e65d..59949d6 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -27,8 +27,6 @@
#include <linux/tc_act/tc_skbedit.h>
#include <net/tc_act/tc_skbedit.h>
-#define SKBEDIT_TAB_MASK 15
-
static unsigned int skbedit_net_id;
static struct tc_action_ops act_skbedit_ops;
@@ -118,18 +116,18 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
- exists = tcf_hash_check(tn, parm->index, a, bind);
+ exists = tcf_idr_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;
if (!flags) {
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
return -EINVAL;
}
if (!exists) {
- ret = tcf_hash_create(tn, parm->index, est, a,
- &act_skbedit_ops, bind, false);
+ ret = tcf_idr_create(tn, parm->index, est, a,
+ &act_skbedit_ops, bind, false);
if (ret)
return ret;
@@ -137,7 +135,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
ret = ACT_P_CREATED;
} else {
d = to_skbedit(*a);
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
}
@@ -163,7 +161,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
spin_unlock_bh(&d->tcf_lock);
if (ret == ACT_P_CREATED)
- tcf_hash_insert(tn, *a);
+ tcf_idr_insert(tn, *a);
return ret;
}
@@ -221,7 +219,7 @@ static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, skbedit_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_skbedit_ops = {
@@ -240,7 +238,7 @@ static __net_init int skbedit_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, skbedit_net_id);
- return tc_action_net_init(tn, &act_skbedit_ops, SKBEDIT_TAB_MASK);
+ return tc_action_net_init(tn, &act_skbedit_ops);
}
static void __net_exit skbedit_exit_net(struct net *net)
diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c
index a73c4bb..b642ad3 100644
--- a/net/sched/act_skbmod.c
+++ b/net/sched/act_skbmod.c
@@ -20,8 +20,6 @@
#include <linux/tc_act/tc_skbmod.h>
#include <net/tc_act/tc_skbmod.h>
-#define SKBMOD_TAB_MASK 15
-
static unsigned int skbmod_net_id;
static struct tc_action_ops act_skbmod_ops;
@@ -129,7 +127,7 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
if (parm->flags & SKBMOD_F_SWAPMAC)
lflags = SKBMOD_F_SWAPMAC;
- exists = tcf_hash_check(tn, parm->index, a, bind);
+ exists = tcf_idr_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;
@@ -137,14 +135,14 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
return -EINVAL;
if (!exists) {
- ret = tcf_hash_create(tn, parm->index, est, a,
- &act_skbmod_ops, bind, true);
+ ret = tcf_idr_create(tn, parm->index, est, a,
+ &act_skbmod_ops, bind, true);
if (ret)
return ret;
ret = ACT_P_CREATED;
} else {
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
}
@@ -155,7 +153,7 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
p = kzalloc(sizeof(struct tcf_skbmod_params), GFP_KERNEL);
if (unlikely(!p)) {
if (ovr)
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
return -ENOMEM;
}
@@ -182,7 +180,7 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
kfree_rcu(p_old, rcu);
if (ret == ACT_P_CREATED)
- tcf_hash_insert(tn, *a);
+ tcf_idr_insert(tn, *a);
return ret;
}
@@ -245,7 +243,7 @@ static int tcf_skbmod_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, skbmod_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_skbmod_ops = {
@@ -265,7 +263,7 @@ static __net_init int skbmod_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, skbmod_net_id);
- return tc_action_net_init(tn, &act_skbmod_ops, SKBMOD_TAB_MASK);
+ return tc_action_net_init(tn, &act_skbmod_ops);
}
static void __net_exit skbmod_exit_net(struct net *net)
diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c
index fd7e756..30c9627 100644
--- a/net/sched/act_tunnel_key.c
+++ b/net/sched/act_tunnel_key.c
@@ -20,8 +20,6 @@
#include <linux/tc_act/tc_tunnel_key.h>
#include <net/tc_act/tc_tunnel_key.h>
-#define TUNNEL_KEY_TAB_MASK 15
-
static unsigned int tunnel_key_net_id;
static struct tc_action_ops act_tunnel_key_ops;
@@ -100,7 +98,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
return -EINVAL;
parm = nla_data(tb[TCA_TUNNEL_KEY_PARMS]);
- exists = tcf_hash_check(tn, parm->index, a, bind);
+ exists = tcf_idr_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;
@@ -159,14 +157,14 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
}
if (!exists) {
- ret = tcf_hash_create(tn, parm->index, est, a,
- &act_tunnel_key_ops, bind, true);
+ ret = tcf_idr_create(tn, parm->index, est, a,
+ &act_tunnel_key_ops, bind, true);
if (ret)
return ret;
ret = ACT_P_CREATED;
} else {
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
}
@@ -177,7 +175,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
params_new = kzalloc(sizeof(*params_new), GFP_KERNEL);
if (unlikely(!params_new)) {
if (ret == ACT_P_CREATED)
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
return -ENOMEM;
}
@@ -193,13 +191,13 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
kfree_rcu(params_old, rcu);
if (ret == ACT_P_CREATED)
- tcf_hash_insert(tn, *a);
+ tcf_idr_insert(tn, *a);
return ret;
err_out:
if (exists)
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
return ret;
}
@@ -304,7 +302,7 @@ static int tunnel_key_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_tunnel_key_ops = {
@@ -324,7 +322,7 @@ static __net_init int tunnel_key_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
- return tc_action_net_init(tn, &act_tunnel_key_ops, TUNNEL_KEY_TAB_MASK);
+ return tc_action_net_init(tn, &act_tunnel_key_ops);
}
static void __net_exit tunnel_key_exit_net(struct net *net)
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index 13ba3a8..16eb067 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -19,8 +19,6 @@
#include <linux/tc_act/tc_vlan.h>
#include <net/tc_act/tc_vlan.h>
-#define VLAN_TAB_MASK 15
-
static unsigned int vlan_net_id;
static struct tc_action_ops act_vlan_ops;
@@ -128,7 +126,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
if (!tb[TCA_VLAN_PARMS])
return -EINVAL;
parm = nla_data(tb[TCA_VLAN_PARMS]);
- exists = tcf_hash_check(tn, parm->index, a, bind);
+ exists = tcf_idr_check(tn, parm->index, a, bind);
if (exists && bind)
return 0;
@@ -139,13 +137,13 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
case TCA_VLAN_ACT_MODIFY:
if (!tb[TCA_VLAN_PUSH_VLAN_ID]) {
if (exists)
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
return -EINVAL;
}
push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
if (push_vid >= VLAN_VID_MASK) {
if (exists)
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
return -ERANGE;
}
@@ -167,20 +165,20 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
break;
default:
if (exists)
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
return -EINVAL;
}
action = parm->v_action;
if (!exists) {
- ret = tcf_hash_create(tn, parm->index, est, a,
- &act_vlan_ops, bind, false);
+ ret = tcf_idr_create(tn, parm->index, est, a,
+ &act_vlan_ops, bind, false);
if (ret)
return ret;
ret = ACT_P_CREATED;
} else {
- tcf_hash_release(*a, bind);
+ tcf_idr_release(*a, bind);
if (!ovr)
return -EEXIST;
}
@@ -199,7 +197,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
spin_unlock_bh(&v->tcf_lock);
if (ret == ACT_P_CREATED)
- tcf_hash_insert(tn, *a);
+ tcf_idr_insert(tn, *a);
return ret;
}
@@ -252,7 +250,7 @@ static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index)
{
struct tc_action_net *tn = net_generic(net, vlan_net_id);
- return tcf_hash_search(tn, a, index);
+ return tcf_idr_search(tn, a, index);
}
static struct tc_action_ops act_vlan_ops = {
@@ -271,7 +269,7 @@ static __net_init int vlan_init_net(struct net *net)
{
struct tc_action_net *tn = net_generic(net, vlan_net_id);
- return tc_action_net_init(tn, &act_vlan_ops, VLAN_TAB_MASK);
+ return tc_action_net_init(tn, &act_vlan_ops);
}
static void __net_exit vlan_exit_net(struct net *net)
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH] DSA support for Micrel KSZ8895
From: Pavel Machek @ 2017-08-28 6:47 UTC (permalink / raw)
To: Florian Fainelli
Cc: Woojung.Huh, nathan.leigh.conrad, vivien.didelot, netdev,
linux-kernel, Tristram.Ha, andrew
In-Reply-To: <0D360298-6B3C-42BA-8E56-9F56E9B29BE4@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2207 bytes --]
Hi!
> >No, tag_ksz part probably is not acceptable. Do you see solution
> >better than just copying it into tag_ksz1 file?
>
> You could have all Micrel tag implementations live under net/dsa/tag_ksz.c and have e.g: DSA_TAG_PROTO_KSZ for the current (newer) switches and DSA_TAG_PROTO_KSZ_LEGACY (or any other name) for the older switches and you would provide two sets of function pointers depending on which protocol is requested by the switch.
>
> Considering the minor difference needed in tagging here, it might be acceptable to actually keep the current functions and just have the xmit() call check what get_tag_protocol returns and use word 1 or 0 based on that. Even though that's a fast path it shouldn't hurt performance too much. If it does, we can always copy the tagging protocol into dsa_slave_priv so you have a fast access to it.
>
Actually I believe I can do optimizer tricks to keep this zero-cost
with clean code, if needed.
> >
> >Any more comments, etc?
>
> The MII emulation bits are interesting, was it not sufficient if you implemented phy_read and phy_write operations that perform the necessary internal PHY accesses or maybe you don't get access to standard MII registers? b53 does such a thing and we merely just need to do a simple shift to access the MII register number, thus avoiding the translation.
>
We don't get standard MII registers over SPI bus.
> >Help would be welcome.
>
> I concur with Andrew, try to get a patch series, even an RFC one together so we can review things individually.
>
> How functional is your driver so far? I'd say the basic stuff to get working: counters (debugging), link management (auto-negotiation, forced, etc.) and basic bridging: all ports separate by default and working port to port switching when brought together in a bridge. VLAN, FDB, MDB, other ethtool goodies can be added later on.
>
Which counters are essential? Link management and basic bridging
should work, not sure if I'll have time to do more than that.
Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply
* Re: [PATCH net-next v2 09/14] net: mvpp2: dynamic reconfiguration of the PHY mode
From: Antoine Tenart @ 2017-08-28 6:52 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: Antoine Tenart, davem, kishon, andrew, jason,
sebastian.hesselbarth, gregory.clement, thomas.petazzoni, nadavh,
linux-kernel, mw, stefanc, miquel.raynal, netdev
In-Reply-To: <20170825224616.GE20805@n2100.armlinux.org.uk>
[-- Attachment #1: Type: text/plain, Size: 915 bytes --]
Hi Russell,
On Fri, Aug 25, 2017 at 11:46:16PM +0100, Russell King - ARM Linux wrote:
> On Fri, Aug 25, 2017 at 04:48:16PM +0200, Antoine Tenart wrote:
> > This patch adds logic to reconfigure the comphy/gop when the link status
> > change at runtime. This is very useful on boards such as the mcbin which
> > have SFP and Ethernet ports connected to the same MAC port: depending on
> > what the user connects the driver will automatically reconfigure the
> > link mode.
>
> This commit commentry needs updating - as I've already pointed out in
> the previous round, the need to reconfigure things has *nothing* to do
> with there being SFP and "Ethernet" ports present. Hence, your commit
> message is entirely misleading.
That's right. I'll update the commit message.
Thanks!
Antoine
--
Antoine Ténart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH net-next v2 05/14] net: mvpp2: do not force the link mode
From: Antoine Tenart @ 2017-08-28 6:55 UTC (permalink / raw)
To: Russell King - ARM Linux
Cc: Antoine Tenart, davem, kishon, andrew, jason,
sebastian.hesselbarth, gregory.clement, thomas.petazzoni, nadavh,
linux-kernel, mw, stefanc, miquel.raynal, netdev
In-Reply-To: <20170825224312.GD20805@n2100.armlinux.org.uk>
[-- Attachment #1: Type: text/plain, Size: 1086 bytes --]
Hi Russell,
On Fri, Aug 25, 2017 at 11:43:13PM +0100, Russell King - ARM Linux wrote:
> On Fri, Aug 25, 2017 at 04:48:12PM +0200, Antoine Tenart wrote:
> > The link mode (speed, duplex) was forced based on what the phylib
> > returns. This should not be the case, and only forced by ethtool
> > functions manually. This patch removes the link mode enforcement from
> > the phylib link_event callback.
>
> So how does RGMII work (which has no in-band signalling between the PHY
> and MAC)?
>
> phylib expects the network driver to configure it according to the PHY
> state at link_event time - I think you need to explain more why you
> think that this is not necessary.
Good catch, this won't work properly with RGMII. This could be done
out-of-band according to the spec, but that would use PHY polling and we
do not want that (the same concern was raised by Andrew on another
patch).
I'll keep this mode enforcement for RGMII then.
Thanks!
Antoine
--
Antoine Ténart, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH] DSA support for Micrel KSZ8895
From: Pavel Machek @ 2017-08-28 7:02 UTC (permalink / raw)
To: Andrew Lunn
Cc: Woojung.Huh, nathan.leigh.conrad, vivien.didelot, f.fainelli,
netdev, linux-kernel, Tristram.Ha
In-Reply-To: <20170827163122.GG13622@lunn.ch>
[-- Attachment #1: Type: text/plain, Size: 1784 bytes --]
Hi!
Thanks for review.
> > + case PHY_REG_STATUS:
> > + ksz_pread8(sw, p, P_LINK_STATUS, &link);
> > + ksz_pread8(sw, p, P_SPEED_STATUS, &speed);
> > + data = PHY_100BTX_FD_CAPABLE |
> > + PHY_100BTX_CAPABLE |
> > + PHY_10BT_FD_CAPABLE |
> > + PHY_10BT_CAPABLE |
> > + PHY_AUTO_NEG_CAPABLE;
> > + if (link & PORT_AUTO_NEG_COMPLETE)
> > + data |= PHY_AUTO_NEG_ACKNOWLEDGE;
> > + if (link & PORT_STAT_LINK_GOOD)
> > + data |= PHY_LINK_STATUS;
> > + break;
> > + case PHY_REG_ID_1:
> > + data = KSZ8895_ID_HI;
> > + break;
> > + case PHY_REG_ID_2:
> > + data = KSZ8895_ID_LO;
> > + break;
>
> According to the datasheet, the PHY has the normal ID registers,
> which have the value 0x0022, 0x1450. So it should be possible to have
> a standard PHY driver in drivers/net/phy.
>
> In fact, the IDs suggest it is a micrel phy, and 1430, 1435 are
> already supported. So it could be you only need minor modifications to
> the micrel.c.
I may be confused here, but AFAICT:
1) Yes, it has standard layout when accessed over MDIO. But then
there's no access to the bridging functionality, and MDIO access may
not be available. [I was told not to use it for this design, so I did
not].
2) drivers/net/phy/spi_ks8995.c can be trivially modified to work with
this chip.. but then you don't get the bridge functionality. (And I'm
not sure how it works / who translates layouts in this case.)
I'd like to get rid of this code, or use some existing code instead,
but I don't think it is possible while keeping the SPI accesss. Let me
know if I'm wrong.
Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
^ permalink raw reply
* Re: connector: Delete an error message for a failed memory allocation in cn_queue_alloc_callback_entry()
From: SF Markus Elfring @ 2017-08-28 7:09 UTC (permalink / raw)
To: Peter Waskiewicz Jr, netdev@vger.kernel.org
Cc: Evgeniy Polyakov, LKML, kernel-janitors
In-Reply-To: <E0D909EE5BB15A4699798539EA149D7F0779689E@ORSMSX103.amr.corp.intel.com>
> Did coccinelle trip on the message
I suggest to reconsider this implementation detail with the combination
of a function call like “kzalloc”.
A script for the semantic patch language can point various update candidates
out according to a source code search pattern which is similar to “OOM_MESSAGE”
in the script “checkpatch.pl”.
> or the fact you weren't returning NULL?
How does this concern fit to my update suggestion?
Regards,
Markus
^ permalink raw reply
* RE: Question about ip_defrag
From: liujian (CE) @ 2017-08-28 8:08 UTC (permalink / raw)
To: liujian (CE), Jesper Dangaard Brouer
Cc: davem@davemloft.net, kuznet@ms2.inr.ac.ru,
yoshfuji@linux-ipv6.org, elena.reshetova@intel.com,
edumazet@google.com, netdev@vger.kernel.org, Wangkefeng (Kevin),
weiyongjun (A)
In-Reply-To: <20170824205926.2c45e3a1@redhat.com>
Hi
I checked our 3.10 kernel, we had backported all percpu_counter bug fix in lib/percpu_counter.c and include/linux/percpu_counter.h.
And I check 4.13-rc6, also has the issue if NIC's rx cpu num big enough.
> > > > the issue:
> > > > Ip_defrag fail caused by frag_mem_limit reached 4M(frags.high_thresh).
> > > > At this moment,sum_frag_mem_limit is about 10K.
So should we change ipfrag high/low thresh to a reasonable value ?
And if it is, is there a standard to change the value?
root@RH8100-V3:/proc/net# cat sockstat
sockets: used 1485
TCP: inuse 4 orphan 0 tw 0 alloc 5 mem 1
UDP: inuse 203 mem 201
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 1 memory 16048, 3156696.
root@RH8100-V3:/proc/net#
In order to print frag_mem_limit, change the code as below:
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 43eb6567..38bfb20 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -73,7 +73,7 @@ static int sockstat_seq_show(struct seq_file *seq, void *v)
seq_printf(seq, "RAW: inuse %d\n",
sock_prot_inuse_get(net, &raw_prot));
frag_mem = ip_frag_mem(net);
- seq_printf(seq, "FRAG: inuse %u memory %u\n", !!frag_mem, frag_mem);
+ seq_printf(seq, "FRAG: inuse %u memory %u, %u.\n", !!frag_mem, frag_mem, frag_mem_limit(&net->ipv4.frags));
return 0;
}
Best Regards,
liujian
> -----Original Message-----
> From: liujian (CE)
> Sent: Friday, August 25, 2017 9:33 AM
> To: 'Jesper Dangaard Brouer'
> Cc: davem@davemloft.net; kuznet@ms2.inr.ac.ru; yoshfuji@linux-ipv6.org;
> elena.reshetova@intel.com; edumazet@google.com; netdev@vger.kernel.org;
> Wangkefeng (Kevin); weiyongjun (A)
> Subject: RE: Question about ip_defrag
>
>
> > -----Original Message-----
> > From: Jesper Dangaard Brouer [mailto:brouer@redhat.com]
> > Sent: Friday, August 25, 2017 2:59 AM
> > To: liujian (CE)
> > Cc: davem@davemloft.net; kuznet@ms2.inr.ac.ru;
> > yoshfuji@linux-ipv6.org; elena.reshetova@intel.com;
> > edumazet@google.com; netdev@vger.kernel.org; brouer@redhat.com
> > Subject: Re: Question about ip_defrag
> >
> >
> > On Thu, 24 Aug 2017 16:04:41 +0000 "liujian (CE)"
> > <liujian56@huawei.com>
> > wrote:
> >
> > > >What kernel version have you seen this issue with?
> > >
> > > 3.10,with some backport.
> > >
> > > >As far as I remember, this issue have been fixed before...
> > >
> > > which one patch? I didnot find out the patch:(
> >
> > AFAIK it was some bugs in the percpu_counter code. If you need to
> > backport look at the git commits:
> >
> > git log lib/percpu_counter.c include/linux/percpu_counter.h
> >
> > Are you maintaining your own 3.10 kernel?
> >
> > I know that for RHEL7 (also kernel 3.10) we backported the
> > percpu_counter fixes...
> >
> Could you tell me which one patch? we have backported most of the two
> files's change.
> Thank you ~
>
>
> > --Jesper
> >
> >
> > > 发件人: Jesper Dangaard Brouer
> > > 收件人: liujian
> > (CE)<liujian56@huawei.com<mailto:liujian56@huawei.com>>
> > > 抄送:
> > >
> >
> davem@davemloft.net<mailto:davem@davemloft.net>;kuznet@ms2.inr.ac.ru
> > <m
> > > ailto:kuznet@ms2.inr.ac.ru>;yoshfuji@linux-ipv6.org<mailto:yoshfuji@
> > > li
> > > nux-ipv6.org>;elena.reshetova@intel.com<mailto:elena.reshetova@intel
> > > .c
> > >
> >
> om>;edumazet@google.com<mailto:edumazet@google.com>;netdev@vger.k
> > ernel
> > > .org<mailto:netdev@vger.kernel.org>;brouer@redhat.com<mailto:brouer
> @
> > > r
> > e
> > > dhat.com>
> > > 主题: Re: Question about ip_defrag
> > > 时间: 2017-08-24 21:53:17
> > >
> > >
> > > On Thu, 24 Aug 2017 13:15:33 +0000 "liujian (CE)"
> > > <liujian56@huawei.com>
> > wrote:
> > > > Hello,
> > > >
> > > > With below patch we met one issue.
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
> > > > /c ommit/?h=v4.13-rc6&id=6d7b857d541e
> > > >
> > > > the issue:
> > > > Ip_defrag fail caused by frag_mem_limit reached 4M(frags.high_thresh).
> > > > At this moment,sum_frag_mem_limit is about 10K.
> > > > and my test machine's cpu num is 64.
> > > >
> > > > Can i only change frag_mem_limit to sum_ frag_mem_limit?
> > > >
> > > >
> > > > diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
> > > > index 96e95e8..f09c00b 100644
> > > > --- a/net/ipv4/inet_fragment.c
> > > > +++ b/net/ipv4/inet_fragment.c
> > > > @@ -120,7 +120,7 @@ static void inet_frag_secret_rebuild(struct
> > > > inet_frags *f) static bool inet_fragq_should_evict(const struct
> > > > inet_frag_queue *q) {
> > > > return q->net->low_thresh == 0 ||
> > > > - frag_mem_limit(q->net) >= q->net->low_thresh;
> > > > + sum_frag_mem_limit(q->net) >= q->net->low_thresh;
> > > > }
> > > >
> > > > static unsigned int
> > > > @@ -355,7 +355,7 @@ static struct inet_frag_queue
> > > > *inet_frag_alloc(struct netns_frags *nf, {
> > > > struct inet_frag_queue *q;
> > > >
> > > > - if (!nf->high_thresh || frag_mem_limit(nf) > nf->high_thresh) {
> > > > + if (!nf->high_thresh || sum_frag_mem_limit(nf) >
> > > > + nf->high_thresh) {
> > > > inet_frag_schedule_worker(f);
> > > > return NULL;
> > > > }
> > > > @@ -396,7 +396,7 @@ struct inet_frag_queue *inet_frag_find(struct
> > netns_frags *nf,
> > > > struct inet_frag_queue *q;
> > > > int depth = 0;
> > > >
> > > > - if (frag_mem_limit(nf) > nf->low_thresh)
> > > > + if (sum_frag_mem_limit(nf) > nf->low_thresh)
> > > > inet_frag_schedule_worker(f);
> > > >
> > > > hash &= (INETFRAGS_HASHSZ - 1);
> > > > --
> > > >
> > > > Thank you for your time.
> > >
> > > What kernel version have you seen this issue with?
> > >
> > > As far as I remember, this issue have been fixed before...
> > >
> > > --
> > > Best regards,
> > > Jesper Dangaard Brouer
> > > MSc.CS, Principal Kernel Engineer at Red Hat
> > > LinkedIn: http://www.linkedin.com/in/brouer
> >
> >
> >
> > --
> > Best regards,
> > Jesper Dangaard Brouer
> > MSc.CS, Principal Kernel Engineer at Red Hat
> > LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply related
* Re: [PATCH] net: sunrpc: svcsock: fix NULL-pointer exception
From: Vadim Lomovtsev @ 2017-08-28 8:38 UTC (permalink / raw)
To: J. Bruce Fields
Cc: trond.myklebust, anna.schumaker, jlayton, davem, linux-nfs,
netdev, linux-kernel, pabeni, vlomovts
In-Reply-To: <20170825220128.GA6276@fieldses.org>
On Fri, Aug 25, 2017 at 06:01:28PM -0400, J. Bruce Fields wrote:
> On Fri, Aug 18, 2017 at 06:00:47AM -0400, Vadim Lomovtsev wrote:
> > While running nfs/connectathon tests kernel NULL-pointer exception
> > has been observed due to races in svcsock.c.
> >
> > Race is appear when kernel accepts connection by kernel_accept
> > (which creates new socket) and start queuing ingress packets
> > to new socket. This happanes in ksoftirq context which concurrently
> > on a differnt core while new socket setup is not done yet.
> >
> > The fix is to re-order socket user data init sequence, add NULL-ptr
> > check before callback call along with barriers to prevent kernel crash.
> >
> > Test results: nfs/connectathon reports '0' failed tests for about 200+ iterations.
>
> By the way, is there anything special about your setup that allows you
> to reproduce this? There's nothing special about connectathon tests, so
> I'm just wondering why we haven't had a lot of reports of this.
>From what I have now - nothing special in test setup and/or configuration.
I believe it is because or high amount of CPU running. It was found at 32
cores CPU, while simply invoking test by "make run" command.
WBR,
Vadim
>
> --b.
>
> >
> > Crash log:
> > ---<-snip->---
> > [ 6708.638984] Unable to handle kernel NULL pointer dereference at virtual address 00000000
> > [ 6708.647093] pgd = ffff0000094e0000
> > [ 6708.650497] [00000000] *pgd=0000010ffff90003, *pud=0000010ffff90003, *pmd=0000010ffff80003, *pte=0000000000000000
> > [ 6708.660761] Internal error: Oops: 86000005 [#1] SMP
> > [ 6708.665630] Modules linked in: nfsv3 nfnetlink_queue nfnetlink_log nfnetlink rpcsec_gss_krb5 nfsv4 dns_resolver nfs fscache overlay xt_CONNSECMARK xt_SECMARK xt_conntrack iptable_security ip_tables ah4 xfrm4_mode_transport sctp tun binfmt_misc ext4 jbd2 mbcache loop tcp_diag udp_diag inet_diag rpcrdma ib_isert iscsi_target_mod ib_iser rdma_cm iw_cm libiscsi scsi_transport_iscsi ib_srpt target_core_mod ib_srp scsi_transport_srp ib_ipoib ib_ucm ib_uverbs ib_umad ib_cm ib_core nls_koi8_u nls_cp932 ts_kmp nf_conntrack_ipv4 nf_defrag_ipv4 nf_conntrack vfat fat ghash_ce sha2_ce sha1_ce cavium_rng_vf i2c_thunderx sg thunderx_edac i2c_smbus edac_core cavium_rng nfsd auth_rpcgss nfs_acl lockd grace sunrpc xfs libcrc32c nicvf nicpf ast i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysim
gblt fb_sys_fops
> > [ 6708.736446] ttm drm i2c_core thunder_bgx thunder_xcv mdio_thunder mdio_cavium dm_mirror dm_region_hash dm_log dm_mod [last unloaded: stap_3c300909c5b3f46dcacd49aab3334af_87021]
> > [ 6708.752275] CPU: 84 PID: 0 Comm: swapper/84 Tainted: G W OE 4.11.0-4.el7.aarch64 #1
> > [ 6708.760787] Hardware name: www.cavium.com CRB-2S/CRB-2S, BIOS 0.3 Mar 13 2017
> > [ 6708.767910] task: ffff810006842e80 task.stack: ffff81000689c000
> > [ 6708.773822] PC is at 0x0
> > [ 6708.776739] LR is at svc_data_ready+0x38/0x88 [sunrpc]
> > [ 6708.781866] pc : [<0000000000000000>] lr : [<ffff0000029d7378>] pstate: 60000145
> > [ 6708.789248] sp : ffff810ffbad3900
> > [ 6708.792551] x29: ffff810ffbad3900 x28: ffff000008c73d58
> > [ 6708.797853] x27: 0000000000000000 x26: ffff81000bbe1e00
> > [ 6708.803156] x25: 0000000000000020 x24: ffff800f7410bf28
> > [ 6708.808458] x23: ffff000008c63000 x22: ffff000008c63000
> > [ 6708.813760] x21: ffff800f7410bf28 x20: ffff81000bbe1e00
> > [ 6708.819063] x19: ffff810012412400 x18: 00000000d82a9df2
> > [ 6708.824365] x17: 0000000000000000 x16: 0000000000000000
> > [ 6708.829667] x15: 0000000000000000 x14: 0000000000000001
> > [ 6708.834969] x13: 0000000000000000 x12: 722e736f622e676e
> > [ 6708.840271] x11: 00000000f814dd99 x10: 0000000000000000
> > [ 6708.845573] x9 : 7374687225000000 x8 : 0000000000000000
> > [ 6708.850875] x7 : 0000000000000000 x6 : 0000000000000000
> > [ 6708.856177] x5 : 0000000000000028 x4 : 0000000000000000
> > [ 6708.861479] x3 : 0000000000000000 x2 : 00000000e5000000
> > [ 6708.866781] x1 : 0000000000000000 x0 : ffff81000bbe1e00
> > [ 6708.872084]
> > [ 6708.873565] Process swapper/84 (pid: 0, stack limit = 0xffff81000689c000)
> > [ 6708.880341] Stack: (0xffff810ffbad3900 to 0xffff8100068a0000)
> > [ 6708.886075] Call trace:
> > [ 6708.888513] Exception stack(0xffff810ffbad3710 to 0xffff810ffbad3840)
> > [ 6708.894942] 3700: ffff810012412400 0001000000000000
> > [ 6708.902759] 3720: ffff810ffbad3900 0000000000000000 0000000060000145 ffff800f79300000
> > [ 6708.910577] 3740: ffff000009274d00 00000000000003ea 0000000000000015 ffff000008c63000
> > [ 6708.918395] 3760: ffff810ffbad3830 ffff800f79300000 000000000000004d 0000000000000000
> > [ 6708.926212] 3780: ffff810ffbad3890 ffff0000080f88dc ffff800f79300000 000000000000004d
> > [ 6708.934030] 37a0: ffff800f7930093c ffff000008c63000 0000000000000000 0000000000000140
> > [ 6708.941848] 37c0: ffff000008c2c000 0000000000040b00 ffff81000bbe1e00 0000000000000000
> > [ 6708.949665] 37e0: 00000000e5000000 0000000000000000 0000000000000000 0000000000000028
> > [ 6708.957483] 3800: 0000000000000000 0000000000000000 0000000000000000 7374687225000000
> > [ 6708.965300] 3820: 0000000000000000 00000000f814dd99 722e736f622e676e 0000000000000000
> > [ 6708.973117] [< (null)>] (null)
> > [ 6708.977824] [<ffff0000086f9fa4>] tcp_data_queue+0x754/0xc5c
> > [ 6708.983386] [<ffff0000086fa64c>] tcp_rcv_established+0x1a0/0x67c
> > [ 6708.989384] [<ffff000008704120>] tcp_v4_do_rcv+0x15c/0x22c
> > [ 6708.994858] [<ffff000008707418>] tcp_v4_rcv+0xaf0/0xb58
> > [ 6709.000077] [<ffff0000086df784>] ip_local_deliver_finish+0x10c/0x254
> > [ 6709.006419] [<ffff0000086dfea4>] ip_local_deliver+0xf0/0xfc
> > [ 6709.011980] [<ffff0000086dfad4>] ip_rcv_finish+0x208/0x3a4
> > [ 6709.017454] [<ffff0000086e018c>] ip_rcv+0x2dc/0x3c8
> > [ 6709.022328] [<ffff000008692fc8>] __netif_receive_skb_core+0x2f8/0xa0c
> > [ 6709.028758] [<ffff000008696068>] __netif_receive_skb+0x38/0x84
> > [ 6709.034580] [<ffff00000869611c>] netif_receive_skb_internal+0x68/0xdc
> > [ 6709.041010] [<ffff000008696bc0>] napi_gro_receive+0xcc/0x1a8
> > [ 6709.046690] [<ffff0000014b0fc4>] nicvf_cq_intr_handler+0x59c/0x730 [nicvf]
> > [ 6709.053559] [<ffff0000014b1380>] nicvf_poll+0x38/0xb8 [nicvf]
> > [ 6709.059295] [<ffff000008697a6c>] net_rx_action+0x2f8/0x464
> > [ 6709.064771] [<ffff000008081824>] __do_softirq+0x11c/0x308
> > [ 6709.070164] [<ffff0000080d14e4>] irq_exit+0x12c/0x174
> > [ 6709.075206] [<ffff00000813101c>] __handle_domain_irq+0x78/0xc4
> > [ 6709.081027] [<ffff000008081608>] gic_handle_irq+0x94/0x190
> > [ 6709.086501] Exception stack(0xffff81000689fdf0 to 0xffff81000689ff20)
> > [ 6709.092929] fde0: 0000810ff2ec0000 ffff000008c10000
> > [ 6709.100747] fe00: ffff000008c70ef4 0000000000000001 0000000000000000 ffff810ffbad9b18
> > [ 6709.108565] fe20: ffff810ffbad9c70 ffff8100169d3800 ffff810006843ab0 ffff81000689fe80
> > [ 6709.116382] fe40: 0000000000000bd0 0000ffffdf979cd0 183f5913da192500 0000ffff8a254ce4
> > [ 6709.124200] fe60: 0000ffff8a254b78 0000aaab10339808 0000000000000000 0000ffff8a0c2a50
> > [ 6709.132018] fe80: 0000ffffdf979b10 ffff000008d6d450 ffff000008c10000 ffff000008d6d000
> > [ 6709.139836] fea0: 0000000000000054 ffff000008cd3dbc 0000000000000000 0000000000000000
> > [ 6709.147653] fec0: 0000000000000000 0000000000000000 0000000000000000 ffff81000689ff20
> > [ 6709.155471] fee0: ffff000008085240 ffff81000689ff20 ffff000008085244 0000000060000145
> > [ 6709.163289] ff00: ffff81000689ff10 ffff00000813f1e4 ffffffffffffffff ffff00000813f238
> > [ 6709.171107] [<ffff000008082eb4>] el1_irq+0xb4/0x140
> > [ 6709.175976] [<ffff000008085244>] arch_cpu_idle+0x44/0x11c
> > [ 6709.181368] [<ffff0000087bf3b8>] default_idle_call+0x20/0x30
> > [ 6709.187020] [<ffff000008116d50>] do_idle+0x158/0x1e4
> > [ 6709.191973] [<ffff000008116ff4>] cpu_startup_entry+0x2c/0x30
> > [ 6709.197624] [<ffff00000808e7cc>] secondary_start_kernel+0x13c/0x160
> > [ 6709.203878] [<0000000001bc71c4>] 0x1bc71c4
> > [ 6709.207967] Code: bad PC value
> > [ 6709.211061] SMP: stopping secondary CPUs
> > [ 6709.218830] Starting crashdump kernel...
> > [ 6709.222749] Bye!
> > ---<-snip>---
> >
> > Signed-off-by: Vadim Lomovtsev <vlomovts@redhat.com>
> > ---
> > net/sunrpc/svcsock.c | 24 ++++++++++++++++++------
> > 1 file changed, 18 insertions(+), 6 deletions(-)
> >
> > diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
> > index 2b720fa..b6496f3 100644
> > --- a/net/sunrpc/svcsock.c
> > +++ b/net/sunrpc/svcsock.c
> > @@ -421,7 +421,9 @@ static void svc_data_ready(struct sock *sk)
> > dprintk("svc: socket %p(inet %p), busy=%d\n",
> > svsk, sk,
> > test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags));
> > - svsk->sk_odata(sk);
> > + rmb();
> > + if (svsk->sk_odata)
> > + svsk->sk_odata(sk);
> > if (!test_and_set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags))
> > svc_xprt_enqueue(&svsk->sk_xprt);
> > }
> > @@ -437,7 +439,9 @@ static void svc_write_space(struct sock *sk)
> > if (svsk) {
> > dprintk("svc: socket %p(inet %p), write_space busy=%d\n",
> > svsk, sk, test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags));
> > - svsk->sk_owspace(sk);
> > + rmb();
> > + if (svsk->sk_owspace)
> > + svsk->sk_owspace(sk);
> > svc_xprt_enqueue(&svsk->sk_xprt);
> > }
> > }
> > @@ -760,8 +764,12 @@ static void svc_tcp_listen_data_ready(struct sock *sk)
> > dprintk("svc: socket %p TCP (listen) state change %d\n",
> > sk, sk->sk_state);
> >
> > - if (svsk)
> > - svsk->sk_odata(sk);
> > + if (svsk) {
> > + rmb();
> > + if (svsk->sk_odata)
> > + svsk->sk_odata(sk);
> > + }
> > +
> > /*
> > * This callback may called twice when a new connection
> > * is established as a child socket inherits everything
> > @@ -794,7 +802,10 @@ static void svc_tcp_state_change(struct sock *sk)
> > if (!svsk)
> > printk("svc: socket %p: no user data\n", sk);
> > else {
> > - svsk->sk_ostate(sk);
> > + rmb();
> > + if (svsk->sk_ostate)
> > + svsk->sk_ostate(sk);
> > +
> > if (sk->sk_state != TCP_ESTABLISHED) {
> > set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
> > svc_xprt_enqueue(&svsk->sk_xprt);
> > @@ -1381,12 +1392,13 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
> > return ERR_PTR(err);
> > }
> >
> > - inet->sk_user_data = svsk;
> > svsk->sk_sock = sock;
> > svsk->sk_sk = inet;
> > svsk->sk_ostate = inet->sk_state_change;
> > svsk->sk_odata = inet->sk_data_ready;
> > svsk->sk_owspace = inet->sk_write_space;
> > + wmb();
> > + inet->sk_user_data = svsk;
> >
> > /* Initialize the socket */
> > if (sock->type == SOCK_DGRAM)
> > --
> > 1.8.3.1
^ permalink raw reply
* Re: [PATCH net-next v2 05/14] net: mvpp2: do not force the link mode
From: Marcin Wojtas @ 2017-08-28 8:38 UTC (permalink / raw)
To: Antoine Tenart
Cc: Russell King - ARM Linux, David S. Miller, kishon, Andrew Lunn,
Jason Cooper, Sebastian Hesselbarth, Gregory Clément,
Thomas Petazzoni, nadavh, linux-kernel, Stefan Chulski,
Miquèl Raynal, netdev
In-Reply-To: <20170828065545.GC2568@kwain>
Hi Antoine,
2017-08-28 8:55 GMT+02:00 Antoine Tenart <antoine.tenart@free-electrons.com>:
> Hi Russell,
>
> On Fri, Aug 25, 2017 at 11:43:13PM +0100, Russell King - ARM Linux wrote:
>> On Fri, Aug 25, 2017 at 04:48:12PM +0200, Antoine Tenart wrote:
>> > The link mode (speed, duplex) was forced based on what the phylib
>> > returns. This should not be the case, and only forced by ethtool
>> > functions manually. This patch removes the link mode enforcement from
>> > the phylib link_event callback.
>>
>> So how does RGMII work (which has no in-band signalling between the PHY
>> and MAC)?
>>
>> phylib expects the network driver to configure it according to the PHY
>> state at link_event time - I think you need to explain more why you
>> think that this is not necessary.
>
> Good catch, this won't work properly with RGMII. This could be done
> out-of-band according to the spec, but that would use PHY polling and we
> do not want that (the same concern was raised by Andrew on another
> patch).
>
> I'll keep this mode enforcement for RGMII then.
>
Can you be 100% sure that when using SGMII with PHY's (like Marvell
Alaska 88E1xxx series), is in-band link information always available?
I'd be very cautious with such assumption and use in-band management
only when set in the DT, like mvneta. I think phylib can properly can
do its work when MDIO connection is provided on the board.
Did you check the change also on A375?
Best regards,
Marcin
^ permalink raw reply
* Re: [PATCH] NFC: fix device-allocation error return
From: Johan Hovold @ 2017-08-28 8:39 UTC (permalink / raw)
To: Samuel Ortiz, David S. Miller
Cc: linux-wireless, netdev, Dan Carpenter, Johan Hovold, stable,
Greg Kroah-Hartman, linux-kernel, Andrew Morton, Ben Hutchings
In-Reply-To: <20170722133228.GE2729@localhost>
Samuel or David,
On Sat, Jul 22, 2017 at 03:32:28PM +0200, Johan Hovold wrote:
> On Sun, Jul 09, 2017 at 01:08:58PM +0200, Johan Hovold wrote:
> > A recent change fixing NFC device allocation itself introduced an
> > error-handling bug by returning an error pointer in case device-id
> > allocation failed. This is clearly broken as the callers still expected
> > NULL to be returned on errors as detected by Dan's static checker.
> >
> > Fix this up by returning NULL in the event that we've run out of memory
> > when allocating a new device id.
> >
> > Note that the offending commit is marked for stable (3.8) so this fix
> > needs to be backported along with it.
> >
> > Fixes: 20777bc57c34 ("NFC: fix broken device allocation")
> > Cc: stable <stable@vger.kernel.org> # 3.8
> > Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
> > Signed-off-by: Johan Hovold <johan@kernel.org>
> Could you apply this follow-up fix so that it can be backported along
> with the offending commit (which was just added to the stable queues)?
>
> We would only hit this error path if an ida allocation fails due to OOM;
> so while this is not critical, it would still be nice to get it fixed.
Another reminder about this one; can you apply it so we can get it into
4.14-rc1?
Note that the offending commit has now been backported to the stable
trees and we really want this trivial follow-up fix to be backported as
well.
Let me know if you want me to resend the patch.
Thanks,
Johan
^ permalink raw reply
* PTP: PHY timestamping when MAC is PTP capable
From: Sørensen, Stefan @ 2017-08-28 8:39 UTC (permalink / raw)
To: netdev@vger.kernel.org, richardcochran@gmail.com
Hi,
I have run into a problem with packet timestamping on a platform (cpsw
+ dp83640) where both the PHY and the MAC is PTP capable and I need
the PHY to perform the timestamping. In the current code,
SIOCGHWTSTAMP is passed to the MAC driver and only if it does not
support PTP itself will it pass it on to the PHY driver.
I see two ways to fix this:
1. Prefer PHY timestamping by passing SIOCGHWTSTAMP to the PHY
driver first, and only if it does not support PTP, pass is on to
the MAC driver. To me this seems reasonable as PHY timestamps
will usually be of better quality, and with a hardware design
using a PTP capable PHY you will most likely want to utilize
it. Note that the ethtool get_ts_info op takes this route and as
such may currently return incorrect info when both MAC and PHY is
PTP capable.
2. Let the user decide, by e.g. a new ethtool op.
For now I am using the patch below, but it does not seem quite right
to me.
Any suggestions on the best way forward?
Regards,
Stefan
---
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index 709a4e6fb447..52f4d2dfad11 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -4,6 +4,7 @@
#include <linux/rtnetlink.h>
#include <linux/net_tstamp.h>
#include <linux/wireless.h>
+#include <linux/phy.h>
#include <net/wext.h>
/*
@@ -316,6 +317,14 @@ static int dev_ifsioc(struct net *net, struct
ifreq *ifr, unsigned int cmd)
return err;
/* fall through */
+ case SIOCGHWTSTAMP:
+ if (dev->phydev) {
+ err = phy_mii_ioctl(dev->phydev, ifr, cmd);
+ if (err != -EOPNOTSUPP)
+ return err;
+ }
+ /* fall through */
+
/*
* Unknown or private ioctl
*/
^ permalink raw reply related
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