[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200522184534.7hynm6jain76n5dr@ws.localdomain>
Date: Fri, 22 May 2020 20:45:34 +0200
From: "Allan W. Nielsen" <allan.nielsen@...rochip.com>
To: Vladimir Oltean <olteanv@...il.com>
CC: Nikolay Aleksandrov <nikolay@...ulusnetworks.com>,
Andrew Lunn <andrew@...n.ch>,
Florian Fainelli <f.fainelli@...il.com>,
Vivien Didelot <vivien.didelot@...il.com>,
"David S. Miller" <davem@...emloft.net>,
"Jiri Pirko" <jiri@...nulli.us>, Ido Schimmel <idosch@...sch.org>,
Jakub Kicinski <kuba@...nel.org>,
Ivan Vecera <ivecera@...hat.com>,
netdev <netdev@...r.kernel.org>,
Horatiu Vultur <horatiu.vultur@...rochip.com>,
Roopa Prabhu <roopa@...ulusnetworks.com>
Subject: Re: [PATCH RFC net-next 10/13] net: bridge: add port flags for host
flooding
On 22.05.2020 16:13, Vladimir Oltean wrote:
>EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>
>On Fri, 22 May 2020 at 15:38, Nikolay Aleksandrov
><nikolay@...ulusnetworks.com> wrote:
>>
>> On 22/05/2020 00:10, Vladimir Oltean wrote:
>> > From: Vladimir Oltean <vladimir.oltean@....com>
>> >
>> > In cases where the bridge is offloaded by a switchdev, there are
>> > situations where we can optimize RX filtering towards the host. To be
>> > precise, the host only needs to do termination, which it can do by
>> > responding at the MAC addresses of the slave ports and of the bridge
>> > interface itself. But most notably, it doesn't need to do forwarding,
>> > so there is no need to see packets with unknown destination address.
>> >
>> > But there are, however, cases when a switchdev does need to flood to the
>> > CPU. Such an example is when the switchdev is bridged with a foreign
>> > interface, and since there is no offloaded datapath, packets need to
>> > pass through the CPU. Currently this is the only identified case, but it
>> > can be extended at any time.
>> >
>> > So far, switchdev implementers made driver-level assumptions, such as:
>> > this chip is never integrated in SoCs where it can be bridged with a
>> > foreign interface, so I'll just disable host flooding and save some CPU
>> > cycles. Or: I can never know what else can be bridged with this
>> > switchdev port, so I must leave host flooding enabled in any case.
>> >
>> > Let the bridge drive the host flooding decision, and pass it to
>> > switchdev via the same mechanism as the external flooding flags.
>> >
>> > Signed-off-by: Vladimir Oltean <vladimir.oltean@....com>
>> > ---
>> > include/linux/if_bridge.h | 3 +++
>> > net/bridge/br_if.c | 40 +++++++++++++++++++++++++++++++++++++++
>> > net/bridge/br_switchdev.c | 4 +++-
>> > 3 files changed, 46 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
>> > index b3a8d3054af0..6891a432862d 100644
>> > --- a/include/linux/if_bridge.h
>> > +++ b/include/linux/if_bridge.h
>> > @@ -49,6 +49,9 @@ struct br_ip_list {
>> > #define BR_ISOLATED BIT(16)
>> > #define BR_MRP_AWARE BIT(17)
>> > #define BR_MRP_LOST_CONT BIT(18)
>> > +#define BR_HOST_FLOOD BIT(19)
>> > +#define BR_HOST_MCAST_FLOOD BIT(20)
>> > +#define BR_HOST_BCAST_FLOOD BIT(21)
>> >
>> > #define BR_DEFAULT_AGEING_TIME (300 * HZ)
>> >
>> > diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
>> > index a0e9a7937412..aae59d1e619b 100644
>> > --- a/net/bridge/br_if.c
>> > +++ b/net/bridge/br_if.c
>> > @@ -166,6 +166,45 @@ void br_manage_promisc(struct net_bridge *br)
>> > }
>> > }
>> >
>> > +static int br_manage_host_flood(struct net_bridge *br)
>> > +{
>> > + const unsigned long mask = BR_HOST_FLOOD | BR_HOST_MCAST_FLOOD |
>> > + BR_HOST_BCAST_FLOOD;
>> > + struct net_bridge_port *p, *q;
>> > +
>> > + list_for_each_entry(p, &br->port_list, list) {
>> > + unsigned long flags = p->flags;
>> > + bool sw_bridging = false;
>> > + int err;
>> > +
>> > + list_for_each_entry(q, &br->port_list, list) {
>> > + if (p == q)
>> > + continue;
>> > +
>> > + if (!netdev_port_same_parent_id(p->dev, q->dev)) {
>> > + sw_bridging = true;
>> > + break;
>> > + }
>> > + }
>> > +
>> > + if (sw_bridging)
>> > + flags |= mask;
>> > + else
>> > + flags &= ~mask;
>> > +
>> > + if (flags == p->flags)
>> > + continue;
>> > +
>> > + err = br_switchdev_set_port_flag(p, flags, mask);
>> > + if (err)
>> > + return err;
>> > +
>> > + p->flags = flags;
>> > + }
>> > +
>> > + return 0;
>> > +}
>> > +
>> > int nbp_backup_change(struct net_bridge_port *p,
>> > struct net_device *backup_dev)
>> > {
>> > @@ -231,6 +270,7 @@ static void nbp_update_port_count(struct net_bridge *br)
>> > br->auto_cnt = cnt;
>> > br_manage_promisc(br);
>> > }
>> > + br_manage_host_flood(br);
>> > }
>> >
>>
>> Can we do this only at port add/del ?
>> Right now it will be invoked also by br_port_flags_change() upon BR_AUTO_MASK flag change.
>>
>
>Yes, we can do that.
>Actually I have some doubts about BR_HOST_BCAST_FLOOD. We can't
>disable that in the no-foreign-interface case, can we? For IPv6, it
>looks like the stack does take care of installing dev_mc addresses for
>the neighbor discovery protocol, but for IPv4 I guess the assumption
>is that broadcast ARP should always be processed?
Ideally this should be per VLAN. In case of IPv4, you only need to be
part of the broadcast domain on VLANs with an associated vlan-interface.
>> > static void nbp_delete_promisc(struct net_bridge_port *p)
>> > diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
>> > index 015209bf44aa..360806ac7463 100644
>> > --- a/net/bridge/br_switchdev.c
>> > +++ b/net/bridge/br_switchdev.c
>> > @@ -56,7 +56,9 @@ bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
>> >
>> > /* Flags that can be offloaded to hardware */
>> > #define BR_PORT_FLAGS_HW_OFFLOAD (BR_LEARNING | BR_FLOOD | \
>> > - BR_MCAST_FLOOD | BR_BCAST_FLOOD)
>> > + BR_MCAST_FLOOD | BR_BCAST_FLOOD | \
>> > + BR_HOST_FLOOD | BR_HOST_MCAST_FLOOD | \
>> > + BR_HOST_BCAST_FLOOD)
>> >
>> > int br_switchdev_set_port_flag(struct net_bridge_port *p,
>> > unsigned long flags,
>> >
>>
>
>Thanks,
>-Vladimir
/Allan
Powered by blists - more mailing lists