aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_device.c7
-rw-r--r--net/bridge/br_fdb.c38
-rw-r--r--net/bridge/br_if.c5
-rw-r--r--net/bridge/br_private.h3
4 files changed, 36 insertions, 17 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index feb77ea7b58e..a3754ac262c3 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -186,7 +186,8 @@ static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info)
186 strcpy(info->bus_info, "N/A"); 186 strcpy(info->bus_info, "N/A");
187} 187}
188 188
189static u32 br_fix_features(struct net_device *dev, u32 features) 189static netdev_features_t br_fix_features(struct net_device *dev,
190 netdev_features_t features)
190{ 191{
191 struct net_bridge *br = netdev_priv(dev); 192 struct net_bridge *br = netdev_priv(dev);
192 193
@@ -341,10 +342,10 @@ void br_dev_setup(struct net_device *dev)
341 dev->priv_flags = IFF_EBRIDGE; 342 dev->priv_flags = IFF_EBRIDGE;
342 343
343 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | 344 dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
344 NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX | 345 NETIF_F_GSO_MASK | NETIF_F_HW_CSUM | NETIF_F_LLTX |
345 NETIF_F_NETNS_LOCAL | NETIF_F_HW_VLAN_TX; 346 NETIF_F_NETNS_LOCAL | NETIF_F_HW_VLAN_TX;
346 dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | 347 dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
347 NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | 348 NETIF_F_GSO_MASK | NETIF_F_HW_CSUM |
348 NETIF_F_HW_VLAN_TX; 349 NETIF_F_HW_VLAN_TX;
349 350
350 br->dev = dev; 351 br->dev = dev;
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index c8e7861b88b0..973813e34428 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -556,7 +556,7 @@ skip:
556 return skb->len; 556 return skb->len;
557} 557}
558 558
559/* Create new static fdb entry */ 559/* Update (create or replace) forwarding database entry */
560static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, 560static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr,
561 __u16 state, __u16 flags) 561 __u16 state, __u16 flags)
562{ 562{
@@ -575,16 +575,21 @@ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr,
575 } else { 575 } else {
576 if (flags & NLM_F_EXCL) 576 if (flags & NLM_F_EXCL)
577 return -EEXIST; 577 return -EEXIST;
578 }
579
580 if (fdb_to_nud(fdb) != state) {
581 if (state & NUD_PERMANENT)
582 fdb->is_local = fdb->is_static = 1;
583 else if (state & NUD_NOARP) {
584 fdb->is_local = 0;
585 fdb->is_static = 1;
586 } else
587 fdb->is_local = fdb->is_static = 0;
578 588
579 if (flags & NLM_F_REPLACE) 589 fdb->updated = fdb->used = jiffies;
580 fdb->updated = fdb->used = jiffies; 590 fdb_notify(fdb, RTM_NEWNEIGH);
581 fdb->is_local = fdb->is_static = 0;
582 } 591 }
583 592
584 if (state & NUD_PERMANENT)
585 fdb->is_local = fdb->is_static = 1;
586 else if (state & NUD_NOARP)
587 fdb->is_static = 1;
588 return 0; 593 return 0;
589} 594}
590 595
@@ -627,6 +632,11 @@ int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
627 return -EINVAL; 632 return -EINVAL;
628 } 633 }
629 634
635 if (!(ndm->ndm_state & (NUD_PERMANENT|NUD_NOARP|NUD_REACHABLE))) {
636 pr_info("bridge: RTM_NEWNEIGH with invalid state %#x\n", ndm->ndm_state);
637 return -EINVAL;
638 }
639
630 p = br_port_get_rtnl(dev); 640 p = br_port_get_rtnl(dev);
631 if (p == NULL) { 641 if (p == NULL) {
632 pr_info("bridge: RTM_NEWNEIGH %s not a bridge port\n", 642 pr_info("bridge: RTM_NEWNEIGH %s not a bridge port\n",
@@ -634,9 +644,15 @@ int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
634 return -EINVAL; 644 return -EINVAL;
635 } 645 }
636 646
637 spin_lock_bh(&p->br->hash_lock); 647 if (ndm->ndm_flags & NTF_USE) {
638 err = fdb_add_entry(p, addr, ndm->ndm_state, nlh->nlmsg_flags); 648 rcu_read_lock();
639 spin_unlock_bh(&p->br->hash_lock); 649 br_fdb_update(p->br, p, addr);
650 rcu_read_unlock();
651 } else {
652 spin_lock_bh(&p->br->hash_lock);
653 err = fdb_add_entry(p, addr, ndm->ndm_state, nlh->nlmsg_flags);
654 spin_unlock_bh(&p->br->hash_lock);
655 }
640 656
641 return err; 657 return err;
642} 658}
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index f603e5b0b930..0a942fbccc9a 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -296,10 +296,11 @@ int br_min_mtu(const struct net_bridge *br)
296/* 296/*
297 * Recomputes features using slave's features 297 * Recomputes features using slave's features
298 */ 298 */
299u32 br_features_recompute(struct net_bridge *br, u32 features) 299netdev_features_t br_features_recompute(struct net_bridge *br,
300 netdev_features_t features)
300{ 301{
301 struct net_bridge_port *p; 302 struct net_bridge_port *p;
302 u32 mask; 303 netdev_features_t mask;
303 304
304 if (list_empty(&br->port_list)) 305 if (list_empty(&br->port_list))
305 return features; 306 return features;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index d7d6fb05411f..4027029aa5e4 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -387,7 +387,8 @@ extern int br_add_if(struct net_bridge *br,
387extern int br_del_if(struct net_bridge *br, 387extern int br_del_if(struct net_bridge *br,
388 struct net_device *dev); 388 struct net_device *dev);
389extern int br_min_mtu(const struct net_bridge *br); 389extern int br_min_mtu(const struct net_bridge *br);
390extern u32 br_features_recompute(struct net_bridge *br, u32 features); 390extern netdev_features_t br_features_recompute(struct net_bridge *br,
391 netdev_features_t features);
391 392
392/* br_input.c */ 393/* br_input.c */
393extern int br_handle_frame_finish(struct sk_buff *skb); 394extern int br_handle_frame_finish(struct sk_buff *skb);