X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fdatapath.c;h=1b5f57f8b2d67d19e2d8b01b7d7e673bd7d79445;hb=30746a1b6a9758a58d6f9a7a85830512aa0e114f;hp=b0dbe7fc23604b449a992e067278b3713fc2a2b3;hpb=a393b897f27405592dc56f7084796c8bf1815519;p=openvswitch diff --git a/datapath/datapath.c b/datapath/datapath.c index b0dbe7fc..1b5f57f8 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -165,7 +165,8 @@ static void dp_ifinfo_notify(int event, struct net_bridge_port *port) kfree_skb(skb); goto errout; } - err = rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); + rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); + return; errout: if (err < 0) rtnl_set_sk_err(net, RTNLGRP_LINK, err); @@ -235,7 +236,7 @@ static int create_dp(int dp_idx, const char __user *devnamep) if (!dp->table) goto err_free_dp; - /* Setup our datapath device */ + /* Set up our datapath device. */ dp_dev = dp_dev_create(dp, devname, ODPP_LOCAL); err = PTR_ERR(dp_dev); if (IS_ERR(dp_dev)) @@ -783,7 +784,8 @@ static int validate_actions(const struct sw_flow_actions *actions) break; case ODPAT_SET_VLAN_PCP: - if (a->vlan_pcp.vlan_pcp & ~VLAN_PCP_MASK) + if (a->vlan_pcp.vlan_pcp + & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT)) return -EINVAL; break; @@ -976,13 +978,18 @@ static int put_actions(const struct sw_flow *flow, struct odp_flow __user *ufp) return 0; } -static int answer_query(struct sw_flow *flow, struct odp_flow __user *ufp) +static int answer_query(struct sw_flow *flow, u32 query_flags, + struct odp_flow __user *ufp) { struct odp_flow_stats stats; unsigned long int flags; spin_lock_irqsave(&flow->lock, flags); get_stats(flow, &stats); + + if (query_flags & ODPFF_ZERO_TCP_FLAGS) { + flow->tcp_flags = 0; + } spin_unlock_irqrestore(&flow->lock, flags); if (__copy_to_user(&ufp->stats, &stats, sizeof(struct odp_flow_stats))) @@ -1020,10 +1027,10 @@ static int del_or_query_flow(struct datapath *dp, * to make sure that we get completely accurate stats, but that * blows our performance, badly. */ dp->n_flows--; - error = answer_query(flow, ufp); + error = answer_query(flow, 0, ufp); flow_deferred_free(flow); } else { - error = answer_query(flow, ufp); + error = answer_query(flow, uf.flags, ufp); } error: @@ -1049,7 +1056,7 @@ static int query_multiple_flows(struct datapath *dp, if (!flow) error = __clear_user(&ufp->stats, sizeof ufp->stats); else - error = answer_query(flow, ufp); + error = answer_query(flow, 0, ufp); if (error) return -EFAULT; } @@ -1070,7 +1077,7 @@ static int list_flow(struct sw_flow *flow, void *cbdata_) if (__copy_to_user(&ufp->key, &flow->key, sizeof flow->key)) return -EFAULT; - error = answer_query(flow, ufp); + error = answer_query(flow, 0, ufp); if (error) return error; @@ -1381,6 +1388,16 @@ get_port_group(struct datapath *dp, struct odp_port_group *upg) return 0; } +static int get_listen_mask(const struct file *f) +{ + return (long)f->private_data; +} + +static void set_listen_mask(struct file *f, int listen_mask) +{ + f->private_data = (void*)(long)listen_mask; +} + static long openvswitch_ioctl(struct file *f, unsigned int cmd, unsigned long argp) { @@ -1432,7 +1449,7 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd, break; case ODP_GET_LISTEN_MASK: - err = put_user((int)f->private_data, (int __user *)argp); + err = put_user(get_listen_mask(f), (int __user *)argp); break; case ODP_SET_LISTEN_MASK: @@ -1443,7 +1460,7 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd, if (listeners & ~ODPL_ALL) break; err = 0; - f->private_data = (void*)listeners; + set_listen_mask(f, listeners); break; case ODP_PORT_QUERY: @@ -1510,7 +1527,7 @@ ssize_t openvswitch_read(struct file *f, char __user *buf, size_t nbytes, loff_t *ppos) { /* XXX is there sufficient synchronization here? */ - int listeners = (int) f->private_data; + int listeners = get_listen_mask(f); int dp_idx = iminor(f->f_dentry->d_inode); struct datapath *dp = get_dp(dp_idx); struct sk_buff *skb; @@ -1550,7 +1567,7 @@ ssize_t openvswitch_read(struct file *f, char __user *buf, size_t nbytes, } } success: - copy_bytes = min(skb->len, nbytes); + copy_bytes = min_t(size_t, skb->len, nbytes); iov.iov_base = buf; iov.iov_len = copy_bytes; retval = skb_copy_datagram_iovec(skb, 0, &iov, iov.iov_len); @@ -1572,7 +1589,7 @@ static unsigned int openvswitch_poll(struct file *file, poll_table *wait) if (dp) { mask = 0; poll_wait(file, &dp->waitqueue, wait); - if (dp_has_packet_of_interest(dp, (int)file->private_data)) + if (dp_has_packet_of_interest(dp, get_listen_mask(file))) mask |= POLLIN | POLLRDNORM; } else { mask = POLLIN | POLLRDNORM | POLLHUP;