openvswitch: add support for netpoll
Subsystems (3)
RFC PATCH 1/1 openvswitch: add support for netpoll
This patch simply forwards unicast netpoll packets via one of physical interface in datapath depending on source mac address from the skb.
It seems possible to use common net flow classification for netpoll but there is no way to guarantee presence of right flow in kernel cache.
Signed-off-by Konstantin Khlebnikov <[email protected]>
--- net/openvswitch/vport-internal_dev.c | 74 ++++++++++++++++++++++++++++++++++ net/openvswitch/vport-netdev.c | 63 ++++++++++++++++++++++++++++- net/openvswitch/vport-netdev.h | 15 +++++++ 3 files changed, 148 insertions(+), 4 deletions(-)
net/openvswitch/vport-internal_dev.c +73 -1
@@ -23,6 +23,7 @@#include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/skbuff.h> +#include <linux/netpoll.h> #include <net/dst.h> #include <net/xfrm.h>
@@ -66,11 +67,77 @@ static struct rtnl_link_stats64 *internal_dev_get_stats(struct net_device *netdereturn stats; } +#ifdef CONFIG_NET_POLL_CONTROLLER + +static void internal_dev_poll_controller (struct net_device *dev) +{ +} + +static struct netdev_vport *get_local_netdev_vport (struct net_device *dev) +{ +struct datapath *dp =internal_dev_priv (dev)->vport->dp; + +return netdev_vport_priv (ovs_lookup_vport (dp,OVSP_LOCAL )); +} + +static int internal_dev_netpoll_setup (struct net_device *internal_dev, +struct netpoll_info *info) +{ +struct netdev_vport *local =get_local_netdev_vport (internal_dev); +struct netdev_vport *lower; +struct list_head *iter; +int ret = -EOPNOTSUPP ; + +ASSERT_RTNL (); +/* succeed if at least one lower device can handle netpoll */ +netdev_for_each_lower_private (local->dev, lower, iter) +if (!ovs_netdev_netpoll_enable (lower)) + ret =0 ; +/* enable netpoll on local device as mark for new devices */ +if (!ret && local->dev != internal_dev) +ovs_netdev_netpoll_enable (local); +return ret; +} + +static void internal_dev_netpoll_cleanup (struct net_device *internal_dev) +{ +struct netdev_vport *local =get_local_netdev_vport (internal_dev); +struct netdev_vport *lower; +struct list_head *iter; + +/* FIXME needs reference counting for more than one netpoll in dp */ + +ASSERT_RTNL (); +netdev_for_each_lower_private (local->dev, lower, iter) +ovs_netdev_netpoll_disable (lower); +ovs_netdev_netpoll_disable (local); +} + +static void internal_dev_netpoll_xmit (struct sk_buff *skb, +struct net_device *internal_dev) +{ +struct netdev_vport *local =get_local_netdev_vport (internal_dev); +struct netdev_vport *lower; +struct list_head *iter; + +netdev_for_each_lower_private_rcu (local->dev, lower, iter) +if (!ovs_netdev_netpoll_send (lower, skb)) +return ;/* Unicast only, first gets all. */ +dev_kfree_skb_irq (skb); +} + +#endif /* CONFIG_NET_POLL_CONTROLLER */ +/* Called with rcu_read_lock_bh. */ static int internal_dev_xmit (struct sk_buff *skb,struct net_device *netdev) {rcu_read_lock (); -ovs_vport_receive (internal_dev_priv (netdev)->vport, skb,NULL ); +#ifdef CONFIG_NET_POLL_CONTROLLER +if (unlikely (netpoll_tx_running (netdev))) +internal_dev_netpoll_xmit (skb, netdev); + else +#endif +ovs_vport_receive (internal_dev_priv (netdev)->vport, skb,NULL );rcu_read_unlock ();return 0 ; }
@@ -122,6 +189,11 @@ static const struct net_device_ops internal_dev_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, .ndo_change_mtu = internal_dev_change_mtu, .ndo_get_stats64 = internal_dev_get_stats, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = internal_dev_poll_controller, + .ndo_netpoll_setup = internal_dev_netpoll_setup, + .ndo_netpoll_cleanup = internal_dev_netpoll_cleanup, +#endif }; static struct rtnl_link_ops internal_dev_link_ops __read_mostly = {
net/openvswitch/vport-netdev.c +60 -3
100 lines not on this page · raw message
net/openvswitch/vport-netdev.h +15 -0
@@ -30,6 +30,9 @@ struct netdev_vport {struct rcu_head rcu;struct net_device *dev; +#ifdef CONFIG_NET_POLL_CONTROLLER +struct netpoll *np; +#endif }; static inline struct netdev_vport *
@@ -44,4 +47,16 @@ void ovs_netdev_detach_dev(struct vport *);int __init ovs_netdev_init (void );void ovs_netdev_exit (void ); +#ifdef CONFIG_NET_POLL_CONTROLLER +int ovs_netdev_netpoll_enable (struct netdev_vport *); +void ovs_netdev_netpoll_disable (struct netdev_vport *); +int ovs_netdev_netpoll_send (struct netdev_vport *,struct sk_buff *); +#else +static inline int ovs_netdev_netpoll_enable (struct netdev_vport *nv) +{ +return -EOPNOTSUPP ; +} +static inline void ovs_netdev_netpoll_disable (struct netdev_vport *nv) { } +#endif +#endif /* vport_netdev.h */
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev