* Re: [PATCH iproute2] ss: report SK_MEMINFO_BACKLOG
From: Eric Dumazet @ 2012-07-27 17:11 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: Vijay Subramanian, netdev
In-Reply-To: <20120727100806.360764f5@nehalam.linuxnetplumber.net>
On Fri, 2012-07-27 at 10:08 -0700, Stephen Hemminger wrote:
> I am holding this until after 3.5 iproute2 is released.
>
> Still want to get a couple more features in 3.5 iproute2, the work Pavel is
> doing on save/restore cleanup, and the bridge fdb stuff.
>
By the way, it seems "ss -u" still uses /proc/net/udp , and not
inet_diag ?
^ permalink raw reply
* Re: [PATCH iproute2] ss: report SK_MEMINFO_BACKLOG
From: Stephen Hemminger @ 2012-07-27 17:08 UTC (permalink / raw)
To: Vijay Subramanian; +Cc: Eric Dumazet, netdev
In-Reply-To: <CAGK4HS-fUp2ZiW9F_ZogOXQo5_2ptcBHT9Y2j25ZaoXrYKnbAQ@mail.gmail.com>
I am holding this until after 3.5 iproute2 is released.
Still want to get a couple more features in 3.5 iproute2, the work Pavel is
doing on save/restore cleanup, and the bridge fdb stuff.
^ permalink raw reply
* Re: [PATCH 2/2] iproute: Add route showdump command (v2)
From: Stephen Hemminger @ 2012-07-27 17:05 UTC (permalink / raw)
To: Pavel Emelyanov; +Cc: Stephen Hemminger, Linux Netdev List
In-Reply-To: <50122FD7.2060701@parallels.com>
On Fri, 27 Jul 2012 10:06:15 +0400
Pavel Emelyanov <xemul@parallels.com> wrote:
> I mean something like the below, just put the RTM_GETADDR stream into a
> file and push it back into the kernel as is. It worked for me in trivial
> cases, but is this approach correct generically?
It is supposed to always work to reverse netlink messages back to the kernel.
There a couple of caveats:
1. Some fields like statistics are just ignored by the kernel and can never
be reset.
2. The feature isn't commonly used and it is always possible that it will
expose a kernel bug.
^ permalink raw reply
* Re: [PATCH 1/2] iproute: Add magic cookie to route dump file
From: Stephen Hemminger @ 2012-07-27 16:59 UTC (permalink / raw)
To: Pavel Emelyanov; +Cc: Stephen Hemminger, Linux Netdev List
In-Reply-To: <50121F4D.8090606@parallels.com>
On Fri, 27 Jul 2012 08:55:41 +0400
Pavel Emelyanov <xemul@parallels.com> wrote:
> In order to somehow verify that a blob contains route dump a
> 4-bytes magic is put at the head of the data and is checked
> on restore.
>
> Magic digits are taken from Portland (OR) coordinates :) Is
> there any more reliable way of generating such?
>
> Signed-of-by: Pavel Emelyanov <xemul@parallels.com>
>
Any magic number is fine as long as it is non-offensive and
unique.
^ permalink raw reply
* Re: [PATCH iproute2 v2 0/3] CAN Filter/Classifier
From: Oliver Hartkopp @ 2012-07-27 16:35 UTC (permalink / raw)
To: Rostislav Lisovy
Cc: Marc Kleine-Budde, netdev, linux-can, lartc, pisa, sojkam1
In-Reply-To: <1343398165.12164.3.camel@lolumad>
On 27.07.2012 16:09, Rostislav Lisovy wrote:
> On Fri, 2012-07-27 at 15:56 +0200, Oliver Hartkopp wrote:
>> On 27.07.2012 12:02, Marc Kleine-Budde wrote:
>>
>>> I'm reposting Rostislav's iproute2 patches, as Stephen requested,
>>> during the v3.6 merge window with the corresponding kernel patches
>>> already applied.
>>
>>
>
>> Btw. i think these patches address the original implementation from Rostislav
>> using the CAN classifier. The review lead to a completely new implementation
>> using ematch. Therefore this patch series is outdated AFAICS.
>>
>> @Rostislav: Am i correct here?
>
> Hello Oliver;
> You are right -- these are the patches for the old "standalone can
> filter/classifier" implementation.
> I will send correct patches hopefully on Monday/Tuesday.
>
No hurry.
I will not have the time next week to check out and test your patches.
But i would like to do so :-)
We have all the time until Linux 3.6 is released somewhere in October.
So getting these things done in August is a good target.
Tnx & best regards,
Oliver
^ permalink raw reply
* [patch net-next 4/4] team: add support for queue override by setting queue_id for port
From: Jiri Pirko @ 2012-07-27 16:28 UTC (permalink / raw)
To: netdev; +Cc: davem, edumazet
In-Reply-To: <1343406535-22388-1-git-send-email-jiri@resnulli.us>
Similar to what bonding has. This allows to set queue_id for port so
this port will be used when skb with matching skb->queue_mapping is
going to be transmitted.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
drivers/net/team/team.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++-
include/linux/if_team.h | 4 ++
2 files changed, 165 insertions(+), 2 deletions(-)
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index a30b7c1..ba10c46 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -658,6 +658,122 @@ static rx_handler_result_t team_handle_frame(struct sk_buff **pskb)
}
+/*************************************
+ * Multiqueue Tx port select override
+ *************************************/
+
+static int team_queue_override_init(struct team *team)
+{
+ struct list_head *listarr;
+ unsigned int queue_cnt = team->dev->num_tx_queues - 1;
+ unsigned int i;
+
+ if (!queue_cnt)
+ return 0;
+ listarr = kmalloc(sizeof(struct list_head) * queue_cnt, GFP_KERNEL);
+ if (!listarr)
+ return -ENOMEM;
+ team->qom_lists = listarr;
+ for (i = 0; i < queue_cnt; i++)
+ INIT_LIST_HEAD(listarr++);
+ return 0;
+}
+
+static void team_queue_override_fini(struct team *team)
+{
+ kfree(team->qom_lists);
+}
+
+static struct list_head *__team_get_qom_list(struct team *team, u16 queue_id)
+{
+ return &team->qom_lists[queue_id - 1];
+}
+
+/*
+ * note: already called with rcu_read_lock
+ */
+static bool team_queue_override_transmit(struct team *team, struct sk_buff *skb)
+{
+ struct list_head *qom_list;
+ struct team_port *port;
+
+ if (!team->queue_override_enabled || !skb->queue_mapping)
+ return false;
+ qom_list = __team_get_qom_list(team, skb->queue_mapping);
+ list_for_each_entry_rcu(port, qom_list, qom_list) {
+ if (!team_dev_queue_xmit(team, port, skb))
+ return true;
+ }
+ return false;
+}
+
+static void __team_queue_override_port_del(struct team *team,
+ struct team_port *port)
+{
+ list_del_rcu(&port->qom_list);
+ synchronize_rcu();
+ INIT_LIST_HEAD(&port->qom_list);
+}
+
+static bool team_queue_override_port_has_gt_prio_than(struct team_port *port,
+ struct team_port *cur)
+{
+ if (port->priority < cur->priority)
+ return true;
+ if (port->priority > cur->priority)
+ return false;
+ if (port->index < cur->index)
+ return true;
+ return false;
+}
+
+static void __team_queue_override_port_add(struct team *team,
+ struct team_port *port)
+{
+ struct team_port *cur;
+ struct list_head *qom_list;
+ struct list_head *node;
+
+ if (!port->queue_id || !team_port_enabled(port))
+ return;
+
+ qom_list = __team_get_qom_list(team, port->queue_id);
+ node = qom_list;
+ list_for_each_entry(cur, qom_list, qom_list) {
+ if (team_queue_override_port_has_gt_prio_than(port, cur))
+ break;
+ node = &cur->qom_list;
+ }
+ list_add_tail_rcu(&port->qom_list, node);
+}
+
+static void __team_queue_override_enabled_check(struct team *team)
+{
+ struct team_port *port;
+ bool enabled = false;
+
+ list_for_each_entry(port, &team->port_list, list) {
+ if (!list_empty(&port->qom_list)) {
+ enabled = true;
+ break;
+ }
+ }
+ if (enabled == team->queue_override_enabled)
+ return;
+ netdev_dbg(team->dev, "%s queue override\n",
+ enabled ? "Enabling" : "Disabling");
+ team->queue_override_enabled = enabled;
+}
+
+static void team_queue_override_port_refresh(struct team *team,
+ struct team_port *port)
+{
+ __team_queue_override_port_del(team, port);
+ __team_queue_override_port_add(team, port);
+ __team_queue_override_enabled_check(team);
+}
+
+
/****************
* Port handling
****************/
@@ -688,6 +804,7 @@ static void team_port_enable(struct team *team,
hlist_add_head_rcu(&port->hlist,
team_port_index_hash(team, port->index));
team_adjust_ops(team);
+ team_queue_override_port_refresh(team, port);
if (team->ops.port_enabled)
team->ops.port_enabled(team, port);
}
@@ -716,6 +833,7 @@ static void team_port_disable(struct team *team,
hlist_del_rcu(&port->hlist);
__reconstruct_port_hlist(team, port->index);
port->index = -1;
+ team_queue_override_port_refresh(team, port);
__team_adjust_ops(team, team->en_port_count - 1);
/*
* Wait until readers see adjusted ops. This ensures that
@@ -881,6 +999,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev)
port->dev = port_dev;
port->team = team;
+ INIT_LIST_HEAD(&port->qom_list);
port->orig.mtu = port_dev->mtu;
err = dev_set_mtu(port_dev, dev->mtu);
@@ -1107,9 +1226,34 @@ static int team_priority_option_set(struct team *team,
struct team_port *port = ctx->info->port;
port->priority = ctx->data.s32_val;
+ team_queue_override_port_refresh(team, port);
return 0;
}
+static int team_queue_id_option_get(struct team *team,
+ struct team_gsetter_ctx *ctx)
+{
+ struct team_port *port = ctx->info->port;
+
+ ctx->data.u32_val = port->queue_id;
+ return 0;
+}
+
+static int team_queue_id_option_set(struct team *team,
+ struct team_gsetter_ctx *ctx)
+{
+ struct team_port *port = ctx->info->port;
+
+ if (port->queue_id == ctx->data.u32_val)
+ return 0;
+ if (ctx->data.u32_val >= team->dev->real_num_tx_queues)
+ return -EINVAL;
+ port->queue_id = ctx->data.u32_val;
+ team_queue_override_port_refresh(team, port);
+ return 0;
+}
+
+
static const struct team_option team_options[] = {
{
.name = "mode",
@@ -1145,6 +1289,13 @@ static const struct team_option team_options[] = {
.getter = team_priority_option_get,
.setter = team_priority_option_set,
},
+ {
+ .name = "queue_id",
+ .type = TEAM_OPTION_TYPE_U32,
+ .per_port = true,
+ .getter = team_queue_id_option_get,
+ .setter = team_queue_id_option_set,
+ },
};
static struct lock_class_key team_netdev_xmit_lock_key;
@@ -1180,6 +1331,9 @@ static int team_init(struct net_device *dev)
for (i = 0; i < TEAM_PORT_HASHENTRIES; i++)
INIT_HLIST_HEAD(&team->en_port_hlist[i]);
INIT_LIST_HEAD(&team->port_list);
+ err = team_queue_override_init(team);
+ if (err)
+ goto err_team_queue_override_init;
team_adjust_ops(team);
@@ -1195,6 +1349,8 @@ static int team_init(struct net_device *dev)
return 0;
err_options_register:
+ team_queue_override_fini(team);
+err_team_queue_override_init:
free_percpu(team->pcpu_stats);
return err;
@@ -1212,6 +1368,7 @@ static void team_uninit(struct net_device *dev)
__team_change_mode(team, NULL); /* cleanup */
__team_options_unregister(team, team_options, ARRAY_SIZE(team_options));
+ team_queue_override_fini(team);
mutex_unlock(&team->lock);
}
@@ -1241,10 +1398,12 @@ static int team_close(struct net_device *dev)
static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct team *team = netdev_priv(dev);
- bool tx_success = false;
+ bool tx_success;
unsigned int len = skb->len;
- tx_success = team->ops.transmit(team, skb);
+ tx_success = team_queue_override_transmit(team, skb);
+ if (!tx_success)
+ tx_success = team->ops.transmit(team, skb);
if (tx_success) {
struct team_pcpu_stats *pcpu_stats;
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
index 06495b3..33fcc20 100644
--- a/include/linux/if_team.h
+++ b/include/linux/if_team.h
@@ -68,6 +68,8 @@ struct team_port {
#endif
s32 priority; /* lower number ~ higher priority */
+ u16 queue_id;
+ struct list_head qom_list; /* node in queue override mapping list */
long mode_priv[0];
};
@@ -200,6 +202,8 @@ struct team {
const struct team_mode *mode;
struct team_mode_ops ops;
+ bool queue_override_enabled;
+ struct list_head *qom_lists; /* array of queue override mapping lists */
long mode_priv[TEAM_MODE_PRIV_LONGS];
};
--
1.7.10.4
^ permalink raw reply related
* [patch net-next 3/4] team: add per port priority option
From: Jiri Pirko @ 2012-07-27 16:28 UTC (permalink / raw)
To: netdev; +Cc: davem, edumazet
In-Reply-To: <1343406535-22388-1-git-send-email-jiri@resnulli.us>
Allow userspace to set port priority.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
drivers/net/team/team.c | 25 +++++++++++++++++++++++++
include/linux/if_team.h | 1 +
2 files changed, 26 insertions(+)
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 70752e6..a30b7c1 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1092,6 +1092,24 @@ static int team_user_linkup_en_option_set(struct team *team,
return 0;
}
+static int team_priority_option_get(struct team *team,
+ struct team_gsetter_ctx *ctx)
+{
+ struct team_port *port = ctx->info->port;
+
+ ctx->data.s32_val = port->priority;
+ return 0;
+}
+
+static int team_priority_option_set(struct team *team,
+ struct team_gsetter_ctx *ctx)
+{
+ struct team_port *port = ctx->info->port;
+
+ port->priority = ctx->data.s32_val;
+ return 0;
+}
+
static const struct team_option team_options[] = {
{
.name = "mode",
@@ -1120,6 +1138,13 @@ static const struct team_option team_options[] = {
.getter = team_user_linkup_en_option_get,
.setter = team_user_linkup_en_option_set,
},
+ {
+ .name = "priority",
+ .type = TEAM_OPTION_TYPE_S32,
+ .per_port = true,
+ .getter = team_priority_option_get,
+ .setter = team_priority_option_set,
+ },
};
static struct lock_class_key team_netdev_xmit_lock_key;
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
index e5571c4..06495b3 100644
--- a/include/linux/if_team.h
+++ b/include/linux/if_team.h
@@ -67,6 +67,7 @@ struct team_port {
struct netpoll *np;
#endif
+ s32 priority; /* lower number ~ higher priority */
long mode_priv[0];
};
--
1.7.10.4
^ permalink raw reply related
* [patch net-next 2/4] team: add signed 32-bit team option type
From: Jiri Pirko @ 2012-07-27 16:28 UTC (permalink / raw)
To: netdev; +Cc: davem, edumazet
In-Reply-To: <1343406535-22388-1-git-send-email-jiri@resnulli.us>
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
drivers/net/team/team.c | 12 ++++++++++++
include/linux/if_team.h | 2 ++
2 files changed, 14 insertions(+)
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 87707ab..70752e6 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1787,6 +1787,12 @@ static int team_nl_fill_one_option_get(struct sk_buff *skb, struct team *team,
nla_put_flag(skb, TEAM_ATTR_OPTION_DATA))
goto nest_cancel;
break;
+ case TEAM_OPTION_TYPE_S32:
+ if (nla_put_u8(skb, TEAM_ATTR_OPTION_TYPE, NLA_S32))
+ goto nest_cancel;
+ if (nla_put_s32(skb, TEAM_ATTR_OPTION_DATA, ctx.data.s32_val))
+ goto nest_cancel;
+ break;
default:
BUG();
}
@@ -1975,6 +1981,9 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
case NLA_FLAG:
opt_type = TEAM_OPTION_TYPE_BOOL;
break;
+ case NLA_S32:
+ opt_type = TEAM_OPTION_TYPE_S32;
+ break;
default:
goto team_put;
}
@@ -2031,6 +2040,9 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
case TEAM_OPTION_TYPE_BOOL:
ctx.data.bool_val = attr_data ? true : false;
break;
+ case TEAM_OPTION_TYPE_S32:
+ ctx.data.s32_val = nla_get_s32(attr_data);
+ break;
default:
BUG();
}
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
index 6960fc1..e5571c4 100644
--- a/include/linux/if_team.h
+++ b/include/linux/if_team.h
@@ -130,6 +130,7 @@ enum team_option_type {
TEAM_OPTION_TYPE_STRING,
TEAM_OPTION_TYPE_BINARY,
TEAM_OPTION_TYPE_BOOL,
+ TEAM_OPTION_TYPE_S32,
};
struct team_option_inst_info {
@@ -146,6 +147,7 @@ struct team_gsetter_ctx {
u32 len;
} bin_val;
bool bool_val;
+ s32 s32_val;
} data;
struct team_option_inst_info *info;
};
--
1.7.10.4
^ permalink raw reply related
* [patch net-next 1/4] netlink: add signed types
From: Jiri Pirko @ 2012-07-27 16:28 UTC (permalink / raw)
To: netdev; +Cc: davem, edumazet
In-Reply-To: <1343406535-22388-1-git-send-email-jiri@resnulli.us>
Signed types might be needed in NL communication from time to time
(I need s32 in team driver), so add them.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
include/net/netlink.h | 98 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 98 insertions(+)
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 785f37a..09175d5 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -98,6 +98,10 @@
* nla_put_u16(skb, type, value) add u16 attribute to skb
* nla_put_u32(skb, type, value) add u32 attribute to skb
* nla_put_u64(skb, type, value) add u64 attribute to skb
+ * nla_put_s8(skb, type, value) add s8 attribute to skb
+ * nla_put_s16(skb, type, value) add s16 attribute to skb
+ * nla_put_s32(skb, type, value) add s32 attribute to skb
+ * nla_put_s64(skb, type, value) add s64 attribute to skb
* nla_put_string(skb, type, str) add string attribute to skb
* nla_put_flag(skb, type) add flag attribute to skb
* nla_put_msecs(skb, type, jiffies) add msecs attribute to skb
@@ -121,6 +125,10 @@
* nla_get_u16(nla) get payload for a u16 attribute
* nla_get_u32(nla) get payload for a u32 attribute
* nla_get_u64(nla) get payload for a u64 attribute
+ * nla_get_s8(nla) get payload for a s8 attribute
+ * nla_get_s16(nla) get payload for a s16 attribute
+ * nla_get_s32(nla) get payload for a s32 attribute
+ * nla_get_s64(nla) get payload for a s64 attribute
* nla_get_flag(nla) return 1 if flag is true
* nla_get_msecs(nla) get payload for a msecs attribute
*
@@ -160,6 +168,10 @@ enum {
NLA_NESTED_COMPAT,
NLA_NUL_STRING,
NLA_BINARY,
+ NLA_S8,
+ NLA_S16,
+ NLA_S32,
+ NLA_S64,
__NLA_TYPE_MAX,
};
@@ -183,6 +195,8 @@ enum {
* NLA_NESTED_COMPAT Minimum length of structure payload
* NLA_U8, NLA_U16,
* NLA_U32, NLA_U64,
+ * NLA_S8, NLA_S16,
+ * NLA_S32, NLA_S64,
* NLA_MSECS Leaving the length field zero will verify the
* given type fits, using it verifies minimum length
* just like "All other"
@@ -879,6 +893,50 @@ static inline int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value)
}
/**
+ * nla_put_s8 - Add a s8 netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ */
+static inline int nla_put_s8(struct sk_buff *skb, int attrtype, s8 value)
+{
+ return nla_put(skb, attrtype, sizeof(s8), &value);
+}
+
+/**
+ * nla_put_s16 - Add a s16 netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ */
+static inline int nla_put_s16(struct sk_buff *skb, int attrtype, s16 value)
+{
+ return nla_put(skb, attrtype, sizeof(s16), &value);
+}
+
+/**
+ * nla_put_s32 - Add a s32 netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ */
+static inline int nla_put_s32(struct sk_buff *skb, int attrtype, s32 value)
+{
+ return nla_put(skb, attrtype, sizeof(s32), &value);
+}
+
+/**
+ * nla_put_s64 - Add a s64 netlink attribute to a socket buffer
+ * @skb: socket buffer to add attribute to
+ * @attrtype: attribute type
+ * @value: numeric value
+ */
+static inline int nla_put_s64(struct sk_buff *skb, int attrtype, s64 value)
+{
+ return nla_put(skb, attrtype, sizeof(s64), &value);
+}
+
+/**
* nla_put_string - Add a string netlink attribute to a socket buffer
* @skb: socket buffer to add attribute to
* @attrtype: attribute type
@@ -994,6 +1052,46 @@ static inline __be64 nla_get_be64(const struct nlattr *nla)
}
/**
+ * nla_get_s32 - return payload of s32 attribute
+ * @nla: s32 netlink attribute
+ */
+static inline s32 nla_get_s32(const struct nlattr *nla)
+{
+ return *(s32 *) nla_data(nla);
+}
+
+/**
+ * nla_get_s16 - return payload of s16 attribute
+ * @nla: s16 netlink attribute
+ */
+static inline s16 nla_get_s16(const struct nlattr *nla)
+{
+ return *(s16 *) nla_data(nla);
+}
+
+/**
+ * nla_get_s8 - return payload of s8 attribute
+ * @nla: s8 netlink attribute
+ */
+static inline s8 nla_get_s8(const struct nlattr *nla)
+{
+ return *(s8 *) nla_data(nla);
+}
+
+/**
+ * nla_get_s64 - return payload of s64 attribute
+ * @nla: s64 netlink attribute
+ */
+static inline s64 nla_get_s64(const struct nlattr *nla)
+{
+ s64 tmp;
+
+ nla_memcpy(&tmp, nla, sizeof(tmp));
+
+ return tmp;
+}
+
+/**
* nla_get_flag - return payload of flag attribute
* @nla: flag netlink attribute
*/
--
1.7.10.4
^ permalink raw reply related
* [patch net-next 0/4] add support for queue override by setting queue_id for port
From: Jiri Pirko @ 2012-07-27 16:28 UTC (permalink / raw)
To: netdev; +Cc: davem, edumazet
Jiri Pirko (4):
netlink: add signed types
team: add signed 32-bit team option type
team: add per port priority option
team: add support for queue override by setting queue_id for port
drivers/net/team/team.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++-
include/linux/if_team.h | 7 ++
include/net/netlink.h | 98 +++++++++++++++++++++++
3 files changed, 303 insertions(+), 2 deletions(-)
--
1.7.10.4
^ permalink raw reply
* Re: [PATCH 00/16] Remove the ipv4 routing cache
From: Eric Dumazet @ 2012-07-27 16:28 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: David Miller, alexander.duyck, netdev
In-Reply-To: <87mx2l41hl.fsf@xmission.com>
On Fri, 2012-07-27 at 09:23 -0700, Eric W. Biederman wrote:
> I am familiar. But does hardware prefetching make a difference
> if your object is less than 64 bytes?
>
Apparently yes, if the prefetch touches a dirtied neighbour cache line.
> I don't believe only allocating 64 bytes will be a problem,
> as no one else well be dirtying your cache line.
>
> I suppose you could run into pathologies where your object
> is 3*64 bytes in size, but your expression doesn't handle
> that case either.
>
Sure, but in most cases fib objects are under 128 bytes.
> The other alternative to guarantee very good cache behavior is
> to ensure you are allocating a power of two size up to some limit,
> perhaps page size.
>
Good idea.
> My point is the magic 128 likely requires an explicatory comment and I
> think the net result is you have encoded something fragile that is good
> for testing but that will in the fullness of time do strange things that
> will be easy to overlook.
Sure, I'll send a v2, thanks.
^ permalink raw reply
* [PATCH] ipv4: fix TCP early demux
From: Eric Dumazet @ 2012-07-27 16:23 UTC (permalink / raw)
To: David Miller; +Cc: netdev
From: Eric Dumazet <edumazet@google.com>
commit 92101b3b2e317 (ipv4: Prepare for change of rt->rt_iif encoding.)
invalidated TCP early demux, because rx_dst_ifindex is not properly
initialized and checked.
Also remove the use of inet_iif(skb) in favor or skb->skb_iif
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/ipv4/tcp_input.c | 1 +
net/ipv4/tcp_ipv4.c | 14 ++++++--------
net/ipv4/tcp_minisocks.c | 1 +
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 3e07a64..aa659e8 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5603,6 +5603,7 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)
if (skb != NULL) {
sk->sk_rx_dst = dst_clone(skb_dst(skb));
+ inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
security_inet_conn_established(sk, skb);
}
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index b6b07c9..2fbd992 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1620,17 +1620,15 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
sock_rps_save_rxhash(sk, skb);
if (sk->sk_rx_dst) {
struct dst_entry *dst = sk->sk_rx_dst;
- if (dst->ops->check(dst, 0) == NULL) {
+ if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif ||
+ dst->ops->check(dst, 0) == NULL) {
dst_release(dst);
sk->sk_rx_dst = NULL;
}
}
if (unlikely(sk->sk_rx_dst == NULL)) {
- struct inet_sock *icsk = inet_sk(sk);
- struct rtable *rt = skb_rtable(skb);
-
- sk->sk_rx_dst = dst_clone(&rt->dst);
- icsk->rx_dst_ifindex = inet_iif(skb);
+ sk->sk_rx_dst = dst_clone(skb_dst(skb));
+ inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
}
if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) {
rsk = sk;
@@ -1709,11 +1707,11 @@ void tcp_v4_early_demux(struct sk_buff *skb)
skb->destructor = sock_edemux;
if (sk->sk_state != TCP_TIME_WAIT) {
struct dst_entry *dst = sk->sk_rx_dst;
- struct inet_sock *icsk = inet_sk(sk);
+
if (dst)
dst = dst_check(dst, 0);
if (dst &&
- icsk->rx_dst_ifindex == skb->skb_iif)
+ inet_sk(sk)->rx_dst_ifindex == skb->skb_iif)
skb_dst_set_noref(skb, dst);
}
}
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 5912ac3..3f1cc20 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -388,6 +388,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
struct tcp_cookie_values *oldcvp = oldtp->cookie_values;
newsk->sk_rx_dst = dst_clone(skb_dst(skb));
+ inet_sk(newsk)->rx_dst_ifindex = skb->skb_iif;
/* TCP Cookie Transactions require space for the cookie pair,
* as it differs for each connection. There is no need to
^ permalink raw reply related
* Re: [PATCH 00/16] Remove the ipv4 routing cache
From: Eric W. Biederman @ 2012-07-27 16:23 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, alexander.duyck, netdev
In-Reply-To: <1343401949.2626.13011.camel@edumazet-glaptop>
Eric Dumazet <eric.dumazet@gmail.com> writes:
> On Fri, 2012-07-27 at 07:53 -0700, Eric W. Biederman wrote:
>> Eric Dumazet <eric.dumazet@gmail.com> writes:
>>
>> > Now IP route cache is removed, we should make sure fib structures
>> > cant share cache lines with possibly often dirtied objects.
>> >
>> > On x86, kmalloc-96 cache can be source of such problems.
>> >
>> > Signed-off-by: Eric Dumazet <edumazet@google.com>
>>
>>
>> > +static inline void *fib_zalloc(size_t size)
>> > +{
>> > + /* We want to avoid possible false sharing */
>> > + return kzalloc(max_t(size_t, 128, size), GFP_KERNEL);
>>
>> Why the hard coded 128 here?
>>
>> It seems more portable and obvious to do
>> return kzalloc(round_up(size, L1_CACHE_BYTES), GFP_KERNEL);
>>
>
> Its not that obvious, because some machines have an apparent
> L1_CACHE_BYTES of 64, but hardware prefetching to 128 bytes
I am familiar. But does hardware prefetching make a difference
if your object is less than 64 bytes?
I don't believe only allocating 64 bytes will be a problem,
as no one else well be dirtying your cache line.
I suppose you could run into pathologies where your object
is 3*64 bytes in size, but your expression doesn't handle
that case either.
> But using 2*L1_CACHE_BYTES as minimum allocation size might be overkill
> on some arches with 256 bytes cache lines.
The other alternative to guarantee very good cache behavior is
to ensure you are allocating a power of two size up to some limit,
perhaps page size.
My point is the magic 128 likely requires an explicatory comment and I
think the net result is you have encoded something fragile that is good
for testing but that will in the fullness of time do strange things that
will be easy to overlook.
Eric
^ permalink raw reply
* Re: bonding and SR-IOV -- do we need arp_validation for loadbalancing too?
From: Chris Friesen @ 2012-07-27 16:15 UTC (permalink / raw)
To: Andy Gospodarek; +Cc: Jay Vosburgh, Jiri Pirko, netdev, andy
In-Reply-To: <20120727145514.GB7323@quad.redhat.com>
On 07/27/2012 08:55 AM, Andy Gospodarek wrote:
> On Tue, Jul 24, 2012 at 03:38:11PM -0600, Chris Friesen wrote:
>> In our environment (ATCA shelf) the switches have been customized to
>> handle some of this stuff so arpmon does work reliably with xor.
> Good.
>
>> In the general case it sounds like the "PF bonding ignores packets
>> from VFs" is a better bet then.
> It really might be. There are some registers in the 82599 datasheets
> that are not used by the ixgbe driver, but might help you in this area.
>
> If you take a look at PFVML2FLT and PFUTA and their current status on
> your system you might be able to put something together that gives you
> what you want.
I think it's simpler than that. By my reading of the 82599 datasheet,
the LB bit in the status field of the rx descriptor will indicate if the
packet came from a VM.
> It would likely mean you have to run a custom ixgbe-driver, but that
> doesn't sound like much of an issue.
While I'd like to avoid it if possible, we've already had to tweak the
driver for other things.
The complication is that we've got a few different types of hardware and
they're not all running 82599. I'm trying to figure out if the other
hardware can do something similar.
Chris
^ permalink raw reply
* pull request: wireless 2012-07-27
From: John W. Linville @ 2012-07-27 15:58 UTC (permalink / raw)
To: davem; +Cc: linux-wireless, netdev, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 4876 bytes --]
commit 28ea499ac5b90f6266a24b826c6d469fc503758c
Dave,
These fixes are intended for the 3.6 stream.
Hauke Mehrtens provides a pair of bcma fixes, one to fix a build
regression on mips and another to correct a pair of missing iounmap
calls.
Thomas Huehn offers a mac80211_hwsim fix to avoid a possible
use-after-free bug.
Please let me know if there are problems!
Thanks,
John
---
The following changes since commit 6ee127b7dd63afe4d6d0a58293786bf4bf336850:
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc (2012-07-26 18:14:11 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git for-davem
for you to fetch changes up to 28ea499ac5b90f6266a24b826c6d469fc503758c:
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless into for-davem (2012-07-27 11:15:03 -0400)
----------------------------------------------------------------
Hauke Mehrtens (2):
bcma: fix regression in interrupt assignment on mips
bcma: add missing iounmap on error path
John W. Linville (1):
Merge branch 'master' of git://git.kernel.org/.../linville/wireless into for-davem
Thomas Huehn (1):
mac80211_hwsim: fix possible race condition in usage of info->control.sta & control.vif
drivers/bcma/driver_mips.c | 6 +++---
drivers/bcma/scan.c | 15 ++++++++++-----
drivers/net/wireless/mac80211_hwsim.c | 5 -----
3 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c
index b013b04..cc65b45 100644
--- a/drivers/bcma/driver_mips.c
+++ b/drivers/bcma/driver_mips.c
@@ -131,7 +131,7 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
/* backplane irq line is in use, find out who uses
* it and set user to irq 0
*/
- list_for_each_entry_reverse(core, &bus->cores, list) {
+ list_for_each_entry(core, &bus->cores, list) {
if ((1 << bcma_core_mips_irqflag(core)) ==
oldirqflag) {
bcma_core_mips_set_irq(core, 0);
@@ -161,7 +161,7 @@ static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
{
struct bcma_device *core;
- list_for_each_entry_reverse(core, &bus->cores, list) {
+ list_for_each_entry(core, &bus->cores, list) {
bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
}
}
@@ -224,7 +224,7 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
mcore->assigned_irqs = 1;
/* Assign IRQs to all cores on the bus */
- list_for_each_entry_reverse(core, &bus->cores, list) {
+ list_for_each_entry(core, &bus->cores, list) {
int mips_irq;
if (core->irq)
continue;
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index 5672b13..8d0b571 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -462,8 +462,10 @@ int bcma_bus_scan(struct bcma_bus *bus)
while (eromptr < eromend) {
struct bcma_device *other_core;
struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL);
- if (!core)
- return -ENOMEM;
+ if (!core) {
+ err = -ENOMEM;
+ goto out;
+ }
INIT_LIST_HEAD(&core->list);
core->bus = bus;
@@ -478,7 +480,7 @@ int bcma_bus_scan(struct bcma_bus *bus)
} else if (err == -ESPIPE) {
break;
}
- return err;
+ goto out;
}
core->core_index = core_num++;
@@ -494,10 +496,12 @@ int bcma_bus_scan(struct bcma_bus *bus)
list_add_tail(&core->list, &bus->cores);
}
+ err = 0;
+out:
if (bus->hosttype == BCMA_HOSTTYPE_SOC)
iounmap(eromptr);
- return 0;
+ return err;
}
int __init bcma_bus_scan_early(struct bcma_bus *bus,
@@ -537,7 +541,7 @@ int __init bcma_bus_scan_early(struct bcma_bus *bus,
else if (err == -ESPIPE)
break;
else if (err < 0)
- return err;
+ goto out;
core->core_index = core_num++;
bus->nr_cores++;
@@ -551,6 +555,7 @@ int __init bcma_bus_scan_early(struct bcma_bus *bus,
break;
}
+out:
if (bus->hosttype == BCMA_HOSTTYPE_SOC)
iounmap(eromptr);
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 643f968..0083839 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -739,11 +739,6 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
txi = IEEE80211_SKB_CB(skb);
- if (txi->control.vif)
- hwsim_check_magic(txi->control.vif);
- if (txi->control.sta)
- hwsim_check_sta_magic(txi->control.sta);
-
ieee80211_tx_info_clear_status(txi);
/* frame was transmitted at most favorable rate at first attempt */
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply related
* Re: [PATCH 4/7] bridge: call NETDEV_RELEASE notifier in br_del_if()
From: Stephen Hemminger @ 2012-07-27 15:50 UTC (permalink / raw)
To: Cong Wang; +Cc: netdev, bridge, David S. Miller, linux-kernel
In-Reply-To: <1343403484-29347-5-git-send-email-amwang@redhat.com>
On Fri, 27 Jul 2012 23:38:01 +0800
Cong Wang <amwang@redhat.com> wrote:
> When a bridge interface deletes its underlying ports, it should
> notify netconsole too, like what bonding interface does.
>
> Cc: "David S. Miller" <davem@davemloft.net>
> Signed-off-by: Cong Wang <amwang@redhat.com>
> ---
> net/bridge/br_if.c | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
> index e1144e1..d243914 100644
> --- a/net/bridge/br_if.c
> +++ b/net/bridge/br_if.c
> @@ -427,6 +427,7 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
> if (!p || p->br != br)
> return -EINVAL;
>
> + call_netdevice_notifiers(NETDEV_RELEASE, br->dev);
> del_nbp(p);
>
> spin_lock_bh(&br->lock);
Since you can have multiple ports attached to the bridge, this
doesn't seem correct. Don't you want the netconsole to keep going
on the other ports of the bridge?
What exactly is the problem with having netconsole persist?
^ permalink raw reply
* [PATCH 7/7] netpoll: take rcu_read_lock_bh() in netpoll_send_skb_on_dev()
From: Cong Wang @ 2012-07-27 15:38 UTC (permalink / raw)
To: netdev
Cc: Cong Wang, David S. Miller, Eric Dumazet, Cong Wang, Joe Perches,
Neil Horman, linux-kernel
In-Reply-To: <1343403484-29347-1-git-send-email-amwang@redhat.com>
This patch fixes several problems in the call path of
netpoll_send_skb_on_dev():
1. We already disable IRQ's before calling netpoll_send_skb_on_dev(),
so we don't need to disable IRQ's again.
2. All the callees of netpoll_send_skb_on_dev() should use
rcu_dereference_bh() to dereference ->npinfo.
3. Rename arp_reply() to netpoll_arp_reply(), the former is too generic.
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
net/core/netpoll.c | 31 +++++++++++++++++--------------
1 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 3965fdb..d6e192b 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -54,7 +54,7 @@ static atomic_t trapped;
MAX_UDP_CHUNK)
static void zap_completion_queue(void);
-static void arp_reply(struct sk_buff *skb);
+static void netpoll_arp_reply(struct sk_buff *skb, struct netpoll_info *npinfo);
static unsigned int carrier_timeout = 4;
module_param(carrier_timeout, uint, 0644);
@@ -170,7 +170,8 @@ static void poll_napi(struct net_device *dev)
list_for_each_entry(napi, &dev->napi_list, dev_list) {
if (napi->poll_owner != smp_processor_id() &&
spin_trylock(&napi->poll_lock)) {
- budget = poll_one_napi(dev->npinfo, napi, budget);
+ budget = poll_one_napi(rcu_dereference_bh(dev->npinfo),
+ napi, budget);
spin_unlock(&napi->poll_lock);
if (!budget)
@@ -185,13 +186,14 @@ static void service_arp_queue(struct netpoll_info *npi)
struct sk_buff *skb;
while ((skb = skb_dequeue(&npi->arp_tx)))
- arp_reply(skb);
+ netpoll_arp_reply(skb, npi);
}
}
static void netpoll_poll_dev(struct net_device *dev)
{
const struct net_device_ops *ops;
+ struct netpoll_info *ni = rcu_dereference_bh(dev->npinfo);
if (!dev || !netif_running(dev))
return;
@@ -206,17 +208,18 @@ static void netpoll_poll_dev(struct net_device *dev)
poll_napi(dev);
if (dev->flags & IFF_SLAVE) {
- if (dev->npinfo) {
+ if (ni) {
struct net_device *bond_dev = dev->master;
struct sk_buff *skb;
- while ((skb = skb_dequeue(&dev->npinfo->arp_tx))) {
+ struct netpoll_info *bond_ni = rcu_dereference_bh(bond_dev->npinfo);
+ while ((skb = skb_dequeue(&ni->arp_tx))) {
skb->dev = bond_dev;
- skb_queue_tail(&bond_dev->npinfo->arp_tx, skb);
+ skb_queue_tail(&bond_ni->arp_tx, skb);
}
}
}
- service_arp_queue(dev->npinfo);
+ service_arp_queue(ni);
zap_completion_queue();
}
@@ -302,6 +305,7 @@ static int netpoll_owner_active(struct net_device *dev)
return 0;
}
+/* call with IRQ disabled */
void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
struct net_device *dev)
{
@@ -309,8 +313,11 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
unsigned long tries;
const struct net_device_ops *ops = dev->netdev_ops;
/* It is up to the caller to keep npinfo alive. */
- struct netpoll_info *npinfo = np->dev->npinfo;
+ struct netpoll_info *npinfo;
+
+ WARN_ON_ONCE(!irqs_disabled());
+ npinfo = rcu_dereference_bh(np->dev->npinfo);
if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) {
__kfree_skb(skb);
return;
@@ -319,11 +326,9 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
/* don't get messages out of order, and no recursion */
if (skb_queue_len(&npinfo->txq) == 0 && !netpoll_owner_active(dev)) {
struct netdev_queue *txq;
- unsigned long flags;
txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb));
- local_irq_save(flags);
/* try until next clock tick */
for (tries = jiffies_to_usecs(1)/USEC_PER_POLL;
tries > 0; --tries) {
@@ -347,10 +352,9 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
}
WARN_ONCE(!irqs_disabled(),
- "netpoll_send_skb(): %s enabled interrupts in poll (%pF)\n",
+ "netpoll_send_skb_on_dev(): %s enabled interrupts in poll (%pF)\n",
dev->name, ops->ndo_start_xmit);
- local_irq_restore(flags);
}
if (status != NETDEV_TX_OK) {
@@ -423,9 +427,8 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
}
EXPORT_SYMBOL(netpoll_send_udp);
-static void arp_reply(struct sk_buff *skb)
+static void netpoll_arp_reply(struct sk_buff *skb, struct netpoll_info *npinfo)
{
- struct netpoll_info *npinfo = skb->dev->npinfo;
struct arphdr *arp;
unsigned char *arp_ptr;
int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
--
1.7.7.6
^ permalink raw reply related
* [PATCH 0/7] netpoll and netconsole fixes for 3.6
From: Cong Wang @ 2012-07-27 15:37 UTC (permalink / raw)
To: netdev; +Cc: Cong Wang, David S. Miller
This patch fixes serval problems in netconsole and netpoll.
I ran this patch in my KVM guest with some netpoll test cases,
even covered with some corner cases, everything worked as expected.
BTW, my kernel config enables the following validatation options:
CONFIG_DEBUG_ATOMIC_SLEEP=y
CONFIG_PROVE_LOCKING=y
CONFIG_PROVE_RCU=y
CONFIG_LOCKDEP=y
CONFIG_RCU_CPU_STALL_TIMEOUT=60
CONFIG_LOCKUP_DETECTOR=y
CONFIG_HARDLOCKUP_DETECTOR=y
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
Cong Wang (7):
netpoll: use GFP_ATOMIC in slave_enable_netpoll() and __netpoll_setup()
netpoll: make __netpoll_cleanup non-block
netconsole: do not release spin_lock when calling __netpoll_cleanup
bridge: call NETDEV_RELEASE notifier in br_del_if()
netpoll: take rcu_read_lock_bh() in netpoll_rx()
netpoll: use netpoll_rx_on() in netpoll_rx()
netpoll: take rcu_read_lock_bh() in netpoll_send_skb_on_dev()
drivers/net/bonding/bond_main.c | 6 +--
drivers/net/netconsole.c | 5 --
include/linux/netpoll.h | 25 +++++++-----
net/8021q/vlan_dev.c | 6 +--
net/bridge/br_device.c | 6 +--
net/bridge/br_if.c | 1 +
net/core/netpoll.c | 78 +++++++++++++++++++++++++-------------
7 files changed, 70 insertions(+), 57 deletions(-)
--
1.7.7.6
^ permalink raw reply
* [PATCH 6/7] netpoll: use netpoll_rx_on() in netpoll_rx()
From: Cong Wang @ 2012-07-27 15:38 UTC (permalink / raw)
To: netdev; +Cc: Cong Wang, David S. Miller, Jiri Pirko, linux-kernel
In-Reply-To: <1343403484-29347-1-git-send-email-amwang@redhat.com>
The logic of the code is same, just call netpoll_rx_on().
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
include/linux/netpoll.h | 18 +++++++++---------
1 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index 36f938c..f654fa3 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -63,6 +63,13 @@ static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
#ifdef CONFIG_NETPOLL
+static inline int netpoll_rx_on(struct sk_buff *skb)
+{
+ struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo);
+
+ return npinfo && (!list_empty(&npinfo->rx_np) || npinfo->rx_flags);
+}
+
static inline bool netpoll_rx(struct sk_buff *skb)
{
struct netpoll_info *npinfo;
@@ -70,11 +77,11 @@ static inline bool netpoll_rx(struct sk_buff *skb)
bool ret = false;
local_irq_save(flags);
- npinfo = rcu_dereference_bh(skb->dev->npinfo);
- if (!npinfo || (list_empty(&npinfo->rx_np) && !npinfo->rx_flags))
+ if (!netpoll_rx_on(skb))
goto out;
+ npinfo = rcu_dereference_bh(skb->dev->npinfo);
spin_lock(&npinfo->rx_lock);
/* check rx_flags again with the lock held */
if (npinfo->rx_flags && __netpoll_rx(skb, npinfo))
@@ -86,13 +93,6 @@ out:
return ret;
}
-static inline int netpoll_rx_on(struct sk_buff *skb)
-{
- struct netpoll_info *npinfo = rcu_dereference_bh(skb->dev->npinfo);
-
- return npinfo && (!list_empty(&npinfo->rx_np) || npinfo->rx_flags);
-}
-
static inline int netpoll_receive_skb(struct sk_buff *skb)
{
if (!list_empty(&skb->dev->napi_list))
--
1.7.7.6
^ permalink raw reply related
* [PATCH 5/7] netpoll: take rcu_read_lock_bh() in netpoll_rx()
From: Cong Wang @ 2012-07-27 15:38 UTC (permalink / raw)
To: netdev
Cc: Cong Wang, David S. Miller, Jiri Pirko, Eric Dumazet, Cong Wang,
Joe Perches, Neil Horman, linux-kernel
In-Reply-To: <1343403484-29347-1-git-send-email-amwang@redhat.com>
In __netpoll_rx(), it dereferences ->npinfo without rcu_dereference_bh(),
this patch fixes it by using the 'npinfo' passed from netpoll_rx()
where it is already dereferenced with rcu_dereference_bh().
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
include/linux/netpoll.h | 4 ++--
net/core/netpoll.c | 3 +--
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index 5011d74..36f938c 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -52,7 +52,7 @@ void netpoll_set_trap(int trap);
void __netpoll_cleanup(struct netpoll *np);
void __netpoll_free_rcu(struct netpoll *np);
void netpoll_cleanup(struct netpoll *np);
-int __netpoll_rx(struct sk_buff *skb);
+int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo);
void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
struct net_device *dev);
static inline void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
@@ -77,7 +77,7 @@ static inline bool netpoll_rx(struct sk_buff *skb)
spin_lock(&npinfo->rx_lock);
/* check rx_flags again with the lock held */
- if (npinfo->rx_flags && __netpoll_rx(skb))
+ if (npinfo->rx_flags && __netpoll_rx(skb, npinfo))
ret = true;
spin_unlock(&npinfo->rx_lock);
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 19dddef..3965fdb 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -543,13 +543,12 @@ static void arp_reply(struct sk_buff *skb)
spin_unlock_irqrestore(&npinfo->rx_lock, flags);
}
-int __netpoll_rx(struct sk_buff *skb)
+int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
{
int proto, len, ulen;
int hits = 0;
const struct iphdr *iph;
struct udphdr *uh;
- struct netpoll_info *npinfo = skb->dev->npinfo;
struct netpoll *np, *tmp;
if (list_empty(&npinfo->rx_np))
--
1.7.7.6
^ permalink raw reply related
* [PATCH 4/7] bridge: call NETDEV_RELEASE notifier in br_del_if()
From: Cong Wang @ 2012-07-27 15:38 UTC (permalink / raw)
To: netdev; +Cc: Cong Wang, David S. Miller, Stephen Hemminger, bridge,
linux-kernel
In-Reply-To: <1343403484-29347-1-git-send-email-amwang@redhat.com>
When a bridge interface deletes its underlying ports, it should
notify netconsole too, like what bonding interface does.
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
net/bridge/br_if.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index e1144e1..d243914 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -427,6 +427,7 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
if (!p || p->br != br)
return -EINVAL;
+ call_netdevice_notifiers(NETDEV_RELEASE, br->dev);
del_nbp(p);
spin_lock_bh(&br->lock);
--
1.7.7.6
^ permalink raw reply related
* [PATCH 3/7] netconsole: do not release spin_lock before calling __netpoll_cleanup
From: Cong Wang @ 2012-07-27 15:38 UTC (permalink / raw)
To: netdev
Cc: Cong Wang, David S. Miller, Gao feng, Lin Ming, Joe Perches,
Flavio Leitner, linux-kernel
In-Reply-To: <1343403484-29347-1-git-send-email-amwang@redhat.com>
With the previous patch applied, __netpoll_cleanup() is non-block now,
so we don't need to release the spin_lock before calling it.
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
drivers/net/netconsole.c | 5 -----
1 files changed, 0 insertions(+), 5 deletions(-)
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index f9347ea..f0ad56c 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -640,12 +640,7 @@ static int netconsole_netdev_event(struct notifier_block *this,
* rtnl_lock already held
*/
if (nt->np.dev) {
- spin_unlock_irqrestore(
- &target_list_lock,
- flags);
__netpoll_cleanup(&nt->np);
- spin_lock_irqsave(&target_list_lock,
- flags);
dev_put(nt->np.dev);
nt->np.dev = NULL;
netconsole_target_put(nt);
--
1.7.7.6
^ permalink raw reply related
* [PATCH 2/7] netpoll: make __netpoll_cleanup non-block
From: Cong Wang @ 2012-07-27 15:37 UTC (permalink / raw)
To: netdev
Cc: bridge, Jiri Pirko, Cong Wang, Neil Horman, Jay Vosburgh,
linux-kernel, David S. Miller, Eric Dumazet, Joe Perches,
Cong Wang, Stephen Hemminger
In-Reply-To: <1343403484-29347-1-git-send-email-amwang@redhat.com>
Like the previous patch, slave_disable_netpoll() and __netpoll_cleanup()
may be called with read_lock() held too, so we should make them
non-block, by moving the cleanup and kfree() to call_rcu_bh() callbacks.
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
drivers/net/bonding/bond_main.c | 4 +--
include/linux/netpoll.h | 3 ++
net/8021q/vlan_dev.c | 6 +----
net/bridge/br_device.c | 6 +----
net/core/netpoll.c | 42 +++++++++++++++++++++++++++++---------
5 files changed, 38 insertions(+), 23 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index ab773d4..9907889 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1257,9 +1257,7 @@ static inline void slave_disable_netpoll(struct slave *slave)
return;
slave->np = NULL;
- synchronize_rcu_bh();
- __netpoll_cleanup(np);
- kfree(np);
+ __netpoll_free_rcu(np);
}
static inline bool slave_dev_support_netpoll(struct net_device *slave_dev)
{
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index 28f5389..5011d74 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -23,6 +23,7 @@ struct netpoll {
u8 remote_mac[ETH_ALEN];
struct list_head rx; /* rx_np list element */
+ struct rcu_head rcu;
};
struct netpoll_info {
@@ -38,6 +39,7 @@ struct netpoll_info {
struct delayed_work tx_work;
struct netpoll *netpoll;
+ struct rcu_head rcu;
};
void netpoll_send_udp(struct netpoll *np, const char *msg, int len);
@@ -48,6 +50,7 @@ int netpoll_setup(struct netpoll *np);
int netpoll_trap(void);
void netpoll_set_trap(int trap);
void __netpoll_cleanup(struct netpoll *np);
+void __netpoll_free_rcu(struct netpoll *np);
void netpoll_cleanup(struct netpoll *np);
int __netpoll_rx(struct sk_buff *skb);
void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb,
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 73a2a83..43e14a2 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -703,11 +703,7 @@ static void vlan_dev_netpoll_cleanup(struct net_device *dev)
info->netpoll = NULL;
- /* Wait for transmitting packets to finish before freeing. */
- synchronize_rcu_bh();
-
- __netpoll_cleanup(netpoll);
- kfree(netpoll);
+ __netpoll_free_rcu(netpoll);
}
#endif /* CONFIG_NET_POLL_CONTROLLER */
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 3334845..bb6a5dd 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -267,11 +267,7 @@ void br_netpoll_disable(struct net_bridge_port *p)
p->np = NULL;
- /* Wait for transmitting packets to finish before freeing. */
- synchronize_rcu_bh();
-
- __netpoll_cleanup(np);
- kfree(np);
+ __netpoll_free_rcu(np);
}
#endif
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index c78a966..19dddef 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -878,6 +878,24 @@ static int __init netpoll_init(void)
}
core_initcall(netpoll_init);
+static void rcu_cleanup_netpoll_info(struct rcu_head *rcu_head)
+{
+ struct netpoll_info *npinfo =
+ container_of(rcu_head, struct netpoll_info, rcu);
+
+ skb_queue_purge(&npinfo->arp_tx);
+ skb_queue_purge(&npinfo->txq);
+
+ /* we can't call cancel_delayed_work_sync here, as we are in softirq*/
+ cancel_delayed_work(&npinfo->tx_work);
+
+ /* clean after last, unfinished work */
+ __skb_queue_purge(&npinfo->txq);
+ /* now cancel it again */
+ cancel_delayed_work(&npinfo->tx_work);
+ kfree(npinfo);
+}
+
void __netpoll_cleanup(struct netpoll *np)
{
struct netpoll_info *npinfo;
@@ -903,20 +921,24 @@ void __netpoll_cleanup(struct netpoll *np)
ops->ndo_netpoll_cleanup(np->dev);
RCU_INIT_POINTER(np->dev->npinfo, NULL);
+ call_rcu_bh(&npinfo->rcu, rcu_cleanup_netpoll_info);
+ }
+}
+EXPORT_SYMBOL_GPL(__netpoll_cleanup);
- /* avoid racing with NAPI reading npinfo */
- synchronize_rcu_bh();
+static void rcu_cleanup_netpoll(struct rcu_head *rcu_head)
+{
+ struct netpoll *np = container_of(rcu_head, struct netpoll, rcu);
- skb_queue_purge(&npinfo->arp_tx);
- skb_queue_purge(&npinfo->txq);
- cancel_delayed_work_sync(&npinfo->tx_work);
+ __netpoll_cleanup(np);
+ kfree(np);
+}
- /* clean after last, unfinished work */
- __skb_queue_purge(&npinfo->txq);
- kfree(npinfo);
- }
+void __netpoll_free_rcu(struct netpoll *np)
+{
+ call_rcu_bh(&np->rcu, rcu_cleanup_netpoll);
}
-EXPORT_SYMBOL_GPL(__netpoll_cleanup);
+EXPORT_SYMBOL_GPL(__netpoll_free_rcu);
void netpoll_cleanup(struct netpoll *np)
{
--
1.7.7.6
^ permalink raw reply related
* [PATCH 1/7] netpoll: use GFP_ATOMIC in slave_enable_netpoll() and __netpoll_setup()
From: Cong Wang @ 2012-07-27 15:37 UTC (permalink / raw)
To: netdev
Cc: Cong Wang, David S. Miller, Jay Vosburgh, Andy Gospodarek,
Eric Dumazet, Cong Wang, Joe Perches, Neil Horman, linux-kernel
In-Reply-To: <1343403484-29347-1-git-send-email-amwang@redhat.com>
slave_enable_netpoll() and __netpoll_setup() may be called
with read_lock() held, so should use GFP_ATOMIC to allocate
memory.
Cc: "David S. Miller" <davem@davemloft.net>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
drivers/net/bonding/bond_main.c | 2 +-
net/core/netpoll.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 6fae5f3..ab773d4 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1235,7 +1235,7 @@ static inline int slave_enable_netpoll(struct slave *slave)
struct netpoll *np;
int err = 0;
- np = kzalloc(sizeof(*np), GFP_KERNEL);
+ np = kzalloc(sizeof(*np), GFP_ATOMIC);
err = -ENOMEM;
if (!np)
goto out;
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index b4c90e4..c78a966 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -734,7 +734,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
}
if (!ndev->npinfo) {
- npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL);
+ npinfo = kmalloc(sizeof(*npinfo), GFP_ATOMIC);
if (!npinfo) {
err = -ENOMEM;
goto out;
--
1.7.7.6
^ permalink raw reply related
* Re: bonding and SR-IOV -- do we need arp_validation for loadbalancing too?
From: Andy Gospodarek @ 2012-07-27 14:55 UTC (permalink / raw)
To: Chris Friesen; +Cc: Jay Vosburgh, Jiri Pirko, netdev, andy
In-Reply-To: <500F15C3.4090906@genband.com>
On Tue, Jul 24, 2012 at 03:38:11PM -0600, Chris Friesen wrote:
> On 07/24/2012 02:49 PM, Jay Vosburgh wrote:
> >Chris Friesen<chris.friesen@genband.com> wrote:
> >
> >>In loadbalance mode wouldn't it just work similar to active-backup? If
> >>it's a reply then verify that it came from the arp target, if it's a
> >>request then check to see if it came from one of the other slaves.
> >
> > The problem isn't verifying the requests or replies, it's that
> >the ARP packets are not distributed across all slaves (because the
> >switch ports are in a channel group / aggregator), so some slaves do not
> >receive any ARPs.
>
> Yeah, okay. And if we turn on arp validation then we ignore all the
> other packets and so they looks dead. Got it.
If you wanted to make this work, I think it could pretty easily be done
if it isn't working right now. Did you try arp_validate=all in your
setup?
> In our environment (ATCA shelf) the switches have been customized to
> handle some of this stuff so arpmon does work reliably with xor.
Good.
> In the general case it sounds like the "PF bonding ignores packets
> from VFs" is a better bet then.
It really might be. There are some registers in the 82599 datasheets
that are not used by the ixgbe driver, but might help you in this area.
If you take a look at PFVML2FLT and PFUTA and their current status on
your system you might be able to put something together that gives you
what you want.
It would likely mean you have to run a custom ixgbe-driver, but that
doesn't sound like much of an issue.
>
>
> >>On 07/24/2012 02:18 PM, Chris Friesen wrote:
> >>>A more general solution might be to have the device driver also track
> >>>the time of the last incoming packet that came from the external network
> >>>(rather than a VF) and having the bond driver ignore those packets for
> >>>the purpose of link health. Doing this efficiently would likely require
> >>>some kind of hardware support though--as an example the 82599 seems to
> >>>support this with the "LB" bit in the rx descriptor.
> >>
> >>That should of course be reversed. We want the bond driver to only use
> >>the packets from the external network for the purpose of link health.
> >>
> >>Does anyone other than bonding actually care about dev->last_rx? If not
> >>then we could just change the drivers to only set it for external packets.
> >That should of course be reversed. We want the bond driver to only use
> >>the packets from the external network for the purpose of link health.
> >>
> > I believe bonding is the main user of last_rx (a search shows a
> >couple of drivers using it internally). For bonding use, in current
> >mainline last_rx is set by bonding itself, not in the network device
> >driver.
>
> Right, I was looking at older code. In that case presumably the
> driver could set an skb flag (external vs VF loopback) that the
> bonding code could check?
>
> Chris
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
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