]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - include/linux/netdevice.h
udp: Set SKB_GSO_UDP_TUNNEL* in UDP GRO path
[mirror_ubuntu-artful-kernel.git] / include / linux / netdevice.h
index ce784d5018e07dab38807313fa4666e6b7cc4223..9e9be221e4bfde6532ac1c0f15ac5d32a52e5912 100644 (file)
@@ -644,39 +644,40 @@ struct rps_dev_flow_table {
 /*
  * The rps_sock_flow_table contains mappings of flows to the last CPU
  * on which they were processed by the application (set in recvmsg).
+ * Each entry is a 32bit value. Upper part is the high order bits
+ * of flow hash, lower part is cpu number.
+ * rps_cpu_mask is used to partition the space, depending on number of
+ * possible cpus : rps_cpu_mask = roundup_pow_of_two(nr_cpu_ids) - 1
+ * For example, if 64 cpus are possible, rps_cpu_mask = 0x3f,
+ * meaning we use 32-6=26 bits for the hash.
  */
 struct rps_sock_flow_table {
-       unsigned int mask;
-       u16 ents[0];
+       u32     mask;
+
+       u32     ents[0] ____cacheline_aligned_in_smp;
 };
-#define        RPS_SOCK_FLOW_TABLE_SIZE(_num) (sizeof(struct rps_sock_flow_table) + \
-    ((_num) * sizeof(u16)))
+#define        RPS_SOCK_FLOW_TABLE_SIZE(_num) (offsetof(struct rps_sock_flow_table, ents[_num]))
 
 #define RPS_NO_CPU 0xffff
 
+extern u32 rps_cpu_mask;
+extern struct rps_sock_flow_table __rcu *rps_sock_flow_table;
+
 static inline void rps_record_sock_flow(struct rps_sock_flow_table *table,
                                        u32 hash)
 {
        if (table && hash) {
-               unsigned int cpu, index = hash & table->mask;
+               unsigned int index = hash & table->mask;
+               u32 val = hash & ~rps_cpu_mask;
 
                /* We only give a hint, preemption can change cpu under us */
-               cpu = raw_smp_processor_id();
+               val |= raw_smp_processor_id();
 
-               if (table->ents[index] != cpu)
-                       table->ents[index] = cpu;
+               if (table->ents[index] != val)
+                       table->ents[index] = val;
        }
 }
 
-static inline void rps_reset_sock_flow(struct rps_sock_flow_table *table,
-                                      u32 hash)
-{
-       if (table && hash)
-               table->ents[hash & table->mask] = RPS_NO_CPU;
-}
-
-extern struct rps_sock_flow_table __rcu *rps_sock_flow_table;
-
 #ifdef CONFIG_RFS_ACCEL
 bool rps_may_expire_flow(struct net_device *dev, u16 rxq_index, u32 flow_id,
                         u16 filter_id);
@@ -2245,7 +2246,9 @@ static inline bool __skb_gro_checksum_validate_needed(struct sk_buff *skb,
                                                      bool zero_okay,
                                                      __sum16 check)
 {
-       return (skb->ip_summed != CHECKSUM_PARTIAL &&
+       return ((skb->ip_summed != CHECKSUM_PARTIAL ||
+               skb_checksum_start_offset(skb) <
+                skb_gro_offset(skb)) &&
                NAPI_GRO_CB(skb)->csum_cnt == 0 &&
                (!zero_okay || check));
 }
@@ -2320,8 +2323,19 @@ do {                                                                     \
                                           compute_pseudo(skb, proto)); \
 } while (0)
 
+struct gro_remcsum {
+       int offset;
+       __wsum delta;
+};
+
+static inline void skb_gro_remcsum_init(struct gro_remcsum *grc)
+{
+       grc->delta = 0;
+}
+
 static inline void skb_gro_remcsum_process(struct sk_buff *skb, void *ptr,
-                                          int start, int offset)
+                                          int start, int offset,
+                                          struct gro_remcsum *grc)
 {
        __wsum delta;
 
@@ -2330,10 +2344,20 @@ static inline void skb_gro_remcsum_process(struct sk_buff *skb, void *ptr,
        delta = remcsum_adjust(ptr, NAPI_GRO_CB(skb)->csum, start, offset);
 
        /* Adjust skb->csum since we changed the packet */
-       skb->csum = csum_add(skb->csum, delta);
        NAPI_GRO_CB(skb)->csum = csum_add(NAPI_GRO_CB(skb)->csum, delta);
+
+       grc->offset = (ptr + offset) - (void *)skb->head;
+       grc->delta = delta;
 }
 
+static inline void skb_gro_remcsum_cleanup(struct sk_buff *skb,
+                                          struct gro_remcsum *grc)
+{
+       if (!grc->delta)
+               return;
+
+       remcsum_unadjust((__sum16 *)(skb->head + grc->offset), grc->delta);
+}
 
 static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev,
                                  unsigned short type,