X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fdatapath.c;h=aea8cc95c8bd8ac0f2a36f6143a319655ee29e51;hb=cdd35cff225bf39767ea9e2e535cf2940b0e5127;hp=14602152cb80b9f8ff57a4fc47f8b65fb86c6b39;hpb=6fa58f7a1533b96d8c958581ed18e0e5a245157b;p=openvswitch diff --git a/datapath/datapath.c b/datapath/datapath.c index 14602152..aea8cc95 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); @@ -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; @@ -1127,6 +1129,7 @@ static int do_execute(struct datapath *dp, const struct odp_execute *executep) struct odp_flow_key key; struct sk_buff *skb; struct sw_flow_actions *actions; + struct ethhdr *eth; int err; err = -EFAULT; @@ -1166,6 +1169,17 @@ static int do_execute(struct datapath *dp, const struct odp_execute *executep) execute.length)) goto error_free_skb; + skb_reset_mac_header(skb); + eth = eth_hdr(skb); + + /* Normally, setting the skb 'protocol' field would be handled by a + * call to eth_type_trans(), but it assumes there's a sending + * device, which we may not have. */ + if (ntohs(eth->h_proto) >= 1536) + skb->protocol = eth->h_proto; + else + skb->protocol = htons(ETH_P_802_2); + flow_extract(skb, execute.in_port, &key); err = execute_actions(dp, skb, &key, actions->actions, actions->n_actions, GFP_KERNEL); @@ -1369,6 +1383,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) { @@ -1420,7 +1444,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: @@ -1431,7 +1455,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: @@ -1498,7 +1522,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; @@ -1538,7 +1562,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); @@ -1560,7 +1584,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;