Skip to content

Commit

Permalink
switchdev: remove pointers from switchdev objects
Browse files Browse the repository at this point in the history
When object is used in deferred work, we cannot use pointers in
switchdev object structures because the memory they point at may be already
used by someone else. So rather do local copy of the value.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Acked-by: Scott Feldman <sfeldma@gmail.com>
Reviewed-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jiri Pirko authored and David S. Miller committed Oct 15, 2015
1 parent 0bc05d5 commit 850d0cb
Show file tree
Hide file tree
Showing 5 changed files with 15 additions and 13 deletions.
6 changes: 3 additions & 3 deletions drivers/net/ethernet/rocker/rocker.c
Original file line number Diff line number Diff line change
Expand Up @@ -4469,7 +4469,7 @@ static int rocker_port_obj_add(struct net_device *dev,
fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj);
err = rocker_port_fib_ipv4(rocker_port, trans,
htonl(fib4->dst), fib4->dst_len,
fib4->fi, fib4->tb_id, 0);
&fib4->fi, fib4->tb_id, 0);
break;
case SWITCHDEV_OBJ_ID_PORT_FDB:
err = rocker_port_fdb_add(rocker_port, trans,
Expand Down Expand Up @@ -4541,7 +4541,7 @@ static int rocker_port_obj_del(struct net_device *dev,
fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj);
err = rocker_port_fib_ipv4(rocker_port, NULL,
htonl(fib4->dst), fib4->dst_len,
fib4->fi, fib4->tb_id,
&fib4->fi, fib4->tb_id,
ROCKER_OP_FLAG_REMOVE);
break;
case SWITCHDEV_OBJ_ID_PORT_FDB:
Expand Down Expand Up @@ -4571,7 +4571,7 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port,
hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, found, entry) {
if (found->key.rocker_port != rocker_port)
continue;
fdb->addr = found->key.addr;
ether_addr_copy(fdb->addr, found->key.addr);
fdb->ndm_state = NUD_REACHABLE;
fdb->vid = rocker_port_vlan_to_vid(rocker_port,
found->key.vlan_id);
Expand Down
7 changes: 3 additions & 4 deletions include/net/switchdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/netdevice.h>
#include <linux/notifier.h>
#include <linux/list.h>
#include <net/ip_fib.h>

#define SWITCHDEV_F_NO_RECURSE BIT(0)
#define SWITCHDEV_F_SKIP_EOPNOTSUPP BIT(1)
Expand Down Expand Up @@ -59,8 +60,6 @@ struct switchdev_attr {
} u;
};

struct fib_info;

enum switchdev_obj_id {
SWITCHDEV_OBJ_ID_UNDEFINED,
SWITCHDEV_OBJ_ID_PORT_VLAN,
Expand Down Expand Up @@ -88,7 +87,7 @@ struct switchdev_obj_ipv4_fib {
struct switchdev_obj obj;
u32 dst;
int dst_len;
struct fib_info *fi;
struct fib_info fi;
u8 tos;
u8 type;
u32 nlflags;
Expand All @@ -101,7 +100,7 @@ struct switchdev_obj_ipv4_fib {
/* SWITCHDEV_OBJ_ID_PORT_FDB */
struct switchdev_obj_port_fdb {
struct switchdev_obj obj;
const unsigned char *addr;
unsigned char addr[ETH_ALEN];
u16 vid;
u16 ndm_state;
};
Expand Down
2 changes: 1 addition & 1 deletion net/bridge/br_fdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@ static void fdb_del_external_learn(struct net_bridge_fdb_entry *f)
{
struct switchdev_obj_port_fdb fdb = {
.obj.id = SWITCHDEV_OBJ_ID_PORT_FDB,
.addr = f->addr.addr,
.vid = f->vlan_id,
};

ether_addr_copy(fdb.addr, f->addr.addr);
switchdev_port_obj_del(f->dst->dev, &fdb.obj);
}

Expand Down
2 changes: 1 addition & 1 deletion net/dsa/slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ static int dsa_slave_port_fdb_dump(struct net_device *dev,
if (ret < 0)
break;

fdb->addr = addr;
ether_addr_copy(fdb->addr, addr);
fdb->vid = vid;
fdb->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;

Expand Down
11 changes: 7 additions & 4 deletions net/switchdev/switchdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/mutex.h>
#include <linux/notifier.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
#include <linux/list.h>
#include <linux/workqueue.h>
Expand Down Expand Up @@ -891,10 +892,10 @@ int switchdev_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
{
struct switchdev_obj_port_fdb fdb = {
.obj.id = SWITCHDEV_OBJ_ID_PORT_FDB,
.addr = addr,
.vid = vid,
};

ether_addr_copy(fdb.addr, addr);
return switchdev_port_obj_add(dev, &fdb.obj);
}
EXPORT_SYMBOL_GPL(switchdev_port_fdb_add);
Expand All @@ -916,10 +917,10 @@ int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
{
struct switchdev_obj_port_fdb fdb = {
.obj.id = SWITCHDEV_OBJ_ID_PORT_FDB,
.addr = addr,
.vid = vid,
};

ether_addr_copy(fdb.addr, addr);
return switchdev_port_obj_del(dev, &fdb.obj);
}
EXPORT_SYMBOL_GPL(switchdev_port_fdb_del);
Expand Down Expand Up @@ -1081,7 +1082,6 @@ int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi,
.obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB,
.dst = dst,
.dst_len = dst_len,
.fi = fi,
.tos = tos,
.type = type,
.nlflags = nlflags,
Expand All @@ -1090,6 +1090,8 @@ int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi,
struct net_device *dev;
int err = 0;

memcpy(&ipv4_fib.fi, fi, sizeof(ipv4_fib.fi));

/* Don't offload route if using custom ip rules or if
* IPv4 FIB offloading has been disabled completely.
*/
Expand Down Expand Up @@ -1133,7 +1135,6 @@ int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi,
.obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB,
.dst = dst,
.dst_len = dst_len,
.fi = fi,
.tos = tos,
.type = type,
.nlflags = 0,
Expand All @@ -1142,6 +1143,8 @@ int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi,
struct net_device *dev;
int err = 0;

memcpy(&ipv4_fib.fi, fi, sizeof(ipv4_fib.fi));

if (!(fi->fib_flags & RTNH_F_OFFLOAD))
return 0;

Expand Down

0 comments on commit 850d0cb

Please sign in to comment.