» »

Kako masovno pingat?

Kako masovno pingat?

ragezor ::

Recimo da nadzorujes dosti naprav in jih moras vskao minuto pingat, da preveris, ce so zive.

sem napisal en test na hitrico:
import subprocess
from threading import Thread
import Queue

q = Queue.Queue()


def ping():
    p = subprocess.Popen(["ping", "-c", "3", '8.8.8.8'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.read()
    return float(p.split('=')[-1].split('/')[-3])


def ping_multi_threaded(q):
    q.put(ping())


def ping_single_threaded(l):
    l.append(ping())

for i in range(1000):
    Thread(target=ping_multi_threaded, args=(q,)).start()

multi = []
while len(multi) < 1000:
    multi.append(q.get())

single = []
for i in range(10):
    ping_single_threaded(single)


print 'Single threaded avg:', sum(single)/float(len(single))
print 'Multi threaded avg:', sum(multi)/float(len(multi))


$ python ping-test.py 
Single threaded avg: 13.9988
Multi threaded avg: 24.27617


in ugotovil, da mi v multithreading nacinu prikazuje napacen ping.

zdaj pa nevem kako bi to resil?

niti ne vem tocno kje je problem. a je problem na ravni OSa, ker pac pingas full naenkrat. ali je problem v python threadih? glede na to, da ne pinga python proces se nagibam k temu, da je kriv OS.
  • spremenil: ragezor ()

videc ::

Zakaj ne uporabiš kakšen nadzorni sistem, ki ima to vgrajeno? Plus nadzor še nad kakšnimi storitvami, itd.

ragezor ::

ker gradim nadzorni sistem

Invictus ::

ragezor je izjavil:

ker gradim nadzorni sistem

Uporabiš Icingo, pa jo lahko razvijaš dalje.

Drugače pa poglej tudi broadcast ping ...
"Life is hard; it's even harder when you're stupid."

http://goo.gl/2YuS2x

ragezor ::

Pri lokalnih IPjih je se vecja razlika
$ python ping-test.py
Single threaded avg: 0.1873
Multi threaded avg: 5.6735

zaenrkat problem resujem s tem, da z randomom porazdelim zacetke pinganja po celotni minuti

def ping_multi_threaded(q):
time.sleep(random.random() * 60)
q.put(ping())

je pa se vedno razlika 0.5 ms
$ python ping-test.py
Single threaded avg: 0.2054
Multi threaded avg: 0.71255


bom pogledal broadcast ping

AndrejO ::

ragezor je izjavil:


niti ne vem tocno kje je problem. a je problem na ravni OSa, ker pac pingas full naenkrat. ali je problem v python threadih? glede na to, da ne pinga python proces se nagibam k temu, da je kriv OS.

Problem je v tvoji kodi. Pretiravaš s številom niti in sam sebi "ubiješ" računalnik. Uporabi multiprocessing.Pool in omeji število procesov na malo bolj zdravo količino, ne pa 1000 njih. Ko si že pri stvari, pa lako tudi kodo nekoliko polepšaš.

V razmislek pa poskusi ugotoviti kaj se zgodi z I/O podsistemom na računalniku, ko poskušaš sočasno zagnati 1000 kopij istega programa, ki nekaj meri in želi biti na 1ms natančen. Hmm.... misliš, da to morda kaj vpliva na timing?

videc ::

AndrejO je izjavil:

ragezor je izjavil:


niti ne vem tocno kje je problem. a je problem na ravni OSa, ker pac pingas full naenkrat. ali je problem v python threadih? glede na to, da ne pinga python proces se nagibam k temu, da je kriv OS.

Problem je v tvoji kodi. Pretiravaš s številom niti in sam sebi "ubiješ" računalnik. Uporabi multiprocessing.Pool in omeji število procesov na malo bolj zdravo količino, ne pa 1000 njih. Ko si že pri stvari, pa lako tudi kodo nekoliko polepšaš.

V razmislek pa poskusi ugotoviti kaj se zgodi z I/O podsistemom na računalniku, ko poskušaš sočasno zagnati 1000 kopij istega programa, ki nekaj meri in želi biti na 1ms natančen. Hmm.... misliš, da to morda kaj vpliva na timing?
+1 na tole in komentar o Icingi. Če ti sama Icinga ni tako všeč razmisli o OMD.

terryww ::

pri takem številu niti se ti splača razmislit o korutinah
It is the night. My body's weak.
I'm on the run. No time to sleep.

ragezor ::

AndrejO je izjavil:

ragezor je izjavil:


niti ne vem tocno kje je problem. a je problem na ravni OSa, ker pac pingas full naenkrat. ali je problem v python threadih? glede na to, da ne pinga python proces se nagibam k temu, da je kriv OS.

Problem je v tvoji kodi. Pretiravaš s številom niti in sam sebi "ubiješ" računalnik. Uporabi multiprocessing.Pool in omeji število procesov na malo bolj zdravo količino, ne pa 1000 njih. Ko si že pri stvari, pa lako tudi kodo nekoliko polepšaš.

V razmislek pa poskusi ugotoviti kaj se zgodi z I/O podsistemom na računalniku, ko poskušaš sočasno zagnati 1000 kopij istega programa, ki nekaj meri in želi biti na 1ms natančen. Hmm.... misliš, da to morda kaj vpliva na timing?


Jaz pac moram pobrati 1000 pingov v eni minuti. Ce bom pobiral zaporedoma, mi v eni minuti ne bo nikoli uspelo. Kot kaze preprosto OS ne utegne poschedulati pravocasno vseh pingov, da bi tocno zmerilo. Kot sem rekel, trenutno startam vse threade naenkrat in potem jih sleepam za random amount, da ne poklicejo vse naenkrat pinga. Torej bi jih lahko poklical tudi dosti vec, ce bi mel zadosti rama. Sem probal narediti tudi pool threadov. Manj thread workerjev, dlje casa traja pobiranje, bolj natancno je. Ampak potem pridem spet do tega, da je enako kot ce threade sleepam (ok, manj thread overheada je).

Korutine spet zmanjsajo overhead threadov ampak ne resujejo problema.

Ocitno bo pac potrebno paziti na obremenitev kompa, ki pinga. Ampak vedno sem mislil, da ce lahko routerji predelajo gigabajte paketkov na sekundo, bo mrezna na kompu ze pohendlala 1000 ping paketkov na easy. Izkaze se, da ping ni nekaj kar bi ICMP protokol podpiral, ampak se cas ocitno meri na aplikacijskem nivoju (sem bolj networking noob).

Verjetno bi za bolj ucinkovit ping moral napisati C program, ki opravi vse pinge, preko enega procesa in enega raw socketa. Potem bi mogoce bilo kaj bolje.

Isotropic ::

nagios?
ce se gres pa NIH, si pa še svoj .net stack napiši. :)
sem bral enkrat na redditu o eni firmi, k je mela nekaj takega :)

Zgodovina sprememb…

AndrejO ::

ragezor je izjavil:


Jaz pac moram pobrati 1000 pingov v eni minuti. Ce bom pobiral zaporedoma, mi v eni minuti ne bo nikoli uspelo. Kot kaze preprosto OS ne utegne poschedulati pravocasno vseh pingov, da bi tocno zmerilo.

Ne izgovarjaj se na OS, če si si za svojo rešitev izbral neprimerno orodje in določil slabo arhitekturo.

ragezor ::

Zato pa je tema tule, da lahko predlagas boljse toole in arhitekture.

Tvoj predlog glede poolov pa na zalost ne deluje, kot sem ti razlozil zgoraj.

ragezor ::

Cenim tudi odgovore tip nagios, etc. Ampak predstavljajte si, da delam produkt, ki bo konkuriral nagiosu. Kako bi potem naredil bolje od njih :)

Isotropic ::

nagios je zastonj, raje nehaj nategovat kupca

NIH

Zgodovina sprememb…

terryww ::

no, če se nočeš igrat s korutinami najde gugl korak boljšo kodo (http://stackoverflow.com/questions/2122... oz če se greš industrijski monitoring so ideje razvite v https://github.com/robertdavidgraham/ma... verjetno kaj iščeš in s čim boš navdušil stranko
It is the night. My body's weak.
I'm on the run. No time to sleep.

AndrejO ::

ragezor je izjavil:

Zato pa je tema tule, da lahko predlagas boljse toole in arhitekture.

Katere programske jezike in okolja obvladaš?
Katere operacijske sisteme želiš podpirati?
Kakšne so minimalne zahteve za strojno opremo?

ragezor ::

Isotropic, zdi se mi, da bi ti koristilo malo manj poslovno gledati na svet. Mogoce bi imel vec veselja delati kake stvari cetudi ne prinasajo denarja?

terryww, ni vse kar najdes na stackoverflowu dobra koda. Za IO bound aplikacije je ustvarjanje procesov slaba izbira, ker sele pri procesih pa res dobis dosti overheada + ce procesi komunicirajo med sabo, morajo serializirati podatke, jih poslati in spet deserializirati. Pri threadih tega ni potrebno.

AndrejO, jezik bi se ze naucil, da bi napisal en mikro servis, ki bi pingal, ce bi v kakem jeziku obstajala kaksna dobra knjiznica posebej za to. Da bi pa sel pisat specializiran ping v Cju (gradnja paketkov, crcjanje, itd,..) pa glih nebi.
Cimvec seveda.
Cim manjse seveda :)

AndrejO ::

ragezor je izjavil:

Za IO bound aplikacije je ustvarjanje procesov slaba izbira, ker sele pri procesih pa res dobis dosti overheada

Pa kljub temu si izbral rešitev, ki počne ravno to: poskuša "na en mah" ustvariti 1000 procesov.

ragezor je izjavil:

+ ce procesi komunicirajo med sabo, morajo serializirati podatke, jih poslati in spet deserializirati. Pri threadih tega ni potrebno.

Ta komunikacija je dejansko zelo poceni. Glede na to, da si pa izbral niti, pa je čudno, da si izbral tudi Python/CPython, ki ima GIL in znane omejitve pri večnitnih programih na večjedrnih računalnikih.

ragezor je izjavil:

AndrejO, jezik bi se ze naucil, da bi napisal en mikro servis, ki bi pingal, ce bi v kakem jeziku obstajala kaksna dobra knjiznica posebej za to. Da bi pa sel pisat specializiran ping v Cju (gradnja paketkov, crcjanje, itd,..) pa glih nebi.

Če je v tebi res toliko programerja, da se bi lahko poljuben jezik na hitro naučil, potem ti je ta "specializiran ping" stvar nekaj uric. Ajde, popoldneva, če se šele učiš jezika.

ragezor je izjavil:

Cimvec seveda.
Cim manjse seveda :)

Malo manj heca. Tile odgovori kažejo tvojo nepremišljenost, če ne kar neresnost. Če se igraš inženirja, potem se obnašaj kot inženir in določi vsaj osnovne kriterije, ki jih mora rešitev izpolniti. Do sedaj si določil samo enega. Torej lahko predvidim, da ti bo odgovor v zbirniku za MIPS verjetno ustrezen, če bo le dal od sebe 3000 QPS.

ragezor ::

Moja resitev ustvarja procese, ker je to bil najhitrejsi nacin implementacije in testiranje zadeve. Tudi python sem izbral zaradi tega, ker ga najbolj poznam in najlazje eksperimentiram.

GIL ne vpliva tukaj dosti na zadevo.

Najprej se delas norca, ker se mi zdi lahko nauciti en jezik za neko malo stvar, ki bi uporabljala neko knjiznico, kasneje se ti zdi cudno, da sem izbral python. A ti se za vsako stvar najprej pozanimas, kje se najhitreje naredi in se potem gres naucit jezik in potem se lotis zadeve? Se dobro, da projekti vsebujejo vedno samo en tip problemov, da lahko izberes potem jezik, ki je najboljsi za ta tip :)

Ja, osnovno uporabo jezika (in knjiznice) se je verjento hitreje nauciti, kot prestudirati par protokolov, razumeti algoritme in potem implementirati zadevo, ki bo performirala boljse kot zadeva, ki so jo verjetno napisali eksperti na podrocju.

Se vedno nobene pametne ideje ali namiga od tebe.

terryww ::

ragezor je izjavil:


terryww, ni vse kar najdes na stackoverflowu dobra koda. Za IO bound aplikacije je ustvarjanje procesov slaba izbira, ker sele pri procesih pa res dobis dosti overheada + ce procesi komunicirajo med sabo, morajo serializirati podatke, jih poslati in spet deserializirati. Pri threadih tega ni potrebno.

ah, ko ljudje niti tolko niso, da dobro pogledajo, če si že vzameš čas da jim odgovoriš...
    s primerom iz stackoverflowa sem ti želel nakazat kako, če že s threadi, ker ti zaženeš thread in v njem nov proces, skratka, kr nekaj

    ker so threadi v pythonu potratni, sploh 1k threadov, kot je AndrejO že večkrat opozoril, sem ti nakazal drugo alternativo - korutine (v pythonu maš greenlet lib ipd.), ki je ravno mišljen za take probleme

    za kaj bolj naprednega maš masscan in rešiš vse probleme
It is the night. My body's weak.
I'm on the run. No time to sleep.

ragezor ::

ja razen mojega ocitno.

masscan ne pinga. pa kolko googlam okrog vsi uporabljajo ping za discovery, noben ne govori nic o tem, da lahko popinga dosti hostov naenkrat in ohrani natancnost.

za korutine sem ti povedal, da so kul, ampak ne resijo mojega problema, ker je krivo to, da klicem preveckrat ping program. zdaj ce to pocnem s threadi, procesi ali korutinami nima veze.

AndrejO ::

ragezor je izjavil:

Moja resitev ustvarja procese, ker je to bil najhitrejsi nacin implementacije in testiranje zadeve. Tudi python sem izbral zaradi tega, ker ga najbolj poznam in najlazje eksperimentiram.

Ali lahko na podlagi tega sklepam, da bi ti Python kot jezik in okolje najbolj ustrezal, ker ga najbolje poznaš?

ragezor je izjavil:

GIL ne vpliva tukaj dosti na zadevo.

Dejansko pomembno vpliva na zadevo. 1000 niti v Pythonu, ki se zaženejo sočasno in sočasno poskušajo opravljati delo, ima svojo ceno ravno zaradi GIL.

ragezor je izjavil:

Najprej se delas norca, ker se mi zdi lahko nauciti en jezik za neko malo stvar, ki bi uporabljala neko knjiznico,

Ne delam se norca, temveč testiram tvoja stališča, da ugotovim kaj in kako si razmišljal, ko si se odločal. Eno je, da ti nekdo strese rešitev iz rokava, nekaj drugega pa potrebujem, če naj ti pomagam najti rešitev, ki bo ustreala tebi in tvojim potrebam.

ragezor je izjavil:

kasneje se ti zdi cudno, da sem izbral python.

Znova testiram, ker navedeš eno stališče, hkrati pa tvoja izbira nakazuje, da si to storil v nasprotju s tem stališčem.

ragezor je izjavil:

A ti se za vsako stvar najprej pozanimas, kje se najhitreje naredi in se potem gres naucit jezik in potem se lotis zadeve? Se dobro, da projekti vsebujejo vedno samo en tip problemov, da lahko izberes potem jezik, ki je najboljsi za ta tip :)

Na mojo srečo imam toliko let naskoka, da sem uporabljal že toliko programskih jezikov, da imam na voljo kar kontretno "orodjarno" za kar veliko različnih vrst problemov. In ja, tudi z vsem tem se mi ne zdi nič nezaslišanega pogledati tudi še neuporabljene jezike, da vidim, če bi s katerim drugim stvar opravil bolje in hitreje.

ragezor je izjavil:

Ja, osnovno uporabo jezika (in knjiznice) se je verjento hitreje nauciti, kot prestudirati par protokolov, razumeti algoritme in potem implementirati zadevo, ki bo performirala boljse kot zadeva, ki so jo verjetno napisali eksperti na podrocju.

Pri konkretnem problemu na srečo ni niti hudih algoritmov, niti hudih protokolov.

ragezor je izjavil:

Se vedno nobene pametne ideje ali namiga od tebe.

Saj bo, saj bo. Samo še malo podatkov mi daj, da ti bom lahko dal nekaj, kar si mislim, da ti bo koristilo bolj, kot pa samo "juhuhu, jaz pa lahko to naredim tako".

ragezor ::

kaksne podatke se torej rabis?

jaz vidim priblizno dve moznosti:
1. najdem nek tool ala masscan, sparsam output in ciao (al pa knjiznico, ki dela isto kot tool)
2. skopiram pure python implementacijo pinga jo probam razumeti in jo stweakam do zeljenih rezultatov. tukaj pa bo potem prislo v postev optimiziranje v stilu korutin in podobnih zadev. ce se izkaze, da je pretezko pac uporabljam to kar mam in zivim s kamnom v srcu, ker vem, da je moj ping verjetno napacen za kaksno milisekundo. ce se kdaj pojavi potreba, da bom moral pingati nenormalno veliko stevilo naprav se pa grem jokat oziroma si vzamem vec casa za resitev problema.

Ribič ::

Zakaj namesto python skripte ne uporabiš nmap skenerja?

# nmap -sP 192.168.1.0/24
Starting Nmap 6.40 ( http://nmap.org ) at 2015-04-24 23:09 CEST
Nmap scan report for ruter.localdomain (192.168.1.1)
Host is up (0.00053s latency).
Nmap scan report for 192.168.1.2
Host is up (0.0012s latency).
Nmap scan report for mojkomp.localdomain (192.168.1.100)
Host is up (0.00034s latency).
Nmap done: 256 IP addresses (3 hosts up) scanned in 2.92 seconds

Potem pa parsaš tale text z pythonom?

AndrejO ::

ragezor je izjavil:

kaksne podatke se torej rabis?

Potrdi ali ovrži moje predvidevanje, da ti bi Python najbolj ugajal.
Vsaj približno opredeli na kakšni strojni opremi želiš doseči 1000 naprav v 60s pri 3x ping za vsako. Je to nekaj tipa Raspberry PI ali nekaj tipa "namizni PC"?

ragezor je izjavil:

1. najdem nek tool ala masscan, sparsam output in ciao (al pa knjiznico, ki dela isto kot tool)

Dokler boš operiral z "lansiram nov proces za vsako napravo posebej", boš vedno naletel na isto težavo. To je napačna smer, razen če boš našel aplikacijo, ki se bo obnašala kot tvoj "ping server", da jih boš lahko zagnal več hkrati nato pa komuniciral z njimi.

ragezor je izjavil:

2. skopiram pure python implementacijo pinga jo probam razumeti in jo stweakam do zeljenih rezultatov.

Če želiš, ti lahko pomagam, da spišeš svojo implementacijo, ki bo tebi v celoti razumljiva, ker jo boš tako ali tako sam spisal. Z nekaj znanja konkkretna zadeva sploh ni zahtevna in tam, kjer se ti bo zatikalo, ti lahko pomagam vsaj jaz, verjetno pa tudi drugi.

ragezor je izjavil:

tukaj pa bo potem prislo v postev optimiziranje v stilu korutin in podobnih zadev. ce se izkaze, da je pretezko pac uporabljam to kar mam in zivim s kamnom v srcu, ker vem, da je moj ping verjetno napacen za kaksno milisekundo.

Kakšno natančnost pa sploh pričakuješ? Glede na to, da bo tvoja (oz. "userland") meritev časa vedno podložna milosti celotnega sistema od gonilnika mrežne kartice naprej, kolikšno odstopanje ti je sprejemljivo? Kaj te tukaj sploh zanima? Dosegljivst naprave, dosegljivost z določenim RTT ali dejanski RTT?

ragezor je izjavil:

ce se kdaj pojavi potreba, da bom moral pingati nenormalno veliko stevilo naprav se pa grem jokat oziroma si vzamem vec casa za resitev problema.

Osnove Pythona znaš, čez vikend lahko z nekaj malega pomoči ali pa tudi brez nje spišeš ta manjkajoči "ping", se naučiš kaj novega in greš z novo izkušnjo naprej.

ragezor ::

ja, python. PC racunalnik oziroma povprecen server.

Odstopanje mora biti manjse kot pri zdajsnjem pristopu. Nevem postaviti neke meje pri takih problemih, ker nikoli ne bo perfektno, ampak je pa fajn, da je cimboljse.

medtem casom sem ze raziskoval in zgleda je point v tem, da je tvoj program kar se da odziven na select()

bom jutri probal taktiko: 2 threada, en najprej ustvari vse paketke, potem jih pa zaporedoma poslje. drug thread pa v while zanki caka na select in shranjuje rezultate in timestampe nekam. ko je vsega konec se pa poracunajo zadeve.

edino ni mi jasno, ce lahko jaz posljem tri paketke do enega hosta naenkrat (z razlicnimi sequenci), ali moram cakati, da dobim prvi paketek nazaj in sele nato lahko naslednjega posljem. pomoje, da lahko vse naenkrat. ne vidim razloga zakaj nebi.

blackbfm ::

googlaj apache vs nginx, kako deluje en in drug..ker imaš točno tak problem

AndrejO ::

ragezor je izjavil:

ja, python. PC racunalnik oziroma povprecen server.

Odlično. Potem je Python več kot primeren in stvar je v njemu v celoti izvedljiva. Recimo v 200 vrsticah kode. Na hitro skupaj zmetana implementacija mi da na mojem prenosniku 1000 x 3 paketke na 8.8.8.8 v cca. 20s s 100 pomožnih procesov (multiprocessing).

ragezor je izjavil:

Odstopanje mora biti manjse kot pri zdajsnjem pristopu. Nevem postaviti neke meje pri takih problemih, ker nikoli ne bo perfektno, ampak je pa fajn, da je cimboljse.

OK, to je tudi dosegljivo, če je omrežje na strani strežnika sposobno daljših poplav paketov brez njihovega odmetavanja.

ragezor je izjavil:

medtem casom sem ze raziskoval in zgleda je point v tem, da je tvoj program kar se da odziven na select()

Select ni nikoli problematičen. Pomembno je, kaj boš zložil okoli njega.

ragezor je izjavil:

bom jutri probal taktiko: 2 threada, en najprej ustvari vse paketke, potem jih pa zaporedoma poslje. drug thread pa v while zanki caka na select in shranjuje rezultate in timestampe nekam. ko je vsega konec se pa poracunajo zadeve.

Znova se boš zapletel v niti in GIL te bo ustavil. Če želiš v Python narediti dejansko več stvari vzporedno, potem je nujno, da uporabiš več procesov.

Poglej si multiprocessing.Pool, ki je ravno prava stvar za to, kar potrebuješ.

ragezor je izjavil:

edino ni mi jasno, ce lahko jaz posljem tri paketke do enega hosta naenkrat (z razlicnimi sequenci), ali moram cakati, da dobim prvi paketek nazaj in sele nato lahko naslednjega posljem. pomoje, da lahko vse naenkrat. ne vidim razloga zakaj nebi.

Načeloma ne rabiš čakati, vendar razmisli kaj točno meriš. Povprečen RTT preko daljšega časa (recimo 5s) je nekaj čisto drugega, kot pa RTT treh zaporednih kratkih (cca. 40 bytov) paketkov. Če boš vse tri stlačil v isto milisekundo, ali potem dejansko rabiš pošiljati tri?

BigWhale ::

A ste vsi skupaj na glavo padl? :)

p = subprocess.Popen(["ping", "-c", "3", '8.8.8.8'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.read()


Klicat Popen in zaganjat externi proces je rahlo neproduktivno in trapasto. Poglej si gevent (http://www.gevent.org/) in prvo implementacijo icmp pinga, ki jo najdes za gevent, recimo tole https://github.com/mastahyeti/gping/blo...

Tole implementiras in bo stvar tridesetkrat bolj scalable in hitrejsa in bolj ucinkovita.

Klicanje zunanjih procesov je nekaj kar ne delas, ce lahko v native jeziku resis stvari, ker te sam klic zunanjega procesa kosta tolk I/Oja, da se ti tega v nobenem primeru ne splaca poceti.

Invictus ::

Najprej se vprašaj zakaj sploh rabiš odgovor 1000 pingov v minuti. Ko boš to vedel, bo vsae ostalo lažje.

Sam delam v nadzornih sistemih že zadnjih 12 let, pa vem da več kot en ping/device ne rabiš bolj pogosto kot na 15 minut.

Poleg tega so ponavadi bolj pomembni drugi parametri neke naprave in ne ping.
"Life is hard; it's even harder when you're stupid."

http://goo.gl/2YuS2x

BigWhale ::

ragezor je izjavil:

Jaz pac moram pobrati 1000 pingov v eni minuti. Ce bom pobiral zaporedoma, mi v eni minuti ne bo nikoli uspelo. Kot kaze preprosto OS ne utegne poschedulati pravocasno vseh pingov, da bi tocno zmerilo.


Uhm.

Kaj tocno bos pa zvedel od 1000 pingov v eni minuti? Da imas 1000 naprav na katerih deluje TCP stack? :)

Spura ::

Lahko bi se naprave javljale nadzornemu serverju vsako minuto? In ce ze mores obratno, zakaj ne mores narest pac da se po 100 pingov naenkrat izvaja namesto 1000?

SeMiNeSanja ::

Isti pomislek, ki ga je napisal Invictus, sem imel tudi jaz, samo se nisem hotel vpletati, da me nebi kdo obsojal, da vlečem diskusijo na offtopic.

Ping je pri nadzoru naprav/omrežja razmeroma nepomemben podatek, pomemben postane le v primeru, da čez daljše časovno obdobje postane nenavadno visok. Za tako statistiko pa povsem zadošča, če na 5 min pošlješ par pingov in vzameš povprečje.

Bolj intenzivno pinganje pa potem uporabljaš, ko si že identificiral problematični node in ugotavlaš posledice določenih posegov na omrežju/napravah.

Vse kar gre preko tega pa je čisto nepotrebno floodanje omrežij, da bi pridobival podatke, ki jih ne bo nihče gledal.

ragezor ::

pomisleki, glede gostote pinganja in ce se res rabi taka natancnost pri pinganju so valid, bolj se gre, da zadevi pridem do dna :)

poleg pinga se pobirajo se ostale informacije preko snmpja, http apija, ... zdaj pri ostalih stvareh lahko ustvarim threade/korutine in je vse kul (ker je zadeva IO bound). vec procesov, kot imas cpu corov je bolj kot ne nesmiselno (razen ce uporabljas non thread safe knjiznice).
torej ugotovimo, da imamo lahko zelo velik throughput brez problema.

pri pingu pa je dodatna zahteva se to, da se vrnjeni paketek cimprej po prejetju obdela in se shrani cas prejetja le tega. tu pa nastane problem, ker nisi ziher, kdaj bo tvoj proces schedulan, da bo pobral rezultate. recimo interupti bi bili en nacin. ko pride paketek se vedno switcha na proces, ki si shrani cas prejetja. to pa mislim, da se ne da narediti, ali?

sem si pogledal implementacijo pinga v pythonu.
https://github.com/CoreSecurity/impacke...
a bi slo odpreti samo en socket, v enem threadu filat noter paketke, v drugem pa jih samo prejemati. ampak nevem kako bi jih identificiral? ne razumem tocno tega, kaj se dogaja s checksumi in podatki, ki jih paketek drzi. pa kako vem, koliko byteov moram sprejemat. ker se bo nagrmadilo verjento vec paketkov zaporedoma bi jih rad jemal enega po enega.

Invictus ::

ragezor je izjavil:


a bi slo odpreti samo en socket, v enem threadu filat noter paketke, v drugem pa jih samo prejemati. ampak nevem kako bi jih identificiral?

Identificiral jih boš po source IPju.
"Life is hard; it's even harder when you're stupid."

http://goo.gl/2YuS2x

ragezor ::

fajn bi bila moznost pinganja istega hosta naenkrat

Randomness ::

pri pingu pa je dodatna zahteva se to, da se vrnjeni paketek cimprej po prejetju obdela in se shrani cas prejetja le tega. tu pa nastane problem, ker nisi ziher, kdaj bo tvoj proces schedulan, da bo pobral rezultate. recimo interupti bi bili en nacin. ko pride paketek se vedno switcha na proces, ki si shrani cas prejetja. to pa mislim, da se ne da narediti, ali?
Mislim, da glede tega malo preveč kompliciraš. Schedulerju se res bolj težko izogneš. Možno je sicer povišati prioriteto procesa/threada/taska, vendar real-time garancij na OS-ih, na katerih teče Python, pač nimaš.

Randomness ::

pa kako vem, koliko byteov moram sprejemat. ker se bo nagrmadilo verjento vec paketkov zaporedoma bi jih rad jemal enega po enega.
Saj drugače kot brati enega po enega tudi ne gre, to ni stream-oriented protocol tako kot TCP.

Randomness ::

ampak nevem kako bi jih identificiral?
V icmp header zabašeš id in sequence number, ki ti poleg src adrese služita za identifikacijo.

Invictus ::

ragezor je izjavil:

fajn bi bila moznost pinganja istega hosta naenkrat

Pa kaj misliš isti host večkrat zapovrstjo pingat?

Precej neuporabno za monitoring, pa še kak IDS/firewall te bo dal na črno listo spama ...
"Life is hard; it's even harder when you're stupid."

http://goo.gl/2YuS2x

AndrejO ::

Invictus je izjavil:

ragezor je izjavil:


a bi slo odpreti samo en socket, v enem threadu filat noter paketke, v drugem pa jih samo prejemati. ampak nevem kako bi jih identificiral?

Identificiral jih boš po source IPju.

Identificiral jih boš po source IP, ID, zaporedni številki in vsebini katero moraš izbrati natančno za ta način.

Invictus je izjavil:

ragezor je izjavil:

fajn bi bila moznost pinganja istega hosta naenkrat

Pa kaj misliš isti host večkrat zapovrstjo pingat?

Precej neuporabno za monitoring, pa še kak IDS/firewall te bo dal na črno listo spama ...

S tem si predvidel naslednje okoliščine:
- za vsak host boš torej poslal samo en paket IN
- paketi na omrežju se vedno vrnejo v enakem zaporedju IN
- nikoli ne bo noben drug proces na računalniku istočasno tudi "pingal" isti host IN
- za vsak poslan paket boš vedno dobil natančno en paket v odgovor.

Vse tri izjave so v resničnem svetu neveljavne in bodo pripeljale do neveljavnih rezultatov.

Sicer pa ne pozabi, da uporabljaš "surov" dostop. Prejel boš veliko prometa, ki te niti najmanj ne briga.

AndrejO ::

Sicer pa tako... da ne bo preveč razmišljanja na suho. Tole načeloma deluje.

ping.py
import os
import select
import socket
import struct
import time


class Error(Exception):
  """Base error class for all ICMP exceptions."""
  def __init__(self, msg="base ping error"):
    super(Exception, self).__init__(msg)


class PingTimeout(Error):
  """Timeout waiting for ICMP Echo reply from destination."""
  def __init__(self, msg="ping timeout"):
    super(PingTimeout, self).__init__(msg)


class InvalidChecksum(Error):
  """Invalid ICMP packet checksum."""
  def __init__(self, msg="invalid checksum"):
    super(InvalidChecksum, self).__init__(msg)


class _ICMPEcho(object):
  """Encapsulation of ICMP Echo and Reply packets."""
  def __init__(self, type, code, id, seq, data):
    self.type = type
    self.code = code
    self.id = id
    self.seq = seq
    self.data = data

  def pack(self):
    fmt = "!BBHHH%ds" % len(self.data)
    pkt = struct.pack(fmt, self.type, self.code, 0, self.id, self.seq, self.data)
    csum = _checksum(pkt)
    return struct.pack(fmt, self.type, self.code, csum, self.id, self.seq, self.data)

  @staticmethod
  def unpack(pkt, has_ip_hdr=False):
    if has_ip_hdr:
      hdr_size = (ord(pkt[0]) & 0xf) << 2
      pkt = pkt[hdr_size:]
    (type, code, csum, id, seq, data) = struct.unpack("!BBHHH%ds" % (len(pkt) - 8), pkt)
    pktchk = struct.pack("!BBHHH%ds" % len(data), type, code, 0, id, seq, data)
    if csum != _checksum(pktchk):
      raise InvalidChecksum()
    return _ICMPEcho(type, code, id, seq, data)


def _checksum(buf):
  """Calculate one's complement of one's complement of sum of 16-bit words."""

  # If buffer length is odd, add 0 byte to it to even it out.
  if len(buf) & 1 == 1:
    buf = buf[:] + "\0"

  # Checksum loop calculates one's complement sum. 16-bit word is assumed
  # to be in network order.
  s = 0
  for ii in range(0, len(buf), 2):
    # Get 16-bit word, network order.
    w = ord(buf[ii + 1]) + (ord(buf[ii]) << 8)
    # Add with carry.
    s += w
    s = (s & 0xffff) + (s >> 16)

  # Checksum is one's complement of one's complement sum.
  return s ^ 0xffff


def ping(address, seq, timeout):
  """Send ICMP Echo request packet to address and wait for reply.

  Sends ICMP Echo request packet to address and waits for reply or timeout.

  Args:
    address: a string, address of host to ping.
    seq:     an int, sequence number between 1 and 65535.
    timeout: a float, time to wait for echo reply reply in seconds.
  Returns:
    a float, time in seconds that it took to receive echo reply.
  Raises:
    PingTimeout: when echo reply isn't received within specified timeout.
  """

  # Prepare ICMP Echo request packet. Discriminator is needed to avoid hitting
  # delayed packets in the same process, because processes could be reused.
  id = os.getpid() & 0xffff
  disc = "%f" % time.time()
  pkt = _ICMPEcho(8, 0, id, seq, disc)

  # Open socket and send prepared packet to destination address.
  s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
  s.sendto(pkt.pack(), (address, 0))

  # Store the time when packet was delivered to the system (assumed sent).
  start = time.time()

  # Deadline is the value of time.time() until which to wait for matching
  # ICMP Reply packet to return. It's used to calculate select() timeout.
  deadline = start + timeout

  while timeout > 0.0:
    # Wait for an event on socket.
    ready = select.select([s], [], [], timeout)

    # If there's nothing to read, a timeout occured.
    if len(ready[0]) == 0:
      raise PingTimeout()

    # Store received time. If packet will match, this will be used to calculate RTT.
    received = time.time()
    pkt, src_addr = s.recvfrom(1528)

    # Short the loop if the packet is from the wrong address.
    if src_addr[0] != address:
      timeout = deadline - time.time()
      continue

    # Short the loop if packet doesn't match the one we have sent.
    pkt = _ICMPEcho.unpack(pkt, has_ip_hdr=True)
    if pkt.type != 0 or pkt.code != 0 or pkt.id != id or pkt.seq != seq or pkt.data != disc:
      timeout = deadline - time.time()
      continue

    # Calculate RTT and return it
    return received - start


pinger.py
import sys
import time

from multiprocessing import Pool

import ping

 
class Ping(object):
  def __init__(self, tries=3, interval=1.0, timeout=1.0):
    self.tries = tries
    self.interval = interval
    self.timeout = timeout

  def __call__(self, address):
    times = []
    for seq in xrange(1, self.tries + 1):
      not_before = time.time() + self.interval
      try:
        times.append(ping.ping(address, seq, self.timeout))
      except ping.PingTimeout:
        times.append(None)
      except Exception as e:
        return (address, e)
      # Wait if needed before moving to the next iteration.
      while seq < self.tries and time.time() < not_before:
        time.sleep(not_before - time.time())
    # Return address and list of tries.
    return (address, times)


def ping_all(addresses, processes=25):
  pool = Pool(processes=processes)
  ok, err = [], []
  for res in pool.imap(Ping(), addresses, chunksize=10):
    if isinstance(res[1], Exception):
      err.append(res)
    elif not [x for x in res[1] if x]:
      err.append((res[0], Exception("host unreachable")))
    else:
      ok.append(res)
  return ok, err


def main(argv):
  addresses = ['127.0.0.1'] * 1000

  start = time.time()
  ok, err = ping_all(addresses)
  end = time.time()

  if ok:
    print "Averages:"
    for result in ok:
      valid = [rtt for rtt in result[1] if rtt]
      success = len(valid) * 100 / len(result[1])
      print "  %s:\t%%/Avg/Min/Max: %3d%%/%f/%f/%f" % (result[0], success, sum(valid)/float(len(valid)), min(valid), max(valid))

  if err:
    print "Errors:"
    for result in err:
      print "  %s:\t%s" % result

  print "Time to execute all: %f" % (end - start)


if __name__ == "__main__":
    sys.exit(main(sys.argv))

ragezor ::

lahko prosim se malo razlozis kaj se dogaja v pack() in unpack() ter kaj je type, code in id?

AndrejO ::

ragezor je izjavil:

lahko prosim se malo razlozis kaj se dogaja v pack() in unpack()

Tukaj.

ragezor je izjavil:

ter kaj je type, code in id?

Tukaj in tukaj.

Povezave pa zato, ker je nemogoče, da bi sam bolje povzel ali opisal kaj katera stvar počne (za modul struct) oziroma kako je sestavljena glava (za razlago tipa, kode in ostalih polj v ICMP Echo Request/Reply paketih).

ragezor ::

imel sem priloznost vec casa posvetiti temu problemu (natancnost pinga)

uporabil sem tole resitev: https://www.kernel.org/doc/Documentatio...
kolikor mi je znano se paketki timestampajo hardwerasko, ce je za to podpora, ce ne pa v kernelu. vsekakor boljse kot pa, ce bi timestampal v userlandu. ne vem kako podprta je zadeva, ampak delovalo je na vseh masinah kar sem jih sprobal.

okvirna implementacija v pythonu:

# kreiranje socketa in nastavitev opcije SO_TIMESTAMP
# vrednost SO_TIMESTAMP je potrebno najti v kernel source kodi, ker je ni v socket modulu
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
s.setsockopt(socket.SOL_SOCKET, 29, 1)  # SO_TIMESTAMP = 29

# ko je socket pripravljen za read dobimo paket v data in timestamp v ancilary messagu
# python3.5 
data, anc_msgs, msg_flags, address = s.recvmsg(65535, 65535)
# nizje verzije pythona
import socketextra
data, anc_msgs, msg_flags, address = socketextra.recvmsg(s, 65535, 65535)
# socketextra ima bug in vedno vrne None kot address

# anc_msgs je lista sporocil, ki so toupli. vzamemo prvo sporocilo. 
# dokumentacija nam pove, da iscemo 3ji element v tuplu
# 3ji element je v bistvu binary niz, ki predstavlja C struct in ga razpakiramo s struct.unpack
seconds, microseconds = struct.unpack('ll', anc_msgs[0][2])
# pokalkuliramo, da dobimo unix timestamp
recv_time = seconds + microseconds / 1000000.0

Zgodovina sprememb…

  • spremenil: ragezor ()


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Python primer async/await

Oddelek: Programiranje
182129 (1235) jype
»

[Python3] Izvajanje ukazov po določenem času

Oddelek: Programiranje
211447 (1057) noraguta
»

Težave z Amisovim modemom

Oddelek: Pomoč in nasveti
245372 (4954) 111111111111
»

If stavek ping

Oddelek: Programiranje
122060 (1525) AndrejO
»

Kateri programski jezik?

Oddelek: Programiranje
494545 (3158) kopernik

Več podobnih tem