Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: bridge: Receive notification about successful FDB offload

When a new static FDB is added to the bridge a notification is sent to
the driver for offload. In case of successful offload the driver should
notify the bridge back, which in turn should mark the FDB as offloaded.

Currently, externally learned is equivalent for being offloaded which is
not correct due to the fact that FDBs which are added from user-space are
also marked as externally learned. In order to specify if an FDB was
successfully offloaded a new flag is introduced.

Signed-off-by: Arkadi Sharshevsky <arkadis@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Arkadi Sharshevsky and committed by
David S. Miller
9fe8bcec 6b26b51b

+37 -3
+1
include/net/switchdev.h
··· 159 159 SWITCHDEV_FDB_DEL_TO_BRIDGE, 160 160 SWITCHDEV_FDB_ADD_TO_DEVICE, 161 161 SWITCHDEV_FDB_DEL_TO_DEVICE, 162 + SWITCHDEV_FDB_OFFLOADED, 162 163 }; 163 164 164 165 struct switchdev_notifier_info {
+1
include/uapi/linux/neighbour.h
··· 41 41 #define NTF_MASTER 0x04 42 42 #define NTF_PROXY 0x08 /* == ATF_PUBL */ 43 43 #define NTF_EXT_LEARNED 0x10 44 + #define NTF_OFFLOADED 0x20 44 45 #define NTF_ROUTER 0x80 45 46 46 47 /*
+10 -1
net/bridge/br.c
··· 142 142 fdb_info = ptr; 143 143 err = br_fdb_external_learn_add(br, p, fdb_info->addr, 144 144 fdb_info->vid); 145 - if (err) 145 + if (err) { 146 146 err = notifier_from_errno(err); 147 + break; 148 + } 149 + br_fdb_offloaded_set(br, p, fdb_info->addr, 150 + fdb_info->vid); 147 151 break; 148 152 case SWITCHDEV_FDB_DEL_TO_BRIDGE: 149 153 fdb_info = ptr; ··· 155 151 fdb_info->vid); 156 152 if (err) 157 153 err = notifier_from_errno(err); 154 + break; 155 + case SWITCHDEV_FDB_OFFLOADED: 156 + fdb_info = ptr; 157 + br_fdb_offloaded_set(br, p, fdb_info->addr, 158 + fdb_info->vid); 158 159 break; 159 160 } 160 161
+21 -1
net/bridge/br_fdb.c
··· 511 511 fdb->is_static = is_static; 512 512 fdb->added_by_user = 0; 513 513 fdb->added_by_external_learn = 0; 514 + fdb->offloaded = 0; 514 515 fdb->updated = fdb->used = jiffies; 515 516 hlist_add_head_rcu(&fdb->hlist, head); 516 517 } ··· 648 647 ndm->ndm_family = AF_BRIDGE; 649 648 ndm->ndm_pad1 = 0; 650 649 ndm->ndm_pad2 = 0; 651 - ndm->ndm_flags = fdb->added_by_external_learn ? NTF_EXT_LEARNED : 0; 650 + ndm->ndm_flags = 0; 652 651 ndm->ndm_type = 0; 653 652 ndm->ndm_ifindex = fdb->dst ? fdb->dst->dev->ifindex : br->dev->ifindex; 654 653 ndm->ndm_state = fdb_to_nud(br, fdb); 654 + 655 + if (fdb->offloaded) 656 + ndm->ndm_flags |= NTF_OFFLOADED; 657 + if (fdb->added_by_external_learn) 658 + ndm->ndm_flags |= NTF_EXT_LEARNED; 655 659 656 660 if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr)) 657 661 goto nla_put_failure; ··· 1128 1122 spin_unlock_bh(&br->hash_lock); 1129 1123 1130 1124 return err; 1125 + } 1126 + 1127 + void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p, 1128 + const unsigned char *addr, u16 vid) 1129 + { 1130 + struct net_bridge_fdb_entry *fdb; 1131 + 1132 + spin_lock_bh(&br->hash_lock); 1133 + 1134 + fdb = br_fdb_find(br, addr, vid); 1135 + if (fdb) 1136 + fdb->offloaded = 1; 1137 + 1138 + spin_unlock_bh(&br->hash_lock); 1131 1139 }
+4 -1
net/bridge/br_private.h
··· 169 169 unsigned char is_local:1, 170 170 is_static:1, 171 171 added_by_user:1, 172 - added_by_external_learn:1; 172 + added_by_external_learn:1, 173 + offloaded:1; 173 174 174 175 /* write-heavy members should not affect lookups */ 175 176 unsigned long updated ____cacheline_aligned_in_smp; ··· 537 536 const unsigned char *addr, u16 vid); 538 537 int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p, 539 538 const unsigned char *addr, u16 vid); 539 + void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p, 540 + const unsigned char *addr, u16 vid); 540 541 541 542 /* br_forward.c */ 542 543 enum br_pkt_type {