switchdev: remove pointers from switchdev objects
authorJiri Pirko <jiri@mellanox.com>
Wed, 14 Oct 2015 17:40:51 +0000 (19:40 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 15 Oct 2015 13:09:49 +0000 (06:09 -0700)
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>
drivers/net/ethernet/rocker/rocker.c
include/net/switchdev.h
net/bridge/br_fdb.c
net/dsa/slave.c
net/switchdev/switchdev.c

index f0e820d2b8ec58a153be32570bdf309c70c57cff..2cd7435b2316cbcb56b45a8877f65ab668986374 100644 (file)
@@ -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,
@@ -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:
@@ -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);
index f7de6f8e9a4c857e92af46eed54d2acaf3f2300f..f8672d7f3ff2b4e3bd977b35774097fcebc6f5b1 100644 (file)
@@ -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)
@@ -59,8 +60,6 @@ struct switchdev_attr {
        } u;
 };
 
-struct fib_info;
-
 enum switchdev_obj_id {
        SWITCHDEV_OBJ_ID_UNDEFINED,
        SWITCHDEV_OBJ_ID_PORT_VLAN,
@@ -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;
@@ -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;
 };
index f43ce05c66a6727f765fe76973d5c9b159955821..f5e7da0fe93b549d2a9c249f18498b5f9ca353ec 100644 (file)
@@ -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);
 }
 
index 84cd8639e37beaec6645bc1bb9c6d7744dcab319..b0b8da0f5af890efd18fe15ca99e2e56dd428112 100644 (file)
@@ -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;
 
index 007b8f40df069b0d9d0fda7fb9eb759fcbd86d97..5963d7ac10268a1e90956878d3327365b27e3f0b 100644 (file)
@@ -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>
@@ -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);
@@ -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);
@@ -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,
@@ -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.
         */
@@ -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,
@@ -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;