aboutsummaryrefslogtreecommitdiffstats
path: root/net
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
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')
-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
-rw-r--r--net/core/dev.c119
5 files changed, 73 insertions, 71 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);
diff --git a/net/core/dev.c b/net/core/dev.c
index ffca5c1066fa..ec01a5998d70 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2604,70 +2604,14 @@ static inline int deliver_skb(struct sk_buff *skb,
2604 return pt_prev->func(skb, skb->dev, pt_prev, orig_dev); 2604 return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
2605} 2605}
2606 2606
2607#if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE) 2607#if (defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)) && \
2608 2608 (defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE))
2609#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
2610/* This hook is defined here for ATM LANE */ 2609/* This hook is defined here for ATM LANE */
2611int (*br_fdb_test_addr_hook)(struct net_device *dev, 2610int (*br_fdb_test_addr_hook)(struct net_device *dev,
2612 unsigned char *addr) __read_mostly; 2611 unsigned char *addr) __read_mostly;
2613EXPORT_SYMBOL_GPL(br_fdb_test_addr_hook); 2612EXPORT_SYMBOL_GPL(br_fdb_test_addr_hook);
2614#endif 2613#endif
2615 2614
2616/*
2617 * If bridge module is loaded call bridging hook.
2618 * returns NULL if packet was consumed.
2619 */
2620struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p,
2621 struct sk_buff *skb) __read_mostly;
2622EXPORT_SYMBOL_GPL(br_handle_frame_hook);
2623
2624static inline struct sk_buff *handle_bridge(struct sk_buff *skb,
2625 struct packet_type **pt_prev, int *ret,
2626 struct net_device *orig_dev)
2627{
2628 struct net_bridge_port *port;
2629
2630 if (skb->pkt_type == PACKET_LOOPBACK ||
2631 (port = rcu_dereference(skb->dev->br_port)) == NULL)
2632 return skb;
2633
2634 if (*pt_prev) {
2635 *ret = deliver_skb(skb, *pt_prev, orig_dev);
2636 *pt_prev = NULL;
2637 }
2638
2639 return br_handle_frame_hook(port, skb);
2640}
2641#else
2642#define handle_bridge(skb, pt_prev, ret, orig_dev) (skb)
2643#endif
2644
2645#if defined(CONFIG_MACVLAN) || defined(CONFIG_MACVLAN_MODULE)
2646struct sk_buff *(*macvlan_handle_frame_hook)(struct macvlan_port *p,
2647 struct sk_buff *skb) __read_mostly;
2648EXPORT_SYMBOL_GPL(macvlan_handle_frame_hook);
2649
2650static inline struct sk_buff *handle_macvlan(struct sk_buff *skb,
2651 struct packet_type **pt_prev,
2652 int *ret,
2653 struct net_device *orig_dev)
2654{
2655 struct macvlan_port *port;
2656
2657 port = rcu_dereference(skb->dev->macvlan_port);
2658 if (!port)
2659 return skb;
2660
2661 if (*pt_prev) {
2662 *ret = deliver_skb(skb, *pt_prev, orig_dev);
2663 *pt_prev = NULL;
2664 }
2665 return macvlan_handle_frame_hook(port, skb);
2666}
2667#else
2668#define handle_macvlan(skb, pt_prev, ret, orig_dev) (skb)
2669#endif
2670
2671#ifdef CONFIG_NET_CLS_ACT 2615#ifdef CONFIG_NET_CLS_ACT
2672/* TODO: Maybe we should just force sch_ingress to be compiled in 2616/* TODO: Maybe we should just force sch_ingress to be compiled in
2673 * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions 2617 * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions
@@ -2763,6 +2707,47 @@ void netif_nit_deliver(struct sk_buff *skb)
2763 rcu_read_unlock(); 2707 rcu_read_unlock();
2764} 2708}
2765 2709
2710/**
2711 * netdev_rx_handler_register - register receive handler
2712 * @dev: device to register a handler for
2713 * @rx_handler: receive handler to register
2714 *
2715 * Register a receive hander for a device. This handler will then be
2716 * called from __netif_receive_skb. A negative errno code is returned
2717 * on a failure.
2718 *
2719 * The caller must hold the rtnl_mutex.
2720 */
2721int netdev_rx_handler_register(struct net_device *dev,
2722 rx_handler_func_t *rx_handler)
2723{
2724 ASSERT_RTNL();
2725
2726 if (dev->rx_handler)
2727 return -EBUSY;
2728
2729 rcu_assign_pointer(dev->rx_handler, rx_handler);
2730
2731 return 0;
2732}
2733EXPORT_SYMBOL_GPL(netdev_rx_handler_register);
2734
2735/**
2736 * netdev_rx_handler_unregister - unregister receive handler
2737 * @dev: device to unregister a handler from
2738 *
2739 * Unregister a receive hander from a device.
2740 *
2741 * The caller must hold the rtnl_mutex.
2742 */
2743void netdev_rx_handler_unregister(struct net_device *dev)
2744{
2745
2746 ASSERT_RTNL();
2747 rcu_assign_pointer(dev->rx_handler, NULL);
2748}
2749EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
2750
2766static inline void skb_bond_set_mac_by_master(struct sk_buff *skb, 2751static inline void skb_bond_set_mac_by_master(struct sk_buff *skb,
2767 struct net_device *master) 2752 struct net_device *master)
2768{ 2753{
@@ -2815,6 +2800,7 @@ EXPORT_SYMBOL(__skb_bond_should_drop);
2815static int __netif_receive_skb(struct sk_buff *skb) 2800static int __netif_receive_skb(struct sk_buff *skb)
2816{ 2801{
2817 struct packet_type *ptype, *pt_prev; 2802 struct packet_type *ptype, *pt_prev;
2803 rx_handler_func_t *rx_handler;
2818 struct net_device *orig_dev; 2804 struct net_device *orig_dev;
2819 struct net_device *master; 2805 struct net_device *master;
2820 struct net_device *null_or_orig; 2806 struct net_device *null_or_orig;
@@ -2877,12 +2863,17 @@ static int __netif_receive_skb(struct sk_buff *skb)
2877ncls: 2863ncls:
2878#endif 2864#endif
2879 2865
2880 skb = handle_bridge(skb, &pt_prev, &ret, orig_dev); 2866 /* Handle special case of bridge or macvlan */
2881 if (!skb) 2867 rx_handler = rcu_dereference(skb->dev->rx_handler);
2882 goto out; 2868 if (rx_handler) {
2883 skb = handle_macvlan(skb, &pt_prev, &ret, orig_dev); 2869 if (pt_prev) {
2884 if (!skb) 2870 ret = deliver_skb(skb, pt_prev, orig_dev);
2885 goto out; 2871 pt_prev = NULL;
2872 }
2873 skb = rx_handler(skb);
2874 if (!skb)
2875 goto out;
2876 }
2886 2877
2887 /* 2878 /*
2888 * Make sure frames received on VLAN interfaces stacked on 2879 * Make sure frames received on VLAN interfaces stacked on