[Devel] [PATCH rh7] net/bridge: zap via_phys_dev

Vladimir Davydov vdavydov at parallels.com
Tue Jun 16 10:03:31 PDT 2015


It was introduced initially in order to avoid the bridge's mac addr
change when a device is added/removed from the bridge. It is redundant
now, because we can force the bridge's MAC addr to a specific value, see
e.g.

http://backreference.org/2010/07/28/linux-bridge-mac-addresses-and-dynamic-ports/

Signed-off-by: Vladimir Davydov <vdavydov at parallels.com>
---
 include/linux/if_bridge.h      |  5 +--
 include/uapi/linux/if_bridge.h |  2 -
 net/bridge/br.c                |  2 -
 net/bridge/br_device.c         | 34 +----------------
 net/bridge/br_forward.c        | 40 ++------------------
 net/bridge/br_if.c             | 20 ----------
 net/bridge/br_input.c          | 24 +++---------
 net/bridge/br_ioctl.c          |  9 -----
 net/bridge/br_netfilter.c      | 10 +----
 net/bridge/br_private.h        |  9 +----
 net/bridge/br_sysfs_br.c       | 23 ------------
 net/core/dev.c                 | 85 ++++++++++--------------------------------
 12 files changed, 34 insertions(+), 229 deletions(-)

diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index ae2587def275..1085ffeef956 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -12,15 +12,12 @@
 #ifndef _LINUX_IF_BRIDGE_H
 #define _LINUX_IF_BRIDGE_H
 
+
 #include <linux/netdevice.h>
 #include <uapi/linux/if_bridge.h>
 
-#define BR_ALREADY_SEEN 1
-
 extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
 
-struct net_bridge_port;
-extern int (*br_hard_xmit_hook)(struct sk_buff *skb, struct net_bridge_port *port);
 typedef int br_should_route_hook_t(struct sk_buff *skb);
 extern br_should_route_hook_t __rcu *br_should_route_hook;
 
diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h
index 12e573d2d8a3..2d70d79ce2fd 100644
--- a/include/uapi/linux/if_bridge.h
+++ b/include/uapi/linux/if_bridge.h
@@ -42,7 +42,6 @@
 #define BRCTL_SET_PORT_PRIORITY 16
 #define BRCTL_SET_PATH_COST 17
 #define BRCTL_GET_FDB_ENTRIES 18
-#define BRCTL_SET_VIA_ORIG_DEV 19
 
 #define BR_STATE_DISABLED 0
 #define BR_STATE_LISTENING 1
@@ -70,7 +69,6 @@ struct __bridge_info {
 	__u32 tcn_timer_value;
 	__u32 topology_change_timer_value;
 	__u32 gc_timer_value;
-	__u8 via_phys_dev;
 };
 
 struct __port_info {
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 5356a3b297a2..ba780cc8e515 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -61,7 +61,6 @@ static int __init br_init(void)
 		goto err_out4;
 
 	brioctl_set(br_ioctl_deviceless_stub);
-	br_hard_xmit_hook = br_xmit;
 
 #if IS_ENABLED(CONFIG_ATM_LANE)
 	br_fdb_test_addr_hook = br_fdb_test_addr;
@@ -98,7 +97,6 @@ static void __exit br_deinit(void)
 	br_fdb_test_addr_hook = NULL;
 #endif
 
-	br_hard_xmit_hook = NULL;
 	br_fdb_fini();
 }
 
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 286b82c08547..54fbeff3612f 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -54,8 +54,6 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
 	skb_reset_mac_header(skb);
 	skb_pull(skb, ETH_HLEN);
 
-	skb->brmark = BR_ALREADY_SEEN;
-
 	if (is_broadcast_ether_addr(dest))
 		br_flood_deliver(br, skb);
 	else if (is_multicast_ether_addr(dest)) {
@@ -75,7 +73,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
 		else
 			br_flood_deliver(br, skb);
 	} else if ((dst = __br_fdb_get(br, dest, vid)) != NULL)
-		br_deliver(dst->dst, skb, 1);
+		br_deliver(dst->dst, skb);
 	else
 		br_flood_deliver(br, skb);
 
