aboutsummaryrefslogtreecommitdiffstats
path: root/net/switchdev/switchdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/switchdev/switchdev.c')
-rw-r--r--net/switchdev/switchdev.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index f34e535e93bd..47f7da58a7f0 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -20,6 +20,7 @@
20#include <linux/list.h> 20#include <linux/list.h>
21#include <linux/workqueue.h> 21#include <linux/workqueue.h>
22#include <linux/if_vlan.h> 22#include <linux/if_vlan.h>
23#include <linux/rtnetlink.h>
23#include <net/ip_fib.h> 24#include <net/ip_fib.h>
24#include <net/switchdev.h> 25#include <net/switchdev.h>
25 26
@@ -345,6 +346,8 @@ static size_t switchdev_obj_size(const struct switchdev_obj *obj)
345 return sizeof(struct switchdev_obj_ipv4_fib); 346 return sizeof(struct switchdev_obj_ipv4_fib);
346 case SWITCHDEV_OBJ_ID_PORT_FDB: 347 case SWITCHDEV_OBJ_ID_PORT_FDB:
347 return sizeof(struct switchdev_obj_port_fdb); 348 return sizeof(struct switchdev_obj_port_fdb);
349 case SWITCHDEV_OBJ_ID_PORT_MDB:
350 return sizeof(struct switchdev_obj_port_mdb);
348 default: 351 default:
349 BUG(); 352 BUG();
350 } 353 }
@@ -565,7 +568,6 @@ int switchdev_port_obj_dump(struct net_device *dev, struct switchdev_obj *obj,
565} 568}
566EXPORT_SYMBOL_GPL(switchdev_port_obj_dump); 569EXPORT_SYMBOL_GPL(switchdev_port_obj_dump);
567 570
568static DEFINE_MUTEX(switchdev_mutex);
569static RAW_NOTIFIER_HEAD(switchdev_notif_chain); 571static RAW_NOTIFIER_HEAD(switchdev_notif_chain);
570 572
571/** 573/**
@@ -580,9 +582,9 @@ int register_switchdev_notifier(struct notifier_block *nb)
580{ 582{
581 int err; 583 int err;
582 584
583 mutex_lock(&switchdev_mutex); 585 rtnl_lock();
584 err = raw_notifier_chain_register(&switchdev_notif_chain, nb); 586 err = raw_notifier_chain_register(&switchdev_notif_chain, nb);
585 mutex_unlock(&switchdev_mutex); 587 rtnl_unlock();
586 return err; 588 return err;
587} 589}
588EXPORT_SYMBOL_GPL(register_switchdev_notifier); 590EXPORT_SYMBOL_GPL(register_switchdev_notifier);
@@ -598,9 +600,9 @@ int unregister_switchdev_notifier(struct notifier_block *nb)
598{ 600{
599 int err; 601 int err;
600 602
601 mutex_lock(&switchdev_mutex); 603 rtnl_lock();
602 err = raw_notifier_chain_unregister(&switchdev_notif_chain, nb); 604 err = raw_notifier_chain_unregister(&switchdev_notif_chain, nb);
603 mutex_unlock(&switchdev_mutex); 605 rtnl_unlock();
604 return err; 606 return err;
605} 607}
606EXPORT_SYMBOL_GPL(unregister_switchdev_notifier); 608EXPORT_SYMBOL_GPL(unregister_switchdev_notifier);
@@ -614,16 +616,17 @@ EXPORT_SYMBOL_GPL(unregister_switchdev_notifier);
614 * Call all network notifier blocks. This should be called by driver 616 * Call all network notifier blocks. This should be called by driver
615 * when it needs to propagate hardware event. 617 * when it needs to propagate hardware event.
616 * Return values are same as for atomic_notifier_call_chain(). 618 * Return values are same as for atomic_notifier_call_chain().
619 * rtnl_lock must be held.
617 */ 620 */
618int call_switchdev_notifiers(unsigned long val, struct net_device *dev, 621int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
619 struct switchdev_notifier_info *info) 622 struct switchdev_notifier_info *info)
620{ 623{
621 int err; 624 int err;
622 625
626 ASSERT_RTNL();
627
623 info->dev = dev; 628 info->dev = dev;
624 mutex_lock(&switchdev_mutex);
625 err = raw_notifier_call_chain(&switchdev_notif_chain, val, info); 629 err = raw_notifier_call_chain(&switchdev_notif_chain, val, info);
626 mutex_unlock(&switchdev_mutex);
627 return err; 630 return err;
628} 631}
629EXPORT_SYMBOL_GPL(call_switchdev_notifiers); 632EXPORT_SYMBOL_GPL(call_switchdev_notifiers);
@@ -723,6 +726,7 @@ static int switchdev_port_vlan_fill(struct sk_buff *skb, struct net_device *dev,
723 u32 filter_mask) 726 u32 filter_mask)
724{ 727{
725 struct switchdev_vlan_dump dump = { 728 struct switchdev_vlan_dump dump = {
729 .vlan.obj.orig_dev = dev,
726 .vlan.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, 730 .vlan.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
727 .skb = skb, 731 .skb = skb,
728 .filter_mask = filter_mask, 732 .filter_mask = filter_mask,
@@ -757,6 +761,7 @@ int switchdev_port_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
757 int nlflags) 761 int nlflags)
758{ 762{
759 struct switchdev_attr attr = { 763 struct switchdev_attr attr = {
764 .orig_dev = dev,
760 .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, 765 .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS,
761 }; 766 };
762 u16 mode = BRIDGE_MODE_UNDEF; 767 u16 mode = BRIDGE_MODE_UNDEF;
@@ -778,6 +783,7 @@ static int switchdev_port_br_setflag(struct net_device *dev,
778 unsigned long brport_flag) 783 unsigned long brport_flag)
779{ 784{
780 struct switchdev_attr attr = { 785 struct switchdev_attr attr = {
786 .orig_dev = dev,
781 .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS, 787 .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS,
782 }; 788 };
783 u8 flag = nla_get_u8(nlattr); 789 u8 flag = nla_get_u8(nlattr);
@@ -853,6 +859,7 @@ static int switchdev_port_br_afspec(struct net_device *dev,
853 struct nlattr *attr; 859 struct nlattr *attr;
854 struct bridge_vlan_info *vinfo; 860 struct bridge_vlan_info *vinfo;
855 struct switchdev_obj_port_vlan vlan = { 861 struct switchdev_obj_port_vlan vlan = {
862 .obj.orig_dev = dev,
856 .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN, 863 .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
857 }; 864 };
858 int rem; 865 int rem;
@@ -975,6 +982,7 @@ int switchdev_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
975 u16 vid, u16 nlm_flags) 982 u16 vid, u16 nlm_flags)
976{ 983{
977 struct switchdev_obj_port_fdb fdb = { 984 struct switchdev_obj_port_fdb fdb = {
985 .obj.orig_dev = dev,
978 .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB, 986 .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB,
979 .vid = vid, 987 .vid = vid,
980 }; 988 };
@@ -1000,6 +1008,7 @@ int switchdev_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
1000 u16 vid) 1008 u16 vid)
1001{ 1009{
1002 struct switchdev_obj_port_fdb fdb = { 1010 struct switchdev_obj_port_fdb fdb = {
1011 .obj.orig_dev = dev,
1003 .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB, 1012 .obj.id = SWITCHDEV_OBJ_ID_PORT_FDB,
1004 .vid = vid, 1013 .vid = vid,
1005 }; 1014 };
@@ -1077,6 +1086,7 @@ int switchdev_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
1077 struct net_device *filter_dev, int idx) 1086 struct net_device *filter_dev, int idx)
1078{ 1087{
1079 struct switchdev_fdb_dump dump = { 1088 struct switchdev_fdb_dump dump = {
1089 .fdb.obj.orig_dev = dev,
1080 .fdb.obj.id = SWITCHDEV_OBJ_ID_PORT_FDB, 1090 .fdb.obj.id = SWITCHDEV_OBJ_ID_PORT_FDB,
1081 .dev = dev, 1091 .dev = dev,
1082 .skb = skb, 1092 .skb = skb,
@@ -1135,6 +1145,7 @@ static struct net_device *switchdev_get_dev_by_nhs(struct fib_info *fi)
1135 if (!dev) 1145 if (!dev)
1136 return NULL; 1146 return NULL;
1137 1147
1148 attr.orig_dev = dev;
1138 if (switchdev_port_attr_get(dev, &attr)) 1149 if (switchdev_port_attr_get(dev, &attr))
1139 return NULL; 1150 return NULL;
1140 1151
@@ -1194,6 +1205,7 @@ int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi,
1194 if (!dev) 1205 if (!dev)
1195 return 0; 1206 return 0;
1196 1207
1208 ipv4_fib.obj.orig_dev = dev;
1197 err = switchdev_port_obj_add(dev, &ipv4_fib.obj); 1209 err = switchdev_port_obj_add(dev, &ipv4_fib.obj);
1198 if (!err) 1210 if (!err)
1199 fi->fib_flags |= RTNH_F_OFFLOAD; 1211 fi->fib_flags |= RTNH_F_OFFLOAD;
@@ -1238,6 +1250,7 @@ int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi,
1238 if (!dev) 1250 if (!dev)
1239 return 0; 1251 return 0;
1240 1252
1253 ipv4_fib.obj.orig_dev = dev;
1241 err = switchdev_port_obj_del(dev, &ipv4_fib.obj); 1254 err = switchdev_port_obj_del(dev, &ipv4_fib.obj);
1242 if (!err) 1255 if (!err)
1243 fi->fib_flags &= ~RTNH_F_OFFLOAD; 1256 fi->fib_flags &= ~RTNH_F_OFFLOAD;
@@ -1270,10 +1283,12 @@ static bool switchdev_port_same_parent_id(struct net_device *a,
1270 struct net_device *b) 1283 struct net_device *b)
1271{ 1284{
1272 struct switchdev_attr a_attr = { 1285 struct switchdev_attr a_attr = {
1286 .orig_dev = a,
1273 .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, 1287 .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID,
1274 .flags = SWITCHDEV_F_NO_RECURSE, 1288 .flags = SWITCHDEV_F_NO_RECURSE,
1275 }; 1289 };
1276 struct switchdev_attr b_attr = { 1290 struct switchdev_attr b_attr = {
1291 .orig_dev = b,
1277 .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, 1292 .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID,
1278 .flags = SWITCHDEV_F_NO_RECURSE, 1293 .flags = SWITCHDEV_F_NO_RECURSE,
1279 }; 1294 };