Commit fab9eca8 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller

net: bridge: create a common function for populating switchdev FDB entries

There are two places where a switchdev FDB entry is constructed, one is
br_switchdev_fdb_notify() and the other is br_fdb_replay(). One uses a
struct initializer, and the other declares the structure as
uninitialized and populates the elements one by one.

One problem when introducing new members of struct
switchdev_notifier_fdb_info is that there is a risk for one of these
functions to run with an uninitialized value.

So centralize the logic of populating such structure into a dedicated
function. Being the primary location where these structures are created,
using an uninitialized variable and populating the members one by one
should be fine, since this one function is supposed to assign values to
all its members.
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: default avatarIdo Schimmel <idosch@nvidia.com>
Acked-by: default avatarNikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5cda5272
......@@ -122,28 +122,38 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
return 0;
}
static void br_switchdev_fdb_populate(struct net_bridge *br,
struct switchdev_notifier_fdb_info *item,
const struct net_bridge_fdb_entry *fdb,
const void *ctx)
{
const struct net_bridge_port *p = READ_ONCE(fdb->dst);
item->addr = fdb->key.addr.addr;
item->vid = fdb->key.vlan_id;
item->added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
item->offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags);
item->is_local = test_bit(BR_FDB_LOCAL, &fdb->flags);
item->info.dev = (!p || item->is_local) ? br->dev : p->dev;
item->info.ctx = ctx;
}
void
br_switchdev_fdb_notify(struct net_bridge *br,
const struct net_bridge_fdb_entry *fdb, int type)
{
const struct net_bridge_port *dst = READ_ONCE(fdb->dst);
struct switchdev_notifier_fdb_info info = {
.addr = fdb->key.addr.addr,
.vid = fdb->key.vlan_id,
.added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags),
.is_local = test_bit(BR_FDB_LOCAL, &fdb->flags),
.offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags),
};
struct net_device *dev = (!dst || info.is_local) ? br->dev : dst->dev;
struct switchdev_notifier_fdb_info item;
br_switchdev_fdb_populate(br, &item, fdb, NULL);
switch (type) {
case RTM_DELNEIGH:
call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_DEVICE,
dev, &info.info, NULL);
item.info.dev, &item.info, NULL);
break;
case RTM_NEWNEIGH:
call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_DEVICE,
dev, &info.info, NULL);
item.info.dev, &item.info, NULL);
break;
}
}
......@@ -274,17 +284,10 @@ static int br_fdb_replay_one(struct net_bridge *br, struct notifier_block *nb,
const struct net_bridge_fdb_entry *fdb,
unsigned long action, const void *ctx)
{
const struct net_bridge_port *p = READ_ONCE(fdb->dst);
struct switchdev_notifier_fdb_info item;
int err;
item.addr = fdb->key.addr.addr;
item.vid = fdb->key.vlan_id;
item.added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
item.offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags);
item.is_local = test_bit(BR_FDB_LOCAL, &fdb->flags);
item.info.dev = (!p || item.is_local) ? br->dev : p->dev;
item.info.ctx = ctx;
br_switchdev_fdb_populate(br, &item, fdb, ctx);
err = nb->notifier_call(nb, action, &item);
return notifier_to_errno(err);
......
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