~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/dsa/switch.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  * Handling of a single switch chip, part of a switch fabric
  4  *
  5  * Copyright (c) 2017 Savoir-faire Linux Inc.
  6  *      Vivien Didelot <vivien.didelot@savoirfairelinux.com>
  7  */
  8 
  9 #include <linux/if_bridge.h>
 10 #include <linux/netdevice.h>
 11 #include <linux/notifier.h>
 12 #include <linux/if_vlan.h>
 13 #include <net/switchdev.h>
 14 
 15 #include "dsa.h"
 16 #include "netlink.h"
 17 #include "port.h"
 18 #include "switch.h"
 19 #include "tag_8021q.h"
 20 #include "trace.h"
 21 #include "user.h"
 22 
 23 static unsigned int dsa_switch_fastest_ageing_time(struct dsa_switch *ds,
 24                                                    unsigned int ageing_time)
 25 {
 26         struct dsa_port *dp;
 27 
 28         dsa_switch_for_each_port(dp, ds)
 29                 if (dp->ageing_time && dp->ageing_time < ageing_time)
 30                         ageing_time = dp->ageing_time;
 31 
 32         return ageing_time;
 33 }
 34 
 35 static int dsa_switch_ageing_time(struct dsa_switch *ds,
 36                                   struct dsa_notifier_ageing_time_info *info)
 37 {
 38         unsigned int ageing_time = info->ageing_time;
 39 
 40         if (ds->ageing_time_min && ageing_time < ds->ageing_time_min)
 41                 return -ERANGE;
 42 
 43         if (ds->ageing_time_max && ageing_time > ds->ageing_time_max)
 44                 return -ERANGE;
 45 
 46         /* Program the fastest ageing time in case of multiple bridges */
 47         ageing_time = dsa_switch_fastest_ageing_time(ds, ageing_time);
 48 
 49         if (ds->ops->set_ageing_time)
 50                 return ds->ops->set_ageing_time(ds, ageing_time);
 51 
 52         return 0;
 53 }
 54 
 55 static bool dsa_port_mtu_match(struct dsa_port *dp,
 56                                struct dsa_notifier_mtu_info *info)
 57 {
 58         return dp == info->dp || dsa_port_is_dsa(dp) || dsa_port_is_cpu(dp);
 59 }
 60 
 61 static int dsa_switch_mtu(struct dsa_switch *ds,
 62                           struct dsa_notifier_mtu_info *info)
 63 {
 64         struct dsa_port *dp;
 65         int ret;
 66 
 67         if (!ds->ops->port_change_mtu)
 68                 return -EOPNOTSUPP;
 69 
 70         dsa_switch_for_each_port(dp, ds) {
 71                 if (dsa_port_mtu_match(dp, info)) {
 72                         ret = ds->ops->port_change_mtu(ds, dp->index,
 73                                                        info->mtu);
 74                         if (ret)
 75                                 return ret;
 76                 }
 77         }
 78 
 79         return 0;
 80 }
 81 
 82 static int dsa_switch_bridge_join(struct dsa_switch *ds,
 83                                   struct dsa_notifier_bridge_info *info)
 84 {
 85         int err;
 86 
 87         if (info->dp->ds == ds) {
 88                 if (!ds->ops->port_bridge_join)
 89                         return -EOPNOTSUPP;
 90 
 91                 err = ds->ops->port_bridge_join(ds, info->dp->index,
 92                                                 info->bridge,
 93                                                 &info->tx_fwd_offload,
 94                                                 info->extack);
 95                 if (err)
 96                         return err;
 97         }
 98 
 99         if (info->dp->ds != ds && ds->ops->crosschip_bridge_join) {
100                 err = ds->ops->crosschip_bridge_join(ds,
101                                                      info->dp->ds->dst->index,
102                                                      info->dp->ds->index,
103                                                      info->dp->index,
104                                                      info->bridge,
105                                                      info->extack);
106                 if (err)
107                         return err;
108         }
109 
110         return 0;
111 }
112 
113 static int dsa_switch_bridge_leave(struct dsa_switch *ds,
114                                    struct dsa_notifier_bridge_info *info)
115 {
116         if (info->dp->ds == ds && ds->ops->port_bridge_leave)
117                 ds->ops->port_bridge_leave(ds, info->dp->index, info->bridge);
118 
119         if (info->dp->ds != ds && ds->ops->crosschip_bridge_leave)
120                 ds->ops->crosschip_bridge_leave(ds, info->dp->ds->dst->index,
121                                                 info->dp->ds->index,
122                                                 info->dp->index,
123                                                 info->bridge);
124 
125         return 0;
126 }
127 
128 /* Matches for all upstream-facing ports (the CPU port and all upstream-facing
129  * DSA links) that sit between the targeted port on which the notifier was
130  * emitted and its dedicated CPU port.
131  */
132 static bool dsa_port_host_address_match(struct dsa_port *dp,
133                                         const struct dsa_port *targeted_dp)
134 {
135         struct dsa_port *cpu_dp = targeted_dp->cpu_dp;
136 
137         if (dsa_switch_is_upstream_of(dp->ds, targeted_dp->ds))
138                 return dp->index == dsa_towards_port(dp->ds, cpu_dp->ds->index,
139                                                      cpu_dp->index);
140 
141         return false;
142 }
143 
144 static struct dsa_mac_addr *dsa_mac_addr_find(struct list_head *addr_list,
145                                               const unsigned char *addr, u16 vid,
146                                               struct dsa_db db)
147 {
148         struct dsa_mac_addr *a;
149 
150         list_for_each_entry(a, addr_list, list)
151                 if (ether_addr_equal(a->addr, addr) && a->vid == vid &&
152                     dsa_db_equal(&a->db, &db))
153                         return a;
154 
155         return NULL;
156 }
157 
158 static int dsa_port_do_mdb_add(struct dsa_port *dp,
159                                const struct switchdev_obj_port_mdb *mdb,
160                                struct dsa_db db)
161 {
162         struct dsa_switch *ds = dp->ds;
163         struct dsa_mac_addr *a;
164         int port = dp->index;
165         int err = 0;
166 
167         /* No need to bother with refcounting for user ports */
168         if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) {
169                 err = ds->ops->port_mdb_add(ds, port, mdb, db);
170                 trace_dsa_mdb_add_hw(dp, mdb->addr, mdb->vid, &db, err);
171 
172                 return err;
173         }
174 
175         mutex_lock(&dp->addr_lists_lock);
176 
177         a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid, db);
178         if (a) {
179                 refcount_inc(&a->refcount);
180                 trace_dsa_mdb_add_bump(dp, mdb->addr, mdb->vid, &db,
181                                        &a->refcount);
182                 goto out;
183         }
184 
185         a = kzalloc(sizeof(*a), GFP_KERNEL);
186         if (!a) {
187                 err = -ENOMEM;
188                 goto out;
189         }
190 
191         err = ds->ops->port_mdb_add(ds, port, mdb, db);
192         trace_dsa_mdb_add_hw(dp, mdb->addr, mdb->vid, &db, err);
193         if (err) {
194                 kfree(a);
195                 goto out;
196         }
197 
198         ether_addr_copy(a->addr, mdb->addr);
199         a->vid = mdb->vid;
200         a->db = db;
201         refcount_set(&a->refcount, 1);
202         list_add_tail(&a->list, &dp->mdbs);
203 
204 out:
205         mutex_unlock(&dp->addr_lists_lock);
206 
207         return err;
208 }
209 
210 static int dsa_port_do_mdb_del(struct dsa_port *dp,
211                                const struct switchdev_obj_port_mdb *mdb,
212                                struct dsa_db db)
213 {
214         struct dsa_switch *ds = dp->ds;
215         struct dsa_mac_addr *a;
216         int port = dp->index;
217         int err = 0;
218 
219         /* No need to bother with refcounting for user ports */
220         if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) {
221                 err = ds->ops->port_mdb_del(ds, port, mdb, db);
222                 trace_dsa_mdb_del_hw(dp, mdb->addr, mdb->vid, &db, err);
223 
224                 return err;
225         }
226 
227         mutex_lock(&dp->addr_lists_lock);
228 
229         a = dsa_mac_addr_find(&dp->mdbs, mdb->addr, mdb->vid, db);
230         if (!a) {
231                 trace_dsa_mdb_del_not_found(dp, mdb->addr, mdb->vid, &db);
232                 err = -ENOENT;
233                 goto out;
234         }
235 
236         if (!refcount_dec_and_test(&a->refcount)) {
237                 trace_dsa_mdb_del_drop(dp, mdb->addr, mdb->vid, &db,
238                                        &a->refcount);
239                 goto out;
240         }
241 
242         err = ds->ops->port_mdb_del(ds, port, mdb, db);
243         trace_dsa_mdb_del_hw(dp, mdb->addr, mdb->vid, &db, err);
244         if (err) {
245                 refcount_set(&a->refcount, 1);
246                 goto out;
247         }
248 
249         list_del(&a->list);
250         kfree(a);
251 
252 out:
253         mutex_unlock(&dp->addr_lists_lock);
254 
255         return err;
256 }
257 
258 static int dsa_port_do_fdb_add(struct dsa_port *dp, const unsigned char *addr,
259                                u16 vid, struct dsa_db db)
260 {
261         struct dsa_switch *ds = dp->ds;
262         struct dsa_mac_addr *a;
263         int port = dp->index;
264         int err = 0;
265 
266         /* No need to bother with refcounting for user ports */
267         if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) {
268                 err = ds->ops->port_fdb_add(ds, port, addr, vid, db);
269                 trace_dsa_fdb_add_hw(dp, addr, vid, &db, err);
270 
271                 return err;
272         }
273 
274         mutex_lock(&dp->addr_lists_lock);
275 
276         a = dsa_mac_addr_find(&dp->fdbs, addr, vid, db);
277         if (a) {
278                 refcount_inc(&a->refcount);
279                 trace_dsa_fdb_add_bump(dp, addr, vid, &db, &a->refcount);
280                 goto out;
281         }
282 
283         a = kzalloc(sizeof(*a), GFP_KERNEL);
284         if (!a) {
285                 err = -ENOMEM;
286                 goto out;
287         }
288 
289         err = ds->ops->port_fdb_add(ds, port, addr, vid, db);
290         trace_dsa_fdb_add_hw(dp, addr, vid, &db, err);
291         if (err) {
292                 kfree(a);
293                 goto out;
294         }
295 
296         ether_addr_copy(a->addr, addr);
297         a->vid = vid;
298         a->db = db;
299         refcount_set(&a->refcount, 1);
300         list_add_tail(&a->list, &dp->fdbs);
301 
302 out:
303         mutex_unlock(&dp->addr_lists_lock);
304 
305         return err;
306 }
307 
308 static int dsa_port_do_fdb_del(struct dsa_port *dp, const unsigned char *addr,
309                                u16 vid, struct dsa_db db)
310 {
311         struct dsa_switch *ds = dp->ds;
312         struct dsa_mac_addr *a;
313         int port = dp->index;
314         int err = 0;
315 
316         /* No need to bother with refcounting for user ports */
317         if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) {
318                 err = ds->ops->port_fdb_del(ds, port, addr, vid, db);
319                 trace_dsa_fdb_del_hw(dp, addr, vid, &db, err);
320 
321                 return err;
322         }
323 
324         mutex_lock(&dp->addr_lists_lock);
325 
326         a = dsa_mac_addr_find(&dp->fdbs, addr, vid, db);
327         if (!a) {
328                 trace_dsa_fdb_del_not_found(dp, addr, vid, &db);
329                 err = -ENOENT;
330                 goto out;
331         }
332 
333         if (!refcount_dec_and_test(&a->refcount)) {
334                 trace_dsa_fdb_del_drop(dp, addr, vid, &db, &a->refcount);
335                 goto out;
336         }
337 
338         err = ds->ops->port_fdb_del(ds, port, addr, vid, db);
339         trace_dsa_fdb_del_hw(dp, addr, vid, &db, err);
340         if (err) {
341                 refcount_set(&a->refcount, 1);
342                 goto out;
343         }
344 
345         list_del(&a->list);
346         kfree(a);
347 
348 out:
349         mutex_unlock(&dp->addr_lists_lock);
350 
351         return err;
352 }
353 
354 static int dsa_switch_do_lag_fdb_add(struct dsa_switch *ds, struct dsa_lag *lag,
355                                      const unsigned char *addr, u16 vid,
356                                      struct dsa_db db)
357 {
358         struct dsa_mac_addr *a;
359         int err = 0;
360 
361         mutex_lock(&lag->fdb_lock);
362 
363         a = dsa_mac_addr_find(&lag->fdbs, addr, vid, db);
364         if (a) {
365                 refcount_inc(&a->refcount);
366                 trace_dsa_lag_fdb_add_bump(lag->dev, addr, vid, &db,
367                                            &a->refcount);
368                 goto out;
369         }
370 
371         a = kzalloc(sizeof(*a), GFP_KERNEL);
372         if (!a) {
373                 err = -ENOMEM;
374                 goto out;
375         }
376 
377         err = ds->ops->lag_fdb_add(ds, *lag, addr, vid, db);
378         trace_dsa_lag_fdb_add_hw(lag->dev, addr, vid, &db, err);
379         if (err) {
380                 kfree(a);
381                 goto out;
382         }
383 
384         ether_addr_copy(a->addr, addr);
385         a->vid = vid;
386         a->db = db;
387         refcount_set(&a->refcount, 1);
388         list_add_tail(&a->list, &lag->fdbs);
389 
390 out:
391         mutex_unlock(&lag->fdb_lock);
392 
393         return err;
394 }
395 
396 static int dsa_switch_do_lag_fdb_del(struct dsa_switch *ds, struct dsa_lag *lag,
397                                      const unsigned char *addr, u16 vid,
398                                      struct dsa_db db)
399 {
400         struct dsa_mac_addr *a;
401         int err = 0;
402 
403         mutex_lock(&lag->fdb_lock);
404 
405         a = dsa_mac_addr_find(&lag->fdbs, addr, vid, db);
406         if (!a) {
407                 trace_dsa_lag_fdb_del_not_found(lag->dev, addr, vid, &db);
408                 err = -ENOENT;
409                 goto out;
410         }
411 
412         if (!refcount_dec_and_test(&a->refcount)) {
413                 trace_dsa_lag_fdb_del_drop(lag->dev, addr, vid, &db,
414                                            &a->refcount);
415                 goto out;
416         }
417 
418         err = ds->ops->lag_fdb_del(ds, *lag, addr, vid, db);
419         trace_dsa_lag_fdb_del_hw(lag->dev, addr, vid, &db, err);
420         if (err) {
421                 refcount_set(&a->refcount, 1);
422                 goto out;
423         }
424 
425         list_del(&a->list);
426         kfree(a);
427 
428 out:
429         mutex_unlock(&lag->fdb_lock);
430 
431         return err;
432 }
433 
434 static int dsa_switch_host_fdb_add(struct dsa_switch *ds,
435                                    struct dsa_notifier_fdb_info *info)
436 {
437         struct dsa_port *dp;
438         int err = 0;
439 
440         if (!ds->ops->port_fdb_add)
441                 return -EOPNOTSUPP;
442 
443         dsa_switch_for_each_port(dp, ds) {
444                 if (dsa_port_host_address_match(dp, info->dp)) {
445                         if (dsa_port_is_cpu(dp) && info->dp->cpu_port_in_lag) {
446                                 err = dsa_switch_do_lag_fdb_add(ds, dp->lag,
447                                                                 info->addr,
448                                                                 info->vid,
449                                                                 info->db);
450                         } else {
451                                 err = dsa_port_do_fdb_add(dp, info->addr,
452                                                           info->vid, info->db);
453                         }
454                         if (err)
455                                 break;
456                 }
457         }
458 
459         return err;
460 }
461 
462 static int dsa_switch_host_fdb_del(struct dsa_switch *ds,
463                                    struct dsa_notifier_fdb_info *info)
464 {
465         struct dsa_port *dp;
466         int err = 0;
467 
468         if (!ds->ops->port_fdb_del)
469                 return -EOPNOTSUPP;
470 
471         dsa_switch_for_each_port(dp, ds) {
472                 if (dsa_port_host_address_match(dp, info->dp)) {
473                         if (dsa_port_is_cpu(dp) && info->dp->cpu_port_in_lag) {
474                                 err = dsa_switch_do_lag_fdb_del(ds, dp->lag,
475                                                                 info->addr,
476                                                                 info->vid,
477                                                                 info->db);
478                         } else {
479                                 err = dsa_port_do_fdb_del(dp, info->addr,
480                                                           info->vid, info->db);
481                         }
482                         if (err)
483                                 break;
484                 }
485         }
486 
487         return err;
488 }
489 
490 static int dsa_switch_fdb_add(struct dsa_switch *ds,
491                               struct dsa_notifier_fdb_info *info)
492 {
493         int port = dsa_towards_port(ds, info->dp->ds->index, info->dp->index);
494         struct dsa_port *dp = dsa_to_port(ds, port);
495 
496         if (!ds->ops->port_fdb_add)
497                 return -EOPNOTSUPP;
498 
499         return dsa_port_do_fdb_add(dp, info->addr, info->vid, info->db);
500 }
501 
502 static int dsa_switch_fdb_del(struct dsa_switch *ds,
503                               struct dsa_notifier_fdb_info *info)
504 {
505         int port = dsa_towards_port(ds, info->dp->ds->index, info->dp->index);
506         struct dsa_port *dp = dsa_to_port(ds, port);
507 
508         if (!ds->ops->port_fdb_del)
509                 return -EOPNOTSUPP;
510 
511         return dsa_port_do_fdb_del(dp, info->addr, info->vid, info->db);
512 }
513 
514 static int dsa_switch_lag_fdb_add(struct dsa_switch *ds,
515                                   struct dsa_notifier_lag_fdb_info *info)
516 {
517         struct dsa_port *dp;
518 
519         if (!ds->ops->lag_fdb_add)
520                 return -EOPNOTSUPP;
521 
522         /* Notify switch only if it has a port in this LAG */
523         dsa_switch_for_each_port(dp, ds)
524                 if (dsa_port_offloads_lag(dp, info->lag))
525                         return dsa_switch_do_lag_fdb_add(ds, info->lag,
526                                                          info->addr, info->vid,
527                                                          info->db);
528 
529         return 0;
530 }
531 
532 static int dsa_switch_lag_fdb_del(struct dsa_switch *ds,
533                                   struct dsa_notifier_lag_fdb_info *info)
534 {
535         struct dsa_port *dp;
536 
537         if (!ds->ops->lag_fdb_del)
538                 return -EOPNOTSUPP;
539 
540         /* Notify switch only if it has a port in this LAG */
541         dsa_switch_for_each_port(dp, ds)
542                 if (dsa_port_offloads_lag(dp, info->lag))
543                         return dsa_switch_do_lag_fdb_del(ds, info->lag,
544                                                          info->addr, info->vid,
545                                                          info->db);
546 
547         return 0;
548 }
549 
550 static int dsa_switch_lag_change(struct dsa_switch *ds,
551                                  struct dsa_notifier_lag_info *info)
552 {
553         if (info->dp->ds == ds && ds->ops->port_lag_change)
554                 return ds->ops->port_lag_change(ds, info->dp->index);
555 
556         if (info->dp->ds != ds && ds->ops->crosschip_lag_change)
557                 return ds->ops->crosschip_lag_change(ds, info->dp->ds->index,
558                                                      info->dp->index);
559 
560         return 0;
561 }
562 
563 static int dsa_switch_lag_join(struct dsa_switch *ds,
564                                struct dsa_notifier_lag_info *info)
565 {
566         if (info->dp->ds == ds && ds->ops->port_lag_join)
567                 return ds->ops->port_lag_join(ds, info->dp->index, info->lag,
568                                               info->info, info->extack);
569 
570         if (info->dp->ds != ds && ds->ops->crosschip_lag_join)
571                 return ds->ops->crosschip_lag_join(ds, info->dp->ds->index,
572                                                    info->dp->index, info->lag,
573                                                    info->info, info->extack);
574 
575         return -EOPNOTSUPP;
576 }
577 
578 static int dsa_switch_lag_leave(struct dsa_switch *ds,
579                                 struct dsa_notifier_lag_info *info)
580 {
581         if (info->dp->ds == ds && ds->ops->port_lag_leave)
582                 return ds->ops->port_lag_leave(ds, info->dp->index, info->lag);
583 
584         if (info->dp->ds != ds && ds->ops->crosschip_lag_leave)
585                 return ds->ops->crosschip_lag_leave(ds, info->dp->ds->index,
586                                                     info->dp->index, info->lag);
587 
588         return -EOPNOTSUPP;
589 }
590 
591 static int dsa_switch_mdb_add(struct dsa_switch *ds,
592                               struct dsa_notifier_mdb_info *info)
593 {
594         int port = dsa_towards_port(ds, info->dp->ds->index, info->dp->index);
595         struct dsa_port *dp = dsa_to_port(ds, port);
596 
597         if (!ds->ops->port_mdb_add)
598                 return -EOPNOTSUPP;
599 
600         return dsa_port_do_mdb_add(dp, info->mdb, info->db);
601 }
602 
603 static int dsa_switch_mdb_del(struct dsa_switch *ds,
604                               struct dsa_notifier_mdb_info *info)
605 {
606         int port = dsa_towards_port(ds, info->dp->ds->index, info->dp->index);
607         struct dsa_port *dp = dsa_to_port(ds, port);
608 
609         if (!ds->ops->port_mdb_del)
610                 return -EOPNOTSUPP;
611 
612         return dsa_port_do_mdb_del(dp, info->mdb, info->db);
613 }
614 
615 static int dsa_switch_host_mdb_add(struct dsa_switch *ds,
616                                    struct dsa_notifier_mdb_info *info)
617 {
618         struct dsa_port *dp;
619         int err = 0;
620 
621         if (!ds->ops->port_mdb_add)
622                 return -EOPNOTSUPP;
623 
624         dsa_switch_for_each_port(dp, ds) {
625                 if (dsa_port_host_address_match(dp, info->dp)) {
626                         err = dsa_port_do_mdb_add(dp, info->mdb, info->db);
627                         if (err)
628                                 break;
629                 }
630         }
631 
632         return err;
633 }
634 
635 static int dsa_switch_host_mdb_del(struct dsa_switch *ds,
636                                    struct dsa_notifier_mdb_info *info)
637 {
638         struct dsa_port *dp;
639         int err = 0;
640 
641         if (!ds->ops->port_mdb_del)
642                 return -EOPNOTSUPP;
643 
644         dsa_switch_for_each_port(dp, ds) {
645                 if (dsa_port_host_address_match(dp, info->dp)) {
646                         err = dsa_port_do_mdb_del(dp, info->mdb, info->db);
647                         if (err)
648                                 break;
649                 }
650         }
651 
652         return err;
653 }
654 
655 /* Port VLANs match on the targeted port and on all DSA ports */
656 static bool dsa_port_vlan_match(struct dsa_port *dp,
657                                 struct dsa_notifier_vlan_info *info)
658 {
659         return dsa_port_is_dsa(dp) || dp == info->dp;
660 }
661 
662 /* Host VLANs match on the targeted port's CPU port, and on all DSA ports
663  * (upstream and downstream) of that switch and its upstream switches.
664  */
665 static bool dsa_port_host_vlan_match(struct dsa_port *dp,
666                                      const struct dsa_port *targeted_dp)
667 {
668         struct dsa_port *cpu_dp = targeted_dp->cpu_dp;
669 
670         if (dsa_switch_is_upstream_of(dp->ds, targeted_dp->ds))
671                 return dsa_port_is_dsa(dp) || dp == cpu_dp;
672 
673         return false;
674 }
675 
676 struct dsa_vlan *dsa_vlan_find(struct list_head *vlan_list,
677                                const struct switchdev_obj_port_vlan *vlan)
678 {
679         struct dsa_vlan *v;
680 
681         list_for_each_entry(v, vlan_list, list)
682                 if (v->vid == vlan->vid)
683                         return v;
684 
685         return NULL;
686 }
687 
688 static int dsa_port_do_vlan_add(struct dsa_port *dp,
689                                 const struct switchdev_obj_port_vlan *vlan,
690                                 struct netlink_ext_ack *extack)
691 {
692         struct dsa_switch *ds = dp->ds;
693         int port = dp->index;
694         struct dsa_vlan *v;
695         int err = 0;
696 
697         /* No need to bother with refcounting for user ports. */
698         if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) {
699                 err = ds->ops->port_vlan_add(ds, port, vlan, extack);
700                 trace_dsa_vlan_add_hw(dp, vlan, err);
701 
702                 return err;
703         }
704 
705         /* No need to propagate on shared ports the existing VLANs that were
706          * re-notified after just the flags have changed. This would cause a
707          * refcount bump which we need to avoid, since it unbalances the
708          * additions with the deletions.
709          */
710         if (vlan->changed)
711                 return 0;
712 
713         mutex_lock(&dp->vlans_lock);
714 
715         v = dsa_vlan_find(&dp->vlans, vlan);
716         if (v) {
717                 refcount_inc(&v->refcount);
718                 trace_dsa_vlan_add_bump(dp, vlan, &v->refcount);
719                 goto out;
720         }
721 
722         v = kzalloc(sizeof(*v), GFP_KERNEL);
723         if (!v) {
724                 err = -ENOMEM;
725                 goto out;
726         }
727 
728         err = ds->ops->port_vlan_add(ds, port, vlan, extack);
729         trace_dsa_vlan_add_hw(dp, vlan, err);
730         if (err) {
731                 kfree(v);
732                 goto out;
733         }
734 
735         v->vid = vlan->vid;
736         refcount_set(&v->refcount, 1);
737         list_add_tail(&v->list, &dp->vlans);
738 
739 out:
740         mutex_unlock(&dp->vlans_lock);
741 
742         return err;
743 }
744 
745 static int dsa_port_do_vlan_del(struct dsa_port *dp,
746                                 const struct switchdev_obj_port_vlan *vlan)
747 {
748         struct dsa_switch *ds = dp->ds;
749         int port = dp->index;
750         struct dsa_vlan *v;
751         int err = 0;
752 
753         /* No need to bother with refcounting for user ports */
754         if (!(dsa_port_is_cpu(dp) || dsa_port_is_dsa(dp))) {
755                 err = ds->ops->port_vlan_del(ds, port, vlan);
756                 trace_dsa_vlan_del_hw(dp, vlan, err);
757 
758                 return err;
759         }
760 
761         mutex_lock(&dp->vlans_lock);
762 
763         v = dsa_vlan_find(&dp->vlans, vlan);
764         if (!v) {
765                 trace_dsa_vlan_del_not_found(dp, vlan);
766                 err = -ENOENT;
767                 goto out;
768         }
769 
770         if (!refcount_dec_and_test(&v->refcount)) {
771                 trace_dsa_vlan_del_drop(dp, vlan, &v->refcount);
772                 goto out;
773         }
774 
775         err = ds->ops->port_vlan_del(ds, port, vlan);
776         trace_dsa_vlan_del_hw(dp, vlan, err);
777         if (err) {
778                 refcount_set(&v->refcount, 1);
779                 goto out;
780         }
781 
782         list_del(&v->list);
783         kfree(v);
784 
785 out:
786         mutex_unlock(&dp->vlans_lock);
787 
788         return err;
789 }
790 
791 static int dsa_switch_vlan_add(struct dsa_switch *ds,
792                                struct dsa_notifier_vlan_info *info)
793 {
794         struct dsa_port *dp;
795         int err;
796 
797         if (!ds->ops->port_vlan_add)
798                 return -EOPNOTSUPP;
799 
800         dsa_switch_for_each_port(dp, ds) {
801                 if (dsa_port_vlan_match(dp, info)) {
802                         err = dsa_port_do_vlan_add(dp, info->vlan,
803                                                    info->extack);
804                         if (err)
805                                 return err;
806                 }
807         }
808 
809         return 0;
810 }
811 
812 static int dsa_switch_vlan_del(struct dsa_switch *ds,
813                                struct dsa_notifier_vlan_info *info)
814 {
815         struct dsa_port *dp;
816         int err;
817 
818         if (!ds->ops->port_vlan_del)
819                 return -EOPNOTSUPP;
820 
821         dsa_switch_for_each_port(dp, ds) {
822                 if (dsa_port_vlan_match(dp, info)) {
823                         err = dsa_port_do_vlan_del(dp, info->vlan);
824                         if (err)
825                                 return err;
826                 }
827         }
828 
829         return 0;
830 }
831 
832 static int dsa_switch_host_vlan_add(struct dsa_switch *ds,
833                                     struct dsa_notifier_vlan_info *info)
834 {
835         struct dsa_port *dp;
836         int err;
837 
838         if (!ds->ops->port_vlan_add)
839                 return -EOPNOTSUPP;
840 
841         dsa_switch_for_each_port(dp, ds) {
842                 if (dsa_port_host_vlan_match(dp, info->dp)) {
843                         err = dsa_port_do_vlan_add(dp, info->vlan,
844                                                    info->extack);
845                         if (err)
846                                 return err;
847                 }
848         }
849 
850         return 0;
851 }
852 
853 static int dsa_switch_host_vlan_del(struct dsa_switch *ds,
854                                     struct dsa_notifier_vlan_info *info)
855 {
856         struct dsa_port *dp;
857         int err;
858 
859         if (!ds->ops->port_vlan_del)
860                 return -EOPNOTSUPP;
861 
862         dsa_switch_for_each_port(dp, ds) {
863                 if (dsa_port_host_vlan_match(dp, info->dp)) {
864                         err = dsa_port_do_vlan_del(dp, info->vlan);
865                         if (err)
866                                 return err;
867                 }
868         }
869 
870         return 0;
871 }
872 
873 static int dsa_switch_change_tag_proto(struct dsa_switch *ds,
874                                        struct dsa_notifier_tag_proto_info *info)
875 {
876         const struct dsa_device_ops *tag_ops = info->tag_ops;
877         struct dsa_port *dp, *cpu_dp;
878         int err;
879 
880         if (!ds->ops->change_tag_protocol)
881                 return -EOPNOTSUPP;
882 
883         ASSERT_RTNL();
884 
885         err = ds->ops->change_tag_protocol(ds, tag_ops->proto);
886         if (err)
887                 return err;
888 
889         dsa_switch_for_each_cpu_port(cpu_dp, ds)
890                 dsa_port_set_tag_protocol(cpu_dp, tag_ops);
891 
892         /* Now that changing the tag protocol can no longer fail, let's update
893          * the remaining bits which are "duplicated for faster access", and the
894          * bits that depend on the tagger, such as the MTU.
895          */
896         dsa_switch_for_each_user_port(dp, ds) {
897                 struct net_device *user = dp->user;
898 
899                 dsa_user_setup_tagger(user);
900 
901                 /* rtnl_mutex is held in dsa_tree_change_tag_proto */
902                 dsa_user_change_mtu(user, user->mtu);
903         }
904 
905         return 0;
906 }
907 
908 /* We use the same cross-chip notifiers to inform both the tagger side, as well
909  * as the switch side, of connection and disconnection events.
910  * Since ds->tagger_data is owned by the tagger, it isn't a hard error if the
911  * switch side doesn't support connecting to this tagger, and therefore, the
912  * fact that we don't disconnect the tagger side doesn't constitute a memory
913  * leak: the tagger will still operate with persistent per-switch memory, just
914  * with the switch side unconnected to it. What does constitute a hard error is
915  * when the switch side supports connecting but fails.
916  */
917 static int
918 dsa_switch_connect_tag_proto(struct dsa_switch *ds,
919                              struct dsa_notifier_tag_proto_info *info)
920 {
921         const struct dsa_device_ops *tag_ops = info->tag_ops;
922         int err;
923 
924         /* Notify the new tagger about the connection to this switch */
925         if (tag_ops->connect) {
926                 err = tag_ops->connect(ds);
927                 if (err)
928                         return err;
929         }
930 
931         if (!ds->ops->connect_tag_protocol)
932                 return -EOPNOTSUPP;
933 
934         /* Notify the switch about the connection to the new tagger */
935         err = ds->ops->connect_tag_protocol(ds, tag_ops->proto);
936         if (err) {
937                 /* Revert the new tagger's connection to this tree */
938                 if (tag_ops->disconnect)
939                         tag_ops->disconnect(ds);
940                 return err;
941         }
942 
943         return 0;
944 }
945 
946 static int
947 dsa_switch_disconnect_tag_proto(struct dsa_switch *ds,
948                                 struct dsa_notifier_tag_proto_info *info)
949 {
950         const struct dsa_device_ops *tag_ops = info->tag_ops;
951 
952         /* Notify the tagger about the disconnection from this switch */
953         if (tag_ops->disconnect && ds->tagger_data)
954                 tag_ops->disconnect(ds);
955 
956         /* No need to notify the switch, since it shouldn't have any
957          * resources to tear down
958          */
959         return 0;
960 }
961 
962 static int
963 dsa_switch_conduit_state_change(struct dsa_switch *ds,
964                                 struct dsa_notifier_conduit_state_info *info)
965 {
966         if (!ds->ops->conduit_state_change)
967                 return 0;
968 
969         ds->ops->conduit_state_change(ds, info->conduit, info->operational);
970 
971         return 0;
972 }
973 
974 static int dsa_switch_event(struct notifier_block *nb,
975                             unsigned long event, void *info)
976 {
977         struct dsa_switch *ds = container_of(nb, struct dsa_switch, nb);
978         int err;
979 
980         switch (event) {
981         case DSA_NOTIFIER_AGEING_TIME:
982                 err = dsa_switch_ageing_time(ds, info);
983                 break;
984         case DSA_NOTIFIER_BRIDGE_JOIN:
985                 err = dsa_switch_bridge_join(ds, info);
986                 break;
987         case DSA_NOTIFIER_BRIDGE_LEAVE:
988                 err = dsa_switch_bridge_leave(ds, info);
989                 break;
990         case DSA_NOTIFIER_FDB_ADD:
991                 err = dsa_switch_fdb_add(ds, info);
992                 break;
993         case DSA_NOTIFIER_FDB_DEL:
994                 err = dsa_switch_fdb_del(ds, info);
995                 break;
996         case DSA_NOTIFIER_HOST_FDB_ADD:
997                 err = dsa_switch_host_fdb_add(ds, info);
998                 break;
999         case DSA_NOTIFIER_HOST_FDB_DEL:
1000                 err = dsa_switch_host_fdb_del(ds, info);
1001                 break;
1002         case DSA_NOTIFIER_LAG_FDB_ADD:
1003                 err = dsa_switch_lag_fdb_add(ds, info);
1004                 break;
1005         case DSA_NOTIFIER_LAG_FDB_DEL:
1006                 err = dsa_switch_lag_fdb_del(ds, info);
1007                 break;
1008         case DSA_NOTIFIER_LAG_CHANGE:
1009                 err = dsa_switch_lag_change(ds, info);
1010                 break;
1011         case DSA_NOTIFIER_LAG_JOIN:
1012                 err = dsa_switch_lag_join(ds, info);
1013                 break;
1014         case DSA_NOTIFIER_LAG_LEAVE:
1015                 err = dsa_switch_lag_leave(ds, info);
1016                 break;
1017         case DSA_NOTIFIER_MDB_ADD:
1018                 err = dsa_switch_mdb_add(ds, info);
1019                 break;
1020         case DSA_NOTIFIER_MDB_DEL:
1021                 err = dsa_switch_mdb_del(ds, info);
1022                 break;
1023         case DSA_NOTIFIER_HOST_MDB_ADD:
1024                 err = dsa_switch_host_mdb_add(ds, info);
1025                 break;
1026         case DSA_NOTIFIER_HOST_MDB_DEL:
1027                 err = dsa_switch_host_mdb_del(ds, info);
1028                 break;
1029         case DSA_NOTIFIER_VLAN_ADD:
1030                 err = dsa_switch_vlan_add(ds, info);
1031                 break;
1032         case DSA_NOTIFIER_VLAN_DEL:
1033                 err = dsa_switch_vlan_del(ds, info);
1034                 break;
1035         case DSA_NOTIFIER_HOST_VLAN_ADD:
1036                 err = dsa_switch_host_vlan_add(ds, info);
1037                 break;
1038         case DSA_NOTIFIER_HOST_VLAN_DEL:
1039                 err = dsa_switch_host_vlan_del(ds, info);
1040                 break;
1041         case DSA_NOTIFIER_MTU:
1042                 err = dsa_switch_mtu(ds, info);
1043                 break;
1044         case DSA_NOTIFIER_TAG_PROTO:
1045                 err = dsa_switch_change_tag_proto(ds, info);
1046                 break;
1047         case DSA_NOTIFIER_TAG_PROTO_CONNECT:
1048                 err = dsa_switch_connect_tag_proto(ds, info);
1049                 break;
1050         case DSA_NOTIFIER_TAG_PROTO_DISCONNECT:
1051                 err = dsa_switch_disconnect_tag_proto(ds, info);
1052                 break;
1053         case DSA_NOTIFIER_TAG_8021Q_VLAN_ADD:
1054                 err = dsa_switch_tag_8021q_vlan_add(ds, info);
1055                 break;
1056         case DSA_NOTIFIER_TAG_8021Q_VLAN_DEL:
1057                 err = dsa_switch_tag_8021q_vlan_del(ds, info);
1058                 break;
1059         case DSA_NOTIFIER_CONDUIT_STATE_CHANGE:
1060                 err = dsa_switch_conduit_state_change(ds, info);
1061                 break;
1062         default:
1063                 err = -EOPNOTSUPP;
1064                 break;
1065         }
1066 
1067         if (err)
1068                 dev_dbg(ds->dev, "breaking chain for DSA event %lu (%d)\n",
1069                         event, err);
1070 
1071         return notifier_from_errno(err);
1072 }
1073 
1074 /**
1075  * dsa_tree_notify - Execute code for all switches in a DSA switch tree.
1076  * @dst: collection of struct dsa_switch devices to notify.
1077  * @e: event, must be of type DSA_NOTIFIER_*
1078  * @v: event-specific value.
1079  *
1080  * Given a struct dsa_switch_tree, this can be used to run a function once for
1081  * each member DSA switch. The other alternative of traversing the tree is only
1082  * through its ports list, which does not uniquely list the switches.
1083  */
1084 int dsa_tree_notify(struct dsa_switch_tree *dst, unsigned long e, void *v)
1085 {
1086         struct raw_notifier_head *nh = &dst->nh;
1087         int err;
1088 
1089         err = raw_notifier_call_chain(nh, e, v);
1090 
1091         return notifier_to_errno(err);
1092 }
1093 
1094 /**
1095  * dsa_broadcast - Notify all DSA trees in the system.
1096  * @e: event, must be of type DSA_NOTIFIER_*
1097  * @v: event-specific value.
1098  *
1099  * Can be used to notify the switching fabric of events such as cross-chip
1100  * bridging between disjoint trees (such as islands of tagger-compatible
1101  * switches bridged by an incompatible middle switch).
1102  *
1103  * WARNING: this function is not reliable during probe time, because probing
1104  * between trees is asynchronous and not all DSA trees might have probed.
1105  */
1106 int dsa_broadcast(unsigned long e, void *v)
1107 {
1108         struct dsa_switch_tree *dst;
1109         int err = 0;
1110 
1111         list_for_each_entry(dst, &dsa_tree_list, list) {
1112                 err = dsa_tree_notify(dst, e, v);
1113                 if (err)
1114                         break;
1115         }
1116 
1117         return err;
1118 }
1119 
1120 int dsa_switch_register_notifier(struct dsa_switch *ds)
1121 {
1122         ds->nb.notifier_call = dsa_switch_event;
1123 
1124         return raw_notifier_chain_register(&ds->dst->nh, &ds->nb);
1125 }
1126 
1127 void dsa_switch_unregister_notifier(struct dsa_switch *ds)
1128 {
1129         int err;
1130 
1131         err = raw_notifier_chain_unregister(&ds->dst->nh, &ds->nb);
1132         if (err)
1133                 dev_err(ds->dev, "failed to unregister notifier (%d)\n", err);
1134 }
1135 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php