diff options
author | Jiri Kosina <jkosina@suse.cz> | 2011-11-13 19:55:35 (GMT) |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2011-11-13 19:55:53 (GMT) |
commit | 2290c0d06d82faee87b1ab2d9d4f7bf81ef64379 (patch) | |
tree | e075e4d5534193f28e6059904f61e5ca03958d3c /net/bridge | |
parent | 4da669a2e3e5bc70b30a0465f3641528681b5f77 (diff) | |
parent | 52e4c2a05256cb83cda12f3c2137ab1533344edb (diff) | |
download | linux-fsl-qoriq-2290c0d06d82faee87b1ab2d9d4f7bf81ef64379.tar.xz |
Merge branch 'master' into for-next
Sync with Linus tree to have 157550ff ("mtd: add GPMI-NAND driver
in the config and Makefile") as I have patch depending on that one.
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br_device.c | 4 | ||||
-rw-r--r-- | net/bridge/br_fdb.c | 23 | ||||
-rw-r--r-- | net/bridge/br_if.c | 41 | ||||
-rw-r--r-- | net/bridge/br_input.c | 34 | ||||
-rw-r--r-- | net/bridge/br_private.h | 7 | ||||
-rw-r--r-- | net/bridge/br_stp_if.c | 1 | ||||
-rw-r--r-- | net/bridge/br_sysfs_br.c | 34 | ||||
-rw-r--r-- | net/bridge/netfilter/ebt_ulog.c | 7 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtable_broute.c | 4 |
9 files changed, 114 insertions, 41 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index ff3ed60..feb77ea 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -301,7 +301,7 @@ static const struct net_device_ops br_netdev_ops = { .ndo_start_xmit = br_dev_xmit, .ndo_get_stats64 = br_get_stats64, .ndo_set_mac_address = br_set_mac_address, - .ndo_set_multicast_list = br_dev_set_multicast_list, + .ndo_set_rx_mode = br_dev_set_multicast_list, .ndo_change_mtu = br_change_mtu, .ndo_do_ioctl = br_dev_ioctl, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -358,6 +358,8 @@ void br_dev_setup(struct net_device *dev) memcpy(br->group_addr, br_group_address, ETH_ALEN); br->stp_enabled = BR_NO_STP; + br->group_fwd_mask = BR_GROUPFWD_DEFAULT; + br->designated_root = br->bridge_id; br->bridge_max_age = br->max_age = 20 * HZ; br->bridge_hello_time = br->hello_time = 2 * HZ; diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 68def3b..c8e7861 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -558,19 +558,28 @@ skip: /* Create new static fdb entry */ static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, - __u16 state) + __u16 state, __u16 flags) { struct net_bridge *br = source->br; struct hlist_head *head = &br->hash[br_mac_hash(addr)]; struct net_bridge_fdb_entry *fdb; fdb = fdb_find(head, addr); - if (fdb) - return -EEXIST; + if (fdb == NULL) { + if (!(flags & NLM_F_CREATE)) + return -ENOENT; - fdb = fdb_create(head, source, addr); - if (!fdb) - return -ENOMEM; + fdb = fdb_create(head, source, addr); + if (!fdb) + return -ENOMEM; + } else { + if (flags & NLM_F_EXCL) + return -EEXIST; + + if (flags & NLM_F_REPLACE) + fdb->updated = fdb->used = jiffies; + fdb->is_local = fdb->is_static = 0; + } if (state & NUD_PERMANENT) fdb->is_local = fdb->is_static = 1; @@ -626,7 +635,7 @@ int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) } spin_lock_bh(&p->br->hash_lock); - err = fdb_add_entry(p, addr, ndm->ndm_state); + err = fdb_add_entry(p, addr, ndm->ndm_state, nlh->nlmsg_flags); spin_unlock_bh(&p->br->hash_lock); return err; diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 1d420f6..f603e5b 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -13,6 +13,7 @@ #include <linux/kernel.h> #include <linux/netdevice.h> +#include <linux/etherdevice.h> #include <linux/netpoll.h> #include <linux/ethtool.h> #include <linux/if_arp.h> @@ -33,20 +34,18 @@ */ static int port_cost(struct net_device *dev) { - if (dev->ethtool_ops && dev->ethtool_ops->get_settings) { - struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET, }; - - if (!dev_ethtool_get_settings(dev, &ecmd)) { - switch (ethtool_cmd_speed(&ecmd)) { - case SPEED_10000: - return 2; - case SPEED_1000: - return 4; - case SPEED_100: - return 19; - case SPEED_10: - return 100; - } + struct ethtool_cmd ecmd; + + if (!__ethtool_get_settings(dev, &ecmd)) { + switch (ethtool_cmd_speed(&ecmd)) { + case SPEED_10000: + return 2; + case SPEED_1000: + return 4; + case SPEED_100: + return 19; + case SPEED_10: + return 100; } } @@ -325,7 +324,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) /* Don't allow bridging non-ethernet like devices */ if ((dev->flags & IFF_LOOPBACK) || - dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN) + dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN || + !is_valid_ether_addr(dev->dev_addr)) return -EINVAL; /* No bridging of bridges */ @@ -353,10 +353,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) err = kobject_init_and_add(&p->kobj, &brport_ktype, &(dev->dev.kobj), SYSFS_BRIDGE_PORT_ATTR); if (err) - goto err0; - - err = br_fdb_insert(br, p, dev->dev_addr); - if (err) goto err1; err = br_sysfs_addif(p); @@ -397,6 +393,9 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) dev_set_mtu(br->dev, br_min_mtu(br)); + if (br_fdb_insert(br, p, dev->dev_addr)) + netdev_err(dev, "failed insert local address bridge forwarding table\n"); + kobject_uevent(&p->kobj, KOBJ_ADD); return 0; @@ -406,11 +405,9 @@ err4: err3: sysfs_remove_link(br->ifobj, p->dev->name); err2: - br_fdb_delete_by_port(br, p, 1); -err1: kobject_put(&p->kobj); p = NULL; /* kobject_put frees */ -err0: +err1: dev_set_promiscuity(dev, -1); put_back: dev_put(dev); diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index f06ee39..5a31731 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -16,6 +16,7 @@ #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/netfilter_bridge.h> +#include <linux/export.h> #include "br_private.h" /* Bridge group multicast address 802.1d (pg 51). */ @@ -162,14 +163,37 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb) p = br_port_get_rcu(skb->dev); if (unlikely(is_link_local(dest))) { - /* Pause frames shouldn't be passed up by driver anyway */ - if (skb->protocol == htons(ETH_P_PAUSE)) + /* + * See IEEE 802.1D Table 7-10 Reserved addresses + * + * Assignment Value + * Bridge Group Address 01-80-C2-00-00-00 + * (MAC Control) 802.3 01-80-C2-00-00-01 + * (Link Aggregation) 802.3 01-80-C2-00-00-02 + * 802.1X PAE address 01-80-C2-00-00-03 + * + * 802.1AB LLDP 01-80-C2-00-00-0E + * + * Others reserved for future standardization + */ + switch (dest[5]) { + case 0x00: /* Bridge Group Address */ + /* If STP is turned off, + then must forward to keep loop detection */ + if (p->br->stp_enabled == BR_NO_STP) + goto forward; + break; + + case 0x01: /* IEEE MAC (Pause) */ goto drop; - /* If STP is turned off, then forward */ - if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0) - goto forward; + default: + /* Allow selective forwarding for most other protocols */ + if (p->br->group_fwd_mask & (1u << dest[5])) + goto forward; + } + /* Deliver packet to local host only */ if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, NULL, br_handle_local_finish)) { return RX_HANDLER_CONSUMED; /* consumed by filter */ diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 857a021..d7d6fb0 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -29,6 +29,11 @@ #define BR_VERSION "2.3" +/* Control of forwarding link local multicast */ +#define BR_GROUPFWD_DEFAULT 0 +/* Don't allow forwarding control protocols like STP and LLDP */ +#define BR_GROUPFWD_RESTRICTED 0x4007u + /* Path to usermode spanning tree program */ #define BR_STP_PROG "/sbin/bridge-stp" @@ -193,6 +198,8 @@ struct net_bridge unsigned long flags; #define BR_SET_MAC_ADDR 0x00000001 + u16 group_fwd_mask; + /* STP */ bridge_id designated_root; bridge_id bridge_id; diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 10eda3c..19308e3 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -12,6 +12,7 @@ */ #include <linux/kernel.h> +#include <linux/kmod.h> #include <linux/etherdevice.h> #include <linux/rtnetlink.h> diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 68b893e..c236c0e 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c @@ -149,6 +149,39 @@ static ssize_t store_stp_state(struct device *d, static DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state, store_stp_state); +static ssize_t show_group_fwd_mask(struct device *d, + struct device_attribute *attr, char *buf) +{ + struct net_bridge *br = to_bridge(d); + return sprintf(buf, "%#x\n", br->group_fwd_mask); +} + + +static ssize_t store_group_fwd_mask(struct device *d, + struct device_attribute *attr, const char *buf, + size_t len) +{ + struct net_bridge *br = to_bridge(d); + char *endp; + unsigned long val; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + val = simple_strtoul(buf, &endp, 0); + if (endp == buf) + return -EINVAL; + + if (val & BR_GROUPFWD_RESTRICTED) + return -EINVAL; + + br->group_fwd_mask = val; + + return len; +} +static DEVICE_ATTR(group_fwd_mask, S_IRUGO | S_IWUSR, show_group_fwd_mask, + store_group_fwd_mask); + static ssize_t show_priority(struct device *d, struct device_attribute *attr, char *buf) { @@ -652,6 +685,7 @@ static struct attribute *bridge_attrs[] = { &dev_attr_max_age.attr, &dev_attr_ageing_time.attr, &dev_attr_stp_state.attr, + &dev_attr_group_fwd_mask.attr, &dev_attr_priority.attr, &dev_attr_bridge_id.attr, &dev_attr_root_id.attr, diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c index bf2a333..5449294 100644 --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -102,16 +102,15 @@ static struct sk_buff *ulog_alloc_skb(unsigned int size) unsigned int n; n = max(size, nlbufsiz); - skb = alloc_skb(n, GFP_ATOMIC); + skb = alloc_skb(n, GFP_ATOMIC | __GFP_NOWARN); if (!skb) { - pr_debug("cannot alloc whole buffer of size %ub!\n", n); if (n > size) { /* try to allocate only as much as we need for * current packet */ skb = alloc_skb(size, GFP_ATOMIC); if (!skb) - pr_debug("cannot even allocate " - "buffer of size %ub\n", size); + pr_debug("cannot even allocate buffer of size %ub\n", + size); } } diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c index 1bcaf36..40d8258 100644 --- a/net/bridge/netfilter/ebtable_broute.c +++ b/net/bridge/netfilter/ebtable_broute.c @@ -87,14 +87,14 @@ static int __init ebtable_broute_init(void) if (ret < 0) return ret; /* see br_input.c */ - rcu_assign_pointer(br_should_route_hook, + RCU_INIT_POINTER(br_should_route_hook, (br_should_route_hook_t *)ebt_broute); return 0; } static void __exit ebtable_broute_fini(void) { - rcu_assign_pointer(br_should_route_hook, NULL); + RCU_INIT_POINTER(br_should_route_hook, NULL); synchronize_net(); unregister_pernet_subsys(&broute_net_ops); } |