* [PATCH] iproute2: GENL: merge GENL_REQUEST and GENL_INITIALIZER
From: Julian Anastasov @ 2012-09-12 6:15 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: netdev
Both macros are used together, so better to have
single define. Update all requests in ipl2tp.c to use the
new macro.
Signed-off-by: Julian Anastasov <ja@ssi.bg>
---
include/libgenl.h | 27 +++++++++-----------
ip/ipl2tp.c | 72 +++++++++++-----------------------------------------
lib/libgenl.c | 7 ++---
3 files changed, 31 insertions(+), 75 deletions(-)
diff --git a/include/libgenl.h b/include/libgenl.h
index 0b11a89..9db4baf 100644
--- a/include/libgenl.h
+++ b/include/libgenl.h
@@ -3,25 +3,22 @@
#include "libnetlink.h"
-#define GENL_REQUEST(_req, _hdrsiz, _bufsiz) \
+#define GENL_REQUEST(_req, _bufsiz, _family, _hdrsiz, _ver, _cmd, _flags) \
struct { \
struct nlmsghdr n; \
struct genlmsghdr g; \
char buf[NLMSG_ALIGN(_hdrsiz) + (_bufsiz)]; \
-} _req
-
-#define GENL_INITIALIZER(_family, _hdrsiz, _ver, _cmd, _flags) \
- { \
- .n = { \
- .nlmsg_type = (_family), \
- .nlmsg_flags = (_flags), \
- .nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN + (_hdrsiz)), \
- }, \
- .g = { \
- .cmd = (_cmd), \
- .version = (_ver), \
- }, \
- }
+} _req = { \
+ .n = { \
+ .nlmsg_type = (_family), \
+ .nlmsg_flags = (_flags), \
+ .nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN + (_hdrsiz)), \
+ }, \
+ .g = { \
+ .cmd = (_cmd), \
+ .version = (_ver), \
+ }, \
+}
extern int genl_resolve_family(struct rtnl_handle *grth, const char *family);
diff --git a/ip/ipl2tp.c b/ip/ipl2tp.c
index aaa3d31..f6e264a 100644
--- a/ip/ipl2tp.c
+++ b/ip/ipl2tp.c
@@ -96,9 +96,8 @@ static int create_tunnel(struct l2tp_parm *p)
uint32_t local_attr = L2TP_ATTR_IP_SADDR;
uint32_t peer_attr = L2TP_ATTR_IP_DADDR;
- GENL_REQUEST(req, 0, 1024)
- = GENL_INITIALIZER(genl_family, NLM_F_REQUEST | NLM_F_ACK, 0,
- L2TP_CMD_TUNNEL_CREATE, L2TP_GENL_VERSION);
+ GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
+ L2TP_CMD_TUNNEL_CREATE, NLM_F_REQUEST | NLM_F_ACK);
addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id);
addattr32(&req.n, 1024, L2TP_ATTR_PEER_CONN_ID, p->peer_tunnel_id);
@@ -126,9 +125,8 @@ static int create_tunnel(struct l2tp_parm *p)
static int delete_tunnel(struct l2tp_parm *p)
{
- GENL_REQUEST(req, 0, 1024)
- = GENL_INITIALIZER(genl_family, NLM_F_REQUEST | NLM_F_ACK, 0,
- L2TP_CMD_TUNNEL_DELETE, L2TP_GENL_VERSION);
+ GENL_REQUEST(req, 128, genl_family, 0, L2TP_GENL_VERSION,
+ L2TP_CMD_TUNNEL_DELETE, NLM_F_REQUEST | NLM_F_ACK);
addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->tunnel_id);
@@ -140,18 +138,8 @@ static int delete_tunnel(struct l2tp_parm *p)
static int create_session(struct l2tp_parm *p)
{
- struct {
- struct nlmsghdr n;
- struct genlmsghdr g;
- char buf[1024];
- } req;
-
- memset(&req, 0, sizeof(req));
- req.n.nlmsg_type = genl_family;
- req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
- req.g.cmd = L2TP_CMD_SESSION_CREATE;
- req.g.version = L2TP_GENL_VERSION;
+ GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
+ L2TP_CMD_SESSION_CREATE, NLM_F_REQUEST | NLM_F_ACK);
addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id);
addattr32(&req.n, 1024, L2TP_ATTR_PEER_CONN_ID, p->peer_tunnel_id);
@@ -182,18 +170,8 @@ static int create_session(struct l2tp_parm *p)
static int delete_session(struct l2tp_parm *p)
{
- struct {
- struct nlmsghdr n;
- struct genlmsghdr g;
- char buf[128];
- } req;
-
- memset(&req, 0, sizeof(req));
- req.n.nlmsg_type = genl_family;
- req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
- req.g.cmd = L2TP_CMD_SESSION_DELETE;
- req.g.version = L2TP_GENL_VERSION;
+ GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
+ L2TP_CMD_SESSION_DELETE, NLM_F_REQUEST | NLM_F_ACK);
addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->tunnel_id);
addattr32(&req.n, 1024, L2TP_ATTR_SESSION_ID, p->session_id);
@@ -380,20 +358,11 @@ static int session_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void
static int get_session(struct l2tp_data *p)
{
- struct {
- struct nlmsghdr n;
- struct genlmsghdr g;
- char buf[128];
- } req;
-
- memset(&req, 0, sizeof(req));
- req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
- req.n.nlmsg_type = genl_family;
- req.n.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
- req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq;
+ GENL_REQUEST(req, 128, genl_family, 0, L2TP_GENL_VERSION,
+ L2TP_CMD_SESSION_GET,
+ NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST);
- req.g.cmd = L2TP_CMD_SESSION_GET;
- req.g.version = L2TP_GENL_VERSION;
+ req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq;
if (p->config.tunnel_id && p->config.session_id) {
addattr32(&req.n, 128, L2TP_ATTR_CONN_ID, p->config.tunnel_id);
@@ -423,20 +392,11 @@ static int tunnel_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, void
static int get_tunnel(struct l2tp_data *p)
{
- struct {
- struct nlmsghdr n;
- struct genlmsghdr g;
- char buf[1024];
- } req;
-
- memset(&req, 0, sizeof(req));
- req.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
- req.n.nlmsg_type = genl_family;
- req.n.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
- req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq;
+ GENL_REQUEST(req, 1024, genl_family, 0, L2TP_GENL_VERSION,
+ L2TP_CMD_TUNNEL_GET,
+ NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST);
- req.g.cmd = L2TP_CMD_TUNNEL_GET;
- req.g.version = L2TP_GENL_VERSION;
+ req.n.nlmsg_seq = genl_rth.dump = ++genl_rth.seq;
if (p->config.tunnel_id)
addattr32(&req.n, 1024, L2TP_ATTR_CONN_ID, p->config.tunnel_id);
diff --git a/lib/libgenl.c b/lib/libgenl.c
index d68e58e..ef3e5db 100644
--- a/lib/libgenl.c
+++ b/lib/libgenl.c
@@ -47,11 +47,10 @@ static int genl_parse_getfamily(struct nlmsghdr *nlh)
int genl_resolve_family(struct rtnl_handle *grth, const char *family)
{
- GENL_REQUEST(req, 0, 1024)
- = GENL_INITIALIZER(GENL_ID_CTRL, 0,
- 0, CTRL_CMD_GETFAMILY, NLM_F_REQUEST);
+ GENL_REQUEST(req, 1024, GENL_ID_CTRL, 0, 0, CTRL_CMD_GETFAMILY,
+ NLM_F_REQUEST);
- addattr_l(&req.n, 1024, CTRL_ATTR_FAMILY_NAME,
+ addattr_l(&req.n, sizeof(req), CTRL_ATTR_FAMILY_NAME,
family, strlen(family) + 1);
if (rtnl_talk(grth, &req.n, 0, 0, &req.n) < 0) {
--
1.7.3.4
^ permalink raw reply related
* Re: [V3 PATCH 9/9] cxgb4vf: Chelsio FCoE offload driver submission (header compatibility fixes).
From: Naresh Kumar Inna @ 2012-09-12 6:27 UTC (permalink / raw)
To: David Miller
Cc: JBottomley@parallels.com, linux-scsi@vger.kernel.org,
Dimitrios Michailidis, Casey Leedom, netdev@vger.kernel.org,
Chethan Seshadri
In-Reply-To: <20120912.014746.636228439025755624.davem@davemloft.net>
On 9/12/2012 11:17 AM, David Miller wrote:
> From: Naresh Kumar Inna <naresh@chelsio.com>
> Date: Wed, 12 Sep 2012 11:05:22 +0530
>
>> On 9/11/2012 11:03 PM, David Miller wrote:
>>> From: Naresh Kumar Inna <naresh@chelsio.com>
>>> Date: Tue, 11 Sep 2012 20:09:07 +0530
>>>
>>>> This patch contains minor fixes to make cxgb4vf driver work with the updates to
>>>> shared firmware/hardware header files.
>>>>
>>>> Signed-off-by: Naresh Kumar Inna <naresh@chelsio.com>
>>>
>>> You cannot submit a patch set that isn't bisectable, and in particular
>>> create a situation that mid-way through your patch set things do not
>>> build or operate correctly.
>>>
>>
>> Sorry, I am new to this process. The reason I did that was because I was
>> not sure if I could create a single patch with both cxgb4 and cxgb4vf
>> files in it, since they are two different subsystems. If I could do
>> that, the single patch then would build on its own, and not be dependent
>> on the other patches in the series. Is that something I can do?
>
> I don't know how else to say this, every step along the way the tree
> has to build. You arrange the patches however necessary to achieve
> that goal.
>
OK, I think I should be able to arrange the patch set to fulfill that
requirement. I was under the impression it was fine for new drivers to
split patches in this fashion, since they go as a single commit, sorry
about that.
As for a single patch with both cxgb4 and cxgb4vf changes, I assume it
is OK for the commit log to start with "cxgb4/cxgb4vf:..."?
Thanks,
Naresh.
^ permalink raw reply
* Re: [PATCH] net_tx_action: Call trace_consume_skb() instead of trace_kfree_skb()
From: Eric Dumazet @ 2012-09-12 7:33 UTC (permalink / raw)
To: Shawn Bohrer; +Cc: netdev, sanagi.koki, davem
In-Reply-To: <1347406098-22071-1-git-send-email-sbohrer@rgmadvisors.com>
On Tue, 2012-09-11 at 18:28 -0500, Shawn Bohrer wrote:
> Call trace_consume_skb() instead of trace_kfree_skb() as skbs are
> removed from the completion_queue during transmit. This avoids false
> positives from dropwatch/drop_monitor making them more useful.
>
> Signed-off-by: Shawn Bohrer <sbohrer@rgmadvisors.com>
> ---
>
> In my case I seem to hit this tracepoint for every packet I transmit so
> these appear to be false positives to me. Perhaps there are cases where
> you could hit this and it is a real packet drop?
>
> net/core/dev.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 8398836..00774ce 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -3015,7 +3015,7 @@ static void net_tx_action(struct softirq_action *h)
> clist = clist->next;
>
> WARN_ON(atomic_read(&skb->users));
> - trace_kfree_skb(skb, net_tx_action);
> + trace_consume_skb(skb);
> __kfree_skb(skb);
> }
> }
> --
> 1.7.7.6
>
>
Problem here is : we dont know if caller of dev_kfree_skb_irq(skb)
wanted to drop or consume skb.
(We dont have a dev_consume_skb_irq(skb) function)
For example, drivers/infiniband/ulp/ipoib/ipoib_main.c function
path_free() does :
while ((skb = __skb_dequeue(&path->queue)))
dev_kfree_skb_irq(skb);
Are these packets dropped or consumed, I dont really know...
Note : NAPI drivers dont use dev_kfree_skb_irq(skb).
What is the NIC driver you are using, I thought it was mellanox (wich is
NAPI) ?
^ permalink raw reply
* Re: [PATCH net-next v3 4/4] ipv6: use DST_* macro to set obselete field
From: Eric Dumazet @ 2012-09-12 7:40 UTC (permalink / raw)
To: Nicolas Dichtel
Cc: vyasevich, davem, sds, james.l.morris, eparis, sri, linux-sctp,
netdev
In-Reply-To: <1347350987-8054-5-git-send-email-nicolas.dichtel@6wind.com>
On Tue, 2012-09-11 at 10:09 +0200, Nicolas Dichtel wrote:
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> ---
> net/ipv6/route.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> index 561f249..0c6f132 100644
> --- a/net/ipv6/route.c
> +++ b/net/ipv6/route.c
> @@ -226,7 +226,7 @@ static struct rt6_info ip6_null_entry_template = {
> .dst = {
> .__refcnt = ATOMIC_INIT(1),
> .__use = 1,
> - .obsolete = -1,
> + .obsolete = DST_OBSOLETE_FORCE_CHK,
> .error = -ENETUNREACH,
> .input = ip6_pkt_discard,
> .output = ip6_pkt_discard_out,
> @@ -246,7 +246,7 @@ static struct rt6_info ip6_prohibit_entry_template = {
> .dst = {
> .__refcnt = ATOMIC_INIT(1),
> .__use = 1,
> - .obsolete = -1,
> + .obsolete = DST_OBSOLETE_FORCE_CHK,
> .error = -EACCES,
> .input = ip6_pkt_prohibit,
> .output = ip6_pkt_prohibit_out,
> @@ -261,7 +261,7 @@ static struct rt6_info ip6_blk_hole_entry_template = {
> .dst = {
> .__refcnt = ATOMIC_INIT(1),
> .__use = 1,
> - .obsolete = -1,
> + .obsolete = DST_OBSOLETE_FORCE_CHK,
> .error = -EINVAL,
> .input = dst_discard,
> .output = dst_discard,
Acked-by: Eric Dumazet <edumazet@google.com>
^ permalink raw reply
* Re: [PATCH] ipv6: replace write lock with read lock when get route info
From: Eric Dumazet @ 2012-09-12 7:45 UTC (permalink / raw)
To: roy.qing.li; +Cc: netdev
In-Reply-To: <1347427553-17781-1-git-send-email-roy.qing.li@gmail.com>
On Wed, 2012-09-12 at 13:25 +0800, roy.qing.li@gmail.com wrote:
> From: Li RongQing <roy.qing.li@gmail.com>
>
> geting route info does not write rt->rt6i_table, so replace
> write lock with read lock
>
> Signed-off-by: Li RongQing <roy.qing.li@gmail.com>
> ---
> net/ipv6/route.c | 8 ++++----
> 1 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> index 399613b..8be1d86 100644
> --- a/net/ipv6/route.c
> +++ b/net/ipv6/route.c
> @@ -1837,7 +1837,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net,
> if (!table)
> return NULL;
>
> - write_lock_bh(&table->tb6_lock);
> + read_lock_bh(&table->tb6_lock);
> fn = fib6_locate(&table->tb6_root, prefix ,prefixlen, NULL, 0);
> if (!fn)
> goto out;
> @@ -1853,7 +1853,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net,
> break;
> }
> out:
> - write_unlock_bh(&table->tb6_lock);
> + read_unlock_bh(&table->tb6_lock);
> return rt;
> }
>
> @@ -1896,7 +1896,7 @@ struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_dev
> if (!table)
> return NULL;
>
> - write_lock_bh(&table->tb6_lock);
> + read_lock_bh(&table->tb6_lock);
> for (rt = table->tb6_root.leaf; rt; rt=rt->dst.rt6_next) {
> if (dev == rt->dst.dev &&
> ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) &&
> @@ -1905,7 +1905,7 @@ struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_dev
> }
> if (rt)
> dst_hold(&rt->dst);
> - write_unlock_bh(&table->tb6_lock);
> + read_unlock_bh(&table->tb6_lock);
> return rt;
> }
>
Why dont you also change addrconf_get_prefix_route() ?
^ permalink raw reply
* [PATCH] netfilter/iptables: Fix log-level processing
From: Joe Perches @ 2012-09-12 7:46 UTC (permalink / raw)
To: auto75914331, Bart De Schuymer, Pablo Neira Ayuso,
Patrick McHardy, Stephen Hemminger
Cc: netfilter-devel, netfilter, coreteam, bridge, netdev,
linux-kernel
In-Reply-To: <20120912045120.9E1A76F446@smtp.hushmail.com>
auto75914331@hushmail.com reports that iptables does not correctly
output the KERN_<level>.
$IPTABLES -A RULE_0_in -j LOG --log-level notice --log-prefix "DENY in: "
result with linux 3.6-rc5
Sep 12 06:37:29 xxxxx kernel: <5>DENY in: IN=eth0 OUT= MAC=.......
result with linux 3.5.3 and older:
Sep 9 10:43:01 xxxxx kernel: DENY in: IN=eth0 OUT= MAC......
commit 04d2c8c83d0
("printk: convert the format for KERN_<LEVEL> to a 2 byte pattern")
updated the syslog header style but did not update netfilter uses.
Do so.
Signed-off-by: Joe Perches <joe@perches.com>
cc: auto75914331@hushmail.com
---
net/bridge/netfilter/ebt_log.c | 4 ++--
net/netfilter/xt_LOG.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index f88ee53..cb46d2f 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -80,8 +80,8 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum,
unsigned int bitmask;
spin_lock_bh(&ebt_log_lock);
- printk("<%c>%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x",
- '0' + loginfo->u.log.level, prefix,
+ printk("%c%c%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x",
+ KERN_SOH_ASCII, '0' + loginfo->u.log.level, prefix,
in ? in->name : "", out ? out->name : "",
eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
ntohs(eth_hdr(skb)->h_proto));
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c
index ff5f75f..bdc5352 100644
--- a/net/netfilter/xt_LOG.c
+++ b/net/netfilter/xt_LOG.c
@@ -436,8 +436,8 @@ log_packet_common(struct sbuff *m,
const struct nf_loginfo *loginfo,
const char *prefix)
{
- sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
- prefix,
+ sb_add(m, "%c%c%sIN=%s OUT=%s ",
+ KERN_SOH_ASCII, '0' + loginfo->u.log.level, prefix,
in ? in->name : "",
out ? out->name : "");
#ifdef CONFIG_BRIDGE_NETFILTER
^ permalink raw reply related
* [PATCH net-next] ipv6: route templates can be const
From: Eric Dumazet @ 2012-09-12 7:47 UTC (permalink / raw)
To: David Miller; +Cc: netdev
From: Eric Dumazet <edumazet@google.com>
We kmemdup() templates, so they can be const.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/ipv6/route.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 399613b..f568ac6 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -222,7 +222,7 @@ static const u32 ip6_template_metrics[RTAX_MAX] = {
[RTAX_HOPLIMIT - 1] = 255,
};
-static struct rt6_info ip6_null_entry_template = {
+static const struct rt6_info ip6_null_entry_template = {
.dst = {
.__refcnt = ATOMIC_INIT(1),
.__use = 1,
@@ -242,7 +242,7 @@ static struct rt6_info ip6_null_entry_template = {
static int ip6_pkt_prohibit(struct sk_buff *skb);
static int ip6_pkt_prohibit_out(struct sk_buff *skb);
-static struct rt6_info ip6_prohibit_entry_template = {
+static const struct rt6_info ip6_prohibit_entry_template = {
.dst = {
.__refcnt = ATOMIC_INIT(1),
.__use = 1,
@@ -257,7 +257,7 @@ static struct rt6_info ip6_prohibit_entry_template = {
.rt6i_ref = ATOMIC_INIT(1),
};
-static struct rt6_info ip6_blk_hole_entry_template = {
+static const struct rt6_info ip6_blk_hole_entry_template = {
.dst = {
.__refcnt = ATOMIC_INIT(1),
.__use = 1,
^ permalink raw reply related
* Re: [v2 PATCH 2/2] netprio_cgroup: Use memcpy instead of the for-loop to copy priomap
From: David Miller @ 2012-09-12 7:49 UTC (permalink / raw)
To: srivatsa.bhat
Cc: nhorman, David.Laight, john.r.fastabend, gaofeng, eric.dumazet,
mark.d.rustad, lizefan, netdev, linux-kernel
In-Reply-To: <20120912060747.11037.42623.stgit@srivatsabhat.in.ibm.com>
From: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
Date: Wed, 12 Sep 2012 11:37:47 +0530
> + memcpy(new_priomap->priomap, old_priomap->priomap,
> + old_priomap->priomap_len *
> + sizeof(old_priomap->priomap[0]));
This argument indentation is ridiculous. Try:
memcpy(new_priomap->priomap, old_priomap->priomap,
old_priomap->priomap_len *
sizeof(old_priomap->priomap[0]));
Using TABs exclusively for argumentat indentation is not the goal.
Rather, lining the arguments up properly so that they sit at the first
column after the first line's openning parenthesis is what you should
be trying to achieve.
And ignoring whatever stylistic convention we may or may not have, I
find it impossibly hard to believe that the code quoted above looks
good even to you.
^ permalink raw reply
* Re: [PATCH] ipv6: replace write lock with read lock when get route info
From: RongQing Li @ 2012-09-12 7:49 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev
In-Reply-To: <1347435907.13103.693.camel@edumazet-glaptop>
>>
>
> Why dont you also change addrconf_get_prefix_route() ?
>
>
I did not find it, I will send v2
Thanks
-Roy
^ permalink raw reply
* Re: [PATCHv4] virtio-spec: virtio network device multiqueue support
From: Michael S. Tsirkin @ 2012-09-12 7:57 UTC (permalink / raw)
To: Rusty Russell
Cc: kvm, netdev, rick.jones2, virtualization, levinsasha928, pbonzini,
Tom Herbert
In-Reply-To: <87har3dc4o.fsf@rustcorp.com.au>
On Wed, Sep 12, 2012 at 03:19:11PM +0930, Rusty Russell wrote:
> Jason Wang <jasowang@redhat.com> writes:
> > On 09/10/2012 02:33 PM, Michael S. Tsirkin wrote:
> >> A final addition: what you suggest above would be
> >> "TX follows RX", right?
>
> BTW, yes. But it's a weird way to express what the nic is doing.
It explains what the system is doing.
TX is done by driver, RX by nic.
We document both driver and device in the spec
so I thought it's fine. any suggestions wellcome.
> >> It is in anticipation of something like that, that I made
> >> steering programming so generic.
>
> >> I think TX follows RX is more immediately useful for reasons above
> >> but we can add both to spec and let drivers and devices
> >> decide what they want to support.
>
> You mean "RX follows TX"? ie. accelerated RFS. I agree.
Yes that's what I meant. Thanks for the correction.
> Perhaps Tom can explain how we avoid out-of-order receive for the
> accelerated RFS case? It's not clear to me, but we need to be able to
> do that for virtio-net if it implements accelerated RFS.
Basically this has tx vq per cpu and relies on scheduler not bouncing threads
between cpus too aggressively. Appears to be what ixgbe does.
> > AFAIK, ixgbe does "rx follows tx". The only differences between ixgbe
> > and virtio-net is that ixgbe driver programs the flow director during
> > packet transmission but we suggest to do it silently in the device for
> > simplicity.
>
> Implying the receive queue by xmit will be slightly laggy. Don't know
> if that's a problem.
>
> Cheers,
> Rusty.
Doesn't seem to be a problem in Jason's testing so far.
^ permalink raw reply
* [PATCH v2] ipv6: replace write lock with read lock when get route info
From: roy.qing.li @ 2012-09-12 7:59 UTC (permalink / raw)
To: netdev
From: Li RongQing <roy.qing.li@gmail.com>
geting route info does not write rt->rt6i_table, so replace
write lock with read lock
Suggested-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Li RongQing <roy.qing.li@gmail.com>
---
net/ipv6/addrconf.c | 4 ++--
net/ipv6/route.c | 8 ++++----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 1237d5d..061c100 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1706,7 +1706,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
if (table == NULL)
return NULL;
- write_lock_bh(&table->tb6_lock);
+ read_lock_bh(&table->tb6_lock);
fn = fib6_locate(&table->tb6_root, pfx, plen, NULL, 0);
if (!fn)
goto out;
@@ -1721,7 +1721,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
break;
}
out:
- write_unlock_bh(&table->tb6_lock);
+ read_unlock_bh(&table->tb6_lock);
return rt;
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 399613b..8be1d86 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1837,7 +1837,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net,
if (!table)
return NULL;
- write_lock_bh(&table->tb6_lock);
+ read_lock_bh(&table->tb6_lock);
fn = fib6_locate(&table->tb6_root, prefix ,prefixlen, NULL, 0);
if (!fn)
goto out;
@@ -1853,7 +1853,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net,
break;
}
out:
- write_unlock_bh(&table->tb6_lock);
+ read_unlock_bh(&table->tb6_lock);
return rt;
}
@@ -1896,7 +1896,7 @@ struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_dev
if (!table)
return NULL;
- write_lock_bh(&table->tb6_lock);
+ read_lock_bh(&table->tb6_lock);
for (rt = table->tb6_root.leaf; rt; rt=rt->dst.rt6_next) {
if (dev == rt->dst.dev &&
((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) &&
@@ -1905,7 +1905,7 @@ struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_dev
}
if (rt)
dst_hold(&rt->dst);
- write_unlock_bh(&table->tb6_lock);
+ read_unlock_bh(&table->tb6_lock);
return rt;
}
--
1.7.4.1
^ permalink raw reply related
* Re: [PATCH] netfilter/iptables: Fix log-level processing
From: Eric Dumazet @ 2012-09-12 8:07 UTC (permalink / raw)
To: Joe Perches
Cc: auto75914331, netfilter, coreteam, netdev, bridge, linux-kernel,
Bart De Schuymer, netfilter-devel, Stephen Hemminger,
Patrick McHardy, Pablo Neira Ayuso
In-Reply-To: <1347435973.2456.23.camel@joe2Laptop>
On Wed, 2012-09-12 at 00:46 -0700, Joe Perches wrote:
> auto75914331@hushmail.com reports that iptables does not correctly
> output the KERN_<level>.
>
> $IPTABLES -A RULE_0_in -j LOG --log-level notice --log-prefix "DENY in: "
>
> result with linux 3.6-rc5
> Sep 12 06:37:29 xxxxx kernel: <5>DENY in: IN=eth0 OUT= MAC=.......
>
> result with linux 3.5.3 and older:
> Sep 9 10:43:01 xxxxx kernel: DENY in: IN=eth0 OUT= MAC......
>
> commit 04d2c8c83d0
> ("printk: convert the format for KERN_<LEVEL> to a 2 byte pattern")
> updated the syslog header style but did not update netfilter uses.
>
> Do so.
>
> Signed-off-by: Joe Perches <joe@perches.com>
> cc: auto75914331@hushmail.com
> ---
> net/bridge/netfilter/ebt_log.c | 4 ++--
> net/netfilter/xt_LOG.c | 4 ++--
> 2 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
> index f88ee53..cb46d2f 100644
> --- a/net/bridge/netfilter/ebt_log.c
> +++ b/net/bridge/netfilter/ebt_log.c
> @@ -80,8 +80,8 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum,
> unsigned int bitmask;
>
> spin_lock_bh(&ebt_log_lock);
> - printk("<%c>%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x",
> - '0' + loginfo->u.log.level, prefix,
> + printk("%c%c%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x",
> + KERN_SOH_ASCII, '0' + loginfo->u.log.level, prefix,
> in ? in->name : "", out ? out->name : "",
> eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
> ntohs(eth_hdr(skb)->h_proto));
> diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c
> index ff5f75f..bdc5352 100644
> --- a/net/netfilter/xt_LOG.c
> +++ b/net/netfilter/xt_LOG.c
> @@ -436,8 +436,8 @@ log_packet_common(struct sbuff *m,
> const struct nf_loginfo *loginfo,
> const char *prefix)
> {
> - sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
> - prefix,
> + sb_add(m, "%c%c%sIN=%s OUT=%s ",
> + KERN_SOH_ASCII, '0' + loginfo->u.log.level, prefix,
> in ? in->name : "",
> out ? out->name : "");
> #ifdef CONFIG_BRIDGE_NETFILTER
>
would be better to avoid the %c
->
sb_add(m, KERN_SOH "%c%sIN=%s OUT=%s ",
'0' + loginfo->u.log.level, prefix,
^ permalink raw reply
* Re: [PATCH v2] ipv6: replace write lock with read lock when get route info
From: Eric Dumazet @ 2012-09-12 8:12 UTC (permalink / raw)
To: roy.qing.li; +Cc: netdev
In-Reply-To: <1347436741-344-1-git-send-email-roy.qing.li@gmail.com>
On Wed, 2012-09-12 at 15:59 +0800, roy.qing.li@gmail.com wrote:
> From: Li RongQing <roy.qing.li@gmail.com>
>
> geting route info does not write rt->rt6i_table, so replace
> write lock with read lock
>
> Suggested-by: Eric Dumazet <edumazet@google.com>
> Signed-off-by: Li RongQing <roy.qing.li@gmail.com>
> ---
> net/ipv6/addrconf.c | 4 ++--
> net/ipv6/route.c | 8 ++++----
> 2 files changed, 6 insertions(+), 6 deletions(-)
I guess you missed the net-next tag in your [PATCH ...] ?
Signed-off-by: Eric Dumazet <edumazet@google.com>
^ permalink raw reply
* Re: [v2 PATCH 2/2] netprio_cgroup: Use memcpy instead of the for-loop to copy priomap
From: Srivatsa S. Bhat @ 2012-09-12 8:24 UTC (permalink / raw)
To: David Miller
Cc: nhorman, David.Laight, john.r.fastabend, gaofeng, eric.dumazet,
mark.d.rustad, lizefan, netdev, linux-kernel
In-Reply-To: <20120912.034901.184817520125489015.davem@davemloft.net>
On 09/12/2012 01:19 PM, David Miller wrote:
> From: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
> Date: Wed, 12 Sep 2012 11:37:47 +0530
>
>> + memcpy(new_priomap->priomap, old_priomap->priomap,
>> + old_priomap->priomap_len *
>> + sizeof(old_priomap->priomap[0]));
>
> This argument indentation is ridiculous. Try:
>
> memcpy(new_priomap->priomap, old_priomap->priomap,
> old_priomap->priomap_len *
> sizeof(old_priomap->priomap[0]));
>
> Using TABs exclusively for argumentat indentation is not the goal.
>
> Rather, lining the arguments up properly so that they sit at the first
> column after the first line's openning parenthesis is what you should
> be trying to achieve.
OK, will fix it, thanks!
>
> And ignoring whatever stylistic convention we may or may not have, I
> find it impossibly hard to believe that the code quoted above looks
> good even to you.
>
On second thoughts, I think the memcpy in this case will actually be worse
since it will copy the contents in chunks of smaller size than the for-loop.
Or, did you mean to say that this code is plain wrong for some reason?
Regards,
Srivatsa S. Bhat
^ permalink raw reply
* [RFC PATCH net-next 0/1] Add support of ECMPv6
From: Nicolas Dichtel @ 2012-09-12 8:29 UTC (permalink / raw)
To: bernat, netdev, yoshfuji, davem
In-Reply-To: <87a9x3vxzp.fsf@guybrush.luffy.cx>
Here is a proposal to add the support of ECMPv6. The previous patch
from Vincent against iproute2 can be used, but a little other patch is needed
too:
diff --git a/ip/iproute.c b/ip/iproute.c
index 2fe44b3..b71f150 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -693,8 +693,10 @@ int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r, int argc, char **argv)
rtnh = RTNH_NEXT(rtnh);
}
- if (rta->rta_len > RTA_LENGTH(0))
+ if (rta->rta_len > RTA_LENGTH(0)) {
addattr_l(n, 1024, RTA_MULTIPATH, RTA_DATA(rta), RTA_PAYLOAD(rta));
+ n->nlmsg_flags &= ~NLM_F_EXCL;
+ }
return 0;
}
If the kernel patch is approved, I will submit formally the patch for
iproute2.
Here is an example of a command to add an ECMP route:
$ ip -6 route add 3ffe:304:124:2306::/64 \
nexthop via fe80::230:1bff:feb4:e05c dev eth0 weight 1 \
nexthop via fe80::230:1bff:feb4:dd4f dev eth0 weight 1
Comments are welcome.
Regards,
Nicolas
^ permalink raw reply related
* [RFC PATCH net-next 1/1] ipv6: add support of ECMP
From: Nicolas Dichtel @ 2012-09-12 8:29 UTC (permalink / raw)
To: bernat, netdev, yoshfuji, davem; +Cc: Nicolas Dichtel
In-Reply-To: <1347438597-4233-1-git-send-email-nicolas.dichtel@6wind.com>
This patch adds the support of equal cost multipath for IPv6.
The patch is based on a previous work from
Luc Saillard <luc.saillard@6wind.com>.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
include/net/ip6_fib.h | 13 ++++
net/ipv6/Kconfig | 32 ++++++++
net/ipv6/ip6_fib.c | 73 ++++++++++++++++++
net/ipv6/route.c | 207 +++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 322 insertions(+), 3 deletions(-)
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index cd64cf3..8071c66 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -47,6 +47,10 @@ struct fib6_config {
unsigned long fc_expires;
struct nlattr *fc_mx;
int fc_mx_len;
+#ifdef CONFIG_IPV6_MULTIPATH
+ struct nlattr *fc_mp;
+ int fc_mp_len;
+#endif
struct nl_info fc_nlinfo;
};
@@ -98,6 +102,15 @@ struct rt6_info {
struct fib6_node *rt6i_node;
struct in6_addr rt6i_gateway;
+#ifdef CONFIG_IPV6_MULTIPATH
+ /*
+ * siblings is a list of rt6_info that have the the same metric/weight,
+ * destination, but not the same gateway. nsiblings is just a cache
+ * to speed up lookup.
+ */
+ unsigned int rt6i_nsiblings;
+ struct list_head rt6i_siblings;
+#endif
atomic_t rt6i_ref;
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 4f7fe72..5980aec 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -266,4 +266,36 @@ config IPV6_PIMSM_V2
Support for IPv6 PIM multicast routing protocol PIM-SMv2.
If unsure, say N.
+config IPV6_MULTIPATH
+ bool "IPv6: equal cost multipath for IPv6 routing"
+ depends on IPV6
+ default y
+ ---help---
+ Enable this option to support ECMP for IPv6.
+ If unsure, say N.
+
+choice
+ prompt "IPv6: choose Multipath algorithm"
+ depends on IPV6_MULTIPATH
+ default IPV6_MULTIPATH_ROUTE
+ ---help---
+ Define the method to select route between each possible path.
+
+ config IPV6_MULTIPATH_ROUTE
+ bool "IPv6: MULTIPATH flow algorithm"
+ ---help---
+ Multipath routes are chosen according to hash of packet header to
+ ensure a flow keeps the same route.
+
+ config IPV6_MULTIPATH_RR
+ bool "IPv6: MULTIPATH round robin algorithm"
+ ---help---
+ Multipath routes are chosen according to Round Robin.
+
+ config IPV6_MULTIPATH_RANDOM
+ bool "IPv6: MULTIPATH random algorithm"
+ ---help---
+ Multipath routes are chosen in a random fashion.
+endchoice
+
endif # IPV6
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 13690d6..3541e44 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -672,6 +672,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
iter->rt6i_idev == rt->rt6i_idev &&
ipv6_addr_equal(&iter->rt6i_gateway,
&rt->rt6i_gateway)) {
+#ifdef CONFIG_IPV6_MULTIPATH
+ if (rt->rt6i_nsiblings)
+ rt->rt6i_nsiblings = 0;
+#endif
if (!(iter->rt6i_flags & RTF_EXPIRES))
return -EEXIST;
if (!(rt->rt6i_flags & RTF_EXPIRES))
@@ -680,6 +684,23 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
rt6_set_expires(iter, rt->dst.expires);
return -EEXIST;
}
+#ifdef CONFIG_IPV6_MULTIPATH
+ /* If we have the same destination and the same metric,
+ * but not the same gateway, then the route we try to
+ * add is sibling to this route, increment our counter
+ * of siblings, and later we will add our route to the
+ * list.
+ * Only static routes (which don't have flag
+ * RTF_EXPIRES) are used for ECMPv6.
+ *
+ * To avoid long list, we only had siblings if the
+ * route have a gateway.
+ */
+ if (rt->rt6i_flags & RTF_GATEWAY &&
+ !(rt->rt6i_flags & RTF_EXPIRES) &&
+ !(iter->rt6i_flags & RTF_EXPIRES))
+ rt->rt6i_nsiblings++;
+#endif
}
if (iter->rt6i_metric > rt->rt6i_metric)
@@ -692,6 +713,43 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
if (ins == &fn->leaf)
fn->rr_ptr = NULL;
+#ifdef CONFIG_IPV6_MULTIPATH
+ /* Link this route to others same route. */
+ if (rt->rt6i_nsiblings) {
+ unsigned int rt6i_nsiblings;
+ struct rt6_info *sibling, *temp_sibling;
+
+ /* Find the first route that have the same metric */
+ sibling = fn->leaf;
+ while (sibling) {
+ if (sibling->rt6i_metric == rt->rt6i_metric) {
+ list_add_tail(&rt->rt6i_siblings,
+ &sibling->rt6i_siblings);
+ break;
+ }
+ sibling = sibling->dst.rt6_next;
+ }
+ /* For each sibling in the list, increment the counter of
+ * siblings. We can check if all the counter are equal.
+ */
+ rt6i_nsiblings = 0;
+ list_for_each_entry_safe(sibling, temp_sibling,
+ &rt->rt6i_siblings,
+ rt6i_siblings) {
+ sibling->rt6i_nsiblings++;
+ if (unlikely(sibling->rt6i_nsiblings !=
+ rt->rt6i_nsiblings)) {
+ pr_err("Wrong number of siblings for route %p (%d)\n",
+ sibling, sibling->rt6i_nsiblings);
+ }
+ rt6i_nsiblings++;
+ }
+ if (unlikely(rt6i_nsiblings != rt->rt6i_nsiblings)) {
+ pr_err("Wrong number of siblings for route %p. I have %d routes, but count %d siblings\n",
+ rt, rt6i_nsiblings, rt->rt6i_nsiblings);
+ }
+ }
+#endif
/*
* insert node
*/
@@ -1197,6 +1255,21 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
if (fn->rr_ptr == rt)
fn->rr_ptr = NULL;
+#ifdef CONFIG_IPV6_MULTIPATH
+ /* Remove this entry from other siblings */
+ if (rt->rt6i_nsiblings) {
+ struct rt6_info *sibling, *next_sibling;
+
+ /* For each siblings, decrement the counter of siblings */
+ list_for_each_entry_safe(sibling, next_sibling,
+ &rt->rt6i_siblings, rt6i_siblings) {
+ sibling->rt6i_nsiblings--;
+ }
+ rt->rt6i_nsiblings = 0;
+ list_del_init(&rt->rt6i_siblings);
+ }
+#endif
+
/* Adjust walkers */
read_lock(&fib6_walker_lock);
FOR_WALKERS(w) {
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 399613b..563d671 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -57,6 +57,9 @@
#include <net/xfrm.h>
#include <net/netevent.h>
#include <net/netlink.h>
+#ifdef CONFIG_IPV6_MULTIPATH
+#include <net/nexthop.h>
+#endif
#include <asm/uaccess.h>
@@ -288,6 +291,10 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
+#ifdef CONFIG_IPV6_MULTIPATH
+ INIT_LIST_HEAD(&rt->rt6i_siblings);
+ rt->rt6i_nsiblings = 0;
+#endif
}
return rt;
}
@@ -388,6 +395,122 @@ static bool rt6_need_strict(const struct in6_addr *daddr)
(IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
}
+#ifdef CONFIG_IPV6_MULTIPATH
+/*
+ * Multipath route selection.
+ */
+
+#ifdef CONFIG_IPV6_MULTIPATH_RANDOM
+/*
+ * Pseudo random candidate function
+ */
+static int rt6_info_hash_randomfn(unsigned int candidate_count)
+{
+ return random32() % candidate_count;
+}
+#endif
+
+#ifdef CONFIG_IPV6_MULTIPATH_RR
+/*
+ * Fake Round Robin candidate function
+ * If we want real RR, we need to add a counter in each route
+ */
+static int rt6_info_hash_falserr(unsigned int candidate_count)
+{
+ static unsigned int seed;
+ seed++;
+ return seed % candidate_count;
+}
+#endif
+
+#ifdef CONFIG_IPV6_MULTIPATH_ROUTE
+/*
+ * Pseudo random candidate using the src port, and other information
+ * Adapted from fib_info_hashfn()
+ */
+static int rt6_info_hash_nhsfn(unsigned int candidate_count,
+ const struct flowi6 *fl6)
+{
+ unsigned int val = fl6->flowi6_proto;
+
+ val ^= fl6->daddr.s6_addr32[0];
+ val ^= fl6->daddr.s6_addr32[1];
+ val ^= fl6->daddr.s6_addr32[2];
+ val ^= fl6->daddr.s6_addr32[3];
+
+ val ^= fl6->saddr.s6_addr32[0];
+ val ^= fl6->saddr.s6_addr32[1];
+ val ^= fl6->saddr.s6_addr32[2];
+ val ^= fl6->saddr.s6_addr32[3];
+
+ /* Work only if this not encapsulated */
+ switch (fl6->flowi6_proto) {
+ case IPPROTO_UDP:
+ case IPPROTO_TCP:
+ case IPPROTO_SCTP:
+ val ^= fl6->fl6_sport;
+ val ^= fl6->fl6_dport;
+ break;
+
+ case IPPROTO_ICMPV6:
+ val ^= fl6->fl6_icmp_type;
+ val ^= fl6->fl6_icmp_code;
+ break;
+ }
+
+ /* Perhaps, we need to tune, this function? */
+ val = val ^ (val >> 7) ^ (val >> 12);
+ return val % candidate_count;
+}
+#endif
+
+/*
+ * This function return an index used to select (at random, round robin, ...)
+ * a route between any siblings.
+ *
+ * Note: fl6 can be NULL
+ */
+static unsigned int rt6_info_hashfn(const struct rt6_info *rt,
+ const struct flowi6 *fl6)
+{
+ int candidate_count = rt->rt6i_nsiblings + 1;
+
+#if defined(CONFIG_IPV6_MULTIPATH_RR)
+ return rt6_info_hash_falserr(candidate_count);
+#elif defined(CONFIG_IPV6_MULTIPATH_RANDOM)
+ return rt6_info_hash_randomfn(candidate_count);
+#elif defined(CONFIG_IPV6_MULTIPATH_ROUTE)
+ if (fl6 == NULL)
+ return 0;
+ return rt6_info_hash_nhsfn(candidate_count, fl6);
+#else
+ return 0;
+#endif
+}
+
+static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
+ struct flowi6 *fl6)
+{
+ struct rt6_info *sibling, *next_sibling;
+ int route_choosen;
+
+ route_choosen = rt6_info_hashfn(match, fl6);
+ /* Don't change the route, if route_choosen == 0
+ * (siblings does not include ourself)
+ */
+ if (route_choosen)
+ list_for_each_entry_safe(sibling, next_sibling,
+ &match->rt6i_siblings, rt6i_siblings) {
+ route_choosen--;
+ if (route_choosen == 0) {
+ match = sibling;
+ break;
+ }
+ }
+ return match;
+}
+#endif /* CONFIG_IPV6_MULTIPATH */
+
/*
* Route lookup. Any table->tb6_lock is implied.
*/
@@ -705,6 +828,10 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
restart:
rt = fn->leaf;
rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags);
+#ifdef CONFIG_IPV6_MULTIPATH
+ if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0)
+ rt = rt6_multipath_select(rt, fl6);
+#endif
BACKTRACK(net, &fl6->saddr);
out:
dst_use(&rt->dst, jiffies);
@@ -866,7 +993,10 @@ restart_2:
restart:
rt = rt6_select(fn, oif, strict | reachable);
-
+#ifdef CONFIG_IPV6_MULTIPATH
+ if (rt->rt6i_nsiblings && oif == 0)
+ rt = rt6_multipath_select(rt, fl6);
+#endif
BACKTRACK(net, &fl6->saddr);
if (rt == net->ipv6.ip6_null_entry ||
rt->rt6i_flags & RTF_CACHE)
@@ -2247,6 +2377,9 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
[RTA_IIF] = { .type = NLA_U32 },
[RTA_PRIORITY] = { .type = NLA_U32 },
[RTA_METRICS] = { .type = NLA_NESTED },
+#ifdef CONFIG_IPV6_MULTIPATH
+ [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) },
+#endif
};
static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -2324,11 +2457,69 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
if (tb[RTA_TABLE])
cfg->fc_table = nla_get_u32(tb[RTA_TABLE]);
+#ifdef CONFIG_IPV6_MULTIPATH
+ if (tb[RTA_MULTIPATH]) {
+ cfg->fc_mp = nla_data(tb[RTA_MULTIPATH]);
+ cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]);
+ }
+#endif
+
err = 0;
errout:
return err;
}
+#ifdef CONFIG_IPV6_MULTIPATH
+static int ip6_route_multipath(struct fib6_config *cfg, int add)
+{
+ struct fib6_config r_cfg;
+ struct rtnexthop *rtnh;
+ int remaining;
+ int attrlen;
+ int err = 0, last_err = 0;
+
+beginning:
+ rtnh = (struct rtnexthop *)cfg->fc_mp;
+ remaining = cfg->fc_mp_len;
+
+ /* Parse a Multipath Entry */
+ while (rtnh_ok(rtnh, remaining)) {
+ memcpy(&r_cfg, cfg, sizeof(*cfg));
+ if (rtnh->rtnh_ifindex)
+ r_cfg.fc_ifindex = rtnh->rtnh_ifindex;
+
+ attrlen = rtnh_attrlen(rtnh);
+ if (attrlen > 0) {
+ struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
+
+ nla = nla_find(attrs, attrlen, RTA_GATEWAY);
+ if (nla) {
+ nla_memcpy(&r_cfg.fc_gateway, nla, 16);
+ r_cfg.fc_flags |= RTF_GATEWAY;
+ }
+ }
+ err = add ? ip6_route_add(&r_cfg) : ip6_route_del(&r_cfg);
+ if (err) {
+ last_err = err;
+ /* If we are trying to remove a route, do not stop the
+ * loop when ip6_route_del() fails (because next hop is
+ * already gone), we should try to remove all next hops.
+ */
+ if (add) {
+ /* If add fails, we should try to delete all
+ * next hops that have been already added.
+ */
+ add = 0;
+ goto beginning;
+ }
+ }
+ rtnh = rtnh_next(rtnh, &remaining);
+ }
+
+ return last_err;
+}
+#endif /* CONFIG_IPV6_MULTIPATH */
+
static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
{
struct fib6_config cfg;
@@ -2338,7 +2529,12 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
if (err < 0)
return err;
- return ip6_route_del(&cfg);
+#ifdef CONFIG_IPV6_MULTIPATH
+ if (cfg.fc_mp)
+ return ip6_route_multipath(&cfg, 0);
+ else
+#endif
+ return ip6_route_del(&cfg);
}
static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
@@ -2350,7 +2546,12 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
if (err < 0)
return err;
- return ip6_route_add(&cfg);
+#ifdef CONFIG_IPV6_MULTIPATH
+ if (cfg.fc_mp)
+ return ip6_route_multipath(&cfg, 1);
+ else
+#endif
+ return ip6_route_add(&cfg);
}
static inline size_t rt6_nlmsg_size(void)
--
1.7.12
^ permalink raw reply related
* Re: [PATCH NEXT] rtlwifi: rtl8192c: rtl8192ce: Add support for B-CUT version of RTL8188CE
From: Anisse Astier @ 2012-09-12 8:37 UTC (permalink / raw)
To: Larry Finger
Cc: linville-2XuSBdqkA4R54TAoqtyWWQ,
linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA, Li Chaoming
In-Reply-To: <1347393962-7661-1-git-send-email-Larry.Finger-tQ5ms3gMjBLk1uMJSBkQmQ@public.gmane.org>
On Tue, 11 Sep 2012 15:06:02 -0500, Larry Finger <Larry.Finger-tQ5ms3gMjBLk1uMJSBkQmQ@public.gmane.org> wrote :
> Realtek devices with designation RTL8188CE-VL have the so-called B-cut
> of the wireless chip. This patch adds the special programming needed by
> these devices.
>
> Signed-off-by: Larry Finger <Larry.Finger-tQ5ms3gMjBLk1uMJSBkQmQ@public.gmane.org>
> Cc: Anisse Astier <anisse-fwwRqrJYcP2HXe+LvDLADg@public.gmane.org>
> Cc: Li Chaoming <chaoming_li-kXabqFNEczNtrwSWzY7KCg@public.gmane.org>
Tested-by: Anisse Astier <anisse-fwwRqrJYcP2HXe+LvDLADg@public.gmane.org>
Fixes both problems I reported:
- kernel freezing/lockup when fwlps=1 (default)
- card not working, then freeze, even if fwlps=0.
> ---
> drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c | 21 +++++++
> drivers/net/wireless/rtlwifi/rtl8192ce/def.h | 3 +
> drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | 61 ++++++++++++++++++--
> drivers/net/wireless/rtlwifi/rtl8192ce/phy.c | 4 +-
> drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 6 +-
> drivers/net/wireless/rtlwifi/rtl8192ce/trx.c | 4 +-
> 6 files changed, 87 insertions(+), 12 deletions(-)
> ---
>
> John,
>
> This patch has the patch entitled "rtlwifi: rtl8192ce: Log message that
> B_CUT device may not work" as a pre-requisite. Unlike the previous patch,
> this one is too invasive to backport to the stable kernels, thus it should
> be applied to 3.7.
>
> Thanks,
>
> Larry
> ---
>
[snip]
> diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
> index 86d73b3..bae5269 100644
> --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
> +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
> @@ -896,7 +896,6 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
> struct rtl_phy *rtlphy = &(rtlpriv->phy);
> struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
> struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
> - static bool iqk_initialized; /* initialized to false */
> bool rtstatus = true;
> bool is92c;
> int err;
> @@ -921,9 +920,28 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
>
> rtlhal->last_hmeboxnum = 0;
> rtl92c_phy_mac_config(hw);
> + /* because last function modify RCR, so we update
> + * rcr var here, or TP will unstable for receive_config
> + * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx
> + * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252*/
> + rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR);
> + rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV);
> + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
> rtl92c_phy_bb_config(hw);
> rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
> rtl92c_phy_rf_config(hw);
> + if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
> + !IS_92C_SERIAL(rtlhal->version)) {
> + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255);
> + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00);
> + } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
> + rtl_set_rfreg(hw, RF90_PATH_A, 0x0C, MASKDWORD, 0x894AE);
> + rtl_set_rfreg(hw, RF90_PATH_A, 0x0A, MASKDWORD, 0x1AF31);
> + rtl_set_rfreg(hw, RF90_PATH_A, RF_IPA, MASKDWORD, 0x8F425);
> + rtl_set_rfreg(hw, RF90_PATH_A, RF_SYN_G2, MASKDWORD, 0x4F200);
> + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK1, MASKDWORD, 0x44053);
> + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK2, MASKDWORD, 0x80201);
> + }
> rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
> RF_CHNLBW, RFREG_OFFSET_MASK);
> rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1,
> @@ -945,11 +963,11 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw)
>
> if (ppsc->rfpwr_state == ERFON) {
> rtl92c_phy_set_rfpath_switch(hw, 1);
> - if (iqk_initialized) {
> + if (rtlphy->iqk_initialized) {
> rtl92c_phy_iq_calibrate(hw, true);
> } else {
> rtl92c_phy_iq_calibrate(hw, false);
> - iqk_initialized = true;
> + rtlphy->iqk_initialized = true;
> }
>
> rtl92c_dm_check_txpower_tracking(hw);
> @@ -1004,6 +1022,13 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw)
> ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) |
> CHIP_VENDOR_UMC));
> }
> + if (IS_92C_SERIAL(version)) {
> + value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM);
> + version = (enum version_8192c)(version |
> + ((CHIP_BONDING_IDENTIFIER(value32)
> + == CHIP_BONDING_92C_1T2R) ?
> + RF_TYPE_1T2R : 0));
> + }
> }
>
> switch (version) {
> @@ -1019,12 +1044,30 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw)
> case VERSION_A_CHIP_88C:
> versionid = "A_CHIP_88C";
> break;
> + case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT:
> + versionid = "A_CUT_92C_1T2R";
> + break;
> + case VERSION_NORMAL_UMC_CHIP_92C_A_CUT:
> + versionid = "A_CUT_92C";
> + break;
> + case VERSION_NORMAL_UMC_CHIP_88C_A_CUT:
> + versionid = "A_CUT_88C";
> + break;
> + case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT:
> + versionid = "B_CUT_92C_1T2R";
> + break;
> + case VERSION_NORMAL_UMC_CHIP_92C_B_CUT:
> + versionid = "B_CUT_92C";
> + break;
> + case VERSION_NORMAL_UMC_CHIP_88C_B_CUT:
> + versionid = "B_CUT_88C";
> + break;
> default:
> versionid = "Unknown. Bug?";
> break;
> }
>
> - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
> + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
> "Chip Version ID: %s\n", versionid);
>
> switch (version & 0x3) {
> @@ -1197,6 +1240,7 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
> {
> struct rtl_priv *rtlpriv = rtl_priv(hw);
> struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
> + struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
> u8 u1b_tmp;
> u32 u4b_tmp;
>
> @@ -1225,7 +1269,8 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
> rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790);
> rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080);
> rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80);
> - rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
> + if (!IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
> + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
> if (rtlpcipriv->bt_coexist.bt_coexistence) {
> u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL);
> u4b_tmp |= 0x03824800;
> @@ -1254,6 +1299,9 @@ void rtl92ce_card_disable(struct ieee80211_hw *hw)
> rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
> RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
> _rtl92ce_poweroff_adapter(hw);
> +
> + /* after power off we should do iqk again */
> + rtlpriv->phy.iqk_initialized = false;
> }
>
> void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw,
> @@ -1912,6 +1960,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw,
> ratr_bitmap &= 0x0f0ff0ff;
> break;
> }
> + sta_entry->ratr_index = ratr_index;
> +
> RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
> "ratr_bitmap :%x\n", ratr_bitmap);
> *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) |
> @@ -2291,3 +2341,4 @@ void rtl92ce_suspend(struct ieee80211_hw *hw)
> void rtl92ce_resume(struct ieee80211_hw *hw)
> {
> }
> +
Whitespace.
Reviewed-by: Anisse Astier <anisse-fwwRqrJYcP2HXe+LvDLADg@public.gmane.org>
Regards,
Anisse
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [RFC PATCH net-next 1/1] ipv6: add support of ECMP
From: YOSHIFUJI Hideaki @ 2012-09-12 8:48 UTC (permalink / raw)
To: Nicolas Dichtel; +Cc: bernat, netdev, davem, YOSHIFUJI Hideaki
In-Reply-To: <1347438597-4233-2-git-send-email-nicolas.dichtel@6wind.com>
Hello.
Nicolas Dichtel wrote:
> This patch adds the support of equal cost multipath for IPv6.
>
> The patch is based on a previous work from
> Luc Saillard <luc.saillard@6wind.com>.
>
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
:
> +config IPV6_MULTIPATH
> + bool "IPv6: equal cost multipath for IPv6 routing"
> + depends on IPV6
> + default y
> + ---help---
> + Enable this option to support ECMP for IPv6.
> + If unsure, say N.
> +
> +choice
> + prompt "IPv6: choose Multipath algorithm"
> + depends on IPV6_MULTIPATH
> + default IPV6_MULTIPATH_ROUTE
> + ---help---
> + Define the method to select route between each possible path.
> +
> + config IPV6_MULTIPATH_ROUTE
> + bool "IPv6: MULTIPATH flow algorithm"
> + ---help---
> + Multipath routes are chosen according to hash of packet header to
> + ensure a flow keeps the same route.
> +
> + config IPV6_MULTIPATH_RR
> + bool "IPv6: MULTIPATH round robin algorithm"
> + ---help---
> + Multipath routes are chosen according to Round Robin.
> +
> + config IPV6_MULTIPATH_RANDOM
> + bool "IPv6: MULTIPATH random algorithm"
> + ---help---
> + Multipath routes are chosen in a random fashion.
> +endchoice
We should use hash-based algorithm by default,
according to RFC4311. See also RFC6438.
Regards,
--yoshfuji
^ permalink raw reply
* Re: GRO aggregation
From: Shlomo Pongartz @ 2012-09-12 9:23 UTC (permalink / raw)
To: Eric Dumazet; +Cc: netdev@vger.kernel.org
In-Reply-To: <1347392132.13103.663.camel@edumazet-glaptop>
On 9/11/2012 10:35 PM, Eric Dumazet wrote:
> On Tue, 2012-09-11 at 19:24 +0000, Shlomo Pongratz wrote:
>
>> I see that in ixgbe the weight for the NAPI is 64 (netif_napi_add). So
>> if packets are arriving in high rate then an the CPU is fast enough to
>> collect the packets as they arrive, assuming packets continue to
>> arrives while the NAPI runs. Then it should have aggregate more. So we
>> will have less passes trough the stack.
>>
> As I said, _if_ your cpu was loaded by other stuff, then you would see
> biggest GRO packets.
>
> GRO is not : "We want to kill latency and have big packets just because
> its better"
>
> Its more like : If load is big enough, try to aggregate TCP frames in
> less skbs.
>
>
>
>
First I want to apologize for breaking the mailing thread. I wasn't at
work and used webmail.
I agree with your but I think that something is still strange.
On the transmitter side all the offloading are enabled, e.g. TSO and GSO.
The tcpdump on the sender side shows size of 64240 which is 44 packets
of 1460 each.
Now since the offloading are enabled the HW should transmit 44 frames
back to back,
that is in a burst of 44 * 1500 bytes, which according to my calculation
should take 52.8 micro on 10G Ethernet.
Using ethtool I've set the rx-usecs to 1022 micro, which I think is the
maximal value for ixgbe.
Note that there is no way to set rx-frames on ixgbe.
Now since the ixgbe weight is 64 I expected that the NAPI will be able
to poll for more then 21 packets,
since 44 packets came in one burst.
However the results remains the same.
Shlomo.
^ permalink raw reply
* Re: GRO aggregation
From: Eric Dumazet @ 2012-09-12 9:33 UTC (permalink / raw)
To: Shlomo Pongartz; +Cc: netdev@vger.kernel.org
In-Reply-To: <505054AE.9040901@mellanox.com>
On Wed, 2012-09-12 at 12:23 +0300, Shlomo Pongartz wrote:
> On 9/11/2012 10:35 PM, Eric Dumazet wrote:
> > On Tue, 2012-09-11 at 19:24 +0000, Shlomo Pongratz wrote:
> >
> >> I see that in ixgbe the weight for the NAPI is 64 (netif_napi_add). So
> >> if packets are arriving in high rate then an the CPU is fast enough to
> >> collect the packets as they arrive, assuming packets continue to
> >> arrives while the NAPI runs. Then it should have aggregate more. So we
> >> will have less passes trough the stack.
> >>
> > As I said, _if_ your cpu was loaded by other stuff, then you would see
> > biggest GRO packets.
> >
> > GRO is not : "We want to kill latency and have big packets just because
> > its better"
> >
> > Its more like : If load is big enough, try to aggregate TCP frames in
> > less skbs.
> >
> >
> >
> >
> First I want to apologize for breaking the mailing thread. I wasn't at
> work and used webmail.
>
> I agree with your but I think that something is still strange.
> On the transmitter side all the offloading are enabled, e.g. TSO and GSO.
> The tcpdump on the sender side shows size of 64240 which is 44 packets
> of 1460 each.
> Now since the offloading are enabled the HW should transmit 44 frames
> back to back,
> that is in a burst of 44 * 1500 bytes, which according to my calculation
> should take 52.8 micro on 10G Ethernet.
> Using ethtool I've set the rx-usecs to 1022 micro, which I think is the
> maximal value for ixgbe.
> Note that there is no way to set rx-frames on ixgbe.
> Now since the ixgbe weight is 64 I expected that the NAPI will be able
> to poll for more then 21 packets,
> since 44 packets came in one burst.
> However the results remains the same.
TSO uses PAGE frags, so 64KB needs about 16 pages.
tcp_sendmsg() could even use order-3 pages, so that only 2 pages would
be needed to fill 64KB of data.
GRO uses whatever fragment size provided by NIC, depending on MTU.
One skb has a limit on number of frags.
Handling a huge array of frags would be actually slower in some helper
functions.
Since you dont exactly describe why you ask all these questions, its
hard to guess what problem you try to solve.
^ permalink raw reply
* Re: [RFC PATCH net-next 1/1] ipv6: add support of ECMP
From: YOSHIFUJI Hideaki @ 2012-09-12 9:42 UTC (permalink / raw)
To: Nicolas Dichtel; +Cc: YOSHIFUJI Hideaki, bernat, netdev, davem
In-Reply-To: <50504C72.1090500@linux-ipv6.org>
Hello.
YOSHIFUJI Hideaki wrote:
> Hello.
>
> Nicolas Dichtel wrote:
>> This patch adds the support of equal cost multipath for IPv6.
>>
>> The patch is based on a previous work from
>> Luc Saillard <luc.saillard@6wind.com>.
>>
>> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> :
>> +config IPV6_MULTIPATH
>> + bool "IPv6: equal cost multipath for IPv6 routing"
>> + depends on IPV6
>> + default y
>> + ---help---
>> + Enable this option to support ECMP for IPv6.
>> + If unsure, say N.
>> +
>> +choice
>> + prompt "IPv6: choose Multipath algorithm"
>> + depends on IPV6_MULTIPATH
>> + default IPV6_MULTIPATH_ROUTE
>> + ---help---
>> + Define the method to select route between each possible path.
>> +
>> + config IPV6_MULTIPATH_ROUTE
>> + bool "IPv6: MULTIPATH flow algorithm"
>> + ---help---
>> + Multipath routes are chosen according to hash of packet header to
>> + ensure a flow keeps the same route.
>> +
>> + config IPV6_MULTIPATH_RR
>> + bool "IPv6: MULTIPATH round robin algorithm"
>> + ---help---
>> + Multipath routes are chosen according to Round Robin.
>> +
>> + config IPV6_MULTIPATH_RANDOM
>> + bool "IPv6: MULTIPATH random algorithm"
>> + ---help---
>> + Multipath routes are chosen in a random fashion.
>> +endchoice
>
> We should use hash-based algorithm by default,
> according to RFC4311. See also RFC6438.
Sorry, I missed something and misunderstood.
I prefer "HASH" of "FLOW" instead of "ROUTE"
because it select route by "hash" or "flow"
(as other options mean; by "round-robin"(RR) or by "random"(RANDOM)).
And, please clearly specify that it is the recommended
the default and recommended algorithm.
(We may have references to RFCs.)
Default is "y" but description says "if unsure, say N."
This is not good.
Of course, we may want to take "flow label" into account
when calculating hash (RFC6438).
Regards,
-----
[*] IPv6: equal cost multipath for IPv6 routing
Enable this option to support ECMP for IPv6.
[*] IPv6: MULTIPATH hash-based algorithm
Multipath routes are chosen according to hash of packet
header information (source, destination, ...)
to ensure a flow keeps the same route.
This is the default and recommended.
[ ] IPv6: MULTIPATH round-robin algorithm
[ ] IPv6: MULTIPATH random algorithm
--yoshfuji
^ permalink raw reply
* Re: [RFC PATCH net-next 1/1] ipv6: add support of ECMP
From: Nicolas Dichtel @ 2012-09-12 9:53 UTC (permalink / raw)
To: YOSHIFUJI Hideaki; +Cc: bernat, netdev, davem
In-Reply-To: <505058F5.9020707@linux-ipv6.org>
Le 12/09/2012 11:42, YOSHIFUJI Hideaki a écrit :
> Hello.
>
> YOSHIFUJI Hideaki wrote:
>> Hello.
>>
>> Nicolas Dichtel wrote:
>>> This patch adds the support of equal cost multipath for IPv6.
>>>
>>> The patch is based on a previous work from
>>> Luc Saillard <luc.saillard@6wind.com>.
>>>
>>> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
>> :
>>> +config IPV6_MULTIPATH
>>> + bool "IPv6: equal cost multipath for IPv6 routing"
>>> + depends on IPV6
>>> + default y
>>> + ---help---
>>> + Enable this option to support ECMP for IPv6.
>>> + If unsure, say N.
>>> +
>>> +choice
>>> + prompt "IPv6: choose Multipath algorithm"
>>> + depends on IPV6_MULTIPATH
>>> + default IPV6_MULTIPATH_ROUTE
>>> + ---help---
>>> + Define the method to select route between each possible path.
>>> +
>>> + config IPV6_MULTIPATH_ROUTE
>>> + bool "IPv6: MULTIPATH flow algorithm"
>>> + ---help---
>>> + Multipath routes are chosen according to hash of packet header to
>>> + ensure a flow keeps the same route.
>>> +
>>> + config IPV6_MULTIPATH_RR
>>> + bool "IPv6: MULTIPATH round robin algorithm"
>>> + ---help---
>>> + Multipath routes are chosen according to Round Robin.
>>> +
>>> + config IPV6_MULTIPATH_RANDOM
>>> + bool "IPv6: MULTIPATH random algorithm"
>>> + ---help---
>>> + Multipath routes are chosen in a random fashion.
>>> +endchoice
>>
>> We should use hash-based algorithm by default,
>> according to RFC4311. See also RFC6438.
>
> Sorry, I missed something and misunderstood.
>
>
> I prefer "HASH" of "FLOW" instead of "ROUTE"
> because it select route by "hash" or "flow"
> (as other options mean; by "round-robin"(RR) or by "random"(RANDOM)).
Ok.
>
> And, please clearly specify that it is the recommended
> the default and recommended algorithm.
> (We may have references to RFCs.)
Ok.
>
> Default is "y" but description says "if unsure, say N."
> This is not good.
Yes, good catch.
>
>
> Of course, we may want to take "flow label" into account
> when calculating hash (RFC6438).
Ok, I will add it. I wait for others comments.
Regards,
Nicolas
^ permalink raw reply
* Re: [v2 PATCH 2/2] netprio_cgroup: Use memcpy instead of the for-loop to copy priomap
From: Srivatsa S. Bhat @ 2012-09-12 10:23 UTC (permalink / raw)
To: David Miller
Cc: nhorman, David.Laight, john.r.fastabend, gaofeng, eric.dumazet,
mark.d.rustad, lizefan, netdev, linux-kernel
In-Reply-To: <505046A5.1050009@linux.vnet.ibm.com>
On 09/12/2012 01:54 PM, Srivatsa S. Bhat wrote:
> On 09/12/2012 01:19 PM, David Miller wrote:
>> From: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
>> Date: Wed, 12 Sep 2012 11:37:47 +0530
>>
>>> + memcpy(new_priomap->priomap, old_priomap->priomap,
>>> + old_priomap->priomap_len *
>>> + sizeof(old_priomap->priomap[0]));
>>
>> This argument indentation is ridiculous. Try:
>>
>> memcpy(new_priomap->priomap, old_priomap->priomap,
>> old_priomap->priomap_len *
>> sizeof(old_priomap->priomap[0]));
>>
>> Using TABs exclusively for argumentat indentation is not the goal.
>>
>> Rather, lining the arguments up properly so that they sit at the first
>> column after the first line's openning parenthesis is what you should
>> be trying to achieve.
>
> OK, will fix it, thanks!
>
>>
>> And ignoring whatever stylistic convention we may or may not have, I
>> find it impossibly hard to believe that the code quoted above looks
>> good even to you.
>>
>
> On second thoughts, I think the memcpy in this case will actually be worse
> since it will copy the contents in chunks of smaller size than the for-loop.
Oops, I missed the __HAVE_ARCH_MEMCPY and was looking at the wrong memcpy
implementation.. And in any case, I went totally off-track by your last comment.
I hadn't realized that you were still referring to the way the code looks, rather
than questioning the switch to memcpy. Sorry about that!
I'll fix the odd-looking indentation and repost the patch.
Regards,
Srivatsa S. Bhat
^ permalink raw reply
* Re: [PATCH net-next V3 1/2] IB/ipoib: Add rtnl_link_ops support
From: Or Gerlitz @ 2012-09-12 10:40 UTC (permalink / raw)
To: Patrick McHardy, Eric Dumazet; +Cc: netdev, Shlomo Pongratz
In-Reply-To: <Pine.GSO.4.63.1208291450330.1098@stinky-local.trash.net>
Patrick McHardy wrote:
> Or Gerlitz wrote:
>
>> +#define IFLA_IPOIB_MAX (__IFLA_IPOIB_MAX - 1)
>
> This should go into include/linux/if_link.h
>
This comment was easy to fix... HOWEVER, using V3 -- this posting
http://marc.info/?l=linux-netdev&m=134572609226343&w=2 -- of the patch
over latest net-next (commit 280050cc81ccb2e06e4061228ee34c0cc86b1560
"x86 bpf_jit: support MOD operation"), when I just run the following trivial
sequence which loads the module and creates/deletes legacy child
$ modprobe ib_ipoib debug_level=1
$ echo 0x8001 > /sys/class/net/ib0/create_child
$ echo 0x8001 > /sys/class/net/ib0/delete_child
$ modprobe -r ib_ipoib
I get the below lockdep warning, pointing to ipoib_vlan_delete which is
by not means called by the module unload sequence, confusing... any idea?
Or.
======================================================
[ INFO: possible circular locking dependency detected ]
3.6.0-rc3+ #144 Not tainted
-------------------------------------------------------
modprobe/4443 is trying to acquire lock:
(s_active#155){++++.+}, at: [<ffffffff8114f93f>]
sysfs_addrm_finish+0x29/0x52
but task is already holding lock:
(rtnl_mutex){+.+.+.}, at: [<ffffffff812fc103>] rtnl_lock+0x12/0x14
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #1 (rtnl_mutex){+.+.+.}:
[<ffffffff81072b30>] lock_acquire+0x14f/0x19b
[<ffffffff81396a43>] mutex_lock_nested+0x64/0x2ce
[<ffffffff812fc103>] rtnl_lock+0x12/0x14
[<ffffffff812eecf1>] netdev_run_todo+0xa5/0x27e
[<ffffffff812fc0dd>] rtnl_unlock+0x9/0xb
[<ffffffffa0394889>] ipoib_vlan_delete+0x111/0x148 [ib_ipoib]
[<ffffffffa038d29b>] delete_child+0x44/0x60 [ib_ipoib]
[<ffffffff81247bd8>] dev_attr_store+0x1b/0x1d
[<ffffffff8114e223>] sysfs_write_file+0x103/0x13f
[<ffffffff810f206b>] vfs_write+0xae/0x133
[<ffffffff810f21a9>] sys_write+0x45/0x6c
[<ffffffff813a05e2>] system_call_fastpath+0x16/0x1b
-> #0 (s_active#155){++++.+}:
[<ffffffff81072364>] __lock_acquire+0x10d1/0x174e
[<ffffffff81072b30>] lock_acquire+0x14f/0x19b
[<ffffffff8114ef79>] sysfs_deactivate+0x93/0xca
[<ffffffff8114f93f>] sysfs_addrm_finish+0x29/0x52
[<ffffffff8114fa36>] sysfs_remove_dir+0x8b/0x9e
[<ffffffff81199c6d>] kobject_del+0x16/0x37
[<ffffffff812491ca>] device_del+0x18f/0x19f
[<ffffffff813000d3>] netdev_unregister_kobject+0x52/0x57
[<ffffffff812eeacc>] rollback_registered_many+0x238/0x27c
[<ffffffff812eebe9>] unregister_netdevice_queue+0x7f/0xbf
[<ffffffff812eec45>] unregister_netdev+0x1c/0x23
[<ffffffffa038d1eb>] ipoib_remove_one+0xad/0xe7 [ib_ipoib]
[<ffffffffa01a89ec>] ib_unregister_client+0x3d/0x11c [ib_core]
[<ffffffffa0398fcf>] ipoib_cleanup_module+0x2f/0x4e [ib_ipoib]
[<ffffffff8107d81d>] sys_delete_module+0x1ac/0x210
[<ffffffff813a05e2>] system_call_fastpath+0x16/0x1b
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(rtnl_mutex);
lock(s_active#155);
lock(rtnl_mutex);
lock(s_active#155);
*** DEADLOCK ***
2 locks held by modprobe/4443:
#0: (device_mutex){+.+.+.}, at: [<ffffffffa01a89d1>]
ib_unregister_client+0x22/0x11c [ib_core]
#1: (rtnl_mutex){+.+.+.}, at: [<ffffffff812fc103>] rtnl_lock+0x12/0x14
stack backtrace:
Pid: 4443, comm: modprobe Not tainted 3.6.0-rc3+ #144
Call Trace:
[<ffffffff8102dad8>] ? console_unlock+0x329/0x37e
[<ffffffff81070c15>] print_circular_bug+0x28e/0x29f
[<ffffffff81072364>] __lock_acquire+0x10d1/0x174e
[<ffffffff8114f93f>] ? sysfs_addrm_finish+0x29/0x52
[<ffffffff81072b30>] lock_acquire+0x14f/0x19b
[<ffffffff8114f93f>] ? sysfs_addrm_finish+0x29/0x52
[<ffffffff8114ef79>] sysfs_deactivate+0x93/0xca
[<ffffffff8114f93f>] ? sysfs_addrm_finish+0x29/0x52
[<ffffffff8114f93f>] sysfs_addrm_finish+0x29/0x52
[<ffffffff8114fa36>] sysfs_remove_dir+0x8b/0x9e
[<ffffffff81199c6d>] kobject_del+0x16/0x37
[<ffffffff812491ca>] device_del+0x18f/0x19f
[<ffffffff813000d3>] netdev_unregister_kobject+0x52/0x57
[<ffffffff812eeacc>] rollback_registered_many+0x238/0x27c
[<ffffffff812eebe9>] unregister_netdevice_queue+0x7f/0xbf
[<ffffffff812eec45>] unregister_netdev+0x1c/0x23
[<ffffffffa038d1eb>] ipoib_remove_one+0xad/0xe7 [ib_ipoib]
[<ffffffffa01a89ec>] ib_unregister_client+0x3d/0x11c [ib_core]
[<ffffffffa0398fcf>] ipoib_cleanup_module+0x2f/0x4e [ib_ipoib]
[<ffffffff8107d81d>] sys_delete_module+0x1ac/0x210
[<ffffffff8106fc4f>] ? trace_hardirqs_on_caller+0x11e/0x155
[<ffffffff811a2a0e>] ? trace_hardirqs_on_thunk+0x3a/0x3f
[<ffffffff813a05e2>] system_call_fastpath+0x16/0x1b
^ permalink raw reply
* [PATCH V2] Generalise "auto-negotiation done" function, move generic PHY code to phy_device.c
From: Alexander Sverdlin @ 2012-09-12 11:11 UTC (permalink / raw)
To: netdev, Andy Fleming, davem
From: Alexander Sverdlin <alexander.sverdlin@sysgo.com>
Generalise "auto-negotiation done" function, move generic PHY code to phy_device.c
Not all devices have "auto-negotiation done" bit at the place, as expected by
phy_aneg_done() in phy.c. Example of such device is Marvell 88E61xx Ethernet
switch which could be controlled by Linux PHY layer, if struct phy_driver had
abstraction for above function. So move hardware-dependent implementation details
for "generic" PHY to phy_device.c, and modify all PHY drivers to use new field.
Now phy.c contains only high-level state-machine functionality, leaving
hardware-layer to different drivers.
V2 is patch against net-next, as one additional PHY driver was added.
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@sysgo.com>
---
Documentation/networking/phy.txt | 9 +++++----
drivers/net/phy/amd.c | 1 +
drivers/net/phy/bcm63xx.c | 2 ++
drivers/net/phy/bcm87xx.c | 2 ++
drivers/net/phy/broadcom.c | 11 +++++++++++
drivers/net/phy/cicada.c | 2 ++
drivers/net/phy/davicom.c | 3 +++
drivers/net/phy/dp83640.c | 1 +
drivers/net/phy/et1011c.c | 1 +
drivers/net/phy/icplus.c | 3 +++
drivers/net/phy/lxt.c | 3 +++
drivers/net/phy/marvell.c | 9 +++++++++
drivers/net/phy/micrel.c | 5 +++++
drivers/net/phy/national.c | 1 +
drivers/net/phy/phy.c | 22 ++--------------------
drivers/net/phy/phy_device.c | 18 ++++++++++++++++++
drivers/net/phy/qsemi.c | 1 +
drivers/net/phy/realtek.c | 1 +
drivers/net/phy/smsc.c | 5 +++++
drivers/net/phy/ste10Xp.c | 2 ++
drivers/net/phy/vitesse.c | 2 ++
include/linux/phy.h | 12 ++++++++++--
22 files changed, 90 insertions(+), 26 deletions(-)
diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt
index 95e5f59..f75fd24 100644
--- a/Documentation/networking/phy.txt
+++ b/Documentation/networking/phy.txt
@@ -1,7 +1,7 @@
-------
PHY Abstraction Layer
-(Updated 2008-04-08)
+(Updated 2012-09-06)
Purpose
@@ -257,15 +257,16 @@ Writing a PHY driver
probe: Does any setup needed by the driver
suspend/resume: power management
config_aneg: Changes the speed/duplex/negotiation settings
+ aneg_done: Reads current auto-negotiation state
read_status: Reads the current speed/duplex/negotiation settings
ack_interrupt: Clear a pending interrupt
config_intr: Enable or disable interrupts
remove: Does any driver take-down
- Of these, only config_aneg and read_status are required to be
+ Of these, only config_aneg, aneg_done and read_status are required to be
assigned by the driver code. The rest are optional. Also, it is
- preferred to use the generic phy driver's versions of these two
- functions if at all possible: genphy_read_status and
+ preferred to use the generic phy driver's versions of these three
+ functions if at all possible: genphy_read_status, genphy_aneg_done and
genphy_config_aneg. If this is not possible, it is likely that
you only need to perform some actions before and after invoking
these functions, and so your functions will wrap the generic
diff --git a/drivers/net/phy/amd.c b/drivers/net/phy/amd.c
index a3fb5ce..286596c 100644
--- a/drivers/net/phy/amd.c
+++ b/drivers/net/phy/amd.c
@@ -69,6 +69,7 @@ static struct phy_driver am79c_driver = {
.flags = PHY_HAS_INTERRUPT,
.config_init = am79c_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = am79c_ack_interrupt,
.config_intr = am79c_config_intr,
diff --git a/drivers/net/phy/bcm63xx.c b/drivers/net/phy/bcm63xx.c
index 84c7a39..5953d1a 100644
--- a/drivers/net/phy/bcm63xx.c
+++ b/drivers/net/phy/bcm63xx.c
@@ -81,6 +81,7 @@ static struct phy_driver bcm63xx_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = bcm63xx_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = bcm63xx_ack_interrupt,
.config_intr = bcm63xx_config_intr,
@@ -94,6 +95,7 @@ static struct phy_driver bcm63xx_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = bcm63xx_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = bcm63xx_ack_interrupt,
.config_intr = bcm63xx_config_intr,
diff --git a/drivers/net/phy/bcm87xx.c b/drivers/net/phy/bcm87xx.c
index 2346b38..9fefbad 100644
--- a/drivers/net/phy/bcm87xx.c
+++ b/drivers/net/phy/bcm87xx.c
@@ -195,6 +195,7 @@ static struct phy_driver bcm87xx_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = bcm87xx_config_init,
.config_aneg = bcm87xx_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = bcm87xx_read_status,
.ack_interrupt = bcm87xx_ack_interrupt,
.config_intr = bcm87xx_config_intr,
@@ -208,6 +209,7 @@ static struct phy_driver bcm87xx_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = bcm87xx_config_init,
.config_aneg = bcm87xx_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = bcm87xx_read_status,
.ack_interrupt = bcm87xx_ack_interrupt,
.config_intr = bcm87xx_config_intr,
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index f8c90ea..aaeb9ee 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -692,6 +692,7 @@ static struct phy_driver broadcom_drivers[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = bcm54xx_ack_interrupt,
.config_intr = bcm54xx_config_intr,
@@ -705,6 +706,7 @@ static struct phy_driver broadcom_drivers[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = bcm54xx_ack_interrupt,
.config_intr = bcm54xx_config_intr,
@@ -718,6 +720,7 @@ static struct phy_driver broadcom_drivers[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = bcm54xx_ack_interrupt,
.config_intr = bcm54xx_config_intr,
@@ -731,6 +734,7 @@ static struct phy_driver broadcom_drivers[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = bcm54xx_ack_interrupt,
.config_intr = bcm54xx_config_intr,
@@ -744,6 +748,7 @@ static struct phy_driver broadcom_drivers[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = bcm5481_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = bcm54xx_ack_interrupt,
.config_intr = bcm54xx_config_intr,
@@ -757,6 +762,7 @@ static struct phy_driver broadcom_drivers[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm5482_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = bcm5482_read_status,
.ack_interrupt = bcm54xx_ack_interrupt,
.config_intr = bcm54xx_config_intr,
@@ -770,6 +776,7 @@ static struct phy_driver broadcom_drivers[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = bcm54xx_ack_interrupt,
.config_intr = bcm54xx_config_intr,
@@ -783,6 +790,7 @@ static struct phy_driver broadcom_drivers[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = bcm54xx_ack_interrupt,
.config_intr = bcm54xx_config_intr,
@@ -796,6 +804,7 @@ static struct phy_driver broadcom_drivers[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = bcm54xx_ack_interrupt,
.config_intr = bcm54xx_config_intr,
@@ -809,6 +818,7 @@ static struct phy_driver broadcom_drivers[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = brcm_fet_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = brcm_fet_ack_interrupt,
.config_intr = brcm_fet_config_intr,
@@ -822,6 +832,7 @@ static struct phy_driver broadcom_drivers[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = brcm_fet_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = brcm_fet_ack_interrupt,
.config_intr = brcm_fet_config_intr,
diff --git a/drivers/net/phy/cicada.c b/drivers/net/phy/cicada.c
index db472ff..7613ec8 100644
--- a/drivers/net/phy/cicada.c
+++ b/drivers/net/phy/cicada.c
@@ -111,6 +111,7 @@ static struct phy_driver cis820x_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = &cis820x_config_init,
.config_aneg = &genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &genphy_read_status,
.ack_interrupt = &cis820x_ack_interrupt,
.config_intr = &cis820x_config_intr,
@@ -123,6 +124,7 @@ static struct phy_driver cis820x_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = &cis820x_config_init,
.config_aneg = &genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &genphy_read_status,
.ack_interrupt = &cis820x_ack_interrupt,
.config_intr = &cis820x_config_intr,
diff --git a/drivers/net/phy/davicom.c b/drivers/net/phy/davicom.c
index 81c7bc0..90b337d 100644
--- a/drivers/net/phy/davicom.c
+++ b/drivers/net/phy/davicom.c
@@ -152,6 +152,7 @@ static struct phy_driver dm91xx_driver[] = {
.features = PHY_BASIC_FEATURES,
.config_init = dm9161_config_init,
.config_aneg = dm9161_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.driver = { .owner = THIS_MODULE,},
}, {
@@ -161,6 +162,7 @@ static struct phy_driver dm91xx_driver[] = {
.features = PHY_BASIC_FEATURES,
.config_init = dm9161_config_init,
.config_aneg = dm9161_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.driver = { .owner = THIS_MODULE,},
}, {
@@ -170,6 +172,7 @@ static struct phy_driver dm91xx_driver[] = {
.features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = dm9161_ack_interrupt,
.config_intr = dm9161_config_intr,
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index b0da022..8c29ceb 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -1257,6 +1257,7 @@ static struct phy_driver dp83640_driver = {
.probe = dp83640_probe,
.remove = dp83640_remove,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ts_info = dp83640_ts_info,
.hwtstamp = dp83640_hwtstamp,
diff --git a/drivers/net/phy/et1011c.c b/drivers/net/phy/et1011c.c
index a8eb19e..2878597 100644
--- a/drivers/net/phy/et1011c.c
+++ b/drivers/net/phy/et1011c.c
@@ -94,6 +94,7 @@ static struct phy_driver et1011c_driver = {
.features = (PHY_BASIC_FEATURES | SUPPORTED_1000baseT_Full),
.flags = PHY_POLL,
.config_aneg = et1011c_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = et1011c_read_status,
.driver = { .owner = THIS_MODULE,},
};
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index d5199cb..7d35770 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -210,6 +210,7 @@ static struct phy_driver icplus_driver[] = {
.features = PHY_BASIC_FEATURES,
.config_init = &ip175c_config_init,
.config_aneg = &ip175c_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &ip175c_read_status,
.suspend = genphy_suspend,
.resume = genphy_resume,
@@ -222,6 +223,7 @@ static struct phy_driver icplus_driver[] = {
SUPPORTED_Asym_Pause,
.config_init = &ip1001_config_init,
.config_aneg = &genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &genphy_read_status,
.suspend = genphy_suspend,
.resume = genphy_resume,
@@ -236,6 +238,7 @@ static struct phy_driver icplus_driver[] = {
.ack_interrupt = ip101a_g_ack_interrupt,
.config_init = &ip101a_g_config_init,
.config_aneg = &genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &genphy_read_status,
.suspend = genphy_suspend,
.resume = genphy_resume,
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index 6d1e3fc..846d408 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -158,6 +158,7 @@ static struct phy_driver lxt97x_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = lxt970_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = lxt970_ack_interrupt,
.config_intr = lxt970_config_intr,
@@ -169,6 +170,7 @@ static struct phy_driver lxt97x_driver[] = {
.features = PHY_BASIC_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = lxt971_ack_interrupt,
.config_intr = lxt971_config_intr,
@@ -181,6 +183,7 @@ static struct phy_driver lxt97x_driver[] = {
.flags = 0,
.probe = lxt973_probe,
.config_aneg = lxt973_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.driver = { .owner = THIS_MODULE,},
} };
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 5d2a3f2..f485290 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -713,6 +713,7 @@ static struct phy_driver marvell_drivers[] = {
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_aneg = &marvell_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &genphy_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
@@ -726,6 +727,7 @@ static struct phy_driver marvell_drivers[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = &m88e1111_config_init,
.config_aneg = &marvell_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &genphy_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
@@ -739,6 +741,7 @@ static struct phy_driver marvell_drivers[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = &m88e1111_config_init,
.config_aneg = &marvell_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &marvell_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
@@ -752,6 +755,7 @@ static struct phy_driver marvell_drivers[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = &m88e1118_config_init,
.config_aneg = &m88e1118_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &genphy_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
@@ -764,6 +768,7 @@ static struct phy_driver marvell_drivers[] = {
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_aneg = &m88e1121_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &marvell_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
@@ -777,6 +782,7 @@ static struct phy_driver marvell_drivers[] = {
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_aneg = &m88e1318_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &marvell_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
@@ -791,6 +797,7 @@ static struct phy_driver marvell_drivers[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = &m88e1145_config_init,
.config_aneg = &marvell_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &genphy_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
@@ -804,6 +811,7 @@ static struct phy_driver marvell_drivers[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = &m88e1149_config_init,
.config_aneg = &m88e1118_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &genphy_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
@@ -817,6 +825,7 @@ static struct phy_driver marvell_drivers[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = &m88e1111_config_init,
.config_aneg = &marvell_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &genphy_read_status,
.ack_interrupt = &marvell_ack_interrupt,
.config_intr = &marvell_config_intr,
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index cf287e0..12d4f13 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -123,6 +123,7 @@ static struct phy_driver ksphy_driver[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = ks8737_config_intr,
@@ -136,6 +137,7 @@ static struct phy_driver ksphy_driver[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = kszphy_config_intr,
@@ -149,6 +151,7 @@ static struct phy_driver ksphy_driver[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = ks8051_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = kszphy_config_intr,
@@ -161,6 +164,7 @@ static struct phy_driver ksphy_driver[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = kszphy_config_intr,
@@ -174,6 +178,7 @@ static struct phy_driver ksphy_driver[] = {
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = kszphy_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = kszphy_ack_interrupt,
.config_intr = ksz9021_config_intr,
diff --git a/drivers/net/phy/national.c b/drivers/net/phy/national.c
index 9a5f234..7b47a2b 100644
--- a/drivers/net/phy/national.c
+++ b/drivers/net/phy/national.c
@@ -137,6 +137,7 @@ static struct phy_driver dp83865_driver = {
.flags = PHY_HAS_INTERRUPT,
.config_init = ns_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = ns_ack_interrupt,
.config_intr = ns_config_intr,
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index ef9ea92..dfca51d 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -95,24 +95,6 @@ static int phy_config_interrupt(struct phy_device *phydev, u32 interrupts)
return err;
}
-
-/**
- * phy_aneg_done - return auto-negotiation status
- * @phydev: target phy_device struct
- *
- * Description: Reads the status register and returns 0 either if
- * auto-negotiation is incomplete, or if there was an error.
- * Returns BMSR_ANEGCOMPLETE if auto-negotiation is done.
- */
-static inline int phy_aneg_done(struct phy_device *phydev)
-{
- int retval;
-
- retval = phy_read(phydev, MII_BMSR);
-
- return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
-}
-
/* A structure for mapping a particular speed and duplex
* combination to a particular SUPPORTED and ADVERTISED value */
struct phy_setting {
@@ -807,7 +789,7 @@ void phy_state_machine(struct work_struct *work)
/* Check if negotiation is done. Break
* if there's an error */
- err = phy_aneg_done(phydev);
+ err = phydev->drv->aneg_done(phydev);
if (err < 0)
break;
@@ -921,7 +903,7 @@ void phy_state_machine(struct work_struct *work)
break;
if (AUTONEG_ENABLE == phydev->autoneg) {
- err = phy_aneg_done(phydev);
+ err = phydev->drv->aneg_done(phydev);
if (err < 0)
break;
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 8af46e8..8e09103 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -785,6 +785,23 @@ int genphy_config_aneg(struct phy_device *phydev)
EXPORT_SYMBOL(genphy_config_aneg);
/**
+ * genphy_aneg_done - return auto-negotiation status
+ * @phydev: target phy_device struct
+ *
+ * Description: Reads the status register and returns positive value if
+ * auto-negotiation is complete, 0 if incomplete and negative on failure.
+ */
+int genphy_aneg_done(struct phy_device *phydev)
+{
+ int retval;
+
+ retval = phy_read(phydev, MII_BMSR);
+
+ return (retval < 0) ? retval : (retval & BMSR_ANEGCOMPLETE);
+}
+EXPORT_SYMBOL(genphy_aneg_done);
+
+/**
* genphy_update_link - update link status in @phydev
* @phydev: target phy_device struct
*
@@ -1117,6 +1134,7 @@ static struct phy_driver genphy_driver = {
.config_init = genphy_config_init,
.features = 0,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.suspend = genphy_suspend,
.resume = genphy_resume,
diff --git a/drivers/net/phy/qsemi.c b/drivers/net/phy/qsemi.c
index fe0d0a1..5208b16 100644
--- a/drivers/net/phy/qsemi.c
+++ b/drivers/net/phy/qsemi.c
@@ -119,6 +119,7 @@ static struct phy_driver qs6612_driver = {
.flags = PHY_HAS_INTERRUPT,
.config_init = qs6612_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = qs6612_ack_interrupt,
.config_intr = qs6612_config_intr,
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 72f9347..2a54bc9 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -57,6 +57,7 @@ static struct phy_driver rtl821x_driver = {
.features = PHY_GBIT_FEATURES,
.flags = PHY_HAS_INTERRUPT,
.config_aneg = &genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &genphy_read_status,
.ack_interrupt = &rtl821x_ack_interrupt,
.config_intr = &rtl821x_config_intr,
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 6d61923..dd494aa 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -73,6 +73,7 @@ static struct phy_driver smsc_phy_driver[] = {
/* basic functions */
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.config_init = smsc_phy_config_init,
@@ -95,6 +96,7 @@ static struct phy_driver smsc_phy_driver[] = {
/* basic functions */
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.config_init = smsc_phy_config_init,
@@ -117,6 +119,7 @@ static struct phy_driver smsc_phy_driver[] = {
/* basic functions */
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.config_init = smsc_phy_config_init,
@@ -139,6 +142,7 @@ static struct phy_driver smsc_phy_driver[] = {
/* basic functions */
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.config_init = lan911x_config_init,
@@ -161,6 +165,7 @@ static struct phy_driver smsc_phy_driver[] = {
/* basic functions */
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.config_init = smsc_phy_config_init,
diff --git a/drivers/net/phy/ste10Xp.c b/drivers/net/phy/ste10Xp.c
index 5e1eb13..8d9baae 100644
--- a/drivers/net/phy/ste10Xp.c
+++ b/drivers/net/phy/ste10Xp.c
@@ -90,6 +90,7 @@ static struct phy_driver ste10xp_pdriver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = ste10Xp_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = ste10Xp_ack_interrupt,
.config_intr = ste10Xp_config_intr,
@@ -104,6 +105,7 @@ static struct phy_driver ste10xp_pdriver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = ste10Xp_config_init,
.config_aneg = genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = genphy_read_status,
.ack_interrupt = ste10Xp_ack_interrupt,
.config_intr = ste10Xp_config_intr,
diff --git a/drivers/net/phy/vitesse.c b/drivers/net/phy/vitesse.c
index 2585c38..17c97b4 100644
--- a/drivers/net/phy/vitesse.c
+++ b/drivers/net/phy/vitesse.c
@@ -160,6 +160,7 @@ static struct phy_driver vsc82xx_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = &vsc824x_config_init,
.config_aneg = &genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &genphy_read_status,
.ack_interrupt = &vsc824x_ack_interrupt,
.config_intr = &vsc82xx_config_intr,
@@ -173,6 +174,7 @@ static struct phy_driver vsc82xx_driver[] = {
.flags = PHY_HAS_INTERRUPT,
.config_init = &vsc8221_config_init,
.config_aneg = &genphy_config_aneg,
+ .aneg_done = genphy_aneg_done,
.read_status = &genphy_read_status,
.ack_interrupt = &vsc824x_ack_interrupt,
.config_intr = &vsc82xx_config_intr,
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 93b3cf7..876fbfa 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -369,8 +369,8 @@ struct phy_device {
* flags: A bitfield defining certain other features this PHY
* supports (like interrupts)
*
- * The drivers must implement config_aneg and read_status. All
- * other functions are optional. Note that none of these
+ * The drivers must implement config_aneg, aneg_done and read_status.
+ * All other functions are optional. Note that none of these
* functions should be called from interrupt time. The goal is
* for the bus read/write functions to be able to block when the
* bus transaction is happening, and be freed up by an interrupt
@@ -408,6 +408,13 @@ struct phy_driver {
*/
int (*config_aneg)(struct phy_device *phydev);
+ /*
+ * Reads auto-negotiation status. Returns positive value if
+ * auto-negotiation is complete, 0 if incomplete and negative
+ * value on error
+ */
+ int (*aneg_done)(struct phy_device *phydev);
+
/* Determines the negotiated speed and duplex */
int (*read_status)(struct phy_device *phydev);
@@ -528,6 +535,7 @@ static inline int phy_read_status(struct phy_device *phydev) {
int genphy_restart_aneg(struct phy_device *phydev);
int genphy_config_aneg(struct phy_device *phydev);
+int genphy_aneg_done(struct phy_device *phydev);
int genphy_update_link(struct phy_device *phydev);
int genphy_read_status(struct phy_device *phydev);
int genphy_suspend(struct phy_device *phydev);
^ 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