aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/net/macvlan.c19
-rw-r--r--include/linux/if_bridge.h2
-rw-r--r--include/linux/if_macvlan.h4
-rw-r--r--include/linux/netdevice.h7
-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
9 files changed, 93 insertions, 83 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 87e8d4cb405..53422ce26f7 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -145,15 +145,16 @@ static void macvlan_broadcast(struct sk_buff *skb,
145} 145}
146 146
147/* called under rcu_read_lock() from netif_receive_skb */ 147/* called under rcu_read_lock() from netif_receive_skb */
148static struct sk_buff *macvlan_handle_frame(struct macvlan_port *port, 148static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
149 struct sk_buff *skb)
150{ 149{
150 struct macvlan_port *port;
151 const struct ethhdr *eth = eth_hdr(skb); 151 const struct ethhdr *eth = eth_hdr(skb);
152 const struct macvlan_dev *vlan; 152 const struct macvlan_dev *vlan;
153 const struct macvlan_dev *src; 153 const struct macvlan_dev *src;
154 struct net_device *dev; 154 struct net_device *dev;
155 unsigned int len; 155 unsigned int len;
156 156
157 port = rcu_dereference(skb->dev->macvlan_port);
157 if (is_multicast_ether_addr(eth->h_dest)) { 158 if (is_multicast_ether_addr(eth->h_dest)) {
158 src = macvlan_hash_lookup(port, eth->h_source); 159 src = macvlan_hash_lookup(port, eth->h_source);
159 if (!src) 160 if (!src)
@@ -515,6 +516,7 @@ static int macvlan_port_create(struct net_device *dev)
515{ 516{
516 struct macvlan_port *port; 517 struct macvlan_port *port;
517 unsigned int i; 518 unsigned int i;
519 int err;
518 520
519 if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK) 521 if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK)
520 return -EINVAL; 522 return -EINVAL;
@@ -528,13 +530,21 @@ static int macvlan_port_create(struct net_device *dev)
528 for (i = 0; i < MACVLAN_HASH_SIZE; i++) 530 for (i = 0; i < MACVLAN_HASH_SIZE; i++)
529 INIT_HLIST_HEAD(&port->vlan_hash[i]); 531 INIT_HLIST_HEAD(&port->vlan_hash[i]);
530 rcu_assign_pointer(dev->macvlan_port, port); 532 rcu_assign_pointer(dev->macvlan_port, port);
531 return 0; 533
534 err = netdev_rx_handler_register(dev, macvlan_handle_frame);
535 if (err) {
536 rcu_assign_pointer(dev->macvlan_port, NULL);
537 kfree(port);
538 }
539
540 return err;
532} 541}
533 542
534static void macvlan_port_destroy(struct net_device *dev) 543static void macvlan_port_destroy(struct net_device *dev)
535{ 544{
536 struct macvlan_port *port = dev->macvlan_port; 545 struct macvlan_port *port = dev->macvlan_port;
537 546
547 netdev_rx_handler_unregister(dev);
538 rcu_assign_pointer(dev->macvlan_port, NULL); 548 rcu_assign_pointer(dev->macvlan_port, NULL);
539 synchronize_rcu(); 549 synchronize_rcu();
540 kfree(port); 550 kfree(port);
@@ -767,14 +777,12 @@ static int __init macvlan_init_module(void)
767 int err; 777 int err;
768 778
769 register_netdevice_notifier(&macvlan_notifier_block); 779 register_netdevice_notifier(&macvlan_notifier_block);
770 macvlan_handle_frame_hook = macvlan_handle_frame;
771 780
772 err = macvlan_link_register(&macvlan_link_ops); 781 err = macvlan_link_register(&macvlan_link_ops);
773 if (err < 0) 782 if (err < 0)
774 goto err1; 783 goto err1;
775 return 0; 784 return 0;
776err1: 785err1:
777 macvlan_handle_frame_hook = NULL;
778 unregister_netdevice_notifier(&macvlan_notifier_block); 786 unregister_netdevice_notifier(&macvlan_notifier_block);
779 return err; 787 return err;
780} 788}
@@ -782,7 +790,6 @@ err1:
782static void __exit macvlan_cleanup_module(void) 790static void __exit macvlan_cleanup_module(void)
783{ 791{
784 rtnl_link_unregister(&macvlan_link_ops); 792 rtnl_link_unregister(&macvlan_link_ops);
785 macvlan_handle_frame_hook = NULL;
786 unregister_netdevice_notifier(&macvlan_notifier_block); 793 unregister_netdevice_notifier(&macvlan_notifier_block);
787} 794}
788 795
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 938b7e81df9..0d241a5c490 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -102,8 +102,6 @@ struct __fdb_entry {
102#include <linux/netdevice.h> 102#include <linux/netdevice.h>
103 103
104extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *)); 104extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __user *));
105extern struct sk_buff *(*br_handle_frame_hook)(struct net_bridge_port *p,
106 struct sk_buff *skb);
107extern int (*br_should_route_hook)(struct sk_buff *skb); 105extern int (*br_should_route_hook)(struct sk_buff *skb);
108 106
109#endif 107#endif
diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h
index 9ea047aca79..c26a0e4f0ce 100644
--- a/include/linux/if_macvlan.h
+++ b/include/linux/if_macvlan.h
@@ -84,8 +84,4 @@ extern int macvlan_link_register(struct rtnl_link_ops *ops);
84extern netdev_tx_t macvlan_start_xmit(struct sk_buff *skb, 84extern netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
85 struct net_device *dev); 85 struct net_device *dev);
86 86
87
88extern struct sk_buff *(*macvlan_handle_frame_hook)(struct macvlan_port *,
89 struct sk_buff *);
90
91#endif /* _LINUX_IF_MACVLAN_H */ 87#endif /* _LINUX_IF_MACVLAN_H */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index bd6b75317d5..5156b806924 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -381,6 +381,8 @@ enum gro_result {
381}; 381};
382typedef enum gro_result gro_result_t; 382typedef enum gro_result gro_result_t;
383 383
384typedef struct sk_buff *rx_handler_func_t(struct sk_buff *skb);
385
384extern void __napi_schedule(struct napi_struct *n); 386extern void __napi_schedule(struct napi_struct *n);
385 387
386static inline int napi_disable_pending(struct napi_struct *n) 388static inline int napi_disable_pending(struct napi_struct *n)
@@ -957,6 +959,7 @@ struct net_device {
957#endif 959#endif
958 960
959 struct netdev_queue rx_queue; 961 struct netdev_queue rx_queue;
962 rx_handler_func_t *rx_handler;
960 963
961 struct netdev_queue *_tx ____cacheline_aligned_in_smp; 964 struct netdev_queue *_tx ____cacheline_aligned_in_smp;
962 965
@@ -1689,6 +1692,10 @@ static inline void napi_free_frags(struct napi_struct *napi)
1689 napi->skb = NULL; 1692 napi->skb = NULL;
1690} 1693}
1691 1694
1695extern int netdev_rx_handler_register(struct net_device *dev,
1696 rx_handler_func_t *rx_handler);
1697extern void netdev_rx_handler_unregister(struct net_device *dev);
1698
1692extern void netif_nit_deliver(struct sk_buff *skb); 1699extern void netif_nit_deliver(struct sk_buff *skb);
1693extern int dev_valid_name(const char *name); 1700extern int dev_valid_name(const char *name);
1694extern int dev_ioctl(struct net *net, unsigned int cmd, void __user *); 1701extern int dev_ioctl(struct net *net, unsigned int cmd, void __user *);
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 76357b54775..c8436fa3134 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 18b245e2c00..d9242342837 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 d36e700f7a2..99647d8f95c 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 0f4a74bc6a9..c83519b555b 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 ffca5c1066f..ec01a5998d7 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