* [PATCH] [PATCH] HFSC (7) & (8) doc... (fixups)
From: Michal Soltys @ 2011-10-31 21:56 UTC (permalink / raw)
To: vapier; +Cc: stephen.hemminger, netdev
In-Reply-To: <4EAF1904.8060307@ziu.info>
Few minore changes and small additions.
---
man/man7/tc-hfsc.7 | 94 ++++++++++++++++++++++++++++++++++++----------------
man/man8/tc-hfsc.8 | 2 +-
man/man8/tc-stab.8 | 49 +++++++++++++++-----------
3 files changed, 94 insertions(+), 51 deletions(-)
diff --git a/man/man7/tc-hfsc.7 b/man/man7/tc-hfsc.7
index bcdea7b..9a9d85a 100644
--- a/man/man7/tc-hfsc.7
+++ b/man/man7/tc-hfsc.7
@@ -1,4 +1,4 @@
-.TH HFSC 7 "25 February 2009" iproute2 Linux
+.TH HFSC 7 "31 October 2011" iproute2 Linux
.ce 1
\fBHIERARCHICAL FAIR SERVICE CURVE\fR
.
@@ -158,7 +158,7 @@ curve.
.IP "V()"
In linkshare criterion, arbitrates which packet to send next. Note that V() is
function of a virtual time \- see \fBLINKSHARE CRITERION\fR section for
-details. Virtual time \&'vt' corresponds to packets' heads
+details. Virtual time \&'vt' corresponds to packets' heads
(vt\~=\~V^(\-1)(w)). Based on LS service curve.
.IP "F()"
An extension to linkshare criterion, used to limit at which speed linkshare
@@ -187,12 +187,12 @@ Interface 10mbit, two classes, both with two\-piece linear service curves:
.PP
Assume for a moment, that we only use D() for both finding eligible packets,
and choosing the most fitting one, thus eligible time would be computed as
-D^(\-1)(w) and deadline time would be computed as D^(\-1)(w+l). If the 2nd
+D^(\-1)(w) and deadline time would be computed as D^(\-1)(w+l). If the 2nd
class starts sending packets 1 second after the 1st class, it's of course
impossible to guarantee 14mbit, as the interface capability is only 10mbit.
The only workaround in this scenario is to allow the 1st class to send the
packets earlier that would normally be allowed. That's where separate E() comes
-to help. Putting all the math aside (see HFSC paper for details), E() for RT
+to help. Putting all the math aside (see HFSC paper for details), E() for RT
concave service curve is just like D(), but for the RT convex service curve \-
it's constructed using \fIonly\fR RT service curve's 2nd slope (in our example
\- 7mbit).
@@ -255,7 +255,7 @@ Such approach has its price though. The problem is analogous to what was
presented in previous section and is caused by non\-linearity of service
curves:
.IP 1) 4
-either it's impossible to guarantee both service curves and satisfy fairness
+either it's impossible to guarantee service curves and satisfy fairness
during certain time periods:
.RS 4
@@ -278,40 +278,40 @@ beyond of what the interface is capable of.
.RE
.IP 2) 4
-and/or it's impossible to guarantee service curves of all classes at all
+and/or it's impossible to guarantee service curves of all classes at the same
+time [fairly or not]:
.RS 4
-Even if we didn't use virtual time and allowed a session to be "punished",
-there's a possibility that service curves of all classes couldn't be
-guaranteed for a brief period. Consider following, a bit more complicated
-example:
-
-Root interface, classes A and B with concave and convex curve (summing up to
-root), A1 & A2 (children of A), \fIboth\fR with concave curves summing up to A,
-B1 & B2 (children of B), \fIboth\fR with convex curves summing up to B.
-Assume that A2, B1 and B2 are constantly backlogged, and at some later point
-A1 becomes backlogged. We can easily choose slopes, so that even if we
-"punish" A2 for earlier excess bandwidth received, A1 will have no chance of
-getting bandwidth corresponding to its first slope. Following from the above
-example:
+This is similar to the above case, but a bit more subtle. We will consider two
+subtrees, arbitrated by their common (root here) parent:
.nf
+R (root) -\ 10mbit
+
A \- 7mbit, then 3mbit
A1 \- 5mbit, then 2mbit
A2 \- 2mbit, then 1mbit
B \- 3mbit, then 7mbit
-B1 \- 2mbit, then 5mbit
-B2 \- 1mbit, then 2mbit
.fi
-At the point when A1 starts sending, it should get 5mbit to not violate its
-service curve. A2 gets punished and doesn't send at all, B1 and B2 both keep
-sending at their 5mbit and 2mbit. But as you can see, we already are beyond
-interface's capacity \- at 12mbit. A1 could get 3mbit at most. If we used
-virtual times and kept fairness property, A1 and A2 would send at 3mbit
-together with 5:2 ratio (so respectively at ~2.14mbit and ~0.86mbit).
+R arbitrates between left subtree (A) and right (B). Assume that A2 and B are
+constantly backlogged, and at some later point A1 becomes backlogged (when all
+other classes are in their 2nd linear part).
+
+What happens now ? B (choice made by R) will \fIalways\fR get 7 mbit as R is
+only (obviously) concerned with the ratio between its direct children. Thus A
+subtree gets 3mbit, but its children would want (at the point when A1 became
+backlogged) 5mbit + 1mbit. That's of course impossible, as they can only get
+3mbit due to interface limitation.
+
+In the left subtree \- we have the same situation as previously (fair split
+between A1 and A2, but violated guarantees), but in the whole tree \- there's
+no fairness (B got 7mbit, but A1 and A2 have to fit together in 3mbit) and
+there's no guarantees for all classes (only B got what it wanted). Even if we
+violated fairness in the A subtree and set A2's service curve to 0, A1 would
+still not get the required bandwidth.
.RE
.
.SH "UPPERLIMIT CRITERION"
@@ -416,6 +416,19 @@ In the other words - LS criterion is meaningless in the above example.
You can quickly "workaround" it by making sure each leaf class has RT service
curve assigned (thus guaranteeing all of them will get some bandwidth), but it
doesn't make it any more valid.
+
+Keep in mind - if you use nonlinear curves and irregularities explained above
+happen \fIonly\fR in the first segment, then there's little wrong with
+"overusing" RT curve a bit:
+
+.nf
+A \- ls 5.0mbit, rt 9mbit/30ms, then 1mbit
+B \- ls 2.5mbit
+C \- ls 2.5mbit
+.fi
+
+Here, the vt of A will "spike" in the initial period, but then A will never get more
+than 1mbit, until B & C catch up. Then everything will be back to normal.
.
.SH "LINUX AND TIMER RESOLUTION"
.
@@ -434,7 +447,7 @@ If you have \&'tickless system' enabled, then the timer interrupt will trigger
as slowly as possible, but each time a scheduler throttles itself (or any
other part of the kernel needs better accuracy), the rate will be increased as
needed / possible. The ceiling is either \&'timer frequency' if \&'high
-resolution timer support' is not available or not compiled in. Otherwise it's
+resolution timer support' is not available or not compiled in, or it's
hardware dependent and can go \fIfar\fR beyond the highest \&'timer frequency'
setting available.
@@ -458,7 +471,7 @@ tc class add dev eth0 parent 1:0 classid 1:1 hfsc rt m2 10mbit
Assuming packet of ~1KB size and HZ=100, that averages to ~0.8mbit \- anything
beyond it (e.g. the above example with specified rate over 10x bigger) will
-require appropriate queuing and cause bursts every ~10 ms. As you can
+require appropriate queuing and cause bursts every ~10 ms. As you can
imagine, any HFSC's RT guarantees will be seriously invalidated by that.
Aforementioned example is mainly important if you deal with old hardware \- as
it's particularly popular for home server chores. Even then, you can easily
@@ -510,6 +523,29 @@ curve there, and in such scenario HFSC simply doesn't throttle at all.
So, in rare case you need those speeds with only RT service curve, or with UL
service curve \- remember about drawbacks.
.
+.SH "CAVEAT: RANDOM ONLINE EXAMPLES"
+.
+For reasons unknown (though well guessed), many examples you can google love to
+overuse UL criterion and stuff it in every node possible. This makes no sense
+and works against what HFSC tries to do (and does pretty damn well). Use UL
+where it makes sense - on the uppermost node to match upstream router's uplink
+capacity. Or - in special cases, such as testing (limit certain subtree to some
+speed) or customers that must never get more than certain speed. In the last
+case you can usually achieve the same by just using RT criterion without LS+UL
+on leaf nodes.
+
+As for router case - remember it's good to differentiate between "traffic to
+router" (remote console, web config, etc.) and "outgoing traffic", so for
+example:
+
+.nf
+tc qdisc add dev eth0 root handle 1:0 hfsc default 0x8002
+tc class add dev eth0 parent 1:0 classid 1:999 hfsc rt m2 50mbit
+tc class add dev eth0 parent 1:0 classid 1:1 hfsc ls m2 2mbit ul m2 2mbit
+.fi
+
+\&... so "internet" tree under 1:1 and "router itself" as 1:999
+.
.SH "LAYER2 ADAPTATION"
.
Please refer to \fBtc\-stab\fR(8)
diff --git a/man/man8/tc-hfsc.8 b/man/man8/tc-hfsc.8
index 22018c0..c5ff331 100644
--- a/man/man8/tc-hfsc.8
+++ b/man/man8/tc-hfsc.8
@@ -1,4 +1,4 @@
-.TH HFSC 8 "25 February 2009" iproute2 Linux
+.TH HFSC 8 "31 October 2011" iproute2 Linux
.
.SH NAME
HFSC \- Hierarchical Fair Service Curve's control under linux
diff --git a/man/man8/tc-stab.8 b/man/man8/tc-stab.8
index 1442a69..522ea00 100644
--- a/man/man8/tc-stab.8
+++ b/man/man8/tc-stab.8
@@ -1,4 +1,4 @@
-.TH STAB 8 "25 February 2009" iproute2 Linux
+.TH STAB 8 "31 October 2011" iproute2 Linux
.
.SH NAME
tc\-stab \- Generic size table manipulations
@@ -42,14 +42,14 @@ size is calculated only once \- when a qdisc enqueues the packet. Initial root
enqueue initializes it to the real packet's size.
Each qdisc can use different size table, but the adjusted size is stored in
-area shared by whole qdisc hierarchy attached to the interface (technically,
-it's stored in skb). The effect is, that if you have such setup, the last qdisc
-with a stab in a chain "wins". For example, consider HFSC with simple pfifo
-attached to one of its leaf classes. If that pfifo qdisc has stab defined, it
-will override lengths calculated during HFSC's enqueue, and in turn, whenever
-HFSC tries to dequeue a packet, it will use potentially invalid size in its
-calculations. Normal setups will usually include stab defined only on root
-qdisc, but further overriding gives extra flexibility for less usual setups.
+area shared by whole qdisc hierarchy attached to the interface. The effect is,
+that if you have such setup, the last qdisc with a stab in a chain "wins". For
+example, consider HFSC with simple pfifo attached to one of its leaf classes.
+If that pfifo qdisc has stab defined, it will override lengths calculated
+during HFSC's enqueue, and in turn, whenever HFSC tries to dequeue a packet, it
+will use potentially invalid size in its calculations. Normal setups will
+usually include stab defined only on root qdisc, but further overriding gives
+extra flexibility for less usual setups.
Initial size table is calculated by \fBtc\fR tool using \fBmtu\fR and
\fBtsize\fR parameters. The algorithm sets each slot's size to the smallest
@@ -59,18 +59,16 @@ table will usually support more than is required by \fBmtu\fR.
For example, with \fBmtu\fR\~=\~1500 and \fBtsize\fR\~=\~128, a table with 128
slots will be created, where slot 0 will correspond to sizes 0\-16, slot 1 to
-17\~\-\~32, \&..., slot 127 to 2033\~\-\~2048. Note, that the sizes
-are shifted 1 byte (normally you would expect 0\~\-\~15, 16\~\-\~31, \&...,
-2032\~\-\~2047). Sizes assigned to each slot depend on \fBlinklayer\fR parameter.
+17\~\-\~32, \&..., slot 127 to 2033\~\-\~2048. Sizes assigned to each slot
+depend on \fBlinklayer\fR parameter.
Stab calculation is also safe for an unusual case, when a size assigned to a
slot would be larger than 2^16\-1 (you will lose the accuracy though).
During kernel part of packet size adjustment, \fBoverhead\fR will be added to
-original size, and after subtracting 1 (to land in the proper slot \- see above
-about shifting by 1 byte) slot will be calculated. If the size would cause
-overflow, more than 1 slot will be used to get the final size. It of course will
-affect accuracy, but it's only a guard against unusual situations.
+original size, and then slot will be calculated. If the size would cause
+overflow, more than 1 slot will be used to get the final size. It of course
+will affect accuracy, but it's only a guard against unusual situations.
Currently there're two methods of creating values stored in the size table \-
ethernet and atm (adsl):
@@ -82,8 +80,8 @@ This is basically 1\-1 mapping, so following our example from above
and so on, up to slot 127 with 2048. Note, that \fBmpu\fR\~>\~0 must be
specified, and slots that would get less than specified by \fBmpu\fR, will get
\fBmpu\fR instead. If you don't specify \fBmpu\fR, the size table will not be
-created at all, although any \fBoverhead\fR value will be respected during
-calculations.
+created at all (it wouldn't make any difference), although any \fBoverhead\fR
+value will be respected during calculations.
.IP "atm, adsl"
.br
ATM linklayer consists of 53 byte cells, where each of them provides 48 bytes
@@ -127,7 +125,7 @@ IPoA in LLC case requires SNAP, instead of LLC\-NLPID (see rfc2684) \- this is
the reason, why it actually takes more space than PPPoA.
.IP \(bu
In rare cases, FCS might be preserved on protocols that include ethernet frame
-(Bridged and PPPoE). In such situation, any ethernet specific padding
+(Bridged and PPPoE). In such situation, any ethernet specific padding
guaranteeing 64 bytes long frame size has to be included as well (see rfc2684).
In the other words, it also guarantees that any packet you send will take
minimum 2 atm cells. You should set \fBmpu\fR accordingly for that.
@@ -136,11 +134,20 @@ When size table is consulted, and you're shaping traffic for the sake of
another modem/router, ethernet header (without padding) will already be added
to initial packet's length. You should compensate for that by subtracting 14
from the above overheads in such case. If you're shaping directly on the router
-(for example, with speedtouch usb modem) using ppp daemon, layer2 header will
-not be added yet.
+(for example, with speedtouch usb modem) using ppp daemon, you're using raw ip
+interface without underlying layer2, so nothing will be added.
For more thorough explanations, please see \fB[1]\fR and \fB[2]\fR.
.
+.SH "ETHERNET CARDS CONSIDERATIONS"
+.
+It's often forgotten, that modern network cards (even cheap ones on desktop
+motherboards) and/or their drivers often support different offloading
+mechanisms. In context of traffic shaping, 'tso' and 'gso' might cause
+undesirable effects, due to massive tcp segments being considered during
+traffic shaping (including stab calculations). For slow uplink interfaces,
+it's good to use \fBethtool\fR to turn off offloading features.
+.
.SH "SEE ALSO"
.
\fBtc\fR(8), \fBtc\-hfsc\fR(7), \fBtc\-hfsc\fR(8),
--
1.7.7.1
^ permalink raw reply related
* Re: [PATCH] 3c505: Fix compile breakage
From: David Miller @ 2011-10-31 21:57 UTC (permalink / raw)
To: joe; +Cc: bharrosh, jbaron, philb, linux-kernel, netdev, randy.dunlap, sfr
In-Reply-To: <1320097524.4399.8.camel@Joe-Laptop>
From: Joe Perches <joe@perches.com>
Date: Mon, 31 Oct 2011 23:45:24 +0200
> The joys of preprocessor games with c90 named initializers.
>
> commit 07613b0b5ef8
> ("dynamic_debug: consolidate repetitive struct _ddebug descriptor definitions")
> uses a ".filename" named initializer.
>
> When filename is also a #define this fails to compile.
>
> Remove #define filename from 3c505.c
>
> Signed-off-by: Joe Perches <joe@perches.com>
Andrew Morton submitted a fix for this earlier today.
http://marc.info/?l=linux-netdev&m=132009089027792&w=2
^ permalink raw reply
* [PATCH] flexcan: Fix CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK
From: Reuben Dowle @ 2011-10-31 22:18 UTC (permalink / raw)
To: netdev; +Cc: linux-can
Currently the flexcan driver uses hardware local echo. This blindly echos all transmitted frames to all receiving sockets, regardless what CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK are set to.
This patch now submits transmitted frames to be echoed in the transmit complete interrupt, preserving the reference to the sending socket. This allows the can protocol to correctly handle the local echo.
Signed-off-by: Reuben Dowle <reuben.dowle@navico.com>
---
drivers/net/can/flexcan.c | 19 +++++++++++++++----
1 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index e023379..542ada8 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -302,7 +302,7 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
flexcan_write(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
flexcan_write(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
- kfree_skb(skb);
+ can_put_echo_skb(skb, dev, 0);
/* tx_packets is incremented in flexcan_irq */
stats->tx_bytes += cf->can_dlc;
@@ -612,6 +612,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
/* tx_bytes is incremented in flexcan_start_xmit */
stats->tx_packets++;
flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1);
+ can_get_echo_skb(dev, 0);
netif_wake_queue(dev);
}
@@ -670,6 +671,8 @@ static int flexcan_chip_start(struct net_device *dev)
int err;
u32 reg_mcr, reg_ctrl;
+ can_free_echo_skb(dev, 0);
+
/* enable module */
flexcan_chip_enable(priv);
@@ -697,12 +700,13 @@ static int flexcan_chip_start(struct net_device *dev)
* only supervisor access
* enable warning int
* choose format C
+ * disable local echo
*
*/
reg_mcr = flexcan_read(®s->mcr);
reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
- FLEXCAN_MCR_IDAM_C;
+ FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS;
dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr);
flexcan_write(reg_mcr, ®s->mcr);
@@ -970,7 +974,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
goto failed_map;
}
- dev = alloc_candev(sizeof(struct flexcan_priv), 0);
+ dev = alloc_candev(sizeof(struct flexcan_priv), 1);
if (!dev) {
err = -ENOMEM;
goto failed_alloc;
@@ -978,7 +982,14 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
dev->netdev_ops = &flexcan_netdev_ops;
dev->irq = irq;
- dev->flags |= IFF_ECHO; /* we support local echo in hardware */
+
+ /* Driver supports local echo.
+ * We support local echo in hardware, however this is not used because
+ * hardware local echo loses the sending socket reference
+ * (thus CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK socket options
+ * would not work)
+ */
+ dev->flags |= IFF_ECHO;
priv = netdev_priv(dev);
priv->can.clock.freq = clock_freq;
^ permalink raw reply related
* Re: [PATCH] 3c505: Fix compile breakage
From: Joe Perches @ 2011-10-31 22:18 UTC (permalink / raw)
To: David Miller; +Cc: bharrosh, jbaron, linux-kernel, netdev, Andrew Morton
In-Reply-To: <20111031.175743.115974002318620455.davem@davemloft.net>
On Mon, 2011-10-31 at 17:57 -0400, David Miller wrote:
> From: Joe Perches <joe@perches.com>
> > Remove #define filename from 3c505.c
> > Signed-off-by: Joe Perches <joe@perches.com>
> Andrew Morton submitted a fix for this earlier today.
Great, thanks.
^ permalink raw reply
* Re: [PATCH] flexcan: Fix CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK
From: Marc Kleine-Budde @ 2011-10-31 22:31 UTC (permalink / raw)
To: Reuben Dowle; +Cc: netdev, linux-can
In-Reply-To: <70F6AAAFDC054F41B9994A9BCD3DF64E16FAA1DD@exch01-aklnz.MARINE.NET.INT>
[-- Attachment #1: Type: text/plain, Size: 3983 bytes --]
On 10/31/2011 11:18 PM, Reuben Dowle wrote:
> Currently the flexcan driver uses hardware local echo. This blindly echos all transmitted frames to all receiving sockets, regardless what CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK are set to.
>
> This patch now submits transmitted frames to be echoed in the transmit complete interrupt, preserving the reference to the sending socket. This allows the can protocol to correctly handle the local echo.
>
> Signed-off-by: Reuben Dowle <reuben.dowle@navico.com>
Patch looks quite good. Can you please wrap the description to about 72
chars?
>
> ---
> drivers/net/can/flexcan.c | 19 +++++++++++++++----
> 1 files changed, 15 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
> index e023379..542ada8 100644
> --- a/drivers/net/can/flexcan.c
> +++ b/drivers/net/can/flexcan.c
> @@ -302,7 +302,7 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
> flexcan_write(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
> flexcan_write(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
>
> - kfree_skb(skb);
> + can_put_echo_skb(skb, dev, 0);
>
> /* tx_packets is incremented in flexcan_irq */
> stats->tx_bytes += cf->can_dlc;
> @@ -612,6 +612,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
> /* tx_bytes is incremented in flexcan_start_xmit */
> stats->tx_packets++;
> flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1);
> + can_get_echo_skb(dev, 0);
> netif_wake_queue(dev);
> }
>
> @@ -670,6 +671,8 @@ static int flexcan_chip_start(struct net_device *dev)
> int err;
> u32 reg_mcr, reg_ctrl;
>
> + can_free_echo_skb(dev, 0);
what about putting this to flexcan_chip_stop? Otherwise you risk a
memleak if you do "ifconfig down; rmmod flexcan"
> +
> /* enable module */
> flexcan_chip_enable(priv);
>
> @@ -697,12 +700,13 @@ static int flexcan_chip_start(struct net_device *dev)
> * only supervisor access
> * enable warning int
> * choose format C
> + * disable local echo
> *
> */
> reg_mcr = flexcan_read(®s->mcr);
> reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
> FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
> - FLEXCAN_MCR_IDAM_C;
> + FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS;
> dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr);
> flexcan_write(reg_mcr, ®s->mcr);
>
> @@ -970,7 +974,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
> goto failed_map;
> }
>
> - dev = alloc_candev(sizeof(struct flexcan_priv), 0);
> + dev = alloc_candev(sizeof(struct flexcan_priv), 1);
> if (!dev) {
> err = -ENOMEM;
> goto failed_alloc;
> @@ -978,7 +982,14 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
>
> dev->netdev_ops = &flexcan_netdev_ops;
> dev->irq = irq;
> - dev->flags |= IFF_ECHO; /* we support local echo in hardware */
> +
> + /* Driver supports local echo.
> + * We support local echo in hardware, however this is not used because
> + * hardware local echo loses the sending socket reference
> + * (thus CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK socket options
> + * would not work)
> + */
IMHO, you can skip this comment. The patch description is good enough.
> + dev->flags |= IFF_ECHO;
>
> priv = netdev_priv(dev);
> priv->can.clock.freq = clock_freq;
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-can" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
^ permalink raw reply
* Re: [PATCH] bonding:update speed/duplex for NETDEV_CHANGE
From: Ben Hutchings @ 2011-10-31 22:41 UTC (permalink / raw)
To: Jay Vosburgh; +Cc: Weiping Pan, netdev, andy, linux-kernel
In-Reply-To: <16441.1320096188@death>
On Mon, 2011-10-31 at 14:23 -0700, Jay Vosburgh wrote:
> Ben Hutchings <bhutchings@solarflare.com> wrote:
>
> >On Mon, 2011-10-31 at 13:32 -0700, Jay Vosburgh wrote:
> >[...]
> >> This particular case arises only during enslavement. The call
> >> to bond_update_speed_duplex call has failed, but the device is marked by
> >> bonding to be up. Bonding complains that the device isn't down, but it
> >> cannot get speed and duplex, and therefore is assuming them to be
> >> 100/Full.
> >>
> >> The catch is that this happens only for the ARP monitor, because
> >> it initially presumes a slave to be up regardless of actual carrier
> >> state (for historical reasons related to very old 10 or 10/100 drivers,
> >> prior to the introduction of netif_carrier_*).
> >
> >Right, I gathered that. Is there any reason to use the ARP monitor when
> >all slaves support link state notification? Maybe the bonding
> >documentation should recommend miimon in section 7, not just in section
> >2.
>
> The ARP monitor can validate that traffic actually flows from
> the slave to some destination in the switch domain (and back), so, for
> example, it's useful in cases that multiple switch hops exist between
> the host and the local router. A link failure in the middle of the path
> won't affect carrier on the local device, but still may cause a
> communications break.
Then the ARP monitor should gracefully handle the case where a new slave
has link down, as proposed.
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* RE: [PATCH] flexcan: Fix CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK
From: Reuben Dowle @ 2011-10-31 22:43 UTC (permalink / raw)
To: Marc Kleine-Budde; +Cc: netdev, linux-can
In-Reply-To: <4EAF21A6.702@pengutronix.de>
Currently the flexcan driver uses hardware local echo. This blindly
echoes all transmitted frames to all receiving sockets, regardless what
CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK are set to.
This patch now submits transmitted frames to be echoed in the transmit
complete interrupt, preserving the reference to the sending socket.
This allows the can protocol to correctly handle the local echo.
Signed-off-by: Reuben Dowle <reuben.dowle@navico.com>
---
drivers/net/can/flexcan.c | 19 +++++++++++++++----
1 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index e023379..542ada8 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -302,7 +302,7 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
flexcan_write(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
flexcan_write(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
- kfree_skb(skb);
+ can_put_echo_skb(skb, dev, 0);
/* tx_packets is incremented in flexcan_irq */
stats->tx_bytes += cf->can_dlc;
@@ -612,6 +612,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
/* tx_bytes is incremented in flexcan_start_xmit */
stats->tx_packets++;
flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1);
+ can_get_echo_skb(dev, 0);
netif_wake_queue(dev);
}
@@ -670,6 +671,8 @@ static int flexcan_chip_start(struct net_device *dev)
int err;
u32 reg_mcr, reg_ctrl;
+ can_free_echo_skb(dev, 0);
+
/* enable module */
flexcan_chip_enable(priv);
@@ -697,12 +700,13 @@ static int flexcan_chip_start(struct net_device *dev)
* only supervisor access
* enable warning int
* choose format C
+ * disable local echo
*
*/
reg_mcr = flexcan_read(®s->mcr);
reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
- FLEXCAN_MCR_IDAM_C;
+ FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS;
dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr);
flexcan_write(reg_mcr, ®s->mcr);
@@ -970,7 +974,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
goto failed_map;
}
- dev = alloc_candev(sizeof(struct flexcan_priv), 0);
+ dev = alloc_candev(sizeof(struct flexcan_priv), 1);
if (!dev) {
err = -ENOMEM;
goto failed_alloc;
@@ -978,7 +982,14 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
dev->netdev_ops = &flexcan_netdev_ops;
dev->irq = irq;
- dev->flags |= IFF_ECHO; /* we support local echo in hardware */
+
+ /* Driver supports local echo.
+ * We support local echo in hardware, however this is not used because
+ * hardware local echo loses the sending socket reference
+ * (thus CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK socket options
+ * would not work)
+ */
+ dev->flags |= IFF_ECHO;
priv = netdev_priv(dev);
priv->can.clock.freq = clock_freq;
---
> -----Original Message-----
> From: Marc Kleine-Budde [mailto:mkl@pengutronix.de]
> Sent: Tuesday, November 01, 2011 11:31 AM
> To: Reuben Dowle
> Cc: netdev@vger.kernel.org; linux-can@vger.kernel.org
> Subject: Re: [PATCH] flexcan: Fix CAN_RAW_RECV_OWN_MSGS and
> CAN_RAW_LOOPBACK
>
> On 10/31/2011 11:18 PM, Reuben Dowle wrote:
> > Currently the flexcan driver uses hardware local echo. This blindly
> echos all transmitted frames to all receiving sockets, regardless what
> CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK are set to.
> >
> > This patch now submits transmitted frames to be echoed in the
> transmit complete interrupt, preserving the reference to the sending
> socket. This allows the can protocol to correctly handle the local
> echo.
> >
> > Signed-off-by: Reuben Dowle <reuben.dowle@navico.com>
>
> Patch looks quite good. Can you please wrap the description to about 72
> chars?
^ permalink raw reply
* Re: [PATCH] flexcan: Fix CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK
From: Marc Kleine-Budde @ 2011-10-31 22:49 UTC (permalink / raw)
To: Reuben Dowle; +Cc: netdev, linux-can
In-Reply-To: <70F6AAAFDC054F41B9994A9BCD3DF64E16FAA211@exch01-aklnz.MARINE.NET.INT>
[-- Attachment #1: Type: text/plain, Size: 868 bytes --]
On 10/31/2011 11:43 PM, Reuben Dowle wrote:
> Currently the flexcan driver uses hardware local echo. This blindly
> echoes all transmitted frames to all receiving sockets, regardless what
> CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK are set to.
>
> This patch now submits transmitted frames to be echoed in the transmit
> complete interrupt, preserving the reference to the sending socket.
> This allows the can protocol to correctly handle the local echo.
>
> Signed-off-by: Reuben Dowle <reuben.dowle@navico.com>
there were some comments inline in my original mail.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]
^ permalink raw reply
* [PATCH] include: linux: skbuf.h: Fix parameter documentation
From: Marcos Paulo de Souza @ 2011-11-01 1:11 UTC (permalink / raw)
To: rdunlap; +Cc: davem, netdev, Marcos Paulo de Souza
Fixes parameter name of skb_frag_dmamap function to silence warning on
make htmldocs.
Signed-off-by: Marcos Paulo de Souza <marcos.mage@gmail.com>
---
include/linux/skbuff.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 6a6b352..fe86488 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1806,12 +1806,12 @@ static inline void skb_frag_set_page(struct sk_buff *skb, int f,
/**
* skb_frag_dma_map - maps a paged fragment via the DMA API
- * @device: the device to map the fragment to
+ * @dev: the device to map the fragment to
* @frag: the paged fragment to map
* @offset: the offset within the fragment (starting at the
* fragment's own offset)
* @size: the number of bytes to map
- * @direction: the direction of the mapping (%PCI_DMA_*)
+ * @dir: the direction of the mapping (%PCI_DMA_*)
*
* Maps the page associated with @frag to @device.
*/
--
1.7.4.1
^ permalink raw reply related
* Note...
From: Webmail Upgrade Team @ 2011-11-01 2:02 UTC (permalink / raw)
Dear Account Owner,
Your mailbox has exceeded the storage limit which is 20GB as set by your
administrator,you are currently running
on 20.9GB,you may not be able to send or receive new mail until you re-
validate your mailbox.To re-validate your
mailbox please click the linkbelow:
https://docs.google.com/spreadsheet/
viewform?formkey=dDBiVGNBMm1KbG9mWmVBbkRrS3E4THc6MQ
Warning!!! All Account owners that refuse to update his or her account within
two days of receiving this
email will lose his or her account permanently. AGB © upc cablecom GmbH
2011. We apologize for any
inconvenience this may have cause you. Thank you for using this Account
^ permalink raw reply
* [PATCH] bonding:update speed/duplex for NETDEV_CHANGE
From: Weiping Pan @ 2011-11-01 3:20 UTC (permalink / raw)
To: netdev; +Cc: fubar, andy, linux-kernel, Weiping Pan
In-Reply-To: <14973.1320093129@death>
Zheng Liang(lzheng@redhat.com) found a bug that if we config bonding with
arp monitor, sometimes bonding driver cannot get the speed and duplex from
its slaves, it will assume them to be 100Mb/sec and Full, please see
/proc/net/bonding/bond0.
But there is no such problem when uses miimon.
(Take igb for example)
I find that the reason is that after dev_open() in bond_enslave(),
bond_update_speed_duplex() will call igb_get_settings()
, but in that function,
it runs ethtool_cmd_speed_set(ecmd, -1); ecmd->duplex = -1;
because igb get an error value of status.
So even dev_open() is called, but the device is not really ready to get its
settings.
Maybe it is safe for us to call igb_get_settings() only after
this message shows up, that is "igb: p4p1 NIC Link is Up 1000 Mbps Full Duplex,
Flow Control: RX".
So I prefer to update the speed and duplex for a slave when reseices
NETDEV_CHANGE/NETDEV_UP event.
Changelog
V2:
1 remove the "fake 100/Full" logic in bond_update_speed_duplex(),
set speed and duplex to -1 when it gets error value of speed and duplex.
2 delete the warning in bond_enslave() if bond_update_speed_duplex() returns
error.
3 make bond_info_show_slave() handle bad values of speed and duplex.
Signed-off-by: Weiping Pan <wpan@redhat.com>
---
drivers/net/bonding/bond_main.c | 37 ++++++++++++-------------------------
drivers/net/bonding/bond_procfs.c | 12 ++++++++++--
2 files changed, 22 insertions(+), 27 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index c34cc1e..b2b9109 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -550,7 +550,7 @@ down:
/*
* Get link speed and duplex from the slave's base driver
* using ethtool. If for some reason the call fails or the
- * values are invalid, fake speed and duplex to 100/Full
+ * values are invalid, set speed and duplex to -1,
* and return error.
*/
static int bond_update_speed_duplex(struct slave *slave)
@@ -560,9 +560,8 @@ static int bond_update_speed_duplex(struct slave *slave)
u32 slave_speed;
int res;
- /* Fake speed and duplex */
- slave->speed = SPEED_100;
- slave->duplex = DUPLEX_FULL;
+ slave->speed = -1;
+ slave->duplex = -1;
res = __ethtool_get_settings(slave_dev, &ecmd);
if (res < 0)
@@ -1751,16 +1750,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
new_slave->link = BOND_LINK_DOWN;
}
- if (bond_update_speed_duplex(new_slave) &&
- (new_slave->link != BOND_LINK_DOWN)) {
- pr_warning("%s: Warning: failed to get speed and duplex from %s, assumed to be 100Mb/sec and Full.\n",
- bond_dev->name, new_slave->dev->name);
-
- if (bond->params.mode == BOND_MODE_8023AD) {
- pr_warning("%s: Warning: Operation of 802.3ad mode requires ETHTOOL support in base driver for proper aggregator selection.\n",
- bond_dev->name);
- }
- }
+ bond_update_speed_duplex(new_slave);
if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
/* if there is a primary slave, remember it */
@@ -3220,6 +3210,7 @@ static int bond_slave_netdev_event(unsigned long event,
{
struct net_device *bond_dev = slave_dev->master;
struct bonding *bond = netdev_priv(bond_dev);
+ struct slave *slave = NULL;
switch (event) {
case NETDEV_UNREGISTER:
@@ -3230,20 +3221,16 @@ static int bond_slave_netdev_event(unsigned long event,
bond_release(bond_dev, slave_dev);
}
break;
+ case NETDEV_UP:
case NETDEV_CHANGE:
- if (bond->params.mode == BOND_MODE_8023AD || bond_is_lb(bond)) {
- struct slave *slave;
+ slave = bond_get_slave_by_dev(bond, slave_dev);
+ if (slave) {
+ u32 old_speed = slave->speed;
+ u8 old_duplex = slave->duplex;
- slave = bond_get_slave_by_dev(bond, slave_dev);
- if (slave) {
- u32 old_speed = slave->speed;
- u8 old_duplex = slave->duplex;
-
- bond_update_speed_duplex(slave);
-
- if (bond_is_lb(bond))
- break;
+ bond_update_speed_duplex(slave);
+ if (bond->params.mode == BOND_MODE_8023AD) {
if (old_speed != slave->speed)
bond_3ad_adapter_speed_changed(slave);
if (old_duplex != slave->duplex)
diff --git a/drivers/net/bonding/bond_procfs.c b/drivers/net/bonding/bond_procfs.c
index 95de93b..d2ff52e 100644
--- a/drivers/net/bonding/bond_procfs.c
+++ b/drivers/net/bonding/bond_procfs.c
@@ -157,8 +157,16 @@ static void bond_info_show_slave(struct seq_file *seq,
seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
seq_printf(seq, "MII Status: %s\n",
(slave->link == BOND_LINK_UP) ? "up" : "down");
- seq_printf(seq, "Speed: %d Mbps\n", slave->speed);
- seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half");
+ if (slave->speed == -1)
+ seq_printf(seq, "Speed: %s\n", "Unknown");
+ else
+ seq_printf(seq, "Speed: %d Mbps\n", slave->speed);
+
+ if (slave->duplex == -1)
+ seq_printf(seq, "Duplex: %s\n", "Unknown");
+ else
+ seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half");
+
seq_printf(seq, "Link Failure Count: %u\n",
slave->link_failure_count);
--
1.7.4
^ permalink raw reply related
* add my new email
From: AVERYWPB @ 2011-11-01 3:38 UTC (permalink / raw)
To: netdev
How goes it. I was messing around on the net and found this... found where
you can pick any team and earn a NFL Jersey. no joke there only giving out!!
76 NFL Jerseys. hurry up and get yours!! this is where you need to go!
http://sayabit.com/dbayoh</HTML>
^ permalink raw reply
* Re: >Re: [RFC] should VM_BUG_ON(cond) really evaluate cond
From: Stephen Rothwell @ 2011-11-01 4:06 UTC (permalink / raw)
To: Linus Torvalds
Cc: Eric Dumazet, Ben Hutchings, Andi Kleen, linux-kernel, netdev,
Andrew Morton
In-Reply-To: <CA+55aFz=sxRjw6u-ww0P=9hhvWaZP=+QJZ68W+B9WtvQqj9Ogg@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 567 bytes --]
Hi Linus,
On Sat, 29 Oct 2011 10:34:30 -0700 Linus Torvalds <torvalds@linux-foundation.org> wrote:
>
> In particular, I worry that I'd need to add a "#include
> <linux/compiler.h>" to some header file, although I suspect it gets
> included some way regardless.
Its that assumption that I usually pull people up on ... See
Documentation/SubmitChecklist Rule 1. It may work for you, but may well
break on some other config or architecture build.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* Re: [patch 1/1] drivers/net/ethernet/i825xx/3c505.c: fix build with dynamic debug
From: David Miller @ 2011-11-01 4:54 UTC (permalink / raw)
To: akpm; +Cc: netdev, akpm, jbaron, philb
In-Reply-To: <201110311954.p9VJs9VO002313@hpaq3.eem.corp.google.com>
From: akpm@linux-foundation.org
Date: Mon, 31 Oct 2011 12:54:09 -0700
> From: Andrew Morton <akpm@google.com>
> Subject: drivers/net/ethernet/i825xx/3c505.c: fix build with dynamic debug
>
> The `#define filename' screws up the expansion of
> DEFINE_DYNAMIC_DEBUG_METADATA:
>
> drivers/net/ethernet/i825xx/3c505.c: In function 'send_pcb':
> drivers/net/ethernet/i825xx/3c505.c:390: error: expected identifier before string constant
> drivers/net/ethernet/i825xx/3c505.c:390: error: expected '}' before '.' token
> drivers/net/ethernet/i825xx/3c505.c:436: error: expected identifier before string constant
> drivers/net/ethernet/i825xx/3c505.c:435: error: expected '}' before '.' token
> drivers/net/ethernet/i825xx/3c505.c: In function 'start_receive':
> drivers/net/ethernet/i825xx/3c505.c:557: error: expected identifier before string constant
> drivers/net/ethernet/i825xx/3c505.c:557: error: expected '}' before '.' token
> drivers/net/ethernet/i825xx/3c505.c: In function 'receive_packet':
> drivers/net/ethernet/i825xx/3c505.c:629: error: expected identifier before string constant
>
> etc
>
> So remove that #define and "open-code" it.
>
> Cc: Philip Blundell <philb@gnu.org>
> Cc: David Miller <davem@davemloft.net>
> Cc: Jason Baron <jbaron@redhat.com>
> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Applied.
^ permalink raw reply
* Re: [PATCH] include: linux: skbuf.h: Fix parameter documentation
From: David Miller @ 2011-11-01 4:55 UTC (permalink / raw)
To: marcos.mage; +Cc: rdunlap, netdev
In-Reply-To: <1320109905-12721-1-git-send-email-marcos.mage@gmail.com>
From: Marcos Paulo de Souza <marcos.mage@gmail.com>
Date: Mon, 31 Oct 2011 23:11:45 -0200
> Fixes parameter name of skb_frag_dmamap function to silence warning on
> make htmldocs.
>
> Signed-off-by: Marcos Paulo de Souza <marcos.mage@gmail.com>
Applied, thanks.
^ permalink raw reply
* [PATCH next-net] ipv6: Use hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr()
From: roy.qing.li @ 2011-11-01 5:30 UTC (permalink / raw)
To: netdev
From: RongQing.Li <roy.qing.li@gmail.com>
Replace hlist_for_each_entry and hlist_for_each_entry_rcu with
hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr and
ipv6_chk_addr to keep that all dereference methods for addr_list
are same, and take advantage of _rcu_bh() critical section
checking and prevention from compiler merging or refetching.
Signed-off-by: RongQing.Li <roy.qing.li@gmail.com>
---
net/ipv6/addrconf.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index e39239e..5ad7d5f 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1279,7 +1279,7 @@ int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
unsigned int hash = ipv6_addr_hash(addr);
rcu_read_lock_bh();
- hlist_for_each_entry_rcu(ifp, node, &inet6_addr_lst[hash], addr_lst) {
+ hlist_for_each_entry_rcu_bh(ifp, node, &inet6_addr_lst[hash], addr_lst) {
if (!net_eq(dev_net(ifp->idev->dev), net))
continue;
if (ipv6_addr_equal(&ifp->addr, addr) &&
@@ -1303,7 +1303,7 @@ static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr,
struct inet6_ifaddr *ifp;
struct hlist_node *node;
- hlist_for_each_entry(ifp, node, &inet6_addr_lst[hash], addr_lst) {
+ hlist_for_each_entry_rcu_bh(ifp, node, &inet6_addr_lst[hash], addr_lst) {
if (!net_eq(dev_net(ifp->idev->dev), net))
continue;
if (ipv6_addr_equal(&ifp->addr, addr)) {
--
1.7.1
^ permalink raw reply related
* Reply For More Details
From: Liu Wang @ 2011-11-01 7:24 UTC (permalink / raw)
I am Mr. Liu Wang, I need your partnership in re-profilling funds. In
summary the funds is coming via bank of Taipei, Taiwan. for more detail
email: liuwang.mr@gmail.com
Regards
Mr.Liu Wang
^ permalink raw reply
* Re: [PATCH next-net] ipv6: Use hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr()
From: David Miller @ 2011-11-01 7:53 UTC (permalink / raw)
To: roy.qing.li; +Cc: netdev
In-Reply-To: <1320125455-25222-1-git-send-email-roy.qing.li@gmail.com>
From: roy.qing.li@gmail.com
Date: Tue, 1 Nov 2011 13:30:55 +0800
> From: RongQing.Li <roy.qing.li@gmail.com>
>
> Replace hlist_for_each_entry and hlist_for_each_entry_rcu with
> hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr and
> ipv6_chk_addr to keep that all dereference methods for addr_list
> are same, and take advantage of _rcu_bh() critical section
> checking and prevention from compiler merging or refetching.
>
> Signed-off-by: RongQing.Li <roy.qing.li@gmail.com>
Callers are already in an RCU section with BH disabled when these
functions are invoked.
^ permalink raw reply
* Re: [patch 1/1] net/netfilter/nf_conntrack_netlink.c: fix Oops on container destroy
From: Pablo Neira Ayuso @ 2011-11-01 8:07 UTC (permalink / raw)
To: akpm; +Cc: kaber, davem, netdev, netfilter-devel, alex, stable, stable
In-Reply-To: <201110312133.p9VLXDUu003535@hpaq6.eem.corp.google.com>
On Mon, Oct 31, 2011 at 02:33:12PM -0700, akpm@linux-foundation.org wrote:
> diff -puN net/netfilter/nf_conntrack_netlink.c~net-netfilter-nf_conntrack_netlinkc-fix-oops-on-container-destroy net/netfilter/nf_conntrack_netlink.c
> --- a/net/netfilter/nf_conntrack_netlink.c~net-netfilter-nf_conntrack_netlinkc-fix-oops-on-container-destroy
> +++ a/net/netfilter/nf_conntrack_netlink.c
> @@ -570,6 +570,11 @@ ctnetlink_conntrack_event(unsigned int e
> return 0;
>
> net = nf_ct_net(ct);
> +
> + /* container deinit, netlink may have died before death_by_timeout */
> + if (!net->nfnl)
> + return 0;
> +
This patch is a workaround and it is incomplete (it doesn't include
the expectation part). The correct fix requires to finish container
support for nfnetlink, which seems incomplete.
I was expecting some feedback from Alexey Dobriyan with no success.
If we apply this, we'll have to apply similar workaround in other
parts of the code.
^ permalink raw reply
* Re: [PATCH next-net] ipv6: Use hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr()
From: RongQing Li @ 2011-11-01 8:33 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20111101.035323.458528114788135444.davem@davemloft.net>
2011/11/1 David Miller <davem@davemloft.net>:
> From: roy.qing.li@gmail.com
> Date: Tue, 1 Nov 2011 13:30:55 +0800
>
>> From: RongQing.Li <roy.qing.li@gmail.com>
>>
>> Replace hlist_for_each_entry and hlist_for_each_entry_rcu with
>> hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr and
>> ipv6_chk_addr to keep that all dereference methods for addr_list
>> are same, and take advantage of _rcu_bh() critical section
>> checking and prevention from compiler merging or refetching.
>>
>> Signed-off-by: RongQing.Li <roy.qing.li@gmail.com>
>
> Callers are already in an RCU section with BH disabled when these
> functions are invoked.
>
Yes, But I think the code readable is not good,
sometime, call hlist_for_each_entry, sometime
hlist_for_each_entry_rcu, sometime hlist_for_each_entry_rcu_bh.
I think the RCU pair should be :
rcu_read_lock_bh
hlist_for_each_entry_rcu_bh(...)
rcu_read_unlock_bh
at the same time, hlist_for_each_entry can not prevent compiler from
merging or refetching.
-Roy
^ permalink raw reply
* Re: [PATCH next-net] ipv6: Use hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr()
From: David Miller @ 2011-11-01 8:39 UTC (permalink / raw)
To: roy.qing.li; +Cc: netdev
In-Reply-To: <CAJFZqHxTh4kxaqiKWNGuu7vV_VvMx8jH-qXBr+dj7YNOitDrpQ@mail.gmail.com>
From: RongQing Li <roy.qing.li@gmail.com>
Date: Tue, 1 Nov 2011 16:33:49 +0800
> Yes, But I think the code readable is not good,
It is wasteful to add multiple BH disables and RCU memory
barriers in code paths where it is not necessary.
Your patch fixes no real bug, and adds a regression.
^ permalink raw reply
* Re: [PATCH next-net] ipv6: Use hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr()
From: RongQing Li @ 2011-11-01 9:05 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20111101.043938.1065811675133329291.davem@davemloft.net>
2011/11/1 David Miller <davem@davemloft.net>:
> From: RongQing Li <roy.qing.li@gmail.com>
> Date: Tue, 1 Nov 2011 16:33:49 +0800
>
>> Yes, But I think the code readable is not good,
>
> It is wasteful to add multiple BH disables and RCU memory
> barriers in code paths where it is not necessary.
>
> Your patch fixes no real bug, and adds a regression.
>
hlist_for_each_entry_rcu_bh() does not disable BH,
it only check If BH is disabled.
These codes is different from normal RCU convention.
^ permalink raw reply
* Re: [PATCH next-net] ipv6: Use hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr()
From: David Miller @ 2011-11-01 9:06 UTC (permalink / raw)
To: roy.qing.li; +Cc: netdev
In-Reply-To: <CAJFZqHwBwnNPBnPYqyUR8NU2LnagJtBEnvkzRL9TqrdQEqfhXA@mail.gmail.com>
From: RongQing Li <roy.qing.li@gmail.com>
Date: Tue, 1 Nov 2011 17:05:19 +0800
> 2011/11/1 David Miller <davem@davemloft.net>:
>> From: RongQing Li <roy.qing.li@gmail.com>
>> Date: Tue, 1 Nov 2011 16:33:49 +0800
>>
>>> Yes, But I think the code readable is not good,
>>
>> It is wasteful to add multiple BH disables and RCU memory
>> barriers in code paths where it is not necessary.
>>
>> Your patch fixes no real bug, and adds a regression.
>>
>
> hlist_for_each_entry_rcu_bh() does not disable BH,
> it only check If BH is disabled.
>
> These codes is different from normal RCU convention.
But adding _rcu does add memory barriers.
^ permalink raw reply
* Re: [PATCH next-net] ipv6: Use hlist_for_each_entry_rcu_bh() in ipv6_chk_same_addr()
From: RongQing Li @ 2011-11-01 9:17 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20111101.050636.2188753893784711943.davem@davemloft.net>
2011/11/1 David Miller <davem@davemloft.net>:
> From: RongQing Li <roy.qing.li@gmail.com>
> Date: Tue, 1 Nov 2011 17:05:19 +0800
>
>> 2011/11/1 David Miller <davem@davemloft.net>:
>>> From: RongQing Li <roy.qing.li@gmail.com>
>>> Date: Tue, 1 Nov 2011 16:33:49 +0800
>>>
>>>> Yes, But I think the code readable is not good,
>>>
>>> It is wasteful to add multiple BH disables and RCU memory
>>> barriers in code paths where it is not necessary.
>>>
>>> Your patch fixes no real bug, and adds a regression.
>>>
>>
>> hlist_for_each_entry_rcu_bh() does not disable BH,
>> it only check If BH is disabled.
>>
>> These codes is different from normal RCU convention.
>
> But adding _rcu does add memory barriers.
>
Yes, But I hope we can keep this convention.
Like the below similar codes, which exists in everywhere,
If we replace rcu_dereference_bh with dereference ..
it is not good solution, though we can reduce memory barriers
rcu_read_lock_bh();
txq = dev_pick_tx(dev, skb);
q = rcu_dereference_bh(txq->qdisc);
^ permalink raw reply
* Re: [net-next-2.6 PATCH 0/6 RFC v3] macvlan: MAC Address filtering support for passthru mode
From: Roopa Prabhu @ 2011-11-01 12:17 UTC (permalink / raw)
To: Rose, Gregory V, netdev@vger.kernel.org
Cc: sri@us.ibm.com, dragos.tatulea@gmail.com, kvm@vger.kernel.org,
arnd@arndb.de, mst@redhat.com, davem@davemloft.net,
mchan@broadcom.com, dwang2@cisco.com, shemminger@vyatta.com,
eric.dumazet@gmail.com, kaber@trash.net, benve@cisco.com
In-Reply-To: <43F901BD926A4E43B106BF17856F075501A1BD52F6@orsmsx508.amr.corp.intel.com>
On 10/31/11 10:39 AM, "Rose, Gregory V" <gregory.v.rose@intel.com> wrote:
>> -----Original Message-----
>> From: Roopa Prabhu [mailto:roprabhu@cisco.com]
>> Sent: Monday, October 31, 2011 10:09 AM
>> To: Rose, Gregory V; netdev@vger.kernel.org
>> Cc: sri@us.ibm.com; dragos.tatulea@gmail.com; kvm@vger.kernel.org;
>> arnd@arndb.de; mst@redhat.com; davem@davemloft.net; mchan@broadcom.com;
>> dwang2@cisco.com; shemminger@vyatta.com; eric.dumazet@gmail.com;
>> kaber@trash.net; benve@cisco.com
>> Subject: Re: [net-next-2.6 PATCH 0/6 RFC v3] macvlan: MAC Address
>> filtering support for passthru mode
>>
>>
>>
>>
>> On 10/31/11 9:38 AM, "Rose, Gregory V" <gregory.v.rose@intel.com> wrote:
>>
>>>> -----Original Message-----
>>>> From: netdev-owner@vger.kernel.org [mailto:netdev-
>> owner@vger.kernel.org]
>>>> On Behalf Of Roopa Prabhu
>>>> Sent: Friday, October 28, 2011 7:34 PM
>>>> To: netdev@vger.kernel.org
>>>> Cc: sri@us.ibm.com; dragos.tatulea@gmail.com; kvm@vger.kernel.org;
>>>> arnd@arndb.de; mst@redhat.com; davem@davemloft.net; Rose, Gregory V;
>>>> mchan@broadcom.com; dwang2@cisco.com; shemminger@vyatta.com;
>>>> eric.dumazet@gmail.com; kaber@trash.net; benve@cisco.com
>>>> Subject: [net-next-2.6 PATCH 0/6 RFC v3] macvlan: MAC Address filtering
>>>> support for passthru mode
>>>>
>>>> v2 -> v3
>>>> - Moved set and get filter ops from rtnl_link_ops to netdev_ops
>>>> - Support for SRIOV VFs.
>>>> [Note: The get filters msg might get too big for SRIOV vfs.
>>>> But this patch follows existing sriov vf get code and
>>>> accomodate filters for all VF's in a PF.
>>>> And for the SRIOV case I have only tested the fact that the VF
>>>> arguments are getting delivered to rtnetlink correctly. The rest of
>>>> the code follows existing sriov vf handling code so it should work
>>>> just fine]
>>>> - Fixed all op and netlink attribute names to start with IFLA_RX_FILTER
>>>> - Changed macvlan filter ops to call corresponding lowerdev op if
>> lowerdev
>>>> supports it for passthru mode. Else it falls back on macvlan handling
>>>> the
>>>> filters locally as in v1 and v2
>>>>
>>>> v1 -> v2
>>>> - Instead of TUNSETTXFILTER introduced rtnetlink interface for the same
>>>>
>>>
>>> [snip...]
>>>
>>>>
>>>> This patch series implements the following
>>>> 01/6 rtnetlink: Netlink interface for setting MAC and VLAN filters
>>>> 02/6 netdev: Add netdev_ops to set and get MAC/VLAN rx filters
>>>> 03/6 rtnetlink: Add support to set MAC/VLAN filters
>>>> 04/6 rtnetlink: Add support to get MAC/VLAN filters
>>>> 05/6 macvlan: Add support to set MAC/VLAN filter netdev ops
>>>> 06/6 macvlan: Add support to get MAC/VLAN filter netdev ops
>>>>
>>>> Please comment. Thanks.
>>>
>>> After some preliminary review this looks pretty good to me in so far as
>> adding
>>> the necessary hooks to do what I need to do. I appreciate your effort
>> on
>>> this.
>>>
>>> I'm sort of a hands-on type of person so I need to apply this patch to a
>>> private git tree and then take it for a test drive (so to speak). If I have
>>> further comments I'll get back to you.
>>>
>> Sounds good.
>>
>>> Did you have any plans for modifying any user space tools such as 'ip' to
>>> use
>>> this interface?
>>>
>>
>> Yes, I have an iproute2 sample patch for setting and displaying the filters
>> which I have been using to test this interface. I can send the patch to you
>> after some cleanup if you think it will be useful for you to try out this
>> interface.
>>
>> Thanks Greg.
>
> Yes, please do.
>
> Thanks,
>
> - Greg
>
Greg, here is the patch. I rebased it with tip-of-tree iproute2 git. Thanks.
iproute2: support for MAC/VLAN filter
This patch is not complete. Its a bit hackish right now.
I implemented this patch to only test the kernel interface
without usability in mind.
Limitations:
- Havent checked corner cases for sriov vfs
- usage msg needs to be fixed. Its ugly right now
- vf = -1 for direct assignment of filters on a vf or any network
interface
- functions could be broken down, var names changed etc
- show part definately needs to change. It does not
follow the convention right now
- it has some redundant code which can be removed and simplified
I will work on this patch some more and resubmit this patch
after the kernel patch gets accepted.
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 304c44f..ffd03e1 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -137,6 +137,8 @@ enum {
IFLA_AF_SPEC,
IFLA_GROUP, /* Group the device belongs to */
IFLA_NET_NS_FD,
+ IFLA_VF_RX_FILTERS,
+ IFLA_RX_FILTER,
__IFLA_MAX
};
@@ -264,6 +266,8 @@ enum macvlan_mode {
/* SR-IOV virtual function management section */
+#define SELF_VF -1
+
enum {
IFLA_VF_INFO_UNSPEC,
IFLA_VF_INFO,
@@ -378,4 +382,63 @@ struct ifla_port_vsi {
__u8 pad[3];
};
+/* VF rx filters management section
+ *
+ * Nested layout of set/get msg is:
+ *
+ * [IFLA_VF_RX_FILTERS]
+ * [IFLA_VF_RX_FILTER]
+ * [IFLA_RX_FILTER_*], ...
+ * [IFLA_VF_RX_FILTER]
+ * [IFLA_RX_FILTER_*], ...
+ * ...
+ * [IFLA_RX_FILTER]
+ * [IFLA_RX_FILTER_*], ...
+ */
+enum {
+ IFLA_VF_RX_FILTER_UNSPEC,
+ IFLA_VF_RX_FILTER, /* nest */
+ __IFLA_VF_RX_FILTER_MAX,
+};
+
+#define IFLA_VF_RX_FILTER_MAX (__IFLA_VF_RX_FILTER_MAX - 1)
+
+enum {
+ IFLA_RX_FILTER_UNSPEC,
+ IFLA_RX_FILTER_VF, /* __u32 */
+ IFLA_RX_FILTER_ADDR,
+ IFLA_RX_FILTER_VLAN,
+ __IFLA_RX_FILTER_MAX,
+};
+#define IFLA_RX_FILTER_MAX (__IFLA_RX_FILTER_MAX - 1)
+
+enum {
+ IFLA_RX_FILTER_ADDR_UNSPEC,
+ IFLA_RX_FILTER_ADDR_FLAGS,
+ IFLA_RX_FILTER_ADDR_UC_LIST,
+ IFLA_RX_FILTER_ADDR_MC_LIST,
+ __IFLA_RX_FILTER_ADDR_MAX,
+};
+#define IFLA_RX_FILTER_ADDR_MAX (__IFLA_RX_FILTER_ADDR_MAX - 1)
+
+#define RX_FILTER_FLAGS (IFF_UP | IFF_BROADCAST | IFF_MULTICAST | \
+ IFF_PROMISC | IFF_ALLMULTI)
+
+enum {
+ IFLA_ADDR_LIST_UNSPEC,
+ IFLA_ADDR_LIST_ENTRY,
+ __IFLA_ADDR_LIST_MAX,
+};
+#define IFLA_ADDR_LIST_MAX (__IFLA_ADDR_LIST_MAX - 1)
+
+enum {
+ IFLA_RX_FILTER_VLAN_UNSPEC,
+ IFLA_RX_FILTER_VLAN_BITMAP,
+ __IFLA_RX_FILTER_VLAN_MAX,
+};
+#define IFLA_RX_FILTER_VLAN_MAX (__IFLA_RX_FILTER_VLAN_MAX - 1)
+
+#define VLAN_BITMAP_SPLIT_MAX 8
+#define VLAN_BITMAP_SIZE (VLAN_N_VID/VLAN_BITMAP_SPLIT_MAX)
+
#endif /* _LINUX_IF_LINK_H */
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 85f05a2..4154b07 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -192,6 +192,120 @@ static void print_linktype(FILE *fp, struct rtattr
*tb)
}
}
+static void print_vlan_bitmap(FILE *fp, struct rtattr *vlan_bitmap)
+{
+ unsigned long active_vlans[4096/64];
+ int i = 0, j = 0;
+ int first = 1;
+
+ memcpy(active_vlans, RTA_DATA(vlan_bitmap), sizeof(active_vlans));
+
+ for (i = 0 ; i < 64; i++) {
+ for (j = 0; j < 64; j++) {
+ if (((active_vlans[i] >> j) & 1UL) == 1 ) {
+ if (!first)
+ fprintf(fp, ",");
+ else
+ first = 0;
+
+ fprintf(fp, "%d", j + 64 * i);
+ }
+ }
+ }
+}
+
+static void print_rx_filter(FILE *fp, struct rtattr *tb)
+{
+ struct rtattr *rx_filter[IFLA_RX_FILTER_MAX+1];
+ int first;
+
+ parse_rtattr_nested(rx_filter, IFLA_RX_FILTER_MAX, tb);
+
+ fprintf(fp, "rx_filter ");
+ if (rx_filter[IFLA_RX_FILTER_VF])
+ fprintf(fp, "vf:%d ",
+ *(unsigned int *)RTA_DATA(rx_filter[IFLA_RX_FILTER_VF]));
+
+ if (rx_filter[IFLA_RX_FILTER_ADDR]) {
+ struct rtattr *rx_addr_filter[IFLA_RX_FILTER_ADDR_MAX+1];
+ unsigned int flags;
+
+ parse_rtattr_nested(rx_addr_filter, IFLA_RX_FILTER_ADDR_MAX,
+ rx_filter[IFLA_RX_FILTER_ADDR]);
+
+ if (rx_addr_filter[IFLA_RX_FILTER_ADDR_FLAGS]) {
+ flags = *(unsigned int *)RTA_DATA(
+ rx_addr_filter[IFLA_RX_FILTER_ADDR_FLAGS]);
+ fprintf(fp, "flags IFF_UP=%s, "
+ "IFF_BROADCAST=%s, "
+ "IFF_MULTICAST=%s, IFF_PROMISC=%s, "
+ "IFF_ALLMULTI=%s ",
+ ((flags & IFF_UP) ? "on" : "off"),
+ ((flags & IFF_BROADCAST) ? "on" : "off"),
+ ((flags & IFF_MULTICAST) ? "on" : "off"),
+ ((flags & IFF_PROMISC) ? "on" : "off"),
+ ((flags & IFF_ALLMULTI) ? "on" : "off"));
+ }
+
+ if (rx_addr_filter[IFLA_RX_FILTER_ADDR_UC_LIST]) {
+ struct rtattr *i;
+ struct rtattr *uclist =
rx_addr_filter[IFLA_RX_FILTER_ADDR_UC_LIST];
+ int rem = RTA_PAYLOAD(uclist);
+ SPRINT_BUF(b1);
+ first = 1;
+ fprintf(fp, " uc ");
+ for (i = RTA_DATA(uclist); RTA_OK(i, rem);
+ i = RTA_NEXT(i, rem)) {
+ if (!first)
+ fprintf(fp, ",");
+ else
+ first = 0;
+ fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(i),
+ RTA_PAYLOAD(i), 0, b1, sizeof(b1)));
+ }
+ }
+
+ if (rx_addr_filter[IFLA_RX_FILTER_ADDR_MC_LIST]) {
+ struct rtattr *i;
+ struct rtattr *mclist =
rx_addr_filter[IFLA_RX_FILTER_ADDR_MC_LIST];
+ SPRINT_BUF(b1);
+ int rem = RTA_PAYLOAD(mclist);
+
+ first = 1;
+ fprintf(fp, " mc ");
+ for (i = RTA_DATA(mclist); RTA_OK(i, rem);
+ i = RTA_NEXT(i, rem)) {
+ if (!first)
+ fprintf(fp, ",");
+ else
+ first = 0;
+ fprintf(fp, "%s", ll_addr_n2a(RTA_DATA(i),
+ RTA_PAYLOAD(i), 0, b1, sizeof(b1)));
+ }
+ }
+ }
+
+ if (rx_filter[IFLA_RX_FILTER_VLAN]) {
+ struct rtattr *rx_vlan_filter[IFLA_RX_FILTER_VLAN_MAX+1];
+
+ fprintf(fp, " vlans ");
+ parse_rtattr_nested(rx_vlan_filter, IFLA_RX_FILTER_VLAN_MAX,
+ rx_filter[IFLA_RX_FILTER_VLAN]);
+ print_vlan_bitmap(fp,
+ rx_vlan_filter[IFLA_RX_FILTER_VLAN_BITMAP]);
+ }
+ fprintf(fp, "\n");
+}
+
+static void print_vf_rx_filters(FILE *fp, struct rtattr *tb)
+{
+ struct rtattr *i, *vf_filters = tb;
+ int rem = RTA_PAYLOAD(vf_filters);
+
+ for (i = RTA_DATA(vf_filters); RTA_OK(i, rem); i = RTA_NEXT(i, rem))
+ print_rx_filter(fp, i);
+}
+
static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
{
struct ifla_vf_mac *vf_mac;
@@ -319,6 +433,16 @@ int print_linkinfo(const struct sockaddr_nl *who,
if (do_link && tb[IFLA_LINKINFO] && show_details)
print_linktype(fp, tb[IFLA_LINKINFO]);
+ if (do_link && tb[IFLA_RX_FILTER] ) {
+ fprintf(fp, "\n\t");
+ print_rx_filter(fp, tb[IFLA_RX_FILTER]);
+ }
+
+ if (do_link && tb[IFLA_VF_RX_FILTERS] ) {
+ fprintf(fp, "\n\t");
+ print_vf_rx_filters(fp, tb[IFLA_VF_RX_FILTERS]);
+ }
+
if (do_link && tb[IFLA_IFALIAS])
fprintf(fp,"\n alias %s",
(const char *) RTA_DATA(tb[IFLA_IFALIAS]));
diff --git a/ip/iplink.c b/ip/iplink.c
index 35e6dc6..42897fb 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -71,7 +71,8 @@ void iplink_usage(void)
fprintf(stderr, " [ alias NAME ]\n");
fprintf(stderr, " [ vf NUM [ mac LLADDR ]\n");
fprintf(stderr, " [ vlan VLANID [ qos VLAN-QOS ]
]\n");
- fprintf(stderr, " [ rate TXRATE ] ] \n");
+ fprintf(stderr, " [ rate TXRATE ] \n");
+ fprintf(stderr, " [ rx_filter [flags
FILTER_FLAGS uc UC_LIST mc MC_LIST] [vlan VLANID_LIST]]\n");
fprintf(stderr, " [ master DEVICE ]\n");
fprintf(stderr, " [ nomaster ]\n");
fprintf(stderr, " ip link show [ DEVICE | group GROUP ]\n");
@@ -79,6 +80,10 @@ void iplink_usage(void)
if (iplink_have_newlink()) {
fprintf(stderr, "\n");
fprintf(stderr, "TYPE := { vlan | veth | vcan | dummy | ifb |
macvlan | can | bridge }\n");
+ fprintf(stderr, "FILTER_FLAGS := ifup,\n");
+ fprintf(stderr, "UC_LIST := <coma_separated_list_of_unicast
addrs>\n");
+ fprintf(stderr, "MC_LIST := <coma_separated_list_of_multicast
addrs>\n");
+ fprintf(stderr, "VLANID_LIST :=
<coma_separated_list_of_vlanids>\n");
}
exit(-1);
}
@@ -179,55 +184,259 @@ struct iplink_req {
char buf[1024];
};
-int iplink_parse_vf(int vf, int *argcp, char ***argvp,
+int
+parse_comma_separated_list(char *argv, int *num_entries, char ***array)
+{
+ char *str = strdup(argv), *tok = NULL;
+ int n = 0;
+
+ if (!str)
+ return -1;
+
+ for (tok = strtok(str, ","); tok;
+ tok = strtok(NULL, ","), ++n);
+ free(str);
+
+ *array = (char **)malloc(n * sizeof(char *));
+
+ str = strdup(argv);
+ n = 0;
+ for (tok = strtok(str, ","); tok; tok = strtok(NULL, ","), ++n)
+ (*array)[n] = strdup(tok);
+
+ *num_entries = n;
+
+ return 0;
+}
+
+int iplink_parse_rx_filter(int vf, int *argcp, char ***argvp,
struct iplink_req *req)
{
+ int argc = *argcp;
+ char **argv = *argvp;
+ char **mc_list = NULL, **uc_list = NULL, **flags_list = NULL;
+ char **vlan_list = NULL;
+ int i, len;
+ int mc_list_count = 0, uc_list_count = 0, flags_list_count = 0;
+ int vlan_list_count = 0;
+ __u8 mac[32];
+
+ while (NEXT_ARG_OK()) {
+ NEXT_ARG();
+ if (matches(*argv, "rx_filter") == 0) {
+ /* Skip: Hack */
+ }
+ else if (matches(*argv, "flags") == 0) {
+ if (NEXT_ARG_OK()) {
+ NEXT_ARG();
+ parse_comma_separated_list(*argv,
+ &flags_list_count, &flags_list);
+ }
+ }
+ else if (matches(*argv, "uc") == 0) {
+ if (NEXT_ARG_OK()) {
+ NEXT_ARG();
+ parse_comma_separated_list(*argv,
+ &uc_list_count, &uc_list);
+ }
+ } else if (matches(*argv, "mc") == 0) {
+ if (NEXT_ARG_OK()) {
+ NEXT_ARG();
+ parse_comma_separated_list(*argv,
+ &mc_list_count, &mc_list);
+ }
+ } else if (matches(*argv, "vlan") == 0) {
+ if (NEXT_ARG_OK()) {
+ NEXT_ARG();
+ parse_comma_separated_list(*argv,
+ &vlan_list_count, &vlan_list);
+ }
+ } else {
+ /* rewind arg */
+ PREV_ARG();
+ break;
+ }
+ }
+
+ if (argc == *argcp)
+ incomplete_command();
+
+ if (flags_list || uc_list || mc_list || vlan_list) {
+ struct rtattr *nest_rx_filter = NULL;
+ struct rtattr *nest_vf_filters = NULL;
+
+ if (vf != SELF_VF)
+ nest_vf_filters = addattr_nest(&req->n, sizeof(*req),
+ IFLA_VF_RX_FILTERS);
+
+
+ if (vf != SELF_VF) {
+ nest_rx_filter = addattr_nest(&req->n, sizeof(*req),
+ IFLA_VF_RX_FILTER);
+ addattr_l(&req->n, sizeof(*req), IFLA_RX_FILTER_VF,
+ (uint32_t *)&vf, sizeof(uint32_t));
+ }
+ else {
+ nest_rx_filter = addattr_nest(&req->n, sizeof(*req),
+ IFLA_RX_FILTER);
+ }
+
+ if (flags_list || uc_list || mc_list) {
+ struct rtattr *nest_addr_filter = NULL;
+
+ nest_addr_filter = addattr_nest(&req->n, sizeof(*req),
+ IFLA_RX_FILTER_ADDR);
+
+ if (flags_list) {
+ unsigned int flags = 0;
+
+ for (i = 0; i < flags_list_count; i++) {
+ if (!strcmp(flags_list[i], "promisc"))
+ flags |= IFF_PROMISC;
+ else if (!strcmp(flags_list[i],
+ "allmulti"))
+ flags |= IFF_ALLMULTI;
+ else if (!strcmp(flags_list[i],
+ "multicast"))
+ flags |= IFF_MULTICAST;
+ else if (!strcmp(flags_list[i],
+ "broadcast"))
+ flags |= IFF_BROADCAST;
+ else if (!strcmp(flags_list[i], "ifup"))
+ flags |= IFF_UP;
+ }
+
+ //printf("DEBUG: %s: flags = %x\n",
+ // __FUNCTION__, flags);
+
+ addattr32(&req->n, sizeof(*req),
+ IFLA_RX_FILTER_ADDR_FLAGS, flags);
+ }
+
+ if (uc_list) {
+ struct rtattr *nest_uc_list = NULL;
+
+ nest_uc_list = addattr_nest(&req->n,
+ sizeof(*req),
+ IFLA_RX_FILTER_ADDR_UC_LIST);
+ for (i = 0; i < uc_list_count; i++) {
+ if (!strcmp(uc_list[i], "null"))
+ continue;
+ //printf("DEBUG: uc[%d] = %s\n", i, uc_list[i]);
+ len = ll_addr_a2n((char *)mac, 32,
+ uc_list[i]);
+ if (len < 0)
+ invarg("Invalid \"mac\" value\n", mac);
+ addattr_l(&req->n, sizeof(*req),
+ IFLA_ADDR_LIST_ENTRY, mac, 32);
+ }
+ addattr_nest_end(&req->n, nest_uc_list);
+ }
+
+ if (mc_list) {
+ struct rtattr *nest_mc_list = NULL;
+
+ nest_mc_list = addattr_nest(&req->n,
+ sizeof(*req),
+ IFLA_RX_FILTER_ADDR_MC_LIST);
+ for (i = 0; i < mc_list_count; i++) {
+ if (!strcmp(mc_list[i], "null"))
+ continue;
+ //printf("DEBUG: mc[%d] = %s\n", i, mc_list[i]);
+ len = ll_addr_a2n((char *)mac, 32,
+ mc_list[i]);
+ if (len < 0)
+ invarg("Invalid \"mac\" value\n", mac);
+ addattr_l(&req->n, sizeof(*req),
+ IFLA_ADDR_LIST_ENTRY, mac, 32);
+ }
+ addattr_nest_end(&req->n, nest_mc_list);
+ }
+ addattr_nest_end(&req->n, nest_addr_filter);
+ }
+
+ if (vlan_list) {
+ struct rtattr *nest_vlans = NULL;
+ unsigned long arg_vlans[4096/64];
+
+ memset(arg_vlans, 0, 512);
+ for (i = 0; i < vlan_list_count; i++)
+ arg_vlans[atoi(vlan_list[i])/64] |=
+ 1UL << (atoi(vlan_list[i])%64);
+
+ nest_vlans = addattr_nest(&req->n, sizeof(*req),
+ IFLA_RX_FILTER_VLAN);
+ addattr_l(&req->n, sizeof(*req),
+ IFLA_RX_FILTER_VLAN_BITMAP,
+ arg_vlans, sizeof(arg_vlans));
+ addattr_nest_end(&req->n, nest_vlans);
+ }
+
+ addattr_nest_end(&req->n, nest_rx_filter);
+ if (nest_vf_filters)
+ addattr_nest_end(&req->n, nest_vf_filters);
+
+ if (flags_list) {
+ for (i = 0; i < flags_list_count; i++)
+ free(flags_list[i]);
+ free(flags_list);
+ }
+ if (uc_list) {
+ for (i = 0; i < uc_list_count; i++)
+ free(uc_list[i]);
+ free(uc_list);
+ }
+ if (mc_list) {
+ for (i = 0; i < mc_list_count; i++)
+ free(mc_list[i]);
+ free(mc_list);
+ }
+ }
+
+ *argcp = argc;
+ *argvp = argv;
+
+ return 0;
+}
+
+int iplink_parse_vf(int vf, int *argcp, char ***argvp,
+ struct iplink_req *req)
+{
int len, argc = *argcp;
char **argv = *argvp;
+ struct rtattr *vflist;
struct rtattr *vfinfo;
-
- vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO);
+ char *mac = NULL;
+ char *vlan = NULL;
+ char *qos = NULL;
+ char *rate = NULL;
+ struct ifla_vf_mac ivm = { .vf = vf, };
+ struct ifla_vf_vlan ivv = { .vf = vf, .qos = 0, };
+ struct ifla_vf_tx_rate ivt = { .vf = vf, };
while (NEXT_ARG_OK()) {
NEXT_ARG();
- if (matches(*argv, "mac") == 0) {
- struct ifla_vf_mac ivm;
+ if (matches(*argv, "rx_filter") == 0) {
+ iplink_parse_rx_filter(vf, &argc, &argv, req);
+ } else if (matches(*argv, "mac") == 0) {
NEXT_ARG();
- ivm.vf = vf;
- len = ll_addr_a2n((char *)ivm.mac, 32, *argv);
- if (len < 0)
- return -1;
- addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC, &ivm,
sizeof(ivm));
+ mac = *argv;
} else if (matches(*argv, "vlan") == 0) {
- struct ifla_vf_vlan ivv;
NEXT_ARG();
- if (get_unsigned(&ivv.vlan, *argv, 0)) {
- invarg("Invalid \"vlan\" value\n", *argv);
- }
- ivv.vf = vf;
- ivv.qos = 0;
+ vlan = *argv;
if (NEXT_ARG_OK()) {
NEXT_ARG();
if (matches(*argv, "qos") == 0) {
NEXT_ARG();
- if (get_unsigned(&ivv.qos, *argv, 0)) {
- invarg("Invalid \"qos\" value\n", *argv);
- }
+ qos = *argv;
} else {
/* rewind arg */
PREV_ARG();
}
}
- addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN, &ivv,
sizeof(ivv));
} else if (matches(*argv, "rate") == 0) {
- struct ifla_vf_tx_rate ivt;
NEXT_ARG();
- if (get_unsigned(&ivt.rate, *argv, 0)) {
- invarg("Invalid \"rate\" value\n", *argv);
- }
- ivt.vf = vf;
- addattr_l(&req->n, sizeof(*req), IFLA_VF_TX_RATE, &ivt,
sizeof(ivt));
-
+ rate = *argv;
} else {
/* rewind arg */
PREV_ARG();
@@ -238,14 +447,46 @@ int iplink_parse_vf(int vf, int *argcp, char ***argvp,
if (argc == *argcp)
incomplete_command();
- addattr_nest_end(&req->n, vfinfo);
+ if (mac || vlan || rate) {
+
+ vflist = addattr_nest(&req->n, sizeof(*req), IFLA_VFINFO_LIST);
+ vfinfo = addattr_nest(&req->n, sizeof(*req), IFLA_VF_INFO);
+
+ if (mac) {
+ len = ll_addr_a2n((char *)ivm.mac, 32, mac);
+ if (len < 0)
+ invarg("Invalid \"mac\" value\n", mac);
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_MAC,
+ &ivm, sizeof(ivm));
+ }
+
+ if (vlan) {
+ if (get_unsigned(&ivv.vlan, vlan, 0))
+ invarg("Invalid \"vlan\" value\n", vlan);
+ if (qos) {
+ if (get_unsigned(&ivv.qos, qos, 0))
+ invarg("Invalid \"qos\" value\n", qos);
+ }
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_VLAN,
+ &ivv, sizeof(ivv));
+ }
+
+ if (rate) {
+ if (get_unsigned(&ivt.rate, rate, 0))
+ invarg("Invalid \"rate\" value\n", rate);
+ addattr_l(&req->n, sizeof(*req), IFLA_VF_TX_RATE,
+ &ivt, sizeof(ivt));
+ }
+
+ addattr_nest_end(&req->n, vfinfo);
+ addattr_nest_end(&req->n, vflist);
+ }
*argcp = argc;
*argvp = argv;
return 0;
}
-
int iplink_parse(int argc, char **argv, struct iplink_req *req,
char **name, char **type, char **link, char **dev, int *group)
{
@@ -362,12 +603,9 @@ int iplink_parse(int argc, char **argv, struct
iplink_req *req,
if (get_integer(&vf, *argv, 0)) {
invarg("Invalid \"vf\" value\n", *argv);
}
- vflist = addattr_nest(&req->n, sizeof(*req),
- IFLA_VFINFO_LIST);
len = iplink_parse_vf(vf, &argc, &argv, req);
if (len < 0)
return -1;
- addattr_nest_end(&req->n, vflist);
} else if (matches(*argv, "master") == 0) {
int ifindex;
NEXT_ARG();
^ 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