]> xenbits.xensource.com Git - people/ssmith/netchannel2-pvops.git/commitdiff
Fix up checksum offload for the newer interfaces. master netchannel2-forklift
authorSteven Smith <ssmith@weybridge.uk.xensource.com>
Wed, 20 May 2009 12:40:07 +0000 (13:40 +0100)
committerSteven Smith <ssmith@weybridge.uk.xensource.com>
Wed, 20 May 2009 12:40:07 +0000 (13:40 +0100)
drivers/net/xen-netchannel2/chan.c
drivers/net/xen-netchannel2/offload.c
drivers/net/xen-netchannel2/posted_buffers.c
drivers/net/xen-netchannel2/receiver_map.c
drivers/net/xen-netchannel2/recv_packet.c
drivers/net/xen-netchannel2/rscb.c
drivers/net/xen-netchannel2/xmit_packet.c
include/xen/interface/io/netchannel2.h

index c4a222701e555596ff4e27bb2498e3869d046ffd..8cce1778a446de44e6767b324bbaf195e8f9f973 100644 (file)
@@ -860,7 +860,7 @@ void nc2_detach_rings(struct netchannel2 *nc)
         /* XXX De-pend the interfaces */
 
         /* Disable all offloads */
         /* XXX De-pend the interfaces */
 
         /* Disable all offloads */
-        nc->net_device->features &= ~NETIF_F_IP_CSUM;
+        nc->net_device->features &= ~NETIF_F_HW_CSUM;
         nc->allow_tx_csum_offload = 0;
 }
 
         nc->allow_tx_csum_offload = 0;
 }
 
index 6c86fa4712b4ac0fbe0d97e4fabb72ea10cd27e0..3a86087d6dd62e9ecae789bbe2ef848a39dc7c4d 100644 (file)
@@ -26,6 +26,10 @@ void nc2_handle_set_offload(struct netchannel2 *nc,
         nc2_copy_from_ring(&nc->rings.cons_ring, &msg, hdr->size);
         if (msg.csum != nc->allow_tx_csum_offload) {
                 nc->allow_tx_csum_offload = msg.csum;
         nc2_copy_from_ring(&nc->rings.cons_ring, &msg, hdr->size);
         if (msg.csum != nc->allow_tx_csum_offload) {
                 nc->allow_tx_csum_offload = msg.csum;
+                if (msg.csum)
+                        nc->net_device->features |= NETIF_F_HW_CSUM;
+                else
+                        nc->net_device->features &= ~NETIF_F_HW_CSUM;
                 nc2_set_tx_csum(nc->net_device, msg.csum);
                 /* Linux doesn't support scatter-gather mode without
                    TX csum offload.  We therefore need to disable SG
                 nc2_set_tx_csum(nc->net_device, msg.csum);
                 /* Linux doesn't support scatter-gather mode without
                    TX csum offload.  We therefore need to disable SG
index 035181da000cc10c56e49a32c3961fc3e10969bf..47a6fdf155d2d5d4e2679a1a77ae145d783796ba 100644 (file)
@@ -171,6 +171,8 @@ struct sk_buff *handle_pre_posted_packet(struct netchannel2 *nc,
         is_bad = 0;
         if (msg->prefix_size < SKB_MIN_PAYLOAD_SIZE)
                 prefix_len = SKB_MIN_PAYLOAD_SIZE;
         is_bad = 0;
         if (msg->prefix_size < SKB_MIN_PAYLOAD_SIZE)
                 prefix_len = SKB_MIN_PAYLOAD_SIZE;
+        else if (msg->prefix_size < msg->csum_offset + 2)
+                prefix_len = msg->csum_offset + 2;
         else
                 prefix_len = msg->prefix_size;
         /* We don't enforce the MAX_PACKET_BYTES limit here.  That's
         else
                 prefix_len = msg->prefix_size;
         /* We don't enforce the MAX_PACKET_BYTES limit here.  That's
@@ -247,9 +249,9 @@ struct sk_buff *handle_pre_posted_packet(struct netchannel2 *nc,
                 head_skb->len = cur_skb->len + acc_len;
                 head_skb->data_len = cur_skb->data_len + acc_len;
                 head_skb->truesize = cur_skb->truesize + acc_len;
                 head_skb->len = cur_skb->len + acc_len;
                 head_skb->data_len = cur_skb->data_len + acc_len;
                 head_skb->truesize = cur_skb->truesize + acc_len;
-                if (skb_headlen(head_skb) < SKB_MIN_PAYLOAD_SIZE)
+                if (skb_headlen(head_skb) < prefix_len)
                         pull_through(head_skb,
                         pull_through(head_skb,
-                                     SKB_MIN_PAYLOAD_SIZE - skb_headlen(head_skb));
+                                     prefix_len - skb_headlen(head_skb));
         }
 
         return head_skb;
         }
 
         return head_skb;
index eab13b71eab6307a22481e2650130795eca6353f..4d0637710b80bf8f5385c4c967a08055999cd842 100644 (file)
@@ -655,6 +655,8 @@ struct sk_buff *handle_receiver_map_packet(struct netchannel2 *nc,
 
         if (msg->prefix_size < SKB_MIN_PAYLOAD_SIZE)
                 prefix_size = SKB_MIN_PAYLOAD_SIZE;
 
         if (msg->prefix_size < SKB_MIN_PAYLOAD_SIZE)
                 prefix_size = SKB_MIN_PAYLOAD_SIZE;
+        else if (msg->prefix_size < msg->csum_offset + 2)
+                prefix_size = msg->csum_offset + 2;
         else
                 prefix_size = msg->prefix_size;
         /* As in posted_buffers.c, we don't limit the total size of
         else
                 prefix_size = msg->prefix_size;
         /* As in posted_buffers.c, we don't limit the total size of
@@ -736,9 +738,8 @@ struct sk_buff *handle_receiver_map_packet(struct netchannel2 *nc,
         }
         spin_unlock(&receive_mapper->rm_lock);
 
         }
         spin_unlock(&receive_mapper->rm_lock);
 
-        if (skb_headlen(head_skb) < SKB_MIN_PAYLOAD_SIZE)
-                pull_through(head_skb,
-                             SKB_MIN_PAYLOAD_SIZE - skb_headlen(head_skb));
+        if (skb_headlen(head_skb) < prefix_size)
+                pull_through(head_skb, prefix_size - skb_headlen(head_skb));
 
         return head_skb;
 
 
         return head_skb;
 
index 430ed6ff8168a88b7811354205bce1301bd23d15..0504d0381625e01920eb8ccb2065ccbec04b3d0c 100644 (file)
@@ -198,6 +198,20 @@ void nc2_handle_packet_msg(struct netchannel2 *nc,
                         break;
                 default:
                         skb->ip_summed = CHECKSUM_PARTIAL;
                         break;
                 default:
                         skb->ip_summed = CHECKSUM_PARTIAL;
+                        if (msg.csum_offset + 2 > skb_headlen(skb)) {
+                                /* Whoops.  Assuming no bugs in our
+                                   receive methods, the other end just
+                                   requested checksum calculation
+                                   beyond the end of the packet. */
+                                if (net_ratelimit())
+                                        dev_warn(&nc->net_device->dev,
+                                                 "csum field too far through packet (%d, skb len %d, headlen %d)\n",
+                                                 msg.csum_offset, skb->len,
+                                                 skb_headlen(skb));
+                                goto err;
+                        }
+                        skb->csum_start = msg.csum_start + skb_headroom(skb);
+                        skb->csum_offset = msg.csum_offset - msg.csum_start;
                         break;
                 }
 #endif
                         break;
                 }
 #endif
index 52ae3b475566f250ee58e997c15906bcbb73374d..3be2a6e082f68686d7efcb6fbf78c7c143129ae7 100644 (file)
@@ -207,7 +207,10 @@ struct sk_buff *handle_receiver_copy_packet(struct netchannel2 *nc,
         skb_headsize = nr_bytes + NET_IP_ALIGN;
         if (skb_headsize >
             ((PAGE_SIZE - sizeof(struct skb_shared_info) - NET_SKB_PAD) & ~(SMP_CACHE_BYTES))) {
         skb_headsize = nr_bytes + NET_IP_ALIGN;
         if (skb_headsize >
             ((PAGE_SIZE - sizeof(struct skb_shared_info) - NET_SKB_PAD) & ~(SMP_CACHE_BYTES))) {
-                skb_headsize = msg->prefix_size + NET_IP_ALIGN;
+                if (msg->prefix_size < msg->csum_offset + 2)
+                        skb_headsize = msg->csum_offset + 2;
+                else
+                        skb_headsize = msg->prefix_size + NET_IP_ALIGN;
         }
 
         skb = dev_alloc_skb(skb_headsize);
         }
 
         skb = dev_alloc_skb(skb_headsize);
index 7da3bf05fe270785a8d9f579dfaece2f45856ec3..48c6c5e93de299f0b666a8d5e8e61ac3535e04b4 100644 (file)
@@ -108,10 +108,14 @@ static void set_offload_flags(struct sk_buff *skb,
                               volatile struct netchannel2_msg_packet *msg)
 {
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20)
                               volatile struct netchannel2_msg_packet *msg)
 {
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20)
-        if (skb->ip_summed == CHECKSUM_PARTIAL)
-                msg->flags |=
-                        NC2_PACKET_FLAG_csum_blank |
-                        NC2_PACKET_FLAG_data_validated;
+        if (skb->ip_summed == CHECKSUM_PARTIAL) {
+                msg->flags |= NC2_PACKET_FLAG_data_validated |
+                        NC2_PACKET_FLAG_csum_blank;
+                msg->csum_start = skb->csum_start - skb_headroom(skb);
+                msg->csum_offset = skb->csum_offset + msg->csum_start;
+        }
+        if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+                msg->flags |= NC2_PACKET_FLAG_data_validated;
 #else
         if (skb->ip_summed == CHECKSUM_HW)
                 msg->flags |=
 #else
         if (skb->ip_summed == CHECKSUM_HW)
                 msg->flags |=
index f746b29dd562bcc981dbbfe7d12d96e4a6306577..1b181b8b4978f0d7687fc4ee45e25271ab898c05 100644 (file)
@@ -61,13 +61,33 @@ struct netchannel2_msg_packet {
         uint8_t pad;
         uint16_t prefix_size;
         uint16_t mss;
         uint8_t pad;
         uint16_t prefix_size;
         uint16_t mss;
+        uint16_t csum_start;
+        uint16_t csum_offset;
         /* Variable-size array.  The number of elements is determined
            by the size of the message. */
         struct netchannel2_fragment frags[0];
 };
         /* Variable-size array.  The number of elements is determined
            by the size of the message. */
         struct netchannel2_fragment frags[0];
 };
+
+/* TX csum offload.  The transmitting domain has skipped a checksum
+ * calculation.  Before forwarding the packet on, the receiving domain
+ * must first perform a 16 bit IP checksum on everything from
+ * csum_start to the end of the packet, and then write the result to
+ * an offset csum_offset in the packet.
+ */
 #define NC2_PACKET_FLAG_csum_blank 1
 #define NC2_PACKET_FLAG_csum_blank 1
+/* RX csum offload.  The transmitting domain has already validated the
+ * protocol-level checksum on this packet (i.e. TCP or UDP), so the
+ * receiving domain shouldn't bother.  This does not tell you anything
+ * about the IP-level checksum. */
 #define NC2_PACKET_FLAG_data_validated 2
 #define NC2_PACKET_FLAG_data_validated 2
+/* If set, this flag indicates that this packet could have used a
+ * bypass if one had been available, and so it should be sent to the
+ * autobypass state machine.
+ */
 #define NC2_PACKET_FLAG_bypass_candidate 4
 #define NC2_PACKET_FLAG_bypass_candidate 4
+/* If set, the transmitting domain requires an event urgently when
+ * this packet's finish message is sent.  Otherwise, the event can be
+ * delayed. */
 #define NC2_PACKET_FLAG_need_event 8
 
 /* The mechanism which should be used to receive the data part of
 #define NC2_PACKET_FLAG_need_event 8
 
 /* The mechanism which should be used to receive the data part of