]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - include/linux/netfilter/x_tables.h
netfilter: x_tables: align per cpu xt_counter
[karo-tx-linux.git] / include / linux / netfilter / x_tables.h
index a3e215bb0241d47379bce4ff6e81ba2b4995d3c3..1c97a2204379e14676ee33f0b15c5174b7afe680 100644 (file)
@@ -62,6 +62,7 @@ struct xt_mtchk_param {
        void *matchinfo;
        unsigned int hook_mask;
        u_int8_t family;
+       bool nft_compat;
 };
 
 /**
@@ -92,6 +93,7 @@ struct xt_tgchk_param {
        void *targinfo;
        unsigned int hook_mask;
        u_int8_t family;
+       bool nft_compat;
 };
 
 /* Target destructor parameters */
@@ -222,13 +224,10 @@ struct xt_table_info {
        unsigned int stacksize;
        unsigned int __percpu *stackptr;
        void ***jumpstack;
-       /* ipt_entry tables: one per CPU */
-       /* Note : this field MUST be the last one, see XT_TABLE_INFO_SZ */
-       void *entries[1];
+
+       unsigned char entries[0] __aligned(8);
 };
 
-#define XT_TABLE_INFO_SZ (offsetof(struct xt_table_info, entries) \
-                         + nr_cpu_ids * sizeof(char *))
 int xt_register_target(struct xt_target *target);
 void xt_unregister_target(struct xt_target *target);
 int xt_register_targets(struct xt_target *target, unsigned int n);
@@ -351,6 +350,57 @@ static inline unsigned long ifname_compare_aligned(const char *_a,
        return ret;
 }
 
+
+/* On SMP, ip(6)t_entry->counters.pcnt holds address of the
+ * real (percpu) counter.  On !SMP, its just the packet count,
+ * so nothing needs to be done there.
+ *
+ * xt_percpu_counter_alloc returns the address of the percpu
+ * counter, or 0 on !SMP. We force an alignment of 16 bytes
+ * so that bytes/packets share a common cache line.
+ *
+ * Hence caller must use IS_ERR_VALUE to check for error, this
+ * allows us to return 0 for single core systems without forcing
+ * callers to deal with SMP vs. NONSMP issues.
+ */
+static inline u64 xt_percpu_counter_alloc(void)
+{
+       if (nr_cpu_ids > 1) {
+               void __percpu *res = __alloc_percpu(sizeof(struct xt_counters),
+                                                   sizeof(struct xt_counters));
+
+               if (res == NULL)
+                       return (u64) -ENOMEM;
+
+               return (__force u64) res;
+       }
+
+       return 0;
+}
+static inline void xt_percpu_counter_free(u64 pcnt)
+{
+       if (nr_cpu_ids > 1)
+               free_percpu((void __percpu *) pcnt);
+}
+
+static inline struct xt_counters *
+xt_get_this_cpu_counter(struct xt_counters *cnt)
+{
+       if (nr_cpu_ids > 1)
+               return this_cpu_ptr((void __percpu *) cnt->pcnt);
+
+       return cnt;
+}
+
+static inline struct xt_counters *
+xt_get_per_cpu_counter(struct xt_counters *cnt, unsigned int cpu)
+{
+       if (nr_cpu_ids > 1)
+               return per_cpu_ptr((void __percpu *) cnt->pcnt, cpu);
+
+       return cnt;
+}
+
 struct nf_hook_ops *xt_hook_link(const struct xt_table *, nf_hookfn *);
 void xt_hook_unlink(const struct xt_table *, struct nf_hook_ops *);