History

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.

Arkadi Sharshevsky committed 9 years ago

Commit 9fe8bce1 parent 6b26b515 files · +37 −3Browse files

Unified · Split

5 files
  1. include/net/switchdev.h +1 −0
  2. include/uapi/linux/neighbour.h +1 −0
  3. net/bridge/br.c +10 −1
  4. net/bridge/br_fdb.c +21 −1
  5. net/bridge/br_private.h +4 −1
include/net/switchdev.h+1−0
@@ -159,6 +159,7 @@ enum switchdev_notifier_type { · 158 unmodified lines
159159 SWITCHDEV_FDB_DEL_TO_BRIDGE,
160160 SWITCHDEV_FDB_ADD_TO_DEVICE,
161161 SWITCHDEV_FDB_DEL_TO_DEVICE,
162+ SWITCHDEV_FDB_OFFLOADED,
162163 };
163164
164165 struct switchdev_notifier_info {
include/uapi/linux/neighbour.h+1−0
@@ -41,6 +41,7 @@ enum { · 40 unmodified lines
4141 #define NTF_MASTER 0x04
4242 #define NTF_PROXY 0x08 /* == ATF_PUBL */
4343 #define NTF_EXT_LEARNED 0x10
44+#define NTF_OFFLOADED 0x20
4445 #define NTF_ROUTER 0x80
4546
4647 /*
net/bridge/br.c+10−1
@@ -142,8 +142,12 @@ static int br_switchdev_event(struct notifier_block *unused, · 141 unmodified lines
142142 fdb_info = ptr;
143143 err = br_fdb_external_learn_add(br, p, fdb_info->addr,
144144 fdb_info->vid);
145− if (err)
145+ if (err) {
146146 err = notifier_from_errno(err);
147+ break;
148+ }
149+ br_fdb_offloaded_set(br, p, fdb_info->addr,
150+ fdb_info->vid);
147151 break;
148152 case SWITCHDEV_FDB_DEL_TO_BRIDGE:
149153 fdb_info = ptr;
@@ -152,6 +156,11 @@ static int br_switchdev_event(struct notifier_block *unused, · 2 unmodified lines
152156 if (err)
153157 err = notifier_from_errno(err);
154158 break;
159+ case SWITCHDEV_FDB_OFFLOADED:
160+ fdb_info = ptr;
161+ br_fdb_offloaded_set(br, p, fdb_info->addr,
162+ fdb_info->vid);
163+ break;
155164 }
156165
157166 out:
net/bridge/br_fdb.c+21−1
@@ -511,6 +511,7 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, · 510 unmodified lines
511511 fdb->is_static = is_static;
512512 fdb->added_by_user = 0;
513513 fdb->added_by_external_learn = 0;
514+ fdb->offloaded = 0;
514515 fdb->updated = fdb->used = jiffies;
515516 hlist_add_head_rcu(&fdb->hlist, head);
516517 }
@@ -647,11 +648,16 @@ static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br, · 130 unmodified lines
647648 ndm->ndm_family = AF_BRIDGE;
648649 ndm->ndm_pad1 = 0;
649650 ndm->ndm_pad2 = 0;
650− ndm->ndm_flags = fdb->added_by_external_learn ? NTF_EXT_LEARNED : 0;
651+ ndm->ndm_flags = 0;
651652 ndm->ndm_type = 0;
652653 ndm->ndm_ifindex = fdb->dst ? fdb->dst->dev->ifindex : br->dev->ifindex;
653654 ndm->ndm_state = fdb_to_nud(br, fdb);
654655
656+ if (fdb->offloaded)
657+ ndm->ndm_flags |= NTF_OFFLOADED;
658+ if (fdb->added_by_external_learn)
659+ ndm->ndm_flags |= NTF_EXT_LEARNED;
660+
655661 if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr))
656662 goto nla_put_failure;
657663 if (nla_put_u32(skb, NDA_MASTER, br->dev->ifindex))
@@ -1123,3 +1129,17 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p, · 465 unmodified lines
11231129
11241130 return err;
11251131 }
1132+
1133+void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
1134+ const unsigned char *addr, u16 vid)
1135+{
1136+ struct net_bridge_fdb_entry *fdb;
1137+
1138+ spin_lock_bh(&br->hash_lock);
1139+
1140+ fdb = br_fdb_find(br, addr, vid);
1141+ if (fdb)
1142+ fdb->offloaded = 1;
1143+
1144+ spin_unlock_bh(&br->hash_lock);
1145+}
net/bridge/br_private.h+4−1
@@ -169,7 +169,8 @@ struct net_bridge_fdb_entry { · 168 unmodified lines
169169 unsigned char is_local:1,
170170 is_static:1,
171171 added_by_user:1,
172− added_by_external_learn:1;
172+ added_by_external_learn:1,
173+ offloaded:1;
173174
174175 /* write-heavy members should not affect lookups */
175176 unsigned long updated ____cacheline_aligned_in_smp;
@@ -536,6 +537,8 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p, · 360 unmodified lines
536537 const unsigned char *addr, u16 vid);
537538 int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
538539 const unsigned char *addr, u16 vid);
540+void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
541+ const unsigned char *addr, u16 vid);
539542
540543 /* br_forward.c */
541544 enum br_pkt_type {