[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