ocehb: (Default)
ocehb ([personal profile] ocehb) wrote2011-12-22 08:34 am
Entry tags:

Задачка про CIDR

Отсюда:
Задача такова: есть ASCIIZ-строка с IP-адресом, надо вернуть true, если этот адрес попадает в один из диапазонов, перечисленных в файле.

Файл текстовый такого формата,

192.168.1.3,192.168.1.5
192.168.2.4,193.0.0.3

Файл не отсортирован, дипапазоны произвольные и могут пересекаться. Первый адрес меньше второго или равен ему. Пересечение диапазонов можно обрабатывать двумя путями: лиюо отказываться грузить такой файл и выдавать что с чем пересеклось, либо не отказываться и корректно работать в таких условиях.

Файл грузится один раз и потом десятки миллионов раз лукапится. Записей в конфиге - сотни.


Решение:

# cat > z.pl
#! /usr/bin/perl

use Net::Patricia;
use Net::CIDR::Lite;

my $pt = new Net::Patricia;
my $cidr = new Net::CIDR::Lite;

open F, shift or die;
while () {
        chomp; s#,#-#;
        foreach my $m ($cidr->add_range($_)->list) { $pt->add_string($m) }
}

foreach (<>) {
        chomp;
        print $_, ":", $pt->match_string($_) ? "YES" : "NO", "\n";
}
^D
# perl z.pl /tmp/ip.range =( print -l 192.168.1.1 192.168.1.4 )
192.168.1.1:NO
192.168.1.4:YES
# perl -le 'foreach (0..$ARGV[0]) { printf "%d.%d.%d.%d\n", rand()%255, rand()%255, rand()%255, rand()%255 }' 10240000 >| /tmp/ip.list
# wc -l /tmp/ip.list
10240001 /tmp/ip.list
# time perl z.pl /tmp/ip.range /tmp/ip.list >| /dev/null
Real: 120.10s User: 105.21s System: 1.31s Percent: 88%% Cmd: perl z.pl /tmp/ip.range /tmp/ip.list >| /dev/null
#


PS. Вкралась ошибка: неправильно сгенерил список ip адресов, надо
# perl -le 'foreach (0..$ARGV[0]) { printf "%d.%d.%d.%d\n", int(rand(255)), int(rand(255)), int(rand(255)), int(rand(255)) }' 10240000 >| /tmp/ip.list

Результат:
# time perl z.pl /tmp/ip.range /tmp/ip.list >| /dev/null
Real: 176.98s User: 153.23s System: 2.20s Percent: 87%% Cmd: perl z.pl /tmp/ip.range /tmp/ip.list >| /dev/null


PS2. Скорость слабо зависит от количества сетей:

# for i in {1..300}; do a=$[ $RANDOM%255 ]; b=$[ $RANDOM%255 ]; c=$[ $RANDOM%254 ]; d=$[ $RANDOM%254 ]; print "$a.$b.$c.$d,$a.$b.$[$c+1].$[$d+1]"; done >| /tmp/ip.range2
# time perl z.pl /tmp/ip.range2 /tmp/ip.list >| /dev/null
Real: 187.54s User: 173.13s System: 1.98s Percent: 93%% Cmd: perl z.pl /tmp/ip.range2 /tmp/ip.list >| /dev/null
#


Post a comment in response:

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org