diff options
-rw-r--r-- | net/bridge/br_fdb.c | 39 |
1 files changed, 20 insertions, 19 deletions
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index d9ca85b87971..b6ae60b08d46 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
@@ -28,7 +28,8 @@ | |||
28 | static struct kmem_cache *br_fdb_cache __read_mostly; | 28 | static struct kmem_cache *br_fdb_cache __read_mostly; |
29 | static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, | 29 | static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, |
30 | const unsigned char *addr); | 30 | const unsigned char *addr); |
31 | static void fdb_notify(const struct net_bridge_fdb_entry *, int); | 31 | static void fdb_notify(struct net_bridge *br, |
32 | const struct net_bridge_fdb_entry *, int); | ||
32 | 33 | ||
33 | static u32 fdb_salt __read_mostly; | 34 | static u32 fdb_salt __read_mostly; |
34 | 35 | ||
@@ -80,10 +81,10 @@ static void fdb_rcu_free(struct rcu_head *head) | |||
80 | kmem_cache_free(br_fdb_cache, ent); | 81 | kmem_cache_free(br_fdb_cache, ent); |
81 | } | 82 | } |
82 | 83 | ||
83 | static inline void fdb_delete(struct net_bridge_fdb_entry *f) | 84 | static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f) |
84 | { | 85 | { |
85 | fdb_notify(f, RTM_DELNEIGH); | ||
86 | hlist_del_rcu(&f->hlist); | 86 | hlist_del_rcu(&f->hlist); |
87 | fdb_notify(br, f, RTM_DELNEIGH); | ||
87 | call_rcu(&f->rcu, fdb_rcu_free); | 88 | call_rcu(&f->rcu, fdb_rcu_free); |
88 | } | 89 | } |
89 | 90 | ||
@@ -114,7 +115,7 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) | |||
114 | } | 115 | } |
115 | 116 | ||
116 | /* delete old one */ | 117 | /* delete old one */ |
117 | fdb_delete(f); | 118 | fdb_delete(br, f); |
118 | goto insert; | 119 | goto insert; |
119 | } | 120 | } |
120 | } | 121 | } |
@@ -144,7 +145,7 @@ void br_fdb_cleanup(unsigned long _data) | |||
144 | continue; | 145 | continue; |
145 | this_timer = f->updated + delay; | 146 | this_timer = f->updated + delay; |
146 | if (time_before_eq(this_timer, jiffies)) | 147 | if (time_before_eq(this_timer, jiffies)) |
147 | fdb_delete(f); | 148 | fdb_delete(br, f); |
148 | else if (time_before(this_timer, next_timer)) | 149 | else if (time_before(this_timer, next_timer)) |
149 | next_timer = this_timer; | 150 | next_timer = this_timer; |
150 | } | 151 | } |
@@ -165,7 +166,7 @@ void br_fdb_flush(struct net_bridge *br) | |||
165 | struct hlist_node *h, *n; | 166 | struct hlist_node *h, *n; |
166 | hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist) { | 167 | hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist) { |
167 | if (!f->is_static) | 168 | if (!f->is_static) |
168 | fdb_delete(f); | 169 | fdb_delete(br, f); |
169 | } | 170 | } |
170 | } | 171 | } |
171 | spin_unlock_bh(&br->hash_lock); | 172 | spin_unlock_bh(&br->hash_lock); |
@@ -209,7 +210,7 @@ void br_fdb_delete_by_port(struct net_bridge *br, | |||
209 | } | 210 | } |
210 | } | 211 | } |
211 | 212 | ||
212 | fdb_delete(f); | 213 | fdb_delete(br, f); |
213 | skip_delete: ; | 214 | skip_delete: ; |
214 | } | 215 | } |
215 | } | 216 | } |
@@ -370,7 +371,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, | |||
370 | br_warn(br, "adding interface %s with same address " | 371 | br_warn(br, "adding interface %s with same address " |
371 | "as a received packet\n", | 372 | "as a received packet\n", |
372 | source->dev->name); | 373 | source->dev->name); |
373 | fdb_delete(fdb); | 374 | fdb_delete(br, fdb); |
374 | } | 375 | } |
375 | 376 | ||
376 | fdb = fdb_create(head, source, addr); | 377 | fdb = fdb_create(head, source, addr); |
@@ -378,7 +379,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, | |||
378 | return -ENOMEM; | 379 | return -ENOMEM; |
379 | 380 | ||
380 | fdb->is_local = fdb->is_static = 1; | 381 | fdb->is_local = fdb->is_static = 1; |
381 | fdb_notify(fdb, RTM_NEWNEIGH); | 382 | fdb_notify(br, fdb, RTM_NEWNEIGH); |
382 | return 0; | 383 | return 0; |
383 | } | 384 | } |
384 | 385 | ||
@@ -427,7 +428,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, | |||
427 | if (likely(!fdb_find(head, addr))) { | 428 | if (likely(!fdb_find(head, addr))) { |
428 | fdb = fdb_create(head, source, addr); | 429 | fdb = fdb_create(head, source, addr); |
429 | if (fdb) | 430 | if (fdb) |
430 | fdb_notify(fdb, RTM_NEWNEIGH); | 431 | fdb_notify(br, fdb, RTM_NEWNEIGH); |
431 | } | 432 | } |
432 | /* else we lose race and someone else inserts | 433 | /* else we lose race and someone else inserts |
433 | * it first, don't bother updating | 434 | * it first, don't bother updating |
@@ -448,7 +449,7 @@ static int fdb_to_nud(const struct net_bridge_fdb_entry *fdb) | |||
448 | return NUD_REACHABLE; | 449 | return NUD_REACHABLE; |
449 | } | 450 | } |
450 | 451 | ||
451 | static int fdb_fill_info(struct sk_buff *skb, | 452 | static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br, |
452 | const struct net_bridge_fdb_entry *fdb, | 453 | const struct net_bridge_fdb_entry *fdb, |
453 | u32 pid, u32 seq, int type, unsigned int flags) | 454 | u32 pid, u32 seq, int type, unsigned int flags) |
454 | { | 455 | { |
@@ -461,7 +462,6 @@ static int fdb_fill_info(struct sk_buff *skb, | |||
461 | if (nlh == NULL) | 462 | if (nlh == NULL) |
462 | return -EMSGSIZE; | 463 | return -EMSGSIZE; |
463 | 464 | ||
464 | |||
465 | ndm = nlmsg_data(nlh); | 465 | ndm = nlmsg_data(nlh); |
466 | ndm->ndm_family = AF_BRIDGE; | 466 | ndm->ndm_family = AF_BRIDGE; |
467 | ndm->ndm_pad1 = 0; | 467 | ndm->ndm_pad1 = 0; |
@@ -493,9 +493,10 @@ static inline size_t fdb_nlmsg_size(void) | |||
493 | + nla_total_size(sizeof(struct nda_cacheinfo)); | 493 | + nla_total_size(sizeof(struct nda_cacheinfo)); |
494 | } | 494 | } |
495 | 495 | ||
496 | static void fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) | 496 | static void fdb_notify(struct net_bridge *br, |
497 | const struct net_bridge_fdb_entry *fdb, int type) | ||
497 | { | 498 | { |
498 | struct net *net = dev_net(fdb->dst->dev); | 499 | struct net *net = dev_net(br->dev); |
499 | struct sk_buff *skb; | 500 | struct sk_buff *skb; |
500 | int err = -ENOBUFS; | 501 | int err = -ENOBUFS; |
501 | 502 | ||
@@ -503,7 +504,7 @@ static void fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) | |||
503 | if (skb == NULL) | 504 | if (skb == NULL) |
504 | goto errout; | 505 | goto errout; |
505 | 506 | ||
506 | err = fdb_fill_info(skb, fdb, 0, 0, type, 0); | 507 | err = fdb_fill_info(skb, br, fdb, 0, 0, type, 0); |
507 | if (err < 0) { | 508 | if (err < 0) { |
508 | /* -EMSGSIZE implies BUG in fdb_nlmsg_size() */ | 509 | /* -EMSGSIZE implies BUG in fdb_nlmsg_size() */ |
509 | WARN_ON(err == -EMSGSIZE); | 510 | WARN_ON(err == -EMSGSIZE); |
@@ -540,7 +541,7 @@ int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
540 | if (idx < cb->args[0]) | 541 | if (idx < cb->args[0]) |
541 | goto skip; | 542 | goto skip; |
542 | 543 | ||
543 | if (fdb_fill_info(skb, f, | 544 | if (fdb_fill_info(skb, br, f, |
544 | NETLINK_CB(cb->skb).pid, | 545 | NETLINK_CB(cb->skb).pid, |
545 | cb->nlh->nlmsg_seq, | 546 | cb->nlh->nlmsg_seq, |
546 | RTM_NEWNEIGH, | 547 | RTM_NEWNEIGH, |
@@ -574,7 +575,7 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, | |||
574 | fdb = fdb_create(head, source, addr); | 575 | fdb = fdb_create(head, source, addr); |
575 | if (!fdb) | 576 | if (!fdb) |
576 | return -ENOMEM; | 577 | return -ENOMEM; |
577 | fdb_notify(fdb, RTM_NEWNEIGH); | 578 | fdb_notify(br, fdb, RTM_NEWNEIGH); |
578 | } else { | 579 | } else { |
579 | if (flags & NLM_F_EXCL) | 580 | if (flags & NLM_F_EXCL) |
580 | return -EEXIST; | 581 | return -EEXIST; |
@@ -590,7 +591,7 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, | |||
590 | fdb->is_local = fdb->is_static = 0; | 591 | fdb->is_local = fdb->is_static = 0; |
591 | 592 | ||
592 | fdb->updated = fdb->used = jiffies; | 593 | fdb->updated = fdb->used = jiffies; |
593 | fdb_notify(fdb, RTM_NEWNEIGH); | 594 | fdb_notify(br, fdb, RTM_NEWNEIGH); |
594 | } | 595 | } |
595 | 596 | ||
596 | return 0; | 597 | return 0; |
@@ -670,7 +671,7 @@ static int fdb_delete_by_addr(struct net_bridge_port *p, const u8 *addr) | |||
670 | if (!fdb) | 671 | if (!fdb) |
671 | return -ENOENT; | 672 | return -ENOENT; |
672 | 673 | ||
673 | fdb_delete(fdb); | 674 | fdb_delete(p->br, fdb); |
674 | return 0; | 675 | return 0; |
675 | } | 676 | } |
676 | 677 | ||