X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fdatapath.c;h=b6aefe892156fb3cbc887bd3d897c78140574bb4;hb=90887925206f585db65ae8872f197a97543f2860;hp=116fd989cd51688a83225e9203fef47c3eee71ce;hpb=a778696338b85b86b31b9ec7d1a4daeda430aa8b;p=openvswitch diff --git a/datapath/datapath.c b/datapath/datapath.c index 116fd989..b6aefe89 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -71,6 +71,7 @@ static DEFINE_MUTEX(dp_mutex); #define MAINT_SLEEP_MSECS 1000 static int new_nbp(struct datapath *, struct net_device *, int port_no); +static void compute_ip_summed(struct sk_buff *skb); /* Must be called with rcu_read_lock or dp_mutex. */ struct datapath *get_dp(int dp_idx) @@ -81,7 +82,7 @@ struct datapath *get_dp(int dp_idx) } EXPORT_SYMBOL_GPL(get_dp); -struct datapath *get_dp_locked(int dp_idx) +static struct datapath *get_dp_locked(int dp_idx) { struct datapath *dp; @@ -176,7 +177,7 @@ static void release_dp(struct kobject *kobj) kfree(dp); } -struct kobj_type dp_ktype = { +static struct kobj_type dp_ktype = { .release = release_dp }; @@ -325,7 +326,7 @@ static void release_nbp(struct kobject *kobj) kfree(p); } -struct kobj_type brport_ktype = { +static struct kobj_type brport_ktype = { #ifdef CONFIG_SYSFS .sysfs_ops = &brport_sysfs_ops, #endif @@ -349,6 +350,7 @@ static int new_nbp(struct datapath *dp, struct net_device *dev, int port_no) p->port_no = port_no; p->dp = dp; p->dev = dev; + atomic_set(&p->sflow_pool, 0); if (!is_dp_dev(dev)) rcu_assign_pointer(dev->br_port, p); else { @@ -422,7 +424,7 @@ got_port_no: set_dp_devs_mtu(dp, dev); dp_sysfs_add_if(dp->ports[port_no]); - err = __put_user(port_no, &port.port); + err = __put_user(port_no, &portp->port); out_put: dev_put(dev); @@ -528,6 +530,8 @@ void dp_process_received_packet(struct sk_buff *skb, struct net_bridge_port *p) WARN_ON_ONCE(skb_shared(skb)); + compute_ip_summed(skb); + /* BHs are off so we don't have to use get_cpu()/put_cpu() here. */ stats = percpu_ptr(dp->stats_percpu, smp_processor_id()); @@ -605,7 +609,7 @@ int vswitch_skb_checksum_setup(struct sk_buff *skb) if (skb->protocol != htons(ETH_P_IP)) goto out; - if (!skb_pull_up_to(skb, skb_network_header(skb) + 1)) + if (!skb_pull_up_to(skb, skb_network_header(skb) + sizeof(struct iphdr))) goto out; iph = ip_hdr(skb); @@ -646,9 +650,7 @@ int vswitch_skb_checksum_setup(struct sk_buff *skb) out: return err; } -#else -int vswitch_skb_checksum_setup(struct sk_buff *skb) { return 0; } -#endif /* CONFIG_XEN && linux == 2.6.18 */ +#endif /* CONFIG_XEN && HAVE_PROTO_DATA_VALID */ /* Types of checksums that we can receive (these all refer to L4 checksums): * 1. CHECKSUM_NONE: Device that did not compute checksum, contains full @@ -671,7 +673,7 @@ int vswitch_skb_checksum_setup(struct sk_buff *skb) { return 0; } * 4. CHECKSUM_UNNECESSARY (with proto_csum_blank true): This packet was * generated locally by a Xen DomU and has a partial checksum. If it is * handled on this machine (Dom0 or DomU), then the checksum will not be - * computed. If it goes off box, the checksum in the packet needs to + * computed. If it goes off box, the checksum in the packet needs to be * completed. Calling skb_checksum_setup converts this to CHECKSUM_HW * (CHECKSUM_PARTIAL) so that the checksum can be completed. In later * kernels, this combination is replaced with CHECKSUM_PARTIAL. @@ -697,11 +699,33 @@ int vswitch_skb_checksum_setup(struct sk_buff *skb) { return 0; } * skb_forward_csum(). It is slightly different because we are only concerned * with bridging and not other types of forwarding and can get away with * slightly more optimal behavior.*/ +static void +compute_ip_summed(struct sk_buff *skb) +{ + OVS_CB(skb)->ip_summed = skb->ip_summed; + +#ifdef CHECKSUM_HW + /* In theory this could be either CHECKSUM_PARTIAL or CHECKSUM_COMPLETE. + * However, we should only get CHECKSUM_PARTIAL packets from Xen, which + * uses some special fields to represent this (see below). Since we + * can only make one type work, pick the one that actually happens in + * practice. */ + if (skb->ip_summed == CHECKSUM_HW) + OVS_CB(skb)->ip_summed = CSUM_COMPLETE; +#endif +#if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID) + /* Xen has a special way of representing CHECKSUM_PARTIAL on older + * kernels. */ + if (skb->proto_csum_blank) + OVS_CB(skb)->ip_summed = CSUM_PARTIAL; +#endif +} + void forward_ip_summed(struct sk_buff *skb) { #ifdef CHECKSUM_HW - if (skb->ip_summed == CHECKSUM_HW) + if (OVS_CB(skb)->ip_summed == CSUM_COMPLETE) skb->ip_summed = CHECKSUM_NONE; #endif } @@ -796,8 +820,7 @@ dp_output_control(struct datapath *dp, struct sk_buff *skb, int queue_no, int err; WARN_ON_ONCE(skb_shared(skb)); - BUG_ON(queue_no != _ODPL_MISS_NR && queue_no != _ODPL_ACTION_NR); - + BUG_ON(queue_no != _ODPL_MISS_NR && queue_no != _ODPL_ACTION_NR && queue_no != _ODPL_SFLOW_NR); queue = &dp->queues[queue_no]; err = -ENOBUFS; if (skb_queue_len(queue) >= DP_MAX_QUEUE_LEN) @@ -942,7 +965,7 @@ static int put_flow(struct datapath *dp, struct odp_flow_put __user *ufp) error = -EFAULT; if (copy_from_user(&uf, ufp, sizeof(struct odp_flow_put))) goto error; - uf.flow.key.reserved = 0; + memset(uf.flow.key.reserved, 0, sizeof uf.flow.key.reserved); table = rcu_dereference(dp->table); flow = dp_table_lookup(table, &uf.flow.key); @@ -1087,7 +1110,7 @@ static int del_flow(struct datapath *dp, struct odp_flow __user *ufp) error = -EFAULT; if (copy_from_user(&uf, ufp, sizeof uf)) goto error; - uf.key.reserved = 0; + memset(uf.key.reserved, 0, sizeof uf.key.reserved); flow = dp_table_lookup(table, &uf.key); error = -ENOENT; @@ -1123,7 +1146,7 @@ static int query_flows(struct datapath *dp, const struct odp_flowvec *flowvec) if (__copy_from_user(&uf, ufp, sizeof uf)) return -EFAULT; - uf.key.reserved = 0; + memset(uf.key.reserved, 0, sizeof uf.key.reserved); flow = dp_table_lookup(table, &uf.key); if (!flow) @@ -1499,6 +1522,7 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd, int dp_idx = iminor(f->f_dentry->d_inode); struct datapath *dp; int drop_frags, listeners, port_no; + unsigned int sflow_probability; int err; /* Handle commands with special locking requirements up front. */ @@ -1562,6 +1586,16 @@ static long openvswitch_ioctl(struct file *f, unsigned int cmd, set_listen_mask(f, listeners); break; + case ODP_GET_SFLOW_PROBABILITY: + err = put_user(dp->sflow_probability, (unsigned int __user *)argp); + break; + + case ODP_SET_SFLOW_PROBABILITY: + err = get_user(sflow_probability, (unsigned int __user *)argp); + if (!err) + dp->sflow_probability = sflow_probability; + break; + case ODP_PORT_QUERY: err = query_port(dp, (struct odp_port __user *)argp); break;