X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=datapath%2Fdatapath.c;h=c8b50889a4937e9cb6dc64b683f07718dabd4ce0;hb=dab45bfd5748e7d871ae312df6e9b7ce89a8f46c;hp=b41110dbcb3fd978db959f3104a48a7cc972869e;hpb=27bcf966b4057623f7b4d856c0348a1e0eb452e0;p=openvswitch diff --git a/datapath/datapath.c b/datapath/datapath.c index b41110db..c8b50889 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -44,16 +44,17 @@ #include #include "openvswitch/datapath-protocol.h" +#include "checksum.h" #include "datapath.h" #include "actions.h" #include "flow.h" +#include "loop_counter.h" #include "odp-compat.h" #include "table.h" #include "vport-internal_dev.h" #include "compat.h" - int (*dp_ioctl_hook)(struct net_device *dev, struct ifreq *rq, int cmd); EXPORT_SYMBOL(dp_ioctl_hook); @@ -63,30 +64,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); -/* We limit the number of times that we pass into dp_process_received_packet() - * to avoid blowing out the stack in the event that we have a loop. */ -struct loop_counter { - int count; /* Count. */ - bool looping; /* Loop detected? */ -}; - -#define DP_MAX_LOOPS 5 - -/* We use a separate counter for each CPU for both interrupt and non-interrupt - * context in order to keep the limit deterministic for a given packet. */ -struct percpu_loop_counters { - struct loop_counter counters[2]; -}; - -static DEFINE_PER_CPU(struct percpu_loop_counters, dp_loop_counters); - -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) @@ -112,7 +96,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) @@ -127,12 +111,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; @@ -151,21 +135,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); @@ -177,7 +160,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; @@ -269,8 +252,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; @@ -292,7 +275,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: @@ -308,18 +291,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); @@ -351,66 +334,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); - } - - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return -ENOMEM; + parms.name = odp_port->devname; + parms.type = odp_port->type; + parms.config = odp_port->config; + parms.dp = dp; + parms.port_no = port_no; - 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; } @@ -426,6 +373,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); @@ -440,7 +388,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; @@ -457,9 +405,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(); @@ -473,31 +420,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(); + /* Then destroy it. */ + vport_lock(); + err = vport_del(p); + vport_unlock(); - if (may_delete) { - const char *port_type = vport_get_type(vport); - - 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; @@ -516,7 +449,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); @@ -526,16 +459,8 @@ out: return err; } -static void suppress_loop(struct datapath *dp, struct sw_flow_actions *actions) -{ - if (net_ratelimit()) - pr_warn("%s: flow looped %d times, dropping\n", - dp_name(dp), DP_MAX_LOOPS); - actions->n_actions = 0; -} - /* 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; @@ -544,7 +469,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; @@ -581,11 +506,11 @@ void dp_process_received_packet(struct dp_port *p, struct sk_buff *skb) acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts); /* Check whether we've looped too much. */ - loop = &get_cpu_var(dp_loop_counters).counters[!!in_interrupt()]; - if (unlikely(++loop->count > DP_MAX_LOOPS)) + loop = loop_get_counter(); + if (unlikely(++loop->count > MAX_LOOPS)) loop->looping = true; if (unlikely(loop->looping)) { - suppress_loop(dp, acts); + loop_suppress(dp, acts); goto out_loop; } @@ -596,13 +521,13 @@ void dp_process_received_packet(struct dp_port *p, struct sk_buff *skb) /* Check whether sub-actions looped too much. */ if (unlikely(loop->looping)) - suppress_loop(dp, acts); + loop_suppress(dp, acts); out_loop: /* Decrement loop counter. */ if (!--loop->count) loop->looping = false; - put_cpu_var(dp_loop_counters); + loop_put_counter(); out: /* Update datapath statistics. */ @@ -616,171 +541,6 @@ out: local_bh_enable(); } -#if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID) -/* This code is based on skb_checksum_setup() from Xen's net/dev/core.c. We - * can't call this function directly because it isn't exported in all - * versions. */ -int vswitch_skb_checksum_setup(struct sk_buff *skb) -{ - struct iphdr *iph; - unsigned char *th; - int err = -EPROTO; - __u16 csum_start, csum_offset; - - if (!skb->proto_csum_blank) - return 0; - - if (skb->protocol != htons(ETH_P_IP)) - goto out; - - if (!pskb_may_pull(skb, skb_network_header(skb) + sizeof(struct iphdr) - skb->data)) - goto out; - - iph = ip_hdr(skb); - th = skb_network_header(skb) + 4 * iph->ihl; - - csum_start = th - skb->head; - switch (iph->protocol) { - case IPPROTO_TCP: - csum_offset = offsetof(struct tcphdr, check); - break; - case IPPROTO_UDP: - csum_offset = offsetof(struct udphdr, check); - break; - default: - if (net_ratelimit()) - pr_err("Attempting to checksum a non-TCP/UDP packet, " - "dropping a protocol %d packet", - iph->protocol); - goto out; - } - - if (!pskb_may_pull(skb, th + csum_offset + 2 - skb->data)) - goto out; - - skb->ip_summed = CHECKSUM_PARTIAL; - skb->proto_csum_blank = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - skb->csum_start = csum_start; - skb->csum_offset = csum_offset; -#else - skb_set_transport_header(skb, csum_start - skb_headroom(skb)); - skb->csum = csum_offset; -#endif - - err = 0; - -out: - return err; -} -#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 - * (though not verified) checksum in packet but not in skb->csum. Packets - * from the bridge local port will also have this type. - * 2. CHECKSUM_COMPLETE (CHECKSUM_HW): Good device that computes checksums, - * also the GRE module. This is the same as CHECKSUM_NONE, except it has - * a valid skb->csum. Importantly, both contain a full checksum (not - * verified) in the packet itself. The only difference is that if the - * packet gets to L4 processing on this machine (not in DomU) we won't - * have to recompute the checksum to verify. Most hardware devices do not - * produce packets with this type, even if they support receive checksum - * offloading (they produce type #5). - * 3. CHECKSUM_PARTIAL (CHECKSUM_HW): Packet without full checksum and needs to - * be computed if it is sent off box. Unfortunately on earlier kernels, - * this case is impossible to distinguish from #2, despite having opposite - * meanings. Xen adds an extra field on earlier kernels (see #4) in order - * to distinguish the different states. - * 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 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. - * 5. CHECKSUM_UNNECESSARY (with proto_csum_blank false): Packet with a correct - * full checksum or using a protocol without a checksum. skb->csum is - * undefined. This is common from devices with receive checksum - * offloading. This is somewhat similar to CHECKSUM_NONE, except that - * nobody will try to verify the checksum with CHECKSUM_UNNECESSARY. - * - * Note that on earlier kernels, CHECKSUM_COMPLETE and CHECKSUM_PARTIAL are - * both defined as CHECKSUM_HW. Normally the meaning of CHECKSUM_HW is clear - * based on whether it is on the transmit or receive path. After the datapath - * it will be intepreted as CHECKSUM_PARTIAL. If the packet already has a - * checksum, we will panic. Since we can receive packets with checksums, we - * assume that all CHECKSUM_HW packets have checksums and map them to - * CHECKSUM_NONE, which has a similar meaning (the it is only different if the - * packet is processed by the local IP stack, in which case it will need to - * be reverified). If we receive a packet with CHECKSUM_HW that really means - * CHECKSUM_PARTIAL, it will be sent with the wrong checksum. However, there - * shouldn't be any devices that do this with bridging. */ -void compute_ip_summed(struct sk_buff *skb, bool xmit) -{ - /* For our convenience these defines change repeatedly between kernel - * versions, so we can't just copy them over... */ - switch (skb->ip_summed) { - case CHECKSUM_NONE: - OVS_CB(skb)->ip_summed = OVS_CSUM_NONE; - break; - case CHECKSUM_UNNECESSARY: - OVS_CB(skb)->ip_summed = OVS_CSUM_UNNECESSARY; - break; -#ifdef CHECKSUM_HW - /* In theory this could be either CHECKSUM_PARTIAL or CHECKSUM_COMPLETE. - * However, on the receive side 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. - * - * On the transmit side (basically after skb_checksum_setup() - * has been run or on internal dev transmit), packets with - * CHECKSUM_COMPLETE aren't generated, so assume CHECKSUM_PARTIAL. */ - case CHECKSUM_HW: - if (!xmit) - OVS_CB(skb)->ip_summed = OVS_CSUM_COMPLETE; - else - OVS_CB(skb)->ip_summed = OVS_CSUM_PARTIAL; - - break; -#else - case CHECKSUM_COMPLETE: - OVS_CB(skb)->ip_summed = OVS_CSUM_COMPLETE; - break; - case CHECKSUM_PARTIAL: - OVS_CB(skb)->ip_summed = OVS_CSUM_PARTIAL; - break; -#endif - default: - pr_err("unknown checksum type %d\n", skb->ip_summed); - /* None seems the safest... */ - OVS_CB(skb)->ip_summed = OVS_CSUM_NONE; - } - -#if defined(CONFIG_XEN) && defined(HAVE_PROTO_DATA_VALID) - /* Xen has a special way of representing CHECKSUM_PARTIAL on older - * kernels. It should not be set on the transmit path though. */ - if (skb->proto_csum_blank) - OVS_CB(skb)->ip_summed = OVS_CSUM_PARTIAL; - - WARN_ON_ONCE(skb->proto_csum_blank && xmit); -#endif -} - -/* This function closely resembles skb_forward_csum() used by the bridge. 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.*/ -void forward_ip_summed(struct sk_buff *skb) -{ -#ifdef CHECKSUM_HW - if (OVS_CB(skb)->ip_summed == OVS_CSUM_COMPLETE) - skb->ip_summed = CHECKSUM_NONE; -#endif -} - /* Append each packet in 'skb' list to 'queue'. There will be only one packet * unless we broke up a GSO packet. */ static int queue_control_packets(struct sk_buff *skb, struct sk_buff_head *queue, @@ -790,8 +550,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; @@ -1415,7 +1175,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(); @@ -1425,10 +1185,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; } @@ -1440,7 +1200,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(); @@ -1448,23 +1208,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; } @@ -1478,7 +1238,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'; @@ -1491,14 +1250,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(); @@ -1521,7 +1278,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])) @@ -1577,26 +1334,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: @@ -1674,11 +1423,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; @@ -1934,9 +1683,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: @@ -1950,15 +1699,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); @@ -1967,7 +1710,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; @@ -2144,15 +1887,9 @@ success: if (skb->ip_summed == CHECKSUM_PARTIAL) { if (copy_bytes == skb->len) { __wsum csum = 0; - unsigned int csum_start, csum_offset; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - csum_start = skb->csum_start - skb_headroom(skb); - csum_offset = skb->csum_offset; -#else - csum_start = skb_transport_header(skb) - skb->data; - csum_offset = skb->csum; -#endif + u16 csum_start, csum_offset; + + get_skb_csum_pointers(skb, &csum_start, &csum_offset); BUG_ON(csum_start >= skb_headlen(skb)); retval = skb_copy_and_csum_datagram(skb, csum_start, buf + csum_start, copy_bytes - csum_start, &csum);