Skip to content

Commit

Permalink
bridge: eliminate call by reference
Browse files Browse the repository at this point in the history
Change the bridging hook to be simple function with return value
rather than modifying the skb argument. This could generate better
code and is cleaner.

Signed-off-by: Stephen Hemminger <[email protected]>
  • Loading branch information
Stephen Hemminger authored and David S. Miller committed Apr 26, 2007
1 parent 6047637 commit 6229e36
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 25 deletions.
3 changes: 2 additions & 1 deletion include/linux/if_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ struct __fdb_entry
#include <linux/netdevice.h>

extern void brioctl_set(int (*ioctl_hook)(unsigned int, void __user *));
extern int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb);
extern struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p,
struct sk_buff *skb);
extern int (*br_should_route_hook)(struct sk_buff **pskb);

#endif
Expand Down
20 changes: 9 additions & 11 deletions net/bridge/br_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,29 +121,27 @@ static inline int is_link_local(const unsigned char *dest)

/*
* Called via br_handle_frame_hook.
* Return 0 if *pskb should be processed furthur
* 1 if *pskb is handled
* Return NULL if skb is handled
* note: already called with rcu_read_lock (preempt_disabled)
*/
int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
{
struct sk_buff *skb = *pskb;
const unsigned char *dest = eth_hdr(skb)->h_dest;

if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
goto err;

if (unlikely(is_link_local(dest))) {
skb->pkt_type = PACKET_HOST;
return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
NULL, br_handle_local_finish) != 0;

return (NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
NULL, br_handle_local_finish) == 0) ? skb : NULL;
}

if (p->state == BR_STATE_FORWARDING || p->state == BR_STATE_LEARNING) {
if (br_should_route_hook) {
if (br_should_route_hook(pskb))
return 0;
skb = *pskb;
if (br_should_route_hook(&skb))
return skb;
dest = eth_hdr(skb)->h_dest;
}

Expand All @@ -152,10 +150,10 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)

NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
br_handle_frame_finish);
return 1;
return NULL;
}

err:
kfree_skb(skb);
return 1;
return NULL;
}
3 changes: 2 additions & 1 deletion net/bridge/br_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,8 @@ extern void br_features_recompute(struct net_bridge *br);

/* br_input.c */
extern int br_handle_frame_finish(struct sk_buff *skb);
extern int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb);
extern struct sk_buff *br_handle_frame(struct net_bridge_port *p,
struct sk_buff *skb);

/* br_ioctl.c */
extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
Expand Down
31 changes: 19 additions & 12 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1687,31 +1687,37 @@ static inline int deliver_skb(struct sk_buff *skb,
}

#if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE)
int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb);
/* These hooks defined here for ATM */
struct net_bridge;
struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
unsigned char *addr);
void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) __read_mostly;

static __inline__ int handle_bridge(struct sk_buff **pskb,
struct packet_type **pt_prev, int *ret,
struct net_device *orig_dev)
/*
* If bridge module is loaded call bridging hook.
* returns NULL if packet was consumed.
*/
struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p,
struct sk_buff *skb) __read_mostly;
static inline struct sk_buff *handle_bridge(struct sk_buff *skb,
struct packet_type **pt_prev, int *ret,
struct net_device *orig_dev)
{
struct net_bridge_port *port;

if ((*pskb)->pkt_type == PACKET_LOOPBACK ||
(port = rcu_dereference((*pskb)->dev->br_port)) == NULL)
return 0;
if (skb->pkt_type == PACKET_LOOPBACK ||
(port = rcu_dereference(skb->dev->br_port)) == NULL)
return skb;

if (*pt_prev) {
*ret = deliver_skb(*pskb, *pt_prev, orig_dev);
*ret = deliver_skb(skb, *pt_prev, orig_dev);
*pt_prev = NULL;
}

return br_handle_frame_hook(port, pskb);
return br_handle_frame_hook(port, skb);
}
#else
#define handle_bridge(skb, pt_prev, ret, orig_dev) (0)
#define handle_bridge(skb, pt_prev, ret, orig_dev) (skb)
#endif

#ifdef CONFIG_NET_CLS_ACT
Expand Down Expand Up @@ -1818,7 +1824,8 @@ int netif_receive_skb(struct sk_buff *skb)
ncls:
#endif

if (handle_bridge(&skb, &pt_prev, &ret, orig_dev))
skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
if (!skb)
goto out;

type = skb->protocol;
Expand Down

0 comments on commit 6229e36

Please sign in to comment.