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
>
next prev 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 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.