Skip to content

Commit

Permalink
macvlan: add netpoll support
Browse files Browse the repository at this point in the history
Add netpoll support to macvlan devices. Based on the netpoll support in the 802.1q vlan code.

Tested and macvlan could work well with netconsole.

Signed-off-by: Ding Tianhong <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
dingtianhong authored and davem330 committed Jun 2, 2014
1 parent 7d507ac commit 688cea8
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 1 deletion.
66 changes: 65 additions & 1 deletion drivers/net/macvlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <linux/workqueue.h>
#include <net/rtnetlink.h>
#include <net/xfrm.h>
#include <linux/netpoll.h>

#define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE)

Expand Down Expand Up @@ -357,12 +358,26 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
return dev_queue_xmit(skb);
}

static inline netdev_tx_t macvlan_netpoll_send_skb(struct macvlan_dev *vlan, struct sk_buff *skb)
{
#ifdef CONFIG_NET_POLL_CONTROLLER
if (vlan->netpoll)
netpoll_send_skb(vlan->netpoll, skb);
#else
BUG();
#endif
return NETDEV_TX_OK;
}

static netdev_tx_t macvlan_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
unsigned int len = skb->len;
int ret;
const struct macvlan_dev *vlan = netdev_priv(dev);
struct macvlan_dev *vlan = netdev_priv(dev);

if (unlikely(netpoll_tx_running(dev)))
return macvlan_netpoll_send_skb(vlan, skb);

if (vlan->fwd_priv) {
skb->dev = vlan->lowerdev;
Expand Down Expand Up @@ -788,6 +803,50 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev,
return features;
}

#ifdef CONFIG_NET_POLL_CONTROLLER
static void macvlan_dev_poll_controller(struct net_device *dev)
{
return;
}

static int macvlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo)
{
struct macvlan_dev *vlan = netdev_priv(dev);
struct net_device *real_dev = vlan->lowerdev;
struct netpoll *netpoll;
int err = 0;

netpoll = kzalloc(sizeof(*netpoll), GFP_KERNEL);
err = -ENOMEM;
if (!netpoll)
goto out;

err = __netpoll_setup(netpoll, real_dev);
if (err) {
kfree(netpoll);
goto out;
}

vlan->netpoll = netpoll;

out:
return err;
}

static void macvlan_dev_netpoll_cleanup(struct net_device *dev)
{
struct macvlan_dev *vlan = netdev_priv(dev);
struct netpoll *netpoll = vlan->netpoll;

if (!netpoll)
return;

vlan->netpoll = NULL;

__netpoll_free_async(netpoll);
}
#endif /* CONFIG_NET_POLL_CONTROLLER */

static const struct ethtool_ops macvlan_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_settings = macvlan_ethtool_get_settings,
Expand All @@ -813,6 +872,11 @@ static const struct net_device_ops macvlan_netdev_ops = {
.ndo_fdb_del = macvlan_fdb_del,
.ndo_fdb_dump = ndo_dflt_fdb_dump,
.ndo_get_lock_subclass = macvlan_get_nest_level,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = macvlan_dev_poll_controller,
.ndo_netpoll_setup = macvlan_dev_netpoll_setup,
.ndo_netpoll_cleanup = macvlan_dev_netpoll_cleanup,
#endif
};

void macvlan_common_setup(struct net_device *dev)
Expand Down
3 changes: 3 additions & 0 deletions include/linux/if_macvlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ struct macvlan_dev {
netdev_features_t tap_features;
int minor;
int nest_level;
#ifdef CONFIG_NET_POLL_CONTROLLER
struct netpoll *netpoll;
#endif
};

static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
Expand Down

0 comments on commit 688cea8

Please sign in to comment.