mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-07 21:25:12 +02:00
geoip: use a binary search to replace the current linear one
Certain countries have lots (around 10000) of IP address ranges (US,GB,DE,...). The current linear search is really bad: No firewall: 3000 packets transmitted, 3000 received, 0% packet loss, time 1992ms Testing against the countries with top 50 IP ranges: 3000 packets transmitted, 3000 received, 0% packet loss, time 8998ms With binary search: 3000 packets transmitted, 3000 received, 0% packet loss, time 2358ms
This commit is contained in:
@@ -113,6 +113,25 @@ static struct geoip_info *find_node(u_int16_t cc)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool geoip_bsearch(const struct geoip_subnet *range,
|
||||||
|
uint32_t addr, int lo, int hi)
|
||||||
|
{
|
||||||
|
int mid;
|
||||||
|
|
||||||
|
if (hi < lo)
|
||||||
|
return false;
|
||||||
|
mid = (lo + hi) / 2;
|
||||||
|
if (range[mid].begin <= addr && addr <= range[mid].end)
|
||||||
|
return true;
|
||||||
|
if (range[mid].begin > addr)
|
||||||
|
return geoip_bsearch(range, addr, lo, mid - 1);
|
||||||
|
else if (range[mid].end < addr)
|
||||||
|
return geoip_bsearch(range, addr, mid + 1, hi);
|
||||||
|
|
||||||
|
WARN_ON(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool xt_geoip_mt(const struct sk_buff *skb, const struct net_device *in,
|
static bool xt_geoip_mt(const struct sk_buff *skb, const struct net_device *in,
|
||||||
const struct net_device *out, const struct xt_match *match,
|
const struct net_device *out, const struct xt_match *match,
|
||||||
const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
|
const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop)
|
||||||
@@ -120,7 +139,7 @@ static bool xt_geoip_mt(const struct sk_buff *skb, const struct net_device *in,
|
|||||||
const struct xt_geoip_match_info *info = matchinfo;
|
const struct xt_geoip_match_info *info = matchinfo;
|
||||||
const struct geoip_info *node; /* This keeps the code sexy */
|
const struct geoip_info *node; /* This keeps the code sexy */
|
||||||
const struct iphdr *iph = ip_hdr(skb);
|
const struct iphdr *iph = ip_hdr(skb);
|
||||||
u_int32_t ip, i, j;
|
uint32_t ip, i;
|
||||||
|
|
||||||
if (info->flags & XT_GEOIP_SRC)
|
if (info->flags & XT_GEOIP_SRC)
|
||||||
ip = ntohl(iph->saddr);
|
ip = ntohl(iph->saddr);
|
||||||
@@ -136,12 +155,10 @@ static bool xt_geoip_mt(const struct sk_buff *skb, const struct net_device *in,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (j = 0; j < node->count; j++)
|
if (geoip_bsearch(node->subnets, ip, 0, node->count)) {
|
||||||
if (ip >= node->subnets[j].begin &&
|
spin_unlock_bh(&geoip_lock);
|
||||||
ip <= node->subnets[j].end) {
|
return (info->flags & XT_GEOIP_INV) ? 0 : 1;
|
||||||
spin_unlock_bh(&geoip_lock);
|
}
|
||||||
return (info->flags & XT_GEOIP_INV) ? 0 : 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_bh(&geoip_lock);
|
spin_unlock_bh(&geoip_lock);
|
||||||
|
Reference in New Issue
Block a user