From a9fcc6a41de947108898bc9807f25fa326467365 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 3 May 2015 22:06:07 +0200 Subject: netfilter: bridge: free nf_bridge info on xmit nf_bridge information is only needed for -m physdev, so we can always free it after POST_ROUTING. This has the advantage that allocation and free will typically happen on the same cpu. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/bridge/br_netfilter.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 13973da29b2a..2b0e8bb49944 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -129,6 +129,14 @@ static struct nf_bridge_info *nf_bridge_info_get(const struct sk_buff *skb) return skb->nf_bridge; } +static void nf_bridge_info_free(struct sk_buff *skb) +{ + if (skb->nf_bridge) { + nf_bridge_put(skb->nf_bridge); + skb->nf_bridge = NULL; + } +} + static inline struct rtable *bridge_parent_rtable(const struct net_device *dev) { struct net_bridge_port *port; @@ -841,6 +849,7 @@ static int br_nf_push_frag_xmit(struct sock *sk, struct sk_buff *skb) skb_copy_to_linear_data_offset(skb, -data->size, data->mac, data->size); __skb_push(skb, data->encap_size); + nf_bridge_info_free(skb); return br_dev_queue_push_xmit(sk, skb); } @@ -850,8 +859,10 @@ static int br_nf_dev_queue_xmit(struct sock *sk, struct sk_buff *skb) int frag_max_size; unsigned int mtu_reserved; - if (skb_is_gso(skb) || skb->protocol != htons(ETH_P_IP)) + if (skb_is_gso(skb) || skb->protocol != htons(ETH_P_IP)) { + nf_bridge_info_free(skb); return br_dev_queue_push_xmit(sk, skb); + } mtu_reserved = nf_bridge_mtu_reduction(skb); /* This is wrong! We should preserve the original fragment @@ -877,6 +888,7 @@ static int br_nf_dev_queue_xmit(struct sock *sk, struct sk_buff *skb) ret = ip_fragment(sk, skb, br_nf_push_frag_xmit); } else { + nf_bridge_info_free(skb); ret = br_dev_queue_push_xmit(sk, skb); } @@ -885,7 +897,8 @@ static int br_nf_dev_queue_xmit(struct sock *sk, struct sk_buff *skb) #else static int br_nf_dev_queue_xmit(struct sock *sk, struct sk_buff *skb) { - return br_dev_queue_push_xmit(sk, skb); + nf_bridge_info_free(skb); + return br_dev_queue_push_xmit(sk, skb); } #endif -- cgit v1.2.3-59-g8ed1b