* [RFC 3/3] TCP: htcp - use measured rtt
From: Stephen Hemminger @ 2007-07-19 7:41 UTC (permalink / raw)
To: David S. Miller; +Cc: Sangtae Ha, Luca De Cicco, Gavin McCullagh, netdev
In-Reply-To: <20070719074129.670215301@linux-foundation.org>
[-- Attachment #1: htcp-fix.patch --]
[-- Type: text/plain, Size: 1447 bytes --]
Change HTCP to use measured RTT rather than smooth RTT.
Srtt is computed using the TCP receive timestamp
options, so it is vulnerable to hostile receivers. To avoid any problems
this might cause use the measured RTT instead.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/net/ipv4/tcp_htcp.c 2007-07-19 08:26:40.000000000 +0100
+++ b/net/ipv4/tcp_htcp.c 2007-07-19 08:28:07.000000000 +0100
@@ -76,12 +76,11 @@ static u32 htcp_cwnd_undo(struct sock *s
return max(tp->snd_cwnd, (tp->snd_ssthresh << 7) / ca->beta);
}
-static inline void measure_rtt(struct sock *sk)
+static inline void measure_rtt(struct sock *sk, u32 srtt)
{
const struct inet_connection_sock *icsk = inet_csk(sk);
const struct tcp_sock *tp = tcp_sk(sk);
struct htcp *ca = inet_csk_ca(sk);
- u32 srtt = tp->srtt >> 3;
/* keep track of minimum RTT seen so far, minRTT is zero at first */
if (ca->minRTT > srtt || !ca->minRTT)
@@ -108,6 +107,9 @@ static void measure_achieved_throughput(
if (icsk->icsk_ca_state == TCP_CA_Open)
ca->pkts_acked = pkts_acked;
+ if (rtt > 0)
+ measure_rtt(sk, usecs_to_jiffies(rtt));
+
if (!use_bandwidth_switch)
return;
@@ -237,8 +239,6 @@ static void htcp_cong_avoid(struct sock
if (tp->snd_cwnd <= tp->snd_ssthresh)
tcp_slow_start(tp);
else {
- measure_rtt(sk);
-
/* In dangerous area, increase slowly.
* In theory this is tp->snd_cwnd += alpha / tp->snd_cwnd
*/
--
^ permalink raw reply
* [RFC 2/3] TCP: cubic - eliminate use of receive time stamp
From: Stephen Hemminger @ 2007-07-19 7:41 UTC (permalink / raw)
To: David S. Miller; +Cc: Sangtae Ha, Luca De Cicco, Gavin McCullagh, netdev
In-Reply-To: <20070719074129.670215301@linux-foundation.org>
[-- Attachment #1: tcp-cubic-rtt.patch --]
[-- Type: text/plain, Size: 2515 bytes --]
Remove use of received timestamp option value from RTT calculation in Cubic.
A hostile receiver may be returning a larger timestamp option than the original
value. This would cause the sender to believe the malevolent receiver had
a larger RTT and because Cubic tries to provide some RTT friendliness, the
sender would then favor the liar.
Instead, use the jiffie resolutionRTT value already computed and
passed back after ack.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/net/ipv4/tcp_cubic.c 2007-07-19 08:21:42.000000000 +0100
+++ b/net/ipv4/tcp_cubic.c 2007-07-19 08:24:58.000000000 +0100
@@ -246,38 +246,12 @@ static inline void bictcp_update(struct
ca->cnt = 1;
}
-
-/* Keep track of minimum rtt */
-static inline void measure_delay(struct sock *sk)
-{
- const struct tcp_sock *tp = tcp_sk(sk);
- struct bictcp *ca = inet_csk_ca(sk);
- u32 delay;
-
- /* No time stamp */
- if (!(tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr) ||
- /* Discard delay samples right after fast recovery */
- (s32)(tcp_time_stamp - ca->epoch_start) < HZ)
- return;
-
- delay = (tcp_time_stamp - tp->rx_opt.rcv_tsecr)<<3;
- if (delay == 0)
- delay = 1;
-
- /* first time call or link delay decreases */
- if (ca->delay_min == 0 || ca->delay_min > delay)
- ca->delay_min = delay;
-}
-
static void bictcp_cong_avoid(struct sock *sk, u32 ack,
u32 seq_rtt, u32 in_flight, int data_acked)
{
struct tcp_sock *tp = tcp_sk(sk);
struct bictcp *ca = inet_csk_ca(sk);
- if (data_acked)
- measure_delay(sk);
-
if (!tcp_is_cwnd_limited(sk, in_flight))
return;
@@ -337,14 +311,30 @@ static void bictcp_state(struct sock *sk
static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)
{
const struct inet_connection_sock *icsk = inet_csk(sk);
+ struct bictcp *ca = inet_csk_ca(sk);
+ u32 delay;
if (cnt > 0 && icsk->icsk_ca_state == TCP_CA_Open) {
- struct bictcp *ca = inet_csk_ca(sk);
cnt -= ca->delayed_ack >> ACK_RATIO_SHIFT;
ca->delayed_ack += cnt;
}
-}
+ /* Some calls are for duplicates without timetamps */
+ if (rtt_us < 0)
+ return;
+
+ /* Discard delay samples right after fast recovery */
+ if ((s32)(tcp_time_stamp - ca->epoch_start) < HZ)
+ return;
+
+ delay = usecs_to_jiffies(rtt_us) << 3;
+ if (delay == 0)
+ delay = 1;
+
+ /* first time call or link delay decreases */
+ if (ca->delay_min == 0 || ca->delay_min > delay)
+ ca->delay_min = delay;
+}
static struct tcp_congestion_ops cubictcp = {
.init = bictcp_init,
--
^ permalink raw reply
* [RFC 1/3] TCP: congestion control API pass RTT in microseconds
From: Stephen Hemminger @ 2007-07-19 7:41 UTC (permalink / raw)
To: David S. Miller; +Cc: Sangtae Ha, Luca De Cicco, Gavin McCullagh, netdev
In-Reply-To: <20070719074129.670215301@linux-foundation.org>
[-- Attachment #1: tcp-cong-rtt.patch --]
[-- Type: text/plain, Size: 8392 bytes --]
This patch changes the API for the callback that is done after an ACK is
received. It solves a couple of issues:
* Some congestion controls want higher resolution value of RTT
(controlled by TCP_CONG_RTT_SAMPLE flag). These don't really want a ktime, but
all compute a RTT in microseconds.
* Other congestion control could use RTT at jiffies resolution.
To keep API consistent the units should be the same for both cases, just the
resolution should change.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
--- a/include/net/tcp.h 2007-07-19 08:12:13.000000000 +0100
+++ b/include/net/tcp.h 2007-07-19 08:12:23.000000000 +0100
@@ -661,7 +661,7 @@ struct tcp_congestion_ops {
/* new value of cwnd after loss (optional) */
u32 (*undo_cwnd)(struct sock *sk);
/* hook for packet ack accounting (optional) */
- void (*pkts_acked)(struct sock *sk, u32 num_acked, ktime_t last);
+ void (*pkts_acked)(struct sock *sk, u32 num_acked, s32 rtt_us);
/* get info for inet_diag (optional) */
void (*get_info)(struct sock *sk, u32 ext, struct sk_buff *skb);
--- a/net/ipv4/tcp_input.c 2007-07-19 08:12:13.000000000 +0100
+++ b/net/ipv4/tcp_input.c 2007-07-19 08:12:23.000000000 +0100
@@ -2490,12 +2490,23 @@ static int tcp_clean_rtx_queue(struct so
tcp_ack_update_rtt(sk, acked, seq_rtt);
tcp_ack_packets_out(sk);
- /* Is the ACK triggering packet unambiguous? */
- if (acked & FLAG_RETRANS_DATA_ACKED)
- last_ackt = net_invalid_timestamp();
+ if (ca_ops->pkts_acked) {
+ s32 rtt_us = -1;
- if (ca_ops->pkts_acked)
- ca_ops->pkts_acked(sk, pkts_acked, last_ackt);
+ /* Is the ACK triggering packet unambiguous? */
+ if (!(acked & FLAG_RETRANS_DATA_ACKED)) {
+ /* High resolution needed and available? */
+ if (ca_ops->flags & TCP_CONG_RTT_STAMP &&
+ !ktime_equal(last_ackt,
+ net_invalid_timestamp()))
+ rtt_us = ktime_us_delta(ktime_get_real(),
+ last_ackt);
+ else if (seq_rtt > 0)
+ rtt_us = jiffies_to_usecs(seq_rtt);
+ }
+
+ ca_ops->pkts_acked(sk, pkts_acked, rtt_us);
+ }
}
#if FASTRETRANS_DEBUG > 0
--- a/net/ipv4/tcp_bic.c 2007-07-17 10:01:51.000000000 +0100
+++ b/net/ipv4/tcp_bic.c 2007-07-19 08:16:35.000000000 +0100
@@ -206,7 +206,7 @@ static void bictcp_state(struct sock *sk
/* Track delayed acknowledgment ratio using sliding window
* ratio = (15*ratio + sample) / 16
*/
-static void bictcp_acked(struct sock *sk, u32 cnt, ktime_t last)
+static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt)
{
const struct inet_connection_sock *icsk = inet_csk(sk);
--- a/net/ipv4/tcp_cubic.c 2007-07-18 22:28:38.000000000 +0100
+++ b/net/ipv4/tcp_cubic.c 2007-07-19 08:21:42.000000000 +0100
@@ -334,7 +334,7 @@ static void bictcp_state(struct sock *sk
/* Track delayed acknowledgment ratio using sliding window
* ratio = (15*ratio + sample) / 16
*/
-static void bictcp_acked(struct sock *sk, u32 cnt, ktime_t last)
+static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us)
{
const struct inet_connection_sock *icsk = inet_csk(sk);
--- a/net/ipv4/tcp_htcp.c 2007-07-18 22:28:38.000000000 +0100
+++ b/net/ipv4/tcp_htcp.c 2007-07-19 08:18:38.000000000 +0100
@@ -98,7 +98,7 @@ static inline void measure_rtt(struct so
}
}
-static void measure_achieved_throughput(struct sock *sk, u32 pkts_acked, ktime_t last)
+static void measure_achieved_throughput(struct sock *sk, u32 pkts_acked, s32 rtt)
{
const struct inet_connection_sock *icsk = inet_csk(sk);
const struct tcp_sock *tp = tcp_sk(sk);
--- a/net/ipv4/tcp_illinois.c 2007-07-19 07:08:45.000000000 +0100
+++ b/net/ipv4/tcp_illinois.c 2007-07-19 08:16:13.000000000 +0100
@@ -83,18 +83,16 @@ static void tcp_illinois_init(struct soc
}
/* Measure RTT for each ack. */
-static void tcp_illinois_acked(struct sock *sk, u32 pkts_acked, ktime_t last)
+static void tcp_illinois_acked(struct sock *sk, u32 pkts_acked, s32 rtt)
{
struct illinois *ca = inet_csk_ca(sk);
- u32 rtt;
ca->acked = pkts_acked;
- if (ktime_equal(last, net_invalid_timestamp()))
+ /* dup ack, no rtt sample */
+ if (rtt < 0)
return;
- rtt = ktime_to_us(net_timedelta(last));
-
/* ignore bogus values, this prevents wraparound in alpha math */
if (rtt > RTT_MAX)
rtt = RTT_MAX;
--- a/net/ipv4/tcp_lp.c 2007-07-19 07:08:45.000000000 +0100
+++ b/net/ipv4/tcp_lp.c 2007-07-19 08:20:12.000000000 +0100
@@ -261,13 +261,13 @@ static void tcp_lp_rtt_sample(struct soc
* newReno in increase case.
* We work it out by following the idea from TCP-LP's paper directly
*/
-static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked, ktime_t last)
+static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked, s32 rtt_us)
{
struct tcp_sock *tp = tcp_sk(sk);
struct lp *lp = inet_csk_ca(sk);
- if (!ktime_equal(last, net_invalid_timestamp()))
- tcp_lp_rtt_sample(sk, ktime_to_us(net_timedelta(last)));
+ if (rtt_us > 0)
+ tcp_lp_rtt_sample(sk, rtt_us);
/* calc inference */
if (tcp_time_stamp > tp->rx_opt.rcv_tsecr)
--- a/net/ipv4/tcp_vegas.c 2007-07-19 07:08:45.000000000 +0100
+++ b/net/ipv4/tcp_vegas.c 2007-07-19 08:14:49.000000000 +0100
@@ -112,16 +112,16 @@ EXPORT_SYMBOL_GPL(tcp_vegas_init);
* o min-filter RTT samples from a much longer window (forever for now)
* to find the propagation delay (baseRTT)
*/
-void tcp_vegas_pkts_acked(struct sock *sk, u32 cnt, ktime_t last)
+void tcp_vegas_pkts_acked(struct sock *sk, u32 cnt, s32 rtt_us)
{
struct vegas *vegas = inet_csk_ca(sk);
u32 vrtt;
- if (ktime_equal(last, net_invalid_timestamp()))
+ if (rtt_us < 0)
return;
/* Never allow zero rtt or baseRTT */
- vrtt = ktime_to_us(net_timedelta(last)) + 1;
+ vrtt = rtt_us + 1;
/* Filter to find propagation delay: */
if (vrtt < vegas->baseRTT)
--- a/net/ipv4/tcp_vegas.h 2007-07-16 14:25:41.000000000 +0100
+++ b/net/ipv4/tcp_vegas.h 2007-07-19 08:22:33.000000000 +0100
@@ -17,7 +17,7 @@ struct vegas {
extern void tcp_vegas_init(struct sock *sk);
extern void tcp_vegas_state(struct sock *sk, u8 ca_state);
-extern void tcp_vegas_pkts_acked(struct sock *sk, u32 cnt, ktime_t last);
+extern void tcp_vegas_pkts_acked(struct sock *sk, u32 cnt, s32 rtt_us);
extern void tcp_vegas_cwnd_event(struct sock *sk, enum tcp_ca_event event);
extern void tcp_vegas_get_info(struct sock *sk, u32 ext, struct sk_buff *skb);
--- a/net/ipv4/tcp_veno.c 2007-07-19 07:08:45.000000000 +0100
+++ b/net/ipv4/tcp_veno.c 2007-07-19 08:19:37.000000000 +0100
@@ -69,16 +69,16 @@ static void tcp_veno_init(struct sock *s
}
/* Do rtt sampling needed for Veno. */
-static void tcp_veno_pkts_acked(struct sock *sk, u32 cnt, ktime_t last)
+static void tcp_veno_pkts_acked(struct sock *sk, u32 cnt, s32 rtt_us)
{
struct veno *veno = inet_csk_ca(sk);
u32 vrtt;
- if (ktime_equal(last, net_invalid_timestamp()))
+ if (rtt_us < 0)
return;
/* Never allow zero rtt or baseRTT */
- vrtt = ktime_to_us(net_timedelta(last)) + 1;
+ vrtt = rtt_us + 1;
/* Filter to find propagation delay: */
if (vrtt < veno->basertt)
--- a/net/ipv4/tcp_westwood.c 2007-07-18 22:28:38.000000000 +0100
+++ b/net/ipv4/tcp_westwood.c 2007-07-19 08:17:43.000000000 +0100
@@ -100,11 +100,12 @@ static void westwood_filter(struct westw
* Called after processing group of packets.
* but all westwood needs is the last sample of srtt.
*/
-static void tcp_westwood_pkts_acked(struct sock *sk, u32 cnt, ktime_t last)
+static void tcp_westwood_pkts_acked(struct sock *sk, u32 cnt, s32 rtt)
{
struct westwood *w = inet_csk_ca(sk);
- if (cnt > 0)
- w->rtt = tcp_sk(sk)->srtt >> 3;
+
+ if (rtt > 0)
+ w->rtt = usecs_to_jiffies(rtt);
}
/*
--- a/net/ipv4/tcp_yeah.c 2007-07-19 07:08:45.000000000 +0100
+++ b/net/ipv4/tcp_yeah.c 2007-07-19 08:23:08.000000000 +0100
@@ -58,7 +58,7 @@ static void tcp_yeah_init(struct sock *s
}
-static void tcp_yeah_pkts_acked(struct sock *sk, u32 pkts_acked, ktime_t last)
+static void tcp_yeah_pkts_acked(struct sock *sk, u32 pkts_acked, s32 rtt_us)
{
const struct inet_connection_sock *icsk = inet_csk(sk);
struct yeah *yeah = inet_csk_ca(sk);
@@ -66,7 +66,7 @@ static void tcp_yeah_pkts_acked(struct s
if (icsk->icsk_ca_state == TCP_CA_Open)
yeah->pkts_acked = pkts_acked;
- tcp_vegas_pkts_acked(sk, pkts_acked, last);
+ tcp_vegas_pkts_acked(sk, pkts_acked, rtt_us);
}
static void tcp_yeah_cong_avoid(struct sock *sk, u32 ack,
--
^ permalink raw reply
* kmap_atomic() oopses in current mainline
From: Andrew Morton @ 2007-07-19 8:33 UTC (permalink / raw)
To: netdev, linux-kernel-announce; +Cc: Dan Williams
I've had a handful of random mystery oopses associated with no particular
activity. A typical trace is at:
http://userweb.kernel.org/~akpm/dsc03659.jpg
the trace is messy and it doesn't seem to want to happen now I've turned on
frame pointers, but it looks networky to me.
So if anyone has made kmap_atomic() changes in networking recently, please
check your work. The machine does have highmem.
The crash appears to be happening here:
BUG_ON(!pte_none(*(kmap_pte-idx)));
which would indicate a wild value is being passing km kmap_atomic()'s
km_type arg.
I don't think the 2-year-old Vaio has offload engine support ;) Dan, this:
+ if (flags & ASYNC_TX_KMAP_DST)
+ dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
+ else
+ dest_buf = page_address(dest) + dest_offset;
+
+ if (flags & ASYNC_TX_KMAP_SRC)
+ src_buf = kmap_atomic(src, KM_USER0) + src_offset;
+ else
+ src_buf = page_address(src) + src_offset;
+
+ memcpy(dest_buf, src_buf, len);
+
+ if (flags & ASYNC_TX_KMAP_DST)
+ kunmap_atomic(dest_buf, KM_USER0);
+
+ if (flags & ASYNC_TX_KMAP_SRC)
+ kunmap_atomic(src_buf, KM_USER0);
+
is very wrong if both ASYNC_TX_KMAP_DST and ASYNC_TX_KMAP_SRC can ever be
set. We'll end up using the same kmap slot for both src add dest and we
get either corrupted data or a BUG.
^ permalink raw reply
* Re: Socket Buffers and Memory Managment
From: Stephen Hemminger @ 2007-07-19 8:10 UTC (permalink / raw)
To: vinay ravuri; +Cc: netdev
In-Reply-To: <261750.43078.qm@web82911.mail.mud.yahoo.com>
On Wed, 18 Jul 2007 23:51:03 -0700 (PDT)
vinay ravuri <vinaynyc@yahoo.com> wrote:
> How about the following approach:
>
> I allocate an skb of 0 bytes and replace data element
> of skb struct (i.e. skb.data = addr_given_by_hw) when
> the h/w interrupts me with a packet. I register for a
> destructor for this skb and when the kernel is ready
> to free the skb, I make sure that my free is invoked -
> Ofcourse this is assuming that their is a facility in
> linux socket buffers to be able to do destructors. Is
> this approach a viable, if so, are any gottcha's?
>
> -Vinay
You need to use frag list for that since upper layers expect to
be able to use that data area for normal use, ie bridging/routing, etc.
Also access to data area would be non-cached so you want to make
sure it is only accessed once.
But how will you handle a slow receiver where all the skb's end up
staying queued. Won't you exhaust your packet memory.
^ permalink raw reply
* Re: [PATCH] Merge GT/MV642xx Support into MV643xx Driver [1/8]
From: Christoph Hellwig @ 2007-07-19 8:38 UTC (permalink / raw)
To: Steven J. Hill; +Cc: netdev
In-Reply-To: <469EECFA.1010704@realitydiluted.com>
On Wed, Jul 18, 2007 at 11:47:54PM -0500, Steven J. Hill wrote:
> This first patch 642xx #defines to the 'include/linux/mv643xx.h' file.
I don't think register names should change based on ifefs. Please make
sure both variants can be supported at runtime. While mips might not
support different controllers in one binary powerpc certainly does.
^ permalink raw reply
* Re: [PATCH] Merge GT/MV642xx Support into MV643xx Driver [4/8]
From: Christoph Hellwig @ 2007-07-19 8:39 UTC (permalink / raw)
To: Steven J. Hill; +Cc: netdev
In-Reply-To: <469EEE4B.2090008@realitydiluted.com>
On Wed, Jul 18, 2007 at 11:53:31PM -0500, Steven J. Hill wrote:
> Add main 642xx support to 'drivers/net/mv643xx_eth.c' file.
This is a little too much ifdef mess. Please factor per-controller type
code into helper functions, and if they're too much have separate files
for either type.
^ permalink raw reply
* Re: [PATCH] Merge GT/MV642xx Support into MV643xx Driver [5/8]
From: Christoph Hellwig @ 2007-07-19 8:40 UTC (permalink / raw)
To: Steven J. Hill; +Cc: netdev
In-Reply-To: <469EEE95.8050500@realitydiluted.com>
On Wed, Jul 18, 2007 at 11:54:45PM -0500, Steven J. Hill wrote:
> Fix 'mv643xx_eth_tx_timeout_task' function prototype.
Patches 5-7 look like valid fixes independent of the merge. Please send
them out inlined in the mail and with proper subjects so they can be
merged independent of the GT/MV642xx support.
^ permalink raw reply
* Re: [PATCH] net/, drivers/net/ , missing EXPERIMENTAL in menus
From: Stefan Richter @ 2007-07-19 8:42 UTC (permalink / raw)
To: Robert P. J. Day
Cc: Adrian Bunk, Jeff Garzik, Randy Dunlap, Gabriel C,
Linux Kernel Mailing List, netdev
In-Reply-To: <Pine.LNX.4.64.0707190331330.11902@localhost.localdomain>
Robert P. J. Day wrote:
> On Thu, 19 Jul 2007, Adrian Bunk wrote:
>
> ...
>> I would consider it more ugly to special case this and that in the
>> kconfig code when plain dependencies already offer exactly the same
>> functionality...
>
> well, this is the *third* time i've proposed adding this kind of
> feature so, at this point, i've really given up caring about it. if
> someone wants to do this, have at it. i have better things to do than
> to keep suggesting it and getting nowhere with it.
For better or worse, it can often be observed that feature requests
don't set anything in motion until a first patch is sent. Even a patch
that is far from perfect can get things going really quickly. (If the
requested feature makes sense to other people.)
--
Stefan Richter
-=====-=-=== -=== =--==
http://arcgraph.de/sr/
^ permalink raw reply
* Re: [PATCH][RFC] network splice receive v3
From: Evgeniy Polyakov @ 2007-07-19 8:44 UTC (permalink / raw)
To: Jens Axboe; +Cc: netdev, linux-kernel, olaf.kirch
In-Reply-To: <20070713122058.GL5328@kernel.dk>
Hi.
On Fri, Jul 13, 2007 at 02:21:00PM +0200, Jens Axboe (jens.axboe@oracle.com) wrote:
> > It really looks like the last tree we tested, so if you think additional
> > one will not hurt, feel free to ping, so I will completely rebase
> > testing tree.
>
> It would be great if you could retest! There are some minor changes in
> there, and some extra testing definitely will not hurt.
I've just tested it with 2.6.22
(e1c1e98d2a3f57b22a0d4136c8160e54404aa437 commit) and did not found any
problems - after qute big files were transferred there is no observed
previously skb leak, no crashes (quite a few debug options are turned on
in config) and files are correct on both peers, so it works good.
> --
> Jens Axboe
--
Evgeniy Polyakov
^ permalink raw reply
* Re: [PATCH][RFC] network splice receive v3
From: YOSHIFUJI Hideaki / 吉藤英明 @ 2007-07-19 9:05 UTC (permalink / raw)
To: jens.axboe; +Cc: netdev, linux-kernel, olaf.kirch, johnpol, yoshfuji
In-Reply-To: <20070711091927.GQ4587@kernel.dk>
Hello.
In article <20070711091927.GQ4587@kernel.dk> (at Wed, 11 Jul 2007 11:19:27 +0200), Jens Axboe <jens.axboe@oracle.com> says:
> @@ -835,6 +835,7 @@ const struct proto_ops inet_stream_ops = {
> .recvmsg = sock_common_recvmsg,
> .mmap = sock_no_mmap,
> .sendpage = tcp_sendpage,
> + .splice_read = tcp_splice_read,
> #ifdef CONFIG_COMPAT
> .compat_setsockopt = compat_sock_common_setsockopt,
> .compat_getsockopt = compat_sock_common_getsockopt,
Please add similar bits in net/ipv6/af_inet6.c
unless there are any dependency on IPv4.
(And if there are, it is not good.)
--yoshfuji
^ permalink raw reply
* Re: [PATCH][RFC] network splice receive v3
From: Jens Axboe @ 2007-07-19 9:07 UTC (permalink / raw)
To: YOSHIFUJI Hideaki / ?$B5HF#1QL@; +Cc: netdev, linux-kernel, olaf.kirch, johnpol
In-Reply-To: <20070719.180518.79100322.yoshfuji@linux-ipv6.org>
On Thu, Jul 19 2007, YOSHIFUJI Hideaki / ?$B5HF#1QL@ wrote:
> Hello.
>
> In article <20070711091927.GQ4587@kernel.dk> (at Wed, 11 Jul 2007 11:19:27 +0200), Jens Axboe <jens.axboe@oracle.com> says:
>
> > @@ -835,6 +835,7 @@ const struct proto_ops inet_stream_ops = {
> > .recvmsg = sock_common_recvmsg,
> > .mmap = sock_no_mmap,
> > .sendpage = tcp_sendpage,
> > + .splice_read = tcp_splice_read,
> > #ifdef CONFIG_COMPAT
> > .compat_setsockopt = compat_sock_common_setsockopt,
> > .compat_getsockopt = compat_sock_common_getsockopt,
>
> Please add similar bits in net/ipv6/af_inet6.c
> unless there are any dependency on IPv4.
> (And if there are, it is not good.)
There are no specific ipv4 depedencies, it's just an oversight. So
thanks for the clue, I'll add it!
--
Jens Axboe
^ permalink raw reply
* Re: Socket Buffers and Memory Managment
From: Evgeniy Polyakov @ 2007-07-19 9:08 UTC (permalink / raw)
To: vinay ravuri; +Cc: Stephen Hemminger, netdev
In-Reply-To: <261750.43078.qm@web82911.mail.mud.yahoo.com>
Hi.
On Wed, Jul 18, 2007 at 11:51:03PM -0700, vinay ravuri (vinaynyc@yahoo.com) wrote:
> How about the following approach:
>
> I allocate an skb of 0 bytes and replace data element
> of skb struct (i.e. skb.data = addr_given_by_hw) when
> the h/w interrupts me with a packet. I register for a
> destructor for this skb and when the kernel is ready
> to free the skb, I make sure that my free is invoked -
> Ofcourse this is assuming that their is a facility in
> linux socket buffers to be able to do destructors. Is
> this approach a viable, if so, are any gottcha's?
It will not work, since kfree_skb() eventually tries to free skb->head
into kmem cache, so you will need to hack kfree_skb() not to try to
release that data at all. Likely the best zero-copy approach in your
case is to use frag_list, but be ready that your netwrok will regularily
stall - when hardware buffers are all in use and not yet freed, you will
not be able to send/receive new packets, although amount of memory will
allow that.
> -Vinay
--
Evgeniy Polyakov
^ permalink raw reply
* [PATCH 0/0] netxen: bug fixes for IMEZ adapters on pblades
From: dhananjay @ 2007-07-19 9:03 UTC (permalink / raw)
To: netdev; +Cc: rob
Couple of bug fixes for netxen IMEZ adapter on powerpc blades. The firmware
must be loaded during probe and free PCI resources during module unload.
Please apply against #upstream-fixes.
drivers/net/netxen/netxen_nic.h | 3 +-
drivers/net/netxen/netxen_nic_main.c | 48 +++++++++++++++---------------
2 files changed, 25 insertions(+), 26 deletions(-)
^ permalink raw reply
* [PATCH 0/1] netxen: bug fixes for IMEZ adapters on pblades
From: dhananjay @ 2007-07-19 9:11 UTC (permalink / raw)
To: netdev; +Cc: rob
Couple of bug fixes for netxen IMEZ adapter on powerpc blades. The firmware
must be loaded during probe and free PCI resources during module unload.
Please apply against #upstream-fixes.
drivers/net/netxen/netxen_nic.h | 3 +-
drivers/net/netxen/netxen_nic_main.c | 48 +++++++++++++++---------------
2 files changed, 25 insertions(+), 26 deletions(-)
^ permalink raw reply
* [PATCH 1/1] netxen: Load firmware during probe, dma watchdog fix.
From: dhananjay @ 2007-07-19 9:11 UTC (permalink / raw)
To: netdev; +Cc: rob, Milan Bag, Wen Xiong
In-Reply-To: <20070719091108.839200259@netxen.com>
[-- Attachment #1: dma.patch --]
[-- Type: text/plain, Size: 4184 bytes --]
The firmware should be loaded after resetting hardware during PCI probe,
besides module unload. This fixes issue with 2nd port of multiport adapter
on powerpc blades. This patch also fixes a bug that PCI resources are not
freed if dma watchdog shutdown failed. The dma watchdog poll messages
during module unload are also suppressed.
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: Milan Bag <mbag@netxen.com>
Signed-off-by: Wen Xiong <wenxiong@us.ibm.com>
Index: netdev-2.6/drivers/net/netxen/netxen_nic_main.c
===================================================================
--- netdev-2.6.orig/drivers/net/netxen/netxen_nic_main.c
+++ netdev-2.6/drivers/net/netxen/netxen_nic_main.c
@@ -46,7 +46,7 @@ MODULE_DESCRIPTION("NetXen Multi port (1
MODULE_LICENSE("GPL");
MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID);
-char netxen_nic_driver_name[] = "netxen-nic";
+char netxen_nic_driver_name[] = "netxen_nic";
static char netxen_nic_driver_string[] = "NetXen Network Driver version "
NETXEN_NIC_LINUX_VERSIONID;
@@ -643,6 +643,10 @@ netxen_nic_probe(struct pci_dev *pdev, c
NETXEN_CRB_NORMALIZE(adapter,
NETXEN_ROMUSB_GLB_PEGTUNE_DONE));
/* Handshake with the card before we register the devices. */
+ writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
+ netxen_pinit_from_rom(adapter, 0);
+ msleep(1);
+ netxen_load_firmware(adapter);
netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
}
@@ -785,19 +789,18 @@ static void __devexit netxen_nic_remove(
if (adapter->portnum == 0) {
if (init_firmware_done) {
- dma_watchdog_shutdown_request(adapter);
- msleep(100);
i = 100;
- while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) {
- printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n");
+ do {
+ if (dma_watchdog_shutdown_request(adapter) == 1)
+ break;
msleep(100);
- i--;
- }
-
- if (i == 0) {
- printk(KERN_ERR "dma_watchdog_shutdown_request failed\n");
- return;
- }
+ if (dma_watchdog_shutdown_poll_result(adapter) == 1)
+ break;
+ } while (--i);
+
+ if (i == 0)
+ printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n",
+ netdev->name);
/* clear the register for future unloads/loads */
writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_CAM_RAM(0x1fc)));
@@ -806,11 +809,9 @@ static void __devexit netxen_nic_remove(
/* leave the hw in the same state as reboot */
writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE));
- if (netxen_pinit_from_rom(adapter, 0))
- return;
+ netxen_pinit_from_rom(adapter, 0);
msleep(1);
- if (netxen_load_firmware(adapter))
- return;
+ netxen_load_firmware(adapter);
netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE);
}
@@ -819,22 +820,21 @@ static void __devexit netxen_nic_remove(
printk(KERN_INFO "State: 0x%0x\n",
readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)));
- dma_watchdog_shutdown_request(adapter);
- msleep(100);
i = 100;
- while ((dma_watchdog_shutdown_poll_result(adapter) != 1) && i) {
- printk(KERN_INFO "dma_watchdog_shutdown_poll still in progress\n");
+ do {
+ if (dma_watchdog_shutdown_request(adapter) == 1)
+ break;
msleep(100);
- i--;
- }
+ if (dma_watchdog_shutdown_poll_result(adapter) == 1)
+ break;
+ } while (--i);
if (i) {
netxen_free_adapter_offload(adapter);
} else {
- printk(KERN_ERR "failed to dma shutdown\n");
- return;
+ printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n",
+ netdev->name);
}
-
}
iounmap(adapter->ahw.db_base);
Index: netdev-2.6/drivers/net/netxen/netxen_nic.h
===================================================================
--- netdev-2.6.orig/drivers/net/netxen/netxen_nic.h
+++ netdev-2.6/drivers/net/netxen/netxen_nic.h
@@ -1179,8 +1179,7 @@ dma_watchdog_shutdown_poll_result(struct
NETXEN_CAM_RAM(NETXEN_CAM_RAM_DMA_WATCHDOG_CTRL), &ctrl, 4))
printk(KERN_ERR "failed to read dma watchdog status\n");
- return ((netxen_get_dma_watchdog_enabled(ctrl) == 0) &&
- (netxen_get_dma_watchdog_disabled(ctrl) == 0));
+ return (netxen_get_dma_watchdog_enabled(ctrl) == 0);
}
static inline int
--
^ permalink raw reply
* [PATCH] Virtual ethernet device (v.4)
From: Pavel Emelyanov @ 2007-07-19 9:24 UTC (permalink / raw)
To: David Miller, Patrick McHardy; +Cc: Linux Netdev List, devel
Veth stands for Virtual ETHernet. It is a simple tunnel driver
that works at the link layer and looks like a pair of ethernet
devices interconnected with each other.
Mainly it allows to communicate between network namespaces but
it can be used as is as well. E.g. one may join to bridged
networking segments together.
Eric recently sent a similar driver called etun with the sysfs
interface. This implementation uses another interface - the
RTM_NRELINK message introduced by Patric.
The newlink callback is organized that way to make it easy to
create the peer device in the separate namespace when we have
them in kernel.
Many thanks to Patrick for reviewing the patches and his advises
on how to make driver cleaner.
Changes from v.3:
* Reserved place for struct ifinfomsg in IFLA_INFO_DATA part
of the packet. This is not used yet, but may be in the
future.
Changes from v.2.1:
* Made the generic routine for link creation to be used
by veth driver, any other tunnel driver that needs to
create several devices at once and rtnl_newlink() code.
Changes from v.2:
* Rebase over latest netdev tree. No actual changes;
* Small code rework.
Changes from v.1:
* Per-cpu statistics;
* Standard convention for nla policy names;
* Module alias added;
* Xmit function fixes noticed by Patric;
* Code cleanup.
The patch for an ip utility is also provided.
Signed-off-by: Pavel Emelianov <xemul@openvz.org>
Acked-by: Patrick McHardy <kaber@trash.net>
^ permalink raw reply
* Re: ~3 hours old git tree: Virtual device lo asks to queue packet!
From: Patrick McHardy @ 2007-07-19 9:25 UTC (permalink / raw)
To: Arkadiusz Miskiewicz; +Cc: netdev
In-Reply-To: <200707190819.53364.arekm@maven.pl>
[-- Attachment #1: Type: text/plain, Size: 575 bytes --]
Arkadiusz Miskiewicz wrote:
> On Thursday 19 of July 2007, Patrick McHardy wrote:
>
>>Arkadiusz Miskiewicz wrote:
>>
>>>I'm having problems with networking on recent git kernel.
>>>
>>>kernel logs tons of "Virtual device lo asks to queue packet!"
>>>and networking stops working correctly:
>>>
>>>CONFIG_NETDEVICES_MULTIQUEUE=y
>>
>>Does it go away if you disable this option?
>
>
> Yes, it goes away after disabling this.
I don't see a bug in the code itself, maybe the queue_mapping points
to an invalid subqueue. Could you please try this patch and post the
output?
[-- Attachment #2: x --]
[-- Type: text/plain, Size: 457 bytes --]
diff --git a/net/core/dev.c b/net/core/dev.c
index 6357f54..f188ffa 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1605,7 +1605,8 @@ gso:
HARD_TX_UNLOCK(dev);
if (net_ratelimit())
printk(KERN_CRIT "Virtual device %s asks to "
- "queue packet!\n", dev->name);
+ "queue packet subqueue %u!\n",
+ dev->name, skb->queue_mapping);
} else {
/* Recursion is detected! It is possible,
* unfortunately */
^ permalink raw reply related
* [PATCH 1/2] Introduce the generic rtnl_create_link()
From: Pavel Emelyanov @ 2007-07-19 9:26 UTC (permalink / raw)
To: David Miller, Patrick McHardy; +Cc: Linux Netdev List, devel
In-Reply-To: <469F2DE7.9090407@openvz.org>
This routine gets the parsed rtnl attributes and creates a new
link with generic info (IFLA_LINKINFO policy). Its intention
is to help the drivers, that need to create several links at
once (like VETH).
This is nothing but a copy-paste-ed part of rtnl_newlink() function
that is responsible for creation of new device.
Signed-off-by: Pavel Emelianov <xemul@openvz.org>
Acked-by: Patrick McHardy <kaber@trash.net>
---
include/net/rtnetlink.h | 4 ++
net/core/rtnetlink.c | 83 ++++++++++++++++++++++++++++++------------------
2 files changed, 57 insertions(+), 30 deletions(-)
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 3861c05..8218288 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -78,6 +78,10 @@ extern void __rtnl_link_unregister(struc
extern int rtnl_link_register(struct rtnl_link_ops *ops);
extern void rtnl_link_unregister(struct rtnl_link_ops *ops);
+extern struct net_device *rtnl_create_link(char *ifname,
+ const struct rtnl_link_ops *ops, struct nlattr *tb[]);
+extern const struct nla_policy ifla_policy[IFLA_MAX+1];
+
#define MODULE_ALIAS_RTNL_LINK(kind) MODULE_ALIAS("rtnl-link-" kind)
#endif
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 864cbdf..02e00e8 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -714,7 +714,7 @@ cont:
return skb->len;
}
-static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
+const struct nla_policy ifla_policy[IFLA_MAX+1] = {
[IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 },
[IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
[IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
@@ -941,6 +941,50 @@ static int rtnl_dellink(struct sk_buff *
return 0;
}
+struct net_device *rtnl_create_link(char *ifname,
+ const struct rtnl_link_ops *ops, struct nlattr *tb[])
+{
+ int err;
+ struct net_device *dev;
+
+ err = -ENOMEM;
+ dev = alloc_netdev(ops->priv_size, ifname, ops->setup);
+ if (!dev)
+ goto err;
+
+ if (strchr(dev->name, '%')) {
+ err = dev_alloc_name(dev, dev->name);
+ if (err < 0)
+ goto err_free;
+ }
+
+ dev->rtnl_link_ops = ops;
+
+ if (tb[IFLA_MTU])
+ dev->mtu = nla_get_u32(tb[IFLA_MTU]);
+ if (tb[IFLA_ADDRESS])
+ memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]),
+ nla_len(tb[IFLA_ADDRESS]));
+ if (tb[IFLA_BROADCAST])
+ memcpy(dev->broadcast, nla_data(tb[IFLA_BROADCAST]),
+ nla_len(tb[IFLA_BROADCAST]));
+ if (tb[IFLA_TXQLEN])
+ dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
+ if (tb[IFLA_WEIGHT])
+ dev->weight = nla_get_u32(tb[IFLA_WEIGHT]);
+ if (tb[IFLA_OPERSTATE])
+ set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
+ if (tb[IFLA_LINKMODE])
+ dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
+
+ return dev;
+
+err_free:
+ free_netdev(dev);
+err:
+ return ERR_PTR(err);
+}
+
static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
const struct rtnl_link_ops *ops;
@@ -1051,40 +1095,17 @@ replay:
if (!ifname[0])
snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind);
- dev = alloc_netdev(ops->priv_size, ifname, ops->setup);
- if (!dev)
- return -ENOMEM;
-
- if (strchr(dev->name, '%')) {
- err = dev_alloc_name(dev, dev->name);
- if (err < 0)
- goto err_free;
- }
- dev->rtnl_link_ops = ops;
- if (tb[IFLA_MTU])
- dev->mtu = nla_get_u32(tb[IFLA_MTU]);
- if (tb[IFLA_ADDRESS])
- memcpy(dev->dev_addr, nla_data(tb[IFLA_ADDRESS]),
- nla_len(tb[IFLA_ADDRESS]));
- if (tb[IFLA_BROADCAST])
- memcpy(dev->broadcast, nla_data(tb[IFLA_BROADCAST]),
- nla_len(tb[IFLA_BROADCAST]));
- if (tb[IFLA_TXQLEN])
- dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
- if (tb[IFLA_WEIGHT])
- dev->weight = nla_get_u32(tb[IFLA_WEIGHT]);
- if (tb[IFLA_OPERSTATE])
- set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
- if (tb[IFLA_LINKMODE])
- dev->link_mode = nla_get_u8(tb[IFLA_LINKMODE]);
+ dev = rtnl_create_link(ifname, ops, tb);
- if (ops->newlink)
+ if (IS_ERR(dev))
+ err = PTR_ERR(dev);
+ else if (ops->newlink)
err = ops->newlink(dev, tb, data);
else
err = register_netdevice(dev);
-err_free:
- if (err < 0)
+
+ if (err < 0 && !IS_ERR(dev))
free_netdev(dev);
return err;
}
@@ -1333,3 +1354,5 @@ EXPORT_SYMBOL(rtnl_unlock);
EXPORT_SYMBOL(rtnl_unicast);
EXPORT_SYMBOL(rtnl_notify);
EXPORT_SYMBOL(rtnl_set_sk_err);
+EXPORT_SYMBOL(rtnl_create_link);
+EXPORT_SYMBOL(ifla_policy);
^ permalink raw reply related
* Re: [PATCH] net/, drivers/net/ , missing EXPERIMENTAL in menus
From: Robert P. J. Day @ 2007-07-19 9:25 UTC (permalink / raw)
To: Stefan Richter
Cc: Adrian Bunk, Jeff Garzik, Randy Dunlap, Gabriel C,
Linux Kernel Mailing List, netdev
In-Reply-To: <469F240E.9040205@s5r6.in-berlin.de>
On Thu, 19 Jul 2007, Stefan Richter wrote:
> Robert P. J. Day wrote:
> > On Thu, 19 Jul 2007, Adrian Bunk wrote:
> >
> > ...
> >> I would consider it more ugly to special case this and that in the
> >> kconfig code when plain dependencies already offer exactly the same
> >> functionality...
> >
> > well, this is the *third* time i've proposed adding this kind of
> > feature so, at this point, i've really given up caring about it. if
> > someone wants to do this, have at it. i have better things to do than
> > to keep suggesting it and getting nowhere with it.
>
> For better or worse, it can often be observed that feature requests
> don't set anything in motion until a first patch is sent. Even a
> patch that is far from perfect can get things going really quickly.
> (If the requested feature makes sense to other people.)
i *did* submit a preliminary patch once upon a time, and it
(predictably) went nowhere. so, if someone else wants to pick this up
and do something with it, you have my blessing. life's too short to
keep wasting time on this.
rday
--
========================================================================
Robert P. J. Day
Linux Consulting, Training and Annoying Kernel Pedantry
Waterloo, Ontario, CANADA
http://fsdev.net/wiki/index.php?title=Main_Page
========================================================================
^ permalink raw reply
* [PATCH 2/2] Virtual ethernet device driver
From: Pavel Emelyanov @ 2007-07-19 9:28 UTC (permalink / raw)
To: David Miller, Patrick McHardy; +Cc: Linux Netdev List, devel
In-Reply-To: <469F2DE7.9090407@openvz.org>
Veth stands for Virtual ETHernet. It is a simple tunnel driver
that works at the link layer and looks like a pair of ethernet
devices interconnected with each other.
Mainly it allows to communicate between network namespaces but
it can be used as is as well.
The newlink callback is organized that way to make it easy to
create the peer device in the separate namespace when we have
them in kernel.
This implementation uses another interface - the RTM_NRELINK
message introduced by Patric.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Acked-by: Patrick McHardy <kaber@trash.net>
---
drivers/net/Kconfig | 6
drivers/net/Makefile | 1
drivers/net/veth.c | 475 +++++++++++++++++++++++++++++++++++++++++++++++++++
include/net/veth.h | 12 +
4 files changed, 494 insertions(+)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 43d0317..ccfc002 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -134,6 +134,12 @@ config TUN
If you don't know what to use this for, you don't need it.
+config VETH
+ tristate "Virtual ethernet device"
+ ---help---
+ The device is an ethernet tunnel. Devices are created in pairs. When
+ one end receives the packet it appears on its pair and vice versa.
+
config NET_SB1000
tristate "General Instruments Surfboard 1000"
depends on PNP
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index eb41676..32db559 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -189,6 +189,7 @@ obj-$(CONFIG_MACSONIC) += macsonic.o
obj-$(CONFIG_MACMACE) += macmace.o
obj-$(CONFIG_MAC89x0) += mac89x0.o
obj-$(CONFIG_TUN) += tun.o
+obj-$(CONFIG_VETH) += veth.o
obj-$(CONFIG_NET_NETX) += netx-eth.o
obj-$(CONFIG_DL2K) += dl2k.o
obj-$(CONFIG_R8169) += r8169.o
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
new file mode 100644
index 0000000..b8f33f0
--- /dev/null
+++ b/drivers/net/veth.c
@@ -0,0 +1,475 @@
+/*
+ * drivers/net/veth.c
+ *
+ * Copyright (C) 2007 OpenVZ http://openvz.org, SWsoft Inc
+ *
+ * Author: Pavel Emelianov <xemul@openvz.org>
+ * Ethtool interface from: Eric W. Biederman <ebiederm@xmission.com>
+ *
+ */
+
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/etherdevice.h>
+
+#include <net/dst.h>
+#include <net/xfrm.h>
+#include <net/veth.h>
+
+#define DRV_NAME "veth"
+#define DRV_VERSION "1.0"
+
+struct veth_net_stats {
+ unsigned long rx_packets;
+ unsigned long tx_packets;
+ unsigned long rx_bytes;
+ unsigned long tx_bytes;
+ unsigned long tx_dropped;
+};
+
+struct veth_priv {
+ struct net_device *peer;
+ struct net_device *dev;
+ struct list_head list;
+ struct veth_net_stats *stats;
+ unsigned ip_summed;
+};
+
+static LIST_HEAD(veth_list);
+
+/*
+ * ethtool interface
+ */
+
+static struct {
+ const char string[ETH_GSTRING_LEN];
+} ethtool_stats_keys[] = {
+ { "peer_ifindex" },
+};
+
+static int veth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ cmd->supported = 0;
+ cmd->advertising = 0;
+ cmd->speed = SPEED_10000;
+ cmd->duplex = DUPLEX_FULL;
+ cmd->port = PORT_TP;
+ cmd->phy_address = 0;
+ cmd->transceiver = XCVR_INTERNAL;
+ cmd->autoneg = AUTONEG_DISABLE;
+ cmd->maxtxpkt = 0;
+ cmd->maxrxpkt = 0;
+ return 0;
+}
+
+static void veth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->fw_version, "N/A");
+}
+
+static void veth_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
+{
+ switch(stringset) {
+ case ETH_SS_STATS:
+ memcpy(buf, ðtool_stats_keys, sizeof(ethtool_stats_keys));
+ break;
+ }
+}
+
+static int veth_get_stats_count(struct net_device *dev)
+{
+ return ARRAY_SIZE(ethtool_stats_keys);
+}
+
+static void veth_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct veth_priv *priv;
+
+ priv = netdev_priv(dev);
+ data[0] = priv->peer->ifindex;
+}
+
+static u32 veth_get_rx_csum(struct net_device *dev)
+{
+ struct veth_priv *priv;
+
+ priv = netdev_priv(dev);
+ return priv->ip_summed == CHECKSUM_UNNECESSARY;
+}
+
+static int veth_set_rx_csum(struct net_device *dev, u32 data)
+{
+ struct veth_priv *priv;
+
+ priv = netdev_priv(dev);
+ priv->ip_summed = data ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
+ return 0;
+}
+
+static u32 veth_get_tx_csum(struct net_device *dev)
+{
+ return (dev->features & NETIF_F_NO_CSUM) != 0;
+}
+
+static int veth_set_tx_csum(struct net_device *dev, u32 data)
+{
+ if (data)
+ dev->features |= NETIF_F_NO_CSUM;
+ else
+ dev->features &= ~NETIF_F_NO_CSUM;
+ return 0;
+}
+
+static struct ethtool_ops veth_ethtool_ops = {
+ .get_settings = veth_get_settings,
+ .get_drvinfo = veth_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_rx_csum = veth_get_rx_csum,
+ .set_rx_csum = veth_set_rx_csum,
+ .get_tx_csum = veth_get_tx_csum,
+ .set_tx_csum = veth_set_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+ .get_strings = veth_get_strings,
+ .get_stats_count = veth_get_stats_count,
+ .get_ethtool_stats = veth_get_ethtool_stats,
+ .get_perm_addr = ethtool_op_get_perm_addr,
+};
+
+/*
+ * xmit
+ */
+
+static int veth_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct net_device *rcv = NULL;
+ struct veth_priv *priv, *rcv_priv;
+ struct veth_net_stats *stats;
+ int length, cpu;
+
+ skb_orphan(skb);
+
+ priv = netdev_priv(dev);
+ rcv = priv->peer;
+ rcv_priv = netdev_priv(rcv);
+
+ cpu = smp_processor_id();
+ stats = per_cpu_ptr(priv->stats, cpu);
+
+ if (!(rcv->flags & IFF_UP))
+ goto outf;
+
+ skb->pkt_type = PACKET_HOST;
+ skb->protocol = eth_type_trans(skb, rcv);
+ if (dev->features & NETIF_F_NO_CSUM)
+ skb->ip_summed = rcv_priv->ip_summed;
+
+ dst_release(skb->dst);
+ skb->dst = NULL;
+ skb->mark = 0;
+ secpath_reset(skb);
+ nf_reset(skb);
+
+ length = skb->len;
+
+ stats->tx_bytes += length;
+ stats->tx_packets++;
+
+ stats = per_cpu_ptr(rcv_priv->stats, cpu);
+ stats->rx_bytes += length;
+ stats->rx_packets++;
+
+ netif_rx(skb);
+ return 0;
+
+outf:
+ kfree_skb(skb);
+ stats->tx_dropped++;
+ return 0;
+}
+
+/*
+ * general routines
+ */
+
+static struct net_device_stats *veth_get_stats(struct net_device *dev)
+{
+ struct veth_priv *priv;
+ struct net_device_stats *dev_stats;
+ int cpu;
+ struct veth_net_stats *stats;
+
+ priv = netdev_priv(dev);
+ dev_stats = &dev->stats;
+
+ dev_stats->rx_packets = 0;
+ dev_stats->tx_packets = 0;
+ dev_stats->rx_bytes = 0;
+ dev_stats->tx_bytes = 0;
+ dev_stats->tx_dropped = 0;
+
+ for_each_online_cpu(cpu) {
+ stats = per_cpu_ptr(priv->stats, cpu);
+
+ dev_stats->rx_packets += stats->rx_packets;
+ dev_stats->tx_packets += stats->tx_packets;
+ dev_stats->rx_bytes += stats->rx_bytes;
+ dev_stats->tx_bytes += stats->tx_bytes;
+ dev_stats->tx_dropped += stats->tx_dropped;
+ }
+
+ return dev_stats;
+}
+
+static int veth_open(struct net_device *dev)
+{
+ struct veth_priv *priv;
+
+ priv = netdev_priv(dev);
+ if (priv->peer == NULL)
+ return -ENOTCONN;
+
+ if (priv->peer->flags & IFF_UP) {
+ netif_carrier_on(dev);
+ netif_carrier_on(priv->peer);
+ }
+ return 0;
+}
+
+static int veth_close(struct net_device *dev)
+{
+ struct veth_priv *priv;
+
+ if (netif_carrier_ok(dev)) {
+ priv = netdev_priv(dev);
+ netif_carrier_off(dev);
+ netif_carrier_off(priv->peer);
+ }
+ return 0;
+}
+
+static int veth_dev_init(struct net_device *dev)
+{
+ struct veth_net_stats *stats;
+ struct veth_priv *priv;
+
+ stats = alloc_percpu(struct veth_net_stats);
+ if (stats == NULL)
+ return -ENOMEM;
+
+ priv = netdev_priv(dev);
+ priv->stats = stats;
+ return 0;
+}
+
+static void veth_dev_free(struct net_device *dev)
+{
+ struct veth_priv *priv;
+
+ priv = netdev_priv(dev);
+ free_percpu(priv->stats);
+ free_netdev(dev);
+}
+
+static void veth_setup(struct net_device *dev)
+{
+ ether_setup(dev);
+
+ dev->hard_start_xmit = veth_xmit;
+ dev->get_stats = veth_get_stats;
+ dev->open = veth_open;
+ dev->stop = veth_close;
+ dev->ethtool_ops = &veth_ethtool_ops;
+ dev->features |= NETIF_F_LLTX;
+ dev->init = veth_dev_init;
+ dev->destructor = veth_dev_free;
+ netif_carrier_off(dev);
+}
+
+/*
+ * netlink interface
+ */
+
+static int veth_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+ if (tb[IFLA_ADDRESS]) {
+ if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
+ return -EINVAL;
+ if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
+ return -EADDRNOTAVAIL;
+ }
+ return 0;
+}
+
+static struct rtnl_link_ops veth_link_ops;
+
+static int veth_newlink(struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[])
+{
+ int err;
+ struct net_device *peer;
+ struct veth_priv *priv;
+ char ifname[IFNAMSIZ];
+ struct nlattr *peer_tb[IFLA_MAX + 1], **tbp;
+
+ /*
+ * create and register peer first
+ *
+ * struct ifinfomsg is at the head of VETH_INFO_PEER, but we
+ * skip it since no info from it is useful yet
+ */
+
+ if (data != NULL && data[VETH_INFO_PEER] != NULL) {
+ struct nlattr *nla_peer;
+
+ nla_peer = data[VETH_INFO_PEER];
+ err = nla_parse(peer_tb, IFLA_MAX,
+ nla_data(nla_peer) + sizeof(struct ifinfomsg),
+ nla_len(nla_peer) - sizeof(struct ifinfomsg),
+ ifla_policy);
+ if (err < 0)
+ return err;
+
+ err = veth_validate(peer_tb, NULL);
+ if (err < 0)
+ return err;
+
+ tbp = peer_tb;
+ } else
+ tbp = tb;
+
+ if (tbp[IFLA_IFNAME])
+ nla_strlcpy(ifname, tbp[IFLA_IFNAME], IFNAMSIZ);
+ else
+ snprintf(ifname, IFNAMSIZ, DRV_NAME "%%d");
+
+ peer = rtnl_create_link(ifname, &veth_link_ops, tbp);
+ if (IS_ERR(peer))
+ return PTR_ERR(peer);
+
+ if (tbp[IFLA_ADDRESS] == NULL)
+ random_ether_addr(peer->dev_addr);
+
+ err = register_netdevice(peer);
+ if (err < 0)
+ goto err_register_peer;
+
+ /*
+ * register dev last
+ *
+ * note, that since we've registered new device the dev's name
+ * should be re-allocated
+ */
+
+ if (tb[IFLA_ADDRESS] == NULL)
+ random_ether_addr(dev->dev_addr);
+
+ if (tb[IFLA_IFNAME])
+ nla_strlcpy(dev->name, tb[IFLA_IFNAME], IFNAMSIZ);
+ else
+ snprintf(dev->name, IFNAMSIZ, DRV_NAME "%%d");
+
+ if (strchr(dev->name, '%')) {
+ err = dev_alloc_name(dev, dev->name);
+ if (err < 0)
+ goto err_alloc_name;
+ }
+
+ err = register_netdevice(dev);
+ if (err < 0)
+ goto err_register_dev;
+
+ /*
+ * tie the deviced together
+ */
+
+ priv = netdev_priv(dev);
+ priv->dev = dev;
+ priv->peer = peer;
+ list_add(&priv->list, &veth_list);
+
+ priv = netdev_priv(peer);
+ priv->dev = peer;
+ priv->peer = dev;
+ INIT_LIST_HEAD(&priv->list);
+ return 0;
+
+err_register_dev:
+ /* nothing to do */
+err_alloc_name:
+ unregister_netdevice(peer);
+ return err;
+
+err_register_peer:
+ free_netdev(peer);
+ return err;
+}
+
+static void veth_dellink(struct net_device *dev)
+{
+ struct veth_priv *priv;
+ struct net_device *peer;
+
+ priv = netdev_priv(dev);
+ peer = priv->peer;
+
+ if (!list_empty(&priv->list))
+ list_del(&priv->list);
+
+ priv = netdev_priv(peer);
+ if (!list_empty(&priv->list))
+ list_del(&priv->list);
+
+ unregister_netdevice(dev);
+ unregister_netdevice(peer);
+}
+
+static const struct nla_policy veth_policy[VETH_INFO_MAX + 1];
+
+static struct rtnl_link_ops veth_link_ops = {
+ .kind = DRV_NAME,
+ .priv_size = sizeof(struct veth_priv),
+ .setup = veth_setup,
+ .validate = veth_validate,
+ .newlink = veth_newlink,
+ .dellink = veth_dellink,
+ .policy = veth_policy,
+ .maxtype = VETH_INFO_MAX,
+};
+
+/*
+ * init/fini
+ */
+
+static __init int veth_init(void)
+{
+ return rtnl_link_register(&veth_link_ops);
+}
+
+static __exit void veth_exit(void)
+{
+ struct veth_priv *priv, *next;
+
+ rtnl_lock();
+ /*
+ * cannot trust __rtnl_link_unregister() to unregister all
+ * devices, as each ->dellink call will remove two devices
+ * from the list at once.
+ */
+ list_for_each_entry_safe(priv, next, &veth_list, list)
+ veth_dellink(priv->dev);
+
+ __rtnl_link_unregister(&veth_link_ops);
+ rtnl_unlock();
+}
+
+module_init(veth_init);
+module_exit(veth_exit);
+
+MODULE_DESCRIPTION("Virtual Ethernet Tunnel");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_RTNL_LINK(DRV_NAME);
diff --git a/include/net/veth.h b/include/net/veth.h
new file mode 100644
index 0000000..3354c1e
--- /dev/null
+++ b/include/net/veth.h
@@ -0,0 +1,12 @@
+#ifndef __NET_VETH_H_
+#define __NET_VETH_H_
+
+enum {
+ VETH_INFO_UNSPEC,
+ VETH_INFO_PEER,
+
+ __VETH_INFO_MAX
+#define VETH_INFO_MAX (__VETH_INFO_MAX - 1)
+};
+
+#endif
^ permalink raw reply related
* Re: kmap_atomic() oopses in current mainline
From: Evgeniy Polyakov @ 2007-07-19 9:28 UTC (permalink / raw)
To: Andrew Morton; +Cc: netdev, linux-kernel-announce, Dan Williams
In-Reply-To: <20070719013304.3c060c99.akpm@linux-foundation.org>
Hi.
On Thu, Jul 19, 2007 at 01:33:04AM -0700, Andrew Morton (akpm@linux-foundation.org) wrote:
> I don't think the 2-year-old Vaio has offload engine support ;) Dan, this:
>
> + if (flags & ASYNC_TX_KMAP_DST)
> + dest_buf = kmap_atomic(dest, KM_USER0) + dest_offset;
> + else
> + dest_buf = page_address(dest) + dest_offset;
> +
> + if (flags & ASYNC_TX_KMAP_SRC)
> + src_buf = kmap_atomic(src, KM_USER0) + src_offset;
> + else
> + src_buf = page_address(src) + src_offset;
> +
> + memcpy(dest_buf, src_buf, len);
> +
> + if (flags & ASYNC_TX_KMAP_DST)
> + kunmap_atomic(dest_buf, KM_USER0);
> +
> + if (flags & ASYNC_TX_KMAP_SRC)
> + kunmap_atomic(src_buf, KM_USER0);
> +
>
> is very wrong if both ASYNC_TX_KMAP_DST and ASYNC_TX_KMAP_SRC can ever be
> set. We'll end up using the same kmap slot for both src add dest and we
> get either corrupted data or a BUG.
So far it can not since the only user is raid code, which only allows to
perform either reading from bio or writing into one, which requires only
one mapping.
Btw, shouldn't it always be kmap_atomic() even if flag is not set.
That pages are usual one returned by alloc_page().
--
Evgeniy Polyakov
^ permalink raw reply
* [PATCH] Module for ip utility to support veth device (v.3)
From: Pavel Emelyanov @ 2007-07-19 9:30 UTC (permalink / raw)
To: David Miller, Patrick McHardy; +Cc: Linux Netdev List, devel
In-Reply-To: <469F2DE7.9090407@openvz.org>
The usage is
# ip link add [name] type veth [device parameters] peer [name <name> <other device params>]
This consists of two parts:
1/2 makes some copy-paste changes in ip/iplink.c for generic CLI
attributes parsing,
2/2 the module itself.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Acked-by: Patrick McHardy <kaber@trash.net>
^ permalink raw reply
* [PATCH 1/2] Introduce iplink_parse() routine
From: Pavel Emelyanov @ 2007-07-19 9:32 UTC (permalink / raw)
To: David Miller, Patrick McHardy; +Cc: Linux Netdev List, devel
In-Reply-To: <469F2F30.5080602@openvz.org>
This routine parses CLI attributes, describing generic link
parameters such as name, address, etc.
This is mostly copy-pasted from iplink_modify().
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Acked-by: Patrick McHardy <kaber@trash.net>
---
include/utils.h | 3 +
ip/iplink.c | 127 ++++++++++++++++++++++++++++++++------------------------
2 files changed, 76 insertions(+), 54 deletions(-)
diff --git a/include/utils.h b/include/utils.h
index a3fd335..3fd851d 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -146,4 +146,7 @@ extern int cmdlineno;
extern size_t getcmdline(char **line, size_t *len, FILE *in);
extern int makeargs(char *line, char *argv[], int maxargs);
+struct iplink_req;
+int iplink_parse(int argc, char **argv, struct iplink_req *req,
+ char **name, char **type, char **link, char **dev);
#endif /* __UTILS_H__ */
diff --git a/ip/iplink.c b/ip/iplink.c
index cfacdab..e0e0d85 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -142,140 +142,159 @@ static int iplink_have_newlink(void)
}
#endif /* ! IPLINK_IOCTL_COMPAT */
-static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
+struct iplink_req {
+ struct nlmsghdr n;
+ struct ifinfomsg i;
+ char buf[1024];
+};
+
+int iplink_parse(int argc, char **argv, struct iplink_req *req,
+ char **name, char **type, char **link, char **dev)
{
+ int ret, len;
+ char abuf[32];
int qlen = -1;
int mtu = -1;
- int len;
- char abuf[32];
- char *dev = NULL;
- char *name = NULL;
- char *link = NULL;
- char *type = NULL;
- struct link_util *lu = NULL;
- struct {
- struct nlmsghdr n;
- struct ifinfomsg i;
- char buf[1024];
- } req;
- memset(&req, 0, sizeof(req));
-
- req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
- req.n.nlmsg_flags = NLM_F_REQUEST|flags;
- req.n.nlmsg_type = cmd;
- req.i.ifi_family = preferred_family;
+ ret = argc;
while (argc > 0) {
if (strcmp(*argv, "up") == 0) {
- req.i.ifi_change |= IFF_UP;
- req.i.ifi_flags |= IFF_UP;
+ req->i.ifi_change |= IFF_UP;
+ req->i.ifi_flags |= IFF_UP;
} else if (strcmp(*argv, "down") == 0) {
- req.i.ifi_change |= IFF_UP;
- req.i.ifi_flags &= ~IFF_UP;
+ req->i.ifi_change |= IFF_UP;
+ req->i.ifi_flags &= ~IFF_UP;
} else if (strcmp(*argv, "name") == 0) {
NEXT_ARG();
- name = *argv;
+ *name = *argv;
} else if (matches(*argv, "link") == 0) {
NEXT_ARG();
- link = *argv;
+ *link = *argv;
} else if (matches(*argv, "address") == 0) {
NEXT_ARG();
len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
- addattr_l(&req.n, sizeof(req), IFLA_ADDRESS, abuf, len);
+ addattr_l(&req->n, sizeof(*req), IFLA_ADDRESS, abuf, len);
} else if (matches(*argv, "broadcast") == 0 ||
- strcmp(*argv, "brd") == 0) {
+ strcmp(*argv, "brd") == 0) {
NEXT_ARG();
len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
- addattr_l(&req.n, sizeof(req), IFLA_BROADCAST, abuf, len);
+ addattr_l(&req->n, sizeof(*req), IFLA_BROADCAST, abuf, len);
} else if (matches(*argv, "txqueuelen") == 0 ||
- strcmp(*argv, "qlen") == 0 ||
- matches(*argv, "txqlen") == 0) {
+ strcmp(*argv, "qlen") == 0 ||
+ matches(*argv, "txqlen") == 0) {
NEXT_ARG();
if (qlen != -1)
duparg("txqueuelen", *argv);
if (get_integer(&qlen, *argv, 0))
invarg("Invalid \"txqueuelen\" value\n", *argv);
- addattr_l(&req.n, sizeof(req), IFLA_TXQLEN, &qlen, 4);
+ addattr_l(&req->n, sizeof(*req), IFLA_TXQLEN, &qlen, 4);
} else if (strcmp(*argv, "mtu") == 0) {
NEXT_ARG();
if (mtu != -1)
duparg("mtu", *argv);
if (get_integer(&mtu, *argv, 0))
invarg("Invalid \"mtu\" value\n", *argv);
- addattr_l(&req.n, sizeof(req), IFLA_MTU, &mtu, 4);
+ addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4);
} else if (strcmp(*argv, "multicast") == 0) {
NEXT_ARG();
- req.i.ifi_change |= IFF_MULTICAST;
+ req->i.ifi_change |= IFF_MULTICAST;
if (strcmp(*argv, "on") == 0) {
- req.i.ifi_flags |= IFF_MULTICAST;
+ req->i.ifi_flags |= IFF_MULTICAST;
} else if (strcmp(*argv, "off") == 0) {
- req.i.ifi_flags &= ~IFF_MULTICAST;
+ req->i.ifi_flags &= ~IFF_MULTICAST;
} else
return on_off("multicast");
} else if (strcmp(*argv, "allmulticast") == 0) {
NEXT_ARG();
- req.i.ifi_change |= IFF_ALLMULTI;
+ req->i.ifi_change |= IFF_ALLMULTI;
if (strcmp(*argv, "on") == 0) {
- req.i.ifi_flags |= IFF_ALLMULTI;
+ req->i.ifi_flags |= IFF_ALLMULTI;
} else if (strcmp(*argv, "off") == 0) {
- req.i.ifi_flags &= ~IFF_ALLMULTI;
+ req->i.ifi_flags &= ~IFF_ALLMULTI;
} else
return on_off("allmulticast");
} else if (strcmp(*argv, "promisc") == 0) {
NEXT_ARG();
- req.i.ifi_change |= IFF_PROMISC;
+ req->i.ifi_change |= IFF_PROMISC;
if (strcmp(*argv, "on") == 0) {
- req.i.ifi_flags |= IFF_PROMISC;
+ req->i.ifi_flags |= IFF_PROMISC;
} else if (strcmp(*argv, "off") == 0) {
- req.i.ifi_flags &= ~IFF_PROMISC;
+ req->i.ifi_flags &= ~IFF_PROMISC;
} else
return on_off("promisc");
} else if (strcmp(*argv, "trailers") == 0) {
NEXT_ARG();
- req.i.ifi_change |= IFF_NOTRAILERS;
+ req->i.ifi_change |= IFF_NOTRAILERS;
if (strcmp(*argv, "off") == 0) {
- req.i.ifi_flags |= IFF_NOTRAILERS;
+ req->i.ifi_flags |= IFF_NOTRAILERS;
} else if (strcmp(*argv, "on") == 0) {
- req.i.ifi_flags &= ~IFF_NOTRAILERS;
+ req->i.ifi_flags &= ~IFF_NOTRAILERS;
} else
return on_off("trailers");
} else if (strcmp(*argv, "arp") == 0) {
NEXT_ARG();
- req.i.ifi_change |= IFF_NOARP;
+ req->i.ifi_change |= IFF_NOARP;
if (strcmp(*argv, "on") == 0) {
- req.i.ifi_flags &= ~IFF_NOARP;
+ req->i.ifi_flags &= ~IFF_NOARP;
} else if (strcmp(*argv, "off") == 0) {
- req.i.ifi_flags |= IFF_NOARP;
+ req->i.ifi_flags |= IFF_NOARP;
} else
return on_off("noarp");
#ifdef IFF_DYNAMIC
} else if (matches(*argv, "dynamic") == 0) {
NEXT_ARG();
- req.i.ifi_change |= IFF_DYNAMIC;
+ req->i.ifi_change |= IFF_DYNAMIC;
if (strcmp(*argv, "on") == 0) {
- req.i.ifi_flags |= IFF_DYNAMIC;
+ req->i.ifi_flags |= IFF_DYNAMIC;
} else if (strcmp(*argv, "off") == 0) {
- req.i.ifi_flags &= ~IFF_DYNAMIC;
+ req->i.ifi_flags &= ~IFF_DYNAMIC;
} else
return on_off("dynamic");
#endif
} else if (matches(*argv, "type") == 0) {
NEXT_ARG();
- type = *argv;
+ *type = *argv;
argc--; argv++;
break;
} else {
- if (strcmp(*argv, "dev") == 0) {
+ if (strcmp(*argv, "dev") == 0) {
NEXT_ARG();
}
- if (dev)
+ if (*dev)
duparg2("dev", *argv);
- dev = *argv;
+ *dev = *argv;
}
argc--; argv++;
}
+ return ret - argc;
+}
+
+static int iplink_modify(int cmd, unsigned int flags, int argc, char **argv)
+{
+ int len;
+ char *dev = NULL;
+ char *name = NULL;
+ char *link = NULL;
+ char *type = NULL;
+ struct link_util *lu = NULL;
+ struct iplink_req req;
+ int ret;
+
+ memset(&req, 0, sizeof(req));
+
+ req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+ req.n.nlmsg_flags = NLM_F_REQUEST|flags;
+ req.n.nlmsg_type = cmd;
+ req.i.ifi_family = preferred_family;
+
+ ret = iplink_parse(argc, argv, &req, &name, &type, &link, &dev);
+ if (ret < 0)
+ return ret;
+
+ argc -= ret;
+ argv += ret;
ll_init_map(&rth);
if (type) {
^ permalink raw reply related
* [PATCH 2/2] Module for ip utility to support veth device
From: Pavel Emelyanov @ 2007-07-19 9:33 UTC (permalink / raw)
To: David Miller, Patrick McHardy; +Cc: Linux Netdev List, devel
In-Reply-To: <469F2F30.5080602@openvz.org>
The link_veth.so itself.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Acked-by: Patrick McHardy <kaber@trash.net>
---
Makefile | 6 ++++-
link_veth.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
veth.h | 12 +++++++++++
3 files changed, 80 insertions(+), 1 deletion(-)
diff --git a/ip/Makefile b/ip/Makefile
index 9a5bfe3..b46bce3 100644
--- a/ip/Makefile
+++ b/ip/Makefile
@@ -8,8 +8,9 @@ RTMONOBJ=rtmon.o
ALLOBJ=$(IPOBJ) $(RTMONOBJ)
SCRIPTS=ifcfg rtpr routel routef
TARGETS=ip rtmon
+LIBS=link_veth.so
-all: $(TARGETS) $(SCRIPTS)
+all: $(TARGETS) $(SCRIPTS) $(LIBS)
ip: $(IPOBJ) $(LIBNETLINK) $(LIBUTIL)
@@ -24,3 +25,6 @@ clean:
LDLIBS += -ldl
LDFLAGS += -Wl,-export-dynamic
+
+%.so: %.c
+ $(CC) $(CFLAGS) -shared $< -o $@
diff --git a/ip/link_veth.c b/ip/link_veth.c
new file mode 100644
index 0000000..ded2cdd
--- /dev/null
+++ b/ip/link_veth.c
@@ -0,0 +1,63 @@
+/*
+ * link_veth.c veth driver module
+ *
+ * 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 Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Authors: Pavel Emelianov <xemul@openvz.org>
+ *
+ */
+
+#include <string.h>
+
+#include "utils.h"
+#include "ip_common.h"
+#include "veth.h"
+
+#define IFNAMSIZ 16
+
+static void usage(void)
+{
+ printf("Usage: ip link add ... type veth "
+ "[peer <peer-name>] [mac <mac>] [peer_mac <mac>]\n");
+}
+
+static int veth_parse_opt(struct link_util *lu, int argc, char **argv,
+ struct nlmsghdr *hdr)
+{
+ char *name, *type, *link, *dev;
+ int err, len;
+ struct rtattr * data;
+
+ if (strcmp(argv[0], "peer") != 0) {
+ usage();
+ return -1;
+ }
+
+ data = NLMSG_TAIL(hdr);
+ addattr_l(hdr, 1024, VETH_INFO_PEER, NULL, 0);
+
+ hdr->nlmsg_len += sizeof(struct ifinfomsg);
+
+ err = iplink_parse(argc - 1, argv + 1, (struct iplink_req *)hdr,
+ &name, &type, &link, &dev);
+ if (err < 0)
+ return err;
+
+ if (name) {
+ len = strlen(name) + 1;
+ if (len > IFNAMSIZ)
+ invarg("\"name\" too long\n", *argv);
+ addattr_l(hdr, 1024, IFLA_IFNAME, name, len);
+ }
+
+ data->rta_len = (void *)NLMSG_TAIL(hdr) - (void *)data;
+ return argc - 1 - err;
+}
+
+struct link_util veth_link_util = {
+ .id = "veth",
+ .parse_opt = veth_parse_opt,
+};
diff --git a/ip/veth.h b/ip/veth.h
new file mode 100644
index 0000000..aa2e6f9
--- /dev/null
+++ b/ip/veth.h
@@ -0,0 +1,12 @@
+#ifndef __NET_VETH_H__
+#define __NET_VETH_H__
+
+enum {
+ VETH_INFO_UNSPEC,
+ VETH_INFO_PEER,
+
+ __VETH_INFO_MAX
+#define VETH_INFO_MAX (__VETH_INFO_MAX - 1)
+};
+
+#endif
^ 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