]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - include/linux/skbuff.h
net: preserve IP control block during GSO segmentation
[mirror_ubuntu-bionic-kernel.git] / include / linux / skbuff.h
index 4355129fff91b6f188136af2a499d6100f2e5bfd..11f935c1a090419d6cda938aa925bfa79de3616b 100644 (file)
 #include <linux/in6.h>
 #include <net/flow.h>
 
-/* A. Checksumming of received packets by device.
+/* The interface for checksum offload between the stack and networking drivers
+ * is as follows...
+ *
+ * A. IP checksum related features
+ *
+ * Drivers advertise checksum offload capabilities in the features of a device.
+ * From the stack's point of view these are capabilities offered by the driver,
+ * a driver typically only advertises features that it is capable of offloading
+ * to its device.
+ *
+ * The checksum related features are:
+ *
+ *     NETIF_F_HW_CSUM - The driver (or its device) is able to compute one
+ *                       IP (one's complement) checksum for any combination
+ *                       of protocols or protocol layering. The checksum is
+ *                       computed and set in a packet per the CHECKSUM_PARTIAL
+ *                       interface (see below).
+ *
+ *     NETIF_F_IP_CSUM - Driver (device) is only able to checksum plain
+ *                       TCP or UDP packets over IPv4. These are specifically
+ *                       unencapsulated packets of the form IPv4|TCP or
+ *                       IPv4|UDP where the Protocol field in the IPv4 header
+ *                       is TCP or UDP. The IPv4 header may contain IP options
+ *                       This feature cannot be set in features for a device
+ *                       with NETIF_F_HW_CSUM also set. This feature is being
+ *                       DEPRECATED (see below).
+ *
+ *     NETIF_F_IPV6_CSUM - Driver (device) is only able to checksum plain
+ *                       TCP or UDP packets over IPv6. These are specifically
+ *                       unencapsulated packets of the form IPv6|TCP or
+ *                       IPv4|UDP where the Next Header field in the IPv6
+ *                       header is either TCP or UDP. IPv6 extension headers
+ *                       are not supported with this feature. This feature
+ *                       cannot be set in features for a device with
+ *                       NETIF_F_HW_CSUM also set. This feature is being
+ *                       DEPRECATED (see below).
+ *
+ *     NETIF_F_RXCSUM - Driver (device) performs receive checksum offload.
+ *                      This flag is used only used to disable the RX checksum
+ *                      feature for a device. The stack will accept receive
+ *                      checksum indication in packets received on a device
+ *                      regardless of whether NETIF_F_RXCSUM is set.
+ *
+ * B. Checksumming of received packets by device. Indication of checksum
+ *    verification is in set skb->ip_summed. Possible values are:
  *
  * CHECKSUM_NONE:
  *
- *   Device failed to checksum this packet e.g. due to lack of capabilities.
+ *   Device did not checksum this packet e.g. due to lack of capabilities.
  *   The packet contains full (though not verified) checksum in packet but
  *   not in skb->csum. Thus, skb->csum is undefined in this case.
  *
@@ -53,9 +97,8 @@
  *   (as in CHECKSUM_COMPLETE), but it does parse headers and verify checksums
  *   for specific protocols. For such packets it will set CHECKSUM_UNNECESSARY
  *   if their checksums are okay. skb->csum is still undefined in this case
- *   though. It is a bad option, but, unfortunately, nowadays most vendors do
- *   this. Apparently with the secret goal to sell you new devices, when you
- *   will add new protocol to your host, f.e. IPv6 8)
+ *   though. A driver or device must never modify the checksum field in the
+ *   packet even if checksum is verified.
  *
  *   CHECKSUM_UNNECESSARY is applicable to following protocols:
  *     TCP: IPv6 and IPv4.
  *   packet that are after the checksum being offloaded are not considered to
  *   be verified.
  *
- * B. Checksumming on output.
- *
- * CHECKSUM_NONE:
- *
- *   The skb was already checksummed by the protocol, or a checksum is not
- *   required.
+ * C. Checksumming on transmit for non-GSO. The stack requests checksum offload
+ *    in the skb->ip_summed for a packet. Values are:
  *
  * CHECKSUM_PARTIAL:
  *
- *   The device is required to checksum the packet as seen by hard_start_xmit()
+ *   The driver is required to checksum the packet as seen by hard_start_xmit()
  *   from skb->csum_start up to the end, and to record/write the checksum at
- *   offset skb->csum_start + skb->csum_offset.
+ *   offset skb->csum_start + skb->csum_offset. A driver may verify that the
+ *   csum_start and csum_offset values are valid values given the length and
+ *   offset of the packet, however they should not attempt to validate that the
+ *   checksum refers to a legitimate transport layer checksum-- it is the
+ *   purview of the stack to validate that csum_start and csum_offset are set
+ *   correctly.
+ *
+ *   When the stack requests checksum offload for a packet, the driver MUST
+ *   ensure that the checksum is set correctly. A driver can either offload the
+ *   checksum calculation to the device, or call skb_checksum_help (in the case
+ *   that the device does not support offload for a particular checksum).
+ *
+ *   NETIF_F_IP_CSUM and NETIF_F_IPV6_CSUM are being deprecated in favor of
+ *   NETIF_F_HW_CSUM. New devices should use NETIF_F_HW_CSUM to indicate
+ *   checksum offload capability. If a device has limited checksum capabilities
+ *   (for instance can only perform NETIF_F_IP_CSUM or NETIF_F_IPV6_CSUM as
+ *   described above) a helper function can be called to resolve
+ *   CHECKSUM_PARTIAL. The helper functions are skb_csum_off_chk*. The helper
+ *   function takes a spec argument that describes the protocol layer that is
+ *   supported for checksum offload and can be called for each packet. If a
+ *   packet does not match the specification for offload, skb_checksum_help
+ *   is called to resolve the checksum.
  *
- *   The device must show its capabilities in dev->features, set up at device
- *   setup time, e.g. netdev_features.h:
+ * CHECKSUM_NONE:
  *
- *     NETIF_F_HW_CSUM - It's a clever device, it's able to checksum everything.
- *     NETIF_F_IP_CSUM - Device is dumb, it's able to checksum only TCP/UDP over
- *                       IPv4. Sigh. Vendors like this way for an unknown reason.
- *                       Though, see comment above about CHECKSUM_UNNECESSARY. 8)
- *     NETIF_F_IPV6_CSUM - About as dumb as the last one but does IPv6 instead.
- *     NETIF_F_...     - Well, you get the picture.
+ *   The skb was already checksummed by the protocol, or a checksum is not
+ *   required.
  *
  * CHECKSUM_UNNECESSARY:
  *
- *   Normally, the device will do per protocol specific checksumming. Protocol
- *   implementations that do not want the NIC to perform the checksum
- *   calculation should use this flag in their outgoing skbs.
- *
- *     NETIF_F_FCOE_CRC - This indicates that the device can do FCoE FC CRC
- *                        offload. Correspondingly, the FCoE protocol driver
- *                        stack should use CHECKSUM_UNNECESSARY.
+ *   This has the same meaning on as CHECKSUM_NONE for checksum offload on
+ *   output.
  *
- * Any questions? No questions, good.          --ANK
+ * CHECKSUM_COMPLETE:
+ *   Not used in checksum output. If a driver observes a packet with this value
+ *   set in skbuff, if should treat as CHECKSUM_NONE being set.
+ *
+ * D. Non-IP checksum (CRC) offloads
+ *
+ *   NETIF_F_SCTP_CRC - This feature indicates that a device is capable of
+ *     offloading the SCTP CRC in a packet. To perform this offload the stack
+ *     will set ip_summed to CHECKSUM_PARTIAL and set csum_start and csum_offset
+ *     accordingly. Note the there is no indication in the skbuff that the
+ *     CHECKSUM_PARTIAL refers to an SCTP checksum, a driver that supports
+ *     both IP checksum offload and SCTP CRC offload must verify which offload
+ *     is configured for a packet presumably by inspecting packet headers.
+ *
+ *   NETIF_F_FCOE_CRC - This feature indicates that a device is capable of
+ *     offloading the FCOE CRC in a packet. To perform this offload the stack
+ *     will set ip_summed to CHECKSUM_PARTIAL and set csum_start and csum_offset
+ *     accordingly. Note the there is no indication in the skbuff that the
+ *     CHECKSUM_PARTIAL refers to an FCOE checksum, a driver that supports
+ *     both IP checksum offload and FCOE CRC offload must verify which offload
+ *     is configured for a packet presumably by inspecting packet headers.
+ *
+ * E. Checksumming on output with GSO.
+ *
+ * In the case of a GSO packet (skb_is_gso(skb) is true), checksum offload
+ * is implied by the SKB_GSO_* flags in gso_type. Most obviously, if the
+ * gso_type is SKB_GSO_TCPV4 or SKB_GSO_TCPV6, TCP checksum offload as
+ * part of the GSO operation is implied. If a checksum is being offloaded
+ * with GSO then ip_summed is CHECKSUM_PARTIAL, csum_start and csum_offset
+ * are set to refer to the outermost checksum being offload (two offloaded
+ * checksums are possible with UDP encapsulation).
  */
 
 /* Don't change this without changing skb_csum_unnecessary! */
@@ -833,7 +913,7 @@ struct sk_buff_fclones {
  *     skb_fclone_busy - check if fclone is busy
  *     @skb: buffer
  *
- * Returns true is skb is a fast clone, and its clone is not freed.
+ * Returns true if skb is a fast clone, and its clone is not freed.
  * Some drivers call skb_orphan() in their ndo_start_xmit(),
  * so we also check that this didnt happen.
  */
@@ -1082,9 +1162,6 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
 
 static inline void skb_sender_cpu_clear(struct sk_buff *skb)
 {
-#ifdef CONFIG_XPS
-       skb->sender_cpu = 0;
-#endif
 }
 
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
@@ -1942,6 +2019,11 @@ static inline unsigned char *skb_inner_transport_header(const struct sk_buff
        return skb->head + skb->inner_transport_header;
 }
 
+static inline int skb_inner_transport_offset(const struct sk_buff *skb)
+{
+       return skb_inner_transport_header(skb) - skb->data;
+}
+
 static inline void skb_reset_inner_transport_header(struct sk_buff *skb)
 {
        skb->inner_transport_header = skb->data - skb->head;
@@ -2723,6 +2805,23 @@ static inline void skb_postpull_rcsum(struct sk_buff *skb,
 
 unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len);
 
+static inline void skb_postpush_rcsum(struct sk_buff *skb,
+                                     const void *start, unsigned int len)
+{
+       /* For performing the reverse operation to skb_postpull_rcsum(),
+        * we can instead of ...
+        *
+        *   skb->csum = csum_add(skb->csum, csum_partial(start, len, 0));
+        *
+        * ... just use this equivalent version here to save a few
+        * instructions. Feeding csum of 0 in csum_partial() and later
+        * on adding skb->csum is equivalent to feed skb->csum in the
+        * first place.
+        */
+       if (skb->ip_summed == CHECKSUM_COMPLETE)
+               skb->csum = csum_partial(start, len, skb->csum);
+}
+
 /**
  *     pskb_trim_rcsum - trim received skb and update checksum
  *     @skb: buffer to trim
@@ -2788,6 +2887,12 @@ static inline void skb_frag_list_init(struct sk_buff *skb)
 #define skb_walk_frags(skb, iter)      \
        for (iter = skb_shinfo(skb)->frag_list; iter; iter = iter->next)
 
+
+int __skb_wait_for_more_packets(struct sock *sk, int *err, long *timeo_p,
+                               const struct sk_buff *skb);
+struct sk_buff *__skb_try_recv_datagram(struct sock *sk, unsigned flags,
+                                       int *peeked, int *off, int *err,
+                                       struct sk_buff **last);
 struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
                                    int *peeked, int *off, int *err);
 struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock,
@@ -3446,7 +3551,8 @@ struct skb_gso_cb {
        int     encap_level;
        __u16   csum_start;
 };
-#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)(skb)->cb)
+#define SKB_SGO_CB_OFFSET      32
+#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)((skb)->cb + SKB_SGO_CB_OFFSET))
 
 static inline int skb_tnl_header_len(const struct sk_buff *inner_skb)
 {