Skip to content

Commit 323dbf9

Browse files
Eric Dumazetkaber
authored andcommitted
netfilter: ip6_tables: unfold two loops in ip6_packet_match()
ip6_tables netfilter module can use an ifname_compare() helper so that two loops are unfolded. Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: Patrick McHardy <[email protected]>
1 parent eacc17f commit 323dbf9

File tree

1 file changed

+21
-12
lines changed

1 file changed

+21
-12
lines changed

net/ipv6/netfilter/ip6_tables.c

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,25 @@ ip6t_ext_hdr(u8 nexthdr)
8989
(nexthdr == IPPROTO_DSTOPTS) );
9090
}
9191

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+
92111
/* Returns whether matches rule or not. */
93112
/* Performance critical - called for every packet */
94113
static inline bool
@@ -99,7 +118,6 @@ ip6_packet_match(const struct sk_buff *skb,
99118
unsigned int *protoff,
100119
int *fragoff, bool *hotdrop)
101120
{
102-
size_t i;
103121
unsigned long ret;
104122
const struct ipv6hdr *ipv6 = ipv6_hdr(skb);
105123

@@ -120,12 +138,7 @@ ip6_packet_match(const struct sk_buff *skb,
120138
return false;
121139
}
122140

123-
/* Look for ifname matches; this should unroll nicely. */
124-
for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
125-
ret |= (((const unsigned long *)indev)[i]
126-
^ ((const unsigned long *)ip6info->iniface)[i])
127-
& ((const unsigned long *)ip6info->iniface_mask)[i];
128-
}
141+
ret = ifname_compare(indev, ip6info->iniface, ip6info->iniface_mask);
129142

130143
if (FWINV(ret != 0, IP6T_INV_VIA_IN)) {
131144
dprintf("VIA in mismatch (%s vs %s).%s\n",
@@ -134,11 +147,7 @@ ip6_packet_match(const struct sk_buff *skb,
134147
return false;
135148
}
136149

137-
for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
138-
ret |= (((const unsigned long *)outdev)[i]
139-
^ ((const unsigned long *)ip6info->outiface)[i])
140-
& ((const unsigned long *)ip6info->outiface_mask)[i];
141-
}
150+
ret = ifname_compare(outdev, ip6info->outiface, ip6info->outiface_mask);
142151

143152
if (FWINV(ret != 0, IP6T_INV_VIA_OUT)) {
144153
dprintf("VIA out mismatch (%s vs %s).%s\n",

0 commit comments

Comments
 (0)