* Re: Linux 2.6.34-rc3 + CAN build problem
From: Németh Márton @ 2010-04-11 5:14 UTC (permalink / raw)
To: David Miller
Cc: socketcan, eric.dumazet, oliver.hartkopp, urs.thuermann,
socketcan-core, netdev, linux-kernel
In-Reply-To: <20100410.155009.66184583.davem@davemloft.net>
David Miller wrote:
> From: Oliver Hartkopp <socketcan@hartkopp.net>
> Date: Sat, 10 Apr 2010 14:36:48 +0200
>
>> So i wonder why Nemeth trapped into this problem ... probably an include file
>> mix-up?
>
> Do you have CONFIG_DEBUG_STRICT_USER_COPY_CHECKS enabled in your
> kernel config?
CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y
> That's the only way you get an actual failure of a build when
> the user copy size can't be proven to be in range by the
> compiler, otherwise it just warns.
>
>
^ permalink raw reply
* Re: Linux 2.6.34-rc3 + CAN build problem
From: David Miller @ 2010-04-11 5:16 UTC (permalink / raw)
To: nm127
Cc: socketcan, eric.dumazet, oliver.hartkopp, urs.thuermann,
socketcan-core, netdev, linux-kernel
In-Reply-To: <4BC15AC7.3010904@freemail.hu>
From: Németh Márton <nm127@freemail.hu>
Date: Sun, 11 Apr 2010 07:14:47 +0200
> David Miller wrote:
>> From: Oliver Hartkopp <socketcan@hartkopp.net>
>> Date: Sat, 10 Apr 2010 14:36:48 +0200
>>
>>> So i wonder why Nemeth trapped into this problem ... probably an include file
>>> mix-up?
>>
>> Do you have CONFIG_DEBUG_STRICT_USER_COPY_CHECKS enabled in your
>> kernel config?
>
> CONFIG_DEBUG_STRICT_USER_COPY_CHECKS=y
Just turn that off in your builds, it's for developers who want
to work on correcting those warnings, not you :-)
^ permalink raw reply
* [PATCH net-next-2.6] drivers: net: last_rx elimination
From: Eric Dumazet @ 2010-04-11 8:48 UTC (permalink / raw)
To: David Miller; +Cc: netdev
Network drivers do not have to update last_rx, unless they need it for
their private use.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
drivers/net/bcm63xx_enet.c | 1 -
drivers/net/can/at91_can.c | 2 --
drivers/net/ixgbevf/ixgbevf_main.c | 1 -
drivers/net/ksz884x.c | 2 --
drivers/net/octeon/octeon_mgmt.c | 1 -
drivers/net/stmmac/stmmac_main.c | 1 -
drivers/net/vmxnet3/vmxnet3_drv.c | 1 -
7 files changed, 9 deletions(-)
diff --git a/drivers/net/bcm63xx_enet.c b/drivers/net/bcm63xx_enet.c
index 5173340..10f428f 100644
--- a/drivers/net/bcm63xx_enet.c
+++ b/drivers/net/bcm63xx_enet.c
@@ -343,7 +343,6 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget)
skb->protocol = eth_type_trans(skb, dev);
priv->stats.rx_packets++;
priv->stats.rx_bytes += len;
- dev->last_rx = jiffies;
netif_receive_skb(skb);
} while (--budget > 0);
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index a2f29a3..1fd45e5 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -662,7 +662,6 @@ static int at91_poll_err(struct net_device *dev, int quota, u32 reg_sr)
at91_poll_err_frame(dev, cf, reg_sr);
netif_receive_skb(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += cf->can_dlc;
@@ -899,7 +898,6 @@ static void at91_irq_err(struct net_device *dev)
at91_irq_err_state(dev, cf, new_state);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += cf->can_dlc;
diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c
index 65cb133..2082c88 100644
--- a/drivers/net/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ixgbevf/ixgbevf_main.c
@@ -610,7 +610,6 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
skb->protocol = eth_type_trans(skb, adapter->netdev);
ixgbevf_receive_skb(q_vector, skb, staterr, rx_ring, rx_desc);
- adapter->netdev->last_rx = jiffies;
next_desc:
rx_desc->wb.upper.status_error = 0;
diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c
index 0977964..26ccf46 100644
--- a/drivers/net/ksz884x.c
+++ b/drivers/net/ksz884x.c
@@ -5053,8 +5053,6 @@ static inline int rx_proc(struct net_device *dev, struct ksz_hw* hw,
priv->stats.rx_bytes += packet_len;
/* Notify upper layer for received packet. */
- dev->last_rx = jiffies;
-
rx_status = netif_rx(skb);
return 0;
diff --git a/drivers/net/octeon/octeon_mgmt.c b/drivers/net/octeon/octeon_mgmt.c
index ee894ed..43ffbba 100644
--- a/drivers/net/octeon/octeon_mgmt.c
+++ b/drivers/net/octeon/octeon_mgmt.c
@@ -316,7 +316,6 @@ good:
skb->protocol = eth_type_trans(skb, netdev);
netdev->stats.rx_packets++;
netdev->stats.rx_bytes += skb->len;
- netdev->last_rx = jiffies;
netif_receive_skb(skb);
rc = 0;
} else if (re.s.code == RING_ENTRY_CODE_MORE) {
diff --git a/drivers/net/stmmac/stmmac_main.c b/drivers/net/stmmac/stmmac_main.c
index 963f591..d03e57c 100644
--- a/drivers/net/stmmac/stmmac_main.c
+++ b/drivers/net/stmmac/stmmac_main.c
@@ -1279,7 +1279,6 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
priv->dev->stats.rx_packets++;
priv->dev->stats.rx_bytes += frame_len;
- priv->dev->last_rx = jiffies;
}
entry = next_entry;
p = p_next; /* use prefetched values */
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 58dfa36..90e783a 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -1174,7 +1174,6 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
netif_receive_skb(skb);
}
- adapter->netdev->last_rx = jiffies;
ctx->skb = NULL;
}
^ permalink raw reply related
* ssh server etc doesn't work anymore with net-2.6
From: Yinghai Lu @ 2010-04-11 9:17 UTC (permalink / raw)
To: David Miller; +Cc: Linux Kernel Mailing List, NetDev, Linus Torvalds
caused by:
commit 2626419ad5be1a054d350786b684b41d23de1538
Author: David S. Miller <davem@davemloft.net>
Date: Thu Apr 8 11:32:30 2010 -0700
tcp: Set CHECKSUM_UNNECESSARY in tcp_init_nondata_skb
it will make sshd server, telnet server and vnc server doesn't respond
connecting request anymore.
YH
^ permalink raw reply
* Re: ssh server etc doesn't work anymore with net-2.6
From: David Miller @ 2010-04-11 9:21 UTC (permalink / raw)
To: yinghai; +Cc: linux-kernel, netdev, torvalds
In-Reply-To: <r2v86802c441004110217u15591f95ydd1e8e1466a36dc2@mail.gmail.com>
From: Yinghai Lu <yinghai@kernel.org>
Date: Sun, 11 Apr 2010 02:17:09 -0700
> caused by:
>
> commit 2626419ad5be1a054d350786b684b41d23de1538
> Author: David S. Miller <davem@davemloft.net>
> Date: Thu Apr 8 11:32:30 2010 -0700
>
> tcp: Set CHECKSUM_UNNECESSARY in tcp_init_nondata_skb
>
> it will make sshd server, telnet server and vnc server doesn't respond
> connecting request anymore.
I'll either fix or revert this, thanks for reporting.
^ permalink raw reply
* Re: ssh server etc doesn't work anymore with net-2.6
From: David Miller @ 2010-04-11 9:24 UTC (permalink / raw)
To: yinghai; +Cc: linux-kernel, netdev, torvalds
In-Reply-To: <r2v86802c441004110217u15591f95ydd1e8e1466a36dc2@mail.gmail.com>
From: Yinghai Lu <yinghai@kernel.org>
Date: Sun, 11 Apr 2010 02:17:09 -0700
> it will make sshd server, telnet server and vnc server doesn't respond
> connecting request anymore.
What kind of network device are you using?
And regardless of the underlying physical network device, are you
going over some virtual device such as a tunnel, a bonding device, or
a virtualization network interface?
Thanks.
^ permalink raw reply
* Re: ssh server etc doesn't work anymore with net-2.6
From: Yinghai Lu @ 2010-04-11 9:32 UTC (permalink / raw)
To: David Miller; +Cc: linux-kernel, netdev, torvalds
In-Reply-To: <20100411.022416.107236208.davem@davemloft.net>
On Sun, Apr 11, 2010 at 2:24 AM, David Miller <davem@davemloft.net> wrote:
> From: Yinghai Lu <yinghai@kernel.org>
> Date: Sun, 11 Apr 2010 02:17:09 -0700
>
>> it will make sshd server, telnet server and vnc server doesn't respond
>> connecting request anymore.
>
> What kind of network device are you using?
>
> And regardless of the underlying physical network device, are you
> going over some virtual device such as a tunnel, a bonding device, or
> a virtualization network interface?
server side: 82576 with net-2.6
client side: opensuse 11.2 on thinkpad T61 wireless + vpnc
Yinghai
^ permalink raw reply
* Re: ssh server etc doesn't work anymore with net-2.6
From: David Miller @ 2010-04-11 9:33 UTC (permalink / raw)
To: yinghai; +Cc: linux-kernel, netdev, torvalds
In-Reply-To: <u2v86802c441004110232l99be1450w4e629ab2bde9bc0c@mail.gmail.com>
From: Yinghai Lu <yinghai@kernel.org>
Date: Sun, 11 Apr 2010 02:32:33 -0700
> On Sun, Apr 11, 2010 at 2:24 AM, David Miller <davem@davemloft.net> wrote:
>> From: Yinghai Lu <yinghai@kernel.org>
>> Date: Sun, 11 Apr 2010 02:17:09 -0700
>>
>>> it will make sshd server, telnet server and vnc server doesn't respond
>>> connecting request anymore.
>>
>> What kind of network device are you using?
>>
>> And regardless of the underlying physical network device, are you
>> going over some virtual device such as a tunnel, a bonding device, or
>> a virtualization network interface?
>
> server side: 82576 with net-2.6
> client side: opensuse 11.2 on thinkpad T61 wireless + vpnc
Thanks.
^ permalink raw reply
* IGB handling of zero length checksumming?
From: David Miller @ 2010-04-11 9:40 UTC (permalink / raw)
To: netdev
Cc: jeffrey.t.kirsher, jesse.brandeburg, bruce.w.allan,
alexander.h.duyck, peter.p.waskiewicz.jr, john.ronciak
If the IGB is given a "skb->ip_summed === CHECKSUM_PARTIAL" packet and
the data area past the TCP header is of zero length, will it do the
right thing?
I'm asking because I made a change recently in net-2.6 that causes TCP
packets with no data (ACKs, etc.) to start using CHECKSUM_PARTIAL.
And a user with IGB interfaces on a system running net-2.6 is getting
failures connecting to SSH and stuff like that and it is known that
this TCP commit of mine is the culprit. See:
http://marc.info/?l=linux-netdev&m=127097744616962&w=2
I'm very likely to just revert this change regardless of what the
problem is, and try to sort this out in net-next-2.6, but it'd be nice
to know if IGB indeed has a problem in this area and that's the true
cause of the issue.
Thanks!
^ permalink raw reply
* Re: ssh server etc doesn't work anymore with net-2.6
From: David Miller @ 2010-04-11 9:43 UTC (permalink / raw)
To: yinghai; +Cc: linux-kernel, netdev, torvalds
In-Reply-To: <u2v86802c441004110232l99be1450w4e629ab2bde9bc0c@mail.gmail.com>
From: Yinghai Lu <yinghai@kernel.org>
Date: Sun, 11 Apr 2010 02:32:33 -0700
> server side: 82576 with net-2.6
> client side: opensuse 11.2 on thinkpad T61 wireless + vpnc
I've pushed out a revert, we'll sort this out in net-next-2.6
and meanwhile I've started a dialog with the Intel driver
folks to see if there IGB chip has a problem with handling
CHECKSUM_PARTIAL packets with a zero length data area.
Thanks for your report.
^ permalink raw reply
* Re: ssh server etc doesn't work anymore with net-2.6
From: Herbert Xu @ 2010-04-11 10:09 UTC (permalink / raw)
To: David Miller; +Cc: yinghai, linux-kernel, netdev, torvalds
In-Reply-To: <20100411.024352.209996508.davem@davemloft.net>
David Miller <davem@davemloft.net> wrote:
> From: Yinghai Lu <yinghai@kernel.org>
> Date: Sun, 11 Apr 2010 02:32:33 -0700
>
>> server side: 82576 with net-2.6
>> client side: opensuse 11.2 on thinkpad T61 wireless + vpnc
>
> I've pushed out a revert, we'll sort this out in net-next-2.6
> and meanwhile I've started a dialog with the Intel driver
> folks to see if there IGB chip has a problem with handling
> CHECKSUM_PARTIAL packets with a zero length data area.
>
> Thanks for your report.
I was confused at first as to whether it was CHECKSUM_UNNECESSARY
that broke or CHECKSUM_PARTIAL.
After looking at the actual net-2.6 tree I see that it is actually
CHECKSUM_PARTIAL that caused this breakage.
The fact that when this was first implemented we didn't use hw
checksums on dataless packets might not have been an oversight
after all.
As I don't think such packets have been tested all by our kernel
on any NICs, and given the fact that IGB apparently broke, I think
the risk of this change is too high.
However, all is not lost as we can still adopt the approach of
the actual patch subject :) That is, we can use CHECKSUM_UNNECESSARY
for packets checksummed locally by software.
This does need a lot more testing so it should spend some time
in net-next first.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* Re: ssh server etc doesn't work anymore with net-2.6
From: Herbert Xu @ 2010-04-11 12:04 UTC (permalink / raw)
To: Herbert Xu; +Cc: davem, yinghai, linux-kernel, netdev, torvalds
In-Reply-To: <20100411100902.GA20141@gondor.apana.org.au>
Herbert Xu <herbert@gondor.apana.org.au> wrote:
>
> After looking at the actual net-2.6 tree I see that it is actually
> CHECKSUM_PARTIAL that caused this breakage.
>
> The fact that when this was first implemented we didn't use hw
> checksums on dataless packets might not have been an oversight
> after all.
Looks like I was too quick to blame the hardware, the synack
code can't handle CHECKSUM_PARTIAL so this is probably the real
cause.
I will send patches to fix this.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply
* [PATCH 1/3] tcp: Handle CHECKSUM_PARTIAL for SYNACK packets for IPv4
From: Herbert Xu @ 2010-04-11 12:15 UTC (permalink / raw)
To: davem, yinghai, linux-kernel, netdev, torvalds
In-Reply-To: <20100411100902.GA20141@gondor.apana.org.au>
tcp: Handle CHECKSUM_PARTIAL for SYNACK packets for IPv4
This patch moves the common code between tcp_v4_send_check and
tcp_v4_gso_send_check into a new function __tcp_v4_send_check.
It then uses the new function in tcp_v4_send_synack so that it
handles CHECKSUM_PARTIAL properly.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/ipv4/tcp_ipv4.c | 31 ++++++++++++++-----------------
1 file changed, 14 insertions(+), 17 deletions(-)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 3c23e70..aebfd28 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -519,26 +519,31 @@ out:
sock_put(sk);
}
-/* This routine computes an IPv4 TCP checksum. */
-void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
+static void __tcp_v4_send_check(struct sk_buff *skb,
+ __be32 saddr, __be32 daddr)
{
- struct inet_sock *inet = inet_sk(sk);
struct tcphdr *th = tcp_hdr(skb);
if (skb->ip_summed == CHECKSUM_PARTIAL) {
- th->check = ~tcp_v4_check(len, inet->inet_saddr,
- inet->inet_daddr, 0);
+ th->check = ~tcp_v4_check(skb->len, saddr, daddr, 0);
skb->csum_start = skb_transport_header(skb) - skb->head;
skb->csum_offset = offsetof(struct tcphdr, check);
} else {
- th->check = tcp_v4_check(len, inet->inet_saddr,
- inet->inet_daddr,
+ th->check = tcp_v4_check(skb->len, saddr, daddr,
csum_partial(th,
th->doff << 2,
skb->csum));
}
}
+/* This routine computes an IPv4 TCP checksum. */
+void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
+{
+ struct inet_sock *inet = inet_sk(sk);
+
+ __tcp_v4_send_check(skb, inet->inet_saddr, inet->inet_daddr);
+}
+
int tcp_v4_gso_send_check(struct sk_buff *skb)
{
const struct iphdr *iph;
@@ -551,10 +556,8 @@ int tcp_v4_gso_send_check(struct sk_buff *skb)
th = tcp_hdr(skb);
th->check = 0;
- th->check = ~tcp_v4_check(skb->len, iph->saddr, iph->daddr, 0);
- skb->csum_start = skb_transport_header(skb) - skb->head;
- skb->csum_offset = offsetof(struct tcphdr, check);
skb->ip_summed = CHECKSUM_PARTIAL;
+ __tcp_v4_send_check(skb, iph->saddr, iph->daddr);
return 0;
}
@@ -763,13 +766,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
skb = tcp_make_synack(sk, dst, req, rvp);
if (skb) {
- struct tcphdr *th = tcp_hdr(skb);
-
- th->check = tcp_v4_check(skb->len,
- ireq->loc_addr,
- ireq->rmt_addr,
- csum_partial(th, skb->len,
- skb->csum));
+ __tcp_v4_send_check(skb, ireq->loc_addr, ireq->rmt_addr);
err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
ireq->rmt_addr,
^ permalink raw reply related
* [PATCH 3/3] inet: Remove unused send_check length argument
From: Herbert Xu @ 2010-04-11 12:15 UTC (permalink / raw)
To: davem, yinghai, linux-kernel, netdev, torvalds
In-Reply-To: <20100411100902.GA20141@gondor.apana.org.au>
inet: Remove unused send_check length argument
This patch removes the unused length argument from the send_check
function in struct inet_connection_sock_af_ops.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/net/inet_connection_sock.h | 3 +--
include/net/tcp.h | 2 +-
net/dccp/dccp.h | 2 +-
net/dccp/ipv4.c | 2 +-
net/dccp/ipv6.c | 3 +--
net/dccp/output.c | 2 +-
net/ipv4/tcp_ipv4.c | 2 +-
net/ipv4/tcp_output.c | 2 +-
net/ipv6/tcp_ipv6.c | 2 +-
9 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 696d6e4..52c8b8b 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -37,8 +37,7 @@ struct tcp_congestion_ops;
*/
struct inet_connection_sock_af_ops {
int (*queue_xmit)(struct sk_buff *skb, int ipfragok);
- void (*send_check)(struct sock *sk, int len,
- struct sk_buff *skb);
+ void (*send_check)(struct sock *sk, struct sk_buff *skb);
int (*rebuild_header)(struct sock *sk);
int (*conn_request)(struct sock *sk, struct sk_buff *skb);
struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb,
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 75be5a2..70c5159 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -423,7 +423,7 @@ extern u8 *tcp_parse_md5sig_option(struct tcphdr *th);
* TCP v4 functions exported for the inet6 API
*/
-extern void tcp_v4_send_check(struct sock *sk, int len,
+extern void tcp_v4_send_check(struct sock *sk,
struct sk_buff *skb);
extern int tcp_v4_conn_request(struct sock *sk,
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 5ef32c2..33035ab 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -223,7 +223,7 @@ static inline void dccp_csum_outgoing(struct sk_buff *skb)
skb->csum = skb_checksum(skb, 0, (cov > skb->len)? skb->len : cov, 0);
}
-extern void dccp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
+extern void dccp_v4_send_check(struct sock *sk, struct sk_buff *skb);
extern int dccp_retransmit_skb(struct sock *sk);
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 52ffa1c..d9b11ef 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -349,7 +349,7 @@ static inline __sum16 dccp_v4_csum_finish(struct sk_buff *skb,
return csum_tcpudp_magic(src, dst, skb->len, IPPROTO_DCCP, skb->csum);
}
-void dccp_v4_send_check(struct sock *sk, int unused, struct sk_buff *skb)
+void dccp_v4_send_check(struct sock *sk, struct sk_buff *skb)
{
const struct inet_sock *inet = inet_sk(sk);
struct dccp_hdr *dh = dccp_hdr(skb);
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 3b11e41..ab1ab95 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -60,8 +60,7 @@ static inline __sum16 dccp_v6_csum_finish(struct sk_buff *skb,
return csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_DCCP, skb->csum);
}
-static inline void dccp_v6_send_check(struct sock *sk, int unused_value,
- struct sk_buff *skb)
+static inline void dccp_v6_send_check(struct sock *sk, struct sk_buff *skb)
{
struct ipv6_pinfo *np = inet6_sk(sk);
struct dccp_hdr *dh = dccp_hdr(skb);
diff --git a/net/dccp/output.c b/net/dccp/output.c
index fc3f436..b8d98e3 100644
--- a/net/dccp/output.c
+++ b/net/dccp/output.c
@@ -129,7 +129,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb)
break;
}
- icsk->icsk_af_ops->send_check(sk, 0, skb);
+ icsk->icsk_af_ops->send_check(sk, skb);
if (set_ack)
dccp_event_ack_sent(sk);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index aebfd28..a24995c 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -537,7 +537,7 @@ static void __tcp_v4_send_check(struct sk_buff *skb,
}
/* This routine computes an IPv4 TCP checksum. */
-void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb)
+void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb)
{
struct inet_sock *inet = inet_sk(sk);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 0dda86e..0ae7ce7 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -878,7 +878,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
}
#endif
- icsk->icsk_af_ops->send_check(sk, skb->len, skb);
+ icsk->icsk_af_ops->send_check(sk, skb);
if (likely(tcb->flags & TCPCB_FLAG_ACK))
tcp_event_ack_sent(sk, tcp_skb_pcount(skb));
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index f84c506..b429dfd 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -933,7 +933,7 @@ static void __tcp_v6_send_check(struct sk_buff *skb,
}
}
-static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
+static void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
{
struct ipv6_pinfo *np = inet6_sk(sk);
^ permalink raw reply related
* [PATCH 2/3] tcp: Handle CHECKSUM_PARTIAL for SYNACK packets for IPv6
From: Herbert Xu @ 2010-04-11 12:15 UTC (permalink / raw)
To: davem, yinghai, linux-kernel, netdev, torvalds
In-Reply-To: <20100411100902.GA20141@gondor.apana.org.au>
tcp: Handle CHECKSUM_PARTIAL for SYNACK packets for IPv6
This patch moves the common code between tcp_v6_send_check and
tcp_v6_gso_send_check into a new function __tcp_v6_send_check.
It then uses the new function in tcp_v6_send_synack as well as
tcp_v6_send_response so that they handle CHECKSUM_PARTIAL properly.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
net/ipv6/tcp_ipv6.c | 37 +++++++++++++++++++------------------
1 file changed, 19 insertions(+), 18 deletions(-)
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index c92ebe8..f84c506 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -75,6 +75,9 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
struct request_sock *req);
static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
+static void __tcp_v6_send_check(struct sk_buff *skb,
+ struct in6_addr *saddr,
+ struct in6_addr *daddr);
static const struct inet_connection_sock_af_ops ipv6_mapped;
static const struct inet_connection_sock_af_ops ipv6_specific;
@@ -503,11 +506,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
skb = tcp_make_synack(sk, dst, req, rvp);
if (skb) {
- struct tcphdr *th = tcp_hdr(skb);
-
- th->check = tcp_v6_check(skb->len,
- &treq->loc_addr, &treq->rmt_addr,
- csum_partial(th, skb->len, skb->csum));
+ __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr);
ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
err = ip6_xmit(sk, skb, &fl, opt, 0);
@@ -918,22 +917,29 @@ static struct timewait_sock_ops tcp6_timewait_sock_ops = {
.twsk_destructor= tcp_twsk_destructor,
};
-static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
+static void __tcp_v6_send_check(struct sk_buff *skb,
+ struct in6_addr *saddr, struct in6_addr *daddr)
{
- struct ipv6_pinfo *np = inet6_sk(sk);
struct tcphdr *th = tcp_hdr(skb);
if (skb->ip_summed == CHECKSUM_PARTIAL) {
- th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0);
+ th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
skb->csum_start = skb_transport_header(skb) - skb->head;
skb->csum_offset = offsetof(struct tcphdr, check);
} else {
- th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP,
- csum_partial(th, th->doff<<2,
- skb->csum));
+ th->check = tcp_v6_check(skb->len, saddr, daddr,
+ csum_partial(th, th->doff << 2,
+ skb->csum));
}
}
+static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb)
+{
+ struct ipv6_pinfo *np = inet6_sk(sk);
+
+ __tcp_v6_send_check(skb, &np->saddr, &np->daddr);
+}
+
static int tcp_v6_gso_send_check(struct sk_buff *skb)
{
struct ipv6hdr *ipv6h;
@@ -946,11 +952,8 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb)
th = tcp_hdr(skb);
th->check = 0;
- th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
- IPPROTO_TCP, 0);
- skb->csum_start = skb_transport_header(skb) - skb->head;
- skb->csum_offset = offsetof(struct tcphdr, check);
skb->ip_summed = CHECKSUM_PARTIAL;
+ __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr);
return 0;
}
@@ -1053,9 +1056,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
ipv6_addr_copy(&fl.fl6_dst, &ipv6_hdr(skb)->saddr);
ipv6_addr_copy(&fl.fl6_src, &ipv6_hdr(skb)->daddr);
- t1->check = csum_ipv6_magic(&fl.fl6_src, &fl.fl6_dst,
- tot_len, IPPROTO_TCP,
- buff->csum);
+ __tcp_v6_send_check(buff, &fl.fl6_src, &fl.fl6_dst);
fl.proto = IPPROTO_TCP;
fl.oif = inet6_iif(skb);
^ permalink raw reply related
* Re: [PATCH 2/2] [V5] Add non-Virtex5 support for LL TEMAC driver
From: Michal Simek @ 2010-04-11 13:16 UTC (permalink / raw)
To: John Linn
Cc: netdev, linuxppc-dev, grant.likely, jwboyer, eric.dumazet,
john.williams, John Tyner
In-Reply-To: <960dddba-8a63-4480-8245-f06fad59ab36@SG2EHSMHS005.ehs.local>
John Linn wrote:
> This patch adds support for using the LL TEMAC Ethernet driver on
> non-Virtex 5 platforms by adding support for accessing the Soft DMA
> registers as if they were memory mapped instead of solely through the
> DCR's (available on the Virtex 5).
>
> The patch also updates the driver so that it runs on the MicroBlaze.
> The changes were tested on the PowerPC 440, PowerPC 405, and the
> MicroBlaze platforms.
>
> Signed-off-by: John Tyner <jtyner@cs.ucr.edu>
> Signed-off-by: John Linn <john.linn@xilinx.com>
>
> ---
>
> V2 - Incorporated comments from Grant and added more logic to allow the driver
> to work on MicroBlaze.
>
> V3 - Only updated it to apply to head, minor change to include slab.h. Also
> verified that it now builds for MicroBlaze. Retested on PowerPC and MicroBlaze.
>
> V4 - Removed buffer alignment for skb and called the network functions that
> already do the alignment for cache line and word alignment. Added constants
> to MicroBlaze system to make sure network alignment is maintained. Also updated
> the Kconfig so it depends on Microblaze or PPC based on Grant's comment.
>
> V5 - Respun the patch on top of a new patch to the driver which removed the
> call to virt_to_bus as it's now illegal and caused a failure when building
> the driver in linux-next. Retested with 440, 405 and Microblaze.
>
> Grant, can you do a build test to verify no build issues?
> ---
> arch/microblaze/include/asm/system.h | 11 +++
> drivers/net/Kconfig | 2 +-
> drivers/net/ll_temac.h | 14 +++-
> drivers/net/ll_temac_main.c | 137 +++++++++++++++++++++++++--------
> 4 files changed, 126 insertions(+), 38 deletions(-)
>
> diff --git a/arch/microblaze/include/asm/system.h b/arch/microblaze/include/asm/system.h
> index 59efb3f..48c4f03 100644
> --- a/arch/microblaze/include/asm/system.h
> +++ b/arch/microblaze/include/asm/system.h
> @@ -12,6 +12,7 @@
> #include <asm/registers.h>
> #include <asm/setup.h>
> #include <asm/irqflags.h>
> +#include <asm/cache.h>
>
> #include <asm-generic/cmpxchg.h>
> #include <asm-generic/cmpxchg-local.h>
> @@ -96,4 +97,14 @@ extern struct dentry *of_debugfs_root;
>
> #define arch_align_stack(x) (x)
>
> +/*
> + * MicroBlaze doesn't handle unaligned accesses in hardware.
> + *
> + * Based on this we force the IP header alignment in network drivers.
> + * We also modify NET_SKB_PAD to be a cacheline in size, thus maintaining
> + * cacheline alignment of buffers.
> + */
> +#define NET_IP_ALIGN 2
> +#define NET_SKB_PAD L1_CACHE_BYTES
> +
> #endif /* _ASM_MICROBLAZE_SYSTEM_H */
I personally prefer to separate this from this patch as we did with
ioread/iowrite.
Michal
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 7b832c7..9073741 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -2434,8 +2434,8 @@ config MV643XX_ETH
>
> config XILINX_LL_TEMAC
> tristate "Xilinx LL TEMAC (LocalLink Tri-mode Ethernet MAC) driver"
> + depends on PPC || MICROBLAZE
> select PHYLIB
> - depends on PPC_DCR_NATIVE
> help
> This driver supports the Xilinx 10/100/1000 LocalLink TEMAC
> core used in Xilinx Spartan and Virtex FPGAs
> diff --git a/drivers/net/ll_temac.h b/drivers/net/ll_temac.h
> index 1af66a1..c033584 100644
> --- a/drivers/net/ll_temac.h
> +++ b/drivers/net/ll_temac.h
> @@ -5,8 +5,11 @@
> #include <linux/netdevice.h>
> #include <linux/of.h>
> #include <linux/spinlock.h>
> +
> +#ifdef CONFIG_PPC_DCR
> #include <asm/dcr.h>
> #include <asm/dcr-regs.h>
> +#endif
>
> /* packet size info */
> #define XTE_HDR_SIZE 14 /* size of Ethernet header */
> @@ -290,9 +293,6 @@ This option defaults to enabled (set) */
>
> #define TX_CONTROL_CALC_CSUM_MASK 1
>
> -#define XTE_ALIGN 32
> -#define BUFFER_ALIGN(adr) ((XTE_ALIGN - ((u32) adr)) % XTE_ALIGN)
> -
> #define MULTICAST_CAM_TABLE_NUM 4
>
> /* TX/RX CURDESC_PTR points to first descriptor */
> @@ -335,9 +335,15 @@ struct temac_local {
> struct mii_bus *mii_bus; /* MII bus reference */
> int mdio_irqs[PHY_MAX_ADDR]; /* IRQs table for MDIO bus */
>
> - /* IO registers and IRQs */
> + /* IO registers, dma functions and IRQs */
> void __iomem *regs;
> + void __iomem *sdma_regs;
> +#ifdef CONFIG_PPC_DCR
> dcr_host_t sdma_dcrs;
> +#endif
> + u32 (*dma_in)(struct temac_local *, int);
> + void (*dma_out)(struct temac_local *, int, u32);
> +
> int tx_irq;
> int rx_irq;
> int emac_num;
> diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c
> index ce9aa78..2b69d6c 100644
> --- a/drivers/net/ll_temac_main.c
> +++ b/drivers/net/ll_temac_main.c
> @@ -20,9 +20,6 @@
> * or rx, so this should be okay.
> *
> * TODO:
> - * - Fix driver to work on more than just Virtex5. Right now the driver
> - * assumes that the locallink DMA registers are accessed via DCR
> - * instructions.
> * - Factor out locallink DMA code into separate driver
> * - Fix multicast assignment.
> * - Fix support for hardware checksumming.
> @@ -116,17 +113,86 @@ void temac_indirect_out32(struct temac_local *lp, int reg, u32 value)
> temac_iow(lp, XTE_CTL0_OFFSET, CNTLREG_WRITE_ENABLE_MASK | reg);
> }
>
> +/**
> + * temac_dma_in32 - Memory mapped DMA read, this function expects a
> + * register input that is based on DCR word addresses which
> + * are then converted to memory mapped byte addresses
> + */
> static u32 temac_dma_in32(struct temac_local *lp, int reg)
> {
> - return dcr_read(lp->sdma_dcrs, reg);
> + return in_be32((u32 *)(lp->sdma_regs + (reg << 2)));
> }
>
> +/**
> + * temac_dma_out32 - Memory mapped DMA read, this function expects a
> + * register input that is based on DCR word addresses which
> + * are then converted to memory mapped byte addresses
> + */
> static void temac_dma_out32(struct temac_local *lp, int reg, u32 value)
> {
> + out_be32((u32 *)(lp->sdma_regs + (reg << 2)), value);
> +}
> +
> +/* DMA register access functions can be DCR based or memory mapped.
> + * The PowerPC 440 is DCR based, the PowerPC 405 and MicroBlaze are both
> + * memory mapped.
> + */
> +#ifdef CONFIG_PPC_DCR
> +
> +/**
> + * temac_dma_dcr_in32 - DCR based DMA read
> + */
> +static u32 temac_dma_dcr_in(struct temac_local *lp, int reg)
> +{
> + return dcr_read(lp->sdma_dcrs, reg);
> +}
> +
> +/**
> + * temac_dma_dcr_out32 - DCR based DMA write
> + */
> +static void temac_dma_dcr_out(struct temac_local *lp, int reg, u32 value)
> +{
> dcr_write(lp->sdma_dcrs, reg, value);
> }
>
> /**
> + * temac_dcr_setup - If the DMA is DCR based, then setup the address and
> + * I/O functions
> + */
> +static int temac_dcr_setup(struct temac_local *lp, struct of_device *op,
> + struct device_node *np)
> +{
> + unsigned int dcrs;
> +
> + /* setup the dcr address mapping if it's in the device tree */
> +
> + dcrs = dcr_resource_start(np, 0);
> + if (dcrs != 0) {
> + lp->sdma_dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0));
> + lp->dma_in = temac_dma_dcr_in;
> + lp->dma_out = temac_dma_dcr_out;
> + dev_dbg(&op->dev, "DCR base: %x\n", dcrs);
> + return 0;
> + }
> + /* no DCR in the device tree, indicate a failure */
> + return -1;
> +}
> +
> +#else
> +
> +/*
> + * temac_dcr_setup - This is a stub for when DCR is not supported,
> + * such as with MicroBlaze
> + */
> +static int temac_dcr_setup(struct temac_local *lp, struct of_device *op,
> + struct device_node *np)
> +{
> + return -1;
> +}
> +
> +#endif
> +
> +/**
> * temac_dma_bd_init - Setup buffer descriptor rings
> */
> static int temac_dma_bd_init(struct net_device *ndev)
> @@ -156,14 +222,14 @@ static int temac_dma_bd_init(struct net_device *ndev)
> lp->rx_bd_v[i].next = lp->rx_bd_p +
> sizeof(*lp->rx_bd_v) * ((i + 1) % RX_BD_NUM);
>
> - skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE
> - + XTE_ALIGN, GFP_ATOMIC);
> + skb = netdev_alloc_skb_ip_align(ndev,
> + XTE_MAX_JUMBO_FRAME_SIZE);
> +
> if (skb == 0) {
> dev_err(&ndev->dev, "alloc_skb error %d\n", i);
> return -1;
> }
> lp->rx_skb[i] = skb;
> - skb_reserve(skb, BUFFER_ALIGN(skb->data));
> /* returns physical address of skb->data */
> lp->rx_bd_v[i].phys = dma_map_single(ndev->dev.parent,
> skb->data,
> @@ -173,23 +239,23 @@ static int temac_dma_bd_init(struct net_device *ndev)
> lp->rx_bd_v[i].app0 = STS_CTRL_APP0_IRQONEND;
> }
>
> - temac_dma_out32(lp, TX_CHNL_CTRL, 0x10220400 |
> + lp->dma_out(lp, TX_CHNL_CTRL, 0x10220400 |
> CHNL_CTRL_IRQ_EN |
> CHNL_CTRL_IRQ_DLY_EN |
> CHNL_CTRL_IRQ_COAL_EN);
> /* 0x10220483 */
> /* 0x00100483 */
> - temac_dma_out32(lp, RX_CHNL_CTRL, 0xff010000 |
> + lp->dma_out(lp, RX_CHNL_CTRL, 0xff010000 |
> CHNL_CTRL_IRQ_EN |
> CHNL_CTRL_IRQ_DLY_EN |
> CHNL_CTRL_IRQ_COAL_EN |
> CHNL_CTRL_IRQ_IOE);
> /* 0xff010283 */
>
> - temac_dma_out32(lp, RX_CURDESC_PTR, lp->rx_bd_p);
> - temac_dma_out32(lp, RX_TAILDESC_PTR,
> + lp->dma_out(lp, RX_CURDESC_PTR, lp->rx_bd_p);
> + lp->dma_out(lp, RX_TAILDESC_PTR,
> lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1)));
> - temac_dma_out32(lp, TX_CURDESC_PTR, lp->tx_bd_p);
> + lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p);
>
> return 0;
> }
> @@ -427,9 +493,9 @@ static void temac_device_reset(struct net_device *ndev)
> temac_indirect_out32(lp, XTE_RXC1_OFFSET, val & ~XTE_RXC1_RXEN_MASK);
>
> /* Reset Local Link (DMA) */
> - temac_dma_out32(lp, DMA_CONTROL_REG, DMA_CONTROL_RST);
> + lp->dma_out(lp, DMA_CONTROL_REG, DMA_CONTROL_RST);
> timeout = 1000;
> - while (temac_dma_in32(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) {
> + while (lp->dma_in(lp, DMA_CONTROL_REG) & DMA_CONTROL_RST) {
> udelay(1);
> if (--timeout == 0) {
> dev_err(&ndev->dev,
> @@ -437,7 +503,7 @@ static void temac_device_reset(struct net_device *ndev)
> break;
> }
> }
> - temac_dma_out32(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE);
> + lp->dma_out(lp, DMA_CONTROL_REG, DMA_TAIL_ENABLE);
>
> temac_dma_bd_init(ndev);
>
> @@ -598,7 +664,7 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
> lp->tx_bd_tail = 0;
>
> /* Kick off the transfer */
> - temac_dma_out32(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */
> + lp->dma_out(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */
>
> return NETDEV_TX_OK;
> }
> @@ -638,16 +704,15 @@ static void ll_temac_recv(struct net_device *ndev)
> ndev->stats.rx_packets++;
> ndev->stats.rx_bytes += length;
>
> - new_skb = alloc_skb(XTE_MAX_JUMBO_FRAME_SIZE + XTE_ALIGN,
> - GFP_ATOMIC);
> + new_skb = netdev_alloc_skb_ip_align(ndev,
> + XTE_MAX_JUMBO_FRAME_SIZE);
> +
> if (new_skb == 0) {
> dev_err(&ndev->dev, "no memory for new sk_buff\n");
> spin_unlock_irqrestore(&lp->rx_lock, flags);
> return;
> }
>
> - skb_reserve(new_skb, BUFFER_ALIGN(new_skb->data));
> -
> cur_p->app0 = STS_CTRL_APP0_IRQONEND;
> cur_p->phys = dma_map_single(ndev->dev.parent, new_skb->data,
> XTE_MAX_JUMBO_FRAME_SIZE,
> @@ -662,7 +727,7 @@ static void ll_temac_recv(struct net_device *ndev)
> cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
> bdstat = cur_p->app0;
> }
> - temac_dma_out32(lp, RX_TAILDESC_PTR, tail_p);
> + lp->dma_out(lp, RX_TAILDESC_PTR, tail_p);
>
> spin_unlock_irqrestore(&lp->rx_lock, flags);
> }
> @@ -673,8 +738,8 @@ static irqreturn_t ll_temac_tx_irq(int irq, void *_ndev)
> struct temac_local *lp = netdev_priv(ndev);
> unsigned int status;
>
> - status = temac_dma_in32(lp, TX_IRQ_REG);
> - temac_dma_out32(lp, TX_IRQ_REG, status);
> + status = lp->dma_in(lp, TX_IRQ_REG);
> + lp->dma_out(lp, TX_IRQ_REG, status);
>
> if (status & (IRQ_COAL | IRQ_DLY))
> temac_start_xmit_done(lp->ndev);
> @@ -691,8 +756,8 @@ static irqreturn_t ll_temac_rx_irq(int irq, void *_ndev)
> unsigned int status;
>
> /* Read and clear the status registers */
> - status = temac_dma_in32(lp, RX_IRQ_REG);
> - temac_dma_out32(lp, RX_IRQ_REG, status);
> + status = lp->dma_in(lp, RX_IRQ_REG);
> + lp->dma_out(lp, RX_IRQ_REG, status);
>
> if (status & (IRQ_COAL | IRQ_DLY))
> ll_temac_recv(lp->ndev);
> @@ -793,7 +858,7 @@ static ssize_t temac_show_llink_regs(struct device *dev,
> int i, len = 0;
>
> for (i = 0; i < 0x11; i++)
> - len += sprintf(buf + len, "%.8x%s", temac_dma_in32(lp, i),
> + len += sprintf(buf + len, "%.8x%s", lp->dma_in(lp, i),
> (i % 8) == 7 ? "\n" : " ");
> len += sprintf(buf + len, "\n");
>
> @@ -819,7 +884,6 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
> struct net_device *ndev;
> const void *addr;
> int size, rc = 0;
> - unsigned int dcrs;
>
> /* Init network device structure */
> ndev = alloc_etherdev(sizeof(*lp));
> @@ -869,13 +933,20 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match)
> goto nodev;
> }
>
> - dcrs = dcr_resource_start(np, 0);
> - if (dcrs == 0) {
> - dev_err(&op->dev, "could not get DMA register address\n");
> - goto nodev;
> + /* Setup the DMA register accesses, could be DCR or memory mapped */
> + if (temac_dcr_setup(lp, op, np)) {
> +
> + /* no DCR in the device tree, try non-DCR */
> + lp->sdma_regs = of_iomap(np, 0);
> + if (lp->sdma_regs) {
> + lp->dma_in = temac_dma_in32;
> + lp->dma_out = temac_dma_out32;
> + dev_dbg(&op->dev, "MEM base: %p\n", lp->sdma_regs);
> + } else {
> + dev_err(&op->dev, "unable to map DMA registers\n");
> + goto nodev;
> + }
> }
> - lp->sdma_dcrs = dcr_map(np, dcrs, dcr_resource_len(np, 0));
> - dev_dbg(&op->dev, "DCR base: %x\n", dcrs);
>
> lp->rx_irq = irq_of_parse_and_map(np, 0);
> lp->tx_irq = irq_of_parse_and_map(np, 1);
--
Michal Simek, Ing. (M.Eng)
PetaLogix - Linux Solutions for a Reconfigurable World
w: www.petalogix.com p: +61-7-30090663,+42-0-721842854 f: +61-7-30090663
^ permalink raw reply
* [PATCH] rps: add flow director support
From: Changli Gao @ 2010-04-11 21:42 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Changli Gao
add rps flow director support
with rps flow director, users can do weighted packet dispatching among CPUs.
For example, CPU0:CPU1 is 1:3 for eth0's rx-0:
localhost linux # echo 4 > /sys/class/net/eth0/queues/rx-0/rps_flows
localhost linux # echo 0 > /sys/class/net/eth0/queues/rx-0/rps_flow_0
localhost linux # echo 1 > /sys/class/net/eth0/queues/rx-0/rps_flow_1
localhost linux # echo 1 > /sys/class/net/eth0/queues/rx-0/rps_flow_2
localhost linux # echo 1 > /sys/class/net/eth0/queues/rx-0/rps_flow_3
Signed-off-by: Changli Gao <xiaosuo@gmail.com>
----
net/core/net-sysfs.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 172 insertions(+), 4 deletions(-)
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 1e7fdd6..d904610 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -511,6 +511,109 @@ static struct sysfs_ops rx_queue_sysfs_ops = {
.store = rx_queue_attr_store,
};
+static DEFINE_MUTEX(rps_map_lock);
+
+static ssize_t show_rps_flow(struct netdev_rx_queue *queue,
+ struct rx_queue_attribute *attribute, char *buf)
+{
+ unsigned long flowid;
+ struct rps_map *map;
+ u16 cpu;
+
+ strict_strtoul(attribute->attr.name + strlen("rps_flow_"), 10, &flowid);
+ rcu_read_lock();
+ map = rcu_dereference(queue->rps_map);
+ if (map && flowid < map->len)
+ cpu = map->cpus[flowid];
+ else
+ cpu = 0;
+ rcu_read_unlock();
+ return sprintf(buf, "%hu\n", cpu);
+}
+
+static ssize_t store_rps_flow(struct netdev_rx_queue *queue,
+ struct rx_queue_attribute *attribute,
+ const char *buf, size_t len)
+{
+ unsigned long flowid, cpu;
+ struct rps_map *map;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (strict_strtoul(buf, 0, &cpu))
+ return -EINVAL;
+ strict_strtoul(attribute->attr.name + strlen("rps_flow_"), 10, &flowid);
+
+ mutex_lock(&rps_map_lock);
+ map = queue->rps_map;
+ if (map && flowid < map->len)
+ map->cpus[flowid] = cpu;
+ mutex_unlock(&rps_map_lock);
+
+ return len;
+}
+
+static struct rx_queue_attribute **rps_flow_attribute;
+static int rps_flow_attribute_size;
+
+/* must be called with rps_map_lock locked */
+static int update_rps_flow_files(struct kobject *kobj,
+ struct rps_map *old_map, struct rps_map *map)
+{
+ int i;
+ int old_map_len = old_map ? old_map->len : 0;
+ int map_len = map ? map->len : 0;
+
+ if (old_map_len >= map_len) {
+ for (i = map_len; i < old_map_len; i++)
+ sysfs_remove_file(kobj, &rps_flow_attribute[i]->attr);
+ return 0;
+ }
+
+ if (map_len > rps_flow_attribute_size) {
+ struct rx_queue_attribute **attrs;
+ char name[sizeof("rps_flow_4294967295")];
+ char *pname;
+
+ attrs = krealloc(rps_flow_attribute, map_len * sizeof(void *),
+ GFP_KERNEL);
+ if (attrs == NULL)
+ return -ENOMEM;
+ rps_flow_attribute = attrs;
+ for (i = rps_flow_attribute_size; i < map_len; i++) {
+ rps_flow_attribute[i] = kmalloc(sizeof(**attrs),
+ GFP_KERNEL);
+ if (rps_flow_attribute[i] == NULL)
+ break;
+ sprintf(name, "rps_flow_%d", i);
+ pname = kstrdup(name, GFP_KERNEL);
+ if (pname == NULL) {
+ kfree(rps_flow_attribute[i]);
+ break;
+ }
+ rps_flow_attribute[i]->attr.name = pname;
+ rps_flow_attribute[i]->attr.mode = S_IRUGO | S_IWUSR;
+ rps_flow_attribute[i]->show = show_rps_flow;
+ rps_flow_attribute[i]->store = store_rps_flow;
+ }
+ rps_flow_attribute_size = i;
+ if (i != map_len)
+ return -ENOMEM;
+ }
+
+ for (i = old_map_len; i < map_len; i++) {
+ if (sysfs_create_file(kobj, &rps_flow_attribute[i]->attr)) {
+ while (--i >= old_map_len)
+ sysfs_remove_file(kobj,
+ &rps_flow_attribute[i]->attr);
+ return -ENOMEM;
+ }
+ }
+
+ return 0;
+}
+
static ssize_t show_rps_map(struct netdev_rx_queue *queue,
struct rx_queue_attribute *attribute, char *buf)
{
@@ -555,7 +658,6 @@ ssize_t store_rps_map(struct netdev_rx_queue *queue,
struct rps_map *old_map, *map;
cpumask_var_t mask;
int err, cpu, i;
- static DEFINE_SPINLOCK(rps_map_lock);
if (!capable(CAP_NET_ADMIN))
return -EPERM;
@@ -588,10 +690,15 @@ ssize_t store_rps_map(struct netdev_rx_queue *queue,
map = NULL;
}
- spin_lock(&rps_map_lock);
+ mutex_lock(&rps_map_lock);
old_map = queue->rps_map;
- rcu_assign_pointer(queue->rps_map, map);
- spin_unlock(&rps_map_lock);
+ err = update_rps_flow_files(&queue->kobj, old_map, map);
+ if (!err)
+ rcu_assign_pointer(queue->rps_map, map);
+ mutex_unlock(&rps_map_lock);
+
+ if (err)
+ return err;
if (old_map)
call_rcu(&old_map->rcu, rps_map_release);
@@ -603,8 +710,69 @@ ssize_t store_rps_map(struct netdev_rx_queue *queue,
static struct rx_queue_attribute rps_cpus_attribute =
__ATTR(rps_cpus, S_IRUGO | S_IWUSR, show_rps_map, store_rps_map);
+static ssize_t show_rps_flows(struct netdev_rx_queue *queue,
+ struct rx_queue_attribute *attribute, char *buf)
+{
+ struct rps_map *map;
+ unsigned int len;
+
+ rcu_read_lock();
+ map = rcu_dereference(queue->rps_map);
+ len = map ? map->len : 0;
+ rcu_read_unlock();
+ return sprintf(buf, "%u\n", len);
+}
+
+static ssize_t store_rps_flows(struct netdev_rx_queue *queue,
+ struct rx_queue_attribute *attribute,
+ const char *buf, size_t len)
+{
+ struct rps_map *old_map, *map;
+ unsigned long flows;
+ int err;
+
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (strict_strtoul(buf, 0, &flows))
+ return -EINVAL;
+ if (flows != 0) {
+ map = kzalloc(max_t(unsigned, RPS_MAP_SIZE(flows),
+ L1_CACHE_BYTES), GFP_KERNEL);
+ if (map == NULL)
+ return -ENOMEM;
+ map->len = flows;
+ } else {
+ map = NULL;
+ }
+
+ mutex_lock(&rps_map_lock);
+ old_map = queue->rps_map;
+ err = update_rps_flow_files(&queue->kobj, old_map, map);
+ if (!err) {
+ if (old_map && map)
+ memcpy(map->cpus, old_map->cpus,
+ sizeof(map->cpus[0]) *
+ min_t(unsigned int, flows, old_map->len));
+ rcu_assign_pointer(queue->rps_map, map);
+ }
+ mutex_unlock(&rps_map_lock);
+
+ if (err)
+ return err;
+
+ if (old_map)
+ call_rcu(&old_map->rcu, rps_map_release);
+
+ return len;
+}
+
+static struct rx_queue_attribute rps_flows_attribute =
+ __ATTR(rps_flows, S_IRUGO | S_IWUSR, show_rps_flows, store_rps_flows);
+
static struct attribute *rx_queue_default_attrs[] = {
&rps_cpus_attribute.attr,
+ &rps_flows_attribute.attr,
NULL
};
^ permalink raw reply related
* Re: [PATCH v2] can: Add esd board support to plx_pci CAN driver
From: Wolfgang Grandegger @ 2010-04-11 14:50 UTC (permalink / raw)
To: Matthias Fuchs
Cc: Socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <201004071309.56518.matthias.fuchs-iOnpLzIbIdM@public.gmane.org>
Matthias Fuchs wrote:
> This patch adds support for SJA1000 based PCI CAN interface cards
> from electronic system design gmbh.
>
> Some changes have been done on the common code:
> - esd boards must not have the 2nd local interupt enabled (PLX9030/9050)
> - a new path for PLX9056/PEX8311 chips has been added
> - new plx9056 reset function has been implemented
> - struct plx_card_info got a reset function entry
>
> In detail the following additional boards are now supported:
>
> CAN-PCI/200 (PCI)
> CAN-PCI/266 (PCI)
> CAN-PMC266 (PMC module)
> CAN-PCIe/2000 (PCI Express)
> CAN-CPCI/200 (Compact PCI, 3U)
> CAN-PCI104 (PCI104)
>
> Signed-off-by: Matthias Fuchs <matthias.fuchs-iOnpLzIbIdM@public.gmane.org>
> ---
> v2:
> - update Kconfig
> - add proper plx9056 reset function
> - add reset function pointer to plx_card_info structure
> - use card's reset function in plx_pci_del_card()
Acked-by: Wolfgang Grandegger <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
Thanks.
Wolfgang.
^ permalink raw reply
* Re: [PATCH] vhost: Make it more scalable by creating a vhost thread per device.
From: Michael S. Tsirkin @ 2010-04-11 15:47 UTC (permalink / raw)
To: Sridhar Samudrala; +Cc: Tom Lendacky, netdev, kvm@vger.kernel.org
In-Reply-To: <1270771542.31186.397.camel@w-sridhar.beaverton.ibm.com>
On Thu, Apr 08, 2010 at 05:05:42PM -0700, Sridhar Samudrala wrote:
> On Mon, 2010-04-05 at 10:35 -0700, Sridhar Samudrala wrote:
> > On Sun, 2010-04-04 at 14:14 +0300, Michael S. Tsirkin wrote:
> > > On Fri, Apr 02, 2010 at 10:31:20AM -0700, Sridhar Samudrala wrote:
> > > > Make vhost scalable by creating a separate vhost thread per vhost
> > > > device. This provides better scaling across multiple guests and with
> > > > multiple interfaces in a guest.
> > >
> > > Thanks for looking into this. An alternative approach is
> > > to simply replace create_singlethread_workqueue with
> > > create_workqueue which would get us a thread per host CPU.
> > >
> > > It seems that in theory this should be the optimal approach
> > > wrt CPU locality, however, in practice a single thread
> > > seems to get better numbers. I have a TODO to investigate this.
> > > Could you try looking into this?
> >
> > Yes. I tried using create_workqueue(), but the results were not good
> > atleast when the number of guest interfaces is less than the number
> > of CPUs. I didn't try more than 8 guests.
> > Creating a separate thread per guest interface seems to be more
> > scalable based on the testing i have done so far.
> >
> > I will try some more tests and get some numbers to compare the following
> > 3 options.
> > - single vhost thread
> > - vhost thread per cpu
> > - vhost thread per guest virtio interface
>
> Here are the results with netperf TCP_STREAM 64K guest to host on a
> 8-cpu Nehalem system. It shows cumulative bandwidth in Mbps and host
> CPU utilization.
>
> Current default single vhost thread
> -----------------------------------
> 1 guest: 12500 37%
> 2 guests: 12800 46%
> 3 guests: 12600 47%
> 4 guests: 12200 47%
> 5 guests: 12000 47%
> 6 guests: 11700 47%
> 7 guests: 11340 47%
> 8 guests: 11200 48%
>
> vhost thread per cpu
> --------------------
> 1 guest: 4900 25%
> 2 guests: 10800 49%
> 3 guests: 17100 67%
> 4 guests: 20400 84%
> 5 guests: 21000 90%
> 6 guests: 22500 92%
> 7 guests: 23500 96%
> 8 guests: 24500 99%
>
> vhost thread per guest interface
> --------------------------------
> 1 guest: 12500 37%
> 2 guests: 21000 72%
> 3 guests: 21600 79%
> 4 guests: 21600 85%
> 5 guests: 22500 89%
> 6 guests: 22800 94%
> 7 guests: 24500 98%
> 8 guests: 26400 99%
>
> Thanks
> Sridhar
Consider using Ingo's perf tool to get error bars, but looks good
overall. One thing I note though is that we seem to be able to
consume up to 99% CPU now. So I think with this approach
we can no longer claim that we are just like some other parts of
networking stack, doing work outside any cgroup, and we should
make the vhost thread inherit the cgroup and cpu mask
from the process calling SET_OWNER.
--
MST
^ permalink raw reply
* Re: [PATCH] rps: add flow director support
From: Eric Dumazet @ 2010-04-11 16:05 UTC (permalink / raw)
To: Changli Gao; +Cc: David S. Miller, netdev, Tom Herbert
In-Reply-To: <1271022140-3917-1-git-send-email-xiaosuo@gmail.com>
Le lundi 12 avril 2010 à 05:42 +0800, Changli Gao a écrit :
> add rps flow director support
>
> with rps flow director, users can do weighted packet dispatching among CPUs.
> For example, CPU0:CPU1 is 1:3 for eth0's rx-0:
>
> localhost linux # echo 4 > /sys/class/net/eth0/queues/rx-0/rps_flows
> localhost linux # echo 0 > /sys/class/net/eth0/queues/rx-0/rps_flow_0
> localhost linux # echo 1 > /sys/class/net/eth0/queues/rx-0/rps_flow_1
> localhost linux # echo 1 > /sys/class/net/eth0/queues/rx-0/rps_flow_2
> localhost linux # echo 1 > /sys/class/net/eth0/queues/rx-0/rps_flow_3
>
> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
> ----
Changli
I am a bit disappointed to find so many bugs in your patch.
I believe this is over engineering at this stage, we yet have to get
some benches or real world results.
Plus it conflicts with the much more interesting upcoming stuff (RFS).
You name this patch 'flow director', to get our attention, but it's an
old idea of you, to get different weights on cpus, that RPS is not yet
able to perform.
Maybe this is the reason you forgot to CC Tom Herbert (and me) ?
Consider now :
1) echo 65000 >/sys/class/net/eth0/queues/rx-0/rps_flow_0
possible crash, dereferencing a smaller cpumap.
2) echo 3000000000 >/sys/class/net/eth0/queues/rx-0/rps_flow_0
probable crash, because of overflow in RPS_MAP_SIZE(flows)
3) How can rps_flow_attribute & rps_flow_attribute_size be static (one
instance for whole kernel), if your intent is to have a per rxqueue
attributes ? (/sys/class/net/eth0/queues/rx-0/ ...). Or the first lines
of update_rps_flow_files() are completely wrong...
echo 10 > /sys/class/net/eth0/queues/rx-0/rps_flows
echo 2 > /sys/class/net/eth1/queues/rx-0/rps_flows
cat /sys/class/net/eth0/queues/rx-0/rps_flow_9
4) Lack of atomic changes of the RPS flows -> many packet reordering can
occur.
5) Many possible memory leaks in update_rps_flow_files(), you obviously
were very lazy. We try to build a bug-free kernel, not only a 'cool
kernel', and if you are lazy, your patches wont be accepted.
> net/core/net-sysfs.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 172 insertions(+), 4 deletions(-)
> diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
> index 1e7fdd6..d904610 100644
> --- a/net/core/net-sysfs.c
> +++ b/net/core/net-sysfs.c
> @@ -511,6 +511,109 @@ static struct sysfs_ops rx_queue_sysfs_ops = {
> .store = rx_queue_attr_store,
> };
>
> +static DEFINE_MUTEX(rps_map_lock);
> +
> +static ssize_t show_rps_flow(struct netdev_rx_queue *queue,
> + struct rx_queue_attribute *attribute, char *buf)
> +{
> + unsigned long flowid;
> + struct rps_map *map;
> + u16 cpu;
> +
> + strict_strtoul(attribute->attr.name + strlen("rps_flow_"), 10, &flowid);
> + rcu_read_lock();
> + map = rcu_dereference(queue->rps_map);
> + if (map && flowid < map->len)
> + cpu = map->cpus[flowid];
> + else
> + cpu = 0;
> + rcu_read_unlock();
> + return sprintf(buf, "%hu\n", cpu);
> +}
> +
> +static ssize_t store_rps_flow(struct netdev_rx_queue *queue,
> + struct rx_queue_attribute *attribute,
> + const char *buf, size_t len)
> +{
> + unsigned long flowid, cpu;
> + struct rps_map *map;
> +
> + if (!capable(CAP_NET_ADMIN))
> + return -EPERM;
> +
> + if (strict_strtoul(buf, 0, &cpu))
> + return -EINVAL;
> + strict_strtoul(attribute->attr.name + strlen("rps_flow_"), 10, &flowid);
> +
> + mutex_lock(&rps_map_lock);
> + map = queue->rps_map;
> + if (map && flowid < map->len)
> + map->cpus[flowid] = cpu;
what can happen is cpu=65000, and NR_CPUS=32 ?
> + mutex_unlock(&rps_map_lock);
> +
> + return len;
> +}
> +
> +static struct rx_queue_attribute **rps_flow_attribute;
> +static int rps_flow_attribute_size;
> +
> +/* must be called with rps_map_lock locked */
> +static int update_rps_flow_files(struct kobject *kobj,
> + struct rps_map *old_map, struct rps_map *map)
> +{
> + int i;
> + int old_map_len = old_map ? old_map->len : 0;
> + int map_len = map ? map->len : 0;
> +
> + if (old_map_len >= map_len) {
> + for (i = map_len; i < old_map_len; i++)
> + sysfs_remove_file(kobj, &rps_flow_attribute[i]->attr);
Removing attributes for this rxqueue, while anothe might need them ?
> + return 0;
> + }
> +
> + if (map_len > rps_flow_attribute_size) {
> + struct rx_queue_attribute **attrs;
> + char name[sizeof("rps_flow_4294967295")];
> + char *pname;
> +
> + attrs = krealloc(rps_flow_attribute, map_len * sizeof(void *),
> + GFP_KERNEL);
> + if (attrs == NULL)
> + return -ENOMEM;
> + rps_flow_attribute = attrs;
> + for (i = rps_flow_attribute_size; i < map_len; i++) {
> + rps_flow_attribute[i] = kmalloc(sizeof(**attrs),
> + GFP_KERNEL);
> + if (rps_flow_attribute[i] == NULL)
> + break;
> + sprintf(name, "rps_flow_%d", i);
> + pname = kstrdup(name, GFP_KERNEL);
> + if (pname == NULL) {
> + kfree(rps_flow_attribute[i]);
> + break;
> + }
> + rps_flow_attribute[i]->attr.name = pname;
> + rps_flow_attribute[i]->attr.mode = S_IRUGO | S_IWUSR;
> + rps_flow_attribute[i]->show = show_rps_flow;
> + rps_flow_attribute[i]->store = store_rps_flow;
> + }
> + rps_flow_attribute_size = i;
> + if (i != map_len)
> + return -ENOMEM;
> + }
> +
> + for (i = old_map_len; i < map_len; i++) {
> + if (sysfs_create_file(kobj, &rps_flow_attribute[i]->attr)) {
> + while (--i >= old_map_len)
> + sysfs_remove_file(kobj,
> + &rps_flow_attribute[i]->attr);
No changes to rps_flow_atribute_size ?
> + return -ENOMEM;
> + }
> + }
> +
> + return 0;
> +}
> +
> static ssize_t show_rps_map(struct netdev_rx_queue *queue,
> struct rx_queue_attribute *attribute, char *buf)
> {
> @@ -555,7 +658,6 @@ ssize_t store_rps_map(struct netdev_rx_queue *queue,
> struct rps_map *old_map, *map;
> cpumask_var_t mask;
> int err, cpu, i;
> - static DEFINE_SPINLOCK(rps_map_lock);
>
> if (!capable(CAP_NET_ADMIN))
> return -EPERM;
> @@ -588,10 +690,15 @@ ssize_t store_rps_map(struct netdev_rx_queue *queue,
> map = NULL;
> }
>
> - spin_lock(&rps_map_lock);
> + mutex_lock(&rps_map_lock);
> old_map = queue->rps_map;
> - rcu_assign_pointer(queue->rps_map, map);
> - spin_unlock(&rps_map_lock);
> + err = update_rps_flow_files(&queue->kobj, old_map, map);
> + if (!err)
> + rcu_assign_pointer(queue->rps_map, map);
> + mutex_unlock(&rps_map_lock);
> +
> + if (err)
> + return err;
>
> if (old_map)
> call_rcu(&old_map->rcu, rps_map_release);
> @@ -603,8 +710,69 @@ ssize_t store_rps_map(struct netdev_rx_queue *queue,
> static struct rx_queue_attribute rps_cpus_attribute =
> __ATTR(rps_cpus, S_IRUGO | S_IWUSR, show_rps_map, store_rps_map);
>
> +static ssize_t show_rps_flows(struct netdev_rx_queue *queue,
> + struct rx_queue_attribute *attribute, char *buf)
> +{
> + struct rps_map *map;
> + unsigned int len;
> +
> + rcu_read_lock();
> + map = rcu_dereference(queue->rps_map);
> + len = map ? map->len : 0;
> + rcu_read_unlock();
> + return sprintf(buf, "%u\n", len);
> +}
> +
> +static ssize_t store_rps_flows(struct netdev_rx_queue *queue,
> + struct rx_queue_attribute *attribute,
> + const char *buf, size_t len)
> +{
> + struct rps_map *old_map, *map;
> + unsigned long flows;
> + int err;
> +
> + if (!capable(CAP_NET_ADMIN))
> + return -EPERM;
> +
> + if (strict_strtoul(buf, 0, &flows))
> + return -EINVAL;
Are you aware RPS_MAP_SIZE(0x80000000) can overflow ?
> + if (flows != 0) {
> + map = kzalloc(max_t(unsigned, RPS_MAP_SIZE(flows),
> + L1_CACHE_BYTES), GFP_KERNEL);
> + if (map == NULL)
> + return -ENOMEM;
> + map->len = flows;
> + } else {
> + map = NULL;
> + }
> +
> + mutex_lock(&rps_map_lock);
> + old_map = queue->rps_map;
> + err = update_rps_flow_files(&queue->kobj, old_map, map);
> + if (!err) {
> + if (old_map && map)
> + memcpy(map->cpus, old_map->cpus,
> + sizeof(map->cpus[0]) *
> + min_t(unsigned int, flows, old_map->len));
> + rcu_assign_pointer(queue->rps_map, map);
> + }
> + mutex_unlock(&rps_map_lock);
> +
> + if (err)
> + return err;
> +
> + if (old_map)
> + call_rcu(&old_map->rcu, rps_map_release);
> +
> + return len;
> +}
> +
> +static struct rx_queue_attribute rps_flows_attribute =
> + __ATTR(rps_flows, S_IRUGO | S_IWUSR, show_rps_flows, store_rps_flows);
> +
> static struct attribute *rx_queue_default_attrs[] = {
> &rps_cpus_attribute.attr,
> + &rps_flows_attribute.attr,
> NULL
> };
>
> --
^ permalink raw reply
* [PATCH net-next-2.6] net: uninline skb_bond_should_drop()
From: Eric Dumazet @ 2010-04-11 16:56 UTC (permalink / raw)
To: David Miller; +Cc: netdev
skb_bond_should_drop() is too big to be inlined.
This patch reduces kernel text size, and its compilation time as well
(shrinking include/linux/netdevice.h)
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
include/linux/netdevice.h | 48 ++---------------------------------
net/core/dev.c | 49 ++++++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+), 44 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d1a21b5..470f7c9 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2089,54 +2089,14 @@ static inline void netif_set_gso_max_size(struct net_device *dev,
dev->gso_max_size = size;
}
-static inline void skb_bond_set_mac_by_master(struct sk_buff *skb,
- struct net_device *master)
-{
- if (skb->pkt_type == PACKET_HOST) {
- u16 *dest = (u16 *) eth_hdr(skb)->h_dest;
-
- memcpy(dest, master->dev_addr, ETH_ALEN);
- }
-}
+extern int __skb_bond_should_drop(struct sk_buff *skb,
+ struct net_device *master);
-/* On bonding slaves other than the currently active slave, suppress
- * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
- * ARP on active-backup slaves with arp_validate enabled.
- */
static inline int skb_bond_should_drop(struct sk_buff *skb,
struct net_device *master)
{
- if (master) {
- struct net_device *dev = skb->dev;
-
- if (master->priv_flags & IFF_MASTER_ARPMON)
- dev->last_rx = jiffies;
-
- if ((master->priv_flags & IFF_MASTER_ALB) && master->br_port) {
- /* Do address unmangle. The local destination address
- * will be always the one master has. Provides the right
- * functionality in a bridge.
- */
- skb_bond_set_mac_by_master(skb, master);
- }
-
- if (dev->priv_flags & IFF_SLAVE_INACTIVE) {
- if ((dev->priv_flags & IFF_SLAVE_NEEDARP) &&
- skb->protocol == __cpu_to_be16(ETH_P_ARP))
- return 0;
-
- if (master->priv_flags & IFF_MASTER_ALB) {
- if (skb->pkt_type != PACKET_BROADCAST &&
- skb->pkt_type != PACKET_MULTICAST)
- return 0;
- }
- if (master->priv_flags & IFF_MASTER_8023AD &&
- skb->protocol == __cpu_to_be16(ETH_P_SLOW))
- return 0;
-
- return 1;
- }
- }
+ if (master)
+ return __skb_bond_should_drop(skb, master);
return 0;
}
diff --git a/net/core/dev.c b/net/core/dev.c
index b98ddc6..c5ca39d 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2645,6 +2645,55 @@ void netif_nit_deliver(struct sk_buff *skb)
rcu_read_unlock();
}
+static inline void skb_bond_set_mac_by_master(struct sk_buff *skb,
+ struct net_device *master)
+{
+ if (skb->pkt_type == PACKET_HOST) {
+ u16 *dest = (u16 *) eth_hdr(skb)->h_dest;
+
+ memcpy(dest, master->dev_addr, ETH_ALEN);
+ }
+}
+
+/* On bonding slaves other than the currently active slave, suppress
+ * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
+ * ARP on active-backup slaves with arp_validate enabled.
+ */
+int __skb_bond_should_drop(struct sk_buff *skb, struct net_device *master)
+{
+ struct net_device *dev = skb->dev;
+
+ if (master->priv_flags & IFF_MASTER_ARPMON)
+ dev->last_rx = jiffies;
+
+ if ((master->priv_flags & IFF_MASTER_ALB) && master->br_port) {
+ /* Do address unmangle. The local destination address
+ * will be always the one master has. Provides the right
+ * functionality in a bridge.
+ */
+ skb_bond_set_mac_by_master(skb, master);
+ }
+
+ if (dev->priv_flags & IFF_SLAVE_INACTIVE) {
+ if ((dev->priv_flags & IFF_SLAVE_NEEDARP) &&
+ skb->protocol == __cpu_to_be16(ETH_P_ARP))
+ return 0;
+
+ if (master->priv_flags & IFF_MASTER_ALB) {
+ if (skb->pkt_type != PACKET_BROADCAST &&
+ skb->pkt_type != PACKET_MULTICAST)
+ return 0;
+ }
+ if (master->priv_flags & IFF_MASTER_8023AD &&
+ skb->protocol == __cpu_to_be16(ETH_P_SLOW))
+ return 0;
+
+ return 1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(__skb_bond_should_drop);
+
static int __netif_receive_skb(struct sk_buff *skb)
{
struct packet_type *ptype, *pt_prev;
^ permalink raw reply related
* [PATCH] netstat 1.42 patch adding ROSE support
From: Bernard Pidoux @ 2010-04-11 17:22 UTC (permalink / raw)
To: dc6iq, net-tools, Linux Netdev List, philb
[-- Attachment #1: Type: text/plain, Size: 2054 bytes --]
Hi,
In netstat README file one can read :
"route/netstat -r do not yet support different address families
cleanly. IPX/DDP/AX25 people, please feel free to add the code."
This is why I am sending this patch against netstat v 1.42 included
in net-tools 1.60-23.
The patch adds AMPR ROSE address family support as may be seen here :
[root@f6bvp-11 net-tools-1.60-23]# netstat -V
net-tools 1.60
netstat 1.42 (2001-04-15)
Fred Baumgarten, Alan Cox, Bernd Eckenfels, Phil Blundell, Tuan Hoang and others
+NEW_ADDRT +RTF_IRTT +RTF_REJECT -FW_MASQUERADE -I18N
AF: (inet) +UNIX +INET -INET6 -IPX +AX25 +NETROM -X25 -ATALK -ECONET +ROSE
HW: +ETHER -ARC -SLIP -PPP -TUNNEL -TR +AX25 +NETROM -X25 -FR +ROSE -ASH -SIT -FDDI -HIPPI -HDLC/LAPB
[root@f6bvp-11 net-tools-1.60-23]# netstat -h
usage: netstat [-veenNcCF] [<Af>] -r netstat {-V|--version|-h|--help}
------
------
<Socket>={-t|--tcp} {-u|--udp} {-w|--raw} {-x|--unix} --ax25 --ipx --netrom --rose
<AF>=Use '-A <af>' or '--<af>'; default: inet
List of possible address families (which support routing):
inet (DARPA Internet) ax25 (AMPR AX.25) netrom (AMPR NET/ROM)
rose (AMPR ROSE)
[root@f6bvp-11 net-tools-1.60-23]# netstat --rose
Active ROSE sockets
dest_addr dest_call src_addr src_call dev lci neigh state
2080175520 WP-0 2080175502 WP-0 rose0 32 16 ESTABLISHED
* * 2080175502 FE6BVP-1 rose0 0 0 LISTENING
2080175520 F6BVP-1 2080175502 F6BVP-12 rose0 0 0 LISTENING
2080175502 FPAD-0 2080175502 WP-0 rose0 32 1 ESTABLISHED
2080428501 F4BWT-10 2080175502 F6BVP-0 rose0 0 0 LISTENING
* * 2080175502 ROUTE-0 rose0 0 0 LISTENING
* * 2080175502 F6BVP-15 rose0 0 0 LISTENING
* * 2080175502 WP-0 rose0 0 0 LISTENING
2080175502 WP-0 2080175502 FPAD-0 rose0 1 1 ESTABLISHED
* * 2080175502 ??????-? rose0 0 0 LISTENING
Bernard Pidoux
[-- Attachment #2: net-tools-1.60-23.netstat.rose.patch --]
[-- Type: text/plain, Size: 11913 bytes --]
diff -ruN net-tools-1.60-23/config.in net-tools-1.60-23/config.in
--- net-tools-1.60-23/config.in 2000-05-21 16:32:12.000000000 +0200
+++ net-tools-1.60-23/config.in 2009-11-21 17:19:02.937147071 +0100
@@ -54,7 +54,7 @@
bool 'Appletalk DDP protocol family' HAVE_AFATALK y
bool 'AX25 (packet radio) protocol family' HAVE_AFAX25 y
bool 'NET/ROM (packet radio) protocol family' HAVE_AFNETROM y
-bool 'Rose (packet radio) protocol family' HAVE_AFROSE n
+bool 'Rose (packet radio) protocol family' HAVE_AFROSE y
bool 'X.25 (CCITT) protocol family' HAVE_AFX25 y
bool 'Econet protocol family' HAVE_AFECONET n
bool 'DECnet protocol family' HAVE_AFDECnet n
@@ -71,7 +71,7 @@
bool 'STRIP (Metricom radio) support' HAVE_HWSTRIP y
bool 'Token ring (generic) support' HAVE_HWTR y
bool 'AX25 (packet radio) support' HAVE_HWAX25 y
-bool 'Rose (packet radio) support' HAVE_HWROSE n
+bool 'Rose (packet radio) support' HAVE_HWROSE y
bool 'NET/ROM (packet radio) support' HAVE_HWNETROM y
bool 'X.25 (generic) support' HAVE_HWX25 y
bool 'DLCI/FRAD (frame relay) support' HAVE_HWFR y
diff -ruN net-tools-1.60-23/lib/af.c net-tools-1.60-23/lib/af.c
--- net-tools-1.60-23/lib/af.c 2000-05-20 20:27:23.000000000 +0200
+++ net-tools-1.60-23/lib/af.c 2009-11-21 17:19:02.937147071 +0100
@@ -32,6 +32,7 @@
int flag_ax25;
int flag_ddp;
int flag_netrom;
+int flag_rose;
int flag_inet;
int flag_inet6;
int flag_econet;
@@ -64,6 +65,9 @@
"netrom", "netrom", &flag_netrom
},
{
+ "rose", "rose", &flag_rose
+ },
+ {
"inet", "inet", &flag_inet
},
{
@@ -100,6 +104,7 @@
extern struct aftype inet6_aftype;
extern struct aftype ax25_aftype;
extern struct aftype netrom_aftype;
+extern struct aftype rose_aftype;
extern struct aftype ipx_aftype;
extern struct aftype ddp_aftype;
extern struct aftype ec_aftype;
diff -ruN net-tools-1.60-23/lib/getroute.c net-tools-1.60-23/lib/getroute.c
--- net-tools-1.60-23/lib/getroute.c 2000-05-20 20:27:23.000000000 +0200
+++ net-tools-1.60-23/lib/getroute.c 2009-11-21 17:19:02.937147071 +0100
@@ -44,6 +44,7 @@
extern struct aftype inet6_aftype;
extern struct aftype ax25_aftype;
extern struct aftype netrom_aftype;
+extern struct aftype rose_aftype;
extern struct aftype ipx_aftype;
extern struct aftype ddp_aftype;
extern struct aftype x25_aftype;
@@ -59,6 +60,9 @@
#if HAVE_AFNETROM
netrom_aftype.rprint = NETROM_rprint;
#endif
+#if HAVE_AFROSE
+ rose_aftype.rprint = ROSE_rprint;
+#endif
#if HAVE_AFAX25
ax25_aftype.rprint = AX25_rprint;
#endif
diff -ruN net-tools-1.60-23/lib/net-support.h net-tools-1.60-23/lib/net-support.h
--- net-tools-1.60-23/lib/net-support.h 2000-10-28 12:59:42.000000000 +0200
+++ net-tools-1.60-23/lib/net-support.h 2009-11-21 17:19:02.937147071 +0100
@@ -109,6 +109,7 @@
extern int DDP_rprint(int options);
extern int IPX_rprint(int options);
extern int NETROM_rprint(int options);
+extern int ROSE_rprint(int options);
extern int AX25_rprint(int options);
extern int X25_rprint(int options);
@@ -117,6 +118,7 @@
extern int DDP_rinput(int action, int flags, char **argv);
extern int IPX_rinput(int action, int flags, char **argv);
extern int NETROM_rinput(int action, int flags, char **argv);
+extern int ROSE_rinput(int action, int flags, char **argv);
extern int AX25_rinput(int action, int flags, char **argv);
extern int X25_rinput(int action, int flags, char **argv);
@@ -130,6 +132,7 @@
extern int flag_ax25;
extern int flag_ddp;
extern int flag_netrom;
+extern int flag_rose;
extern int flag_x25;
extern int flag_inet;
extern int flag_inet6;
@@ -143,6 +146,7 @@
{"ipx", 0, 0, 1}, \
{"appletalk", 0, 0, 1}, \
{"netrom", 0, 0, 1}, \
+ {"rose", 0, 0, 1}, \
{"inet", 0, 0, 1}, \
{"inet6", 0, 0, 1}, \
{"ddp", 0, 0, 1}, \
diff -ruN net-tools-1.60-23/lib/pathnames.h net-tools-1.60-23/lib/pathnames.h
--- net-tools-1.60-23/lib/pathnames.h 2000-05-20 20:27:26.000000000 +0200
+++ net-tools-1.60-23/lib/pathnames.h 2009-11-21 17:19:02.937147071 +0100
@@ -41,6 +41,9 @@
#define _PATH_PROCNET_DEV "/proc/net/dev"
#define _PATH_PROCNET_RARP "/proc/net/rarp"
#define _PATH_ETHERS "/etc/ethers"
+#define _PATH_PROCNET_ROSE "/proc/net/rose"
+#define _PATH_PROCNET_ROSE_NEIGH "/proc/net/rose_neigh"
+#define _PATH_PROCNET_ROSE_NODES "/proc/net/rose_nodes"
#define _PATH_PROCNET_ROSE_ROUTE "/proc/net/rose_routes"
#define _PATH_PROCNET_X25 "/proc/net/x25"
#define _PATH_PROCNET_X25_ROUTE "/proc/net/x25_routes"
diff -ruN net-tools-1.60-23/lib/rose_gr.c net-tools-1.60-23/lib/rose_gr.c
--- net-tools-1.60-23/lib/rose_gr.c 1999-01-09 16:55:24.000000000 +0100
+++ net-tools-1.60-23/lib/rose_gr.c 2009-11-21 17:19:02.937147071 +0100
@@ -11,6 +11,9 @@
* Copyright 1999 Bernd Eckenfels, Germany
* base on Code from Jonathan Naylor <jsn@Cs.Nott.AC.UK>
*
+ * Largely rewritten by Bernard Pidoux f6bvp@amsat.org
+ * November 2009.
+ *
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software
@@ -41,27 +44,48 @@
int ROSE_rprint(int options)
{
- FILE *f = NULL;
- char buffer[256];
- int use;
+ FILE *f1 = NULL;
+ FILE *f2 = NULL;
+ char buffer1[256], buffer2[256];
+ int i, neigh, use;
- f=fopen(_PATH_PROCNET_ROSE_ROUTE, "r");
- if (f == NULL) {
- perror(_PATH_PROCNET_ROSE_ROUTE);
+ f2=fopen(_PATH_PROCNET_ROSE_NEIGH, "r");
+ f1=fopen(_PATH_PROCNET_ROSE_NODES, "r");
+ if (f1 == NULL) {
+ perror(_PATH_PROCNET_ROSE_NODES);
printf(_("ROSE not configured in this system.\n")); /* xxx */
return 1;
}
printf(_("Kernel ROSE routing table\n"));
- printf(_("Destination Iface Use\n"));
- fgets(buffer, 256, f);
- while (fgets(buffer, 256, f)) {
- buffer[9] = 0;
- buffer[14] = 0;
- use = atoi(buffer + 15);
- printf("%-9s %-5s %5d\n",
- buffer, buffer + 10, use);
+ printf(_("Destination neigh1 callsign device neigh2 callsign device neigh3 callsign device\n"));
+ fgets(buffer1, 256, f1);
+ while (fgets(buffer1, 256, f1)) {
+ buffer1[10] = 0; /* address */
+ buffer1[15] = 0; /* mask */
+ buffer1[17] = 0; /* use */
+ buffer1[23] = 0; /* neigh 1 */
+ buffer1[29] = 0; /* neigh 2 */
+ buffer1[35] = 0; /* neigh 3 */
+/* mask = atoi(buffer1 + 11); */
+ use = atoi(buffer1 + 16);
+ neigh = atoi(buffer1 + 18);
+ printf("%-10s ", buffer1);
+ for (i=0; i < use; i++) {
+ neigh = atoi(buffer1 + 6*(i+3));
+ printf("%05d ", neigh);
+ rewind(f2);
+ fgets(buffer2, 256, f2);
+ while (fgets(buffer2, 256, f2)) {
+ buffer2[15] = 0;
+ buffer2[21] = 0;
+ if (atoi(buffer2) == neigh)
+ printf("%-10s %-4s", buffer2 + 6, buffer2 + 16);
+ }
+ }
+ printf("\n");
}
- fclose(f);
+ fclose(f1);
+ fclose(f2);
return 0;
}
diff -ruN net-tools-1.60-23/netstat.c net-tools-1.60-23/netstat.c
--- net-tools-1.60-23/netstat.c 2001-04-15 16:41:17.000000000 +0200
+++ net-tools-1.60-23/netstat.c 2009-11-21 17:19:02.937147071 +0100
@@ -58,6 +58,7 @@
*
*990420 {1.38} Tuan Hoang removed a useless assignment from igmp_do_one()
*20010404 {1.39} Arnaldo Carvalho de Melo - use setlocale
+ *20091121 Bernard Pidoux completed ampr ROSE support
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
@@ -488,6 +489,49 @@
}
#endif
+#if HAVE_AFROSE
+static const char *rose_state[] =
+{
+ N_("LISTENING"),
+ N_("CONN SENT"),
+ N_("DISC SENT"),
+ N_("ESTABLISHED")
+};
+
+static int rose_info(void)
+{
+ FILE *f;
+ char buffer[256], dev[6];
+ int ret, st, lci, neigh;
+ char src_addr[10], src_call[9], dest_addr[10], dest_call[9];
+
+ f = fopen(_PATH_PROCNET_ROSE, "r");
+ if (f == NULL) {
+ if (errno != ENOENT) {
+ perror(_PATH_PROCNET_ROSE);
+ return (-1);
+ }
+ if (flag_arg || flag_ver)
+ ESYSNOT("netstat", "AF ROSE");
+ if (flag_arg)
+ return (1);
+ else
+ return (0);
+ }
+ printf(_("Active ROSE sockets\n"));
+ printf(_("dest_addr dest_call src_addr src_call dev lci neigh state\n"));
+ fgets(buffer, 256, f);
+
+ while (fgets(buffer, 256, f)) {
+ ret = sscanf(buffer, "%s %s %s %s %s %d %d %d", dest_addr, dest_call, src_addr, src_call, dev, &lci, &neigh, &st);
+ printf("%-10s %-9s %-10s %-9s %-5s %3d %5d %s\n", dest_addr, dest_call, src_addr, src_call, dev, lci, neigh, _(rose_state[st]));
+
+ }
+ fclose(f);
+ return 0;
+}
+#endif
+
/* These enums are used by IPX too. :-( */
enum {
TCP_ESTABLISHED = 1,
@@ -1502,7 +1546,7 @@
fprintf(stderr, _(" -F, --fib display Forwarding Information Base (default)\n"));
fprintf(stderr, _(" -C, --cache display routing cache instead of FIB\n\n"));
- fprintf(stderr, _(" <Socket>={-t|--tcp} {-u|--udp} {-w|--raw} {-x|--unix} --ax25 --ipx --netrom\n"));
+ fprintf(stderr, _(" <Socket>={-t|--tcp} {-u|--udp} {-w|--raw} {-x|--unix} --ax25 --ipx --netrom --rose\n"));
fprintf(stderr, _(" <AF>=Use '-A <af>' or '--<af>'; default: %s\n"), DFLT_AF);
fprintf(stderr, _(" List of possible address families (which support routing):\n"));
print_aflist(1); /* 1 = routeable */
@@ -1665,7 +1709,7 @@
flag_inet = flag_inet6 = 1;
flag_arg = flag_tcp + flag_udp + flag_raw + flag_unx + flag_ipx
- + flag_ax25 + flag_netrom + flag_igmp + flag_x25;
+ + flag_ax25 + flag_netrom + flag_rose + flag_igmp + flag_x25;
if (flag_mas) {
#if HAVE_FW_MASQUERADE && HAVE_AFINET
@@ -1845,6 +1889,18 @@
}
#endif
}
+ if (!flag_arg || flag_rose) {
+#if HAVE_AFROSE
+ i = rose_info();
+ if (i)
+ return (i);
+#else
+ if (flag_arg) {
+ i = 1;
+ ENOSUPP("netstat", "AF ROSE");
+ }
+#endif
+ }
if (!flag_cnt || i)
break;
sleep(1);
@@ -1852,3 +1908,4 @@
}
return (i);
}
+
diff -ruN net-tools-1.60-23/po/fr.po net-tools-1.60-23/po/fr.po
--- net-tools-1.60-23/po/fr.po 2000-02-20 22:47:00.000000000 +0100
+++ net-tools-1.60-23/po/fr.po 2009-11-21 17:19:02.937147071 +0100
@@ -797,7 +797,7 @@
#: ../netstat.c:394 ../netstat.c:1089 ../netstat.c:1166
msgid "LISTENING"
-msgstr "LISTENING"
+msgstr "ECOUTE"
#: ../netstat.c:395
msgid "CONN SENT"
@@ -809,11 +809,19 @@
#: ../netstat.c:397 ../netstat.c:464 ../netstat.c:809 ../netstat.c:1169
msgid "ESTABLISHED"
-msgstr "ESTABLISHED"
+msgstr "ETABLIE"
-#: ../netstat.c:419
+#: ../netstat.c:467
msgid "Active NET/ROM sockets\n"
-msgstr "sockets NET/ROM actives\n"
+msgstr "Prises (sockets) NET/ROM actives\n"
+
+#: ../netstat.c:521
+msgid "Active ROSE sockets\n"
+msgstr "Prises (sockets) ROSE actives\n"
+
+#: ../netstat.c:522
+msgid "dest_addr dest_call src_addr src_call dev lci neigh state\n"
+msgstr "Destinat call_dest Source call_src Periph lci Voisin Etat \n"
#: ../netstat.c:420
msgid ""
@@ -826,7 +834,7 @@
#: ../netstat.c:430 ../netstat.c:1208
#, c-format
msgid "Problem reading data from %s\n"
-msgstr ""
+msgstr "Ne peut lire les données de %s\n"
#: ../netstat.c:465
msgid "SYN_SENT"
@@ -1008,7 +1016,7 @@
#: ../netstat.c:1184
msgid "Active AX.25 sockets\n"
-msgstr "Sockets AX.25 actives\n"
+msgstr "Prises (sockets) AX.25 actives\n"
#: ../netstat.c:1185
msgid "Dest Source Device State Vr/Vs Send-Q Recv-Q\n"
^ permalink raw reply
* [RFC PATCH 2/9] net: fib_rules: set family in fib_rule_hdr centrally
From: kaber @ 2010-04-11 17:37 UTC (permalink / raw)
To: netdev
In-Reply-To: <1271007435-20035-1-git-send-email-kaber@trash.net>
From: Patrick McHardy <kaber@trash.net>
All fib_rules implementations need to set the family in their ->fill()
functions. Since the value is available to the generic fib_nl_fill_rule()
function, set it there.
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
net/core/fib_rules.c | 1 +
net/decnet/dn_rules.c | 1 -
net/ipv4/fib_rules.c | 1 -
net/ipv6/fib6_rules.c | 1 -
4 files changed, 1 insertions(+), 3 deletions(-)
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index ca8215a..9ac60ec 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -534,6 +534,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
return -EMSGSIZE;
frh = nlmsg_data(nlh);
+ frh->family = ops->family;
frh->table = rule->table;
NLA_PUT_U32(skb, FRA_TABLE, rule->table);
frh->res1 = 0;
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 2d14093..1c8cc6d 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -196,7 +196,6 @@ static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
{
struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
- frh->family = AF_DECnet;
frh->dst_len = r->dst_len;
frh->src_len = r->src_len;
frh->tos = 0;
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 73b6784..a18355e 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -213,7 +213,6 @@ static int fib4_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
{
struct fib4_rule *rule4 = (struct fib4_rule *) rule;
- frh->family = AF_INET;
frh->dst_len = rule4->dst_len;
frh->src_len = rule4->src_len;
frh->tos = rule4->tos;
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 5e463c4..92b2b7f 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -208,7 +208,6 @@ static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
{
struct fib6_rule *rule6 = (struct fib6_rule *) rule;
- frh->family = AF_INET6;
frh->dst_len = rule6->dst.plen;
frh->src_len = rule6->src.plen;
frh->tos = rule6->tclass;
--
1.7.0.4
^ permalink raw reply related
* [RFC PATCH 1/9] net: fib_rules: consolidate IPv4 and DECnet ->default_pref() functions.
From: kaber @ 2010-04-11 17:37 UTC (permalink / raw)
To: netdev
In-Reply-To: <1271007435-20035-1-git-send-email-kaber@trash.net>
From: Patrick McHardy <kaber@trash.net>
Both functions are equivalent, consolidate them since a following patch
needs a third implementation for multicast routing.
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
include/net/fib_rules.h | 1 +
net/core/fib_rules.c | 18 ++++++++++++++++++
net/decnet/dn_rules.c | 19 +------------------
net/ipv4/fib_rules.c | 19 +------------------
4 files changed, 21 insertions(+), 36 deletions(-)
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index c07ac96..665b9fe 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -113,4 +113,5 @@ extern int fib_rules_lookup(struct fib_rules_ops *,
extern int fib_default_rule_add(struct fib_rules_ops *,
u32 pref, u32 table,
u32 flags);
+extern u32 fib_default_rule_pref(struct fib_rules_ops *ops);
#endif
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 2ff3489..ca8215a 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -38,6 +38,24 @@ int fib_default_rule_add(struct fib_rules_ops *ops,
}
EXPORT_SYMBOL(fib_default_rule_add);
+u32 fib_default_rule_pref(struct fib_rules_ops *ops)
+{
+ struct list_head *pos;
+ struct fib_rule *rule;
+
+ if (!list_empty(&ops->rules_list)) {
+ pos = ops->rules_list.next;
+ if (pos->next != &ops->rules_list) {
+ rule = list_entry(pos->next, struct fib_rule, list);
+ if (rule->pref)
+ return rule->pref - 1;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(fib_default_rule_pref);
+
static void notify_rule_change(int event, struct fib_rule *rule,
struct fib_rules_ops *ops, struct nlmsghdr *nlh,
u32 pid);
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 7466c54..2d14093 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -212,23 +212,6 @@ nla_put_failure:
return -ENOBUFS;
}
-static u32 dn_fib_rule_default_pref(struct fib_rules_ops *ops)
-{
- struct list_head *pos;
- struct fib_rule *rule;
-
- if (!list_empty(&dn_fib_rules_ops->rules_list)) {
- pos = dn_fib_rules_ops->rules_list.next;
- if (pos->next != &dn_fib_rules_ops->rules_list) {
- rule = list_entry(pos->next, struct fib_rule, list);
- if (rule->pref)
- return rule->pref - 1;
- }
- }
-
- return 0;
-}
-
static void dn_fib_rule_flush_cache(struct fib_rules_ops *ops)
{
dn_rt_cache_flush(-1);
@@ -243,7 +226,7 @@ static struct fib_rules_ops dn_fib_rules_ops_template = {
.configure = dn_fib_rule_configure,
.compare = dn_fib_rule_compare,
.fill = dn_fib_rule_fill,
- .default_pref = dn_fib_rule_default_pref,
+ .default_pref = fib_default_rule_pref,
.flush_cache = dn_fib_rule_flush_cache,
.nlgroup = RTNLGRP_DECnet_RULE,
.policy = dn_fib_rule_policy,
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index ca2d07b..73b6784 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -234,23 +234,6 @@ nla_put_failure:
return -ENOBUFS;
}
-static u32 fib4_rule_default_pref(struct fib_rules_ops *ops)
-{
- struct list_head *pos;
- struct fib_rule *rule;
-
- if (!list_empty(&ops->rules_list)) {
- pos = ops->rules_list.next;
- if (pos->next != &ops->rules_list) {
- rule = list_entry(pos->next, struct fib_rule, list);
- if (rule->pref)
- return rule->pref - 1;
- }
- }
-
- return 0;
-}
-
static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule)
{
return nla_total_size(4) /* dst */
@@ -272,7 +255,7 @@ static struct fib_rules_ops fib4_rules_ops_template = {
.configure = fib4_rule_configure,
.compare = fib4_rule_compare,
.fill = fib4_rule_fill,
- .default_pref = fib4_rule_default_pref,
+ .default_pref = fib_default_rule_pref,
.nlmsg_payload = fib4_rule_nlmsg_payload,
.flush_cache = fib4_rule_flush_cache,
.nlgroup = RTNLGRP_IPV4_RULE,
--
1.7.0.4
^ permalink raw reply related
* [RFC PATCH 0/9] net: support multiple independant multicast routing instances
From: kaber @ 2010-04-11 17:37 UTC (permalink / raw)
To: netdev
The following patches add support for multiple independant multicast
routing instances. This can be useful to seperate traffic when building
a multicast router that is serving multiple independant networks. Patch
09 contains a more detailed description of this feature in the changelog.
The patchset consists of the following parts:
- Patch 01 and 02 consolidate a small amount of code in the different
fib_rules users.
- Patch 03 decouples fib_rules family values from real address families
to allow using them in code that is not a seperate address family without
increasing AF_MAX/NPROTO.
- Patch 04 moves the raw_sock/raw_sk() definitions from icmp.h to raw.h
since they will also be used by ipmr in a following patch.
- Patch 05-08 contain some preparatory work and cleanup for supporting
multiple multicast routing instances.
- Patch 09 contains the actual changes to support multiple multicast
routing instances.
These patches have been tested using pimd by myself and using xorp by
Ben Greear.
Comments welcome.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox