aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Pirko <jiri@mellanox.com>2015-10-14 13:40:51 -0400
committerDavid S. Miller <davem@davemloft.net>2015-10-15 09:09:49 -0400
commit850d0cbc9171f63f0418afffb0d89a84db927851 (patch)
tree21ecd5e1adb0d14f8c455484d57795d0a86379ea
parent0bc05d585d381c30de3fdf955730df31593d2101 (diff)
switchdev: remove pointers from switchdev objects
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>
-rw-r--r--drivers/net/ethernet/rocker/rocker.c6
-rw-r--r--include/net/switchdev.h7
-rw-r--r--net/bridge/br_fdb.c2
-rw-r--r--net/dsa/slave.c2
-rw-r--r--net/switchdev/switchdev.c11
5 files changed, 15 insertions, 13 deletions
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
index f0e820d2b8ec..2cd7435b2316 100644
--- a/drivers/net/ethernet/rocker/rocker.c
+++ b/drivers/net/ethernet/rocker/rocker.c
@@ -4469,7 +4469,7 @@ static int rocker_port_obj_add(struct net_device *dev,
4469 fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj); 4469 fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj);
4470 err = rocker_port_fib_ipv4(rocker_port, trans, 4470 err = rocker_port_fib_ipv4(rocker_port, trans,
4471 htonl(fib4->dst), fib4->dst_len, 4471 htonl(fib4->dst), fib4->dst_len,
4472 fib4->fi, fib4->tb_id, 0); 4472 &fib4->fi, fib4->tb_id, 0);
4473 break; 4473 break;
4474 case SWITCHDEV_OBJ_ID_PORT_FDB: 4474 case SWITCHDEV_OBJ_ID_PORT_FDB:
4475 err = rocker_port_fdb_add(rocker_port, trans, 4475 err = rocker_port_fdb_add(rocker_port, trans,
@@ -4541,7 +4541,7 @@ static int rocker_port_obj_del(struct net_device *dev,
4541 fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj); 4541 fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj);
4542 err = rocker_port_fib_ipv4(rocker_port, NULL, 4542 err = rocker_port_fib_ipv4(rocker_port, NULL,
4543 htonl(fib4->dst), fib4->dst_len, 4543 htonl(fib4->dst), fib4->dst_len,
4544 fib4->fi, fib4->tb_id, 4544 &fib4->fi, fib4->tb_id,
4545 ROCKER_OP_FLAG_REMOVE); 4545 ROCKER_OP_FLAG_REMOVE);
4546 break; 4546 break;
4547 case SWITCHDEV_OBJ_ID_PORT_FDB: 4547 case SWITCHDEV_OBJ_ID_PORT_FDB:
@@ -4571,7 +4571,7 @@ static int rocker_port_fdb_dump(const struct rocker_port *rocker_port,
4571 hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, found, entry) { 4571 hash_for_each_safe(rocker->fdb_tbl, bkt, tmp, found, entry) {
4572 if (found->key.rocker_port != rocker_port) 4572 if (found->key.rocker_port != rocker_port)
4573 continue; 4573 continue;
4574 fdb->addr = found->key.addr; 4574 ether_addr_copy(fdb->addr, found->key.addr);
4575 fdb->ndm_state = NUD_REACHABLE; 4575 fdb->ndm_state = NUD_REACHABLE;
4576 fdb->vid = rocker_port_vlan_to_vid(rocker_port, 4576 fdb->vid = rocker_port_vlan_to_vid(rocker_port,
4577 found->key.vlan_id); 4577 found->key.vlan_id);
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index f7de6f8e9a4c..f8672d7f3ff2 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -14,6 +14,7 @@
14#include <linux/netdevice.h> 14#include <linux/netdevice.h>
15#include <linux/notifier.h> 15#include <linux/notifier.h>
16#include <linux/list.h> 16#include <linux/list.h>
17#include <net/ip_fib.h>
17 18
18#define SWITCHDEV_F_NO_RECURSE BIT(0) 19#define SWITCHDEV_F_NO_RECURSE BIT(0)
19#define SWITCHDEV_F_SKIP_EOPNOTSUPP BIT(1) 20#define SWITCHDEV_F_SKIP_EOPNOTSUPP BIT(1)
@@ -59,8 +60,6 @@ struct switchdev_attr {
59 } u; 60 } u;
60}; 61};
61 62
62struct fib_info;
63
64enum switchdev_obj_id { 63enum switchdev_obj_id {
65 SWITCHDEV_OBJ_ID_UNDEFINED, 64 SWITCHDEV_OBJ_ID_UNDEFINED,
66 SWITCHDEV_OBJ_ID_PORT_VLAN, 65 SWITCHDEV_OBJ_ID_PORT_VLAN,
@@ -88,7 +87,7 @@ struct switchdev_obj_ipv4_fib {
88 struct switchdev_obj obj; 87 struct switchdev_obj obj;
89 u32 dst; 88 u32 dst;
90 int dst_len; 89 int dst_len;
91 struct fib_info *fi; 90 struct fib_info fi;
92 u8 tos; 91 u8 tos;
93 u8 type; 92 u8 type;
94 u32 nlflags; 93 u32 nlflags;
@@ -101,7 +100,7 @@ struct switchdev_obj_ipv4_fib {
101/* SWITCHDEV_OBJ_ID_PORT_FDB */ 100/* SWITCHDEV_OBJ_ID_PORT_FDB */
102struct switchdev_obj_port_fdb { 101struct switchdev_obj_port_fdb {
103 struct switchdev_obj obj; 102 struct switchdev_obj obj;
104 const unsigned char *addr; 103 unsigned char addr[ETH_ALEN];
105 u16 vid; 104 u16 vid;
106 u16 ndm_state; 105 u16 ndm_state;
107}; 106};
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index f43ce05c66a6..f5e7da0fe93b 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -135,10 +135,10 @@ static void fdb_del_external_learn(struct net_bridge_fdb_entry *f)
135{ 135{
136 struct switchdev_obj_port_fdb fdb = { 136 struct switchdev_obj_port_fdb fdb = {
137 .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB, 137 .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB,
138 .addr = f->addr.addr,
139 .vid = f->vlan_id, 138 .vid = f->vlan_id,
140 }; 139 };
141 140
141 ether_addr_copy(fdb.addr, f->addr.addr);
142 switchdev_port_obj_del(f->dst->dev, &fdb.obj); 142 switchdev_port_obj_del(f->dst->dev, &fdb.obj);
143} 143}
144 144
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 84cd8639e37b..b0b8da0f5af8 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -393,7 +393,7 @@ static int dsa_slave_port_fdb_dump(struct net_device *dev,
393 if (ret < 0) 393 if (ret < 0)
394 break; 394 break;
395 395
396 fdb->addr = addr; 396 ether_addr_copy(fdb->addr, addr);
397 fdb->vid = vid; 397 fdb->vid = vid;
398 fdb->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE; 398 fdb->ndm_state = is_static ? NUD_NOARP : NUD_REACHABLE;
399 399
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index 007b8f40df06..5963d7ac1026 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -15,6 +15,7 @@
15#include <linux/mutex.h> 15#include <linux/mutex.h>
16#include <linux/notifier.h> 16#include <linux/notifier.h>
17#include <linux/netdevice.h> 17#include <linux/netdevice.h>
18#include <linux/etherdevice.h>
18#include <linux/if_bridge.h> 19#include <linux/if_bridge.h>
19#include <linux/list.h> 20#include <linux/list.h>
20#include <linux/workqueue.h> 21#include <linux/workqueue.h>
@@ -891,10 +892,10 @@ int switchdev_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
891{ 892{
892 struct switchdev_obj_port_fdb fdb = { 893 struct switchdev_obj_port_fdb fdb = {
893 .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB, 894 .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB,
894 .addr = addr,
895 .vid = vid, 895 .vid = vid,
896 }; 896 };
897 897
898 ether_addr_copy(fdb.addr, addr);
898 return switchdev_port_obj_add(dev, &fdb.obj); 899 return switchdev_port_obj_add(dev, &fdb.obj);
899} 900}
900EXPORT_SYMBOL_GPL(switchdev_port_fdb_add); 901EXPORT_SYMBOL_GPL(switchdev_port_fdb_add);
@@ -916,10 +917,10 @@ int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
916{ 917{
917 struct switchdev_obj_port_fdb fdb = { 918 struct switchdev_obj_port_fdb fdb = {
918 .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB, 919 .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB,
919 .addr = addr,
920 .vid = vid, 920 .vid = vid,
921 }; 921 };
922 922
923 ether_addr_copy(fdb.addr, addr);
923 return switchdev_port_obj_del(dev, &fdb.obj); 924 return switchdev_port_obj_del(dev, &fdb.obj);
924} 925}
925EXPORT_SYMBOL_GPL(switchdev_port_fdb_del); 926EXPORT_SYMBOL_GPL(switchdev_port_fdb_del);
@@ -1081,7 +1082,6 @@ int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi,
1081 .obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB, 1082 .obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB,
1082 .dst = dst, 1083 .dst = dst,
1083 .dst_len = dst_len, 1084 .dst_len = dst_len,
1084 .fi = fi,
1085 .tos = tos, 1085 .tos = tos,
1086 .type = type, 1086 .type = type,
1087 .nlflags = nlflags, 1087 .nlflags = nlflags,
@@ -1090,6 +1090,8 @@ int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi,
1090 struct net_device *dev; 1090 struct net_device *dev;
1091 int err = 0; 1091 int err = 0;
1092 1092
1093 memcpy(&ipv4_fib.fi, fi, sizeof(ipv4_fib.fi));
1094
1093 /* Don't offload route if using custom ip rules or if 1095 /* Don't offload route if using custom ip rules or if
1094 * IPv4 FIB offloading has been disabled completely. 1096 * IPv4 FIB offloading has been disabled completely.
1095 */ 1097 */
@@ -1133,7 +1135,6 @@ int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi,
1133 .obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB, 1135 .obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB,
1134 .dst = dst, 1136 .dst = dst,
1135 .dst_len = dst_len, 1137 .dst_len = dst_len,
1136 .fi = fi,
1137 .tos = tos, 1138 .tos = tos,
1138 .type = type, 1139 .type = type,
1139 .nlflags = 0, 1140 .nlflags = 0,
@@ -1142,6 +1143,8 @@ int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi,
1142 struct net_device *dev; 1143 struct net_device *dev;
1143 int err = 0; 1144 int err = 0;
1144 1145
1146 memcpy(&ipv4_fib.fi, fi, sizeof(ipv4_fib.fi));
1147
1145 if (!(fi->fib_flags & RTNH_F_OFFLOAD)) 1148 if (!(fi->fib_flags & RTNH_F_OFFLOAD))
1146 return 0; 1149 return 0;
1147 1150