* Re: [Bridge] [PATCH net-next v4 2/3] bridge: suppress arp pkts on BR_NEIGH_SUPPRESS ports
From: Toshiaki Makita @ 2017-10-04 7:35 UTC (permalink / raw)
To: Roopa Prabhu, davem; +Cc: nikolay, netdev, bridge
In-Reply-To: <1507093953-59929-3-git-send-email-roopa@cumulusnetworks.com>
On 2017/10/04 14:12, Roopa Prabhu wrote:
> From: Roopa Prabhu <roopa@cumulusnetworks.com>
>
> This patch avoids flooding and proxies arp packets
> for BR_NEIGH_SUPPRESS ports.
>
> Moves existing br_do_proxy_arp to br_do_proxy_suppress_arp
> to support both proxy arp and neigh suppress.
>
> Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
> ---
...
> +static void br_arp_send(struct net_bridge_port *p, int type, int ptype,
type and ptype are always the same so seems unnecessary.
> + __be32 dest_ip, struct net_device *dev,
> + __be32 src_ip, const unsigned char *dest_hw,
> + const unsigned char *src_hw,
> + const unsigned char *target_hw,
> + __be16 vlan_proto, u16 vlan_tci)
> +{
> + struct sk_buff *skb;
> +
> + netdev_dbg(dev, "arp send dev %s dst %pI4 dst_hw %pM src %pI4 src_hw %pM\n",
> + dev->name, &dest_ip, dest_hw, &src_ip, src_hw);
> +
> + if (!vlan_tci) {
> + arp_send(type, ptype, dest_ip, dev, src_ip,
> + dest_hw, src_hw, target_hw);
I may be missing something, but wouldn't it send arp reply from the
bridge device, while it should be received to the bridge device, when p
== NULL?
> + return;
> + }
> +
> + skb = arp_create(type, ptype, dest_ip, dev, src_ip,
> + dest_hw, src_hw, target_hw);
> + if (!skb)
> + return;
> +
> + if (p) {
Why doesn't bridge device consider pvid?
> + struct net_bridge_vlan_group *vg;
> + u16 pvid;
> +
> + vg = nbp_vlan_group_rcu(p);
> + pvid = br_get_pvid(vg);
> + if (pvid == vlan_tci)
Need vlan_tci & VLAN_VID_MASK
Or use skb_vlan_tag_get_id() in caller side.
> + vlan_tci = 0;
> + }
> +
> + if (vlan_tci) {
> + skb = vlan_insert_tag_set_proto(skb, vlan_proto,
> + vlan_tci);
Should be __vlan_hwaccel_put_tag()
> + if (!skb) {
> + net_err_ratelimited("%s: failed to insert VLAN tag\n",
> + __func__);
> + return;
> + }
> + }
> +
> + arp_xmit(skb);
> +}
...
> +void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
> + u16 vid, struct net_bridge_port *p)
> +{
...
> + if (br->neigh_suppress_enabled) {
> + if (p && (p->flags & BR_NEIGH_SUPPRESS))
> + return;
> + if (ipv4_is_zeronet(sip) || sip == tip) {
> + /* prevent flooding to neigh suppress ports */
> + BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
> + return;
> + }
> + }
> +
> + if (parp->ar_op != htons(ARPOP_REQUEST))
> + return;
> +
> + if (vid != 0) {
vid should be 0 if untagged is set on the bridge device?
> + vlandev = __vlan_find_dev_deep_rcu(br->dev, skb->vlan_proto,
> + vid);
> + if (!vlandev)
> + return;
> + }
> +
> + if (br->neigh_suppress_enabled && br_is_local_ip(vlandev, tip)) {
> + /* its our local ip, so don't proxy reply
> + * and don't forward to neigh suppress ports
> + */
> + BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
> + return;
> + }
--
Toshiaki Makita
^ permalink raw reply
* Re: [PATCH net-next v4 1/3] bridge: add new BR_NEIGH_SUPPRESS port flag to suppress arp and nd flood
From: Toshiaki Makita @ 2017-10-04 7:21 UTC (permalink / raw)
To: Roopa Prabhu; +Cc: nikolay, netdev, bridge, davem
In-Reply-To: <1507093953-59929-2-git-send-email-roopa@cumulusnetworks.com>
On 2017/10/04 14:12, Roopa Prabhu wrote:
> From: Roopa Prabhu <roopa@cumulusnetworks.com>
>
> This patch adds a new bridge port flag BR_NEIGH_SUPPRESS to
> suppress arp and nd flood on bridge ports. It implements
> rfc7432, section 10.
> https://tools.ietf.org/html/rfc7432#section-10
> for ethernet VPN deployments. It is similar to the existing
> BR_ARP_PROXY flag but has a few semantic differences to conform
> to EVPN standard. In case of EVPN, it is mainly used to
> avoid flooding to tunnel ports like vxlan. Unlike the existing
> flags it suppresses flood of all neigh discovery packets
> (arp, nd) to tunnel ports.
>
> This patch adds netlink and sysfs support to set this bridge port
> flag.
>
> Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
> ---
...
> diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
> index dea88a2..d8c2706 100644
> --- a/net/bridge/br_netlink.c
> +++ b/net/bridge/br_netlink.c
> @@ -138,6 +138,7 @@ static inline size_t br_port_info_size(void)
> + nla_total_size(1) /* IFLA_BRPORT_PROXYARP */
> + nla_total_size(1) /* IFLA_BRPORT_PROXYARP_WIFI */
> + nla_total_size(1) /* IFLA_BRPORT_VLAN_TUNNEL */
> + + nla_total_size(1) /* IFLA_BRPORT_NEIGH_SUPPRESS */
> + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_ROOT_ID */
> + nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_BRIDGE_ID */
> + nla_total_size(sizeof(u16)) /* IFLA_BRPORT_DESIGNATED_PORT */
> @@ -210,7 +211,9 @@ static int br_port_fill_attrs(struct sk_buff *skb,
> nla_put_u8(skb, IFLA_BRPORT_CONFIG_PENDING, p->config_pending) ||
> nla_put_u8(skb, IFLA_BRPORT_VLAN_TUNNEL, !!(p->flags &
> BR_VLAN_TUNNEL)) ||
> - nla_put_u16(skb, IFLA_BRPORT_GROUP_FWD_MASK, p->group_fwd_mask))
> + nla_put_u16(skb, IFLA_BRPORT_GROUP_FWD_MASK, p->group_fwd_mask) ||
> + nla_put_u8(skb, IFLA_BRPORT_NEIGH_SUPPRESS, !!(p->flags &
> + BR_NEIGH_SUPPRESS)))
Wouldn't it be better to make the indentation like this?
... !!(p->flags &
BR_NEIGH_SUPPRESS)))
> return -EMSGSIZE;
>
> timerval = br_timer_value(&p->message_age_timer);
> @@ -692,6 +695,7 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
> {
> unsigned long old_flags = p->flags;
> bool br_vlan_tunnel_old = false;
> + int neigh_suppress_old = 0;
> int err;
>
> err = br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
> @@ -785,6 +789,12 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
> p->group_fwd_mask = fwd_mask;
> }
>
> + neigh_suppress_old = (p->flags & BR_NEIGH_SUPPRESS);
> + br_set_port_flag(p, tb, IFLA_BRPORT_NEIGH_SUPPRESS,
> + BR_NEIGH_SUPPRESS);
> + if (neigh_suppress_old != (p->flags & BR_NEIGH_SUPPRESS))
> + br_recalculate_neigh_suppress_enabled(p->br);
> +
You are calling br_recalculate_neigh_suppress_enabled() from within
br_port_flags_change() immediately after this.
I think you can just call br_set_port_flag() here.
> br_port_flags_change(p, old_flags ^ p->flags);
> return 0;
> }
--
Toshiaki Makita
^ permalink raw reply
* etsec2 attached to sgmii phy
From: Jörg Willmann @ 2017-10-04 5:56 UTC (permalink / raw)
To: netdev
Hi,
we use a QorIQ P1011 connected via SGMII to a switch (Marvell 88E6352).
Currently we still use a really old linux kernel (2.6.33) successfully.
For configuration of the MDIO Bus attached to the corresponding eTSEC/TBI
Phy we use the following settings in the device tree:
mdio@25000 {
#address-cells = <0x1>;
#size-cells = <0x0>;
compatible = "fsl,etsec2-tbi";
reg = <0x25000 0x1000 0xb1030 0x4>;
tbi-phy@11 {
reg = <0x11>;
device_type = "tbi-phy";
linux,phandle = <0x5>;
phandle = <0x5>;
};
};
First resource in the mdio config is the base address of the MDIO bus, the
second resource defines the address of TBIPA.
Doing tests with a newer kernel (4.4.71) I was faced with problems
communicating with the TBIPHY.
Debugging this I found out that TBIPA is no longer parameterized correctly
and I found out why:
In commit afae5ad78b342f401c28b0bb1adb3cd494cb125a initialization of TIBPA
has been changed:
In former versions in get_gfar_tbipa(...) for compatible "etsec2-tbi" the
second resource of the reg entry has been used. But now only first
resource is mapped and get_etsec_tbipa(...) which is now
responsible to return the proper address does not (and has no way due to
missing *np as function argument) do so but returns the first resource
(which is the base address of mdio controller).
What do you think would be the correct way to solve this issue? Re-add *np
to the get_*_tba() functions to be able to return the proper address?
Thank's for reading,
Best regards,
Joerg
^ permalink raw reply
* Re: [PATCH v4 net-next 0/8] flow_dissector: Protocol specific flow dissector offload
From: Jiri Pirko @ 2017-10-04 6:45 UTC (permalink / raw)
To: Tom Herbert
Cc: Tom Herbert, David Miller, Hannes Frederic Sowa,
Linux Kernel Network Developers, Rohit Seth
In-Reply-To: <CAPDqMeq3er9=P9AUFKf4-FcSgthpv2hUz+WTb78DRHGEJ0TTWA@mail.gmail.com>
Tue, Oct 03, 2017 at 08:35:54PM CEST, tom@quantonium.net wrote:
>On Tue, Oct 3, 2017 at 12:46 AM, Jiri Pirko <jiri@resnulli.us> wrote:
>> Fri, Sep 29, 2017 at 07:59:35PM CEST, tom@herbertland.com wrote:
>>>On Fri, Sep 29, 2017 at 10:42 AM, David Miller <davem@davemloft.net> wrote:
>>>> From: Tom Herbert <tom@herbertland.com>
>>>> Date: Fri, 29 Sep 2017 08:48:55 -0700
>>>>
>>>>> The flow_dissector interface is not a uAPI.
>>>>
>>>> That's not true, insofar as cls_flower.c uses the flow_dissector
>>>> therefore if you change the flow_dissector in certain ways then
>>>> cls_flower.c might have it's behavior changed and that is in fact UAPI
>>>> facing.
>>>
>>>Then I would suggest adding another flag like FLOW_DISSECTOR_F_FLOWER
>>>and when anyone puts new code into flow_dissector they can wrap it
>>>with "if !(flags & FLOW_DISSECTOR_F_FLOWER)". If the flower uAPI is
>>>subsequently update then the conditional can be removed. This way
>>>flower can support maintain its APIs, but we can still still extend
>>>and improve flow_dissector for othersuse cases.
>>
>> This is not flower-specific problem. Flow_dissector is a servant of many.
>
>Besides flower, what other use cases of flow_dissector have made
>flow_dissector interface a uAPI? Any use of hashing does not do this.
>Maybe OVS does?
It may be that currently it affects only flower. That does not mean you
should add flower-specific quirk. All I say is this should be handled in
a generic way, independent on the caller.
>
>> As such, it is instructed what should it do. If you want to
>> change the way inner headers are parsed, you should either:
>
>Why would that only affect the way inner headers are parsed? Wouldn't
>we need to consider any change to flow_dissector that might affect the
>output in any way. For instance, the depth limits I added would change
>to output for someone that was parsing thirty-five layers of
>encapsulation so it it looks like that feature needs a flag. What if
>someone adds a new Ethernet protocol or a new encap protocol?
Sure, what I ment was any change of behaviour.
>
>> 1) change the callers so they are behaving the same as before
>> 2) make the flow_dissection change optional so the caller can say if he
>> wants original or new behaviour.
>
>I guess we can do that, but am concerned about the overhead this will
>generate if were adding a flag each time anyone modifies the function.
>There are performance critical use cases of flow_dissector that will
>be impacted by such changes.
I don't think that the overhead would be much different from what you
proposed.
>
>Tom
>
>
>>
^ permalink raw reply
* Re: [PATCH net-next 5/7] net: bonding: Add extack messages for some enslave failures
From: Jiri Pirko @ 2017-10-04 6:38 UTC (permalink / raw)
To: David Ahern
Cc: netdev, j.vosburgh, vfalico, andy, jiri, idosch, davem, bridge
In-Reply-To: <1507093134-20406-6-git-send-email-dsahern@gmail.com>
Wed, Oct 04, 2017 at 06:58:52AM CEST, dsahern@gmail.com wrote:
>A number of bond_enslave errors are logged using the netdev_err API.
>Return those messages to userspace via the extack facility.
>
>Signed-off-by: David Ahern <dsahern@gmail.com>
>---
> drivers/net/bonding/bond_main.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
>diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
>index bc92307c2082..6688dc9154e0 100644
>--- a/drivers/net/bonding/bond_main.c
>+++ b/drivers/net/bonding/bond_main.c
>@@ -1348,12 +1348,15 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
>
> /* already in-use? */
> if (netdev_is_rx_handler_busy(slave_dev)) {
>+ NL_SET_ERR_MSG(extack,
>+ "Device is in use and cannot be enslaved");
Please don't do this kind of wrapping. Just let the string be on the
same line.
^ permalink raw reply
* Re: [next-queue PATCH v4 3/4] net/sched: Introduce Credit Based Shaper (CBS) qdisc
From: Jiri Pirko @ 2017-10-04 6:36 UTC (permalink / raw)
To: Vinicius Costa Gomes
Cc: netdev, intel-wired-lan, jhs, xiyou.wangcong, andre.guedes,
ivan.briano, jesus.sanchez-palencia, boon.leong.ong,
richardcochran, henrik, levipearson, rodney.cummings
In-Reply-To: <20171004002831.18371-4-vinicius.gomes@intel.com>
Wed, Oct 04, 2017 at 02:28:30AM CEST, vinicius.gomes@intel.com wrote:
>This queueing discipline implements the shaper algorithm defined by
>the 802.1Q-2014 Section 8.6.8.2 and detailed in Annex L.
>
>It's primary usage is to apply some bandwidth reservation to user
>defined traffic classes, which are mapped to different queues via the
>mqprio qdisc.
>
>Initially, it only supports offloading the traffic shaping work to
>supporting controllers.
>
>Later, when a software implementation is added, the current dependency
>on being installed "under" mqprio can be lifted.
>
>Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
>Signed-off-by: Jesus Sanchez-Palencia <jesus.sanchez-palencia@intel.com>
>---
> include/linux/netdevice.h | 1 +
> include/net/pkt_sched.h | 9 ++
> include/uapi/linux/pkt_sched.h | 17 ++++
> net/sched/Kconfig | 11 ++
> net/sched/Makefile | 1 +
> net/sched/sch_cbs.c | 225 +++++++++++++++++++++++++++++++++++++++++
> 6 files changed, 264 insertions(+)
> create mode 100644 net/sched/sch_cbs.c
>
>diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
>index e1d6ef130611..b8798adc214f 100644
>--- a/include/linux/netdevice.h
>+++ b/include/linux/netdevice.h
>@@ -775,6 +775,7 @@ enum tc_setup_type {
> TC_SETUP_CLSFLOWER,
> TC_SETUP_CLSMATCHALL,
> TC_SETUP_CLSBPF,
>+ TC_SETUP_CBS,
Please split this into 2 patches. One will introduce the new qdisc,
second will add offload capabilities.
[...]
>+static struct Qdisc_ops cbs_qdisc_ops __read_mostly = {
>+ .next = NULL,
>+ .id = "cbs",
>+ .priv_size = sizeof(struct cbs_sched_data),
>+ .enqueue = cbs_enqueue,
>+ .dequeue = qdisc_dequeue_head,
>+ .peek = qdisc_peek_dequeued,
>+ .init = cbs_init,
>+ .reset = qdisc_reset_queue,
>+ .destroy = cbs_destroy,
>+ .change = cbs_change,
>+ .dump = cbs_dump,
>+ .owner = THIS_MODULE,
>+};
I don't see a software implementation for this. Looks like you are
trying abuse tc subsystem to bypass kernel. Could you please explain
this? The golden rule is: implement in kernel, then offload.
^ permalink raw reply
* Re: [PATCH] net: dsa: mv88e6xxx: rework in-chip bridging
From: Greg Ungerer @ 2017-10-04 6:20 UTC (permalink / raw)
To: Vivien Didelot; +Cc: netdev@vger.kernel.org, Andrew Lunn, Florian Fainelli
[-- Attachment #1: Type: text/plain, Size: 4610 bytes --]
Hi Vivien,
On Wed, Mar 29, 2017 at 04:30:16PM -0400, Vivien Didelot wrote:
> All ports -- internal and external, for chips featuring a PVT -- have a
> mask restricting to which internal ports a frame is allowed to egress.
>
> Now that DSA exposes the number of ports and their bridge devices, it is
> possible to extract the code generating the VLAN map and make it generic
> so that it can be shared later with the cross-chip bridging code.
This patch changes the behavior of interfaces on startup if they are
not part of a bridge.
I have a board with a Marvell 6350 switch with a device tree that sets
up the 5 ports as lan1, lan2, lan3, lan4, wan. With kernels before
this patch (so linux-4.12 and older) after system startup I could do:
ifconfig lan1 192.168.0.1
And then ping out that interface with no problems.
After this patch is applied (effects linux-4.13 and newer) then the
ping fails:
PING 192.168.0.22 (192.168.0.22) 56(84) bytes of data.
From 192.168.0.1 icmp_seq=1 Destination Host Unreachable
From 192.168.0.1 icmp_seq=2 Destination Host Unreachable
From 192.168.0.1 icmp_seq=3 Destination Host Unreachable
If I incorporate an interface into a bridge then it all works ok.
So simply:
brctl addbr br0
brctl addif br0 lan1
ifconfig lan1 up
ifconfig br0 192.168.0.1
Then pings out work as expected. And if I now remove that lan1
interface from the bridge and use it alone again then it will
now work ok:
ifconfig br0 down
brctl delif br0 lan1
ifconfig lan1 192.168.0.1
And that now pings ok.
I fixed this with the attached patch. It is probably not the correct
approach, but it does restore the older behavior.
What do you think?
Regards
Greg
> Signed-off-by: Vivien Didelot <vivien.dide...@savoirfairelinux.com>
> ---
> drivers/net/dsa/mv88e6xxx/chip.c | 53 ++++++++++++++++++++++++++--------------
> 1 file changed, 34 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
> index b114bf8e6a11..e5165831e8b5 100644
> --- a/drivers/net/dsa/mv88e6xxx/chip.c
> +++ b/drivers/net/dsa/mv88e6xxx/chip.c
> @@ -1123,27 +1123,42 @@ static int mv88e6xxx_set_eee(struct dsa_switch *ds, int
> port,
> return err;
> }
>
> +static u16 mv88e6xxx_port_vlan(struct mv88e6xxx_chip *chip, int dev, int port)
> +{
> + struct dsa_switch *ds = NULL;
> + struct net_device *br;
> + u16 pvlan;
> + int i;
> +
> + if (dev < DSA_MAX_SWITCHES)
> + ds = chip->ds->dst->ds[dev];
> +
> + /* Prevent frames from unknown switch or port */
> + if (!ds || port >= ds->num_ports)
> + return 0;
> +
> + /* Frames from DSA links and CPU ports can egress any local port */
> + if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
> + return mv88e6xxx_port_mask(chip);
> +
> + br = ds->ports[port].bridge_dev;
> + pvlan = 0;
> +
> + /* Frames from user ports can egress any local DSA links and CPU ports,
> + * as well as any local member of their bridge group.
> + */
> + for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
> + if (dsa_is_cpu_port(chip->ds, i) ||
> + dsa_is_dsa_port(chip->ds, i) ||
> + (br && chip->ds->ports[i].bridge_dev == br))
> + pvlan |= BIT(i);
> +
> + return pvlan;
> +}
> +
> static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int
> port)
> {
> - struct dsa_switch *ds = chip->ds;
> - struct net_device *bridge = ds->ports[port].bridge_dev;
> - u16 output_ports = 0;
> - int i;
> -
> - /* allow CPU port or DSA link(s) to send frames to every port */
> - if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) {
> - output_ports = ~0;
> - } else {
> - for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
> - /* allow sending frames to every group member */
> - if (bridge && ds->ports[i].bridge_dev == bridge)
> - output_ports |= BIT(i);
> -
> - /* allow sending frames to CPU port and DSA link(s) */
> - if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
> - output_ports |= BIT(i);
> - }
> - }
> + u16 output_ports = mv88e6xxx_port_vlan(chip, chip->ds->index, port);
>
> /* prevent frames from going back out of the port they came in on */
> output_ports &= ~BIT(port);
> --
[-- Attachment #2: 0001-linux-dsa-fix-first-use-port-breakage.patch --]
[-- Type: text/x-patch, Size: 1545 bytes --]
>From d81c15dda9fd84895caa67e4c187ad0b6b33af1f Mon Sep 17 00:00:00 2001
From: Greg Ungerer <gerg@linux-m68k.org>
Date: Thu, 21 Sep 2017 13:35:35 +1000
Subject: [PATCH] net: dsa: mv88e6xxx: fix first-use port breakage
The very first time you configure a switch port for use - as a stand alone
port - the interface cannot pass packets. If you configure the interface
as part of a bridge it works. If you then remove it from the bridge and
again try to use it as a stand alone port it will now work.
Commit e5887a2a11094 ("net: dsa: mv88e6xxx: rework in-chip bridging")
changes the switch initialization code and introduces the different
behavior.
To fix I changed the initialization behavior to make it similar to the
older code for the case at system startup (before all data structures
associated with this switch device have been fully setup).
Signed-off-by: Greg Ungerer <gerg@linux-m68k.org>
---
drivers/net/dsa/mv88e6xxx/chip.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 929b62c..38527e0 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -911,8 +911,11 @@ static u16 mv88e6xxx_port_vlan(struct mv88e6xxx_chip *chip, int dev, int port)
u16 pvlan;
int i;
- if (dev < DSA_MAX_SWITCHES)
+ if (dev < DSA_MAX_SWITCHES) {
ds = chip->ds->dst->ds[dev];
+ if (ds == NULL)
+ ds = chip->ds;
+ }
/* Prevent frames from unknown switch or port */
if (!ds || port >= ds->num_ports)
--
1.9.1
^ permalink raw reply related
* Re: [PATCH RESEND net 0/9] Fixes, cleanup and modernization for some legacy ethernet NIC drivers
From: Finn Thain @ 2017-10-04 6:16 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-kernel
In-Reply-To: <20171003.214121.339749620339054592.davem@davemloft.net>
On Tue, 3 Oct 2017, David Miller wrote:
> From: Finn Thain <fthain@telegraphics.com.au>
> Date: Mon, 2 Oct 2017 21:07:17 -0400 (EDT)
>
> > This patch series fixes some logging bugs and adds some missing
> > message severity levels.
> >
> > There are also cleanup patches for dead code and some Kconfig cruft.
> >
> > Custom debug message logging is converted to netif_* calls to reduce
> > code duplication.
> >
> > All up, about 150 lines of code are eliminated.
> >
> > My apologies for duplicated messages. I messed up the addressing.
>
> Finn, I'm finding real bugs in this series and seriously if you cannot
> test these changes in some way please leave this code alone.
>
Well, this series has been tested on SONIC, MACE and 8390 devices. I do
have 89x0 hardware but it is stored elsewhere and I can't get to it right
now.
> For example, you're removing the "once_is_enough" logic from
> mac89x0_probe().
>
> But you can't do that.
I take your point. I overlooked the Space.c logic. But that's not the
whole story here.
> The probe function can in fact be called multiple times, from
> drivers/net/Space.c It gets called in a loop iterating over different
> 'unit' argument values.
>
Testing shows that mac8390 doesn't probe any devices unless it is modular.
In the CONFIG_MAC8390=m case, the mac8390_probe() call in Space.c is
elided by '#ifdef CONFIG_MAC8390' and the device gets probed by
init_module() instead. (And the binaries published in the Debian archive
and the mac68k project on sourceforge all use CONFIG_MAC8390=m and
CONFIG_MAC89x0=m.)
In the CONFIG_MAC8390=y case, no device is probed (for some reason). This
test result suggests that the probe function is not actually called. Its
safe to assume that mac89x0 has the same problem as mac8390, and it
follows that the once_is_enough logic is redundant. At least, that was my
thinking when I made the change; that is, init_module() must be the only
caller of the probe function.
BTW, mac8390 does this,
if (slots & (1 << ndev->board->slot))
continue;
which is equivalent to the once_is_enough test, and I went looking for
some way to avoid this too.
Anyway, I see now that changing the once_is_enough logic is wrong. First
the bug has to be found or else bus matching implemented for nubus
drivers.
> Unless you're making stylistic changes where you can prove the object
> code resulting is still the same, you really should not be playing with
> fire by trying to remove "dead code" like this in legacy drivers you
> cannot fully test.
>
I agree, and that's why I've been careful with any code I cannot test
(like xtsonic) by making only changes that I can test (with macsonic).
I should have added tested-by tags...
> Thank you.
>
Thanks for your review. I will revert the once_is_enough change, describe
the testing better and re-submit.
--
^ permalink raw reply
* etsec2 attached to sgmii phy
From: Jörg Willmann @ 2017-10-04 5:50 UTC (permalink / raw)
To: netdev
[-- Attachment #1: Type: text/plain, Size: 1967 bytes --]
Hi,
we use a QorIQ P1011 connected via SGMII to a switch (Marvell 88E6352).
Currently we still use a really old linux kernel (2.6.33) successfully.
For configuration of the MDIO Bus attached to the corresponding eTSEC/TBI
Phy we use the following settings in the device tree:
mdio@25000 {
#address-cells = <0x1>;
#size-cells = <0x0>;
compatible = "fsl,etsec2-tbi";
reg = <0x25000 0x1000 0xb1030 0x4>;
tbi-phy@11 {
reg = <0x11>;
device_type = "tbi-phy";
linux,phandle = <0x5>;
phandle = <0x5>;
};
};
First resource in the mdio config is the base address of the MDIO bus, the
second resource defines the address of TBIPA.
Doing tests with a newer kernel (4.4.71) I was faced with problems
communicating with the TBIPHY.
Debugging this I found out that TBIPA is no longer parameterized correctly
and I found out why:
In commit afae5ad78b342f401c28b0bb1adb3cd494cb125a initialization of TIBPA
has been changed:
In former versions in get_gfar_tbipa(...) for compatible "etsec2-tbi" the
second resource of the reg entry has been used. But now only first resource
is mapped and get_etsec_tbipa(...) which is now responsible to return the
proper address does not (and has no way due to missing *np as function
argument) do so but returns the first resource (which is the base
address of mdio controller).
What do you think would be the correct way to solve this issue? Re-add *np
to the get_*_tba() functions to be able to return the proper address?
Thank’s for reading,
Best regards,
Joerg
^ permalink raw reply
* (unknown),
From: morice.diane @ 2017-10-04 5:56 UTC (permalink / raw)
To: netdev
[-- Attachment #1: 85708430384537.zip --]
[-- Type: application/zip, Size: 7217 bytes --]
^ permalink raw reply
* Re: [PATCH net] net: fib_rules: Fix fib_rules_ops->compare implementations to support exact match
From: Shmulik Ladkani @ 2017-10-04 5:34 UTC (permalink / raw)
To: David Miller, dsa
Cc: netdev, mateusz.bajorski, tgraf, shmulik.ladkani, eyal.birger
In-Reply-To: <20171003.145418.677435703318514230.davem@davemloft.net>
Hi David,
On Tue, 03 Oct 2017 14:54:18 -0700 (PDT) David Miller <davem@davemloft.net> wrote:
> I don't see any inconsistency. When you insert using NLM_F_EXCL the
> insertion fails if any existing rule matches or overlaps in any way
> with the keys in the new rule.
Please note that current situation is as follows:
A: Generic (non /0), followed by specific that overlaps, ALLOWED
# ip ru add from 0.0.0.0/1 iif eth2 pref 33 table 33
# ip ru add from 10.0.0.0/8 iif eth2 pref 33 table 33
A Reversed: Specific, followed by generic (non /0) that overlaps, ALLOWED
# ip ru add from 10.0.0.0/8 iif eth2 pref 33 table 33
# ip ru add from 0.0.0.0/1 iif eth2 pref 33 table 33
B: 0.0.0.0/0, followed by specific that overlaps, ALLOWED
# ip ru add from 0.0.0.0/0 iif eth2 pref 33 table 33
# ip ru add from 10.0.0.0/8 iif eth2 pref 33 table 33
B Reversed: Specific, followed by 0.0.0.0/0, FAILS
# ip ru add from 10.0.0.0/8 iif eth2 pref 33 table 33
# ip ru add from 0.0.0.0/0 iif eth2 pref 33 table 33
(File exists)
Is there any reason why 0.0.0.0/0 should be treated differently, meaning,
insertion of 0.0.0.0/0 is order dependant (where other overlapping
rules are allowed REGARDLESS order of insertion)?
Please do note there is absolutely NO "overlapping" detection logic in
'fib4_rule_compare' whatsoever; just strict comparison of the FRA_SRC
addresses.
The only exception is if the new FRA_SRC address is 0.0.0.0/0 - which is
considered "colliding" with ANY existing rule.
The "treat /0 as a collision" existed way prior NLM_F_EXCL enforcement
was introduced, as the single usecase of ->compare() was for DELRULE
which had wildcard semantics.
Alas for NEWRULE+NLM_F_EXCL it exposes the above anomaly.
Best,
Shmulik
^ permalink raw reply
* Re: [PATCH net-next 1/2] tcp: uniform the set up of sockets after successful connection
From: Wei Wang @ 2017-10-04 5:32 UTC (permalink / raw)
To: David Miller
Cc: Linux Kernel Network Developers, Yuchung Cheng, Neal Cardwell,
Eric Dumazet
In-Reply-To: <20171003.212826.427984613713921100.davem@davemloft.net>
On Tue, Oct 3, 2017 at 9:28 PM, David Miller <davem@davemloft.net> wrote:
> From: Wei Wang <weiwan@google.com>
> Date: Mon, 2 Oct 2017 10:01:35 -0700
>
>> @@ -456,6 +456,19 @@ void tcp_init_sock(struct sock *sk)
>> }
>> EXPORT_SYMBOL(tcp_init_sock);
>>
>> +void tcp_init_transfer(struct sock *sk, int bpf_op)
>> +{
>> + struct inet_connection_sock *icsk = inet_csk(sk);
>> +
>> + tcp_mtup_init(sk);
>> + icsk->icsk_af_ops->rebuild_header(sk);
>> + tcp_init_metrics(sk);
>> + tcp_call_bpf(sk, bpf_op);
>> + tcp_init_congestion_control(sk);
>> + tcp_init_buffer_space(sk);
>> +}
>> +EXPORT_SYMBOL(tcp_init_transfer);
>
> This symbol export is unnecessary, and if it were it should
> be EXPORT_SYMBOL_GPL().
I see. This function is only called in the TCP stack. Will remove
EXPORT_SYMBOL() in v2.
^ permalink raw reply
* [PATCH net-next v4 3/3] bridge: suppress nd pkts on BR_NEIGH_SUPPRESS ports
From: Roopa Prabhu @ 2017-10-04 5:12 UTC (permalink / raw)
To: davem; +Cc: netdev, nikolay, stephen, bridge
In-Reply-To: <1507093953-59929-1-git-send-email-roopa@cumulusnetworks.com>
From: Roopa Prabhu <roopa@cumulusnetworks.com>
This patch avoids flooding and proxies ndisc packets
for BR_NEIGH_SUPPRESS ports.
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
net/bridge/br_arp_nd_proxy.c | 246 +++++++++++++++++++++++++++++++++++++++++++
net/bridge/br_device.c | 11 ++
net/bridge/br_input.c | 10 ++
net/bridge/br_private.h | 3 +
4 files changed, 270 insertions(+)
diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c
index 66df55d..791b2dd 100644
--- a/net/bridge/br_arp_nd_proxy.c
+++ b/net/bridge/br_arp_nd_proxy.c
@@ -216,3 +216,249 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
}
}
#endif
+
+#if IS_ENABLED(CONFIG_IPV6)
+struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb, struct nd_msg *msg)
+{
+ struct nd_msg *m;
+
+ m = skb_header_pointer(skb, skb_network_offset(skb) +
+ sizeof(struct ipv6hdr), sizeof(*msg), msg);
+ if (!m)
+ return NULL;
+
+ if (m->icmph.icmp6_code != 0 ||
+ (m->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION &&
+ m->icmph.icmp6_type != NDISC_NEIGHBOUR_ADVERTISEMENT))
+ return NULL;
+
+ return m;
+}
+
+static void br_nd_send(struct net_bridge_port *p, struct sk_buff *request,
+ struct neighbour *n, __be16 vlan_proto, u16 vlan_tci,
+ struct nd_msg *ns)
+{
+ struct net_device *dev = request->dev;
+ struct sk_buff *reply;
+ struct nd_msg *na;
+ struct ipv6hdr *pip6;
+ u8 *daddr;
+ int na_olen = 8; /* opt hdr + ETH_ALEN for target */
+ int ns_olen;
+ int i, len;
+
+ if (!dev)
+ return;
+
+ len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) +
+ sizeof(*na) + na_olen + dev->needed_tailroom;
+
+ reply = alloc_skb(len, GFP_ATOMIC);
+ if (!reply)
+ return;
+
+ reply->protocol = htons(ETH_P_IPV6);
+ reply->dev = dev;
+ skb_reserve(reply, LL_RESERVED_SPACE(dev));
+ skb_push(reply, sizeof(struct ethhdr));
+ skb_set_mac_header(reply, 0);
+
+ daddr = eth_hdr(request)->h_source;
+
+ /* Do we need option processing ? */
+ ns_olen = request->len - (skb_network_offset(request) +
+ sizeof(struct ipv6hdr)) - sizeof(*ns);
+ for (i = 0; i < ns_olen - 1; i += (ns->opt[i + 1] << 3)) {
+ if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) {
+ daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
+ break;
+ }
+ }
+
+ /* Ethernet header */
+ ether_addr_copy(eth_hdr(reply)->h_dest, daddr);
+ ether_addr_copy(eth_hdr(reply)->h_source, n->ha);
+ eth_hdr(reply)->h_proto = htons(ETH_P_IPV6);
+ reply->protocol = htons(ETH_P_IPV6);
+
+ skb_pull(reply, sizeof(struct ethhdr));
+ skb_set_network_header(reply, 0);
+ skb_put(reply, sizeof(struct ipv6hdr));
+
+ /* IPv6 header */
+ pip6 = ipv6_hdr(reply);
+ memset(pip6, 0, sizeof(struct ipv6hdr));
+ pip6->version = 6;
+ pip6->priority = ipv6_hdr(request)->priority;
+ pip6->nexthdr = IPPROTO_ICMPV6;
+ pip6->hop_limit = 255;
+ pip6->daddr = ipv6_hdr(request)->saddr;
+ pip6->saddr = *(struct in6_addr *)n->primary_key;
+
+ skb_pull(reply, sizeof(struct ipv6hdr));
+ skb_set_transport_header(reply, 0);
+
+ na = (struct nd_msg *)skb_put(reply, sizeof(*na) + na_olen);
+
+ /* Neighbor Advertisement */
+ memset(na, 0, sizeof(*na) + na_olen);
+ na->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
+ na->icmph.icmp6_router = 0; /* XXX: should be 1 ? */
+ na->icmph.icmp6_override = 1;
+ na->icmph.icmp6_solicited = 1;
+ na->target = ns->target;
+ ether_addr_copy(&na->opt[2], n->ha);
+ na->opt[0] = ND_OPT_TARGET_LL_ADDR;
+ na->opt[1] = na_olen >> 3;
+
+ na->icmph.icmp6_cksum = csum_ipv6_magic(&pip6->saddr,
+ &pip6->daddr,
+ sizeof(*na) + na_olen,
+ IPPROTO_ICMPV6,
+ csum_partial(na, sizeof(*na) + na_olen, 0));
+
+ pip6->payload_len = htons(sizeof(*na) + na_olen);
+
+ skb_push(reply, sizeof(struct ipv6hdr));
+ skb_push(reply, sizeof(struct ethhdr));
+
+ reply->ip_summed = CHECKSUM_UNNECESSARY;
+
+ if (p) {
+ struct net_bridge_vlan_group *vg;
+ u16 pvid;
+
+ vg = nbp_vlan_group_rcu(p);
+ pvid = br_get_pvid(vg);
+ if (pvid && pvid == vlan_tci)
+ vlan_tci = 0;
+ }
+
+ if (vlan_tci != 0) {
+ reply = vlan_insert_tag_set_proto(reply, vlan_proto, vlan_tci);
+ if (!reply) {
+ net_err_ratelimited("evpn: failed to insert VLAN tag\n");
+ return;
+ }
+ }
+
+ netdev_dbg(dev, "nd send dev %s dst %pI6 dst_hw %pM src %pI6 src_hw %pM\n",
+ dev->name, &pip6->daddr, daddr, &pip6->saddr, n->ha);
+
+ dev_queue_xmit(reply);
+}
+
+static int br_chk_addr_ip6(struct net_device *dev, void *data)
+{
+ struct in6_addr *addr = (struct in6_addr *)data;
+
+ if (ipv6_chk_addr(dev_net(dev), addr, dev, 0))
+ return 1;
+
+ return 0;
+}
+
+static bool br_is_local_ip6(struct net_device *dev, struct in6_addr *addr)
+
+{
+ if (br_chk_addr_ip6(dev, addr))
+ return true;
+
+ /* check if ip is configured on upper dev */
+ if (netdev_walk_all_upper_dev_rcu(dev, br_chk_addr_ip6, addr))
+ return true;
+
+ return false;
+}
+
+void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
+ u16 vid, struct net_bridge_port *p, struct nd_msg *msg)
+{
+ struct net_device *dev = br->dev;
+ struct net_device *vlandev = NULL;
+ struct in6_addr *saddr, *daddr;
+ struct ipv6hdr *iphdr;
+ struct inet6_dev *in6_dev;
+ struct neighbour *n;
+
+ BR_INPUT_SKB_CB(skb)->proxyarp_replied = false;
+
+ if (p && (p->flags & BR_NEIGH_SUPPRESS))
+ return;
+
+ if (msg->icmph.icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT &&
+ !msg->icmph.icmp6_solicited) {
+ /* prevent flooding to neigh suppress ports */
+ BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
+ return;
+ }
+
+ if (msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION)
+ return;
+
+ in6_dev = __in6_dev_get(dev);
+ if (!in6_dev)
+ return;
+
+ iphdr = ipv6_hdr(skb);
+ saddr = &iphdr->saddr;
+ daddr = &iphdr->daddr;
+
+ if (ipv6_addr_any(saddr) || !ipv6_addr_cmp(saddr, daddr)) {
+ /* prevent flooding to neigh suppress ports */
+ BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
+ return;
+ }
+
+ if (vid != 0) {
+ /* build neigh table lookup on the vlan device */
+ vlandev = __vlan_find_dev_deep_rcu(br->dev, skb->vlan_proto,
+ vid);
+ if (!vlandev)
+ return;
+ } else {
+ vlandev = dev;
+ }
+
+ if (br_is_local_ip6(vlandev, &msg->target)) {
+ /* its our own ip, so don't proxy reply
+ * and don't forward to arp suppress ports
+ */
+ BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
+ return;
+ }
+
+ n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, vlandev);
+ if (n) {
+ struct net_bridge_fdb_entry *f;
+
+ if (!(n->nud_state & NUD_VALID)) {
+ neigh_release(n);
+ return;
+ }
+
+ f = br_fdb_find_rcu(br, n->ha, vid);
+ if (f) {
+ bool replied = false;
+
+ if (f->dst && (f->dst->flags & BR_NEIGH_SUPPRESS)) {
+ if (vid != 0)
+ br_nd_send(p, skb, n, skb->vlan_proto,
+ skb_vlan_tag_get(skb), msg);
+ else
+ br_nd_send(p, skb, n, 0, 0, msg);
+ replied = true;
+ }
+
+ /* If we have replied or as long as we know the
+ * mac, indicate to NEIGH_SUPPRESS ports that we
+ * have replied
+ */
+ if (replied || br->neigh_suppress_enabled)
+ BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
+ }
+ neigh_release(n);
+ }
+}
+#endif
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 53d1456..c85345a 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -69,6 +69,17 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
eth->h_proto == htons(ETH_P_RARP)) &&
br->neigh_suppress_enabled) {
br_do_proxy_suppress_arp(skb, br, vid, NULL);
+ } else if (IS_ENABLED(CONFIG_IPV6) &&
+ skb->protocol == htons(ETH_P_IPV6) &&
+ br->neigh_suppress_enabled &&
+ pskb_may_pull(skb, sizeof(struct ipv6hdr) +
+ sizeof(struct nd_msg)) &&
+ ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) {
+ struct nd_msg *msg, _msg;
+
+ msg = br_is_nd_neigh_msg(skb, &_msg);
+ if (msg)
+ br_do_suppress_nd(skb, br, vid, NULL, msg);
}
dest = eth_hdr(skb)->h_dest;
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 4b8d2ec..013b65f 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -119,6 +119,16 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
(skb->protocol == htons(ETH_P_ARP) ||
skb->protocol == htons(ETH_P_RARP))) {
br_do_proxy_suppress_arp(skb, br, vid, p);
+ } else if (IS_ENABLED(CONFIG_IPV6) && br->neigh_suppress_enabled &&
+ skb->protocol == htons(ETH_P_IPV6) &&
+ pskb_may_pull(skb, sizeof(struct ipv6hdr) +
+ sizeof(struct nd_msg)) &&
+ ipv6_hdr(skb)->nexthdr == IPPROTO_ICMPV6) {
+ struct nd_msg *msg, _msg;
+
+ msg = br_is_nd_neigh_msg(skb, &_msg);
+ if (msg)
+ br_do_suppress_nd(skb, br, vid, p, msg);
}
switch (pkt_type) {
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index bb095dc..f6936e9 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1143,4 +1143,7 @@ static inline void br_switchdev_frame_unmark(struct sk_buff *skb)
void br_recalculate_neigh_suppress_enabled(struct net_bridge *br);
void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
u16 vid, struct net_bridge_port *p);
+void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
+ u16 vid, struct net_bridge_port *p, struct nd_msg *msg);
+struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb, struct nd_msg *m);
#endif
--
2.1.4
^ permalink raw reply related
* [PATCH net-next v4 2/3] bridge: suppress arp pkts on BR_NEIGH_SUPPRESS ports
From: Roopa Prabhu @ 2017-10-04 5:12 UTC (permalink / raw)
To: davem; +Cc: netdev, nikolay, stephen, bridge
In-Reply-To: <1507093953-59929-1-git-send-email-roopa@cumulusnetworks.com>
From: Roopa Prabhu <roopa@cumulusnetworks.com>
This patch avoids flooding and proxies arp packets
for BR_NEIGH_SUPPRESS ports.
Moves existing br_do_proxy_arp to br_do_proxy_suppress_arp
to support both proxy arp and neigh suppress.
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
net/bridge/br_arp_nd_proxy.c | 186 +++++++++++++++++++++++++++++++++++++++++++
net/bridge/br_device.c | 9 +++
net/bridge/br_input.c | 63 ++-------------
net/bridge/br_private.h | 3 +
4 files changed, 203 insertions(+), 58 deletions(-)
diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c
index f889ad5..66df55d 100644
--- a/net/bridge/br_arp_nd_proxy.c
+++ b/net/bridge/br_arp_nd_proxy.c
@@ -14,6 +14,13 @@
*/
#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/neighbour.h>
+#include <net/arp.h>
+#include <linux/if_vlan.h>
+#include <linux/inetdevice.h>
+#include <net/addrconf.h>
#include "br_private.h"
void br_recalculate_neigh_suppress_enabled(struct net_bridge *br)
@@ -30,3 +37,182 @@ void br_recalculate_neigh_suppress_enabled(struct net_bridge *br)
br->neigh_suppress_enabled = neigh_suppress;
}
+
+#if IS_ENABLED(CONFIG_INET)
+static void br_arp_send(struct net_bridge_port *p, int type, int ptype,
+ __be32 dest_ip, struct net_device *dev,
+ __be32 src_ip, const unsigned char *dest_hw,
+ const unsigned char *src_hw,
+ const unsigned char *target_hw,
+ __be16 vlan_proto, u16 vlan_tci)
+{
+ struct sk_buff *skb;
+
+ netdev_dbg(dev, "arp send dev %s dst %pI4 dst_hw %pM src %pI4 src_hw %pM\n",
+ dev->name, &dest_ip, dest_hw, &src_ip, src_hw);
+
+ if (!vlan_tci) {
+ arp_send(type, ptype, dest_ip, dev, src_ip,
+ dest_hw, src_hw, target_hw);
+ return;
+ }
+
+ skb = arp_create(type, ptype, dest_ip, dev, src_ip,
+ dest_hw, src_hw, target_hw);
+ if (!skb)
+ return;
+
+ if (p) {
+ struct net_bridge_vlan_group *vg;
+ u16 pvid;
+
+ vg = nbp_vlan_group_rcu(p);
+ pvid = br_get_pvid(vg);
+ if (pvid == vlan_tci)
+ vlan_tci = 0;
+ }
+
+ if (vlan_tci) {
+ skb = vlan_insert_tag_set_proto(skb, vlan_proto,
+ vlan_tci);
+ if (!skb) {
+ net_err_ratelimited("%s: failed to insert VLAN tag\n",
+ __func__);
+ return;
+ }
+ }
+
+ arp_xmit(skb);
+}
+
+static int br_chk_addr_ip(struct net_device *dev, void *data)
+{
+ __be32 ip = *(__be32 *)data;
+ struct in_device *in_dev;
+ __be32 addr = 0;
+
+ in_dev = __in_dev_get_rcu(dev);
+ if (in_dev)
+ addr = inet_confirm_addr(dev_net(dev), in_dev, 0, ip,
+ RT_SCOPE_HOST);
+
+ if (addr == ip)
+ return 1;
+
+ return 0;
+}
+
+static bool br_is_local_ip(struct net_device *dev, __be32 ip)
+{
+ if (br_chk_addr_ip(dev, &ip))
+ return true;
+
+ /* check if ip is configured on upper dev */
+ if (netdev_walk_all_upper_dev_rcu(dev, br_chk_addr_ip, &ip))
+ return true;
+
+ return false;
+}
+
+void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
+ u16 vid, struct net_bridge_port *p)
+{
+ struct net_device *dev = br->dev;
+ struct net_device *vlandev = dev;
+ struct neighbour *n;
+ struct arphdr *parp;
+ u8 *arpptr, *sha;
+ __be32 sip, tip;
+
+ BR_INPUT_SKB_CB(skb)->proxyarp_replied = false;
+
+ if ((dev->flags & IFF_NOARP) ||
+ !pskb_may_pull(skb, arp_hdr_len(dev)))
+ return;
+
+ parp = arp_hdr(skb);
+
+ if (parp->ar_pro != htons(ETH_P_IP) ||
+ parp->ar_hln != dev->addr_len ||
+ parp->ar_pln != 4)
+ return;
+
+ arpptr = (u8 *)parp + sizeof(struct arphdr);
+ sha = arpptr;
+ arpptr += dev->addr_len; /* sha */
+ memcpy(&sip, arpptr, sizeof(sip));
+ arpptr += sizeof(sip);
+ arpptr += dev->addr_len; /* tha */
+ memcpy(&tip, arpptr, sizeof(tip));
+
+ if (ipv4_is_loopback(tip) ||
+ ipv4_is_multicast(tip))
+ return;
+
+ if (br->neigh_suppress_enabled) {
+ if (p && (p->flags & BR_NEIGH_SUPPRESS))
+ return;
+ if (ipv4_is_zeronet(sip) || sip == tip) {
+ /* prevent flooding to neigh suppress ports */
+ BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
+ return;
+ }
+ }
+
+ if (parp->ar_op != htons(ARPOP_REQUEST))
+ return;
+
+ if (vid != 0) {
+ vlandev = __vlan_find_dev_deep_rcu(br->dev, skb->vlan_proto,
+ vid);
+ if (!vlandev)
+ return;
+ }
+
+ if (br->neigh_suppress_enabled && br_is_local_ip(vlandev, tip)) {
+ /* its our local ip, so don't proxy reply
+ * and don't forward to neigh suppress ports
+ */
+ BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
+ return;
+ }
+
+ n = neigh_lookup(&arp_tbl, &tip, vlandev);
+ if (n) {
+ struct net_bridge_fdb_entry *f;
+
+ if (!(n->nud_state & NUD_VALID)) {
+ neigh_release(n);
+ return;
+ }
+
+ f = br_fdb_find_rcu(br, n->ha, vid);
+ if (f) {
+ bool replied = false;
+
+ if ((p && (p->flags & BR_PROXYARP)) ||
+ (f->dst && (f->dst->flags & (BR_PROXYARP_WIFI |
+ BR_NEIGH_SUPPRESS)))) {
+ if (!vid)
+ br_arp_send(p, ARPOP_REPLY, ETH_P_ARP,
+ sip, skb->dev, tip, sha,
+ n->ha, sha, 0, 0);
+ else
+ br_arp_send(p, ARPOP_REPLY, ETH_P_ARP,
+ sip, skb->dev, tip, sha,
+ n->ha, sha, skb->vlan_proto,
+ skb_vlan_tag_get(skb));
+ replied = true;
+ }
+
+ /* If we have replied or as long as we know the
+ * mac, indicate to arp replied
+ */
+ if (replied || br->neigh_suppress_enabled)
+ BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
+ }
+
+ neigh_release(n);
+ }
+}
+#endif
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index f6b6a92..53d1456 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -39,6 +39,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
struct pcpu_sw_netstats *brstats = this_cpu_ptr(br->stats);
const struct nf_br_ops *nf_ops;
const unsigned char *dest;
+ struct ethhdr *eth;
u16 vid = 0;
rcu_read_lock();
@@ -57,11 +58,19 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
BR_INPUT_SKB_CB(skb)->brdev = dev;
skb_reset_mac_header(skb);
+ eth = eth_hdr(skb);
skb_pull(skb, ETH_HLEN);
if (!br_allowed_ingress(br, br_vlan_group_rcu(br), skb, &vid))
goto out;
+ if (IS_ENABLED(CONFIG_INET) &&
+ (eth->h_proto == htons(ETH_P_ARP) ||
+ eth->h_proto == htons(ETH_P_RARP)) &&
+ br->neigh_suppress_enabled) {
+ br_do_proxy_suppress_arp(skb, br, vid, NULL);
+ }
+
dest = eth_hdr(skb)->h_dest;
if (is_broadcast_ether_addr(dest)) {
br_flood(br, skb, BR_PKT_BROADCAST, false, true);
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 7cb6137..4b8d2ec 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -71,62 +71,6 @@ static int br_pass_frame_up(struct sk_buff *skb)
br_netif_receive_skb);
}
-static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br,
- u16 vid, struct net_bridge_port *p)
-{
- struct net_device *dev = br->dev;
- struct neighbour *n;
- struct arphdr *parp;
- u8 *arpptr, *sha;
- __be32 sip, tip;
-
- BR_INPUT_SKB_CB(skb)->proxyarp_replied = false;
-
- if ((dev->flags & IFF_NOARP) ||
- !pskb_may_pull(skb, arp_hdr_len(dev)))
- return;
-
- parp = arp_hdr(skb);
-
- if (parp->ar_pro != htons(ETH_P_IP) ||
- parp->ar_op != htons(ARPOP_REQUEST) ||
- parp->ar_hln != dev->addr_len ||
- parp->ar_pln != 4)
- return;
-
- arpptr = (u8 *)parp + sizeof(struct arphdr);
- sha = arpptr;
- arpptr += dev->addr_len; /* sha */
- memcpy(&sip, arpptr, sizeof(sip));
- arpptr += sizeof(sip);
- arpptr += dev->addr_len; /* tha */
- memcpy(&tip, arpptr, sizeof(tip));
-
- if (ipv4_is_loopback(tip) ||
- ipv4_is_multicast(tip))
- return;
-
- n = neigh_lookup(&arp_tbl, &tip, dev);
- if (n) {
- struct net_bridge_fdb_entry *f;
-
- if (!(n->nud_state & NUD_VALID)) {
- neigh_release(n);
- return;
- }
-
- f = br_fdb_find_rcu(br, n->ha, vid);
- if (f && ((p->flags & BR_PROXYARP) ||
- (f->dst && (f->dst->flags & BR_PROXYARP_WIFI)))) {
- arp_send(ARPOP_REPLY, ETH_P_ARP, sip, skb->dev, tip,
- sha, n->ha, sha);
- BR_INPUT_SKB_CB(skb)->proxyarp_replied = true;
- }
-
- neigh_release(n);
- }
-}
-
/* note: already called with rcu_read_lock */
int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
{
@@ -171,8 +115,11 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
BR_INPUT_SKB_CB(skb)->brdev = br->dev;
- if (IS_ENABLED(CONFIG_INET) && skb->protocol == htons(ETH_P_ARP))
- br_do_proxy_arp(skb, br, vid, p);
+ if (IS_ENABLED(CONFIG_INET) &&
+ (skb->protocol == htons(ETH_P_ARP) ||
+ skb->protocol == htons(ETH_P_RARP))) {
+ br_do_proxy_suppress_arp(skb, br, vid, p);
+ }
switch (pkt_type) {
case BR_PKT_MULTICAST:
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index f47332e..bb095dc 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1139,5 +1139,8 @@ static inline void br_switchdev_frame_unmark(struct sk_buff *skb)
}
#endif /* CONFIG_NET_SWITCHDEV */
+/* br_arp_nd_proxy.c */
void br_recalculate_neigh_suppress_enabled(struct net_bridge *br);
+void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
+ u16 vid, struct net_bridge_port *p);
#endif
--
2.1.4
^ permalink raw reply related
* [PATCH net-next v4 1/3] bridge: add new BR_NEIGH_SUPPRESS port flag to suppress arp and nd flood
From: Roopa Prabhu @ 2017-10-04 5:12 UTC (permalink / raw)
To: davem; +Cc: netdev, nikolay, stephen, bridge
In-Reply-To: <1507093953-59929-1-git-send-email-roopa@cumulusnetworks.com>
From: Roopa Prabhu <roopa@cumulusnetworks.com>
This patch adds a new bridge port flag BR_NEIGH_SUPPRESS to
suppress arp and nd flood on bridge ports. It implements
rfc7432, section 10.
https://tools.ietf.org/html/rfc7432#section-10
for ethernet VPN deployments. It is similar to the existing
BR_ARP_PROXY flag but has a few semantic differences to conform
to EVPN standard. In case of EVPN, it is mainly used to
avoid flooding to tunnel ports like vxlan. Unlike the existing
flags it suppresses flood of all neigh discovery packets
(arp, nd) to tunnel ports.
This patch adds netlink and sysfs support to set this bridge port
flag.
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
include/linux/if_bridge.h | 1 +
include/uapi/linux/if_link.h | 1 +
net/bridge/Makefile | 2 +-
net/bridge/br_arp_nd_proxy.c | 32 ++++++++++++++++++++++++++++++++
net/bridge/br_forward.c | 2 +-
net/bridge/br_if.c | 5 +++++
net/bridge/br_netlink.c | 12 +++++++++++-
net/bridge/br_private.h | 2 ++
net/bridge/br_sysfs_if.c | 2 ++
9 files changed, 56 insertions(+), 3 deletions(-)
create mode 100644 net/bridge/br_arp_nd_proxy.c
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 3cd18ac..316ee11 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -49,6 +49,7 @@ struct br_ip_list {
#define BR_MULTICAST_TO_UNICAST BIT(12)
#define BR_VLAN_TUNNEL BIT(13)
#define BR_BCAST_FLOOD BIT(14)
+#define BR_NEIGH_SUPPRESS BIT(15)
#define BR_DEFAULT_AGEING_TIME (300 * HZ)
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index ea87bd7..0d51f4f 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -326,6 +326,7 @@ enum {
IFLA_BRPORT_VLAN_TUNNEL,
IFLA_BRPORT_BCAST_FLOOD,
IFLA_BRPORT_GROUP_FWD_MASK,
+ IFLA_BRPORT_NEIGH_SUPPRESS,
__IFLA_BRPORT_MAX
};
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
diff --git a/net/bridge/Makefile b/net/bridge/Makefile
index 40b1ede..4aee55f 100644
--- a/net/bridge/Makefile
+++ b/net/bridge/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_BRIDGE) += bridge.o
bridge-y := br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \
br_ioctl.o br_stp.o br_stp_bpdu.o \
br_stp_if.o br_stp_timer.o br_netlink.o \
- br_netlink_tunnel.o
+ br_netlink_tunnel.o br_arp_nd_proxy.o
bridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o
diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c
new file mode 100644
index 0000000..f889ad5
--- /dev/null
+++ b/net/bridge/br_arp_nd_proxy.c
@@ -0,0 +1,32 @@
+/*
+ * Handle bridge arp/nd proxy/suppress
+ *
+ * Copyright (C) 2017 Cumulus Networks
+ * Copyright (c) 2017 Roopa Prabhu <roopa@cumulusnetworks.com>
+ *
+ * Authors:
+ * Roopa Prabhu <roopa@cumulusnetworks.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include "br_private.h"
+
+void br_recalculate_neigh_suppress_enabled(struct net_bridge *br)
+{
+ struct net_bridge_port *p;
+ bool neigh_suppress = false;
+
+ list_for_each_entry(p, &br->port_list, list) {
+ if (p->flags & BR_NEIGH_SUPPRESS) {
+ neigh_suppress = true;
+ break;
+ }
+ }
+
+ br->neigh_suppress_enabled = neigh_suppress;
+}
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 48fb174..b4eed11 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -204,7 +204,7 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
/* Do not flood to ports that enable proxy ARP */
if (p->flags & BR_PROXYARP)
continue;
- if ((p->flags & BR_PROXYARP_WIFI) &&
+ if ((p->flags & (BR_PROXYARP_WIFI | BR_NEIGH_SUPPRESS)) &&
BR_INPUT_SKB_CB(skb)->proxyarp_replied)
continue;
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index f3aef22..8f615d4 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -310,6 +310,8 @@ void br_dev_delete(struct net_device *dev, struct list_head *head)
del_nbp(p);
}
+ br_recalculate_neigh_suppress_enabled(br);
+
br_fdb_delete_by_port(br, NULL, 0, 1);
cancel_delayed_work_sync(&br->gc_work);
@@ -653,4 +655,7 @@ void br_port_flags_change(struct net_bridge_port *p, unsigned long mask)
if (mask & BR_AUTO_MASK)
nbp_update_port_count(br);
+
+ if (mask & BR_NEIGH_SUPPRESS)
+ br_recalculate_neigh_suppress_enabled(br);
}
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index dea88a2..d8c2706 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -138,6 +138,7 @@ static inline size_t br_port_info_size(void)
+ nla_total_size(1) /* IFLA_BRPORT_PROXYARP */
+ nla_total_size(1) /* IFLA_BRPORT_PROXYARP_WIFI */
+ nla_total_size(1) /* IFLA_BRPORT_VLAN_TUNNEL */
+ + nla_total_size(1) /* IFLA_BRPORT_NEIGH_SUPPRESS */
+ nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_ROOT_ID */
+ nla_total_size(sizeof(struct ifla_bridge_id)) /* IFLA_BRPORT_BRIDGE_ID */
+ nla_total_size(sizeof(u16)) /* IFLA_BRPORT_DESIGNATED_PORT */
@@ -210,7 +211,9 @@ static int br_port_fill_attrs(struct sk_buff *skb,
nla_put_u8(skb, IFLA_BRPORT_CONFIG_PENDING, p->config_pending) ||
nla_put_u8(skb, IFLA_BRPORT_VLAN_TUNNEL, !!(p->flags &
BR_VLAN_TUNNEL)) ||
- nla_put_u16(skb, IFLA_BRPORT_GROUP_FWD_MASK, p->group_fwd_mask))
+ nla_put_u16(skb, IFLA_BRPORT_GROUP_FWD_MASK, p->group_fwd_mask) ||
+ nla_put_u8(skb, IFLA_BRPORT_NEIGH_SUPPRESS, !!(p->flags &
+ BR_NEIGH_SUPPRESS)))
return -EMSGSIZE;
timerval = br_timer_value(&p->message_age_timer);
@@ -692,6 +695,7 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
{
unsigned long old_flags = p->flags;
bool br_vlan_tunnel_old = false;
+ int neigh_suppress_old = 0;
int err;
err = br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
@@ -785,6 +789,12 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
p->group_fwd_mask = fwd_mask;
}
+ neigh_suppress_old = (p->flags & BR_NEIGH_SUPPRESS);
+ br_set_port_flag(p, tb, IFLA_BRPORT_NEIGH_SUPPRESS,
+ BR_NEIGH_SUPPRESS);
+ if (neigh_suppress_old != (p->flags & BR_NEIGH_SUPPRESS))
+ br_recalculate_neigh_suppress_enabled(p->br);
+
br_port_flags_change(p, old_flags ^ p->flags);
return 0;
}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 020c709..f47332e 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -404,6 +404,7 @@ struct net_bridge {
#ifdef CONFIG_NET_SWITCHDEV
int offload_fwd_mark;
#endif
+ bool neigh_suppress_enabled;
};
struct br_input_skb_cb {
@@ -1138,4 +1139,5 @@ static inline void br_switchdev_frame_unmark(struct sk_buff *skb)
}
#endif /* CONFIG_NET_SWITCHDEV */
+void br_recalculate_neigh_suppress_enabled(struct net_bridge *br);
#endif
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 9110d5e..0a1fa9c 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -191,6 +191,7 @@ BRPORT_ATTR_FLAG(proxyarp, BR_PROXYARP);
BRPORT_ATTR_FLAG(proxyarp_wifi, BR_PROXYARP_WIFI);
BRPORT_ATTR_FLAG(multicast_flood, BR_MCAST_FLOOD);
BRPORT_ATTR_FLAG(broadcast_flood, BR_BCAST_FLOOD);
+BRPORT_ATTR_FLAG(neigh_suppress, BR_NEIGH_SUPPRESS);
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf)
@@ -241,6 +242,7 @@ static const struct brport_attribute *brport_attrs[] = {
&brport_attr_multicast_flood,
&brport_attr_broadcast_flood,
&brport_attr_group_fwd_mask,
+ &brport_attr_neigh_suppress,
NULL
};
--
2.1.4
^ permalink raw reply related
* [PATCH net-next v4 0/3] bridge: neigh msg proxy and flood suppression support
From: Roopa Prabhu @ 2017-10-04 5:12 UTC (permalink / raw)
To: davem; +Cc: netdev, nikolay, stephen, bridge
From: Roopa Prabhu <roopa@cumulusnetworks.com>
This series implements arp and nd suppression in the bridge
driver for ethernet vpns. It implements rfc7432, section 10
https://tools.ietf.org/html/rfc7432#section-10
for ethernet VPN deployments. It is similar to the existing
BR_ARP_PROXY flag but has a few semantic differences to conform
to EVPN standard. In case of EVPN, it is mainly used to avoid flooding to
tunnel ports like vxlan. Unlike the existing flags it suppresses flood
of all neigh discovery packets (arp, nd) to tunnel ports.
v2 : rebase to latest + address some optimization feedback from Nikolay.
v3 : fix kbuild reported build errors with CONFIG_INET off
v4 : simplify port flag mask as suggested by stephen
Roopa Prabhu (3):
bridge: add new BR_NEIGH_SUPPRESS port flag to suppress arp and nd
flood
neigh arp suppress first
bridge: suppress nd messages from going to BR_NEIGH_SUPPRESS ports
include/linux/if_bridge.h | 1 +
include/uapi/linux/if_link.h | 1 +
net/bridge/Makefile | 2 +-
net/bridge/br_arp_nd_proxy.c | 492 +++++++++++++++++++++++++++++++++++++++++++
net/bridge/br_device.c | 18 ++
net/bridge/br_forward.c | 3 +-
net/bridge/br_if.c | 5 +
net/bridge/br_input.c | 73 ++-----
net/bridge/br_netlink.c | 16 +-
net/bridge/br_private.h | 9 +
net/bridge/br_sysfs_if.c | 2 +
11 files changed, 561 insertions(+), 61 deletions(-)
create mode 100644 net/bridge/br_arp_nd_proxy.c
--
2.1.4
^ permalink raw reply
* Re: [v2] cdc-ether: divorce initialisation with a filter reset and a generic method
From: Vignesh R @ 2017-10-04 5:02 UTC (permalink / raw)
To: David Miller; +Cc: oneukum@suse.com, netdev@vger.kernel.org, bjorn@mork.no
In-Reply-To: <20171003.095955.1603961040065728073.davem@davemloft.net>
On Tuesday 03 October 2017 10:29 PM, David Miller wrote:
> From: Vignesh R <vigneshr@ti.com>
> Date: Tue, 3 Oct 2017 13:39:18 +0530
>
>> Hi Dave,
>>
>> On Monday 22 May 2017 06:20 PM, Oliver Neukum wrote:
>>> Some devices need their multicast filter reset but others are crashed by that.
>>> So the methods need to be separated.
>>>
>>> Signed-off-by: Oliver Neukum <oneukum@suse.com>
>>> Reported-by: "Ridgway, Keith" <kridgway@harris.com>
>>> ---
>>
>> I see this patch was merged and said to be queued for -stable, but I
>> don't see this fix in any of the stable kernels. Would you please ask
>> for this patch to be backported to -stable kernels?
>
> I submit networking -stable patches at a time of my own choosing.
> Usually 1 to 2 weeks after it gets applied to my tree.
>
Sorry, but this patch was merged in v4.12-rc3(end of May) and I did not
see them in netdev stable patchwork nor in Greg's queue. Hence, I
thought this patch might have slipped through the cracks.
> Please be patient.
>
--
Regards
Vignesh
^ permalink raw reply
* [PATCH net-next 7/7] mlxsw: spectrum: Add extack messages for enslave failures
From: David Ahern @ 2017-10-04 4:58 UTC (permalink / raw)
To: netdev; +Cc: j.vosburgh, vfalico, andy, jiri, idosch, davem, bridge,
David Ahern
In-Reply-To: <1507093134-20406-1-git-send-email-dsahern@gmail.com>
mlxsw fails device enslavement for a number of reasons. Use the extack
facility to return an error message to the user stating why the enslave
is failing.
Messages are prefixed with "spectrum" so users know it is a constraint
imposed by the hardware driver. For example:
$ ip li add br0.11 link br0 type vlan id 11
$ ip li set swp11 master br0
Error: spectrum: Enslaving a port to a device that already has an upper device is not supported.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 46 ++++++++++++++++++++------
1 file changed, 36 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 3adf237c951a..a6cc00e4e543 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -4019,14 +4019,20 @@ static int mlxsw_sp_lag_index_get(struct mlxsw_sp *mlxsw_sp,
static bool
mlxsw_sp_master_lag_check(struct mlxsw_sp *mlxsw_sp,
struct net_device *lag_dev,
- struct netdev_lag_upper_info *lag_upper_info)
+ struct netdev_lag_upper_info *lag_upper_info,
+ struct netlink_ext_ack *extack)
{
u16 lag_id;
- if (mlxsw_sp_lag_index_get(mlxsw_sp, lag_dev, &lag_id) != 0)
+ if (mlxsw_sp_lag_index_get(mlxsw_sp, lag_dev, &lag_id) != 0) {
+ NL_SET_ERR_MSG(extack, "spectrum: Unknown LAG device");
return false;
- if (lag_upper_info->tx_type != NETDEV_LAG_TX_TYPE_HASH)
+ }
+ if (lag_upper_info->tx_type != NETDEV_LAG_TX_TYPE_HASH) {
+ NL_SET_ERR_MSG(extack,
+ "spectrum: LAG device using unsupported Tx type");
return false;
+ }
return true;
}
@@ -4231,6 +4237,7 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
{
struct netdev_notifier_changeupper_info *info;
struct mlxsw_sp_port *mlxsw_sp_port;
+ struct netlink_ext_ack *extack;
struct net_device *upper_dev;
struct mlxsw_sp *mlxsw_sp;
int err = 0;
@@ -4238,6 +4245,7 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
mlxsw_sp_port = netdev_priv(dev);
mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
info = ptr;
+ extack = netdev_notifier_info_to_extack(&info->info);
switch (event) {
case NETDEV_PRECHANGEUPPER:
@@ -4245,25 +4253,43 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
if (!is_vlan_dev(upper_dev) &&
!netif_is_lag_master(upper_dev) &&
!netif_is_bridge_master(upper_dev) &&
- !netif_is_ovs_master(upper_dev))
+ !netif_is_ovs_master(upper_dev)) {
+ NL_SET_ERR_MSG(extack,
+ "spectrum: Unknown upper device type");
return -EINVAL;
+ }
if (!info->linking)
break;
- if (netdev_has_any_upper_dev(upper_dev))
+ if (netdev_has_any_upper_dev(upper_dev)) {
+ NL_SET_ERR_MSG(extack,
+ "spectrum: Enslaving a port to a device that already has an upper device is not supported");
return -EINVAL;
+ }
if (netif_is_lag_master(upper_dev) &&
!mlxsw_sp_master_lag_check(mlxsw_sp, upper_dev,
- info->upper_info))
+ info->upper_info, extack))
return -EINVAL;
- if (netif_is_lag_master(upper_dev) && vlan_uses_dev(dev))
+ if (netif_is_lag_master(upper_dev) && vlan_uses_dev(dev)) {
+ NL_SET_ERR_MSG(extack,
+ "spectrum: Master device is a LAG master and this device has a VLAN");
return -EINVAL;
+ }
if (netif_is_lag_port(dev) && is_vlan_dev(upper_dev) &&
- !netif_is_lag_master(vlan_dev_real_dev(upper_dev)))
+ !netif_is_lag_master(vlan_dev_real_dev(upper_dev))) {
+ NL_SET_ERR_MSG(extack,
+ "spectrum: Can not put a VLAN on a LAG port");
return -EINVAL;
- if (netif_is_ovs_master(upper_dev) && vlan_uses_dev(dev))
+ }
+ if (netif_is_ovs_master(upper_dev) && vlan_uses_dev(dev)) {
+ NL_SET_ERR_MSG(extack,
+ "spectrum: Master device is an OVS master and this device has a VLAN");
return -EINVAL;
- if (netif_is_ovs_port(dev) && is_vlan_dev(upper_dev))
+ }
+ if (netif_is_ovs_port(dev) && is_vlan_dev(upper_dev)) {
+ NL_SET_ERR_MSG(extack,
+ "spectrum: Can not put a VLAN on an OVS port");
return -EINVAL;
+ }
break;
case NETDEV_CHANGEUPPER:
upper_dev = info->upper_dev;
--
2.1.4
^ permalink raw reply related
* [PATCH net-next 6/7] net: bridge: Pass extack to down to netdev_master_upper_dev_link
From: David Ahern @ 2017-10-04 4:58 UTC (permalink / raw)
To: netdev; +Cc: j.vosburgh, vfalico, andy, jiri, idosch, davem, bridge,
David Ahern
In-Reply-To: <1507093134-20406-1-git-send-email-dsahern@gmail.com>
Pass extack arg to br_add_if. Add messages for a couple of failures
and pass arg to netdev_master_upper_dev_link.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
net/bridge/br_device.c | 2 +-
net/bridge/br_if.c | 15 +++++++++++----
net/bridge/br_ioctl.c | 2 +-
net/bridge/br_private.h | 3 ++-
4 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index cb0131d70ab1..7acb77c9bd65 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -326,7 +326,7 @@ static int br_add_slave(struct net_device *dev, struct net_device *slave_dev,
{
struct net_bridge *br = netdev_priv(dev);
- return br_add_if(br, slave_dev);
+ return br_add_if(br, slave_dev, extack);
}
static int br_del_slave(struct net_device *dev, struct net_device *slave_dev)
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 0a3fd727048d..59a74a414e20 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -480,7 +480,8 @@ netdev_features_t br_features_recompute(struct net_bridge *br,
}
/* called with RTNL */
-int br_add_if(struct net_bridge *br, struct net_device *dev)
+int br_add_if(struct net_bridge *br, struct net_device *dev,
+ struct netlink_ext_ack *extack)
{
struct net_bridge_port *p;
int err = 0;
@@ -500,16 +501,22 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
return -EINVAL;
/* No bridging of bridges */
- if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit)
+ if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit) {
+ NL_SET_ERR_MSG(extack,
+ "Can not enslave a bridge to a bridge");
return -ELOOP;
+ }
/* Device is already being bridged */
if (br_port_exists(dev))
return -EBUSY;
/* No bridging devices that dislike that (e.g. wireless) */
- if (dev->priv_flags & IFF_DONT_BRIDGE)
+ if (dev->priv_flags & IFF_DONT_BRIDGE) {
+ NL_SET_ERR_MSG(extack,
+ "Device does not allow enslaving to a bridge");
return -EOPNOTSUPP;
+ }
p = new_nbp(br, dev);
if (IS_ERR(p))
@@ -540,7 +547,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
dev->priv_flags |= IFF_BRIDGE_PORT;
- err = netdev_master_upper_dev_link(dev, br->dev, NULL, NULL, NULL);
+ err = netdev_master_upper_dev_link(dev, br->dev, NULL, NULL, extack);
if (err)
goto err5;
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 66cd98772051..8f29103935a3 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -98,7 +98,7 @@ static int add_del_if(struct net_bridge *br, int ifindex, int isadd)
return -EINVAL;
if (isadd)
- ret = br_add_if(br, dev);
+ ret = br_add_if(br, dev, NULL);
else
ret = br_del_if(br, dev);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 020c709a017f..ab4df24f7bba 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -566,7 +566,8 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
void br_port_carrier_check(struct net_bridge_port *p);
int br_add_bridge(struct net *net, const char *name);
int br_del_bridge(struct net *net, const char *name);
-int br_add_if(struct net_bridge *br, struct net_device *dev);
+int br_add_if(struct net_bridge *br, struct net_device *dev,
+ struct netlink_ext_ack *extack);
int br_del_if(struct net_bridge *br, struct net_device *dev);
int br_min_mtu(const struct net_bridge *br);
netdev_features_t br_features_recompute(struct net_bridge *br,
--
2.1.4
^ permalink raw reply related
* [PATCH net-next 5/7] net: bonding: Add extack messages for some enslave failures
From: David Ahern @ 2017-10-04 4:58 UTC (permalink / raw)
To: netdev; +Cc: j.vosburgh, vfalico, andy, jiri, idosch, davem, bridge,
David Ahern
In-Reply-To: <1507093134-20406-1-git-send-email-dsahern@gmail.com>
A number of bond_enslave errors are logged using the netdev_err API.
Return those messages to userspace via the extack facility.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
drivers/net/bonding/bond_main.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index bc92307c2082..6688dc9154e0 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1348,12 +1348,15 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
/* already in-use? */
if (netdev_is_rx_handler_busy(slave_dev)) {
+ NL_SET_ERR_MSG(extack,
+ "Device is in use and cannot be enslaved");
netdev_err(bond_dev,
"Error: Device is in use and cannot be enslaved\n");
return -EBUSY;
}
if (bond_dev == slave_dev) {
+ NL_SET_ERR_MSG(extack, "Cannot enslave bond to itself.");
netdev_err(bond_dev, "cannot enslave bond to itself.\n");
return -EPERM;
}
@@ -1364,6 +1367,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
netdev_dbg(bond_dev, "%s is NETIF_F_VLAN_CHALLENGED\n",
slave_dev->name);
if (vlan_uses_dev(bond_dev)) {
+ NL_SET_ERR_MSG(extack,
+ "Can not enslave VLAN challenged device to VLAN enabled bond");
netdev_err(bond_dev, "Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n",
slave_dev->name, bond_dev->name);
return -EPERM;
@@ -1383,6 +1388,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
* enslaving it; the old ifenslave will not.
*/
if (slave_dev->flags & IFF_UP) {
+ NL_SET_ERR_MSG(extack, "Device can not be enslaved while up");
netdev_err(bond_dev, "%s is up - this may be due to an out of date ifenslave\n",
slave_dev->name);
return -EPERM;
@@ -1423,6 +1429,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
bond_dev);
}
} else if (bond_dev->type != slave_dev->type) {
+ NL_SET_ERR_MSG(extack,
+ "Device type is different from other slaves");
netdev_err(bond_dev, "%s ether type (%d) is different from other slaves (%d), can not enslave it\n",
slave_dev->name, slave_dev->type, bond_dev->type);
return -EINVAL;
@@ -1430,6 +1438,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
if (slave_dev->type == ARPHRD_INFINIBAND &&
BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) {
+ NL_SET_ERR_MSG(extack,
+ "Only active-backup mode is supported for infiniband slaves");
netdev_warn(bond_dev, "Type (%d) supports only active-backup mode\n",
slave_dev->type);
res = -EOPNOTSUPP;
@@ -1445,6 +1455,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
bond->params.fail_over_mac = BOND_FOM_ACTIVE;
netdev_warn(bond_dev, "Setting fail_over_mac to active for active-backup mode\n");
} else {
+ NL_SET_ERR_MSG(extack,
+ "Slave device does not support setting the MAC address, but fail_over_mac is not set to active");
netdev_err(bond_dev, "The slave device specified does not support setting the MAC address, but fail_over_mac is not set to active\n");
res = -EOPNOTSUPP;
goto err_undo_flags;
--
2.1.4
^ permalink raw reply related
* [PATCH net-next 4/7] net: vrf: Add extack messages for enslave errors
From: David Ahern @ 2017-10-04 4:58 UTC (permalink / raw)
To: netdev; +Cc: j.vosburgh, vfalico, andy, jiri, idosch, davem, bridge,
David Ahern
In-Reply-To: <1507093134-20406-1-git-send-email-dsahern@gmail.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
---
drivers/net/vrf.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 77d0655a0250..0b54f553228e 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -772,8 +772,11 @@ static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev,
/* do not allow loopback device to be enslaved to a VRF.
* The vrf device acts as the loopback for the vrf.
*/
- if (port_dev == dev_net(dev)->loopback_dev)
+ if (port_dev == dev_net(dev)->loopback_dev) {
+ NL_SET_ERR_MSG(extack,
+ "Can not enslave loopback device to a VRF");
return -EOPNOTSUPP;
+ }
port_dev->priv_flags |= IFF_L3MDEV_SLAVE;
ret = netdev_master_upper_dev_link(port_dev, dev, NULL, NULL, extack);
@@ -792,7 +795,13 @@ static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev,
static int vrf_add_slave(struct net_device *dev, struct net_device *port_dev,
struct netlink_ext_ack *extack)
{
- if (netif_is_l3_master(port_dev) || netif_is_l3_slave(port_dev))
+ if (netif_is_l3_master(port_dev)) {
+ NL_SET_ERR_MSG(extack,
+ "Can not enslave an L3 master device to a VRF");
+ return -EINVAL;
+ }
+
+ if (netif_is_l3_slave(port_dev))
return -EINVAL;
return do_vrf_add_slave(dev, port_dev, extack);
--
2.1.4
^ permalink raw reply related
* [PATCH net-next 3/7] net: Add extack to upper device linking
From: David Ahern @ 2017-10-04 4:58 UTC (permalink / raw)
To: netdev; +Cc: j.vosburgh, vfalico, andy, jiri, idosch, davem, bridge,
David Ahern
In-Reply-To: <1507093134-20406-1-git-send-email-dsahern@gmail.com>
Add extack arg to netdev_upper_dev_link and netdev_master_upper_dev_link
Signed-off-by: David Ahern <dsahern@gmail.com>
---
drivers/net/bonding/bond_main.c | 7 ++++---
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c | 2 +-
drivers/net/hyperv/netvsc_drv.c | 2 +-
drivers/net/ipvlan/ipvlan_main.c | 2 +-
drivers/net/macsec.c | 2 +-
drivers/net/macvlan.c | 7 ++++---
drivers/net/macvtap.c | 2 +-
drivers/net/team/team.c | 2 +-
drivers/net/usb/qmi_wwan.c | 2 +-
drivers/net/vrf.c | 7 ++++---
include/linux/if_macvlan.h | 3 ++-
include/linux/netdevice.h | 6 ++++--
net/8021q/vlan.c | 6 +++---
net/8021q/vlan.h | 2 +-
net/8021q/vlan_netlink.c | 2 +-
net/batman-adv/hard-interface.c | 2 +-
net/bridge/br_if.c | 2 +-
net/core/dev.c | 15 ++++++++++-----
net/openvswitch/vport-netdev.c | 3 ++-
19 files changed, 44 insertions(+), 32 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 78feb94a36db..bc92307c2082 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1217,14 +1217,15 @@ static enum netdev_lag_tx_type bond_lag_tx_type(struct bonding *bond)
}
}
-static int bond_master_upper_dev_link(struct bonding *bond, struct slave *slave)
+static int bond_master_upper_dev_link(struct bonding *bond, struct slave *slave,
+ struct netlink_ext_ack *extack)
{
struct netdev_lag_upper_info lag_upper_info;
int err;
lag_upper_info.tx_type = bond_lag_tx_type(bond);
err = netdev_master_upper_dev_link(slave->dev, bond->dev, slave,
- &lag_upper_info);
+ &lag_upper_info, extack);
if (err)
return err;
rtmsg_ifinfo(RTM_NEWLINK, slave->dev, IFF_SLAVE, GFP_KERNEL);
@@ -1710,7 +1711,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
goto err_detach;
}
- res = bond_master_upper_dev_link(bond, new_slave);
+ res = bond_master_upper_dev_link(bond, new_slave, extack);
if (res) {
netdev_dbg(bond_dev, "Error %d calling bond_master_upper_dev_link\n", res);
goto err_unregister;
diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
index 98f22551eb45..1af326a60cbb 100644
--- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
+++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c
@@ -178,7 +178,7 @@ static int rmnet_newlink(struct net *src_net, struct net_device *dev,
if (err)
goto err1;
- err = netdev_master_upper_dev_link(dev, real_dev, NULL, NULL);
+ err = netdev_master_upper_dev_link(dev, real_dev, NULL, NULL, extack);
if (err)
goto err2;
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index f300ae61c6c6..dfb986421ec6 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1748,7 +1748,7 @@ static int netvsc_vf_join(struct net_device *vf_netdev,
goto rx_handler_failed;
}
- ret = netdev_upper_dev_link(vf_netdev, ndev);
+ ret = netdev_upper_dev_link(vf_netdev, ndev, NULL);
if (ret != 0) {
netdev_err(vf_netdev,
"can not set master device %s (err = %d)\n",
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index c74893c1e620..57c3856bab05 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -584,7 +584,7 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev,
if (err < 0)
goto remove_ida;
- err = netdev_upper_dev_link(phy_dev, dev);
+ err = netdev_upper_dev_link(phy_dev, dev, extack);
if (err) {
goto unregister_netdev;
}
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 98e4deaa3a6a..ccbe4eaffe4d 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -3244,7 +3244,7 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
&macsec_netdev_addr_lock_key,
macsec_get_nest_level(dev));
- err = netdev_upper_dev_link(real_dev, dev);
+ err = netdev_upper_dev_link(real_dev, dev, extack);
if (err < 0)
goto unregister;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 1ffe77e95d46..858bd66511a2 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1344,7 +1344,8 @@ static int macvlan_changelink_sources(struct macvlan_dev *vlan, u32 mode,
}
int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
- struct nlattr *tb[], struct nlattr *data[])
+ struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack)
{
struct macvlan_dev *vlan = netdev_priv(dev);
struct macvlan_port *port;
@@ -1433,7 +1434,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
goto destroy_macvlan_port;
dev->priv_flags |= IFF_MACVLAN;
- err = netdev_upper_dev_link(lowerdev, dev);
+ err = netdev_upper_dev_link(lowerdev, dev, extack);
if (err)
goto unregister_netdev;
@@ -1456,7 +1457,7 @@ static int macvlan_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
- return macvlan_common_newlink(src_net, dev, tb, data);
+ return macvlan_common_newlink(src_net, dev, tb, data, extack);
}
void macvlan_dellink(struct net_device *dev, struct list_head *head)
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index c2d0ea2fb019..f62aea2fcfa9 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -105,7 +105,7 @@ static int macvtap_newlink(struct net *src_net, struct net_device *dev,
/* Don't put anything that may fail after macvlan_common_newlink
* because we can't undo what it does.
*/
- err = macvlan_common_newlink(src_net, dev, tb, data);
+ err = macvlan_common_newlink(src_net, dev, tb, data, extack);
if (err) {
netdev_rx_handler_unregister(dev);
return err;
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 4359d45aa131..a468439969df 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1112,7 +1112,7 @@ static int team_upper_dev_link(struct team *team, struct team_port *port)
lag_upper_info.tx_type = team->mode->lag_tx_type;
err = netdev_master_upper_dev_link(port->dev, team->dev, NULL,
- &lag_upper_info);
+ &lag_upper_info, NULL);
if (err)
return err;
port->dev->priv_flags |= IFF_TEAM_PORT;
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 8c3733608271..db7279d5b250 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -221,7 +221,7 @@ static int qmimux_register_device(struct net_device *real_dev, u8 mux_id)
/* Account for reference in struct qmimux_priv_priv */
dev_hold(real_dev);
- err = netdev_upper_dev_link(real_dev, new_dev);
+ err = netdev_upper_dev_link(real_dev, new_dev, NULL);
if (err)
goto out_unregister_netdev;
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 4a082ef53533..77d0655a0250 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -764,7 +764,8 @@ static void cycle_netdev(struct net_device *dev)
}
}
-static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
+static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev,
+ struct netlink_ext_ack *extack)
{
int ret;
@@ -775,7 +776,7 @@ static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
return -EOPNOTSUPP;
port_dev->priv_flags |= IFF_L3MDEV_SLAVE;
- ret = netdev_master_upper_dev_link(port_dev, dev, NULL, NULL);
+ ret = netdev_master_upper_dev_link(port_dev, dev, NULL, NULL, extack);
if (ret < 0)
goto err;
@@ -794,7 +795,7 @@ static int vrf_add_slave(struct net_device *dev, struct net_device *port_dev,
if (netif_is_l3_master(port_dev) || netif_is_l3_slave(port_dev))
return -EINVAL;
- return do_vrf_add_slave(dev, port_dev);
+ return do_vrf_add_slave(dev, port_dev, extack);
}
/* inverse of do_vrf_add_slave */
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index c9ec1343d187..10e319f41fb1 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -72,7 +72,8 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
extern void macvlan_common_setup(struct net_device *dev);
extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
- struct nlattr *tb[], struct nlattr *data[]);
+ struct nlattr *tb[], struct nlattr *data[],
+ struct netlink_ext_ack *extack);
extern void macvlan_count_rx(const struct macvlan_dev *vlan,
unsigned int len, bool success,
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 368a5064a487..31bb3010c69b 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3919,10 +3919,12 @@ void *netdev_adjacent_get_private(struct list_head *adj_list);
void *netdev_lower_get_first_private_rcu(struct net_device *dev);
struct net_device *netdev_master_upper_dev_get(struct net_device *dev);
struct net_device *netdev_master_upper_dev_get_rcu(struct net_device *dev);
-int netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev);
+int netdev_upper_dev_link(struct net_device *dev, struct net_device *upper_dev,
+ struct netlink_ext_ack *extack);
int netdev_master_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev,
- void *upper_priv, void *upper_info);
+ void *upper_priv, void *upper_info,
+ struct netlink_ext_ack *extack);
void netdev_upper_dev_unlink(struct net_device *dev,
struct net_device *upper_dev);
void netdev_adjacent_rename_links(struct net_device *dev, char *oldname);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 9649579b5b9f..71c3e045505b 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -138,7 +138,7 @@ int vlan_check_real_dev(struct net_device *real_dev,
return 0;
}
-int register_vlan_dev(struct net_device *dev)
+int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack)
{
struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
struct net_device *real_dev = vlan->real_dev;
@@ -174,7 +174,7 @@ int register_vlan_dev(struct net_device *dev)
if (err < 0)
goto out_uninit_mvrp;
- err = netdev_upper_dev_link(real_dev, dev);
+ err = netdev_upper_dev_link(real_dev, dev, extack);
if (err)
goto out_unregister_netdev;
@@ -270,7 +270,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
vlan->flags = VLAN_FLAG_REORDER_HDR;
new_dev->rtnl_link_ops = &vlan_link_ops;
- err = register_vlan_dev(new_dev);
+ err = register_vlan_dev(new_dev, NULL);
if (err < 0)
goto out_free_newdev;
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index df8bd65dd370..94f8eed9f9b3 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -107,7 +107,7 @@ void vlan_dev_get_realdev_name(const struct net_device *dev, char *result);
int vlan_check_real_dev(struct net_device *real_dev,
__be16 protocol, u16 vlan_id);
void vlan_setup(struct net_device *dev);
-int register_vlan_dev(struct net_device *dev);
+int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack);
void unregister_vlan_dev(struct net_device *dev, struct list_head *head);
bool vlan_dev_inherit_address(struct net_device *dev,
struct net_device *real_dev);
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
index 5e831de3103e..6e7c5a6a7930 100644
--- a/net/8021q/vlan_netlink.c
+++ b/net/8021q/vlan_netlink.c
@@ -160,7 +160,7 @@ static int vlan_newlink(struct net *src_net, struct net_device *dev,
if (err < 0)
return err;
- return register_vlan_dev(dev);
+ return register_vlan_dev(dev, extack);
}
static inline size_t vlan_qos_map_size(unsigned int n)
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index e348f76ea8c1..f7b413b9297e 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -738,7 +738,7 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
bat_priv = netdev_priv(hard_iface->soft_iface);
ret = netdev_master_upper_dev_link(hard_iface->net_dev,
- soft_iface, NULL, NULL);
+ soft_iface, NULL, NULL, NULL);
if (ret)
goto err_dev;
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index f3aef22931ab..0a3fd727048d 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -540,7 +540,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
dev->priv_flags |= IFF_BRIDGE_PORT;
- err = netdev_master_upper_dev_link(dev, br->dev, NULL, NULL);
+ err = netdev_master_upper_dev_link(dev, br->dev, NULL, NULL, NULL);
if (err)
goto err5;
diff --git a/net/core/dev.c b/net/core/dev.c
index dbeeefebfbb7..b417b76ff8fc 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6276,11 +6276,13 @@ static void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev,
static int __netdev_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev, bool master,
- void *upper_priv, void *upper_info)
+ void *upper_priv, void *upper_info,
+ struct netlink_ext_ack *extack)
{
struct netdev_notifier_changeupper_info changeupper_info = {
.info = {
.dev = dev,
+ .extack = extack,
},
.upper_dev = upper_dev,
.master = master,
@@ -6340,9 +6342,11 @@ static int __netdev_upper_dev_link(struct net_device *dev,
* returns zero.
*/
int netdev_upper_dev_link(struct net_device *dev,
- struct net_device *upper_dev)
+ struct net_device *upper_dev,
+ struct netlink_ext_ack *extack)
{
- return __netdev_upper_dev_link(dev, upper_dev, false, NULL, NULL);
+ return __netdev_upper_dev_link(dev, upper_dev, false,
+ NULL, NULL, extack);
}
EXPORT_SYMBOL(netdev_upper_dev_link);
@@ -6361,10 +6365,11 @@ EXPORT_SYMBOL(netdev_upper_dev_link);
*/
int netdev_master_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev,
- void *upper_priv, void *upper_info)
+ void *upper_priv, void *upper_info,
+ struct netlink_ext_ack *extack)
{
return __netdev_upper_dev_link(dev, upper_dev, true,
- upper_priv, upper_info);
+ upper_priv, upper_info, extack);
}
EXPORT_SYMBOL(netdev_master_upper_dev_link);
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index 0389398fa4ab..2e5e7a41d8ef 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -108,7 +108,8 @@ struct vport *ovs_netdev_link(struct vport *vport, const char *name)
rtnl_lock();
err = netdev_master_upper_dev_link(vport->dev,
- get_dpdev(vport->dp), NULL, NULL);
+ get_dpdev(vport->dp),
+ NULL, NULL, NULL);
if (err)
goto error_unlock;
--
2.1.4
^ permalink raw reply related
* [PATCH net-next 2/7] net: Add extack to ndo_add_slave
From: David Ahern @ 2017-10-04 4:58 UTC (permalink / raw)
To: netdev; +Cc: j.vosburgh, vfalico, andy, jiri, idosch, davem, bridge,
David Ahern
In-Reply-To: <1507093134-20406-1-git-send-email-dsahern@gmail.com>
Pass extack to do_set_master and down to ndo_add_slave
Signed-off-by: David Ahern <dsahern@gmail.com>
---
drivers/net/bonding/bond_main.c | 5 +++--
drivers/net/bonding/bond_options.c | 2 +-
drivers/net/team/team.c | 3 ++-
drivers/net/vrf.c | 3 ++-
include/linux/netdevice.h | 3 ++-
include/net/bonding.h | 3 ++-
net/batman-adv/soft-interface.c | 3 ++-
net/bridge/br_device.c | 3 ++-
net/core/rtnetlink.c | 10 ++++++----
9 files changed, 22 insertions(+), 13 deletions(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index b19dc033fb36..78feb94a36db 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1328,7 +1328,8 @@ void bond_lower_state_changed(struct slave *slave)
}
/* enslave device <slave> to bond device <master> */
-int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
+int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
+ struct netlink_ext_ack *extack)
{
struct bonding *bond = netdev_priv(bond_dev);
const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
@@ -3492,7 +3493,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
switch (cmd) {
case BOND_ENSLAVE_OLD:
case SIOCBONDENSLAVE:
- res = bond_enslave(bond_dev, slave_dev);
+ res = bond_enslave(bond_dev, slave_dev, NULL);
break;
case BOND_RELEASE_OLD:
case SIOCBONDRELEASE:
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 5931aa2fe997..8a9b085c2a98 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -1383,7 +1383,7 @@ static int bond_option_slaves_set(struct bonding *bond,
switch (command[0]) {
case '+':
netdev_dbg(bond->dev, "Adding slave %s\n", dev->name);
- ret = bond_enslave(bond->dev, dev);
+ ret = bond_enslave(bond->dev, dev, NULL);
break;
case '-':
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index ae53e899259f..4359d45aa131 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -1914,7 +1914,8 @@ static int team_netpoll_setup(struct net_device *dev,
}
#endif
-static int team_add_slave(struct net_device *dev, struct net_device *port_dev)
+static int team_add_slave(struct net_device *dev, struct net_device *port_dev,
+ struct netlink_ext_ack *extack)
{
struct team *team = netdev_priv(dev);
int err;
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index cc18b7b11612..4a082ef53533 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -788,7 +788,8 @@ static int do_vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
return ret;
}
-static int vrf_add_slave(struct net_device *dev, struct net_device *port_dev)
+static int vrf_add_slave(struct net_device *dev, struct net_device *port_dev,
+ struct netlink_ext_ack *extack)
{
if (netif_is_l3_master(port_dev) || netif_is_l3_slave(port_dev))
return -EINVAL;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 05fcaba4b0d9..368a5064a487 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1246,7 +1246,8 @@ struct net_device_ops {
u32 flow_id);
#endif
int (*ndo_add_slave)(struct net_device *dev,
- struct net_device *slave_dev);
+ struct net_device *slave_dev,
+ struct netlink_ext_ack *extack);
int (*ndo_del_slave)(struct net_device *dev,
struct net_device *slave_dev);
netdev_features_t (*ndo_fix_features)(struct net_device *dev,
diff --git a/include/net/bonding.h b/include/net/bonding.h
index b2e68657a216..2860cc66c2bb 100644
--- a/include/net/bonding.h
+++ b/include/net/bonding.h
@@ -596,7 +596,8 @@ void bond_destroy_sysfs(struct bond_net *net);
void bond_prepare_sysfs_group(struct bonding *bond);
int bond_sysfs_slave_add(struct slave *slave);
void bond_sysfs_slave_del(struct slave *slave);
-int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
+int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
+ struct netlink_ext_ack *extack);
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb);
int bond_set_carrier(struct bonding *bond);
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index c2c986746d0b..e7d5fbb6ad53 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -867,7 +867,8 @@ static int batadv_softif_init_late(struct net_device *dev)
* Return: 0 if successful or error otherwise.
*/
static int batadv_softif_slave_add(struct net_device *dev,
- struct net_device *slave_dev)
+ struct net_device *slave_dev,
+ struct netlink_ext_ack *extack)
{
struct batadv_hard_iface *hard_iface;
struct net *net = dev_net(dev);
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index f6b6a92f1c48..cb0131d70ab1 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -320,7 +320,8 @@ void br_netpoll_disable(struct net_bridge_port *p)
#endif
-static int br_add_slave(struct net_device *dev, struct net_device *slave_dev)
+static int br_add_slave(struct net_device *dev, struct net_device *slave_dev,
+ struct netlink_ext_ack *extack)
{
struct net_bridge *br = netdev_priv(dev);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 3961f87cdc76..1b355219e520 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1964,7 +1964,8 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr **tb)
return err;
}
-static int do_set_master(struct net_device *dev, int ifindex)
+static int do_set_master(struct net_device *dev, int ifindex,
+ struct netlink_ext_ack *extack)
{
struct net_device *upper_dev = netdev_master_upper_dev_get(dev);
const struct net_device_ops *ops;
@@ -1989,7 +1990,7 @@ static int do_set_master(struct net_device *dev, int ifindex)
return -EINVAL;
ops = upper_dev->netdev_ops;
if (ops->ndo_add_slave) {
- err = ops->ndo_add_slave(upper_dev, dev);
+ err = ops->ndo_add_slave(upper_dev, dev, extack);
if (err)
return err;
} else {
@@ -2122,7 +2123,7 @@ static int do_setlink(const struct sk_buff *skb,
}
if (tb[IFLA_MASTER]) {
- err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]));
+ err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]), extack);
if (err)
goto errout;
status |= DO_SETLINK_MODIFIED;
@@ -2766,7 +2767,8 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
goto out_unregister;
}
if (tb[IFLA_MASTER]) {
- err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]));
+ err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]),
+ extack);
if (err)
goto out_unregister;
}
--
2.1.4
^ permalink raw reply related
* [PATCH net-next 1/7] net: Add extack to netdev_notifier_info
From: David Ahern @ 2017-10-04 4:58 UTC (permalink / raw)
To: netdev; +Cc: j.vosburgh, vfalico, andy, jiri, idosch, davem, bridge,
David Ahern
In-Reply-To: <1507093134-20406-1-git-send-email-dsahern@gmail.com>
Add netlink_ext_ack to netdev_notifier_info to allow notifier
handlers to return errors to userspace.
Clean up the initialization in dev.c such that extack is easily
added in subsequent patches where relevant. Specifically, remove
the init call in call_netdevice_notifiers_info and have callers
initalize on stack when info is declared.
Signed-off-by: David Ahern <dsahern@gmail.com>
---
include/linux/netdevice.h | 10 +++++-
net/core/dev.c | 79 ++++++++++++++++++++++++++++-------------------
2 files changed, 56 insertions(+), 33 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d04424cfffba..05fcaba4b0d9 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2309,7 +2309,8 @@ int register_netdevice_notifier(struct notifier_block *nb);
int unregister_netdevice_notifier(struct notifier_block *nb);
struct netdev_notifier_info {
- struct net_device *dev;
+ struct net_device *dev;
+ struct netlink_ext_ack *extack;
};
struct netdev_notifier_change_info {
@@ -2334,6 +2335,7 @@ static inline void netdev_notifier_info_init(struct netdev_notifier_info *info,
struct net_device *dev)
{
info->dev = dev;
+ info->extack = NULL;
}
static inline struct net_device *
@@ -2342,6 +2344,12 @@ netdev_notifier_info_to_dev(const struct netdev_notifier_info *info)
return info->dev;
}
+static inline struct netlink_ext_ack *
+netdev_notifier_info_to_extack(const struct netdev_notifier_info *info)
+{
+ return info->extack;
+}
+
int call_netdevice_notifiers(unsigned long val, struct net_device *dev);
diff --git a/net/core/dev.c b/net/core/dev.c
index 1770097cfd86..dbeeefebfbb7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -162,7 +162,6 @@ static struct list_head offload_base __read_mostly;
static int netif_rx_internal(struct sk_buff *skb);
static int call_netdevice_notifiers_info(unsigned long val,
- struct net_device *dev,
struct netdev_notifier_info *info);
static struct napi_struct *napi_by_id(unsigned int napi_id);
@@ -1338,10 +1337,11 @@ EXPORT_SYMBOL(netdev_features_change);
void netdev_state_change(struct net_device *dev)
{
if (dev->flags & IFF_UP) {
- struct netdev_notifier_change_info change_info;
+ struct netdev_notifier_change_info change_info = {
+ .info.dev = dev,
+ };
- change_info.flags_changed = 0;
- call_netdevice_notifiers_info(NETDEV_CHANGE, dev,
+ call_netdevice_notifiers_info(NETDEV_CHANGE,
&change_info.info);
rtmsg_ifinfo(RTM_NEWLINK, dev, 0, GFP_KERNEL);
}
@@ -1562,9 +1562,10 @@ EXPORT_SYMBOL(dev_disable_lro);
static int call_netdevice_notifier(struct notifier_block *nb, unsigned long val,
struct net_device *dev)
{
- struct netdev_notifier_info info;
+ struct netdev_notifier_info info = {
+ .dev = dev,
+ };
- netdev_notifier_info_init(&info, dev);
return nb->notifier_call(nb, val, &info);
}
@@ -1689,11 +1690,9 @@ EXPORT_SYMBOL(unregister_netdevice_notifier);
*/
static int call_netdevice_notifiers_info(unsigned long val,
- struct net_device *dev,
struct netdev_notifier_info *info)
{
ASSERT_RTNL();
- netdev_notifier_info_init(info, dev);
return raw_notifier_call_chain(&netdev_chain, val, info);
}
@@ -1708,9 +1707,11 @@ static int call_netdevice_notifiers_info(unsigned long val,
int call_netdevice_notifiers(unsigned long val, struct net_device *dev)
{
- struct netdev_notifier_info info;
+ struct netdev_notifier_info info = {
+ .dev = dev,
+ };
- return call_netdevice_notifiers_info(val, dev, &info);
+ return call_netdevice_notifiers_info(val, &info);
}
EXPORT_SYMBOL(call_netdevice_notifiers);
@@ -6277,7 +6278,15 @@ static int __netdev_upper_dev_link(struct net_device *dev,
struct net_device *upper_dev, bool master,
void *upper_priv, void *upper_info)
{
- struct netdev_notifier_changeupper_info changeupper_info;
+ struct netdev_notifier_changeupper_info changeupper_info = {
+ .info = {
+ .dev = dev,
+ },
+ .upper_dev = upper_dev,
+ .master = master,
+ .linking = true,
+ .upper_info = upper_info,
+ };
int ret = 0;
ASSERT_RTNL();
@@ -6295,12 +6304,7 @@ static int __netdev_upper_dev_link(struct net_device *dev,
if (master && netdev_master_upper_dev_get(dev))
return -EBUSY;
- changeupper_info.upper_dev = upper_dev;
- changeupper_info.master = master;
- changeupper_info.linking = true;
- changeupper_info.upper_info = upper_info;
-
- ret = call_netdevice_notifiers_info(NETDEV_PRECHANGEUPPER, dev,
+ ret = call_netdevice_notifiers_info(NETDEV_PRECHANGEUPPER,
&changeupper_info.info);
ret = notifier_to_errno(ret);
if (ret)
@@ -6311,7 +6315,7 @@ static int __netdev_upper_dev_link(struct net_device *dev,
if (ret)
return ret;
- ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
+ ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER,
&changeupper_info.info);
ret = notifier_to_errno(ret);
if (ret)
@@ -6375,20 +6379,24 @@ EXPORT_SYMBOL(netdev_master_upper_dev_link);
void netdev_upper_dev_unlink(struct net_device *dev,
struct net_device *upper_dev)
{
- struct netdev_notifier_changeupper_info changeupper_info;
+ struct netdev_notifier_changeupper_info changeupper_info = {
+ .info = {
+ .dev = dev,
+ },
+ .upper_dev = upper_dev,
+ .linking = false,
+ };
ASSERT_RTNL();
- changeupper_info.upper_dev = upper_dev;
changeupper_info.master = netdev_master_upper_dev_get(dev) == upper_dev;
- changeupper_info.linking = false;
- call_netdevice_notifiers_info(NETDEV_PRECHANGEUPPER, dev,
+ call_netdevice_notifiers_info(NETDEV_PRECHANGEUPPER,
&changeupper_info.info);
__netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
- call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
+ call_netdevice_notifiers_info(NETDEV_CHANGEUPPER,
&changeupper_info.info);
}
EXPORT_SYMBOL(netdev_upper_dev_unlink);
@@ -6404,11 +6412,13 @@ EXPORT_SYMBOL(netdev_upper_dev_unlink);
void netdev_bonding_info_change(struct net_device *dev,
struct netdev_bonding_info *bonding_info)
{
- struct netdev_notifier_bonding_info info;
+ struct netdev_notifier_bonding_info info = {
+ .info.dev = dev,
+ };
memcpy(&info.bonding_info, bonding_info,
sizeof(struct netdev_bonding_info));
- call_netdevice_notifiers_info(NETDEV_BONDING_INFO, dev,
+ call_netdevice_notifiers_info(NETDEV_BONDING_INFO,
&info.info);
}
EXPORT_SYMBOL(netdev_bonding_info_change);
@@ -6534,11 +6544,13 @@ EXPORT_SYMBOL(dev_get_nest_level);
void netdev_lower_state_changed(struct net_device *lower_dev,
void *lower_state_info)
{
- struct netdev_notifier_changelowerstate_info changelowerstate_info;
+ struct netdev_notifier_changelowerstate_info changelowerstate_info = {
+ .info.dev = lower_dev,
+ };
ASSERT_RTNL();
changelowerstate_info.lower_state_info = lower_state_info;
- call_netdevice_notifiers_info(NETDEV_CHANGELOWERSTATE, lower_dev,
+ call_netdevice_notifiers_info(NETDEV_CHANGELOWERSTATE,
&changelowerstate_info.info);
}
EXPORT_SYMBOL(netdev_lower_state_changed);
@@ -6829,11 +6841,14 @@ void __dev_notify_flags(struct net_device *dev, unsigned int old_flags,
if (dev->flags & IFF_UP &&
(changes & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI | IFF_VOLATILE))) {
- struct netdev_notifier_change_info change_info;
-
- change_info.flags_changed = changes;
- call_netdevice_notifiers_info(NETDEV_CHANGE, dev,
- &change_info.info);
+ struct netdev_notifier_change_info change_info = {
+ .info = {
+ .dev = dev,
+ },
+ .flags_changed = changes,
+ };
+
+ call_netdevice_notifiers_info(NETDEV_CHANGE, &change_info.info);
}
}
--
2.1.4
^ permalink raw reply related
* [PATCH net-next 0/7] net: Plumb extack error reporting to enslavements
From: David Ahern @ 2017-10-04 4:58 UTC (permalink / raw)
To: netdev; +Cc: j.vosburgh, vfalico, andy, jiri, idosch, davem, bridge,
David Ahern
Another round of extending extack error reporting, this time for
enslavements through ndo_add_slave and notifiers.
David Ahern (7):
net: Add extack to netdev_notifier_info
net: Add extack to ndo_add_slave
net: Add extack to upper device linking
net: vrf: Add extack messages for enslave errors
net: bonding: Add extack messages for some enslave failures
net: bridge: Pass extack to down to netdev_master_upper_dev_link
mlxsw: spectrum: Add extack messages for enslave failures
drivers/net/bonding/bond_main.c | 24 ++++--
drivers/net/bonding/bond_options.c | 2 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 46 ++++++++---
drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c | 2 +-
drivers/net/hyperv/netvsc_drv.c | 2 +-
drivers/net/ipvlan/ipvlan_main.c | 2 +-
drivers/net/macsec.c | 2 +-
drivers/net/macvlan.c | 7 +-
drivers/net/macvtap.c | 2 +-
drivers/net/team/team.c | 5 +-
drivers/net/usb/qmi_wwan.c | 2 +-
drivers/net/vrf.c | 23 ++++--
include/linux/if_macvlan.h | 3 +-
include/linux/netdevice.h | 19 ++++-
include/net/bonding.h | 3 +-
net/8021q/vlan.c | 6 +-
net/8021q/vlan.h | 2 +-
net/8021q/vlan_netlink.c | 2 +-
net/batman-adv/hard-interface.c | 2 +-
net/batman-adv/soft-interface.c | 3 +-
net/bridge/br_device.c | 5 +-
net/bridge/br_if.c | 15 +++-
net/bridge/br_ioctl.c | 2 +-
net/bridge/br_private.h | 3 +-
net/core/dev.c | 96 +++++++++++++---------
net/core/rtnetlink.c | 10 ++-
net/openvswitch/vport-netdev.c | 3 +-
27 files changed, 196 insertions(+), 97 deletions(-)
--
2.1.4
^ 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