X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fdatapath.c;h=7b8687d651e74a967fe331ad9e9e9ef7de968267;hb=29b639ed7522594dac03bd10ad477f2f188ce4b6;hp=522d4ec100c71c9329c5cd889ae74537bbeb3f82;hpb=7eaa9830512604ea9f18e8efb306b9bd75a8248b;p=openvswitch diff --git a/datapath/datapath.c b/datapath/datapath.c index 522d4ec1..7b8687d6 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -54,7 +54,6 @@ #include "compat.h" - int (*dp_ioctl_hook)(struct net_device *dev, struct ifreq *rq, int cmd); EXPORT_SYMBOL(dp_ioctl_hook); @@ -64,13 +63,13 @@ EXPORT_SYMBOL(dp_ioctl_hook); * dp_mutex nests inside the RTNL lock: if you need both you must take the RTNL * lock first. * - * It is safe to access the datapath and dp_port structures with just + * It is safe to access the datapath and vport structures with just * dp_mutex. */ static struct datapath *dps[ODP_MAX]; static DEFINE_MUTEX(dp_mutex); -static int new_dp_port(struct datapath *, struct odp_port *, int port_no); +static int new_vport(struct datapath *, struct odp_port *, int port_no); /* Must be called with rcu_read_lock or dp_mutex. */ struct datapath *get_dp(int dp_idx) @@ -96,7 +95,7 @@ static struct datapath *get_dp_locked(int dp_idx) /* Must be called with rcu_read_lock or RTNL lock. */ const char *dp_name(const struct datapath *dp) { - return vport_get_name(dp->ports[ODPP_LOCAL]->vport); + return vport_get_name(dp->ports[ODPP_LOCAL]); } static inline size_t br_nlmsg_size(void) @@ -111,12 +110,12 @@ static inline size_t br_nlmsg_size(void) } static int dp_fill_ifinfo(struct sk_buff *skb, - const struct dp_port *port, + const struct vport *port, int event, unsigned int flags) { const struct datapath *dp = port->dp; - int ifindex = vport_get_ifindex(port->vport); - int iflink = vport_get_iflink(port->vport); + int ifindex = vport_get_ifindex(port); + int iflink = vport_get_iflink(port); struct ifinfomsg *hdr; struct nlmsghdr *nlh; @@ -135,21 +134,20 @@ static int dp_fill_ifinfo(struct sk_buff *skb, hdr->__ifi_pad = 0; hdr->ifi_type = ARPHRD_ETHER; hdr->ifi_index = ifindex; - hdr->ifi_flags = vport_get_flags(port->vport); + hdr->ifi_flags = vport_get_flags(port); hdr->ifi_change = 0; - NLA_PUT_STRING(skb, IFLA_IFNAME, vport_get_name(port->vport)); - NLA_PUT_U32(skb, IFLA_MASTER, vport_get_ifindex(dp->ports[ODPP_LOCAL]->vport)); - NLA_PUT_U32(skb, IFLA_MTU, vport_get_mtu(port->vport)); + NLA_PUT_STRING(skb, IFLA_IFNAME, vport_get_name(port)); + NLA_PUT_U32(skb, IFLA_MASTER, vport_get_ifindex(dp->ports[ODPP_LOCAL])); + NLA_PUT_U32(skb, IFLA_MTU, vport_get_mtu(port)); #ifdef IFLA_OPERSTATE NLA_PUT_U8(skb, IFLA_OPERSTATE, - vport_is_running(port->vport) - ? vport_get_operstate(port->vport) + vport_is_running(port) + ? vport_get_operstate(port) : IF_OPER_DOWN); #endif - NLA_PUT(skb, IFLA_ADDRESS, ETH_ALEN, - vport_get_addr(port->vport)); + NLA_PUT(skb, IFLA_ADDRESS, ETH_ALEN, vport_get_addr(port)); if (ifindex != iflink) NLA_PUT_U32(skb, IFLA_LINK,iflink); @@ -161,7 +159,7 @@ nla_put_failure: return -EMSGSIZE; } -static void dp_ifinfo_notify(int event, struct dp_port *port) +static void dp_ifinfo_notify(int event, struct vport *port) { struct sk_buff *skb; int err = -ENOBUFS; @@ -253,8 +251,8 @@ static int create_dp(int dp_idx, const char __user *devnamep) /* Set up our datapath device. */ BUILD_BUG_ON(sizeof(internal_dev_port.devname) != sizeof(devname)); strcpy(internal_dev_port.devname, devname); - internal_dev_port.flags = ODP_PORT_INTERNAL; - err = new_dp_port(dp, &internal_dev_port, ODPP_LOCAL); + strcpy(internal_dev_port.type, "internal"); + err = new_vport(dp, &internal_dev_port, ODPP_LOCAL); if (err) { if (err == -EBUSY) err = -EEXIST; @@ -276,7 +274,7 @@ static int create_dp(int dp_idx, const char __user *devnamep) return 0; err_destroy_local_port: - dp_detach_port(dp->ports[ODPP_LOCAL], 1); + dp_detach_port(dp->ports[ODPP_LOCAL]); err_destroy_table: tbl_destroy(dp->table, NULL); err_free_dp: @@ -292,18 +290,18 @@ err: static void do_destroy_dp(struct datapath *dp) { - struct dp_port *p, *n; + struct vport *p, *n; int i; list_for_each_entry_safe (p, n, &dp->port_list, node) if (p->port_no != ODPP_LOCAL) - dp_detach_port(p, 1); + dp_detach_port(p); dp_sysfs_del_dp(dp); rcu_assign_pointer(dps[dp->dp_idx], NULL); - dp_detach_port(dp->ports[ODPP_LOCAL], 1); + dp_detach_port(dp->ports[ODPP_LOCAL]); tbl_destroy(dp->table, flow_free_tbl); @@ -335,66 +333,30 @@ err_unlock: return err; } -static void release_dp_port(struct kobject *kobj) -{ - struct dp_port *p = container_of(kobj, struct dp_port, kobj); - kfree(p); -} - -static struct kobj_type brport_ktype = { -#ifdef CONFIG_SYSFS - .sysfs_ops = &brport_sysfs_ops, -#endif - .release = release_dp_port -}; - /* Called with RTNL lock and dp_mutex. */ -static int new_dp_port(struct datapath *dp, struct odp_port *odp_port, int port_no) +static int new_vport(struct datapath *dp, struct odp_port *odp_port, int port_no) { + struct vport_parms parms; struct vport *vport; - struct dp_port *p; - int err; - - vport = vport_locate(odp_port->devname); - if (!vport) { - vport_lock(); - if (odp_port->flags & ODP_PORT_INTERNAL) - vport = vport_add(odp_port->devname, "internal", NULL); - else - vport = vport_add(odp_port->devname, "netdev", NULL); - - vport_unlock(); - - if (IS_ERR(vport)) - return PTR_ERR(vport); - } + parms.name = odp_port->devname; + parms.type = odp_port->type; + parms.config = odp_port->config; + parms.dp = dp; + parms.port_no = port_no; - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return -ENOMEM; - - p->port_no = port_no; - p->dp = dp; - p->vport = vport; - atomic_set(&p->sflow_pool, 0); + vport_lock(); + vport = vport_add(&parms); + vport_unlock(); - err = vport_attach(vport, p); - if (err) { - kfree(p); - return err; - } + if (IS_ERR(vport)) + return PTR_ERR(vport); - rcu_assign_pointer(dp->ports[port_no], p); - list_add_rcu(&p->node, &dp->port_list); + rcu_assign_pointer(dp->ports[port_no], vport); + list_add_rcu(&vport->node, &dp->port_list); dp->n_ports++; - /* Initialize kobject for bridge. This will be added as - * /sys/class/net//brport later, if sysfs is enabled. */ - p->kobj.kset = NULL; - kobject_init(&p->kobj, &brport_ktype); - - dp_ifinfo_notify(RTM_NEWLINK, p); + dp_ifinfo_notify(RTM_NEWLINK, vport); return 0; } @@ -410,6 +372,7 @@ static int attach_port(int dp_idx, struct odp_port __user *portp) if (copy_from_user(&port, portp, sizeof port)) goto out; port.devname[IFNAMSIZ - 1] = '\0'; + port.type[VPORT_TYPE_SIZE - 1] = '\0'; rtnl_lock(); dp = get_dp_locked(dp_idx); @@ -424,7 +387,7 @@ static int attach_port(int dp_idx, struct odp_port __user *portp) goto out_unlock_dp; got_port_no: - err = new_dp_port(dp, &port, port_no); + err = new_vport(dp, &port, port_no); if (err) goto out_unlock_dp; @@ -441,9 +404,8 @@ out: return err; } -int dp_detach_port(struct dp_port *p, int may_delete) +int dp_detach_port(struct vport *p) { - struct vport *vport = p->vport; int err; ASSERT_RTNL(); @@ -457,31 +419,17 @@ int dp_detach_port(struct dp_port *p, int may_delete) list_del_rcu(&p->node); rcu_assign_pointer(p->dp->ports[p->port_no], NULL); - err = vport_detach(vport); - if (err) - return err; - - /* Then wait until no one is still using it, and destroy it. */ - synchronize_rcu(); - - if (may_delete) { - const char *port_type = vport_get_type(vport); + /* Then destroy it. */ + vport_lock(); + err = vport_del(p); + vport_unlock(); - if (!strcmp(port_type, "netdev") || !strcmp(port_type, "internal")) { - vport_lock(); - vport_del(vport); - vport_unlock(); - } - } - - kobject_put(&p->kobj); - - return 0; + return err; } static int detach_port(int dp_idx, int port_no) { - struct dp_port *p; + struct vport *p; struct datapath *dp; int err; @@ -500,7 +448,7 @@ static int detach_port(int dp_idx, int port_no) if (!p) goto out_unlock_dp; - err = dp_detach_port(p, 1); + err = dp_detach_port(p); out_unlock_dp: mutex_unlock(&dp->mutex); @@ -511,7 +459,7 @@ out: } /* Must be called with rcu_read_lock. */ -void dp_process_received_packet(struct dp_port *p, struct sk_buff *skb) +void dp_process_received_packet(struct vport *p, struct sk_buff *skb) { struct datapath *dp = p->dp; struct dp_stats_percpu *stats; @@ -520,7 +468,7 @@ void dp_process_received_packet(struct dp_port *p, struct sk_buff *skb) struct loop_counter *loop; int error; - OVS_CB(skb)->dp_port = p; + OVS_CB(skb)->vport = p; if (!OVS_CB(skb)->flow) { struct odp_flow_key key; @@ -766,8 +714,8 @@ static int queue_control_packets(struct sk_buff *skb, struct sk_buff_head *queue int port_no; int err; - if (OVS_CB(skb)->dp_port) - port_no = OVS_CB(skb)->dp_port->port_no; + if (OVS_CB(skb)->vport) + port_no = OVS_CB(skb)->vport->port_no; else port_no = ODPP_LOCAL; @@ -1391,7 +1339,7 @@ static int get_dp_stats(struct datapath *dp, struct odp_stats __user *statsp) /* MTU of the dp pseudo-device: ETH_DATA_LEN or the minimum of the ports */ int dp_min_mtu(const struct datapath *dp) { - struct dp_port *p; + struct vport *p; int mtu = 0; ASSERT_RTNL(); @@ -1401,10 +1349,10 @@ int dp_min_mtu(const struct datapath *dp) /* Skip any internal ports, since that's what we're trying to * set. */ - if (is_internal_vport(p->vport)) + if (is_internal_vport(p)) continue; - dev_mtu = vport_get_mtu(p->vport); + dev_mtu = vport_get_mtu(p); if (!mtu || dev_mtu < mtu) mtu = dev_mtu; } @@ -1416,7 +1364,7 @@ int dp_min_mtu(const struct datapath *dp) * be called with RTNL lock. */ void set_internal_devs_mtu(const struct datapath *dp) { - struct dp_port *p; + struct vport *p; int mtu; ASSERT_RTNL(); @@ -1424,23 +1372,23 @@ void set_internal_devs_mtu(const struct datapath *dp) mtu = dp_min_mtu(dp); list_for_each_entry_rcu (p, &dp->port_list, node) { - if (is_internal_vport(p->vport)) - vport_set_mtu(p->vport, mtu); + if (is_internal_vport(p)) + vport_set_mtu(p, mtu); } } -static int put_port(const struct dp_port *p, struct odp_port __user *uop) +static int put_port(const struct vport *p, struct odp_port __user *uop) { struct odp_port op; memset(&op, 0, sizeof op); rcu_read_lock(); - strncpy(op.devname, vport_get_name(p->vport), sizeof op.devname); + strncpy(op.devname, vport_get_name(p), sizeof op.devname); + strncpy(op.type, vport_get_type(p), sizeof op.type); rcu_read_unlock(); op.port = p->port_no; - op.flags = is_internal_vport(p->vport) ? ODP_PORT_INTERNAL : 0; return copy_to_user(uop, &op, sizeof op) ? -EFAULT : 0; } @@ -1454,7 +1402,6 @@ static int query_port(struct datapath *dp, struct odp_port __user *uport) if (port.devname[0]) { struct vport *vport; - struct dp_port *dp_port; int err = 0; port.devname[IFNAMSIZ - 1] = '\0'; @@ -1467,14 +1414,12 @@ static int query_port(struct datapath *dp, struct odp_port __user *uport) err = -ENODEV; goto error_unlock; } - - dp_port = vport_get_dp_port(vport); - if (!dp_port || dp_port->dp != dp) { + if (vport->dp != dp) { err = -ENOENT; goto error_unlock; } - port.port = dp_port->port_no; + port.port = vport->port_no; error_unlock: rcu_read_unlock(); @@ -1497,7 +1442,7 @@ static int do_list_ports(struct datapath *dp, struct odp_port __user *uports, { int idx = 0; if (n_ports) { - struct dp_port *p; + struct vport *p; list_for_each_entry_rcu (p, &dp->port_list, node) { if (put_port(p, &uports[idx])) @@ -1553,26 +1498,18 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd, err = destroy_dp(dp_idx); goto exit; - case ODP_PORT_ATTACH: + case ODP_VPORT_ATTACH: err = attach_port(dp_idx, (struct odp_port __user *)argp); goto exit; - case ODP_PORT_DETACH: + case ODP_VPORT_DETACH: err = get_user(port_no, (int __user *)argp); if (!err) err = detach_port(dp_idx, port_no); goto exit; - case ODP_VPORT_ADD: - err = vport_user_add((struct odp_vport_add __user *)argp); - goto exit; - case ODP_VPORT_MOD: - err = vport_user_mod((struct odp_vport_mod __user *)argp); - goto exit; - - case ODP_VPORT_DEL: - err = vport_user_del((char __user *)argp); + err = vport_user_mod((struct odp_port __user *)argp); goto exit; case ODP_VPORT_STATS_GET: @@ -1650,11 +1587,11 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd, dp->sflow_probability = sflow_probability; break; - case ODP_PORT_QUERY: + case ODP_VPORT_QUERY: err = query_port(dp, (struct odp_port __user *)argp); break; - case ODP_PORT_LIST: + case ODP_VPORT_LIST: err = list_ports(dp, (struct odp_portvec __user *)argp); break; @@ -1910,9 +1847,9 @@ static long openvswitch_compat_ioctl(struct file *f, unsigned int cmd, unsigned return openvswitch_ioctl(f, cmd, argp); case ODP_DP_CREATE: - case ODP_PORT_ATTACH: - case ODP_PORT_DETACH: - case ODP_VPORT_DEL: + case ODP_VPORT_ATTACH: + case ODP_VPORT_DETACH: + case ODP_VPORT_MOD: case ODP_VPORT_MTU_SET: case ODP_VPORT_MTU_GET: case ODP_VPORT_ETHER_SET: @@ -1926,15 +1863,9 @@ static long openvswitch_compat_ioctl(struct file *f, unsigned int cmd, unsigned case ODP_GET_LISTEN_MASK: case ODP_SET_SFLOW_PROBABILITY: case ODP_GET_SFLOW_PROBABILITY: - case ODP_PORT_QUERY: + case ODP_VPORT_QUERY: /* Ioctls that just need their pointer argument extended. */ return openvswitch_ioctl(f, cmd, (unsigned long)compat_ptr(argp)); - - case ODP_VPORT_ADD32: - return compat_vport_user_add(compat_ptr(argp)); - - case ODP_VPORT_MOD32: - return compat_vport_user_mod(compat_ptr(argp)); } dp = get_dp_locked(dp_idx); @@ -1943,7 +1874,7 @@ static long openvswitch_compat_ioctl(struct file *f, unsigned int cmd, unsigned goto exit; switch (cmd) { - case ODP_PORT_LIST32: + case ODP_VPORT_LIST32: err = compat_list_ports(dp, compat_ptr(argp)); break;