@@ -95,36 +93,6 @@ static int br_dev_init(struct net_device *dev)
 	return 0;
 }
 
-int br_xmit(struct sk_buff *skb, struct net_bridge_port *port)
-{
-	struct net_bridge *br = port->br;
-	const unsigned char *dest = skb->data;
-	struct net_bridge_fdb_entry *dst;
-	int ret = 0;
-
-	if (!br->via_phys_dev)
-		return 0;
-
-	br->dev->stats.tx_packets++;
-	br->dev->stats.tx_bytes += skb->len;
-
-	skb_reset_mac_header(skb);
-	skb_pull(skb, ETH_HLEN);
-
-	skb->brmark = BR_ALREADY_SEEN;
-
-	if (dest[0] & 1)
-		br_xmit_deliver(br, port, skb);
-	else if ((dst = __br_fdb_get(br, dest, 0)) != NULL)
-		ret = br_deliver(dst->dst, skb, 0);
-	else
-		br_xmit_deliver(br, port, skb);
-
-	skb_push(skb, ETH_HLEN);
-
-	return ret;
-}
-
 static int br_dev_open(struct net_device *dev)
 {
 	struct net_bridge *br = netdev_priv(dev);
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 653c0aa4a06f..53134342ac96 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -107,26 +107,14 @@ static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
 }
 
 /* called with rcu_read_lock */
-int br_deliver(const struct net_bridge_port *to, struct sk_buff *skb, int free)
+void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
 {
 	if (to && should_deliver(to, skb)) {
-		if (!free) {
-			struct sk_buff *skb2;
-
-			if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
-				to->dev->stats.tx_dropped++;
-				return 1;
-			}
-			skb = skb2;
-		}
 		__br_deliver(to, skb);
-		return 1;
+		return;
 	}
 
-	if (free)
-		kfree_skb(skb);
-
-	return 0;
+	kfree_skb(skb);
 }
 
 /* called with rcu_read_lock */
@@ -221,32 +209,10 @@ void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb)
 	br_flood(br, skb, NULL, __br_deliver);
 }
 
-/* called with rcu_read_lock */
-void br_xmit_deliver(struct net_bridge *br, struct net_bridge_port *port,
-						struct sk_buff *skb)
-{
-	struct net_bridge_port *p;
-
-	list_for_each_entry_rcu(p, &br->port_list, list) {
-		if (p == port)
-			continue;
-		if (should_deliver(p, skb)) {
-			struct sk_buff *skb2;
-
-			if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
-				br->dev->stats.tx_dropped++;
-				return;
-			}
-			__br_deliver(p, skb2);
-		}
-	}
-}
-
 /* called under bridge lock */
 void br_flood_forward(struct net_bridge *br, struct sk_buff *skb,
 		      struct sk_buff *skb2)
 {
-	skb->brmark = BR_ALREADY_SEEN;
 	br_flood(br, skb, skb2, __br_forward);
 }
 
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index a357ce8fe8a8..6b02ba09bee9 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -12,7 +12,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/nsproxy.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/netpoll.h>
@@ -169,11 +168,6 @@ void br_dev_delete(struct net_device *dev, struct list_head *head)
 	struct net_bridge *br = netdev_priv(dev);
 	struct net_bridge_port *p, *n;
 
-	if (br->master_dev) {
-		dev_put(br->master_dev);
-		br->master_dev = NULL;
-	}
-
 	list_for_each_entry_safe(p, n, &br->port_list, list) {
 		del_nbp(p);
 	}
@@ -397,10 +391,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
 	if (netif_running(dev) && netif_oper_up(dev) &&
 	    (br->dev->flags & IFF_UP))
 		br_stp_enable_port(p);
-	if (!(dev->features & NETIF_F_VIRTUAL) && !br->master_dev) {
-		dev_hold(dev);
-		br->master_dev = dev;
-	}
 	spin_unlock_bh(&br->lock);
 
 	br_ifinfo_notify(RTM_NEWLINK, p);
@@ -452,16 +442,6 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
 
 	spin_lock_bh(&br->lock);
 	changed_addr = br_stp_recalculate_bridge_id(br);
