Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[firefly-linux-kernel-4.4.55.git] / include / net / inet_frag.h
index 0a1dcc2fa2f58c5be1f177f579fa4fa57c138dfd..bfcbc0017950372ddd39dd540ff3f6da99f2bee6 100644 (file)
@@ -41,7 +41,7 @@ struct inet_frag_queue {
        struct netns_frags      *net;
 };
 
-#define INETFRAGS_HASHSZ               64
+#define INETFRAGS_HASHSZ       1024
 
 /* averaged:
  * max_depth = default ipfrag_high_thresh / INETFRAGS_HASHSZ /
@@ -50,10 +50,16 @@ struct inet_frag_queue {
  */
 #define INETFRAGS_MAXDEPTH             128
 
+struct inet_frag_bucket {
+       struct hlist_head       chain;
+       spinlock_t              chain_lock;
+};
+
 struct inet_frags {
-       struct hlist_head       hash[INETFRAGS_HASHSZ];
+       struct inet_frag_bucket hash[INETFRAGS_HASHSZ];
        /* This rwlock is a global lock (seperate per IPv4, IPv6 and
         * netfilter). Important to keep this on a seperate cacheline.
+        * Its primarily a rebuild protection rwlock.
         */
        rwlock_t                lock ____cacheline_aligned_in_smp;
        int                     secret_interval;
@@ -135,14 +141,16 @@ static inline int sum_frag_mem_limit(struct netns_frags *nf)
 static inline void inet_frag_lru_move(struct inet_frag_queue *q)
 {
        spin_lock(&q->net->lru_lock);
-       list_move_tail(&q->lru_list, &q->net->lru_list);
+       if (!list_empty(&q->lru_list))
+               list_move_tail(&q->lru_list, &q->net->lru_list);
        spin_unlock(&q->net->lru_lock);
 }
 
 static inline void inet_frag_lru_del(struct inet_frag_queue *q)
 {
        spin_lock(&q->net->lru_lock);
-       list_del(&q->lru_list);
+       list_del_init(&q->lru_list);
+       q->net->nqueues--;
        spin_unlock(&q->net->lru_lock);
 }
 
@@ -151,6 +159,19 @@ static inline void inet_frag_lru_add(struct netns_frags *nf,
 {
        spin_lock(&nf->lru_lock);
        list_add_tail(&q->lru_list, &nf->lru_list);
+       q->net->nqueues++;
        spin_unlock(&nf->lru_lock);
 }
+
+/* RFC 3168 support :
+ * We want to check ECN values of all fragments, do detect invalid combinations.
+ * In ipq->ecn, we store the OR value of each ip4_frag_ecn() fragment value.
+ */
+#define        IPFRAG_ECN_NOT_ECT      0x01 /* one frag had ECN_NOT_ECT */
+#define        IPFRAG_ECN_ECT_1        0x02 /* one frag had ECN_ECT_1 */
+#define        IPFRAG_ECN_ECT_0        0x04 /* one frag had ECN_ECT_0 */
+#define        IPFRAG_ECN_CE           0x08 /* one frag had ECN_CE */
+
+extern const u8 ip_frag_ecn_table[16];
+
 #endif