* [PATCH] net_sched: gred: Fix oops in gred_dump() in WRED mode
From: David Ward @ 2012-04-15 22:31 UTC (permalink / raw)
To: netdev; +Cc: David Ward
A parameter set exists for WRED mode, called wred_set, to hold the same
values for qavg and qidlestart across all VQs. The WRED mode values had
been previously held in the VQ for the default DP. After these values
were moved to wred_set, the VQ for the default DP was no longer created
automatically (so that it could be omitted on purpose, to have packets
in the default DP enqueued directly to the device without using RED).
However, gred_dump() was overlooked during that change; in WRED mode it
still reads qavg/qidlestart from the VQ for the default DP, which might
not even exist. As a result, this command sequence will cause an oops:
tc qdisc add dev $DEV handle $HANDLE parent $PARENT gred setup \
DPs 3 default 2 grio
tc qdisc change dev $DEV handle $HANDLE gred DP 0 prio 8 $RED_OPTIONS
tc qdisc change dev $DEV handle $HANDLE gred DP 1 prio 8 $RED_OPTIONS
This fixes gred_dump() in WRED mode to use the values held in wred_set.
Signed-off-by: David Ward <david.ward@ll.mit.edu>
---
net/sched/sch_gred.c | 7 ++-----
1 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index 55e3310..ab620bf 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -567,11 +567,8 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
opt.packets = q->packetsin;
opt.bytesin = q->bytesin;
- if (gred_wred_mode(table)) {
- q->vars.qidlestart =
- table->tab[table->def]->vars.qidlestart;
- q->vars.qavg = table->tab[table->def]->vars.qavg;
- }
+ if (gred_wred_mode(table))
+ gred_load_wred_set(table, q);
opt.qave = red_calc_qavg(&q->parms, &q->vars, q->vars.qavg);
--
1.7.1
^ permalink raw reply related
* [PATCH] net_sched: red: Make minor corrections to comments
From: David Ward @ 2012-04-15 22:31 UTC (permalink / raw)
To: netdev; +Cc: David Ward
In-Reply-To: <1334529106-5035-1-git-send-email-david.ward@ll.mit.edu>
Signed-off-by: David Ward <david.ward@ll.mit.edu>
---
include/net/red.h | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/include/net/red.h b/include/net/red.h
index 77d4c37..c0bc25e 100644
--- a/include/net/red.h
+++ b/include/net/red.h
@@ -28,7 +28,7 @@
the inertia of the algorithm. To allow larger bursts, W should be
decreased.
- if (avg > th_max) -> packet marked (dropped).
+ if (avg > th_max) -> packet marked (dropped) with probability max_P.
if (avg < th_min) -> packet passes.
if (th_min < avg < th_max) we calculate probability:
@@ -245,7 +245,7 @@ static inline unsigned long red_calc_qavg_from_idle_time(const struct red_parms
*
* dummy packets as a burst after idle time, i.e.
*
- * p->qavg *= (1-W)^m
+ * v->qavg *= (1-W)^m
*
* This is an apparently overcomplicated solution (f.e. we have to
* precompute a table to make this calculation in reasonable time)
@@ -279,7 +279,7 @@ static inline unsigned long red_calc_qavg_no_idle_time(const struct red_parms *p
unsigned int backlog)
{
/*
- * NOTE: p->qavg is fixed point number with point at Wlog.
+ * NOTE: v->qavg is fixed point number with point at Wlog.
* The formula below is equvalent to floating point
* version:
*
@@ -390,7 +390,7 @@ static inline void red_adaptative_algo(struct red_parms *p, struct red_vars *v)
if (red_is_idling(v))
qavg = red_calc_qavg_from_idle_time(p, v);
- /* p->qavg is fixed point number with point at Wlog */
+ /* v->qavg is fixed point number with point at Wlog */
qavg >>= p->Wlog;
if (qavg > p->target_max && p->max_P <= MAX_P_MAX)
--
1.7.1
^ permalink raw reply related
* [PATCH] net: usb: smsc75xx: fix mtu
From: Stephane Fillod @ 2012-04-15 21:38 UTC (permalink / raw)
To: netdev; +Cc: steve.glendinning
Make smsc75xx recalculate the hard_mtu after adjusting the
hard_header_len.
Without this, usbnet adjusts the MTU down to 1492 bytes, and the host is
unable to receive standard 1500-byte frames from the device.
Inspired by same fix on cdc_eem 78fb72f7936c01d5b426c03a691eca082b03f2b9.
Tested on ARM/Omap3 with EVB-LAN7500-LC.
Signed-off-by: Stephane Fillod <fillods@users.sf.net>
---
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1049,6 +1049,7 @@
dev->net->ethtool_ops = &smsc75xx_ethtool_ops;
dev->net->flags |= IFF_MULTICAST;
dev->net->hard_header_len += SMSC75XX_TX_OVERHEAD;
+ dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
return 0;
}
^ permalink raw reply
* Re: Patch for man unix(7)
From: Michael Kerrisk (man-pages) @ 2012-04-15 21:42 UTC (permalink / raw)
To: Tetsuo Handa
Cc: linux-man-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
Michael Kerrisk
In-Reply-To: <201011232159.DFE78143.tSHMFQOLFVFJOO-JPay3/Yim36HaxMnTkn67Xf5DAMn2ifp@public.gmane.org>
Hello Tetsuao Handa
[Thanks for the text program that you sent more recently]
On Wed, Nov 24, 2010 at 1:59 AM, Tetsuo Handa
<penguin-kernel-1yMVhJb1mP/7nzcFbJAaVXf5DAMn2ifp@public.gmane.org> wrote:
> From f388eedbdc0b099bb9f36ab007f9370432abb300 Mon Sep 17 00:00:00 2001
> From: Tetsuo Handa <penguin-kernel-JPay3/Yim36HaxMnTkn67Xf5DAMn2ifp@public.gmane.org>
> Date: Tue, 23 Nov 2010 21:34:25 +0900
> Subject: [PATCH] unix.7: Fix description of "pathname" sockets
>
> Since unix_mkname() in net/unix/af_unix.c does
>
> ((char *)sunaddr)[len] = 0;
>
> rather than
>
> ((char *)sunaddr)[len - 1] = 0;
>
> , sunaddr->sun_path may not be terminated with a null byte if
> len == sizeof(*sunaddr).
>
> Therefore, the caller of getsockname(), getpeername(), accept() must not assume
> that sunaddr->sun_path contains a null-terminated pathname even if the returned
> addrlen is greater than sizeof(sa_family_t) and sun_path[0] != '\0'.
Thanks. I see what you mean. However, I'm wondering, is the kernel
behavior simply a bug that should be fixed, so that a null terminator
is always placed in sun_path?
I realize that's an ABI change, but:
a) I suspect most sane applications would never create a sun_path that
didn't contain a null terminator within sizeof(sun_path) bytes.
b) Considering these two sets:
1. [applications that would break if the assumption that there
is no null terminator inside sizeof(sun_path) bytes doesn't
hold true]
2. [applications that would break if the kernel behavior changed]
I suspect that set 1 is much larger than set 2.
Your thoughts?
Thanks,
Michael
> Signed-off-by: Tetsuo Handa <penguin-kernel-JPay3/Yim36HaxMnTkn67Xf5DAMn2ifp@public.gmane.org>
> ---
> man7/unix.7 | 19 ++++++++++++++++---
> 1 files changed, 16 insertions(+), 3 deletions(-)
>
> diff --git a/man7/unix.7 b/man7/unix.7
> index b53328b..7b0b47c 100644
> --- a/man7/unix.7
> +++ b/man7/unix.7
> @@ -80,10 +80,23 @@ When the address of the socket is returned by
> and
> .BR accept (2),
> its length is
> -.IR "offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1" ,
> +.IR "offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1".
> +Note that this length can be one byte larger than
> +.IR "sizeof(struct sockaddr_un)"
> +because
> +.BR bind (2)
> +accepts
> +.IR sun_path
> +which is not terminated with a null byte ('\\0').
> +Therefore, you must not use string manipulation functions (e.g. strlen(),
> +printf("%s")) against
> +.IR sun_path
> +because
> +.BR getsockname (2),
> +.BR getpeername (2),
> and
> -.I sun_path
> -contains the null-terminated pathname.
> +.BR accept (2)
> +may not have stored a null-terminated string.
> .IP *
> .IR unnamed :
> A stream socket that has not been bound to a pathname using
> --
> 1.6.1
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Author of "The Linux Programming Interface"; http://man7.org/tlpi/
--
To unsubscribe from this list: send the line "unsubscribe linux-man" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: Documenting UNIX domain autobind
From: Michael Kerrisk (man-pages) @ 2012-04-15 21:07 UTC (permalink / raw)
To: Tetsuo Handa; +Cc: netdev, mzxreary
In-Reply-To: <201010171428.DDC17187.FFFJSLtOOHOMQV@I-love.SAKURA.ne.jp>
Hello Tetsuo Handa,
On Sun, Oct 17, 2010 at 6:28 PM, Tetsuo Handa
<penguin-kernel@i-love.sakura.ne.jp> wrote:
> Michael Kerrisk wrote:
>> I think this text correctly documents the technical details (but let
>> me know if you see errors). What is lacking is an explanation of why
>> this feature exists. Is someone able to explain where this feature is
>> used and why?
>
> What we can see is that unix_autobind() was added in Linux 2.1.15
>
> http://lxr.linux.no/linux-old+v2.1.15/net/unix/af_unix.c#L464
> addr->len = sprintf(addr->name->sun_path+1, "%08x", ordernum) + 1 + sizeof(short);
>
> 49 * Differences from 2.0.0-11-... (ANK)
> 50 * Bug fixes and improvements.
> 51 * - client shutdown killed server socket.
> 52 * - removed all useless cli/sti pairs.
> 53 * - (suspicious!) not allow connect/send to connected not to us
> 54 * socket, return EPERM.
> 55 *
> 56 * Semantic changes/extensions.
> 57 * - generic control message passing.
> 58 * - SCM_CREDENTIALS control message.
> 59 * - "Abstract" (not FS based) socket bindings.
> 60 * Abstract names are sequences of bytes (not zero terminated)
> 61 * started by 0, so that this name space does not intersect
> 62 * with BSD names.
>
> and was changed to allow from 2^32 names to 2^20 names in Linux 2.3.15.
>
> http://lxr.linux.no/linux-old+v2.3.15/net/unix/af_unix.c#L514
> addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short);
>
> I don't know the reason.
Long after the fact, I added text to unix(7) to note the change in the
size of the namespace you noted above.
However, the unix(7) man page still lacks an explanation of the
purpose of the autobind feature. Can anyone help?
Thanks,
Michael
--
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Author of "The Linux Programming Interface"; http://man7.org/tlpi/
^ permalink raw reply
* Re: [PATCH net-next] tcp: RFC6298 supersedes RFC2988bis
From: Eric Dumazet @ 2012-04-15 20:01 UTC (permalink / raw)
To: Jerry Chu; +Cc: David Miller, netdev, Tom Herbert
In-Reply-To: <CAPshTCiew0w4kF2yE=Bn_E702vxdFwZipnnEpsAuhSm6OO187Q@mail.gmail.com>
On Sun, 2012-04-15 at 11:33 -0700, Jerry Chu wrote:
> [send again - it looks like my previous comment was lost...]
>
> On Thu, Apr 12, 2012 at 10:48 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> > Updates some comments to track RFC6298
> >
> > Signed-off-by: Eric Dumazet <edumazet@google.com>
> > Cc: H.K. Jerry Chu <hkchu@google.com>
> > Cc: Tom Herbert <therbert@google.com>
> > ---
> > BTW, one side effect of the TCP_TIMEOUT_INIT change (3 -> 1) is
> > () latency is 200% worse:
>
> Or even worse - 300% (3/1)?
well, 3 instead of 1 is a 200% increase ;)
>
> >
> > It fires every 200ms and scans 40% of hash table each time, listener
> > socket held.
>
> If this becomes a real issue we could decrease TCP_SYNQ_INTERVAL,
> essentially making the keepalive timer fire more often, but each time with
> less work to do?
Hmm... 200ms is already aggressive for power saving
>
> Also why is
> budget = 2 * (lopt->nr_table_entries / (timeout / interval));
> rather than
> budget = (lopt->nr_table_entries / (timeout / interval)) + 1;
> ?
Thats because if we do that, retransmits could be delayed by 100%,
instead of 50% with this solution.
(right now it takes 2.5 rounds to scan whole table, so a one sec 'timer'
can be fired after 1.6 second)
^ permalink raw reply
* Re: [PATCH net-next] tcp: RFC6298 supersedes RFC2988bis
From: Jerry Chu @ 2012-04-15 18:33 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev, Tom Herbert
In-Reply-To: <1334296120.5300.8404.camel@edumazet-glaptop>
[send again - it looks like my previous comment was lost...]
On Thu, Apr 12, 2012 at 10:48 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> Updates some comments to track RFC6298
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: H.K. Jerry Chu <hkchu@google.com>
> Cc: Tom Herbert <therbert@google.com>
> ---
> BTW, one side effect of the TCP_TIMEOUT_INIT change (3 -> 1) is
> () latency is 200% worse:
Or even worse - 300% (3/1)?
>
> It fires every 200ms and scans 40% of hash table each time, listener
> socket held.
If this becomes a real issue we could decrease TCP_SYNQ_INTERVAL,
essentially making the keepalive timer fire more often, but each time with
less work to do?
Also why is
budget = 2 * (lopt->nr_table_entries / (timeout / interval));
rather than
budget = (lopt->nr_table_entries / (timeout / interval)) + 1;
?
Acked-by: Jerry Chu <hkchu@google.com>
>
> include/net/tcp.h | 2 +-
> net/ipv4/inet_connection_sock.c | 2 +-
> net/ipv4/tcp_input.c | 4 ++--
> 3 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/include/net/tcp.h b/include/net/tcp.h
> index f75a04d..057f016 100644
> --- a/include/net/tcp.h
> +++ b/include/net/tcp.h
> @@ -123,7 +123,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
> #endif
> #define TCP_RTO_MAX ((unsigned)(120*HZ))
> #define TCP_RTO_MIN ((unsigned)(HZ/5))
> -#define TCP_TIMEOUT_INIT ((unsigned)(1*HZ)) /* RFC2988bis initial RTO value */
> +#define TCP_TIMEOUT_INIT ((unsigned)(1*HZ)) /* RFC6298 2.1 initial RTO value */
> #define TCP_TIMEOUT_FALLBACK ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value, now
> * used as a fallback RTO for the
> * initial data transmission if no
> diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
> index 19d66ce..c12396f 100644
> --- a/net/ipv4/inet_connection_sock.c
> +++ b/net/ipv4/inet_connection_sock.c
> @@ -514,7 +514,7 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
>
> /* Normally all the openreqs are young and become mature
> * (i.e. converted to established socket) for first timeout.
> - * If synack was not acknowledged for 3 seconds, it means
> + * If synack was not acknowledged for 1 second, it means
> * one of the following things: synack was lost, ack was lost,
> * rtt is high or nobody planned to ack (i.e. synflood).
> * When server is a bit loaded, queue is populated with old
> diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
> index e886e2f..9147c27 100644
> --- a/net/ipv4/tcp_input.c
> +++ b/net/ipv4/tcp_input.c
> @@ -933,7 +933,7 @@ static void tcp_init_metrics(struct sock *sk)
> tcp_set_rto(sk);
> reset:
> if (tp->srtt == 0) {
> - /* RFC2988bis: We've failed to get a valid RTT sample from
> + /* RFC6298: 5.7 We've failed to get a valid RTT sample from
> * 3WHS. This is most likely due to retransmission,
> * including spurious one. Reset the RTO back to 3secs
> * from the more aggressive 1sec to avoid more spurious
> @@ -943,7 +943,7 @@ reset:
> inet_csk(sk)->icsk_rto = TCP_TIMEOUT_FALLBACK;
> }
> /* Cut cwnd down to 1 per RFC5681 if SYN or SYN-ACK has been
> - * retransmitted. In light of RFC2988bis' more aggressive 1sec
> + * retransmitted. In light of RFC6298 more aggressive 1sec
> * initRTO, we only reset cwnd when more than 1 SYN/SYN-ACK
> * retransmission has occurred.
> */
>
>
^ permalink raw reply
* Re: [PATCH v2] bonding: start slaves with link down for ARP monitor
From: Flavio Leitner @ 2012-04-15 18:07 UTC (permalink / raw)
To: Jay Vosburgh; +Cc: Michal Kubecek, netdev, Andy Gospodarek
In-Reply-To: <19180.1334465333@death.nxdomain>
On Sat, 14 Apr 2012 21:48:53 -0700
Jay Vosburgh <fubar@us.ibm.com> wrote:
> Flavio Leitner <fbl@redhat.com> wrote:
>
> >On Sat, 14 Apr 2012 22:16:16 +0200
> >Michal Kubecek <mkubecek@suse.cz> wrote:
> >
> >> Initialize slave device link state as down if ARP monitor is
> >> active and net_carrier_ok() returns zero. Also shift initial
> >> value of its last_arp_tx so that it doesn't immediately cause
> >> fake detection of "up" state.
> >>
> >> When ARP monitoring is used, initializing the slave device with
> >> up link state can cause ARP monitor to detect link failure
> >> before the device is really up (with igb driver, this can take
> >> more than two seconds).
> >>
> >> Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
> >> ---
> >> drivers/net/bonding/bond_main.c | 34 +++++++++++++++++++++-------------
> >> 1 files changed, 21 insertions(+), 13 deletions(-)
> >>
> >> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
> >> index 62d2409..6a79ee3 100644
> >> --- a/drivers/net/bonding/bond_main.c
> >> +++ b/drivers/net/bonding/bond_main.c
> >> @@ -1726,7 +1726,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
> >>
> >> read_lock(&bond->lock);
> >>
> >> - new_slave->last_arp_rx = jiffies;
> >> + new_slave->last_arp_rx = jiffies -
> >> + (msecs_to_jiffies(bond->params.arp_interval) + 1);
> >>
> >> if (bond->params.miimon && !bond->params.use_carrier) {
> >> link_reporting = bond_check_dev_link(bond, slave_dev, 1);
> >> @@ -1751,21 +1752,28 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
> >> }
> >>
> >> /* check for initial state */
> >> - if (!bond->params.miimon ||
> >> - (bond_check_dev_link(bond, slave_dev, 0) == BMSR_LSTATUS)) {
> >> - if (bond->params.updelay) {
> >> - pr_debug("Initial state of slave_dev is BOND_LINK_BACK\n");
> >> - new_slave->link = BOND_LINK_BACK;
> >> - new_slave->delay = bond->params.updelay;
> >> + if (bond->params.miimon) {
> >> + if (bond_check_dev_link(bond, slave_dev, 0) == BMSR_LSTATUS) {
> >> + if (bond->params.updelay) {
> >> + new_slave->link = BOND_LINK_BACK;
> >> + new_slave->delay = bond->params.updelay;
> >> + } else {
> >> + new_slave->link = BOND_LINK_UP;
> >> + }
> >> } else {
> >> - pr_debug("Initial state of slave_dev is BOND_LINK_UP\n");
> >> - new_slave->link = BOND_LINK_UP;
> >> + new_slave->link = BOND_LINK_DOWN;
> >> }
> >> + } else if (bond->params.arp_interval) {
> >> + new_slave->link = (netif_carrier_ok(slave_dev) ?
> >> + BOND_LINK_UP : BOND_LINK_DOWN);
> >
> >The interface would have to negotiate the link and report back
> >very very fast because the dev_open(slave) was just called and
> >most drivers initialize the state as DOWN and then wait either
> >for an interrupt or a watchdog to update the link status.
> >
> >Therefore, the practical final result for most cards (if not all)
> >is new_slave->link = BOND_LINK_DOWN and forced to wait for an
> >ARP monitor cycle before going link up according to ARP monitor.
>
> My recollection is that the code was written this way
> specifically because cards could autoneg before the next ARP went out,
> and starting from "up" was the proper choice for the majority of devices
> at the time. Granted, that was back in the 10/100 days, prior to
> netif_carrier_*, so directly checking carrier was not particularly
> straightforward. A dim memory says that some cards with WoL would
> assert carrier up almost instantly because carrier was already
> negotiated prior to dev_open being called.
>
> But, yes, the practical result is that most 1G or better cards
> will likely hit this with carrier still down.
>
> >This will change the current behavior which is faster and good
> >enough for most cases. What about a new option to decide that?
> >For instance, arp_init_slave=UP/DOWN/MII with default to UP.
>
> By "current behavior" do you mean the current checked in code
> (start at up, flap if autoneg is slow relative to arp_interval), or the
> current (well, prior version) patch (start at down)?
>
current checked in code.
> I'm not in favor of an option for minutiae of this degree.
>
> I'm not really seeing a down side to going with what the carrier
> state is, either, even if most devices are too slow to hit the window.
>
> If the device doesn't do netif_carrier, then this would not be a
> change in behavior. If the device has wicked fast autoneg, then more
> power to 'em (and they probably need it, since it's likely at 10 or 100
> Mb/sec). If the device has the currently typical 2-ish second autoneg,
> then the bounce stuff goes away.
>
> Anybody got a 10 or 100 card laying around with fast autoneg to
> try? Back in the day I used 3c59x and e100s, and I seem to recall that
> the 3c59x board I had was pretty speedy at going carrier up.
>
> >Jay? Andy? :)
>
> I think the bottom line here for the majority of users is that,
> really, this is about removing some log spew at boot time, and perhaps
> not irritating some functionality that start hitting the device as soon
> as it claims to be carrier up (DHCP, maybe?). Starting from an assumed
> state of UP or DOWN isn't going to change the actual time the slave
> becomes available, but starting from UP can cause bonding today to
> assert carrier up for the master before it's actually able to transmit
> anything, which may have side effects.
>
My concern was that after the patch most users will have to wait
the link negotiation plus the ARP monitor validation while before
the patch just the link negotiation was enough.
Anyways, I think the patch is correct and I was worried with the
possible consequences while booting the system and etc...
thanks,
fbl
^ permalink raw reply
* Re: [PATCH 0/9] atl1: add napi to Atheros L1 NIC
From: David Miller @ 2012-04-15 17:28 UTC (permalink / raw)
To: antonz; +Cc: netdev, jcliburn, csnook, khorenko
In-Reply-To: <20120415.130346.1822341707659142562.davem@davemloft.net>
From: David Miller <davem@davemloft.net>
Date: Sun, 15 Apr 2012 13:03:46 -0400 (EDT)
> From: Tony Zelenoff <antonz@parallels.com>
> Date: Fri, 13 Apr 2012 20:09:45 +0400
>
>> Added NAPI interface to the driver of Atheros L1 NIC.
>> RX speed reported by iperf in TCP mode (with and without -N
>> switch) improved by ~7 Mbps. In UDP mode the speed up is
>> improved by ~4 Mbps.
>> Also hard RX/TX rings processing with memory allocation in
>> interrupt handlers is not very good idea. So, fixed this.
>>
>> Note: thouse patches must be applied after patch, that fix
>> kernel panic in this driver.
>> Its subject is: "atl1: fix kernel panic in case of DMA errors"
>
> Unfortunately this is bullshit. These patches actually depend upon
> that bug fix not being applied. Look at the patches, they reference
> and use the reset workqueue the bug fix removed.
My bad, I thought I had merged the net tree into net-next before
processing your patches but I didn't.
I just fixed this all up in the net-next tree, please double
check my work.
Thank you.
^ permalink raw reply
* Re: [net-next PATCH v4 0/8] Managing the forwarding database(FDB)
From: David Miller @ 2012-04-15 17:06 UTC (permalink / raw)
To: john.r.fastabend
Cc: shemminger, mst, bhutchings, sri, hadi, jeffrey.t.kirsher, netdev,
gregory.v.rose, krkumar2
In-Reply-To: <20120415163905.14091.30491.stgit@jf-dev1-dcblab>
From: John Fastabend <john.r.fastabend@intel.com>
Date: Sun, 15 Apr 2012 09:43:51 -0700
> The following series is a submission for net-next to allow
> embedded switches and other stacked devices other then the
> Linux bridge to manage a forwarding database.
>
> Previously discussed here,
>
> http://lists.openwall.net/netdev/2012/03/19/26
>
> v4: propagate return codes correctly for ndo_dflt_Fdb_dump()
>
> v3: resolve the macvlan patch 8/8 to fix a dev_set_promiscuity()
> error and add the flags field to change and get link routines.
>
> v2: addressed feedback from Ben Hutchings resolving a typo in the
> multicast add/del routines and improving the error handling
> when both NTF_SELF and NTF_MASTER are set.
>
> I've tested this with 'br' tool published by Stephen Hemminger
> soon to be renamed 'bridge' I believe and various traffic
> generators mostly pktgen, ping, and netperf.
All applied, if we need any more tweaks we can just add them
on top of this work.
Thanks John.
^ permalink raw reply
* Re: [PATCH 0/9] atl1: add napi to Atheros L1 NIC
From: David Miller @ 2012-04-15 17:03 UTC (permalink / raw)
To: antonz; +Cc: netdev, jcliburn, csnook, khorenko
In-Reply-To: <1334333394-38404-1-git-send-email-antonz@parallels.com>
From: Tony Zelenoff <antonz@parallels.com>
Date: Fri, 13 Apr 2012 20:09:45 +0400
> Added NAPI interface to the driver of Atheros L1 NIC.
> RX speed reported by iperf in TCP mode (with and without -N
> switch) improved by ~7 Mbps. In UDP mode the speed up is
> improved by ~4 Mbps.
> Also hard RX/TX rings processing with memory allocation in
> interrupt handlers is not very good idea. So, fixed this.
>
> Note: thouse patches must be applied after patch, that fix
> kernel panic in this driver.
> Its subject is: "atl1: fix kernel panic in case of DMA errors"
Unfortunately this is bullshit. These patches actually depend upon
that bug fix not being applied. Look at the patches, they reference
and use the reset workqueue the bug fix removed.
Anyways, I sorted through all of these merge hassles, and fixed up the
off-by-one bug Ben spotted in patch #2 because I was tired of waiting
and didn't want these patches to just keep rotting in patchwork.
^ permalink raw reply
* [net-next PATCH v4 8/8] macvlan: add FDB bridge ops and macvlan flags
From: John Fastabend @ 2012-04-15 16:44 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings
Cc: sri, hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120415163905.14091.30491.stgit@jf-dev1-dcblab>
This adds FDB bridge ops to the macvlan device passthru mode.
Additionally a flags field was added and a NOPROMISC bit to
allow users to use passthru mode without the driver calling
dev_set_promiscuity(). The flags field is a u16 placed in a
4 byte hole (consuming 2 bytes) of the macvlan_dev struct.
We want to do this so that the macvlan driver or stack
above the macvlan driver does not have to process every
packet. For the use case where we know all the MAC addresses
of the endstations above us this works well.
This patch is a result of Roopa Prabhu's work. Follow up
patches are needed for VEPA and VEB macvlan modes.
v2: Change from distinct nopromisc mode to a flags field to
configure this. This avoids the tendency to add a new
mode every time we need some slightly different behavior.
v3: fix error in dev_set_promiscuity and add change and get
link attributes for flags.
CC: Roopa Prabhu <roprabhu@cisco.com>
CC: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
drivers/net/macvlan.c | 73 ++++++++++++++++++++++++++++++++++++++++----
include/linux/if_link.h | 3 ++
include/linux/if_macvlan.h | 1 +
3 files changed, 71 insertions(+), 6 deletions(-)
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index b17fc90..9653ed6 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -312,7 +312,8 @@ static int macvlan_open(struct net_device *dev)
int err;
if (vlan->port->passthru) {
- dev_set_promiscuity(lowerdev, 1);
+ if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
+ dev_set_promiscuity(lowerdev, 1);
goto hash_add;
}
@@ -344,12 +345,15 @@ static int macvlan_stop(struct net_device *dev)
struct macvlan_dev *vlan = netdev_priv(dev);
struct net_device *lowerdev = vlan->lowerdev;
+ dev_uc_unsync(lowerdev, dev);
+ dev_mc_unsync(lowerdev, dev);
+
if (vlan->port->passthru) {
- dev_set_promiscuity(lowerdev, -1);
+ if (!(vlan->flags & MACVLAN_FLAG_NOPROMISC))
+ dev_set_promiscuity(lowerdev, -1);
goto hash_del;
}
- dev_mc_unsync(lowerdev, dev);
if (dev->flags & IFF_ALLMULTI)
dev_set_allmulti(lowerdev, -1);
@@ -399,10 +403,11 @@ static void macvlan_change_rx_flags(struct net_device *dev, int change)
dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1);
}
-static void macvlan_set_multicast_list(struct net_device *dev)
+static void macvlan_set_mac_lists(struct net_device *dev)
{
struct macvlan_dev *vlan = netdev_priv(dev);
+ dev_uc_sync(vlan->lowerdev, dev);
dev_mc_sync(vlan->lowerdev, dev);
}
@@ -542,6 +547,43 @@ static int macvlan_vlan_rx_kill_vid(struct net_device *dev,
return 0;
}
+static int macvlan_fdb_add(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr,
+ u16 flags)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ int err = -EINVAL;
+
+ if (!vlan->port->passthru)
+ return -EOPNOTSUPP;
+
+ if (is_unicast_ether_addr(addr))
+ err = dev_uc_add_excl(dev, addr);
+ else if (is_multicast_ether_addr(addr))
+ err = dev_mc_add_excl(dev, addr);
+
+ return err;
+}
+
+static int macvlan_fdb_del(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr)
+{
+ struct macvlan_dev *vlan = netdev_priv(dev);
+ int err = -EINVAL;
+
+ if (!vlan->port->passthru)
+ return -EOPNOTSUPP;
+
+ if (is_unicast_ether_addr(addr))
+ err = dev_uc_del(dev, addr);
+ else if (is_multicast_ether_addr(addr))
+ err = dev_mc_del(dev, addr);
+
+ return err;
+}
+
static void macvlan_ethtool_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *drvinfo)
{
@@ -572,11 +614,14 @@ static const struct net_device_ops macvlan_netdev_ops = {
.ndo_change_mtu = macvlan_change_mtu,
.ndo_change_rx_flags = macvlan_change_rx_flags,
.ndo_set_mac_address = macvlan_set_mac_address,
- .ndo_set_rx_mode = macvlan_set_multicast_list,
+ .ndo_set_rx_mode = macvlan_set_mac_lists,
.ndo_get_stats64 = macvlan_dev_get_stats64,
.ndo_validate_addr = eth_validate_addr,
.ndo_vlan_rx_add_vid = macvlan_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = macvlan_vlan_rx_kill_vid,
+ .ndo_fdb_add = macvlan_fdb_add,
+ .ndo_fdb_del = macvlan_fdb_del,
+ .ndo_fdb_dump = ndo_dflt_fdb_dump,
};
void macvlan_common_setup(struct net_device *dev)
@@ -711,6 +756,9 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
if (data && data[IFLA_MACVLAN_MODE])
vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
+ if (data && data[IFLA_MACVLAN_FLAGS])
+ vlan->flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
+
if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
if (port->count)
return -EINVAL;
@@ -760,6 +808,16 @@ static int macvlan_changelink(struct net_device *dev,
struct macvlan_dev *vlan = netdev_priv(dev);
if (data && data[IFLA_MACVLAN_MODE])
vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
+ if (data && data[IFLA_MACVLAN_FLAGS]) {
+ __u16 flags = nla_get_u16(data[IFLA_MACVLAN_FLAGS]);
+ bool promisc = (flags ^ vlan->flags) & MACVLAN_FLAG_NOPROMISC;
+
+ if (promisc && (flags & MACVLAN_FLAG_NOPROMISC))
+ dev_set_promiscuity(vlan->lowerdev, -1);
+ else if (promisc && !(flags & MACVLAN_FLAG_NOPROMISC))
+ dev_set_promiscuity(vlan->lowerdev, 1);
+ vlan->flags = flags;
+ }
return 0;
}
@@ -775,6 +833,8 @@ static int macvlan_fill_info(struct sk_buff *skb,
if (nla_put_u32(skb, IFLA_MACVLAN_MODE, vlan->mode))
goto nla_put_failure;
+ if (nla_put_u16(skb, IFLA_MACVLAN_FLAGS, vlan->flags))
+ goto nla_put_failure;
return 0;
nla_put_failure:
@@ -782,7 +842,8 @@ nla_put_failure:
}
static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
- [IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
+ [IFLA_MACVLAN_MODE] = { .type = NLA_U32 },
+ [IFLA_MACVLAN_FLAGS] = { .type = NLA_U16 },
};
int macvlan_link_register(struct rtnl_link_ops *ops)
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 2f4fa93..f715750 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -255,6 +255,7 @@ struct ifla_vlan_qos_mapping {
enum {
IFLA_MACVLAN_UNSPEC,
IFLA_MACVLAN_MODE,
+ IFLA_MACVLAN_FLAGS,
__IFLA_MACVLAN_MAX,
};
@@ -267,6 +268,8 @@ enum macvlan_mode {
MACVLAN_MODE_PASSTHRU = 8,/* take over the underlying device */
};
+#define MACVLAN_FLAG_NOPROMISC 1
+
/* SR-IOV virtual function management section */
enum {
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index d103dca..f65e8d2 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -60,6 +60,7 @@ struct macvlan_dev {
struct net_device *lowerdev;
struct macvlan_pcpu_stats __percpu *pcpu_stats;
enum macvlan_mode mode;
+ u16 flags;
int (*receive)(struct sk_buff *skb);
int (*forward)(struct net_device *dev, struct sk_buff *skb);
struct macvtap_queue *taps[MAX_MACVTAP_QUEUES];
^ permalink raw reply related
* [net-next PATCH v4 7/8] ixgbe: UTA table incorrectly programmed
From: John Fastabend @ 2012-04-15 16:44 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings
Cc: sri, hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120415163905.14091.30491.stgit@jf-dev1-dcblab>
From: Greg Rose <gregory.v.rose@intel.com>
The UTA table was being set to the functional equivalent of promiscuous
mode. This was resulting in traffic from the virtual function being
flooded onto the wire and the PF device. This resulted in additional
overhead for VF traffic sent to the network and in the case of traffic
sent to the PF or another VF resulted in unwanted packets on the wire.
This was actually not the intended behavior. Now that we can program
the embedded switch correctly we can remove this snippit of code. Users
who want to support this should configure the FDB correctly using the
FDB ops.
Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 29 -------------------------
1 files changed, 0 insertions(+), 29 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 25a7ed9..10606bd 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -2904,33 +2904,6 @@ static void ixgbe_configure_rscctl(struct ixgbe_adapter *adapter,
IXGBE_WRITE_REG(hw, IXGBE_RSCCTL(reg_idx), rscctrl);
}
-/**
- * ixgbe_set_uta - Set unicast filter table address
- * @adapter: board private structure
- *
- * The unicast table address is a register array of 32-bit registers.
- * The table is meant to be used in a way similar to how the MTA is used
- * however due to certain limitations in the hardware it is necessary to
- * set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscuous
- * enable bit to allow vlan tag stripping when promiscuous mode is enabled
- **/
-static void ixgbe_set_uta(struct ixgbe_adapter *adapter)
-{
- struct ixgbe_hw *hw = &adapter->hw;
- int i;
-
- /* The UTA table only exists on 82599 hardware and newer */
- if (hw->mac.type < ixgbe_mac_82599EB)
- return;
-
- /* we only need to do this if VMDq is enabled */
- if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
- return;
-
- for (i = 0; i < 128; i++)
- IXGBE_WRITE_REG(hw, IXGBE_UTA(i), ~0);
-}
-
#define IXGBE_MAX_RX_DESC_POLL 10
static void ixgbe_rx_desc_queue_enable(struct ixgbe_adapter *adapter,
struct ixgbe_ring *ring)
@@ -3224,8 +3197,6 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
/* Program registers for the distribution of queues */
ixgbe_setup_mrqc(adapter);
- ixgbe_set_uta(adapter);
-
/* set_rx_buffer_len must be called before ring initialization */
ixgbe_set_rx_buffer_len(adapter);
^ permalink raw reply related
* [net-next PATCH v4 6/8] ixgbe: allow RAR table to be updated in promisc mode
From: John Fastabend @ 2012-04-15 16:44 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings
Cc: sri, hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120415163905.14091.30491.stgit@jf-dev1-dcblab>
This allows RAR table updates while in promiscuous. With
SR-IOV enabled it is valuable to allow the RAR table to
be updated even when in promisc mode to configure forwarding
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 21 +++++++++++----------
1 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 8b37395..25a7ed9 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -3462,16 +3462,17 @@ void ixgbe_set_rx_mode(struct net_device *netdev)
}
ixgbe_vlan_filter_enable(adapter);
hw->addr_ctrl.user_set_promisc = false;
- /*
- * Write addresses to available RAR registers, if there is not
- * sufficient space to store all the addresses then enable
- * unicast promiscuous mode
- */
- count = ixgbe_write_uc_addr_list(netdev);
- if (count < 0) {
- fctrl |= IXGBE_FCTRL_UPE;
- vmolr |= IXGBE_VMOLR_ROPE;
- }
+ }
+
+ /*
+ * Write addresses to available RAR registers, if there is not
+ * sufficient space to store all the addresses then enable
+ * unicast promiscuous mode
+ */
+ count = ixgbe_write_uc_addr_list(netdev);
+ if (count < 0) {
+ fctrl |= IXGBE_FCTRL_UPE;
+ vmolr |= IXGBE_VMOLR_ROPE;
}
if (adapter->num_vfs) {
^ permalink raw reply related
* [net-next PATCH v4 5/8] ixgbe: enable FDB netdevice ops
From: John Fastabend @ 2012-04-15 16:44 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings
Cc: sri, hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120415163905.14091.30491.stgit@jf-dev1-dcblab>
Enable FDB ops on ixgbe when in SR-IOV mode.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 71 +++++++++++++++++++++++++
1 files changed, 71 insertions(+), 0 deletions(-)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 3e26b1f..8b37395 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -6681,6 +6681,74 @@ static int ixgbe_set_features(struct net_device *netdev,
return 0;
}
+static int ixgbe_ndo_fdb_add(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr,
+ u16 flags)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ int err = -EOPNOTSUPP;
+
+ if (ndm->ndm_state & NUD_PERMANENT) {
+ pr_info("%s: FDB only supports static addresses\n",
+ ixgbe_driver_name);
+ return -EINVAL;
+ }
+
+ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
+ if (is_unicast_ether_addr(addr))
+ err = dev_uc_add_excl(dev, addr);
+ else if (is_multicast_ether_addr(addr))
+ err = dev_mc_add_excl(dev, addr);
+ else
+ err = -EINVAL;
+ }
+
+ /* Only return duplicate errors if NLM_F_EXCL is set */
+ if (err == -EEXIST && !(flags & NLM_F_EXCL))
+ err = 0;
+
+ return err;
+}
+
+static int ixgbe_ndo_fdb_del(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+ int err = -EOPNOTSUPP;
+
+ if (ndm->ndm_state & NUD_PERMANENT) {
+ pr_info("%s: FDB only supports static addresses\n",
+ ixgbe_driver_name);
+ return -EINVAL;
+ }
+
+ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) {
+ if (is_unicast_ether_addr(addr))
+ err = dev_uc_del(dev, addr);
+ else if (is_multicast_ether_addr(addr))
+ err = dev_mc_del(dev, addr);
+ else
+ err = -EINVAL;
+ }
+
+ return err;
+}
+
+static int ixgbe_ndo_fdb_dump(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct net_device *dev,
+ int idx)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+ if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
+ idx = ndo_dflt_fdb_dump(skb, cb, dev, idx);
+
+ return idx;
+}
+
static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_open = ixgbe_open,
.ndo_stop = ixgbe_close,
@@ -6717,6 +6785,9 @@ static const struct net_device_ops ixgbe_netdev_ops = {
#endif /* IXGBE_FCOE */
.ndo_set_features = ixgbe_set_features,
.ndo_fix_features = ixgbe_fix_features,
+ .ndo_fdb_add = ixgbe_ndo_fdb_add,
+ .ndo_fdb_del = ixgbe_ndo_fdb_del,
+ .ndo_fdb_dump = ixgbe_ndo_fdb_dump,
};
static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter,
^ permalink raw reply related
* [net-next PATCH v4 4/8] net: rtnetlink notify events for FDB NTF_SELF adds and deletes
From: John Fastabend @ 2012-04-15 16:44 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings
Cc: sri, hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120415163905.14091.30491.stgit@jf-dev1-dcblab>
It is useful to be able to monitor for FDB events in user space.
This patch adds support to generate netlink events when a change
is made to a device supporting the FDB ops.
This brings embedded switches inline with the SW net/bridge which
triggers events on FDB updates as well.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
net/core/rtnetlink.c | 35 +++++++++++++++++++++++++++++++++--
1 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 9149018..46f69b5 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -2011,6 +2011,33 @@ nla_put_failure:
return -EMSGSIZE;
}
+static inline size_t rtnl_fdb_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct ndmsg)) + nla_total_size(ETH_ALEN);
+}
+
+static void rtnl_fdb_notify(struct net_device *dev, u8 *addr, int type)
+{
+ struct net *net = dev_net(dev);
+ struct sk_buff *skb;
+ int err = -ENOBUFS;
+
+ skb = nlmsg_new(rtnl_fdb_nlmsg_size(), GFP_ATOMIC);
+ if (!skb)
+ goto errout;
+
+ err = nlmsg_populate_fdb_fill(skb, dev, addr, 0, 0, type, NTF_SELF);
+ if (err < 0) {
+ kfree_skb(skb);
+ goto errout;
+ }
+
+ rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
+ return;
+errout:
+ rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
+}
+
static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
struct net *net = sock_net(skb->sk);
@@ -2067,8 +2094,10 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
err = dev->netdev_ops->ndo_fdb_add(ndm, dev, addr,
nlh->nlmsg_flags);
- if (!err)
+ if (!err) {
+ rtnl_fdb_notify(dev, addr, RTM_NEWNEIGH);
ndm->ndm_flags &= ~NTF_SELF;
+ }
}
out:
return err;
@@ -2125,8 +2154,10 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_del) {
err = dev->netdev_ops->ndo_fdb_del(ndm, dev, addr);
- if (!err)
+ if (!err) {
+ rtnl_fdb_notify(dev, addr, RTM_DELNEIGH);
ndm->ndm_flags &= ~NTF_SELF;
+ }
}
out:
return err;
^ permalink raw reply related
* [net-next PATCH v4 3/8] net: add fdb generic dump routine
From: John Fastabend @ 2012-04-15 16:44 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings
Cc: sri, hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120415163905.14091.30491.stgit@jf-dev1-dcblab>
This adds a generic dump routine drivers can call. It
should be sufficient to handle any bridging model that
uses the unicast address list. This should be most SR-IOV
enabled NICs.
v2: return error on nlmsg_put and use -EMSGSIZE instead
of -ENOMEM this is inline other usages
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
net/core/rtnetlink.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 84 insertions(+), 0 deletions(-)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 037f53c..9149018 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1980,6 +1980,37 @@ errout:
rtnl_set_sk_err(net, RTNLGRP_LINK, err);
}
+static int nlmsg_populate_fdb_fill(struct sk_buff *skb,
+ struct net_device *dev,
+ u8 *addr, u32 pid, u32 seq,
+ int type, unsigned int flags)
+{
+ struct nlmsghdr *nlh;
+ struct ndmsg *ndm;
+
+ nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), NLM_F_MULTI);
+ if (!nlh)
+ return -EMSGSIZE;
+
+ ndm = nlmsg_data(nlh);
+ ndm->ndm_family = AF_BRIDGE;
+ ndm->ndm_pad1 = 0;
+ ndm->ndm_pad2 = 0;
+ ndm->ndm_flags = flags;
+ ndm->ndm_type = 0;
+ ndm->ndm_ifindex = dev->ifindex;
+ ndm->ndm_state = NUD_PERMANENT;
+
+ if (nla_put(skb, NDA_LLADDR, ETH_ALEN, addr))
+ goto nla_put_failure;
+
+ return nlmsg_end(skb, nlh);
+
+nla_put_failure:
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
+}
+
static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
struct net *net = sock_net(skb->sk);
@@ -2101,6 +2132,59 @@ out:
return err;
}
+static int nlmsg_populate_fdb(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct net_device *dev,
+ int *idx,
+ struct netdev_hw_addr_list *list)
+{
+ struct netdev_hw_addr *ha;
+ int err;
+ u32 pid, seq;
+
+ pid = NETLINK_CB(cb->skb).pid;
+ seq = cb->nlh->nlmsg_seq;
+
+ list_for_each_entry(ha, &list->list, list) {
+ if (*idx < cb->args[0])
+ goto skip;
+
+ err = nlmsg_populate_fdb_fill(skb, dev, ha->addr,
+ pid, seq, 0, NTF_SELF);
+ if (err < 0)
+ return err;
+skip:
+ *idx += 1;
+ }
+ return 0;
+}
+
+/**
+ * ndo_dflt_fdb_dump: default netdevice operation to dump an FDB table.
+ * @nlh: netlink message header
+ * @dev: netdevice
+ *
+ * Default netdevice operation to dump the existing unicast address list.
+ * Returns zero on success.
+ */
+int ndo_dflt_fdb_dump(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct net_device *dev,
+ int idx)
+{
+ int err;
+
+ netif_addr_lock_bh(dev);
+ err = nlmsg_populate_fdb(skb, cb, dev, &idx, &dev->uc);
+ if (err)
+ goto out;
+ nlmsg_populate_fdb(skb, cb, dev, &idx, &dev->mc);
+out:
+ netif_addr_unlock_bh(dev);
+ return idx;
+}
+EXPORT_SYMBOL(ndo_dflt_fdb_dump);
+
static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
int idx = 0;
^ permalink raw reply related
* [net-next PATCH v4 2/8] net: addr_list: add exclusive dev_uc_add and dev_mc_add
From: John Fastabend @ 2012-04-15 16:44 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings
Cc: sri, hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120415163905.14091.30491.stgit@jf-dev1-dcblab>
This adds a dev_uc_add_excl() and dev_mc_add_excl() calls
similar to the original dev_{uc|mc}_add() except it sets
the global bit and returns -EEXIST for duplicat entires.
This is useful for drivers that support SR-IOV, macvlan
devices and any other devices that need to manage the
unicast and multicast lists.
v2: fix typo UNICAST should be MULTICAST in dev_mc_add_excl()
CC: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
include/linux/netdevice.h | 2 +
net/core/dev_addr_lists.c | 97 ++++++++++++++++++++++++++++++++++++++-------
2 files changed, 83 insertions(+), 16 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7600c61..3f738ca 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2569,6 +2569,7 @@ extern int dev_addr_init(struct net_device *dev);
/* Functions used for unicast addresses handling */
extern int dev_uc_add(struct net_device *dev, unsigned char *addr);
+extern int dev_uc_add_excl(struct net_device *dev, unsigned char *addr);
extern int dev_uc_del(struct net_device *dev, unsigned char *addr);
extern int dev_uc_sync(struct net_device *to, struct net_device *from);
extern void dev_uc_unsync(struct net_device *to, struct net_device *from);
@@ -2578,6 +2579,7 @@ extern void dev_uc_init(struct net_device *dev);
/* Functions used for multicast addresses handling */
extern int dev_mc_add(struct net_device *dev, unsigned char *addr);
extern int dev_mc_add_global(struct net_device *dev, unsigned char *addr);
+extern int dev_mc_add_excl(struct net_device *dev, unsigned char *addr);
extern int dev_mc_del(struct net_device *dev, unsigned char *addr);
extern int dev_mc_del_global(struct net_device *dev, unsigned char *addr);
extern int dev_mc_sync(struct net_device *to, struct net_device *from);
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c
index 626698f..c4cc2bc 100644
--- a/net/core/dev_addr_lists.c
+++ b/net/core/dev_addr_lists.c
@@ -21,12 +21,35 @@
* General list handling functions
*/
+static int __hw_addr_create_ex(struct netdev_hw_addr_list *list,
+ unsigned char *addr, int addr_len,
+ unsigned char addr_type, bool global)
+{
+ struct netdev_hw_addr *ha;
+ int alloc_size;
+
+ alloc_size = sizeof(*ha);
+ if (alloc_size < L1_CACHE_BYTES)
+ alloc_size = L1_CACHE_BYTES;
+ ha = kmalloc(alloc_size, GFP_ATOMIC);
+ if (!ha)
+ return -ENOMEM;
+ memcpy(ha->addr, addr, addr_len);
+ ha->type = addr_type;
+ ha->refcount = 1;
+ ha->global_use = global;
+ ha->synced = false;
+ list_add_tail_rcu(&ha->list, &list->list);
+ list->count++;
+
+ return 0;
+}
+
static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
unsigned char *addr, int addr_len,
unsigned char addr_type, bool global)
{
struct netdev_hw_addr *ha;
- int alloc_size;
if (addr_len > MAX_ADDR_LEN)
return -EINVAL;
@@ -46,21 +69,7 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
}
}
-
- alloc_size = sizeof(*ha);
- if (alloc_size < L1_CACHE_BYTES)
- alloc_size = L1_CACHE_BYTES;
- ha = kmalloc(alloc_size, GFP_ATOMIC);
- if (!ha)
- return -ENOMEM;
- memcpy(ha->addr, addr, addr_len);
- ha->type = addr_type;
- ha->refcount = 1;
- ha->global_use = global;
- ha->synced = false;
- list_add_tail_rcu(&ha->list, &list->list);
- list->count++;
- return 0;
+ return __hw_addr_create_ex(list, addr, addr_len, addr_type, global);
}
static int __hw_addr_add(struct netdev_hw_addr_list *list, unsigned char *addr,
@@ -377,6 +386,34 @@ EXPORT_SYMBOL(dev_addr_del_multiple);
*/
/**
+ * dev_uc_add_excl - Add a global secondary unicast address
+ * @dev: device
+ * @addr: address to add
+ */
+int dev_uc_add_excl(struct net_device *dev, unsigned char *addr)
+{
+ struct netdev_hw_addr *ha;
+ int err;
+
+ netif_addr_lock_bh(dev);
+ list_for_each_entry(ha, &dev->uc.list, list) {
+ if (!memcmp(ha->addr, addr, dev->addr_len) &&
+ ha->type == NETDEV_HW_ADDR_T_UNICAST) {
+ err = -EEXIST;
+ goto out;
+ }
+ }
+ err = __hw_addr_create_ex(&dev->uc, addr, dev->addr_len,
+ NETDEV_HW_ADDR_T_UNICAST, true);
+ if (!err)
+ __dev_set_rx_mode(dev);
+out:
+ netif_addr_unlock_bh(dev);
+ return err;
+}
+EXPORT_SYMBOL(dev_uc_add_excl);
+
+/**
* dev_uc_add - Add a secondary unicast address
* @dev: device
* @addr: address to add
@@ -501,6 +538,34 @@ EXPORT_SYMBOL(dev_uc_init);
* Multicast list handling functions
*/
+/**
+ * dev_mc_add_excl - Add a global secondary multicast address
+ * @dev: device
+ * @addr: address to add
+ */
+int dev_mc_add_excl(struct net_device *dev, unsigned char *addr)
+{
+ struct netdev_hw_addr *ha;
+ int err;
+
+ netif_addr_lock_bh(dev);
+ list_for_each_entry(ha, &dev->mc.list, list) {
+ if (!memcmp(ha->addr, addr, dev->addr_len) &&
+ ha->type == NETDEV_HW_ADDR_T_MULTICAST) {
+ err = -EEXIST;
+ goto out;
+ }
+ }
+ err = __hw_addr_create_ex(&dev->mc, addr, dev->addr_len,
+ NETDEV_HW_ADDR_T_MULTICAST, true);
+ if (!err)
+ __dev_set_rx_mode(dev);
+out:
+ netif_addr_unlock_bh(dev);
+ return err;
+}
+EXPORT_SYMBOL(dev_mc_add_excl);
+
static int __dev_mc_add(struct net_device *dev, unsigned char *addr,
bool global)
{
^ permalink raw reply related
* [net-next PATCH v4 1/8] net: add generic PF_BRIDGE:RTM_ FDB hooks
From: John Fastabend @ 2012-04-15 16:43 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings
Cc: sri, hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
In-Reply-To: <20120415163905.14091.30491.stgit@jf-dev1-dcblab>
This adds two new flags NTF_MASTER and NTF_SELF that can
now be used to specify where PF_BRIDGE netlink commands should
be sent. NTF_MASTER sends the commands to the 'dev->master'
device for parsing. Typically this will be the linux net/bridge,
or open-vswitch devices. Also without any flags set the command
will be handled by the master device as well so that current user
space tools continue to work as expected.
The NTF_SELF flag will push the PF_BRIDGE commands to the
device. In the basic example below the commands are then parsed
and programmed in the embedded bridge.
Note if both NTF_SELF and NTF_MASTER bits are set then the
command will be sent to both 'dev->master' and 'dev' this allows
user space to easily keep the embedded bridge and software bridge
in sync.
There is a slight complication in the case with both flags set
when an error occurs. To resolve this the rtnl handler clears
the NTF_ flag in the netlink ack to indicate which sets completed
successfully. The add/del handlers will abort as soon as any
error occurs.
To support this new net device ops were added to call into
the device and the existing bridging code was refactored
to use these. There should be no required changes in user space
to support the current bridge behavior.
A basic setup with a SR-IOV enabled NIC looks like this,
veth0 veth2
| |
------------
| bridge0 | <---- software bridging
------------
/
/
ethx.y ethx
VF PF
\ \ <---- propagate FDB entries to HW
\ \
--------------------
| Embedded Bridge | <---- hardware offloaded switching
--------------------
In this case the embedded bridge must be managed to allow 'veth0'
to communicate with 'ethx.y' correctly. At present drivers managing
the embedded bridge either send frames onto the network which
then get dropped by the switch OR the embedded bridge will flood
these frames. With this patch we have a mechanism to manage the
embedded bridge correctly from user space. This example is specific
to SR-IOV but replacing the VF with another PF or dropping this
into the DSA framework generates similar management issues.
Examples session using the 'br'[1] tool to add, dump and then
delete a mac address with a new "embedded" option and enabled
ixgbe driver:
# br fdb add 22:35:19:ac:60:59 dev eth3
# br fdb
port mac addr flags
veth0 22:35:19:ac:60:58 static
veth0 9a:5f:81:f7:f6:ec local
eth3 00:1b:21:55:23:59 local
eth3 22:35:19:ac:60:59 static
veth0 22:35:19:ac:60:57 static
#br fdb add 22:35:19:ac:60:59 embedded dev eth3
#br fdb
port mac addr flags
veth0 22:35:19:ac:60:58 static
veth0 9a:5f:81:f7:f6:ec local
eth3 00:1b:21:55:23:59 local
eth3 22:35:19:ac:60:59 static
veth0 22:35:19:ac:60:57 static
eth3 22:35:19:ac:60:59 local embedded
#br fdb del 22:35:19:ac:60:59 embedded dev eth3
I added a couple lines to 'br' to set the flags correctly is all. It
is my opinion that the merit of this patch is now embedded and SW
bridges can both be modeled correctly in user space using very nearly
the same message passing.
[1] 'br' tool was published as an RFC here and will be renamed 'bridge'
http://patchwork.ozlabs.org/patch/117664/
Thanks to Jamal Hadi Salim, Stephen Hemminger and Ben Hutchings for
valuable feedback, suggestions, and review.
v2: fixed api descriptions and error case with both NTF_SELF and
NTF_MASTER set plus updated patch description.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
include/linux/neighbour.h | 3 +
include/linux/netdevice.h | 23 +++++++
include/linux/rtnetlink.h | 4 +
net/bridge/br_device.c | 3 +
net/bridge/br_fdb.c | 128 +++++++++-----------------------------
net/bridge/br_netlink.c | 12 ----
net/bridge/br_private.h | 15 ++++
net/core/rtnetlink.c | 152 +++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 228 insertions(+), 112 deletions(-)
diff --git a/include/linux/neighbour.h b/include/linux/neighbour.h
index b188f68..275e5d6 100644
--- a/include/linux/neighbour.h
+++ b/include/linux/neighbour.h
@@ -33,6 +33,9 @@ enum {
#define NTF_PROXY 0x08 /* == ATF_PUBL */
#define NTF_ROUTER 0x80
+#define NTF_SELF 0x02
+#define NTF_MASTER 0x04
+
/*
* Neighbor Cache Entry States.
*/
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 5cbaa20..7600c61 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -54,6 +54,7 @@
#include <net/netprio_cgroup.h>
#include <linux/netdev_features.h>
+#include <linux/neighbour.h>
struct netpoll_info;
struct device;
@@ -905,6 +906,16 @@ struct netdev_fcoe_hbainfo {
* feature set might be less than what was returned by ndo_fix_features()).
* Must return >0 or -errno if it changed dev->features itself.
*
+ * int (*ndo_fdb_add)(struct ndmsg *ndm, struct net_device *dev,
+ * unsigned char *addr, u16 flags)
+ * Adds an FDB entry to dev for addr.
+ * int (*ndo_fdb_del)(struct ndmsg *ndm, struct net_device *dev,
+ * unsigned char *addr)
+ * Deletes the FDB entry from dev coresponding to addr.
+ * int (*ndo_fdb_dump)(struct sk_buff *skb, struct netlink_callback *cb,
+ * struct net_device *dev, int idx)
+ * Used to add FDB entries to dump requests. Implementers should add
+ * entries to skb and update idx with the number of entries.
*/
struct net_device_ops {
int (*ndo_init)(struct net_device *dev);
@@ -1002,6 +1013,18 @@ struct net_device_ops {
netdev_features_t features);
int (*ndo_neigh_construct)(struct neighbour *n);
void (*ndo_neigh_destroy)(struct neighbour *n);
+
+ int (*ndo_fdb_add)(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr,
+ u16 flags);
+ int (*ndo_fdb_del)(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr);
+ int (*ndo_fdb_dump)(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct net_device *dev,
+ int idx);
};
/*
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 577592e..2c1de89 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -801,6 +801,10 @@ rtattr_failure:
return table;
}
+extern int ndo_dflt_fdb_dump(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct net_device *dev,
+ int idx);
#endif /* __KERNEL__ */
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index ba829de..d6e5929 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -317,6 +317,9 @@ static const struct net_device_ops br_netdev_ops = {
.ndo_add_slave = br_add_slave,
.ndo_del_slave = br_del_slave,
.ndo_fix_features = br_fix_features,
+ .ndo_fdb_add = br_fdb_add,
+ .ndo_fdb_del = br_fdb_delete,
+ .ndo_fdb_dump = br_fdb_dump,
};
static void br_dev_free(struct net_device *dev)
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 80dbce4..5945c54 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -535,44 +535,38 @@ errout:
}
/* Dump information about entries, in response to GETNEIGH */
-int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
+int br_fdb_dump(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct net_device *dev,
+ int idx)
{
- struct net *net = sock_net(skb->sk);
- struct net_device *dev;
- int idx = 0;
-
- rcu_read_lock();
- for_each_netdev_rcu(net, dev) {
- struct net_bridge *br = netdev_priv(dev);
- int i;
-
- if (!(dev->priv_flags & IFF_EBRIDGE))
- continue;
+ struct net_bridge *br = netdev_priv(dev);
+ int i;
- for (i = 0; i < BR_HASH_SIZE; i++) {
- struct hlist_node *h;
- struct net_bridge_fdb_entry *f;
+ if (!(dev->priv_flags & IFF_EBRIDGE))
+ goto out;
- hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) {
- if (idx < cb->args[0])
- goto skip;
+ for (i = 0; i < BR_HASH_SIZE; i++) {
+ struct hlist_node *h;
+ struct net_bridge_fdb_entry *f;
- if (fdb_fill_info(skb, br, f,
- NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq,
- RTM_NEWNEIGH,
- NLM_F_MULTI) < 0)
- break;
+ hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) {
+ if (idx < cb->args[0])
+ goto skip;
+
+ if (fdb_fill_info(skb, br, f,
+ NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq,
+ RTM_NEWNEIGH,
+ NLM_F_MULTI) < 0)
+ break;
skip:
- ++idx;
- }
+ ++idx;
}
}
- rcu_read_unlock();
-
- cb->args[0] = idx;
- return skb->len;
+out:
+ return idx;
}
/* Update (create or replace) forwarding database entry */
@@ -614,43 +608,11 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr,
}
/* Add new permanent fdb entry with RTM_NEWNEIGH */
-int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+int br_fdb_add(struct ndmsg *ndm, struct net_device *dev,
+ unsigned char *addr, u16 nlh_flags)
{
- struct net *net = sock_net(skb->sk);
- struct ndmsg *ndm;
- struct nlattr *tb[NDA_MAX+1];
- struct net_device *dev;
struct net_bridge_port *p;
- const __u8 *addr;
- int err;
-
- ASSERT_RTNL();
- err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
- if (err < 0)
- return err;
-
- ndm = nlmsg_data(nlh);
- if (ndm->ndm_ifindex == 0) {
- pr_info("bridge: RTM_NEWNEIGH with invalid ifindex\n");
- return -EINVAL;
- }
-
- dev = __dev_get_by_index(net, ndm->ndm_ifindex);
- if (dev == NULL) {
- pr_info("bridge: RTM_NEWNEIGH with unknown ifindex\n");
- return -ENODEV;
- }
-
- if (!tb[NDA_LLADDR] || nla_len(tb[NDA_LLADDR]) != ETH_ALEN) {
- pr_info("bridge: RTM_NEWNEIGH with invalid address\n");
- return -EINVAL;
- }
-
- addr = nla_data(tb[NDA_LLADDR]);
- if (!is_valid_ether_addr(addr)) {
- pr_info("bridge: RTM_NEWNEIGH with invalid ether address\n");
- return -EINVAL;
- }
+ int err = 0;
if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE))) {
pr_info("bridge: RTM_NEWNEIGH with invalid state %#x\n", ndm->ndm_state);
@@ -670,14 +632,14 @@ int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
rcu_read_unlock();
} else {
spin_lock_bh(&p->br->hash_lock);
- err = fdb_add_entry(p, addr, ndm->ndm_state, nlh->nlmsg_flags);
+ err = fdb_add_entry(p, addr, ndm->ndm_state, nlh_flags);
spin_unlock_bh(&p->br->hash_lock);
}
return err;
}
-static int fdb_delete_by_addr(struct net_bridge_port *p, const u8 *addr)
+static int fdb_delete_by_addr(struct net_bridge_port *p, u8 *addr)
{
struct net_bridge *br = p->br;
struct hlist_head *head = &br->hash[br_mac_hash(addr)];
@@ -692,40 +654,12 @@ static int fdb_delete_by_addr(struct net_bridge_port *p, const u8 *addr)
}
/* Remove neighbor entry with RTM_DELNEIGH */
-int br_fdb_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+int br_fdb_delete(struct ndmsg *ndm, struct net_device *dev,
+ unsigned char *addr)
{
- struct net *net = sock_net(skb->sk);
- struct ndmsg *ndm;
struct net_bridge_port *p;
- struct nlattr *llattr;
- const __u8 *addr;
- struct net_device *dev;
int err;
- ASSERT_RTNL();
- if (nlmsg_len(nlh) < sizeof(*ndm))
- return -EINVAL;
-
- ndm = nlmsg_data(nlh);
- if (ndm->ndm_ifindex == 0) {
- pr_info("bridge: RTM_DELNEIGH with invalid ifindex\n");
- return -EINVAL;
- }
-
- dev = __dev_get_by_index(net, ndm->ndm_ifindex);
- if (dev == NULL) {
- pr_info("bridge: RTM_DELNEIGH with unknown ifindex\n");
- return -ENODEV;
- }
-
- llattr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_LLADDR);
- if (llattr == NULL || nla_len(llattr) != ETH_ALEN) {
- pr_info("bridge: RTM_DELNEIGH with invalid address\n");
- return -EINVAL;
- }
-
- addr = nla_data(llattr);
-
p = br_port_get_rtnl(dev);
if (p == NULL) {
pr_info("bridge: RTM_DELNEIGH %s not a bridge port\n",
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 346b368..1fa0535 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -232,18 +232,6 @@ int __init br_netlink_init(void)
br_rtm_setlink, NULL, NULL);
if (err)
goto err3;
- err = __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH,
- br_fdb_add, NULL, NULL);
- if (err)
- goto err3;
- err = __rtnl_register(PF_BRIDGE, RTM_DELNEIGH,
- br_fdb_delete, NULL, NULL);
- if (err)
- goto err3;
- err = __rtnl_register(PF_BRIDGE, RTM_GETNEIGH,
- NULL, br_fdb_dump, NULL);
- if (err)
- goto err3;
return 0;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index e1d8822..dd8a121 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -359,9 +359,18 @@ extern int br_fdb_insert(struct net_bridge *br,
extern void br_fdb_update(struct net_bridge *br,
struct net_bridge_port *source,
const unsigned char *addr);
-extern int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb);
-extern int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
-extern int br_fdb_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
+
+extern int br_fdb_delete(struct ndmsg *ndm,
+ struct net_device *dev,
+ unsigned char *addr);
+extern int br_fdb_add(struct ndmsg *nlh,
+ struct net_device *dev,
+ unsigned char *addr,
+ u16 nlh_flags);
+extern int br_fdb_dump(struct sk_buff *skb,
+ struct netlink_callback *cb,
+ struct net_device *dev,
+ int idx);
/* br_forward.c */
extern void br_deliver(const struct net_bridge_port *to,
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 4a0d8cf..037f53c 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -35,7 +35,9 @@
#include <linux/security.h>
#include <linux/mutex.h>
#include <linux/if_addr.h>
+#include <linux/if_bridge.h>
#include <linux/pci.h>
+#include <linux/etherdevice.h>
#include <asm/uaccess.h>
@@ -1978,6 +1980,152 @@ errout:
rtnl_set_sk_err(net, RTNLGRP_LINK, err);
}
+static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ struct net *net = sock_net(skb->sk);
+ struct net_device *master = NULL;
+ struct ndmsg *ndm;
+ struct nlattr *tb[NDA_MAX+1];
+ struct net_device *dev;
+ u8 *addr;
+ int err;
+
+ err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
+ if (err < 0)
+ return err;
+
+ ndm = nlmsg_data(nlh);
+ if (ndm->ndm_ifindex == 0) {
+ pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid ifindex\n");
+ return -EINVAL;
+ }
+
+ dev = __dev_get_by_index(net, ndm->ndm_ifindex);
+ if (dev == NULL) {
+ pr_info("PF_BRIDGE: RTM_NEWNEIGH with unknown ifindex\n");
+ return -ENODEV;
+ }
+
+ if (!tb[NDA_LLADDR] || nla_len(tb[NDA_LLADDR]) != ETH_ALEN) {
+ pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid address\n");
+ return -EINVAL;
+ }
+
+ addr = nla_data(tb[NDA_LLADDR]);
+ if (!is_valid_ether_addr(addr)) {
+ pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid ether address\n");
+ return -EINVAL;
+ }
+
+ err = -EOPNOTSUPP;
+
+ /* Support fdb on master device the net/bridge default case */
+ if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) &&
+ (dev->priv_flags & IFF_BRIDGE_PORT)) {
+ master = dev->master;
+ err = master->netdev_ops->ndo_fdb_add(ndm, dev, addr,
+ nlh->nlmsg_flags);
+ if (err)
+ goto out;
+ else
+ ndm->ndm_flags &= ~NTF_MASTER;
+ }
+
+ /* Embedded bridge, macvlan, and any other device support */
+ if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_add) {
+ err = dev->netdev_ops->ndo_fdb_add(ndm, dev, addr,
+ nlh->nlmsg_flags);
+
+ if (!err)
+ ndm->ndm_flags &= ~NTF_SELF;
+ }
+out:
+ return err;
+}
+
+static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ struct net *net = sock_net(skb->sk);
+ struct ndmsg *ndm;
+ struct nlattr *llattr;
+ struct net_device *dev;
+ int err = -EINVAL;
+ __u8 *addr;
+
+ if (nlmsg_len(nlh) < sizeof(*ndm))
+ return -EINVAL;
+
+ ndm = nlmsg_data(nlh);
+ if (ndm->ndm_ifindex == 0) {
+ pr_info("PF_BRIDGE: RTM_DELNEIGH with invalid ifindex\n");
+ return -EINVAL;
+ }
+
+ dev = __dev_get_by_index(net, ndm->ndm_ifindex);
+ if (dev == NULL) {
+ pr_info("PF_BRIDGE: RTM_DELNEIGH with unknown ifindex\n");
+ return -ENODEV;
+ }
+
+ llattr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_LLADDR);
+ if (llattr == NULL || nla_len(llattr) != ETH_ALEN) {
+ pr_info("PF_BRIGDE: RTM_DELNEIGH with invalid address\n");
+ return -EINVAL;
+ }
+
+ addr = nla_data(llattr);
+ err = -EOPNOTSUPP;
+
+ /* Support fdb on master device the net/bridge default case */
+ if ((!ndm->ndm_flags || ndm->ndm_flags & NTF_MASTER) &&
+ (dev->priv_flags & IFF_BRIDGE_PORT)) {
+ struct net_device *master = dev->master;
+
+ if (master->netdev_ops->ndo_fdb_del)
+ err = master->netdev_ops->ndo_fdb_del(ndm, dev, addr);
+
+ if (err)
+ goto out;
+ else
+ ndm->ndm_flags &= ~NTF_MASTER;
+ }
+
+ /* Embedded bridge, macvlan, and any other device support */
+ if ((ndm->ndm_flags & NTF_SELF) && dev->netdev_ops->ndo_fdb_del) {
+ err = dev->netdev_ops->ndo_fdb_del(ndm, dev, addr);
+
+ if (!err)
+ ndm->ndm_flags &= ~NTF_SELF;
+ }
+out:
+ return err;
+}
+
+static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int idx = 0;
+ struct net *net = sock_net(skb->sk);
+ struct net_device *dev;
+
+ rcu_read_lock();
+ for_each_netdev_rcu(net, dev) {
+ if (dev->priv_flags & IFF_BRIDGE_PORT) {
+ struct net_device *master = dev->master;
+ const struct net_device_ops *ops = master->netdev_ops;
+
+ if (ops->ndo_fdb_dump)
+ idx = ops->ndo_fdb_dump(skb, cb, dev, idx);
+ }
+
+ if (dev->netdev_ops->ndo_fdb_dump)
+ idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, idx);
+ }
+ rcu_read_unlock();
+
+ cb->args[0] = idx;
+ return skb->len;
+}
+
/* Protected by RTNL sempahore. */
static struct rtattr **rta_buf;
static int rtattr_max;
@@ -2150,5 +2298,9 @@ void __init rtnetlink_init(void)
rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, NULL);
rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, NULL);
+
+ rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, rtnl_fdb_add, NULL, NULL);
+ rtnl_register(PF_BRIDGE, RTM_DELNEIGH, rtnl_fdb_del, NULL, NULL);
+ rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, rtnl_fdb_dump, NULL);
}
^ permalink raw reply related
* [net-next PATCH v4 0/8] Managing the forwarding database(FDB)
From: John Fastabend @ 2012-04-15 16:43 UTC (permalink / raw)
To: shemminger, mst, davem, bhutchings
Cc: sri, hadi, jeffrey.t.kirsher, netdev, gregory.v.rose, krkumar2
The following series is a submission for net-next to allow
embedded switches and other stacked devices other then the
Linux bridge to manage a forwarding database.
Previously discussed here,
http://lists.openwall.net/netdev/2012/03/19/26
v4: propagate return codes correctly for ndo_dflt_Fdb_dump()
v3: resolve the macvlan patch 8/8 to fix a dev_set_promiscuity()
error and add the flags field to change and get link routines.
v2: addressed feedback from Ben Hutchings resolving a typo in the
multicast add/del routines and improving the error handling
when both NTF_SELF and NTF_MASTER are set.
I've tested this with 'br' tool published by Stephen Hemminger
soon to be renamed 'bridge' I believe and various traffic
generators mostly pktgen, ping, and netperf.
Thanks for the feedback any comments welcome.
John
---
Greg Rose (1):
ixgbe: UTA table incorrectly programmed
John Fastabend (7):
macvlan: add FDB bridge ops and macvlan flags
ixgbe: allow RAR table to be updated in promisc mode
ixgbe: enable FDB netdevice ops
net: rtnetlink notify events for FDB NTF_SELF adds and deletes
net: add fdb generic dump routine
net: addr_list: add exclusive dev_uc_add and dev_mc_add
net: add generic PF_BRIDGE:RTM_ FDB hooks
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 121 ++++++++---
drivers/net/macvlan.c | 73 ++++++-
include/linux/if_link.h | 3
include/linux/if_macvlan.h | 1
include/linux/neighbour.h | 3
include/linux/netdevice.h | 25 ++
include/linux/rtnetlink.h | 4
net/bridge/br_device.c | 3
net/bridge/br_fdb.c | 128 +++---------
net/bridge/br_netlink.c | 12 -
net/bridge/br_private.h | 15 +
net/core/dev_addr_lists.c | 97 ++++++++-
net/core/rtnetlink.c | 267 +++++++++++++++++++++++++
13 files changed, 579 insertions(+), 173 deletions(-)
--
Signature
^ permalink raw reply
* Re: [0/3] bridge: Do not send multicast queries by default
From: David Miller @ 2012-04-15 16:52 UTC (permalink / raw)
To: herbert; +Cc: netdev
In-Reply-To: <20120413123641.GA758@gondor.apana.org.au>
From: Herbert Xu <herbert@gondor.hengli.com.au>
Date: Fri, 13 Apr 2012 20:36:41 +0800
> This series of patches is aimed to change the default multicast
> snooping behaviour to one that is safer to deploy in the wild.
>
> There have been numerous reports of switches misbehaving with
> our current behaviour of sending general queries, presumably
> because we're using a zero source IP address which is unavoidable
> as using anything else would interfere with multicast querier
> elections (incidentally, I noticed that our IPv6 code has been
> "fixed" to not use zero source addresses, which is wrong as we
> may end up being THE MLD querier in a network).
>
> Since our queries aren't actually required for multicast snooping
> to function, but is merely an optimisation mostly for faster
> start-up convergence, I think we should disable this by default.
All applied to net-next, thanks Herbert.
^ permalink raw reply
* Re: [0/3] bridge: Do not send multicast queries by default
From: David Miller @ 2012-04-15 16:50 UTC (permalink / raw)
To: herbert; +Cc: netdev
In-Reply-To: <20120415111300.GA14147@gondor.apana.org.au>
From: Herbert Xu <herbert@gondor.hengli.com.au>
Date: Sun, 15 Apr 2012 19:13:00 +0800
> However, we're not implementing an RFC2710 node here. What we're
> doing is better described by RFC4541 (IGMP/MLD snooping), which calls
> for the use of a zero source address for both IPv4 and IPv6.
>
> The reason is precisely because it's invalid for normal querier
> nodes and as such they would ignore us (rather than elect us
> and potentially disrupt things).
Ok, make sense.
And in fact, I welcome changing this back to using a zero saddr, as
the ipv6 source address setting code brought in a lot of ugly
dependencies. :-)
^ permalink raw reply
* Re: [PATCH net-next] tcp: RFC6298 supersedes RFC2988bis
From: David Miller @ 2012-04-15 16:48 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev, hkchu, therbert
In-Reply-To: <1334504406.28012.17.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Sun, 15 Apr 2012 17:40:06 +0200
> 3) use RCU and dont hold parent socket lock to allow parallelism for
> multiqueue NICS (or RPS ...)
This part could be tricky.
We have to be careful in the case that one cpu comes in and finds the
listner sock for a particular child, meanwhile another cpu progresses
that child socket into ESTABLISHED state. Most of the parent locking
and strict synchronization is there to make sure this case works out
properly.
^ permalink raw reply
* Re: [PATCH net-next] net: cleanup unsigned to unsigned int
From: David Miller @ 2012-04-15 16:45 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev
In-Reply-To: <1334505486.28012.27.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Sun, 15 Apr 2012 17:58:06 +0200
> Use of "unsigned int" is preferred to bare "unsigned" in net tree.
>
> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH][trivial] ipv4: fix checkpatch errors
From: David Miller @ 2012-04-15 16:38 UTC (permalink / raw)
To: dbaluta; +Cc: netdev, trivial, linux-kernel
In-Reply-To: <1334489681-4662-1-git-send-email-dbaluta@ixiacom.com>
From: dbaluta@ixiacom.com
Date: Sun, 15 Apr 2012 14:34:41 +0300
> From: Daniel Baluta <dbaluta@ixiacom.com>
>
> Fix checkpatch errors of the following type:
> * ERROR: "foo * bar" should be "foo *bar"
> * ERROR: "(foo*)" should be "(foo *)"
>
> Signed-off-by: Daniel Baluta <dbaluta@ixiacom.com>
Applied, but:
> @@ -216,7 +216,7 @@ static struct rtnl_link_stats64 *ipgre_get_stats64(struct net_device *dev,
>
> /* Given src, dst and key, find appropriate for input tunnel. */
>
> -static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
> +static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev,
> __be32 remote, __be32 local,
> __be32 key, __be16 gre_proto)
> {
I had to reindent these function arguments on the lines after the one
you modified so that they continue to line up properly with the column
of the openning parenthesis on the previous line.
Do not blindly make checkpatch fixes without taking into consideration
the indentation modifications necessary in the context around your
change.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox