All of lore.kernel.org
 help / color / mirror / Atom feed
From: Patrick McHardy <kaber@trash.net>
To: Jiri Pirko <jpirko@redhat.com>
Cc: netdev@vger.kernel.org, davem@davemloft.net,
	shemminger@vyatta.com, eric.dumazet@gmail.com
Subject: Re: [PATCH net-next-2.6] net: replace hooks in __netif_receive_skb
Date: Thu, 27 May 2010 16:06:54 +0200	[thread overview]
Message-ID: <4BFE7C7E.8090803@trash.net> (raw)
In-Reply-To: <20100527134935.GA6916@psychotron.lab.eng.brq.redhat.com>

Jiri Pirko wrote:
> @@ -511,10 +512,16 @@ static void macvlan_setup(struct net_device *dev)
>  	dev->tx_queue_len	= 0;
>  }
>  
> +static struct netdev_rx_handler macvlan_rx_handler = {
> +	.order		= NETDEV_RX_HANDLER_ORDER_MACVLAN,
> +	.callback	= macvlan_handle_frame,
> +};

It seems this could be const since you duplicate it on
registration.

> +
>  static int macvlan_port_create(struct net_device *dev)
>  {
>  	struct macvlan_port *port;
>  	unsigned int i;
> +	int err;
>  
>  	if (dev->type != ARPHRD_ETHER || dev->flags & IFF_LOOPBACK)
>  		return -EINVAL;
> @@ -528,6 +535,15 @@ static int macvlan_port_create(struct net_device *dev)
>  	for (i = 0; i < MACVLAN_HASH_SIZE; i++)
>  		INIT_HLIST_HEAD(&port->vlan_hash[i]);
>  	rcu_assign_pointer(dev->macvlan_port, port);
> +
> +	err = netdev_rx_handler_register(dev, &macvlan_rx_handler);
> +	if (err) {
> +		rcu_assign_pointer(dev->macvlan_port, NULL);
> +		synchronize_rcu();
> +		kfree(port);
> +		return err;
> +	}

I'd prefer goto-based unroll since that makes changes in the
future easier.

> +
>  	return 0;
>  }
>  
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index a1bff65..8e95b2d 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -254,6 +254,15 @@ struct netdev_hw_addr_list {
>  #define netdev_for_each_mc_addr(ha, dev) \
>  	netdev_hw_addr_list_for_each(ha, &(dev)->mc)
>  
> +
> +struct netdev_rx_handler {
> +	struct list_head	list;
> +	unsigned int		order;
> +#define NETDEV_RX_HANDLER_ORDER_BRIDGE	1
> +#define NETDEV_RX_HANDLER_ORDER_MACVLAN	2

Any reason for not using an enum?

> +	struct sk_buff		*(*callback)(struct sk_buff *skb);
> +};
> +
>  struct hh_cache {
>  	struct hh_cache *hh_next;	/* Next entry			     */
>  	atomic_t	hh_refcnt;	/* number of users                   */
> @@ -1031,6 +1040,10 @@ struct net_device {
>  	/* GARP */
>  	struct garp_port	*garp_port;
>  
> +	/* receive handlers (hooks) list */
> +	spinlock_t		rx_handlers_lock;
> +	struct list_head	rx_handlers;
> +
>  	/* class/net/name entry */
>  	struct device		dev;
>  	/* space for optional device, statistics, and wireless sysfs groups */
> diff --git a/net/core/dev.c b/net/core/dev.c
> index 6c82065..8d4a817 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -2744,6 +2688,82 @@ void netif_nit_deliver(struct sk_buff *skb)
>  	rcu_read_unlock();
>  }
>  
> +static bool rx_handlers_equal(struct netdev_rx_handler *rh1,
> +			      struct netdev_rx_handler *rh2)
> +{
> +	return (rh1->order == rh2->order) && (rh1->callback == rh2->callback);
> +}
> +
> +/**
> + *	netdev_rx_handler_register - register receive handler
> + *	@dev: device to register a handler for
> + *	@rh: receive handler to register
> + *
> + *	Register a receive hander for a device. This handler will then be
> + *	called from __netif_receive_skb. A negative errno code is returned
> + *	on a failure.
> + */
> +int netdev_rx_handler_register(struct net_device *dev,
> +			       struct netdev_rx_handler *rh)
> +{
> +	struct list_head *list, *add_after;
> +	struct netdev_rx_handler *rh1;
> +	int err = 0;
> +
> +	spin_lock_bh(&dev->rx_handlers_lock);

Why are you using a spin lock and even disable BHs? This function
should only be called from user context, so a mutex will work fine
(and would fix the use of GFP_KERNEL in an atomic section).

> +	add_after = &dev->rx_handlers;
> +	list_for_each(list, &dev->rx_handlers) {

Naming the element "list" is confusing. Also this should be
using list_for_each_entry().

> +		rh1 = list_entry(list, struct netdev_rx_handler, list);
> +		if (rx_handlers_equal(rh, rh1)) {
> +			err = -EEXIST;
> +			goto unlock;
> +		}
> +		if (rh1->order > rh->order)
> +			break;
> +		add_after = list;
> +	}
> +	rh1 = kzalloc(sizeof(*rh), GFP_KERNEL);
> +	if (!rh1) {
> +		err = -ENOMEM;
> +		goto unlock;
> +	}
> +
> +	rh1->order = rh->order;
> +	rh1->callback = rh->callback;
> +	list_add_rcu(&rh1->list, add_after);
> +
> +unlock:
> +	spin_unlock_bh(&dev->rx_handlers_lock);
> +
> +	return err;
> +}
> +EXPORT_SYMBOL(netdev_rx_handler_register);

  reply	other threads:[~2010-05-27 14:06 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-05-27 13:49 [PATCH net-next-2.6] net: replace hooks in __netif_receive_skb Jiri Pirko
2010-05-27 14:06 ` Patrick McHardy [this message]
2010-05-27 14:57   ` Jiri Pirko
2010-05-27 14:17 ` Eric Dumazet
2010-05-27 15:02   ` Jiri Pirko
2010-05-27 14:47 ` Stephen Hemminger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4BFE7C7E.8090803@trash.net \
    --to=kaber@trash.net \
    --cc=davem@davemloft.net \
    --cc=eric.dumazet@gmail.com \
    --cc=jpirko@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=shemminger@vyatta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.