+ 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. The only real user of this type
+ * with bridging is Xen (on later kernels).
+ * 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.
+ *
+ * The bridge has similar behavior and this function closely resembles
+ * 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.*/
+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, 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.
+ *
+ * The one exception to this is if we are on the transmit path
+ * (basically after skb_checksum_setup() has been run) the type has
+ * already been converted, so we should stay with that. */
+ 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
+}
+
+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,
+ int queue_no, u32 arg)
+{
+ struct sk_buff *nskb;
+ int port_no;
+ int err;
+
+ port_no = ODPP_LOCAL;
+ if (skb->dev) {
+ if (skb->dev->br_port)
+ port_no = skb->dev->br_port->port_no;
+ else if (is_dp_dev(skb->dev))
+ port_no = dp_dev_priv(skb->dev)->port_no;
+ }
+
+ do {
+ struct odp_msg *header;
+
+ nskb = skb->next;
+ skb->next = NULL;
+
+ /* If a checksum-deferred packet is forwarded to the
+ * controller, correct the pointers and checksum. This happens
+ * on a regular basis only on Xen, on which VMs can pass up
+ * packets that do not have their checksum computed.
+ */
+ err = vswitch_skb_checksum_setup(skb);
+ if (err)
+ goto err_kfree_skbs;
+#ifndef CHECKSUM_HW
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+ /* Until 2.6.22, the start of the transport header was
+ * also the start of data to be checksummed. Linux
+ * 2.6.22 introduced the csum_start field for this
+ * purpose, but we should point the transport header to
+ * it anyway for backward compatibility, as
+ * dev_queue_xmit() does even in 2.6.28. */
+ skb_set_transport_header(skb, skb->csum_start -
+ skb_headroom(skb));
+#endif
+ err = skb_checksum_help(skb);
+ if (err)
+ goto err_kfree_skbs;
+ }
+#else
+ if (skb->ip_summed == CHECKSUM_HW) {
+ err = skb_checksum_help(skb, 0);
+ if (err)
+ goto err_kfree_skbs;
+ }
+#endif
+
+ err = skb_cow(skb, sizeof *header);
+ if (err)
+ goto err_kfree_skbs;
+
+ header = (struct odp_msg*)__skb_push(skb, sizeof *header);
+ header->type = queue_no;
+ header->length = skb->len;
+ header->port = port_no;
+ header->reserved = 0;
+ header->arg = arg;
+ skb_queue_tail(queue, skb);
+
+ skb = nskb;
+ } while (skb);
+ return 0;
+
+err_kfree_skbs:
+ kfree_skb(skb);
+ while ((skb = nskb) != NULL) {
+ nskb = skb->next;
+ kfree_skb(skb);
+ }
+ return err;