+ * 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:
+ printk(KERN_ERR "openvswitch: 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.*/