Commit 9fe8bcec authored by Arkadi Sharshevsky's avatar Arkadi Sharshevsky Committed by David S. Miller

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: default avatarArkadi Sharshevsky <arkadis@mellanox.com>
Reviewed-by: default avatarIdo Schimmel <idosch@mellanox.com>
Reviewed-by: default avatarNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6b26b51b
...@@ -159,6 +159,7 @@ enum switchdev_notifier_type { ...@@ -159,6 +159,7 @@ enum switchdev_notifier_type {
SWITCHDEV_FDB_DEL_TO_BRIDGE, SWITCHDEV_FDB_DEL_TO_BRIDGE,
SWITCHDEV_FDB_ADD_TO_DEVICE, SWITCHDEV_FDB_ADD_TO_DEVICE,
SWITCHDEV_FDB_DEL_TO_DEVICE, SWITCHDEV_FDB_DEL_TO_DEVICE,
SWITCHDEV_FDB_OFFLOADED,
}; };
struct switchdev_notifier_info { struct switchdev_notifier_info {
......
...@@ -41,6 +41,7 @@ enum { ...@@ -41,6 +41,7 @@ enum {
#define NTF_MASTER 0x04 #define NTF_MASTER 0x04
#define NTF_PROXY 0x08 /* == ATF_PUBL */ #define NTF_PROXY 0x08 /* == ATF_PUBL */
#define NTF_EXT_LEARNED 0x10 #define NTF_EXT_LEARNED 0x10
#define NTF_OFFLOADED 0x20
#define NTF_ROUTER 0x80 #define NTF_ROUTER 0x80
/* /*
......
...@@ -142,8 +142,12 @@ static int br_switchdev_event(struct notifier_block *unused, ...@@ -142,8 +142,12 @@ static int br_switchdev_event(struct notifier_block *unused,
fdb_info = ptr; fdb_info = ptr;
err = br_fdb_external_learn_add(br, p, fdb_info->addr, err = br_fdb_external_learn_add(br, p, fdb_info->addr,
fdb_info->vid); fdb_info->vid);
if (err) if (err) {
err = notifier_from_errno(err); err = notifier_from_errno(err);
break;
}
br_fdb_offloaded_set(br, p, fdb_info->addr,
fdb_info->vid);
break; break;
case SWITCHDEV_FDB_DEL_TO_BRIDGE: case SWITCHDEV_FDB_DEL_TO_BRIDGE:
fdb_info = ptr; fdb_info = ptr;
...@@ -152,6 +156,11 @@ static int br_switchdev_event(struct notifier_block *unused, ...@@ -152,6 +156,11 @@ static int br_switchdev_event(struct notifier_block *unused,
if (err) if (err)
err = notifier_from_errno(err); err = notifier_from_errno(err);
break; break;
case SWITCHDEV_FDB_OFFLOADED:
fdb_info = ptr;
br_fdb_offloaded_set(br, p, fdb_info->addr,
fdb_info->vid);
break;
} }
out: out:
......
...@@ -511,6 +511,7 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, ...@@ -511,6 +511,7 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
fdb->is_static = is_static; fdb->is_static = is_static;
fdb->added_by_user = 0; fdb->added_by_user = 0;
fdb->added_by_external_learn = 0; fdb->added_by_external_learn = 0;
fdb->offloaded = 0;
fdb->updated = fdb->used = jiffies; fdb->updated = fdb->used = jiffies;
hlist_add_head_rcu(&fdb->hlist, head); hlist_add_head_rcu(&fdb->hlist, head);
} }
...@@ -647,11 +648,16 @@ static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br, ...@@ -647,11 +648,16 @@ static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br,
ndm->ndm_family = AF_BRIDGE; ndm->ndm_family = AF_BRIDGE;
ndm->ndm_pad1 = 0; ndm->ndm_pad1 = 0;
ndm->ndm_pad2 = 0; ndm->ndm_pad2 = 0;
ndm->ndm_flags = fdb->added_by_external_learn ? NTF_EXT_LEARNED : 0; ndm->ndm_flags = 0;
ndm->ndm_type = 0; ndm->ndm_type = 0;
ndm->ndm_ifindex = fdb->dst ? fdb->dst->dev->ifindex : br->dev->ifindex; ndm->ndm_ifindex = fdb->dst ? fdb->dst->dev->ifindex : br->dev->ifindex;
ndm->ndm_state = fdb_to_nud(br, fdb); ndm->ndm_state = fdb_to_nud(br, fdb);
if (fdb->offloaded)
ndm->ndm_flags |= NTF_OFFLOADED;
if (fdb->added_by_external_learn)
ndm->ndm_flags |= NTF_EXT_LEARNED;
if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr)) if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr))
goto nla_put_failure; goto nla_put_failure;
if (nla_put_u32(skb, NDA_MASTER, br->dev->ifindex)) 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, ...@@ -1123,3 +1129,17 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
return err; return err;
} }
void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
const unsigned char *addr, u16 vid)
{
struct net_bridge_fdb_entry *fdb;
spin_lock_bh(&br->hash_lock);
fdb = br_fdb_find(br, addr, vid);
if (fdb)
fdb->offloaded = 1;
spin_unlock_bh(&br->hash_lock);
}
...@@ -169,7 +169,8 @@ struct net_bridge_fdb_entry { ...@@ -169,7 +169,8 @@ struct net_bridge_fdb_entry {
unsigned char is_local:1, unsigned char is_local:1,
is_static:1, is_static:1,
added_by_user:1, added_by_user:1,
added_by_external_learn:1; added_by_external_learn:1,
offloaded:1;
/* write-heavy members should not affect lookups */ /* write-heavy members should not affect lookups */
unsigned long updated ____cacheline_aligned_in_smp; 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, ...@@ -536,6 +537,8 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
const unsigned char *addr, u16 vid); const unsigned char *addr, u16 vid);
int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p, int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
const unsigned char *addr, u16 vid); const unsigned char *addr, u16 vid);
void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
const unsigned char *addr, u16 vid);
/* br_forward.c */ /* br_forward.c */
enum br_pkt_type { enum br_pkt_type {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment