def instr_change(track, ptr, ev): # (ev), ev2, value # ev=width, ev2=type if ev == 0xA4: get = ptr.u8 LOG.info('instr_change u8') elif ev == 0xAC: get = ptr.u16 LOG.info('instr_change u16') else: assert False ev2 = ptr.u8() value = get() if ev2 == 0x20: ev2 = 'bank' elif ev2 == 0x21: ev2 = 'patch' else: LOG.warning('[instr %s] Unknown type %02X value=%02X', b2h(ev), ev2, value) ev2 = 'unknown %s' % b2h(ev2) track.insert(InstrChange, ev2=ev2, value=value)
def checkRequirementConfig(d, d_req): config = d['config'] fibbing_ctrl = config.get('fibbing-controller') hosts_link = config.get('hosts-link') links = config.get('links') main_controller = config.get('main-controller') ospf_links = config.get('ospf-links') routers = config.get('routers') conf = d_req['config'] link = conf["link"] Error = False # Set up the Controller requirements for x in link: # set up router connected to dest as last one of the path rs = x.get('requirement')[-1] if rs == '*': LOG.error('The Path cannot end with the * router') Error = True continue ds = str(x.get('dest')) R = () for r in x.get('requirement'): R += (str(r), ) IS_OK = False for dsr in hosts_link: host = dsr.get('host') router = dsr.get('router') # check if dest is indeed connected to router # in the topology if host.get('name') == ds and router.get('name') == rs: IS_OK = True if not IS_OK: LOG.warning('Destination ' + ds + ' is not connected to ' + ds) if str(x.get('status')) == SCHED: start_hour = x.get('scheduled').get('start-hour') end_hour = x.get('scheduled').get('end-hour') tmp = compare(start_hour, end_hour) if (tmp == False): Error = True LOG.error('start-hour must be smaller than end-hour') if str(x.get('status')) == SCHED and\ (str(x.get('scheduled').get('type')) == BAND or\ str(x.get('scheduled').get('type')) == BACK): if not x.get('scheduled').get('link').get('from') or \ not x.get('scheduled').get('link').get('to') : Error = True LOG.error( 'router from and to of link bandwidth or backup not set') Error = check_path(links, Error, link) return Error
async def download(self): retries = 0 while retries < 5: retries += 1 try: await self._download() except asyncio.TimeoutError: LOG.warning('Timed out connecting with: {}'.format(self.host))
def from_ptr(cls, ptr: Pointer): d = cls() d.tracknum = ptr.u8() d.addr = ptr.u24() LOG.warning('Track %d', d.tracknum) return d
async def download(self): retries = 0 while retries < 5: retries = retries + 1 try: await self._download() except asyncio.TimeoutError: LOG.warning("Timed out connection with host {}".format( self.host))
def checkRequirementConfig(network, requirement): """ Check the config received from the ConfD agent, concerning the requirement Input : network is the dictionary that contains the network config, requirement is the dictionary that contains the requirements config, return False if no Error was found, retrun True if at least one Error was found """ Error = False conf = requirement['config'] link = conf["link"] for x in link: if x.get('requirement')[-1] == '*': LOG.error('Path of requirement cannnot end by *') continue rs = x.get('requirement')[-1] ds = str(x.get('dest')) IS_OK = False for lk in network.get('link'): src = lk.get('src') dest = lk.get('dest') # check if dest is indeed connected to router # in the topology if (src.get('name') == ds and dest.get('name') == rs)\ or (src.get('name') == rs and dest.get('name') == ds) : IS_OK = True if not IS_OK: LOG.warning('Destination ' + ds + ' is not connected to ' + rs) if str(x.get('status')) == SCHED: start_hour = x.get('scheduled').get('start-hour') end_hour = x.get('scheduled').get('end-hour') tmp = compare(start_hour, end_hour) if (tmp == False): Error = True LOG.error('start-hour must be smaller than end-hour') if str(x.get('status')) == SCHED and\ (str(x.get('scheduled').get('type')) == BAND or\ str(x.get('scheduled').get('type')) == BACK): if not x.get('scheduled').get('link').get('from') or \ not x.get('scheduled').get('link').get('to') : Error = True LOG.error( 'router from and to of link bandwidth or backup not set') Error = check_path(network.get('link'), Error, link) return Error
def child(track, ptr): tracknum = ptr.u8() addr = ptr.u24() LOG.warning('Track %d', tracknum) # Symlink track.insert(Child, tracknum=tracknum, addr=addr ) BmsTrack(track._file, addr, tracknum, None).parse()
def after(self, track: BmsTrack): addr = self.addr hist = track._ptr.hist(addr) if hist == Visit.MIDDLE: raise OverlapError('%s %s - middle of command' % (getname(self), hex(addr))) # We are either visiting NONE or BEGIN. # Not visited: # Visit target. # Visited: # (addr) Check preconditions and apply postconditions. # Note that OldNote compares == None. if hist == Visit.NONE: track = BmsTrack(track._file, addr, None, track.note_history).parse() else: assert hist == Visit.BEGIN # **** ASSERTION **** # We will encounter issues if any touched notes differ from the original call. # TODO: We assume we're not calling into the middle of a visited section... :'( track = track._file.track_at[addr] different = (track.pre_history != track.note_history) if any(different & track.touched): LOG.error( '''Invalid call from %06X to %06X new:%s old:%s out:%s touched:%s''', track._prev_addr, addr, track.note_history, track.pre_history, track.note_history, track.touched) # endif already visited # BMS really shouldn't be touching notes, AND leaving running notes untouched... if any(track.touched): untouched = ~track.touched if any(track.pre_history.astype(bool) & untouched): LOG.warning('Function leaves running notes untouched %s %s %s', track.touched, track.pre_history, track.note_history) # Knowing that all "touched" entries entered identically... # We must apply all "touched" entries of the note history. track.note_history[track.touched] = track.note_history[track.touched]
def after(event, file: 'BmsFile', ptr: Pointer): addr = event.addr hist = ptr.hist(addr) if hist == Visit.NONE: track = BmsTrack(track._file, addr, None, track.note_history).parse() else: assert hist == Visit.BEGIN # **** ASSERTION **** # We will encounter issues if any touched notes differ from the original call. # TODO: We assume we're not calling into the middle of a visited section... :'( track = track._file.track_at[addr] different = (track.pre_history != track.note_history) if any(different & track.touched): LOG.error( '''Invalid call from %06X to %06X new:%s old:%s out:%s touched:%s''', track._prev_addr, addr, track.note_history, track.pre_history, track.note_history, track.touched) # endif already visited # BMS really shouldn't be touching notes, AND leaving running notes untouched... if any(track.touched): untouched = ~track.touched if any(track.pre_history.astype(bool) & untouched): LOG.warning('Function leaves running notes untouched %s %s %s', track.touched, track.pre_history, track.note_history) # Knowing that all "touched" entries entered identically... # We must apply all "touched" entries of the note history. track.note_history[track.touched] = track.note_history[track.touched]
def check_network(network, Error): """ return True if and Error has been detected otherwise return Error """ controller = network.get('controller') if not controller: LOG.error('A controller must be specified') Error = True if not network.get('destinations'): LOG.warning( 'Destinations should be configured to specify requirements') ips = {} routerids = {} routerospf = [] hosts = [] for router in network.get('routers'): if router.get('ospf6').get('enable') and\ not router.get('ospf6').get('router-id') : LOG.error('If ospf is enable router %s must have a router-id ' % router.get('name')) Error = True if not router.get('ospf6').get('enable'): hosts.append(router.get('name')) if router.get('ospf6').get('enable') and\ routerids.get(router.get('ospf6').get('router-id') ) : LOG.error('routerid should be unique %s' % router.get('ospf6').get('router-id')) LOG.info('already found here %s ' % routerids.get(router.get('ospf6').get('router-id'))) Error = True else: routerids[router.get('ospf6').get('router-id')] = router.get( 'name') routerospf.append(router.get('name')) if not router.get('loopback-addr'): LOG.error('router %s have a loopback-addr' % router.get('name')) Error = True else: if ips.get(router.get('loopback-addr')): LOG.error('loopback-addr must be unique %s' % router.get('loopback-addr')) LOG.info('already found here %s ' % ips.get(router.get('loopback-addr'))) Error = True else: ips[router.get('loopback-addr')] = router.get('name') ospfconfig = {} host_link = {} ospf_link = [] link_name_map = {} for link in network.get('link'): link_name_map[link.get('name')] = link for link in network.get('ospf-links'): l = link_name_map[link.get('name')] ospf_link.append(link.get('name')) for intf in [link.get('src'), link.get('dest')]: area = intf.get('ospf').get('area') if not ospfconfig or ospfconfig.get(area): ospfconfig[area] = { 'area': intf.get('ospf').get('area'), 'hello-interval': intf.get('ospf').get('hello-interval'), 'dead-interval': intf.get('ospf').get('dead-interval'), } else: if ospfconfig.get(area).get('hello-interval') != intf.get( 'ospf').get('hello-interval'): LOG.error( 'hello-interval should be the same for the same area %s' % area) Error = True if ospfconfig.get(area).get('hello-interval') != intf.get( 'ospf').get('hello-interval'): LOG.error( 'hello-interval should be the same for the same area %s' % area) Error = True if l.get('src').get('name') not in routerospf: LOG.error( 'To enable ospf on a link both router must have ospf enable %s' % l.get('src').get('name')) Error = True if l.get('dest').get('name') not in routerospf: LOG.error( 'To enable ospf on a link both router must have ospf enable %s' % l.get('dest').get('name')) Error = True for link in network.get('link'): src = link.get('src') dest = link.get('dest') if not src.get('name'): LOG.error('Link must have a src ') Error = True continue if not dest.get('name'): LOG.error('Link must have a dest ') Error = True continue if not src.get('ip'): LOG.error('Link must have an ip address') Error = True continue if not dest.get('ip'): LOG.error('Link must have an ip address') Error = True continue if ips.get(src.get('ip')): LOG.error('ip address should be different %s than loopback-addr' % src.get('ip')) LOG.info('already found %s' % ips.get(src.get('ip'))) Error = True if ips.get(dest.get('ip')): LOG.error('ip address should be different %s' % dest.get('ip')) LOG.info('already found %s' % ips.get(dest.get('ip'))) Error = True if link.get('name') not in ospf_link: # checking static link if src.get('name') in hosts and src.get('name') in host_link: LOG.error( 'A router without ospf can only have one static link') Error = True else: if src.get('name') in hosts and dest.get('name') in hosts: LOG.error( 'Cannot have a static link between two router without ospf' ) Error = True else: host_link[src.get('name')] = dest.get('name') if dest.get('name') in hosts and dest.get('name') in host_link: LOG.error( 'A router without ospf can only have one static link') Error = True else: if src.get('name') in hosts and dest.get('name') in hosts: LOG.error( 'Cannot have a static link between two router without ospf' ) Error = True else: host_link[dest.get('name')] = src.get('name') return Error
def check_network(config, Error): try: fibbing_ctrl = config.get('fibbing-controller') hosts_link = config.get('hosts-link') links = config.get('links') main_controller = config.get('main-controller') ospf_links = config.get('ospf-links') routers = config.get('routers') routerid = [] ospf_router = [] for r in routers: if r.get('ospf').get('enable'): if r.get('ospf').get('router-id') in routerid: LOG.error('Router id already used %s' % r.get('ospf').get('router-id')) Error = True else: routerid.append(r.get('ospf').get('router-id')) else: LOG.warning( 'For this framework all routers must have ospf enable') ospf_router.append(r.get('name')) link_key_map = {} for link in links: if not link.get('src').get('name'): LOG.error('A link must have a src router name') Error = True if not link.get('src').get('ip'): LOG.error('A link must have a src router ip') Error = True if not link.get('dest').get('name'): LOG.error('A link must have a dest router name') Error = True if not link.get('dest').get('ip'): LOG.error('A link must have a dest router ip') Error = True link_key_map[link.get('name')] = link ospf_config = {} for o_l in ospf_links: link = link_key_map.get(o_l.get('name')) if link.get('src').get('name') not in ospf_router or \ link.get('dest').get('name') not in ospf_router: LOG.error( 'A link with ospf configured must have both src and dest with ospf enabled' ) Error = True src_o_conf = o_l.get('src').get('ospf') dest_o_conf = o_l.get('dest').get('ospf') if src_o_conf.get('area') not in ospf_config: ospf_config[src_o_conf.get('area')] = src_o_conf else: area_conf = ospf_config[src_o_conf.get('area')] if src_o_conf.get('hello-interval') != area_conf.get('hello-interval') or\ src_o_conf.get('dead-interval') != area_conf.get('dead-interval') : LOG.error( 'Hello and dead interval must be the same for the same broadcast domain' ) Error = True if dest_o_conf.get('area') not in ospf_config: ospf_config[dest_o_conf.get('area')] = dest_o_conf else: area_conf = ospf_config[dest_o_conf.get('area')] if dest_o_conf.get('hello-interval') != area_conf.get('hello-interval') or\ dest_o_conf.get('dead-interval') != area_conf.get('dead-interval') : LOG.error( 'Hello and dead interval must be the same for the same broadcast domain' ) Error = True controller_o_conf = fibbing_ctrl.get('controller-config').get('ospf') if controller_o_conf.get('area') not in ospf_config: LOG.error( 'The Fibbing controller should be in the same area of at least some other router' ) Error = True else: area_conf = ospf_config[controller_o_conf.get('area')] if controller_o_conf.get('hello-interval') != area_conf.get('hello-interval') or\ controller_o_conf.get('dead-interval') != area_conf.get('dead-interval') : LOG.error( 'Hello and dead interval must be the same for the same broadcast domain' ) Error = True if not main_controller: LOG.error( 'The host acting as the main controller must be specified') Error = True return Error except Exception as e: LOG.critical('Error :' + str(e)) Error = True return Error
def after(self, track: BmsTrack): if self.unknown != 0: LOG.warning('Track init %04X != 0x0000', unknown)
def call_jump(track, ev, ptr): jumps = {0xC4: Call, 0xC8: Jump} evtype = jumps[ev] mode = BmsSeekMode(ptr.u8()) addr = ptr.u24() track.insert(evtype, mode=mode, addr=addr) # Assert that we aren't jumping into the middle of an instruction. hist = ptr.hist(addr) if hist == Visit.MIDDLE: raise OverlapError('%s %s - middle of command' % (jumps[ev], hex(addr))) # We are either visiting NONE or BEGIN. # Jump: Visit target (if necessary), then continue. # Call # Not visited: # Visit target. # Visited: # (addr) Check preconditions and apply postconditions. # Note that OldNote compares == None. # HISTORY_MODE == 'LAZY' # **** CALL **** if hist == Visit.NONE: track = BmsTrack(track._file, addr, None, track.note_history).parse() else: assert hist == Visit.BEGIN # **** ASSERTION **** # We will encounter issues if any touched notes differ from the original call. # TODO: We assume we're not calling into the middle of a visited section... :'( track = track._file.track_at[addr] different = (track.pre_history != track.note_history) if any(different & track.touched): LOG.error( '''Invalid call from %06X to %06X new:%s old:%s out:%s touched:%s''', track._prev_addr, addr, track.note_history, track.pre_history, track.note_history, track.touched) # endif already visited # BMS really shouldn't be touching notes, AND leaving running notes untouched... if any(track.touched): untouched = ~track.touched if any(track.pre_history.astype(bool) & untouched): LOG.warning('Function leaves running notes untouched %s %s %s', track.touched, track.pre_history, track.note_history) # Knowing that all "touched" entries entered identically... # We must apply all "touched" entries of the note history. track.note_history[track.touched] = track.note_history[track.touched] # **** JUMP **** if hist == Visit.NONE: track._ptr.addr = addr else: assert hist == Visit.BEGIN
def parse(track) -> 'BmsTrack': insert = track.insert ptr = track._ptr stop = False track._prev_addr = None # type: int while 1: prev_addr = ptr.addr track._prev_addr = prev_addr ev = ptr.u8(mode=Visit.BEGIN) # **** FLOW COMMANDS if 0: pass elif ev == 0xC1: # new track track.child(ptr) elif ev == 0xFF: # end track if track.tracknum is None: raise SeqError('end_track from function') insert(EndTrack, next=False) stop = True elif ev in [0xC4, 0xC8]: # call address track.call_jump(ev, ptr) elif ev == 0xC6: # pop address if track.tracknum is not None: raise SeqError('pop from root thread') insert(Pop, next=False) stop = True # **** SPECIAL COMMANDS elif ev == 0xE7: # init track unknown = ptr.u16() # ASSERT if unknown != 0: LOG.warning('Track init %04X != 0x0000', unknown) insert(InitTrack, unknown=unknown) elif ev in [0xA4, 0xAC]: # instr change track.instr_change(ptr, ev) elif ev == 0xFE: # tick rate insert(TickRate, value=ptr.u16()) elif ev == 0xFD: # tempo insert(Tempo, value=ptr.u16()) elif ev == 0xE6: # TODO unknown unknown = ptr.u16() # ASSERT if unknown != 0: LOG.warning('WriteRemovePool %04X != 0x0000', unknown) insert(WriteRemovePool, unknown=unknown) # **** NOTES elif ev < 0x80: # note on track.note_on(ptr, ev) elif ev in range(0x81, 0x88): track.note_off(ptr, ev) # **** CONTROL CHANGES elif 0x94 <= ev <= 0x9F: track.control_change(ptr, ev) # **** DELAYS elif ev == 0x80: insert(Delay, dtime = ptr.u8()) elif ev == 0x88: insert(Delay, dtime = ptr.u16()) elif ev == 0xEA: insert(Delay, dtime = ptr.u24()) # TODO 0xCF elif ev == 0xF0: insert(Delay, dtime = ptr.vlq()) # **** FALLBACK else: text = 'unknown event %s' % b2h(ev) LOG.warning(text) insert(text) stop = True assert prev_addr in track._file.at assert track._file.at[prev_addr] is not None if stop: break # HISTORY_MODE == 'LAZY' return track