diff mbox

[04/11] bridge: Cache vlan in the cb for faster egress lookup.

Message ID 1355342477-4971-5-git-send-email-vyasevic@redhat.com
State Deferred, archived
Delegated to: David Miller
Headers show

Commit Message

Vlad Yasevich Dec. 12, 2012, 8:01 p.m. UTC
On input, cache the pointer to the bridge vlan info, so that
on egress, we have can simply look at the port bitmap instead
of traversing a vlan list.

Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
---
 net/bridge/br_device.c  |    8 ++++++++
 net/bridge/br_forward.c |   14 ++++++++++++++
 net/bridge/br_input.c   |    6 +++++-
 net/bridge/br_private.h |    1 +
 4 files changed, 28 insertions(+), 1 deletions(-)

Comments

stephen hemminger Dec. 18, 2012, 5:04 p.m. UTC | #1
On Wed, 12 Dec 2012 15:01:10 -0500
Vlad Yasevich <vyasevic@redhat.com> wrote:

> On input, cache the pointer to the bridge vlan info, so that
> on egress, we have can simply look at the port bitmap instead
> of traversing a vlan list.
> 
> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>

This isn't going to be safe. Once packet is passed up, the cb[]
can get overwritten by other things.
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Vlad Yasevich Dec. 18, 2012, 5:50 p.m. UTC | #2
On 12/18/2012 12:04 PM, Stephen Hemminger wrote:
> On Wed, 12 Dec 2012 15:01:10 -0500
> Vlad Yasevich <vyasevic@redhat.com> wrote:
>
>> On input, cache the pointer to the bridge vlan info, so that
>> on egress, we have can simply look at the port bitmap instead
>> of traversing a vlan list.
>>
>> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
>
> This isn't going to be safe. Once packet is passed up, the cb[]
> can get overwritten by other things.
>

Right, but only care about it while in bridging code.  We don't look
at it anywhere else...

Or are you saying that cb is not guaranteed to be preserved between 
br_handle_frame_finish and br_forward?

-vlad
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 9546742..57c5bac 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -30,6 +30,7 @@  netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
 	struct net_bridge_fdb_entry *dst;
 	struct net_bridge_mdb_entry *mdst;
 	struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats);
+	struct net_bridge_vlan *vlan;
 
 	rcu_read_lock();
 #ifdef CONFIG_BRIDGE_NETFILTER
@@ -47,6 +48,13 @@  netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	BR_INPUT_SKB_CB(skb)->brdev = dev;
 
+	/* Any vlan transmitted by the bridge itself is permitted.
+	 * Try to cache the vlan in the CB to speed up forwarding.
+	 */
+	vlan = br_vlan_find(br, br_get_vlan(skb));
+	if (vlan)
+		BR_INPUT_SKB_CB(skb)->vlan = vlan;
+
 	skb_reset_mac_header(skb);
 	skb_pull(skb, ETH_HLEN);
 
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 0c7ffc2..4ae5f55 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -30,11 +30,25 @@  static inline bool br_allowed_egress(const struct net_bridge_port *p,
 				     const struct sk_buff *skb)
 {
 	struct net_port_vlan *pve;
+	struct net_bridge_vlan *vlan = NULL;
 	u16 vid;
 
 	if (list_empty(&p->vlan_list))
 		return true;
 
+	vlan = BR_INPUT_SKB_CB(skb)->vlan;
+	if (vlan) {
+		/* If we have cached VLAN information, use port_bitmap
+		 * of the vlan to make the decision
+		 */
+		if (test_bit(p->port_no, vlan->port_bitmap))
+			return true;
+		return false;
+	}
+
+	/* We don't have cached vlan information, so we need to do
+	 * it the hard way.
+	 */
 	vid = br_get_vlan(skb);
 	pve = nbp_vlan_find(p, vid);
 	if (pve)
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 54c0894..e475f49 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -47,6 +47,8 @@  static bool br_allowed_ingress(struct net_bridge_port *p, struct sk_buff *skb)
 	struct net_port_vlan *pve;
 	u16 vid;
 
+	BR_INPUT_SKB_CB(skb)->vlan = NULL;
+
 	/* If there are no vlan in the permitted list, all packets are
 	 * permitted.
 	 */
@@ -55,8 +57,10 @@  static bool br_allowed_ingress(struct net_bridge_port *p, struct sk_buff *skb)
 
 	vid = br_get_vlan(skb);
 	pve = nbp_vlan_find(p, vid);
-	if (pve)
+	if (pve) {
+		BR_INPUT_SKB_CB(skb)->vlan = pve->vlan;
 		return true;
+	}
 
 	return false;
 }
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index a385d9a..1475fab 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -300,6 +300,7 @@  struct net_bridge
 
 struct br_input_skb_cb {
 	struct net_device *brdev;
+	struct net_bridge_vlan *vlan;
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 	int igmp;
 	int mrouters_only;