Re: [RFC net-next 2/7] net: bridge: switchdev: Include local flag in FDB notifications
From: Nikolay Aleksandrov <hidden>
Date: 2021-01-18 21:42:51
On 18/01/2021 23:22, Nikolay Aleksandrov wrote:
On 18/01/2021 23:17, Nikolay Aleksandrov wrote:quoted
On 18/01/2021 22:19, Tobias Waldekranz wrote:quoted
On Mon, Jan 18, 2021 at 21:27, Vladimir Oltean [off-list ref] wrote:quoted
On Mon, Jan 18, 2021 at 07:58:59PM +0100, Tobias Waldekranz wrote:quoted
Ah I see, no I was not aware of that. I just saw that the entry towards the CPU was added to the ATU, which it would in both cases. I.e. from the switch's POV, in this setup: br0 / \ (A) swp0 dummy0 (B) A "local" entry like (A), or a "static" entry like (B) means the same thing to the switch: "it is somewhere behind my CPU-port".Yes, except that if dummy0 was a real and non-switchdev interface, then the "local" entry would probably break your traffic if what you meant was "static".Agreed.quoted
quoted
quoted
So I think there is a very real issue in that the FDB entries with the is_local bit was never specified to switchdev thus far, and now suddenly is. I'm sorry, but what you're saying in the commit message, that "!added_by_user has so far been indistinguishable from is_local" is simply false.Alright, so how do you do it? Here is the struct: struct switchdev_notifier_fdb_info { struct switchdev_notifier_info info; /* must be first */ const unsigned char *addr; u16 vid; u8 added_by_user:1, offloaded:1; }; Which field separates a local address on swp0 from a dynamically learned address on swp0?None, that's the problem. Local addresses are already presented to switchdev without saying that they're local. Which is the entire reason that users are misled into thinking that the addresses are not local. I may have misread what you said, but to me, "!added_by_user has so far been indistinguishable from is_local" means that: - every struct switchdev_notifier_fdb_info with added_by_user == true also had an implicit is_local == false - every struct switchdev_notifier_fdb_info with added_by_user == false also had an implicit is_local == true It is _this_ that I deemed as clearly untrue. The is_local flag is not indistinguishable from !added_by_user, it is indistinguishable full stop. Which makes it hard to work with in a backwards-compatible way.This was probably a semantic mistake on my part, we meant the same thing.quoted
quoted
Ok, so just to see if I understand this correctly: The situation today it that `bridge fdb add ADDR dev DEV master` results in flows towards ADDR being sent to: 1. DEV if DEV belongs to a DSA switch. 2. To the host if DEV was a non-offloaded interface.Not quite. In the bridge software FDB, the entry is marked as is_local in both cases, doesn't matter if the interface is offloaded or not. Just that switchdev does not propagate the is_local flag, which makes the switchdev listeners think it is not local. The interpretation of that will probably vary among switchdev drivers. The subtlety is that for a non-offloading interface, the misconfiguration (when you mean static but use local) is easy to catch. Since only the entry from the software FDB will be hit, this means that the frame will never be forwarded, so traffic will break. But in the case of a switchdev offloading interface, the frames will hit the hardware FDB entry more often than the software FDB entry. So everything will work just fine and dandy even though it shouldn't.Quite right.quoted
quoted
With this series applied both would result in (2) which, while idiosyncratic, is as intended. But this of course runs the risk of breaking existing scripts which rely on the current behavior.Yes. My only hope is that we could just offload the entries pointing towards br0, and ignore the local ones. But for that I would need the bridgeThat was my initial approach. Unfortunately that breaks down when the bridge inherits its address from a port, i.e. the default case. When the address is added to the bridge (fdb->dst == NULL), fdb_insert will find the previous local entry that is set on the port and bail out before sending a notification: if (fdb) { /* it is okay to have multiple ports with same * address, just use the first one. */ if (test_bit(BR_FDB_LOCAL, &fdb->flags)) return 0; br_warn(br, "adding interface %s with same address as a received packet (addr:%pM, vlan:%u)\n", source ? source->dev->name : br->dev->name, addr, vid); fdb_delete(br, fdb, true); } You could change this so that a notification always is sent out. Or you could give precedence to !fdb->dst and update the existing entry.quoted
maintainers to clarify what is the difference between then, as I asked in your other patch.I am pretty sure they mean the same thing, I believe that !fdb->dst implies is_local. It is just that "bridge fdb add ADDR dev br0 self" is a new(er) thing, and before that there was "local" entries on ports. Maybe I should try to get rid of the local flag in the bridge first, and then come back to this problem once that is done? Either way, I agree that 5/7 is all we want to add to DSA to get this working.BR_FDB_LOCAL and !fdb->dst are not the same thing, check fdb_add_entry(). You cannot get rid of it, !fdb->dst implies BR_FDB_LOCAL, but it's not symmetrical.Scratch that, I spoke too soon. You can get rid of it internally, just need to be careful not to break user-visible behaviour as Vladimir mentioned.
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1611005977; bh=bdfYBvMa8LNyHkRyEtaHStOZr794nuxZw02BF6Zfg5c=; h=ARC-Seal:ARC-Message-Signature:ARC-Authentication-Results: Authentication-Results:Subject:From:To:CC:References:Message-ID: Date:User-Agent:In-Reply-To:Content-Type:Content-Language: Content-Transfer-Encoding:X-Originating-IP:X-ClientProxiedBy: MIME-Version:X-MS-Exchange-MessageSentRepresentingType: X-MS-PublicTrafficType:X-MS-Office365-Filtering-Correlation-Id: X-MS-TrafficTypeDiagnostic:X-MS-Exchange-Transport-Forked: X-Microsoft-Antispam-PRVS:X-MS-Oob-TLC-OOBClassifiers: X-MS-Exchange-SenderADCheck:X-Microsoft-Antispam: X-Microsoft-Antispam-Message-Info:X-Forefront-Antispam-Report: X-MS-Exchange-AntiSpam-MessageData: X-MS-Exchange-CrossTenant-Network-Message-Id: X-MS-Exchange-CrossTenant-AuthSource: X-MS-Exchange-CrossTenant-AuthAs: X-MS-Exchange-CrossTenant-OriginalArrivalTime: X-MS-Exchange-CrossTenant-FromEntityHeader: X-MS-Exchange-CrossTenant-Id:X-MS-Exchange-CrossTenant-MailboxType: X-MS-Exchange-CrossTenant-UserPrincipalName: X-MS-Exchange-Transport-CrossTenantHeadersStamped:X-OriginatorOrg; b=lOH2ClNGfg5hhcLMJSlOtsM9K7JoVYkrv1v5FBtgFxxiiWBcOGYir2uqdIfXvMTD/ LUTYZ9tVzvZJ/tKymoPhlR+V27URN1nOwkEdz3k1u46QcB+3eQa1blAz8c8bU/HMAP joO4AKJ9BIuG/sc3ZTAX7jdOE3JUSOmCdfhqTCNc6sGmaVFBAwPrrhGPVth3niCkc7 JwfTXir+8JtBC0XV3Vw2DiYs8RCX22S/48evhzu6O3PNsmLTFaOZaDb0Ep76MquFPu rjCjXH2ZfG9J/D9YchY/hybtGMRK4aruos1La9mEVi6WzUeW+PhR0/FiXzfW/6fef7 cswqoYtddosLw== Apologies for the multiple emails, but wanted to leave an example: 00:11:22:33:44:55 dev ens16 master bridge permanent This must always exist and user-space must be able to create it, which might be against what you want to achieve (no BR_FDB_LOCAL entries with fdb->dst != NULL).