aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
authorJiri Pirko <jpirko@redhat.com>2010-06-01 17:52:08 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-02 10:11:15 -0400
commitab95bfe01f9872459c8678572ccadbf646badad0 (patch)
tree8e11f94077c9a80f7af52ce3dd50591a686561d7 /net/bridge
parent20c59de2e6b6bc74bbf714dcd4e720afe8d516cf (diff)
net: replace hooks in __netif_receive_skb V5
What this patch does is it removes two receive frame hooks (for bridge and for macvlan) from __netif_receive_skb. These are replaced them with a single hook for both. It only supports one hook per device because it makes no sense to do bridging and macvlan on the same device. Then a network driver (of virtual netdev like macvlan or bridge) can register an rx_handler for needed net device. Signed-off-by: Jiri Pirko <jpirko@redhat.com> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br.c2
-rw-r--r--net/bridge/br_if.c8
-rw-r--r--net/bridge/br_input.c12
-rw-r--r--net/bridge/br_private.h3
4 files changed, 18 insertions, 7 deletions
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 76357b547752..c8436fa31344 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -63,7 +63,6 @@ static int __init br_init(void)
63 goto err_out4; 63 goto err_out4;
64 64
65 brioctl_set(br_ioctl_deviceless_stub); 65 brioctl_set(br_ioctl_deviceless_stub);
66 br_handle_frame_hook = br_handle_frame;
67 66
68#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) 67#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
69 br_fdb_test_addr_hook = br_fdb_test_addr; 68 br_fdb_test_addr_hook = br_fdb_test_addr;
@@ -100,7 +99,6 @@ static void __exit br_deinit(void)
100 br_fdb_test_addr_hook = NULL; 99 br_fdb_test_addr_hook = NULL;
101#endif 100#endif
102 101
103 br_handle_frame_hook = NULL;
104 br_fdb_fini(); 102 br_fdb_fini();
105} 103}
106 104
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 18b245e2c00e..d9242342837e 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -147,6 +147,7 @@ static void del_nbp(struct net_bridge_port *p)
147 147
148 list_del_rcu(&p->list); 148 list_del_rcu(&p->list);
149 149
150 netdev_rx_handler_unregister(dev);
150 rcu_assign_pointer(dev->br_port, NULL); 151 rcu_assign_pointer(dev->br_port, NULL);
151 152
152 br_multicast_del_port(p); 153 br_multicast_del_port(p);
@@ -429,6 +430,11 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
429 goto err2; 430 goto err2;
430 431
431 rcu_assign_pointer(dev->br_port, p); 432 rcu_assign_pointer(dev->br_port, p);
433
434 err = netdev_rx_handler_register(dev, br_handle_frame);
435 if (err)
436 goto err3;
437
432 dev_disable_lro(dev); 438 dev_disable_lro(dev);
433 439
434 list_add_rcu(&p->list, &br->port_list); 440 list_add_rcu(&p->list, &br->port_list);
@@ -451,6 +457,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
451 br_netpoll_enable(br, dev); 457 br_netpoll_enable(br, dev);
452 458
453 return 0; 459 return 0;
460err3:
461 rcu_assign_pointer(dev->br_port, NULL);
454err2: 462err2:
455 br_fdb_delete_by_port(br, p, 1); 463 br_fdb_delete_by_port(br, p, 1);
456err1: 464err1:
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index d36e700f7a26..99647d8f95c8 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -131,15 +131,19 @@ static inline int is_link_local(const unsigned char *dest)
131} 131}
132 132
133/* 133/*
134 * Called via br_handle_frame_hook.
135 * Return NULL if skb is handled 134 * Return NULL if skb is handled
136 * note: already called with rcu_read_lock (preempt_disabled) 135 * note: already called with rcu_read_lock (preempt_disabled) from
136 * netif_receive_skb
137 */ 137 */
138struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb) 138struct sk_buff *br_handle_frame(struct sk_buff *skb)
139{ 139{
140 struct net_bridge_port *p;
140 const unsigned char *dest = eth_hdr(skb)->h_dest; 141 const unsigned char *dest = eth_hdr(skb)->h_dest;
141 int (*rhook)(struct sk_buff *skb); 142 int (*rhook)(struct sk_buff *skb);
142 143
144 if (skb->pkt_type == PACKET_LOOPBACK)
145 return skb;
146
143 if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) 147 if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
144 goto drop; 148 goto drop;
145 149
@@ -147,6 +151,8 @@ struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
147 if (!skb) 151 if (!skb)
148 return NULL; 152 return NULL;
149 153
154 p = rcu_dereference(skb->dev->br_port);
155
150 if (unlikely(is_link_local(dest))) { 156 if (unlikely(is_link_local(dest))) {
151 /* Pause frames shouldn't be passed up by driver anyway */ 157 /* Pause frames shouldn't be passed up by driver anyway */
152 if (skb->protocol == htons(ETH_P_PAUSE)) 158 if (skb->protocol == htons(ETH_P_PAUSE))
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 0f4a74bc6a9b..c83519b555bb 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -331,8 +331,7 @@ extern void br_features_recompute(struct net_bridge *br);
331 331
332/* br_input.c */ 332/* br_input.c */
333extern int br_handle_frame_finish(struct sk_buff *skb); 333extern int br_handle_frame_finish(struct sk_buff *skb);
334extern struct sk_buff *br_handle_frame(struct net_bridge_port *p, 334extern struct sk_buff *br_handle_frame(struct sk_buff *skb);
335 struct sk_buff *skb);
336 335
337/* br_ioctl.c */ 336/* br_ioctl.c */
338extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); 337extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);