-	if (br->master_dev == dev) {
-		br->master_dev = NULL;
-		dev_put(dev);
-		list_for_each_entry(p, &br->port_list, list)
-			if (!(p->dev->features & NETIF_F_VIRTUAL)) {
-				dev_hold(p->dev);
-				br->master_dev = p->dev;
-				break;
-			}
-	}
 	spin_unlock_bh(&br->lock);
 
 	if (changed_addr)
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 15f99fe87674..37ac27339098 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -24,9 +24,10 @@
 br_should_route_hook_t __rcu *br_should_route_hook __read_mostly;
 EXPORT_SYMBOL(br_should_route_hook);
 
-static int br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
+static int br_pass_frame_up(struct sk_buff *skb)
 {
 	struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
+	struct net_bridge *br = netdev_priv(brdev);
 	struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats);
 
 	u64_stats_update_begin(&brstats->syncp);
@@ -49,13 +50,7 @@ static int br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
 		return NET_RX_DROP;
 
 	indev = skb->dev;
-	if (!br->via_phys_dev)
-		skb->dev = brdev;
-	else {
-		skb->brmark = BR_ALREADY_SEEN;
-		if (br->master_dev)
-			skb->dev = br->master_dev;
-	}
+	skb->dev = brdev;
 
 	return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
 		       netif_receive_skb);
@@ -95,7 +90,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
 	/* The packet skb2 goes to the local host (NULL to skip). */
 	skb2 = NULL;
 
-	if ((br->dev->flags & IFF_PROMISC) && !br->via_phys_dev)
+	if (br->dev->flags & IFF_PROMISC)
 		skb2 = skb;
 
 	dst = NULL;
@@ -128,7 +123,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
 		skb2 = skb_clone(skb, GFP_ATOMIC);
 
 	if (skb2)
