<s> import os , sys , random , time , optparse , datetime <EOL> from string import Template <EOL> try : <EOL> from core import pycore <EOL> except ImportError : <EOL> if "<STR_LIT>" in sys . path : <EOL> sys . path . append ( "<STR_LIT>" ) <EOL> if "<STR_LIT>" in sys . path : <EOL> sys . path . append ( "<STR_LIT>" ) <EOL> if "<STR_LIT>" in sys . path : <EOL> sys . path . append ( "<STR_LIT>" ) <EOL> if "<STR_LIT>" in sys . path : <EOL> sys . path . append ( "<STR_LIT>" ) <EOL> from core import pycore <EOL> from core . misc import ipaddr <EOL> from core . misc . utils import mutecall <EOL> from core . constants import QUAGGA_STATE_DIR <EOL> quagga_sbin_search = ( "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ) <EOL> quagga_path = "<STR_LIT>" <EOL> try : <EOL> for p in quagga_sbin_search : <EOL> if os . path . exists ( os . path . join ( p , "<STR_LIT>" ) ) : <EOL> quagga_path = p <EOL> break <EOL> mutecall ( [ os . path . join ( quagga_path , "<STR_LIT>" ) , <EOL> "<STR_LIT>" , "<STR_LIT:root>" , "<STR_LIT>" , "<STR_LIT:root>" , "<STR_LIT>" ] ) <EOL> except OSError : <EOL> sys . stderr . write ( "<STR_LIT>" ) <EOL> sys . exit ( <NUM_LIT:1> ) <EOL> class ManetNode ( pycore . nodes . LxcNode ) : <EOL> """<STR_LIT>""" <EOL> conftemp = Template ( """<STR_LIT>""" ) <EOL> confdir = "<STR_LIT>" <EOL> def __init__ ( self , core , ipaddr , routerid = None , <EOL> objid = None , name = None , nodedir = None ) : <EOL> if routerid is None : <EOL> routerid = ipaddr . split ( "<STR_LIT:/>" ) [ <NUM_LIT:0> ] <EOL> self . ipaddr = ipaddr <EOL> self . routerid = routerid <EOL> pycore . nodes . LxcNode . __init__ ( self , core , objid , name , nodedir ) <EOL> self . privatedir ( self . confdir ) <EOL> self . privatedir ( QUAGGA_STATE_DIR ) <EOL> def qconf ( self ) : <EOL> return self . conftemp . substitute ( ipaddr = self . ipaddr , <EOL> routerid = self . routerid ) <EOL> def config ( self ) : <EOL> filename = os . path . join ( self . confdir , "<STR_LIT>" ) <EOL> f = self . opennodefile ( filename , "<STR_LIT:w>" ) <EOL> f . write ( self . qconf ( ) ) <EOL> f . close ( ) <EOL> tmp = self . bootscript ( ) <EOL> if tmp : <EOL> self . nodefile ( self . bootsh , tmp , mode = <NUM_LIT:0> <NUM_LIT> ) <EOL> def boot ( self ) : <EOL> self . config ( ) <EOL> self . session . services . bootnodeservices ( self ) <EOL> def bootscript ( self ) : <EOL> return """<STR_LIT>""" % ( QUAGGA_STATE_DIR , quagga_path , quagga_path ) <EOL> class Route ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , prefix = None , gw = None , metric = None ) : <EOL> try : <EOL> self . prefix = ipaddr . IPv4Prefix ( prefix ) <EOL> except Exception , e : <EOL> raise ValueError , "<STR_LIT>" % ( prefix , e ) <EOL> self . gw = gw <EOL> self . metric = metric <EOL> def __eq__ ( self , other ) : <EOL> try : <EOL> return self . prefix == other . prefix and self . gw == other . gw and self . metric == other . metric <EOL> except : <EOL> return False <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % ( self . prefix , self . gw , self . metric ) <EOL> @ staticmethod <EOL> def key ( r ) : <EOL> if not r . prefix : <EOL> return <NUM_LIT:0> <EOL> return r . prefix . prefix <EOL> class ManetExperiment ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , options , start ) : <EOL> """<STR_LIT>""" <EOL> self . session = None <EOL> self . nodes = [ ] <EOL> self . net = None <EOL> self . verbose = options . verbose <EOL> self . options = options <EOL> self . start = start <EOL> self . logbegin ( ) <EOL> def info ( self , msg ) : <EOL> '''<STR_LIT>''' <EOL> print msg <EOL> sys . stdout . flush ( ) <EOL> self . log ( msg ) <EOL> def warn ( self , msg ) : <EOL> '''<STR_LIT>''' <EOL> print >> sys . stderr , msg <EOL> sys . stderr . flush ( ) <EOL> self . log ( msg ) <EOL> def logbegin ( self ) : <EOL> """<STR_LIT>""" <EOL> self . logfp = None <EOL> if not self . options . logfile : <EOL> return <EOL> self . logfp = open ( self . options . logfile , "<STR_LIT:w>" ) <EOL> self . log ( "<STR_LIT>" % self . start . ctime ( ) ) <EOL> def logend ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . logfp : <EOL> return <EOL> end = datetime . datetime . now ( ) <EOL> self . log ( "<STR_LIT>" % ( end . ctime ( ) , end - self . start ) ) <EOL> self . logfp . flush ( ) <EOL> self . logfp . close ( ) <EOL> self . logfp = None <EOL> def log ( self , msg ) : <EOL> """<STR_LIT>""" <EOL> if not self . logfp : <EOL> return <EOL> print >> self . logfp , msg <EOL> def logdata ( self , nbrs , mdrs , lsdbs , krs , zrs ) : <EOL> """<STR_LIT>""" <EOL> self . log ( "<STR_LIT>" ) <EOL> self . log ( "<STR_LIT>" ) <EOL> self . log ( "<STR_LIT:%s>" % self . options ) <EOL> self . log ( "<STR_LIT>" ) <EOL> for rtrid in sorted ( nbrs . keys ( ) ) : <EOL> self . log ( "<STR_LIT>" % ( rtrid , nbrs [ rtrid ] ) ) <EOL> self . log ( "<STR_LIT>" ) <EOL> self . log ( mdrs ) <EOL> self . log ( "<STR_LIT>" ) <EOL> for rtrid in sorted ( lsdbs . keys ( ) ) : <EOL> self . log ( "<STR_LIT>" % rtrid ) <EOL> for line in lsdbs [ rtrid ] . split ( "<STR_LIT:\n>" ) : <EOL> self . log ( line ) <EOL> self . log ( "<STR_LIT>" ) <EOL> for rtrid in sorted ( krs . keys ( ) ) : <EOL> msg = rtrid + "<STR_LIT>" <EOL> for rt in krs [ rtrid ] : <EOL> msg += "<STR_LIT:%s>" % rt <EOL> self . log ( msg ) <EOL> self . log ( "<STR_LIT>" ) <EOL> for rtrid in sorted ( zrs . keys ( ) ) : <EOL> msg = rtrid + "<STR_LIT>" <EOL> for rt in zrs [ rtrid ] : <EOL> msg += "<STR_LIT:%s>" % rt <EOL> self . log ( msg ) <EOL> def topology ( self , numnodes , linkprob , verbose = False ) : <EOL> """<STR_LIT>""" <EOL> prefix = ipaddr . IPv4Prefix ( "<STR_LIT>" ) <EOL> self . session = pycore . Session ( ) <EOL> self . net = self . session . addobj ( cls = pycore . nodes . WlanNode ) <EOL> for i in xrange ( <NUM_LIT:1> , numnodes + <NUM_LIT:1> ) : <EOL> addr = "<STR_LIT>" % ( prefix . addr ( i ) , <NUM_LIT:32> ) <EOL> tmp = self . session . addobj ( cls = ManetNode , ipaddr = addr , objid = "<STR_LIT>" % i , name = "<STR_LIT>" % i ) <EOL> tmp . newnetif ( self . net , [ addr ] ) <EOL> self . nodes . append ( tmp ) <EOL> for i in xrange ( numnodes ) : <EOL> for j in xrange ( i + <NUM_LIT:1> , numnodes ) : <EOL> r = random . random ( ) <EOL> if r < linkprob : <EOL> if self . verbose : <EOL> self . info ( "<STR_LIT>" % ( i , j ) ) <EOL> self . net . link ( self . nodes [ i ] . netif ( <NUM_LIT:0> ) , self . nodes [ j ] . netif ( <NUM_LIT:0> ) ) <EOL> j = i <EOL> while j == i : <EOL> j = random . randint ( <NUM_LIT:0> , numnodes - <NUM_LIT:1> ) <EOL> if self . verbose : <EOL> self . info ( "<STR_LIT>" % ( i , j ) ) <EOL> self . net . link ( self . nodes [ i ] . netif ( <NUM_LIT:0> ) , self . nodes [ j ] . netif ( <NUM_LIT:0> ) ) <EOL> self . nodes [ i ] . boot ( ) <EOL> for i in xrange ( numnodes ) : <EOL> self . nodes [ i ] . cmd ( [ "<STR_LIT>" % self . nodes [ i ] . bootsh ] ) <EOL> def compareroutes ( self , node , kr , zr ) : <EOL> """<STR_LIT>""" <EOL> kr . sort ( key = Route . key ) <EOL> zr . sort ( key = Route . key ) <EOL> if kr != zr : <EOL> self . warn ( "<STR_LIT>" ) <EOL> if self . verbose : <EOL> msg = "<STR_LIT>" <EOL> for r in kr : <EOL> msg += "<STR_LIT>" % r <EOL> msg += "<STR_LIT>" <EOL> for r in zr : <EOL> msg += "<STR_LIT>" % r <EOL> self . warn ( msg ) <EOL> else : <EOL> self . info ( "<STR_LIT>" ) <EOL> def comparemdrlevels ( self , nbrs , mdrs ) : <EOL> """<STR_LIT>""" <EOL> msg = "<STR_LIT>" <EOL> for n in self . nodes : <EOL> if mdrs [ n . routerid ] != "<STR_LIT>" : <EOL> continue <EOL> connected = False <EOL> for nbr in nbrs [ n . routerid ] : <EOL> if mdrs [ nbr ] == "<STR_LIT>" or mdrs [ nbr ] == "<STR_LIT>" : <EOL> connected = True <EOL> break <EOL> if not connected : <EOL> msg = "<STR_LIT>" <EOL> self . warn ( "<STR_LIT>" % ( n . routerid , nbrs [ n . routerid ] ) ) <EOL> if self . verbose : <EOL> self . info ( msg ) <EOL> def comparelsdbs ( self , lsdbs ) : <EOL> """<STR_LIT>""" <EOL> msg = "<STR_LIT>" <EOL> prev = self . nodes [ <NUM_LIT:0> ] <EOL> for n in self . nodes : <EOL> db = lsdbs [ n . routerid ] <EOL> if lsdbs [ prev . routerid ] != db : <EOL> msg = "<STR_LIT>" <EOL> self . warn ( "<STR_LIT>" % ( n . routerid , prev . routerid ) ) <EOL> i = <NUM_LIT:0> <EOL> for entry in lsdbs [ n . routerid ] . split ( "<STR_LIT:\n>" ) : <EOL> preventries = lsdbs [ prev . routerid ] . split ( "<STR_LIT:\n>" ) <EOL> try : <EOL> preventry = preventries [ i ] <EOL> except IndexError : <EOL> preventry = None <EOL> if entry != preventry : <EOL> self . warn ( "<STR_LIT>" % ( n . routerid , entry ) ) <EOL> self . warn ( "<STR_LIT>" % ( prev . routerid , preventry ) ) <EOL> i += <NUM_LIT:1> <EOL> prev = n <EOL> if self . verbose : <EOL> self . info ( msg ) <EOL> def checknodes ( self ) : <EOL> """<STR_LIT>""" <EOL> nbrs = { } <EOL> mdrs = { } <EOL> lsdbs = { } <EOL> krs = { } <EOL> zrs = { } <EOL> v = self . verbose <EOL> for n in self . nodes : <EOL> self . info ( "<STR_LIT>" % n . name ) <EOL> nbrs [ n . routerid ] = Ospf6NeighState ( n , verbose = v ) . run ( ) <EOL> krs [ n . routerid ] = KernelRoutes ( n , verbose = v ) . run ( ) <EOL> zrs [ n . routerid ] = ZebraRoutes ( n , verbose = v ) . run ( ) <EOL> self . compareroutes ( n , krs [ n . routerid ] , zrs [ n . routerid ] ) <EOL> mdrs [ n . routerid ] = Ospf6MdrLevel ( n , verbose = v ) . run ( ) <EOL> lsdbs [ n . routerid ] = Ospf6Database ( n , verbose = v ) . run ( ) <EOL> self . comparemdrlevels ( nbrs , mdrs ) <EOL> self . comparelsdbs ( lsdbs ) <EOL> self . logdata ( nbrs , mdrs , lsdbs , krs , zrs ) <EOL> class Cmd : <EOL> """<STR_LIT>""" <EOL> args = "<STR_LIT>" <EOL> def __init__ ( self , node , verbose = False ) : <EOL> """<STR_LIT>""" <EOL> self . id = None <EOL> self . stdin = None <EOL> self . out = None <EOL> self . node = node <EOL> self . verbose = verbose <EOL> def info ( self , msg ) : <EOL> '''<STR_LIT>''' <EOL> print msg <EOL> sys . stdout . flush ( ) <EOL> def warn ( self , msg ) : <EOL> '''<STR_LIT>''' <EOL> print >> sys . stderr , "<STR_LIT>" % self . node . routerid , msg <EOL> sys . stderr . flush ( ) <EOL> def run ( self ) : <EOL> """<STR_LIT>""" <EOL> self . open ( ) <EOL> r = self . parse ( ) <EOL> self . cleanup ( ) <EOL> return r <EOL> def open ( self ) : <EOL> """<STR_LIT>""" <EOL> self . id , self . stdin , self . out , self . err = self . node . popen ( ( self . args ) ) <EOL> def parse ( self ) : <EOL> """<STR_LIT>""" <EOL> return None <EOL> def cleanup ( self ) : <EOL> """<STR_LIT>""" <EOL> self . stdin . close ( ) <EOL> self . out . close ( ) <EOL> self . err . close ( ) <EOL> tmp = self . id . wait ( ) <EOL> if tmp : <EOL> self . warn ( "<STR_LIT>" , tmp ) <EOL> class VtyshCmd ( Cmd ) : <EOL> """<STR_LIT>""" <EOL> def open ( self ) : <EOL> args = ( "<STR_LIT>" , "<STR_LIT:-c>" , self . args ) <EOL> self . id , self . stdin , self . out , self . err = self . node . popen ( ( args ) ) <EOL> class Ospf6NeighState ( VtyshCmd ) : <EOL> """<STR_LIT>""" <EOL> args = "<STR_LIT>" <EOL> def parse ( self ) : <EOL> self . out . readline ( ) <EOL> nbrlist = [ ] <EOL> for line in self . out : <EOL> field = line . split ( ) <EOL> nbr = field [ <NUM_LIT:0> ] <EOL> state = field [ <NUM_LIT:3> ] . split ( "<STR_LIT:/>" ) [ <NUM_LIT:0> ] <EOL> if not state . lower ( ) in ( "<STR_LIT>" , "<STR_LIT>" ) : <EOL> self . warn ( "<STR_LIT>" % ( nbr , state ) ) <EOL> nbrlist . append ( nbr ) <EOL> if len ( nbrlist ) == <NUM_LIT:0> : <EOL> self . warn ( "<STR_LIT>" ) <EOL> if self . verbose : <EOL> self . info ( "<STR_LIT>" % ( self . node . routerid , len ( nbrlist ) ) ) <EOL> return nbrlist <EOL> class Ospf6MdrLevel ( VtyshCmd ) : <EOL> """<STR_LIT>""" <EOL> args = "<STR_LIT>" <EOL> def parse ( self ) : <EOL> line = self . out . readline ( ) <EOL> field = line . split ( ) <EOL> mdrlevel = field [ <NUM_LIT:4> ] <EOL> if not mdrlevel in ( "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ) : <EOL> self . warn ( "<STR_LIT>" % mdrlevel ) <EOL> if self . verbose : <EOL> self . info ( "<STR_LIT>" % ( self . node . routerid , mdrlevel ) ) <EOL> return mdrlevel <EOL> class Ospf6Database ( VtyshCmd ) : <EOL> """<STR_LIT>""" <EOL> args = "<STR_LIT>" <EOL> def parse ( self ) : <EOL> db = "<STR_LIT>" <EOL> for line in self . out : <EOL> field = line . split ( ) <EOL> if len ( field ) < <NUM_LIT:8> : <EOL> continue <EOL> filtered = field [ : <NUM_LIT:3> ] + field [ <NUM_LIT:4> : <NUM_LIT:7> ] <EOL> db += "<STR_LIT:U+0020>" . join ( filtered ) + "<STR_LIT:\n>" <EOL> return db <EOL> class ZebraRoutes ( VtyshCmd ) : <EOL> """<STR_LIT>""" <EOL> args = "<STR_LIT>" <EOL> def parse ( self ) : <EOL> for i in xrange ( <NUM_LIT:0> , <NUM_LIT:3> ) : <EOL> self . out . readline ( ) <EOL> r = [ ] <EOL> prefix = None <EOL> for line in self . out : <EOL> field = line . split ( ) <EOL> if len ( field ) < <NUM_LIT:1> : <EOL> continue <EOL> elif field [ <NUM_LIT:0> ] [ : <NUM_LIT:2> ] == "<STR_LIT>" : <EOL> prefix = field [ <NUM_LIT:1> ] <EOL> metric = field [ <NUM_LIT:2> ] . split ( "<STR_LIT:/>" ) [ <NUM_LIT:1> ] [ : - <NUM_LIT:1> ] <EOL> if field [ <NUM_LIT:0> ] [ <NUM_LIT:2> : ] != "<STR_LIT:*>" : <EOL> continue <EOL> if field [ <NUM_LIT:3> ] == "<STR_LIT>" : <EOL> gw = field [ <NUM_LIT:4> ] [ : - <NUM_LIT:1> ] <EOL> else : <EOL> gw = field [ <NUM_LIT:6> ] [ : - <NUM_LIT:1> ] <EOL> r . append ( Route ( prefix , gw , metric ) ) <EOL> prefix = None <EOL> elif prefix and field [ <NUM_LIT:0> ] == "<STR_LIT:*>" : <EOL> gw = field [ <NUM_LIT:2> ] [ : - <NUM_LIT:1> ] <EOL> r . append ( Route ( prefix , gw , metric ) ) <EOL> prefix = None <EOL> if len ( r ) == <NUM_LIT:0> : <EOL> self . warn ( "<STR_LIT>" ) <EOL> if self . verbose : <EOL> self . info ( "<STR_LIT>" % ( self . node . routerid , len ( r ) ) ) <EOL> return r <EOL> class KernelRoutes ( Cmd ) : <EOL> """<STR_LIT>""" <EOL> args = ( "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ) <EOL> def parse ( self ) : <EOL> r = [ ] <EOL> prefix = None <EOL> for line in self . out : <EOL> field = line . split ( ) <EOL> if field [ <NUM_LIT:0> ] == "<STR_LIT>" : <EOL> if not prefix : <EOL> continue <EOL> else : <EOL> prefix = field [ <NUM_LIT:0> ] <EOL> metric = field [ - <NUM_LIT:1> ] <EOL> tmp = prefix . split ( "<STR_LIT:/>" ) <EOL> if len ( tmp ) < <NUM_LIT:2> : <EOL> prefix += "<STR_LIT>" <EOL> if field [ <NUM_LIT:1> ] == "<STR_LIT>" : <EOL> continue <EOL> gw = field [ <NUM_LIT:2> ] <EOL> r . append ( Route ( prefix , gw , metric ) ) <EOL> prefix = None <EOL> if len ( r ) == <NUM_LIT:0> : <EOL> self . warn ( "<STR_LIT>" ) <EOL> if self . verbose : <EOL> self . info ( "<STR_LIT>" % ( self . node . routerid , len ( r ) ) ) <EOL> return r <EOL> def main ( ) : <EOL> usagestr = "<STR_LIT>" <EOL> parser = optparse . OptionParser ( usage = usagestr ) <EOL> parser . set_defaults ( numnodes = <NUM_LIT:10> , linkprob = <NUM_LIT> , delay = <NUM_LIT:20> , seed = None ) <EOL> parser . add_option ( "<STR_LIT>" , "<STR_LIT>" , dest = "<STR_LIT>" , type = int , <EOL> help = "<STR_LIT>" ) <EOL> parser . add_option ( "<STR_LIT>" , "<STR_LIT>" , dest = "<STR_LIT>" , type = float , <EOL> help = "<STR_LIT>" ) <EOL> parser . add_option ( "<STR_LIT>" , "<STR_LIT>" , dest = "<STR_LIT>" , type = float , <EOL> help = "<STR_LIT>" ) <EOL> parser . add_option ( "<STR_LIT>" , "<STR_LIT>" , dest = "<STR_LIT>" , type = int , <EOL> help = "<STR_LIT>" ) <EOL> parser . add_option ( "<STR_LIT>" , "<STR_LIT>" , dest = "<STR_LIT>" , <EOL> action = "<STR_LIT:store_true>" , help = "<STR_LIT>" ) <EOL> parser . add_option ( "<STR_LIT>" , "<STR_LIT>" , dest = "<STR_LIT>" , type = str , <EOL> help = "<STR_LIT>" ) <EOL> def usage ( msg = None , err = <NUM_LIT:0> ) : <EOL> sys . stdout . write ( "<STR_LIT:\n>" ) <EOL> if msg : <EOL> sys . stdout . write ( msg + "<STR_LIT>" ) <EOL> parser . print_help ( ) <EOL> sys . exit ( err ) <EOL> ( options , args ) = parser . parse_args ( ) <EOL> if options . numnodes < <NUM_LIT:2> : <EOL> usage ( "<STR_LIT>" % options . numnodes ) <EOL> if options . linkprob <= <NUM_LIT:0.0> or options . linkprob > <NUM_LIT:1.0> : <EOL> usage ( "<STR_LIT>" % options . linkprob ) <EOL> if options . delay < <NUM_LIT:0.0> : <EOL> usage ( "<STR_LIT>" % options . delay ) <EOL> for a in args : <EOL> sys . stderr . write ( "<STR_LIT>" % a ) <EOL> if options . seed : <EOL> random . seed ( options . seed ) <EOL> me = ManetExperiment ( options = options , start = datetime . datetime . now ( ) ) <EOL> me . info ( "<STR_LIT>" % ( options . numnodes , options . linkprob ) ) <EOL> me . topology ( options . numnodes , options . linkprob ) <EOL> me . info ( "<STR_LIT>" % options . delay ) <EOL> time . sleep ( options . delay ) <EOL> me . info ( "<STR_LIT>" ) <EOL> me . checknodes ( ) <EOL> me . info ( "<STR_LIT>" ) <EOL> me . info ( "<STR_LIT>" % ( datetime . datetime . now ( ) - me . start ) ) <EOL> me . logend ( ) <EOL> return me <EOL> if __name__ == "<STR_LIT:__main__>" : <EOL> me = main ( ) </s>
