summaryrefslogtreecommitdiffstats
path: root/net/dsa
diff options
context:
space:
mode:
authorVivien Didelot <vivien.didelot@savoirfairelinux.com>2017-05-19 17:00:53 -0400
committerDavid S. Miller <davem@davemloft.net>2017-05-22 19:37:32 -0400
commit685fb6a40ddace10a0bc8a680ab6ba65c6cdfdaf (patch)
tree258dc0f599d0e3ae686ce59ba7c5b84655328a7b /net/dsa
parent1faabf7440f17999f41973e91878c13ad9f080b2 (diff)
net: dsa: add FDB notifier
Add two new DSA_NOTIFIER_FDB_ADD and DSA_NOTIFIER_FDB_DEL events to notify not only a single switch, but all switches of a the fabric when an FDB entry is added or removed. For the moment, keep the current behavior and ignore other switches. Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa')
-rw-r--r--net/dsa/dsa_priv.h10
-rw-r--r--net/dsa/port.c29
-rw-r--r--net/dsa/switch.c43
3 files changed, 66 insertions, 16 deletions
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index becaf8a61b13..6a7d0d7d0489 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -20,6 +20,8 @@ enum {
20 DSA_NOTIFIER_AGEING_TIME, 20 DSA_NOTIFIER_AGEING_TIME,
21 DSA_NOTIFIER_BRIDGE_JOIN, 21 DSA_NOTIFIER_BRIDGE_JOIN,
22 DSA_NOTIFIER_BRIDGE_LEAVE, 22 DSA_NOTIFIER_BRIDGE_LEAVE,
23 DSA_NOTIFIER_FDB_ADD,
24 DSA_NOTIFIER_FDB_DEL,
23}; 25};
24 26
25/* DSA_NOTIFIER_AGEING_TIME */ 27/* DSA_NOTIFIER_AGEING_TIME */
@@ -36,6 +38,14 @@ struct dsa_notifier_bridge_info {
36 int port; 38 int port;
37}; 39};
38 40
41/* DSA_NOTIFIER_FDB_* */
42struct dsa_notifier_fdb_info {
43 const struct switchdev_obj_port_fdb *fdb;
44 struct switchdev_trans *trans;
45 int sw_index;
46 int port;
47};
48
39struct dsa_device_ops { 49struct dsa_device_ops {
40 struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev); 50 struct sk_buff *(*xmit)(struct sk_buff *skb, struct net_device *dev);
41 struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev, 51 struct sk_buff *(*rcv)(struct sk_buff *skb, struct net_device *dev,
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 59328a35394d..ed88d8381642 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -151,29 +151,26 @@ int dsa_port_fdb_add(struct dsa_port *dp,
151 const struct switchdev_obj_port_fdb *fdb, 151 const struct switchdev_obj_port_fdb *fdb,
152 struct switchdev_trans *trans) 152 struct switchdev_trans *trans)
153{ 153{
154 struct dsa_switch *ds = dp->ds; 154 struct dsa_notifier_fdb_info info = {
155 155 .sw_index = dp->ds->index,
156 if (switchdev_trans_ph_prepare(trans)) { 156 .port = dp->index,
157 if (!ds->ops->port_fdb_prepare || !ds->ops->port_fdb_add) 157 .trans = trans,
158 return -EOPNOTSUPP; 158 .fdb = fdb,
159 159 };
160 return ds->ops->port_fdb_prepare(ds, dp->index, fdb, trans);
161 }
162
163 ds->ops->port_fdb_add(ds, dp->index, fdb, trans);
164 160
165 return 0; 161 return dsa_port_notify(dp, DSA_NOTIFIER_FDB_ADD, &info);
166} 162}
167 163
168int dsa_port_fdb_del(struct dsa_port *dp, 164int dsa_port_fdb_del(struct dsa_port *dp,
169 const struct switchdev_obj_port_fdb *fdb) 165 const struct switchdev_obj_port_fdb *fdb)
170{ 166{
171 struct dsa_switch *ds = dp->ds; 167 struct dsa_notifier_fdb_info info = {
172 168 .sw_index = dp->ds->index,
173 if (ds->ops->port_fdb_del) 169 .port = dp->index,
174 return -EOPNOTSUPP; 170 .fdb = fdb,
171 };
175 172
176 return ds->ops->port_fdb_del(ds, dp->index, fdb); 173 return dsa_port_notify(dp, DSA_NOTIFIER_FDB_DEL, &info);
177} 174}
178 175
179int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb, 176int dsa_port_fdb_dump(struct dsa_port *dp, struct switchdev_obj_port_fdb *fdb,
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index 540770ecc8b0..e71cc860d32c 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -84,6 +84,43 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds,
84 return 0; 84 return 0;
85} 85}
86 86
87static int dsa_switch_fdb_add(struct dsa_switch *ds,
88 struct dsa_notifier_fdb_info *info)
89{
90 const struct switchdev_obj_port_fdb *fdb = info->fdb;
91 struct switchdev_trans *trans = info->trans;
92
93 /* Do not care yet about other switch chips of the fabric */
94 if (ds->index != info->sw_index)
95 return 0;
96
97 if (switchdev_trans_ph_prepare(trans)) {
98 if (!ds->ops->port_fdb_prepare || !ds->ops->port_fdb_add)
99 return -EOPNOTSUPP;
100
101 return ds->ops->port_fdb_prepare(ds, info->port, fdb, trans);
102 }
103
104 ds->ops->port_fdb_add(ds, info->port, fdb, trans);
105
106 return 0;
107}
108
109static int dsa_switch_fdb_del(struct dsa_switch *ds,
110 struct dsa_notifier_fdb_info *info)
111{
112 const struct switchdev_obj_port_fdb *fdb = info->fdb;
113
114 /* Do not care yet about other switch chips of the fabric */
115 if (ds->index != info->sw_index)
116 return 0;
117
118 if (!ds->ops->port_fdb_del)
119 return -EOPNOTSUPP;
120
121 return ds->ops->port_fdb_del(ds, info->port, fdb);
122}
123
87static int dsa_switch_event(struct notifier_block *nb, 124static int dsa_switch_event(struct notifier_block *nb,
88 unsigned long event, void *info) 125 unsigned long event, void *info)
89{ 126{
@@ -100,6 +137,12 @@ static int dsa_switch_event(struct notifier_block *nb,
100 case DSA_NOTIFIER_BRIDGE_LEAVE: 137 case DSA_NOTIFIER_BRIDGE_LEAVE:
101 err = dsa_switch_bridge_leave(ds, info); 138 err = dsa_switch_bridge_leave(ds, info);
102 break; 139 break;
140 case DSA_NOTIFIER_FDB_ADD:
141 err = dsa_switch_fdb_add(ds, info);
142 break;
143 case DSA_NOTIFIER_FDB_DEL:
144 err = dsa_switch_fdb_del(ds, info);
145 break;
103 default: 146 default:
104 err = -EOPNOTSUPP; 147 err = -EOPNOTSUPP;
105 break; 148 break;