X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fvport.c;h=691ab84ba8a15af10c6ee1d172fa0ca0aec14c0c;hb=9dca7bd50a93eeb26fb7e47ddb896de22f782e7b;hp=716a4588384ea859a911d8c9ff28991e6375210a;hpb=f7cf2ff0b63dc76af9358282dcbe81e9433a94ae;p=openvswitch diff --git a/datapath/vport.c b/datapath/vport.c index 716a4588..691ab84b 100644 --- a/datapath/vport.c +++ b/datapath/vport.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "vport.h" @@ -187,30 +188,26 @@ vport_exit(void) * on device type). This function is for userspace callers and assumes no * locks are held. */ -int -vport_add(const struct odp_vport_add __user *uvport_config) +static int +do_vport_add(struct odp_vport_add *vport_config) { - struct odp_vport_add vport_config; struct vport *vport; int err = 0; - if (copy_from_user(&vport_config, uvport_config, sizeof(struct odp_vport_add))) - return -EFAULT; - - vport_config.port_type[VPORT_TYPE_SIZE - 1] = '\0'; - vport_config.devname[IFNAMSIZ - 1] = '\0'; + vport_config->port_type[VPORT_TYPE_SIZE - 1] = '\0'; + vport_config->devname[IFNAMSIZ - 1] = '\0'; rtnl_lock(); - vport = vport_locate(vport_config.devname); + vport = vport_locate(vport_config->devname); if (vport) { err = -EEXIST; goto out; } vport_lock(); - vport = __vport_add(vport_config.devname, vport_config.port_type, - vport_config.config); + vport = __vport_add(vport_config->devname, vport_config->port_type, + vport_config->config); vport_unlock(); if (IS_ERR(vport)) @@ -221,6 +218,35 @@ out: return err; } +int +vport_add(const struct odp_vport_add __user *uvport_config) +{ + struct odp_vport_add vport_config; + + if (copy_from_user(&vport_config, uvport_config, sizeof(struct odp_vport_add))) + return -EFAULT; + + return do_vport_add(&vport_config); +} + +#ifdef CONFIG_COMPAT +int +compat_vport_add(struct compat_odp_vport_add *ucompat) +{ + struct compat_odp_vport_add compat; + struct odp_vport_add vport_config; + + if (copy_from_user(&compat, ucompat, sizeof(struct compat_odp_vport_add))) + return -EFAULT; + + memcpy(vport_config.port_type, compat.port_type, VPORT_TYPE_SIZE); + memcpy(vport_config.devname, compat.devname, IFNAMSIZ); + vport_config.config = compat_ptr(compat.config); + + return do_vport_add(&vport_config); +} +#endif + /** * vport_mod - modify existing vport device (for userspace callers) * @@ -230,28 +256,24 @@ out: * dependent on device type). This function is for userspace callers and * assumes no locks are held. */ -int -vport_mod(const struct odp_vport_mod __user *uvport_config) +static int +do_vport_mod(struct odp_vport_mod *vport_config) { - struct odp_vport_mod vport_config; struct vport *vport; int err; - if (copy_from_user(&vport_config, uvport_config, sizeof(struct odp_vport_mod))) - return -EFAULT; - - vport_config.devname[IFNAMSIZ - 1] = '\0'; + vport_config->devname[IFNAMSIZ - 1] = '\0'; rtnl_lock(); - vport = vport_locate(vport_config.devname); + vport = vport_locate(vport_config->devname); if (!vport) { err = -ENODEV; goto out; } vport_lock(); - err = __vport_mod(vport, vport_config.config); + err = __vport_mod(vport, vport_config->config); vport_unlock(); out: @@ -259,6 +281,34 @@ out: return err; } +int +vport_mod(const struct odp_vport_mod __user *uvport_config) +{ + struct odp_vport_mod vport_config; + + if (copy_from_user(&vport_config, uvport_config, sizeof(struct odp_vport_mod))) + return -EFAULT; + + return do_vport_mod(&vport_config); +} + +#ifdef CONFIG_COMPAT +int +compat_vport_mod(struct compat_odp_vport_mod *ucompat) +{ + struct compat_odp_vport_mod compat; + struct odp_vport_mod vport_config; + + if (copy_from_user(&compat, ucompat, sizeof(struct compat_odp_vport_mod))) + return -EFAULT; + + memcpy(vport_config.devname, compat.devname, IFNAMSIZ); + vport_config.config = compat_ptr(compat.config); + + return do_vport_mod(&vport_config); +} +#endif + /** * vport_del - delete existing vport device (for userspace callers) * @@ -350,9 +400,12 @@ vport_stats_get(struct odp_vport_stats_req __user *ustats_req) goto out; } - if (vport->ops->get_stats) + if (vport->ops->get_stats) { + rcu_read_lock(); err = vport->ops->get_stats(vport, &stats_req.stats); - else if (vport->ops->flags & VPORT_F_GEN_STATS) { + rcu_read_unlock(); + + } else if (vport->ops->flags & VPORT_F_GEN_STATS) { int i; memset(&stats_req.stats, 0, sizeof(struct odp_vport_stats)); @@ -425,7 +478,9 @@ vport_ether_get(struct odp_vport_ether __user *uvport_ether) goto out; } + rcu_read_lock(); memcpy(vport_ether.ether_addr, vport_get_addr(vport), ETH_ALEN); + rcu_read_unlock(); out: vport_unlock(); @@ -582,11 +637,17 @@ vport_locate(const char *name) dump_stack(); } + rcu_read_lock(); + hlist_for_each_entry(vport, node, bucket, hash_node) if (!strcmp(name, vport_get_name(vport))) - return vport; + goto out; - return NULL; + vport = NULL; + +out: + rcu_read_unlock(); + return vport; } static void @@ -1037,10 +1098,9 @@ vport_get_mtu(const struct vport *vport) * @vport: vport that received the packet * @skb: skb that was received * - * Must be called with rcu_read_lock and bottom halves disabled. The packet - * cannot be shared and skb->data should point to the Ethernet header. The - * caller must have already called compute_ip_summed() to initialize the - * checksumming fields. + * Must be called with rcu_read_lock. The packet cannot be shared and + * skb->data should point to the Ethernet header. The caller must have already + * called compute_ip_summed() to initialize the checksumming fields. */ void vport_receive(struct vport *vport, struct sk_buff *skb)