Commit b8dfe498775de912116f275680ddb57c8799d9ef
Committed by
Patrick McHardy
1 parent
78f3648601
Exists in
master
and in
7 other branches
netfilter: factorize ifname_compare()
We use same not trivial helper function in four places. We can factorize it. Signed-off-by: Eric Dumazet <dada1@cosmosbay.com> Signed-off-by: Patrick McHardy <kaber@trash.net>
Showing 5 changed files with 30 additions and 74 deletions Side-by-side Diff
include/linux/netfilter/x_tables.h
... | ... | @@ -435,6 +435,29 @@ |
435 | 435 | extern void xt_table_entry_swap_rcu(struct xt_table_info *old, |
436 | 436 | struct xt_table_info *new); |
437 | 437 | |
438 | +/* | |
439 | + * This helper is performance critical and must be inlined | |
440 | + */ | |
441 | +static inline unsigned long ifname_compare_aligned(const char *_a, | |
442 | + const char *_b, | |
443 | + const char *_mask) | |
444 | +{ | |
445 | + const unsigned long *a = (const unsigned long *)_a; | |
446 | + const unsigned long *b = (const unsigned long *)_b; | |
447 | + const unsigned long *mask = (const unsigned long *)_mask; | |
448 | + unsigned long ret; | |
449 | + | |
450 | + ret = (a[0] ^ b[0]) & mask[0]; | |
451 | + if (IFNAMSIZ > sizeof(unsigned long)) | |
452 | + ret |= (a[1] ^ b[1]) & mask[1]; | |
453 | + if (IFNAMSIZ > 2 * sizeof(unsigned long)) | |
454 | + ret |= (a[2] ^ b[2]) & mask[2]; | |
455 | + if (IFNAMSIZ > 3 * sizeof(unsigned long)) | |
456 | + ret |= (a[3] ^ b[3]) & mask[3]; | |
457 | + BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); | |
458 | + return ret; | |
459 | +} | |
460 | + | |
438 | 461 | #ifdef CONFIG_COMPAT |
439 | 462 | #include <net/compat.h> |
440 | 463 |
net/ipv4/netfilter/arp_tables.c
... | ... | @@ -80,19 +80,7 @@ |
80 | 80 | static unsigned long ifname_compare(const char *_a, const char *_b, const char *_mask) |
81 | 81 | { |
82 | 82 | #ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS |
83 | - const unsigned long *a = (const unsigned long *)_a; | |
84 | - const unsigned long *b = (const unsigned long *)_b; | |
85 | - const unsigned long *mask = (const unsigned long *)_mask; | |
86 | - unsigned long ret; | |
87 | - | |
88 | - ret = (a[0] ^ b[0]) & mask[0]; | |
89 | - if (IFNAMSIZ > sizeof(unsigned long)) | |
90 | - ret |= (a[1] ^ b[1]) & mask[1]; | |
91 | - if (IFNAMSIZ > 2 * sizeof(unsigned long)) | |
92 | - ret |= (a[2] ^ b[2]) & mask[2]; | |
93 | - if (IFNAMSIZ > 3 * sizeof(unsigned long)) | |
94 | - ret |= (a[3] ^ b[3]) & mask[3]; | |
95 | - BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); | |
83 | + unsigned long ret = ifname_compare_aligned(_a, _b, _mask); | |
96 | 84 | #else |
97 | 85 | unsigned long ret = 0; |
98 | 86 | int i; |
net/ipv4/netfilter/ip_tables.c
... | ... | @@ -74,25 +74,6 @@ |
74 | 74 | |
75 | 75 | Hence the start of any table is given by get_table() below. */ |
76 | 76 | |
77 | -static unsigned long ifname_compare(const char *_a, const char *_b, | |
78 | - const unsigned char *_mask) | |
79 | -{ | |
80 | - const unsigned long *a = (const unsigned long *)_a; | |
81 | - const unsigned long *b = (const unsigned long *)_b; | |
82 | - const unsigned long *mask = (const unsigned long *)_mask; | |
83 | - unsigned long ret; | |
84 | - | |
85 | - ret = (a[0] ^ b[0]) & mask[0]; | |
86 | - if (IFNAMSIZ > sizeof(unsigned long)) | |
87 | - ret |= (a[1] ^ b[1]) & mask[1]; | |
88 | - if (IFNAMSIZ > 2 * sizeof(unsigned long)) | |
89 | - ret |= (a[2] ^ b[2]) & mask[2]; | |
90 | - if (IFNAMSIZ > 3 * sizeof(unsigned long)) | |
91 | - ret |= (a[3] ^ b[3]) & mask[3]; | |
92 | - BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); | |
93 | - return ret; | |
94 | -} | |
95 | - | |
96 | 77 | /* Returns whether matches rule or not. */ |
97 | 78 | /* Performance critical - called for every packet */ |
98 | 79 | static inline bool |
... | ... | @@ -121,7 +102,7 @@ |
121 | 102 | return false; |
122 | 103 | } |
123 | 104 | |
124 | - ret = ifname_compare(indev, ipinfo->iniface, ipinfo->iniface_mask); | |
105 | + ret = ifname_compare_aligned(indev, ipinfo->iniface, ipinfo->iniface_mask); | |
125 | 106 | |
126 | 107 | if (FWINV(ret != 0, IPT_INV_VIA_IN)) { |
127 | 108 | dprintf("VIA in mismatch (%s vs %s).%s\n", |
... | ... | @@ -130,7 +111,7 @@ |
130 | 111 | return false; |
131 | 112 | } |
132 | 113 | |
133 | - ret = ifname_compare(outdev, ipinfo->outiface, ipinfo->outiface_mask); | |
114 | + ret = ifname_compare_aligned(outdev, ipinfo->outiface, ipinfo->outiface_mask); | |
134 | 115 | |
135 | 116 | if (FWINV(ret != 0, IPT_INV_VIA_OUT)) { |
136 | 117 | dprintf("VIA out mismatch (%s vs %s).%s\n", |
net/ipv6/netfilter/ip6_tables.c
... | ... | @@ -89,25 +89,6 @@ |
89 | 89 | (nexthdr == IPPROTO_DSTOPTS) ); |
90 | 90 | } |
91 | 91 | |
92 | -static unsigned long ifname_compare(const char *_a, const char *_b, | |
93 | - const unsigned char *_mask) | |
94 | -{ | |
95 | - const unsigned long *a = (const unsigned long *)_a; | |
96 | - const unsigned long *b = (const unsigned long *)_b; | |
97 | - const unsigned long *mask = (const unsigned long *)_mask; | |
98 | - unsigned long ret; | |
99 | - | |
100 | - ret = (a[0] ^ b[0]) & mask[0]; | |
101 | - if (IFNAMSIZ > sizeof(unsigned long)) | |
102 | - ret |= (a[1] ^ b[1]) & mask[1]; | |
103 | - if (IFNAMSIZ > 2 * sizeof(unsigned long)) | |
104 | - ret |= (a[2] ^ b[2]) & mask[2]; | |
105 | - if (IFNAMSIZ > 3 * sizeof(unsigned long)) | |
106 | - ret |= (a[3] ^ b[3]) & mask[3]; | |
107 | - BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); | |
108 | - return ret; | |
109 | -} | |
110 | - | |
111 | 92 | /* Returns whether matches rule or not. */ |
112 | 93 | /* Performance critical - called for every packet */ |
113 | 94 | static inline bool |
... | ... | @@ -138,7 +119,7 @@ |
138 | 119 | return false; |
139 | 120 | } |
140 | 121 | |
141 | - ret = ifname_compare(indev, ip6info->iniface, ip6info->iniface_mask); | |
122 | + ret = ifname_compare_aligned(indev, ip6info->iniface, ip6info->iniface_mask); | |
142 | 123 | |
143 | 124 | if (FWINV(ret != 0, IP6T_INV_VIA_IN)) { |
144 | 125 | dprintf("VIA in mismatch (%s vs %s).%s\n", |
... | ... | @@ -147,7 +128,7 @@ |
147 | 128 | return false; |
148 | 129 | } |
149 | 130 | |
150 | - ret = ifname_compare(outdev, ip6info->outiface, ip6info->outiface_mask); | |
131 | + ret = ifname_compare_aligned(outdev, ip6info->outiface, ip6info->outiface_mask); | |
151 | 132 | |
152 | 133 | if (FWINV(ret != 0, IP6T_INV_VIA_OUT)) { |
153 | 134 | dprintf("VIA out mismatch (%s vs %s).%s\n", |
net/netfilter/xt_physdev.c
... | ... | @@ -20,24 +20,7 @@ |
20 | 20 | MODULE_ALIAS("ipt_physdev"); |
21 | 21 | MODULE_ALIAS("ip6t_physdev"); |
22 | 22 | |
23 | -static unsigned long ifname_compare(const char *_a, const char *_b, const char *_mask) | |
24 | -{ | |
25 | - const unsigned long *a = (const unsigned long *)_a; | |
26 | - const unsigned long *b = (const unsigned long *)_b; | |
27 | - const unsigned long *mask = (const unsigned long *)_mask; | |
28 | - unsigned long ret; | |
29 | 23 | |
30 | - ret = (a[0] ^ b[0]) & mask[0]; | |
31 | - if (IFNAMSIZ > sizeof(unsigned long)) | |
32 | - ret |= (a[1] ^ b[1]) & mask[1]; | |
33 | - if (IFNAMSIZ > 2 * sizeof(unsigned long)) | |
34 | - ret |= (a[2] ^ b[2]) & mask[2]; | |
35 | - if (IFNAMSIZ > 3 * sizeof(unsigned long)) | |
36 | - ret |= (a[3] ^ b[3]) & mask[3]; | |
37 | - BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); | |
38 | - return ret; | |
39 | -} | |
40 | - | |
41 | 24 | static bool |
42 | 25 | physdev_mt(const struct sk_buff *skb, const struct xt_match_param *par) |
43 | 26 | { |
... | ... | @@ -85,7 +68,7 @@ |
85 | 68 | if (!(info->bitmask & XT_PHYSDEV_OP_IN)) |
86 | 69 | goto match_outdev; |
87 | 70 | indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname; |
88 | - ret = ifname_compare(indev, info->physindev, info->in_mask); | |
71 | + ret = ifname_compare_aligned(indev, info->physindev, info->in_mask); | |
89 | 72 | |
90 | 73 | if (!ret ^ !(info->invert & XT_PHYSDEV_OP_IN)) |
91 | 74 | return false; |
... | ... | @@ -95,7 +78,7 @@ |
95 | 78 | return true; |
96 | 79 | outdev = nf_bridge->physoutdev ? |
97 | 80 | nf_bridge->physoutdev->name : nulldevname; |
98 | - ret = ifname_compare(outdev, info->physoutdev, info->out_mask); | |
81 | + ret = ifname_compare_aligned(outdev, info->physoutdev, info->out_mask); | |
99 | 82 | |
100 | 83 | return (!!ret ^ !(info->invert & XT_PHYSDEV_OP_OUT)); |
101 | 84 | } |