netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
To: Vlad Yasevich <vyasevic@redhat.com>
Cc: netdev@vger.kernel.org
Subject: Re: [RFC PATCH bridge 4/5] bridge: Add private ioctls to configure vlans on bridge ports
Date: Fri, 24 Aug 2012 10:56:16 -0700	[thread overview]
Message-ID: <20120824175616.GL2472@linux.vnet.ibm.com> (raw)
In-Reply-To: <1345750195-31598-5-git-send-email-vyasevic@redhat.com>

On Thu, Aug 23, 2012 at 03:29:54PM -0400, Vlad Yasevich wrote:
> Add a private ioctl to add and remove vlan configuration on bridge port.
> 
> Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>

One question below...

> ---
>  include/linux/if_bridge.h |    2 +
>  net/bridge/br_if.c        |   69 +++++++++++++++++++++++++++++++++++++++++++++
>  net/bridge/br_ioctl.c     |   31 ++++++++++++++++++++
>  net/bridge/br_private.h   |    2 +
>  4 files changed, 104 insertions(+), 0 deletions(-)
> 
> diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
> index 288ff10..ab750dd 100644
> --- a/include/linux/if_bridge.h
> +++ b/include/linux/if_bridge.h
> @@ -42,6 +42,8 @@
>  #define BRCTL_SET_PORT_PRIORITY 16
>  #define BRCTL_SET_PATH_COST 17
>  #define BRCTL_GET_FDB_ENTRIES 18
> +#define BRCTL_ADD_VLAN 19
> +#define BRCTL_DEL_VLAN 20
> 
>  #define BR_STATE_DISABLED 0
>  #define BR_STATE_LISTENING 1
> diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
> index e1144e1..90c1038 100644
> --- a/net/bridge/br_if.c
> +++ b/net/bridge/br_if.c
> @@ -23,6 +23,7 @@
>  #include <linux/if_ether.h>
>  #include <linux/slab.h>
>  #include <net/sock.h>
> +#include <linux/if_vlan.h>
> 
>  #include "br_private.h"
> 
> @@ -441,6 +442,74 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
>  	return 0;
>  }
> 
> +/* Called with RTNL */
> +int br_set_port_vlan(struct net_bridge_port *p, unsigned long vlan)
> +{
> +	unsigned long table_size = (VLAN_N_VID/sizeof(unsigned long)) + 1;
> +	unsigned long *vid_map = NULL;
> +	__u16 vid = (__u16) vlan + 1;
> +
> +	/* We are under lock so we can check this without rcu.
> +	 * The vlan map is indexed by vid+1.  This way we can store
> +	 * vid 0 (untagged) into the map as well.
> +	 */
> +	if (!p->vlan_map) {
> +		vid_map = kzalloc(table_size, GFP_KERNEL);
> +		if (!vid_map)
> +			return -ENOMEM;
> +
> +		set_bit(vid, vid_map);
> +		rcu_assign_pointer(p->vlan_map, vid_map);
> +
> +	} else {
> +		/* Map is already allocated */
> +		set_bit(vid, p->vlan_map);
> +	}
> +
> +	return 0;
> +}
> +
> +
> +/* Called with RTNL */
> +int br_del_port_vlan(struct net_bridge_port *p, unsigned long vlan)
> +{
> +	unsigned long first_bit;
> +	unsigned long next_bit;
> +	__u16 vid = (__u16) vlan+1;
> +	unsigned long tbl_len = VLAN_N_VID+1;
> +
> +	if (!p->vlan_map)
> +		return -EINVAL;
> +
> +	if (!test_bit(vlan, p->vlan_map))
> +		return -EINVAL;
> +
> +	/* Check to see if any other vlans are in this table.  If this
> +	 * is the last vlan, delete the whole table.  If this is not the
> +	 * last vlan, just clear the bit.
> +	 */
> +	first_bit = find_first_bit(p->vlan_map, tbl_len);
> +	next_bit = find_next_bit(p->vlan_map, tbl_len, (tbl_len - vid));
> +
> +	if ((__u16)first_bit != vid || (__u16)next_bit < tbl_len) {
> +		/* There are other vlans still configured.  We can simply
> +		 * clear our bit and be safe.
> +		 */
> +		clear_bit(vid, p->vlan_map);
> +	} else {
> +		/* This is the last vlan we are removing.  Replace the
> +		 * map with a NULL pointer and free the old map
> +		 */
> +		unsigned long *map = rcu_dereference(p->vlan_map);
> +
> +		rcu_assign_pointer(p->vlan_map, NULL);
> +		synchronize_net();
> +		kfree(map);
> +	}
> +
> +	return 0;
> +}
> +
>  void __net_exit br_net_exit(struct net *net)
>  {
>  	struct net_device *dev;
> diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
> index 7222fe1..3a5b1f9 100644
> --- a/net/bridge/br_ioctl.c
> +++ b/net/bridge/br_ioctl.c
> @@ -289,6 +289,37 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
>  	case BRCTL_GET_FDB_ENTRIES:
>  		return get_fdb_entries(br, (void __user *)args[1],
>  				       args[2], args[3]);
> +	case BRCTL_ADD_VLAN:
> +	{
> +		struct net_bridge_port *p;
> +
> +		if (!capable(CAP_NET_ADMIN))
> +			return -EPERM;
> +
> +		rcu_read_lock();
> +		if ((p = br_get_port(br, args[1])) == NULL) {
> +			rcu_read_unlock();
> +			return -EINVAL;
> +		}
> +		rcu_read_unlock();

Why is it safe to pass "p" out of the RCU read-side critical section?
I don't see that br_get_port() does anything to make this safe, at least
not in v3.5.

> +		return br_set_port_vlan(p, args[2]);
> +	}
> +
> +	case BRCTL_DEL_VLAN:
> +	{
> +		struct net_bridge_port *p;
> +
> +		if (!capable(CAP_NET_ADMIN))
> +			return -EPERM;
> +
> +		rcu_read_lock();
> +		if ((p = br_get_port(br, args[1])) == NULL) {
> +			rcu_read_unlock();
> +			return -EINVAL;
> +		}
> +		rcu_read_unlock();
> +		br_set_port_vlan(p, args[2]);
> +	}
>  	}
> 
>  	return -EOPNOTSUPP;
> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index b6c56ab..5639c1c 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -402,6 +402,8 @@ extern int br_del_if(struct net_bridge *br,
>  extern int br_min_mtu(const struct net_bridge *br);
>  extern netdev_features_t br_features_recompute(struct net_bridge *br,
>  	netdev_features_t features);
> +extern int br_set_port_vlan(struct net_bridge_port *p, unsigned long vid);
> +extern int br_del_port_vlan(struct net_bridge_port *p, unsigned long vid);
> 
>  /* br_input.c */
>  extern int br_handle_frame_finish(struct sk_buff *skb);
> -- 
> 1.7.7.6
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

  parent reply	other threads:[~2012-08-24 17:56 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-23 19:29 [RFC PATCH bridge 0/5] Add basic VLAN support to bridges Vlad Yasevich
2012-08-23 19:29 ` [RFC PATCH bridge 1/5] bridge: Add vlan check to forwarding path Vlad Yasevich
2012-08-23 20:58   ` Nicolas de Pesloüan
2012-08-30 12:19   ` Michael S. Tsirkin
2012-08-23 19:29 ` [RFC PATCH bridge 2/5] bridge: Add vlan to unicast fdb entries Vlad Yasevich
2012-08-23 19:39   ` Stephen Hemminger
2012-08-23 19:42     ` Vlad Yasevich
2012-08-30 14:33   ` Michael S. Tsirkin
2012-08-30 14:48     ` Vlad Yasevich
2012-08-30 15:45       ` Michael S. Tsirkin
2012-08-30 16:07         ` Vlad Yasevich
2012-08-23 19:29 ` [RFC PATCH bridge 3/5] bridge: Add vlan id to multicast groups Vlad Yasevich
2012-08-30 12:30   ` Michael S. Tsirkin
2012-08-30 12:55   ` Eric Dumazet
2012-08-23 19:29 ` [RFC PATCH bridge 4/5] bridge: Add private ioctls to configure vlans on bridge ports Vlad Yasevich
2012-08-23 19:38   ` Stephen Hemminger
2012-08-23 19:41     ` Vlad Yasevich
2012-08-24 17:56   ` Paul E. McKenney [this message]
2012-08-24 18:11     ` Stephen Hemminger
2012-08-24 18:19     ` Vlad Yasevich
2012-08-30 12:17   ` Michael S. Tsirkin
2012-08-23 19:29 ` [RFC PATCH bridge 5/5] bridge: Add sysfs interface to display VLANS Vlad Yasevich
2012-08-30 12:27   ` Michael S. Tsirkin
2012-08-30 14:05     ` Vlad Yasevich
2012-08-30 14:26       ` Michael S. Tsirkin
2012-08-30 14:36         ` Vlad Yasevich
2012-08-30 14:44           ` Michael S. Tsirkin
2012-08-30 14:51             ` Vlad Yasevich
2012-08-30 15:03               ` Michael S. Tsirkin
2012-08-30 15:07                 ` Vlad Yasevich
2012-08-30 15:47                   ` Michael S. Tsirkin
2012-08-30 15:52                     ` Vlad Yasevich
2012-08-30 15:58                       ` Michael S. Tsirkin
2012-08-23 19:41 ` [RFC PATCH bridge 0/5] Add basic VLAN support to bridges Stephen Hemminger
2012-08-23 19:53   ` Vlad Yasevich
2012-08-23 21:03 ` Nicolas de Pesloüan
2012-08-23 21:12   ` Stephen Hemminger
2012-08-24  2:52   ` Vlad Yasevich
2012-08-24 20:44     ` Stephen Hemminger
2012-08-24 21:09       ` Nicolas de Pesloüan
2012-08-30 12:37 ` Michael S. Tsirkin
2012-08-30 13:37   ` Vlad Yasevich
2012-08-30 14:34     ` Michael S. Tsirkin
2012-08-30 14:41       ` Vlad Yasevich
2012-08-30 14:46         ` Michael S. Tsirkin

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=20120824175616.GL2472@linux.vnet.ibm.com \
    --to=paulmck@linux.vnet.ibm.com \
    --cc=netdev@vger.kernel.org \
    --cc=vyasevic@redhat.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).