X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fbrcompat.c;h=d4a0acad926868011c81a25ad3333b90d9c4a4ef;hb=ef13dc11ad6ec612954bd5b59751cc437f504e65;hp=718e4897804492ec30858774c43d3b934200186b;hpb=6455100f38e9312346f4d58511595f695d813537;p=openvswitch diff --git a/datapath/brcompat.c b/datapath/brcompat.c index 718e4897..d4a0acad 100644 --- a/datapath/brcompat.c +++ b/datapath/brcompat.c @@ -1,13 +1,24 @@ /* - * Copyright (c) 2009, 2011 Nicira Networks. - * Distributed under the terms of the GNU GPL version 2. + * Copyright (c) 2007-2012 Nicira Networks. * - * Significant portions of this file may be copied from parts of the Linux - * kernel, by Linus Torvalds and others. + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -39,9 +50,10 @@ static DECLARE_COMPLETION(brc_done); /* Userspace signaled operation done? */ static struct sk_buff *brc_reply; /* Reply from userspace. */ static u32 brc_seq; /* Sequence number for current op. */ -static struct sk_buff *brc_send_command(struct sk_buff *, +static struct sk_buff *brc_send_command(struct net *, + struct sk_buff *, struct nlattr **attrs); -static int brc_send_simple_command(struct sk_buff *); +static int brc_send_simple_command(struct net *, struct sk_buff *); static struct sk_buff *brc_make_request(int op, const char *bridge, const char *port) @@ -63,13 +75,13 @@ error: return NULL; } -static int brc_send_simple_command(struct sk_buff *request) +static int brc_send_simple_command(struct net *net, struct sk_buff *request) { struct nlattr *attrs[BRC_GENL_A_MAX + 1]; struct sk_buff *reply; int error; - reply = brc_send_command(request, attrs); + reply = brc_send_command(net, request, attrs); if (IS_ERR(reply)) return PTR_ERR(reply); @@ -78,7 +90,7 @@ static int brc_send_simple_command(struct sk_buff *request) return -error; } -static int brc_add_del_bridge(char __user *uname, int add) +static int brc_add_del_bridge(struct net *net, char __user *uname, int add) { struct sk_buff *request; char name[IFNAMSIZ]; @@ -95,10 +107,11 @@ static int brc_add_del_bridge(char __user *uname, int add) if (!request) return -ENOMEM; - return brc_send_simple_command(request); + return brc_send_simple_command(net, request); } -static int brc_get_indices(int op, const char *br_name, +static int brc_get_indices(struct net *net, + int op, const char *br_name, int __user *uindices, int n) { struct nlattr *attrs[BRC_GENL_A_MAX + 1]; @@ -116,7 +129,7 @@ static int brc_get_indices(int op, const char *br_name, if (!request) return -ENOMEM; - reply = brc_send_command(request, attrs); + reply = brc_send_command(net, request, attrs); ret = PTR_ERR(reply); if (IS_ERR(reply)) goto exit; @@ -144,13 +157,13 @@ exit: } /* Called with br_ioctl_mutex. */ -static int brc_get_bridges(int __user *uindices, int n) +static int brc_get_bridges(struct net *net, int __user *uindices, int n) { - return brc_get_indices(BRC_GENL_C_GET_BRIDGES, NULL, uindices, n); + return brc_get_indices(net, BRC_GENL_C_GET_BRIDGES, NULL, uindices, n); } /* Legacy deviceless bridge ioctl's. Called with br_ioctl_mutex. */ -static int old_deviceless(void __user *uarg) +static int old_deviceless(struct net *net, void __user *uarg) { unsigned long args[3]; @@ -159,12 +172,12 @@ static int old_deviceless(void __user *uarg) switch (args[0]) { case BRCTL_GET_BRIDGES: - return brc_get_bridges((int __user *)args[1], args[2]); + return brc_get_bridges(net, (int __user *)args[1], args[2]); case BRCTL_ADD_BRIDGE: - return brc_add_del_bridge((void __user *)args[1], 1); + return brc_add_del_bridge(net, (void __user *)args[1], 1); case BRCTL_DEL_BRIDGE: - return brc_add_del_bridge((void __user *)args[1], 0); + return brc_add_del_bridge(net, (void __user *)args[1], 0); } return -EOPNOTSUPP; @@ -174,19 +187,21 @@ static int old_deviceless(void __user *uarg) static int #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23) brc_ioctl_deviceless_stub(unsigned int cmd, void __user *uarg) +{ + struct net *net = NULL; #else brc_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uarg) -#endif { +#endif switch (cmd) { case SIOCGIFBR: case SIOCSIFBR: - return old_deviceless(uarg); + return old_deviceless(net, uarg); case SIOCBRADDBR: - return brc_add_del_bridge(uarg, 1); + return brc_add_del_bridge(net, uarg, 1); case SIOCBRDELBR: - return brc_add_del_bridge(uarg, 0); + return brc_add_del_bridge(net, uarg, 0); } return -EOPNOTSUPP; @@ -201,7 +216,7 @@ static int brc_add_del_port(struct net_device *dev, int port_ifindex, int add) if (!capable(CAP_NET_ADMIN)) return -EPERM; - port = __dev_get_by_index(&init_net, port_ifindex); + port = __dev_get_by_index(dev_net(dev), port_ifindex); if (!port) return -EINVAL; @@ -213,7 +228,7 @@ static int brc_add_del_port(struct net_device *dev, int port_ifindex, int add) return -ENOMEM; rtnl_unlock(); - err = brc_send_simple_command(request); + err = brc_send_simple_command(dev_net(dev), request); rtnl_lock(); return err; @@ -244,7 +259,7 @@ static int brc_get_port_list(struct net_device *dev, int __user *uindices, int retval; rtnl_unlock(); - retval = brc_get_indices(BRC_GENL_C_GET_PORTS, dev->name, + retval = brc_get_indices(dev_net(dev), BRC_GENL_C_GET_PORTS, dev->name, uindices, num); rtnl_lock(); @@ -277,7 +292,7 @@ static int brc_get_fdb_entries(struct net_device *dev, void __user *userbuf, NLA_PUT_U64(request, BRC_GENL_A_FDB_SKIP, offset); rtnl_unlock(); - reply = brc_send_command(request, attrs); + reply = brc_send_command(dev_net(dev), request, attrs); retval = PTR_ERR(reply); if (IS_ERR(reply)) goto exit; @@ -367,6 +382,7 @@ static struct genl_family brc_genl_family = { .name = BRC_GENL_FAMILY_NAME, .version = 1, .maxattr = BRC_GENL_A_MAX, + SET_NETNSOK }; static int brc_genl_query(struct sk_buff *skb, struct genl_info *info) @@ -445,7 +461,8 @@ static struct genl_ops brc_genl_ops[] = { }, }; -static struct sk_buff *brc_send_command(struct sk_buff *request, +static struct sk_buff *brc_send_command(struct net *net, + struct sk_buff *request, struct nlattr **attrs) { unsigned long int flags; @@ -464,7 +481,8 @@ static struct sk_buff *brc_send_command(struct sk_buff *request, nlmsg_end(request, nlmsg_hdr(request)); /* Send message. */ - error = genlmsg_multicast(request, 0, brc_mc_group.id, GFP_KERNEL); + error = genlmsg_multicast_netns(net, request, 0, + brc_mc_group.id, GFP_KERNEL); if (error < 0) goto error; @@ -506,7 +524,7 @@ static int __init brc_init(void) brioctl_set(brc_ioctl_deviceless_stub); /* Set the openvswitch_mod device ioctl handler */ - dp_ioctl_hook = brc_dev_ioctl; + ovs_dp_ioctl_hook = brc_dev_ioctl; /* Randomize the initial sequence number. This is not a security * feature; it only helps avoid crossed wires between userspace and @@ -537,7 +555,7 @@ error: static void brc_cleanup(void) { /* Unregister ioctl hooks */ - dp_ioctl_hook = NULL; + ovs_dp_ioctl_hook = NULL; brioctl_set(NULL); genl_unregister_family(&brc_genl_family); @@ -549,3 +567,12 @@ module_exit(brc_cleanup); MODULE_DESCRIPTION("Open vSwitch bridge compatibility"); MODULE_AUTHOR("Nicira Networks"); MODULE_LICENSE("GPL"); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) +/* + * In kernels 2.6.36 and later, Open vSwitch can safely coexist with + * the Linux bridge module, but it does not make sense to load both bridge and + * brcompat_mod, so this prevents it. + */ +BRIDGE_MUTUAL_EXCLUSION; +#endif