-		err = br_pass_frame_up(br, skb2);
+		err = br_pass_frame_up(skb2);
 
 	if (skb) {
 		if (dst) {
@@ -223,8 +218,6 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
 
 forward:
 	switch (p->state) {
-		struct net_device *out;
-
 	case BR_STATE_FORWARDING:
 		rhook = rcu_dereference(br_should_route_hook);
 		if (rhook) {
@@ -236,12 +229,7 @@ forward:
 		}
 		/* fall through */
 	case BR_STATE_LEARNING:
-		if (skb->brmark == BR_ALREADY_SEEN)
-			return RX_HANDLER_PASS;
-
-		out = p->br->via_phys_dev ? p->br->master_dev : p->br->dev;
-
-		if (out && ether_addr_equal(out->dev_addr, dest))
+		if (ether_addr_equal(p->br->dev->dev_addr, dest))
 			skb->pkt_type = PACKET_HOST;
 
 		NF_HOOK(NFPROTO_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index 9687cfea0fc8..98447b8dc19d 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -15,7 +15,6 @@
 #include <linux/kernel.h>
 #include <linux/if_bridge.h>
 #include <linux/netdevice.h>
-#include <linux/nsproxy.h>
 #include <linux/slab.h>
 #include <linux/times.h>
 #include <net/net_namespace.h>
@@ -143,7 +142,6 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 		b.root_port = br->root_port;
 
 		b.stp_enabled = (br->stp_enabled != BR_NO_STP);
-		b.via_phys_dev = br->via_phys_dev;
 		b.ageing_time = jiffies_to_clock_t(br->ageing_time);
 		b.hello_timer_value = br_timer_value(&br->hello_timer);
 		b.tcn_timer_value = br_timer_value(&br->tcn_timer);
@@ -245,13 +243,6 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 		br_stp_set_enabled(br, args[1]);
 		return 0;
 
-	case BRCTL_SET_VIA_ORIG_DEV:
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-
-		br->via_phys_dev = args[1] ? 1 : 0;
-		return 0;
-
 	case BRCTL_SET_BRIDGE_PRIORITY:
 		if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
 			return -EPERM;
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 4dc65f9d7e93..a8570dfcdc10 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -182,17 +182,9 @@ static inline struct rtable *bridge_parent_rtable(const struct net_device *dev)
 static inline struct net_device *bridge_parent(const struct net_device *dev)
 {
 	struct net_bridge_port *port;
-	struct net_bridge *br;
 
 	port = br_port_get_rcu(dev);
-	if (!port)
-		return NULL;
-
-	br = port->br;
-	if (br->via_phys_dev && br->master_dev)
-		return br->master_dev;
-	else
-		return br->dev;
+	return port ? port->br->dev : NULL;
 }
 
 static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index c7dd805b88e8..65d40c34e651 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -226,8 +226,6 @@ struct net_bridge
 	struct list_head		port_list;
 	struct net_device		*dev;
 
-	struct net_device		*master_dev;
-	unsigned char			via_phys_dev;
 	struct br_cpu_netstats __percpu *stats;
 	spinlock_t			hash_lock;
 	struct hlist_head		hash[BR_HASH_SIZE];
@@ -350,8 +348,6 @@ extern void br_dev_setup(struct net_device *dev);
 extern void br_dev_delete(struct net_device *dev, struct list_head *list);
 extern netdev_tx_t br_dev_xmit(struct sk_buff *skb,
 			       struct net_device *dev);
-extern netdev_tx_t br_xmit(struct sk_buff *skb, struct net_bridge_port *port);
-
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br)
 {
@@ -429,14 +425,13 @@ extern int br_fdb_dump(struct sk_buff *skb,
 		       int idx);
 
 /* br_forward.c */
-extern int br_deliver(const struct net_bridge_port *to,
-		struct sk_buff *skb, int free);
+extern void br_deliver(const struct net_bridge_port *to,
+		struct sk_buff *skb);
 extern int br_dev_queue_push_xmit(struct sk_buff *skb);
 extern void br_forward(const struct net_bridge_port *to,
 		struct sk_buff *skb, struct sk_buff *skb0);
 extern int br_forward_finish(struct sk_buff *skb);
 extern void br_flood_deliver(struct net_bridge *br, struct sk_buff *skb);
-extern void br_xmit_deliver(struct net_bridge *br, struct net_bridge_port *port, struct sk_buff *skb);
 extern void br_flood_forward(struct net_bridge *br, struct sk_buff *skb,
 			     struct sk_buff *skb2);
 
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index 266be109f5ef..8baa9c08e1a4 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -183,28 +183,6 @@ static ssize_t store_group_fwd_mask(struct device *d,
 static DEVICE_ATTR(group_fwd_mask, S_IRUGO | S_IWUSR, show_group_fwd_mask,
 		   store_group_fwd_mask);
 
-static ssize_t show_via_phys_dev_state(struct device *cd,
-				struct device_attribute *attr, char *buf)
-{
-	struct net_bridge *br = to_bridge(cd);
-	return sprintf(buf, "%d\n", br->via_phys_dev);
-}
-
-static int set_via_phys_dev_state(struct net_bridge *br, unsigned long val)
-{
-	br->via_phys_dev = val ? 1 : 0;
-	return 0;
-}
-
-static ssize_t store_via_phys_dev_state(struct device *cd,
-		struct device_attribute *attr, const char *buf, size_t len)
-{
-	return store_bridge_parm(cd, buf, len, set_via_phys_dev_state);
-}
-
-static DEVICE_ATTR(via_phys_dev, S_IRUGO | S_IWUSR, show_via_phys_dev_state,
-			 store_via_phys_dev_state);
-
 static ssize_t show_priority(struct device *d, struct device_attribute *attr,
 			     char *buf)
 {
@@ -738,7 +716,6 @@ static struct attribute *bridge_attrs[] = {
 	&dev_attr_max_age.attr,
 	&dev_attr_ageing_time.attr,
 	&dev_attr_stp_state.attr,
-	&dev_attr_via_phys_dev.attr,
 	&dev_attr_group_fwd_mask.attr,
 	&dev_attr_priority.attr,
 	&dev_attr_bridge_id.attr,
diff --git a/net/core/dev.c b/net/core/dev.c
index 8e9bce73788e..79022a51d015 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2495,66 +2495,23 @@ static inline int skb_needs_linearize(struct sk_buff *skb,
 				!(features & NETIF_F_SG)));
 }
 
-#if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE)
-#include "../bridge/br_private.h"
-int (*br_hard_xmit_hook)(struct sk_buff *skb, struct net_bridge_port *port);
-EXPORT_SYMBOL(br_hard_xmit_hook);
-static __inline__ int bridge_hard_start_xmit(struct sk_buff *skb,
-					     struct net_device *dev)
-{
-	struct net_bridge_port *port;
-
-	if (!br_hard_xmit_hook)
-		return 0;
-
-	if (((port = br_port_get_rcu(dev)) == NULL) ||
-			(skb->brmark == BR_ALREADY_SEEN))
-		return 0;
-
-	return br_hard_xmit_hook(skb, port);
-}
-#else
-#define bridge_hard_start_xmit(skb, dev)       (0)
-#endif
-
-static inline int dev_hard_xmit(struct sk_buff *skb, struct net_device *dev)
+int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
+			struct netdev_queue *txq)
 {
 	const struct net_device_ops *ops = dev->netdev_ops;
 	int rc = NETDEV_TX_OK;
 	unsigned int skb_len;
 
-	/*
-	 * Bridge must handle packet with dst information set.
-	 * If there is no dst set in skb - it can cause oops in NAT.
-	 */
-	rc = bridge_hard_start_xmit(skb, dev);
-
-	/*
-	 * If device doesn't need skb->dst, release it right now while
-	 * its hot in this cpu cache
-	 */
-	if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
-		skb_dst_drop(skb);
-
-	if (rc > 0) {
-		kfree_skb(skb);
-		return NETDEV_TX_OK;
-	}
-
-	skb_len = skb->len;
-	rc = ops->ndo_start_xmit(skb, dev);
-	trace_net_dev_xmit(skb, rc, dev, skb_len);
-	return rc;
-}
-
-int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
-		struct netdev_queue *txq)
-{
-	int rc = NETDEV_TX_OK;
-
 	if (likely(!skb->next)) {
 		netdev_features_t features;
 
+		/*
+		 * If device doesn't need skb->dst, release it right now while
+		 * its hot in this cpu cache
+		 */
+		if (dev->priv_flags & IFF_XMIT_DST_RELEASE)
+			skb_dst_drop(skb);
+
 		features = netif_skb_features(skb);
 
 		if (vlan_tx_tag_present(skb) &&
@@ -2604,8 +2561,9 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
 		if (!list_empty(&ptype_all))
 			dev_queue_xmit_nit(skb, dev);
 
-		rc = dev_hard_xmit(skb, dev);
-
+		skb_len = skb->len;
+		rc = ops->ndo_start_xmit(skb, dev);
+		trace_net_dev_xmit(skb, rc, dev, skb_len);
 		if (rc == NETDEV_TX_OK)
 			txq_trans_update(txq);
 		return rc;
@@ -2621,8 +2579,9 @@ gso:
 		if (!list_empty(&ptype_all))
 			dev_queue_xmit_nit(nskb, dev);
 
-		rc = dev_hard_xmit(nskb, dev);
-
+		skb_len = nskb->len;
+		rc = ops->ndo_start_xmit(nskb, dev);
+		trace_net_dev_xmit(nskb, rc, dev, skb_len);
 		if (unlikely(rc != NETDEV_TX_OK)) {
 			if (rc & ~NETDEV_TX_MASK)
 				goto out_kfree_gso_skb;
@@ -3488,17 +3447,13 @@ another_round:
 	if (pfmemalloc)
 		goto skip_taps;
 
-#if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE)
-	if (skb->brmark != BR_ALREADY_SEEN) {
-		list_for_each_entry_rcu(ptype, &ptype_all, list) {
-			if (!ptype->dev || ptype->dev == skb->dev) {
-				if (pt_prev)
-					ret = deliver_skb(skb, pt_prev, orig_dev);
-				pt_prev = ptype;
-			}
+	list_for_each_entry_rcu(ptype, &ptype_all, list) {
+		if (!ptype->dev || ptype->dev == skb->dev) {
+			if (pt_prev)
+				ret = deliver_skb(skb, pt_prev, orig_dev);
+			pt_prev = ptype;
 		}
 	}
-#endif
 
 skip_taps:
 #ifdef CONFIG_NET_CLS_ACT
-- 
2.1.4




More information about the Devel mailing list