hc
2024-01-04 1543e317f1da31b75942316931e8f491a8920811
kernel/net/bridge/br_fdb.c
....@@ -1,14 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Forwarding database
34 * Linux ethernet bridge
45 *
56 * Authors:
67 * Lennert Buytenhek <buytenh@gnu.org>
7
- *
8
- * This program is free software; you can redistribute it and/or
9
- * modify it under the terms of the GNU General Public License
10
- * as published by the Free Software Foundation; either version
11
- * 2 of the License, or (at your option) any later version.
128 */
139
1410 #include <linux/kernel.h>
....@@ -33,7 +29,6 @@
3329 .key_offset = offsetof(struct net_bridge_fdb_entry, key),
3430 .key_len = sizeof(struct net_bridge_fdb_key),
3531 .automatic_shrinking = true,
36
- .locks_mul = 1,
3732 };
3833
3934 static struct kmem_cache *br_fdb_cache __read_mostly;
....@@ -80,8 +75,9 @@
8075 static inline int has_expired(const struct net_bridge *br,
8176 const struct net_bridge_fdb_entry *fdb)
8277 {
83
- return !fdb->is_static && !fdb->added_by_external_learn &&
84
- time_before_eq(fdb->updated + hold_time(br), jiffies);
78
+ return !test_bit(BR_FDB_STATIC, &fdb->flags) &&
79
+ !test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &fdb->flags) &&
80
+ time_before_eq(fdb->updated + hold_time(br), jiffies);
8581 }
8682
8783 static void fdb_rcu_free(struct rcu_head *head)
....@@ -202,7 +198,7 @@
202198 {
203199 trace_fdb_delete(br, f);
204200
205
- if (f->is_static)
201
+ if (test_bit(BR_FDB_STATIC, &f->flags))
206202 fdb_del_hw_addr(br, f->key.addr.addr);
207203
208204 hlist_del_init_rcu(&f->fdb_node);
....@@ -229,7 +225,7 @@
229225 if (op != p && ether_addr_equal(op->dev->dev_addr, addr) &&
230226 (!vid || br_vlan_find(vg, vid))) {
231227 f->dst = op;
232
- f->added_by_user = 0;
228
+ clear_bit(BR_FDB_ADDED_BY_USER, &f->flags);
233229 return;
234230 }
235231 }
....@@ -240,7 +236,7 @@
240236 if (p && ether_addr_equal(br->dev->dev_addr, addr) &&
241237 (!vid || (v && br_vlan_should_use(v)))) {
242238 f->dst = NULL;
243
- f->added_by_user = 0;
239
+ clear_bit(BR_FDB_ADDED_BY_USER, &f->flags);
244240 return;
245241 }
246242
....@@ -255,7 +251,8 @@
255251
256252 spin_lock_bh(&br->hash_lock);
257253 f = br_fdb_find(br, addr, vid);
258
- if (f && f->is_local && !f->added_by_user && f->dst == p)
254
+ if (f && test_bit(BR_FDB_LOCAL, &f->flags) &&
255
+ !test_bit(BR_FDB_ADDED_BY_USER, &f->flags) && f->dst == p)
259256 fdb_delete_local(br, p, f);
260257 spin_unlock_bh(&br->hash_lock);
261258 }
....@@ -270,7 +267,8 @@
270267 spin_lock_bh(&br->hash_lock);
271268 vg = nbp_vlan_group(p);
272269 hlist_for_each_entry(f, &br->fdb_list, fdb_node) {
273
- if (f->dst == p && f->is_local && !f->added_by_user) {
270
+ if (f->dst == p && test_bit(BR_FDB_LOCAL, &f->flags) &&
271
+ !test_bit(BR_FDB_ADDED_BY_USER, &f->flags)) {
274272 /* delete old one */
275273 fdb_delete_local(br, p, f);
276274
....@@ -311,7 +309,8 @@
311309
312310 /* If old entry was unassociated with any port, then delete it. */
313311 f = br_fdb_find(br, br->dev->dev_addr, 0);
314
- if (f && f->is_local && !f->dst && !f->added_by_user)
312
+ if (f && test_bit(BR_FDB_LOCAL, &f->flags) &&
313
+ !f->dst && !test_bit(BR_FDB_ADDED_BY_USER, &f->flags))
315314 fdb_delete_local(br, NULL, f);
316315
317316 fdb_insert(br, NULL, newaddr, 0);
....@@ -326,7 +325,8 @@
326325 if (!br_vlan_should_use(v))
327326 continue;
328327 f = br_fdb_find(br, br->dev->dev_addr, v->vid);
329
- if (f && f->is_local && !f->dst && !f->added_by_user)
328
+ if (f && test_bit(BR_FDB_LOCAL, &f->flags) &&
329
+ !f->dst && !test_bit(BR_FDB_ADDED_BY_USER, &f->flags))
330330 fdb_delete_local(br, NULL, f);
331331 fdb_insert(br, NULL, newaddr, v->vid);
332332 }
....@@ -349,11 +349,21 @@
349349 */
350350 rcu_read_lock();
351351 hlist_for_each_entry_rcu(f, &br->fdb_list, fdb_node) {
352
- unsigned long this_timer;
352
+ unsigned long this_timer = f->updated + delay;
353353
354
- if (f->is_static || f->added_by_external_learn)
354
+ if (test_bit(BR_FDB_STATIC, &f->flags) ||
355
+ test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &f->flags)) {
356
+ if (test_bit(BR_FDB_NOTIFY, &f->flags)) {
357
+ if (time_after(this_timer, now))
358
+ work_delay = min(work_delay,
359
+ this_timer - now);
360
+ else if (!test_and_set_bit(BR_FDB_NOTIFY_INACTIVE,
361
+ &f->flags))
362
+ fdb_notify(br, f, RTM_NEWNEIGH, false);
363
+ }
355364 continue;
356
- this_timer = f->updated + delay;
365
+ }
366
+
357367 if (time_after(this_timer, now)) {
358368 work_delay = min(work_delay, this_timer - now);
359369 } else {
....@@ -378,7 +388,7 @@
378388
379389 spin_lock_bh(&br->hash_lock);
380390 hlist_for_each_entry_safe(f, tmp, &br->fdb_list, fdb_node) {
381
- if (!f->is_static)
391
+ if (!test_bit(BR_FDB_STATIC, &f->flags))
382392 fdb_delete(br, f, true);
383393 }
384394 spin_unlock_bh(&br->hash_lock);
....@@ -402,10 +412,13 @@
402412 continue;
403413
404414 if (!do_all)
405
- if (f->is_static || (vid && f->key.vlan_id != vid))
415
+ if (test_bit(BR_FDB_STATIC, &f->flags) ||
416
+ (test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &f->flags) &&
417
+ !test_bit(BR_FDB_OFFLOADED, &f->flags)) ||
418
+ (vid && f->key.vlan_id != vid))
406419 continue;
407420
408
- if (f->is_local)
421
+ if (test_bit(BR_FDB_LOCAL, &f->flags))
409422 fdb_delete_local(br, p, f);
410423 else
411424 fdb_delete(br, f, true);
....@@ -474,8 +487,8 @@
474487 fe->port_no = f->dst->port_no;
475488 fe->port_hi = f->dst->port_no >> 8;
476489
477
- fe->is_local = f->is_local;
478
- if (!f->is_static)
490
+ fe->is_local = test_bit(BR_FDB_LOCAL, &f->flags);
491
+ if (!test_bit(BR_FDB_STATIC, &f->flags))
479492 fe->ageing_timer_value = jiffies_delta_to_clock_t(jiffies - f->updated);
480493 ++fe;
481494 ++num;
....@@ -489,8 +502,7 @@
489502 struct net_bridge_port *source,
490503 const unsigned char *addr,
491504 __u16 vid,
492
- unsigned char is_local,
493
- unsigned char is_static)
505
+ unsigned long flags)
494506 {
495507 struct net_bridge_fdb_entry *fdb;
496508
....@@ -499,11 +511,7 @@
499511 memcpy(fdb->key.addr.addr, addr, ETH_ALEN);
500512 fdb->dst = source;
501513 fdb->key.vlan_id = vid;
502
- fdb->is_local = is_local;
503
- fdb->is_static = is_static;
504
- fdb->added_by_user = 0;
505
- fdb->added_by_external_learn = 0;
506
- fdb->offloaded = 0;
514
+ fdb->flags = flags;
507515 fdb->updated = fdb->used = jiffies;
508516 if (rhashtable_lookup_insert_fast(&br->fdb_hash_tbl,
509517 &fdb->rhnode,
....@@ -530,14 +538,15 @@
530538 /* it is okay to have multiple ports with same
531539 * address, just use the first one.
532540 */
533
- if (fdb->is_local)
541
+ if (test_bit(BR_FDB_LOCAL, &fdb->flags))
534542 return 0;
535543 br_warn(br, "adding interface %s with same address as a received packet (addr:%pM, vlan:%u)\n",
536544 source ? source->dev->name : br->dev->name, addr, vid);
537545 fdb_delete(br, fdb, true);
538546 }
539547
540
- fdb = fdb_create(br, source, addr, vid, 1, 1);
548
+ fdb = fdb_create(br, source, addr, vid,
549
+ BIT(BR_FDB_LOCAL) | BIT(BR_FDB_STATIC));
541550 if (!fdb)
542551 return -ENOMEM;
543552
....@@ -558,56 +567,62 @@
558567 return ret;
559568 }
560569
570
+/* returns true if the fdb was modified */
571
+static bool __fdb_mark_active(struct net_bridge_fdb_entry *fdb)
572
+{
573
+ return !!(test_bit(BR_FDB_NOTIFY_INACTIVE, &fdb->flags) &&
574
+ test_and_clear_bit(BR_FDB_NOTIFY_INACTIVE, &fdb->flags));
575
+}
576
+
561577 void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
562
- const unsigned char *addr, u16 vid, bool added_by_user)
578
+ const unsigned char *addr, u16 vid, unsigned long flags)
563579 {
564580 struct net_bridge_fdb_entry *fdb;
565
- bool fdb_modified = false;
566581
567582 /* some users want to always flood. */
568583 if (hold_time(br) == 0)
569584 return;
570585
571
- /* ignore packets unless we are using this port */
572
- if (!(source->state == BR_STATE_LEARNING ||
573
- source->state == BR_STATE_FORWARDING))
574
- return;
575
-
576586 fdb = fdb_find_rcu(&br->fdb_hash_tbl, addr, vid);
577587 if (likely(fdb)) {
578588 /* attempt to update an entry for a local interface */
579
- if (unlikely(fdb->is_local)) {
589
+ if (unlikely(test_bit(BR_FDB_LOCAL, &fdb->flags))) {
580590 if (net_ratelimit())
581591 br_warn(br, "received packet on %s with own address as source address (addr:%pM, vlan:%u)\n",
582592 source->dev->name, addr, vid);
583593 } else {
584594 unsigned long now = jiffies;
595
+ bool fdb_modified = false;
596
+
597
+ if (now != fdb->updated) {
598
+ fdb->updated = now;
599
+ fdb_modified = __fdb_mark_active(fdb);
600
+ }
585601
586602 /* fastpath: update of existing entry */
587
- if (unlikely(source != fdb->dst)) {
603
+ if (unlikely(source != fdb->dst &&
604
+ !test_bit(BR_FDB_STICKY, &fdb->flags))) {
588605 fdb->dst = source;
589606 fdb_modified = true;
590607 /* Take over HW learned entry */
591
- if (unlikely(fdb->added_by_external_learn))
592
- fdb->added_by_external_learn = 0;
608
+ if (unlikely(test_bit(BR_FDB_ADDED_BY_EXT_LEARN,
609
+ &fdb->flags)))
610
+ clear_bit(BR_FDB_ADDED_BY_EXT_LEARN,
611
+ &fdb->flags);
593612 }
594
- if (now != fdb->updated)
595
- fdb->updated = now;
596
- if (unlikely(added_by_user))
597
- fdb->added_by_user = 1;
613
+
614
+ if (unlikely(test_bit(BR_FDB_ADDED_BY_USER, &flags)))
615
+ set_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
598616 if (unlikely(fdb_modified)) {
599
- trace_br_fdb_update(br, source, addr, vid, added_by_user);
617
+ trace_br_fdb_update(br, source, addr, vid, flags);
600618 fdb_notify(br, fdb, RTM_NEWNEIGH, true);
601619 }
602620 }
603621 } else {
604622 spin_lock(&br->hash_lock);
605
- fdb = fdb_create(br, source, addr, vid, 0, 0);
623
+ fdb = fdb_create(br, source, addr, vid, flags);
606624 if (fdb) {
607
- if (unlikely(added_by_user))
608
- fdb->added_by_user = 1;
609
- trace_br_fdb_update(br, source, addr, vid,
610
- added_by_user);
625
+ trace_br_fdb_update(br, source, addr, vid, flags);
611626 fdb_notify(br, fdb, RTM_NEWNEIGH, true);
612627 }
613628 /* else we lose race and someone else inserts
....@@ -620,9 +635,9 @@
620635 static int fdb_to_nud(const struct net_bridge *br,
621636 const struct net_bridge_fdb_entry *fdb)
622637 {
623
- if (fdb->is_local)
638
+ if (test_bit(BR_FDB_LOCAL, &fdb->flags))
624639 return NUD_PERMANENT;
625
- else if (fdb->is_static)
640
+ else if (test_bit(BR_FDB_STATIC, &fdb->flags))
626641 return NUD_NOARP;
627642 else if (has_expired(br, fdb))
628643 return NUD_STALE;
....@@ -652,10 +667,12 @@
652667 ndm->ndm_ifindex = fdb->dst ? fdb->dst->dev->ifindex : br->dev->ifindex;
653668 ndm->ndm_state = fdb_to_nud(br, fdb);
654669
655
- if (fdb->offloaded)
670
+ if (test_bit(BR_FDB_OFFLOADED, &fdb->flags))
656671 ndm->ndm_flags |= NTF_OFFLOADED;
657
- if (fdb->added_by_external_learn)
672
+ if (test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &fdb->flags))
658673 ndm->ndm_flags |= NTF_EXT_LEARNED;
674
+ if (test_bit(BR_FDB_STICKY, &fdb->flags))
675
+ ndm->ndm_flags |= NTF_STICKY;
659676
660677 if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->key.addr))
661678 goto nla_put_failure;
....@@ -672,6 +689,23 @@
672689 &fdb->key.vlan_id))
673690 goto nla_put_failure;
674691
692
+ if (test_bit(BR_FDB_NOTIFY, &fdb->flags)) {
693
+ struct nlattr *nest = nla_nest_start(skb, NDA_FDB_EXT_ATTRS);
694
+ u8 notify_bits = FDB_NOTIFY_BIT;
695
+
696
+ if (!nest)
697
+ goto nla_put_failure;
698
+ if (test_bit(BR_FDB_NOTIFY_INACTIVE, &fdb->flags))
699
+ notify_bits |= FDB_NOTIFY_INACTIVE_BIT;
700
+
701
+ if (nla_put_u8(skb, NFEA_ACTIVITY_NOTIFY, notify_bits)) {
702
+ nla_nest_cancel(skb, nest);
703
+ goto nla_put_failure;
704
+ }
705
+
706
+ nla_nest_end(skb, nest);
707
+ }
708
+
675709 nlmsg_end(skb, nlh);
676710 return 0;
677711
....@@ -686,7 +720,9 @@
686720 + nla_total_size(ETH_ALEN) /* NDA_LLADDR */
687721 + nla_total_size(sizeof(u32)) /* NDA_MASTER */
688722 + nla_total_size(sizeof(u16)) /* NDA_VLAN */
689
- + nla_total_size(sizeof(struct nda_cacheinfo));
723
+ + nla_total_size(sizeof(struct nda_cacheinfo))
724
+ + nla_total_size(0) /* NDA_FDB_EXT_ATTRS */
725
+ + nla_total_size(sizeof(u8)); /* NFEA_ACTIVITY_NOTIFY */
690726 }
691727
692728 static void fdb_notify(struct net_bridge *br,
....@@ -770,12 +806,67 @@
770806 return err;
771807 }
772808
809
+int br_fdb_get(struct sk_buff *skb,
810
+ struct nlattr *tb[],
811
+ struct net_device *dev,
812
+ const unsigned char *addr,
813
+ u16 vid, u32 portid, u32 seq,
814
+ struct netlink_ext_ack *extack)
815
+{
816
+ struct net_bridge *br = netdev_priv(dev);
817
+ struct net_bridge_fdb_entry *f;
818
+ int err = 0;
819
+
820
+ rcu_read_lock();
821
+ f = br_fdb_find_rcu(br, addr, vid);
822
+ if (!f) {
823
+ NL_SET_ERR_MSG(extack, "Fdb entry not found");
824
+ err = -ENOENT;
825
+ goto errout;
826
+ }
827
+
828
+ err = fdb_fill_info(skb, br, f, portid, seq,
829
+ RTM_NEWNEIGH, 0);
830
+errout:
831
+ rcu_read_unlock();
832
+ return err;
833
+}
834
+
835
+/* returns true if the fdb is modified */
836
+static bool fdb_handle_notify(struct net_bridge_fdb_entry *fdb, u8 notify)
837
+{
838
+ bool modified = false;
839
+
840
+ /* allow to mark an entry as inactive, usually done on creation */
841
+ if ((notify & FDB_NOTIFY_INACTIVE_BIT) &&
842
+ !test_and_set_bit(BR_FDB_NOTIFY_INACTIVE, &fdb->flags))
843
+ modified = true;
844
+
845
+ if ((notify & FDB_NOTIFY_BIT) &&
846
+ !test_and_set_bit(BR_FDB_NOTIFY, &fdb->flags)) {
847
+ /* enabled activity tracking */
848
+ modified = true;
849
+ } else if (!(notify & FDB_NOTIFY_BIT) &&
850
+ test_and_clear_bit(BR_FDB_NOTIFY, &fdb->flags)) {
851
+ /* disabled activity tracking, clear notify state */
852
+ clear_bit(BR_FDB_NOTIFY_INACTIVE, &fdb->flags);
853
+ modified = true;
854
+ }
855
+
856
+ return modified;
857
+}
858
+
773859 /* Update (create or replace) forwarding database entry */
774860 static int fdb_add_entry(struct net_bridge *br, struct net_bridge_port *source,
775
- const __u8 *addr, __u16 state, __u16 flags, __u16 vid)
861
+ const u8 *addr, struct ndmsg *ndm, u16 flags, u16 vid,
862
+ struct nlattr *nfea_tb[])
776863 {
864
+ bool is_sticky = !!(ndm->ndm_flags & NTF_STICKY);
865
+ bool refresh = !nfea_tb[NFEA_DONT_REFRESH];
777866 struct net_bridge_fdb_entry *fdb;
867
+ u16 state = ndm->ndm_state;
778868 bool modified = false;
869
+ u8 notify = 0;
779870
780871 /* If the port cannot learn allow only local and static entries */
781872 if (source && !(state & NUD_PERMANENT) && !(state & NUD_NOARP) &&
....@@ -789,12 +880,22 @@
789880 return -EINVAL;
790881 }
791882
883
+ if (is_sticky && (state & NUD_PERMANENT))
884
+ return -EINVAL;
885
+
886
+ if (nfea_tb[NFEA_ACTIVITY_NOTIFY]) {
887
+ notify = nla_get_u8(nfea_tb[NFEA_ACTIVITY_NOTIFY]);
888
+ if ((notify & ~BR_FDB_NOTIFY_SETTABLE_BITS) ||
889
+ (notify & BR_FDB_NOTIFY_SETTABLE_BITS) == FDB_NOTIFY_INACTIVE_BIT)
890
+ return -EINVAL;
891
+ }
892
+
792893 fdb = br_fdb_find(br, addr, vid);
793894 if (fdb == NULL) {
794895 if (!(flags & NLM_F_CREATE))
795896 return -ENOENT;
796897
797
- fdb = fdb_create(br, source, addr, vid, 0, 0);
898
+ fdb = fdb_create(br, source, addr, vid, 0);
798899 if (!fdb)
799900 return -ENOMEM;
800901
....@@ -811,32 +912,36 @@
811912
812913 if (fdb_to_nud(br, fdb) != state) {
813914 if (state & NUD_PERMANENT) {
814
- fdb->is_local = 1;
815
- if (!fdb->is_static) {
816
- fdb->is_static = 1;
915
+ set_bit(BR_FDB_LOCAL, &fdb->flags);
916
+ if (!test_and_set_bit(BR_FDB_STATIC, &fdb->flags))
817917 fdb_add_hw_addr(br, addr);
818
- }
819918 } else if (state & NUD_NOARP) {
820
- fdb->is_local = 0;
821
- if (!fdb->is_static) {
822
- fdb->is_static = 1;
919
+ clear_bit(BR_FDB_LOCAL, &fdb->flags);
920
+ if (!test_and_set_bit(BR_FDB_STATIC, &fdb->flags))
823921 fdb_add_hw_addr(br, addr);
824
- }
825922 } else {
826
- fdb->is_local = 0;
827
- if (fdb->is_static) {
828
- fdb->is_static = 0;
923
+ clear_bit(BR_FDB_LOCAL, &fdb->flags);
924
+ if (test_and_clear_bit(BR_FDB_STATIC, &fdb->flags))
829925 fdb_del_hw_addr(br, addr);
830
- }
831926 }
832927
833928 modified = true;
834929 }
835
- fdb->added_by_user = 1;
930
+
931
+ if (is_sticky != test_bit(BR_FDB_STICKY, &fdb->flags)) {
932
+ change_bit(BR_FDB_STICKY, &fdb->flags);
933
+ modified = true;
934
+ }
935
+
936
+ if (fdb_handle_notify(fdb, notify))
937
+ modified = true;
938
+
939
+ set_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
836940
837941 fdb->used = jiffies;
838942 if (modified) {
839
- fdb->updated = jiffies;
943
+ if (refresh)
944
+ fdb->updated = jiffies;
840945 fdb_notify(br, fdb, RTM_NEWNEIGH, true);
841946 }
842947
....@@ -845,7 +950,8 @@
845950
846951 static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge *br,
847952 struct net_bridge_port *p, const unsigned char *addr,
848
- u16 nlh_flags, u16 vid)
953
+ u16 nlh_flags, u16 vid, struct nlattr *nfea_tb[],
954
+ struct netlink_ext_ack *extack)
849955 {
850956 int err = 0;
851957
....@@ -855,28 +961,42 @@
855961 br->dev->name);
856962 return -EINVAL;
857963 }
964
+ if (!nbp_state_should_learn(p))
965
+ return 0;
966
+
858967 local_bh_disable();
859968 rcu_read_lock();
860
- br_fdb_update(br, p, addr, vid, true);
969
+ br_fdb_update(br, p, addr, vid, BIT(BR_FDB_ADDED_BY_USER));
861970 rcu_read_unlock();
862971 local_bh_enable();
863972 } else if (ndm->ndm_flags & NTF_EXT_LEARNED) {
973
+ if (!p && !(ndm->ndm_state & NUD_PERMANENT)) {
974
+ NL_SET_ERR_MSG_MOD(extack,
975
+ "FDB entry towards bridge must be permanent");
976
+ return -EINVAL;
977
+ }
864978 err = br_fdb_external_learn_add(br, p, addr, vid, true);
865979 } else {
866980 spin_lock_bh(&br->hash_lock);
867
- err = fdb_add_entry(br, p, addr, ndm->ndm_state,
868
- nlh_flags, vid);
981
+ err = fdb_add_entry(br, p, addr, ndm, nlh_flags, vid, nfea_tb);
869982 spin_unlock_bh(&br->hash_lock);
870983 }
871984
872985 return err;
873986 }
874987
988
+static const struct nla_policy br_nda_fdb_pol[NFEA_MAX + 1] = {
989
+ [NFEA_ACTIVITY_NOTIFY] = { .type = NLA_U8 },
990
+ [NFEA_DONT_REFRESH] = { .type = NLA_FLAG },
991
+};
992
+
875993 /* Add new permanent fdb entry with RTM_NEWNEIGH */
876994 int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
877995 struct net_device *dev,
878
- const unsigned char *addr, u16 vid, u16 nlh_flags)
996
+ const unsigned char *addr, u16 vid, u16 nlh_flags,
997
+ struct netlink_ext_ack *extack)
879998 {
999
+ struct nlattr *nfea_tb[NFEA_MAX + 1], *attr;
8801000 struct net_bridge_vlan_group *vg;
8811001 struct net_bridge_port *p = NULL;
8821002 struct net_bridge_vlan *v;
....@@ -909,6 +1029,16 @@
9091029 vg = nbp_vlan_group(p);
9101030 }
9111031
1032
+ if (tb[NDA_FDB_EXT_ATTRS]) {
1033
+ attr = tb[NDA_FDB_EXT_ATTRS];
1034
+ err = nla_parse_nested(nfea_tb, NFEA_MAX, attr,
1035
+ br_nda_fdb_pol, extack);
1036
+ if (err)
1037
+ return err;
1038
+ } else {
1039
+ memset(nfea_tb, 0, sizeof(struct nlattr *) * (NFEA_MAX + 1));
1040
+ }
1041
+
9121042 if (vid) {
9131043 v = br_vlan_find(vg, vid);
9141044 if (!v || !br_vlan_should_use(v)) {
....@@ -917,9 +1047,11 @@
9171047 }
9181048
9191049 /* VID was specified, so use it. */
920
- err = __br_fdb_add(ndm, br, p, addr, nlh_flags, vid);
1050
+ err = __br_fdb_add(ndm, br, p, addr, nlh_flags, vid, nfea_tb,
1051
+ extack);
9211052 } else {
922
- err = __br_fdb_add(ndm, br, p, addr, nlh_flags, 0);
1053
+ err = __br_fdb_add(ndm, br, p, addr, nlh_flags, 0, nfea_tb,
1054
+ extack);
9231055 if (err || !vg || !vg->num_vlans)
9241056 goto out;
9251057
....@@ -930,7 +1062,8 @@
9301062 list_for_each_entry(v, &vg->vlan_list, vlist) {
9311063 if (!br_vlan_should_use(v))
9321064 continue;
933
- err = __br_fdb_add(ndm, br, p, addr, nlh_flags, v->vid);
1065
+ err = __br_fdb_add(ndm, br, p, addr, nlh_flags, v->vid,
1066
+ nfea_tb, extack);
9341067 if (err)
9351068 goto out;
9361069 }
....@@ -1028,7 +1161,7 @@
10281161 rcu_read_lock();
10291162 hlist_for_each_entry_rcu(f, &br->fdb_list, fdb_node) {
10301163 /* We only care for static entries */
1031
- if (!f->is_static)
1164
+ if (!test_bit(BR_FDB_STATIC, &f->flags))
10321165 continue;
10331166 err = dev_uc_add(p->dev, f->key.addr.addr);
10341167 if (err)
....@@ -1042,7 +1175,7 @@
10421175 rollback:
10431176 hlist_for_each_entry_rcu(tmp, &br->fdb_list, fdb_node) {
10441177 /* We only care for static entries */
1045
- if (!tmp->is_static)
1178
+ if (!test_bit(BR_FDB_STATIC, &tmp->flags))
10461179 continue;
10471180 if (tmp == f)
10481181 break;
....@@ -1061,7 +1194,7 @@
10611194 rcu_read_lock();
10621195 hlist_for_each_entry_rcu(f, &br->fdb_list, fdb_node) {
10631196 /* We only care for static entries */
1064
- if (!f->is_static)
1197
+ if (!test_bit(BR_FDB_STATIC, &f->flags))
10651198 continue;
10661199
10671200 dev_uc_del(p->dev, f->key.addr.addr);
....@@ -1083,14 +1216,19 @@
10831216
10841217 fdb = br_fdb_find(br, addr, vid);
10851218 if (!fdb) {
1086
- fdb = fdb_create(br, p, addr, vid, 0, 0);
1219
+ unsigned long flags = BIT(BR_FDB_ADDED_BY_EXT_LEARN);
1220
+
1221
+ if (swdev_notify)
1222
+ flags |= BIT(BR_FDB_ADDED_BY_USER);
1223
+
1224
+ if (!p)
1225
+ flags |= BIT(BR_FDB_LOCAL);
1226
+
1227
+ fdb = fdb_create(br, p, addr, vid, flags);
10871228 if (!fdb) {
10881229 err = -ENOMEM;
10891230 goto err_unlock;
10901231 }
1091
- if (swdev_notify)
1092
- fdb->added_by_user = 1;
1093
- fdb->added_by_external_learn = 1;
10941232 fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
10951233 } else {
10961234 fdb->updated = jiffies;
....@@ -1100,17 +1238,20 @@
11001238 modified = true;
11011239 }
11021240
1103
- if (fdb->added_by_external_learn) {
1241
+ if (test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &fdb->flags)) {
11041242 /* Refresh entry */
11051243 fdb->used = jiffies;
1106
- } else if (!fdb->added_by_user) {
1244
+ } else if (!test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags)) {
11071245 /* Take over SW learned entry */
1108
- fdb->added_by_external_learn = 1;
1246
+ set_bit(BR_FDB_ADDED_BY_EXT_LEARN, &fdb->flags);
11091247 modified = true;
11101248 }
11111249
11121250 if (swdev_notify)
1113
- fdb->added_by_user = 1;
1251
+ set_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
1252
+
1253
+ if (!p)
1254
+ set_bit(BR_FDB_LOCAL, &fdb->flags);
11141255
11151256 if (modified)
11161257 fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
....@@ -1132,7 +1273,7 @@
11321273 spin_lock_bh(&br->hash_lock);
11331274
11341275 fdb = br_fdb_find(br, addr, vid);
1135
- if (fdb && fdb->added_by_external_learn)
1276
+ if (fdb && test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &fdb->flags))
11361277 fdb_delete(br, fdb, swdev_notify);
11371278 else
11381279 err = -ENOENT;
....@@ -1143,15 +1284,35 @@
11431284 }
11441285
11451286 void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
1146
- const unsigned char *addr, u16 vid)
1287
+ const unsigned char *addr, u16 vid, bool offloaded)
11471288 {
11481289 struct net_bridge_fdb_entry *fdb;
11491290
11501291 spin_lock_bh(&br->hash_lock);
11511292
11521293 fdb = br_fdb_find(br, addr, vid);
1153
- if (fdb)
1154
- fdb->offloaded = 1;
1294
+ if (fdb && offloaded != test_bit(BR_FDB_OFFLOADED, &fdb->flags))
1295
+ change_bit(BR_FDB_OFFLOADED, &fdb->flags);
11551296
11561297 spin_unlock_bh(&br->hash_lock);
11571298 }
1299
+
1300
+void br_fdb_clear_offload(const struct net_device *dev, u16 vid)
1301
+{
1302
+ struct net_bridge_fdb_entry *f;
1303
+ struct net_bridge_port *p;
1304
+
1305
+ ASSERT_RTNL();
1306
+
1307
+ p = br_port_get_rtnl(dev);
1308
+ if (!p)
1309
+ return;
1310
+
1311
+ spin_lock_bh(&p->br->hash_lock);
1312
+ hlist_for_each_entry(f, &p->br->fdb_list, fdb_node) {
1313
+ if (f->dst == p && f->key.vlan_id == vid)
1314
+ clear_bit(BR_FDB_OFFLOADED, &f->flags);
1315
+ }
1316
+ spin_unlock_bh(&p->br->hash_lock);
1317
+}
1318
+EXPORT_SYMBOL_GPL(br_fdb_clear_offload);