Skip to content

Instantly share code, notes, and snippets.

@sebres
Last active April 3, 2020 12:30
Show Gist options
  • Save sebres/eaed471108560fce2e75497bb0826aec to your computer and use it in GitHub Desktop.
Save sebres/eaed471108560fce2e75497bb0826aec to your computer and use it in GitHub Desktop.
test-concurrent-ipset.tcl -- test script concurrently flooding IPs in ipset(s)
#!/usr/bin/env tclsh
package require Thread
array set in {-max-threads 4 -single-set 0 -max-ips 255 -iterations 3 -debug 0}
array set in $::argv
set commoncode {
if {$in(-single-set)} {
proc thipset {n} {return "f2b-test"}
proc thip {i} {return "192.${::thn}.[expr {2 + ($i >> 8)}].[expr {$i & 0xFF}]"}
} else {
proc thipset {n} {return "f2b-test-$n"}
proc thip {i} {return "192.0.[expr {2 + ($i >> 8)}].[expr {$i & 0xFF}]"}
}
if {$in(-debug)} {
set ::logpref [format " # %08s" [regsub {^tid0x} [thread::id] {\1}]]
proc log.debug {msg} {puts "$::logpref $msg"}
} else {
proc log.debug args {}
}
}
eval $commoncode
# init thread pool:
set i 0; while {[incr i] <= $in(-max-threads)} {
set th($i) [thread::create]
thread::send -async $th($i) [list set master [thread::id]]
thread::send -async $th($i) [list array set in [array get in]]
thread::send -async $th($i) $commoncode
}
time {
puts "== iteration [incr iter] =="
# create sets and flood ipset with 255 IPs by every thread:
set ::ready 0
set i 0; while {[incr i] <= $in(-max-threads)} {
thread::send -async $th($i) [list set ::thn $i]
thread::send -async $th($i) {
set sn [thipset $::thn]; exec ipset -exist create $sn hash:ip hashsize 8192 timeout 0
}
}
# add tasks in lock to cause paralleled run of test in all workers (concurrence):
tsv::lock commonlock {
set i 0; while {[incr i] <= $in(-max-threads)} {
thread::send -async $th($i) {
tsv::lock commonlock {}; # wait all workers initialized
log.debug "begins flood ..."
set k 0; while {[incr k] <= $in(-max-ips)} {
set ip [thip $k]
log.debug " $ip -> $sn"
exec ipset add $sn $ip timeout 0 -exist
}
log.debug "ready."
}
thread::send -async $th($i) {thread::send -async $master {incr ::ready}}
}
}
# wait all threads are ready with its flooding part:
while {$::ready < $in(-max-threads)} {vwait ::ready}
# check all ips are present:
set i 0; while {[incr i] <= $in(-max-threads)} {
set sn [thipset $i]
set lst [exec ipset list $sn]
set lst [regexp -all -line -inline {^\s*(?:\d+\.){3}\d+} $lst]
puts " $sn has [llength $lst] IPs"
# check every IP is in the set:
set ::thn $i
set k 0; while {[incr k] <= $in(-max-ips)} {
set ip [thip $k]
if {$ip ni $lst} {puts " ** ERROR: $ip is not in set"}
}
if {$in(-single-set)} break
}
# remove sets:
set i 0; while {[incr i] <= $in(-max-threads)} {
set sn [thipset $i]
exec ipset flush $sn
exec ipset destroy $sn
if {$in(-single-set)} break
}
} $in(-iterations)
set i 0; while {[incr i] <= $in(-max-threads)} {
thread::release -wait $th($i)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment