Example #1
0
 def update(self, bss, iface):
     assert bss.ssid == self.ssid
     assert bss.bssid == self.bssid
     if self.frequency != bss.frequency:
         print "Frequency for bss %s, %s has changed from %i to %i MHz."%(mac_addr.pretty(bss.bssid), bss.ssid, self.frequency, bss.frequency) # FIXME
     self.frequency = bss.frequency
     self.by_iface[iface] = bss
Example #2
0
class WirelessInterface(DhcpInterface):
    def __init__(self, iface, tableid):
        DhcpInterface.__init__(self, iface, tableid)
        self.wifi = pythonwifi.iwlibs.Wireless(iface)
        self.iwinfo = pythonwifi.iwlibs.WirelessInfo(iface)
        self.radio_sm = radio_sm.radio_sm(iface)
        self.ping_monitor = ping_tester.PingMonitor(self)
        self.had_exception_last_time = False

    def _update_specialized(self):
        has_link = self.status > IFSTATE.LINK_ADDR
        had_exception_this_time = False
        try:
            self.essid = self.wifi.getEssid()
            self.diags.append(('ESSID', self.essid))
        except Exception, e:
            if has_link:
                had_exception_this_time = True
                if self.had_exception_last_time:
                    traceback.print_exc(10)
                    print
            self.diags.append(('ESSID', 'Error collecting data.'))
            self.essid = "###ERROR-COLLECTING-DATA###"

        try:
            self.bssid = mac_addr.pretty(self.wifi.getAPaddr())
            self.diags.append(('BSSID', self.bssid))
        except Exception, e:
            if has_link:
                had_exception_this_time = True
                if self.had_exception_last_time:
                    traceback.print_exc(10)
                    print
            self.bssid = "00:00:00:00:00:00"
            self.diags.append(('BSSID', 'Error collecting data.'))
Example #3
0
 def _log_associations(self, iface, old_state, new_state):
     if new_state:
         print >> radio_manager_decisions, "--> Associated to %s on %s."%(mac_addr.pretty(new_state.bssid), iface.iface)
     elif new_state == radio.Associating:
         print >> radio_manager_decisions, "--> Associating on %s."%iface.iface
     elif new_state == radio.Unassociated:
         print >> radio_manager_decisions, "--> Unassociated on %s."%iface.iface
     else: 
         print >> radio_manager_decisions, "--> ERROR!! Unknown association state %s on %s."%(new_state, iface.iface)
Example #4
0
 def update(self, bss, iface):
     assert bss.ssid == self.ssid
     assert bss.bssid == self.bssid
     if self.frequency != bss.frequency:
         print "Frequency for bss %s, %s has changed from %i to %i MHz." % (
             mac_addr.pretty(bss.bssid),
             bss.ssid,
             self.frequency,
             bss.frequency,
         )  # FIXME
     self.frequency = bss.frequency
     self.by_iface[iface] = bss
Example #5
0
 def _log_associations(self, iface, old_state, new_state):
     if new_state:
         print >> radio_manager_decisions, "--> Associated to %s on %s." % (
             mac_addr.pretty(new_state.bssid),
             iface.iface,
         )
     elif new_state == radio.Associating:
         print >> radio_manager_decisions, "--> Associating on %s." % iface.iface
     elif new_state == radio.Unassociated:
         print >> radio_manager_decisions, "--> Unassociated on %s." % iface.iface
     else:
         print >> radio_manager_decisions, "--> ERROR!! Unknown association state %s on %s." % (
             new_state,
             iface.iface,
         )
Example #6
0
 def _check_cur_bss(self, iface):
     """Makes sure that the current bss satisfies forcing constraints."""
     #print "_check_cur_bss"
     cur_bss = iface.radio_sm.associated.get()
     if not cur_bss:
         return
     if not self.check_bss_matches_forcing(cur_bss):
         print iface.iface, "associated to", cur_bss.ssid, mac_addr.pretty(cur_bss.bssid), cur_bss.frequency
         print "but want", self.forced_ssid, self.forced_ssid, self.forced_band
         print "Unassociating because bss does not match requirements."
         iface.radio_sm.unassociate()
         return
     if not self.check_iface_matches_forcing(iface):
         print "Unassociating %s because interface forced to %s"%(iface, self.forced_iface)
         iface.radio_sm.unassociate()
         return
Example #7
0
 def _check_cur_bss(self, iface):
     """Makes sure that the current bss satisfies forcing constraints."""
     # print "_check_cur_bss"
     cur_bss = iface.radio_sm.associated.get()
     if not cur_bss:
         return
     if not self.check_bss_matches_forcing(cur_bss):
         print iface.iface, "associated to", cur_bss.ssid, mac_addr.pretty(cur_bss.bssid), cur_bss.frequency
         print "but want", self.forced_ssid, self.forced_ssid, self.forced_band
         print "Unassociating because bss does not match requirements."
         iface.radio_sm.unassociate()
         return
     if not self.check_iface_matches_forcing(iface):
         print "Unassociating %s because interface forced to %s" % (iface, self.forced_iface)
         iface.radio_sm.unassociate()
         return
Example #8
0
    def update(self, bsses, iface):
        for bss in bsses:
            id = (bss.ssid, bss.bssid)
            if id not in self.bsses:
                self.bsses[id] = Bss(bss)
            self.bsses[id].update(bss, iface)
            self.freq_list.hit(bss.frequency, bss.stamp.to_sec())

        if True:  # Gives an overview of currently known bsses.
            all = self.bsses.items()
            all.sort(key=lambda (x, y): (y.frequency, x))
            now = time.time()
            print >> known_bsses_log, "\033[2J\033[0;0H"
            print >> known_bsses_log, "Known BSSes bsses:"
            for _, bss in all:
                print >> known_bsses_log, mac_addr.pretty(bss.bssid), "%20.20s" % bss.ssid, bss.frequency,
                ifaces = bss.by_iface.keys()
                ifaces.sort()
                min_stamp = now - max(bss.by_iface.itervalues(), key=lambda bss: bss.stamp).stamp.to_sec()
                max_level = max(bss.by_iface.itervalues(), key=lambda bss: bss.level).level
                print >> known_bsses_log, "%5.1f/%3i" % (min_stamp, max_level),
                for iface in ifaces:
                    print >> known_bsses_log, iface.iface, "%5.1f/%3i" % (
                        now - bss.by_iface[iface].stamp.to_sec(),
                        bss.by_iface[iface].level,
                    ),
                print >> known_bsses_log
            print >> known_bsses_log

            fl = self.freq_list.frequencies.keys()
            fl.sort()
            for f in fl:
                fc = self.freq_list.frequencies[f]
                if fc.last_hit:
                    print >> known_bsses_log, f, "%5.1f" % (now - fc.last_hit),
                else:
                    print >> known_bsses_log, f, "never",
                print >> known_bsses_log, "%5.1f" % (fc.next_scan_time - now),
                for iface in fc.next_scan_time_by_iface:
                    print >> known_bsses_log, "%s %5.1f" % (iface.iface, now - fc.next_scan_time_by_iface[iface]),
                print >> known_bsses_log
            print >> known_bsses_log
Example #9
0
    def update(self, bsses, iface):
        for bss in bsses:
            id = (bss.ssid, bss.bssid)
            if id not in self.bsses:
                self.bsses[id] = Bss(bss)
            self.bsses[id].update(bss, iface)
            self.freq_list.hit(bss.frequency, bss.stamp.to_sec())

        if True: # Gives an overview of currently known bsses.
            all = self.bsses.items()
            all.sort(key=lambda (x,y):(y.frequency, x))
            now = time.time()
            print >> known_bsses_log, "\033[2J\033[0;0H"
            print >> known_bsses_log, "Known BSSes bsses:"
            for _, bss in all:
                print >> known_bsses_log, mac_addr.pretty(bss.bssid), "%20.20s"%bss.ssid, bss.frequency,
                ifaces = bss.by_iface.keys()
                ifaces.sort()
                min_stamp = now - max(bss.by_iface.itervalues(), key = lambda bss: bss.stamp).stamp.to_sec()
                max_level = max(bss.by_iface.itervalues(), key = lambda bss: bss.level).level
                print >> known_bsses_log, "%5.1f/%3i"%(min_stamp,max_level),
                for iface in ifaces:
                    print >> known_bsses_log, iface.iface, "%5.1f/%3i"%(now - bss.by_iface[iface].stamp.to_sec(), bss.by_iface[iface].level),
                print >> known_bsses_log 
            print >> known_bsses_log 

            fl = self.freq_list.frequencies.keys()
            fl.sort()
            for f in fl:
                fc = self.freq_list.frequencies[f]
                if fc.last_hit:
                    print >> known_bsses_log, f, "%5.1f"%(now - fc.last_hit),
                else:
                    print >> known_bsses_log, f, "never",
                print >> known_bsses_log, "%5.1f"%(fc.next_scan_time - now),
                for iface in fc.next_scan_time_by_iface:
                    print >> known_bsses_log, "%s %5.1f"%(iface.iface, now - fc.next_scan_time_by_iface[iface]),
                print >> known_bsses_log
            print >> known_bsses_log
Example #10
0
    def update(self):
        """Called in the main update cycle after all the scores have been
        computed. Decides which interfaces should be activated."""

        def iface_score(iface):
            """Used to decide what to activate and disactivate."""
            return iface.prescore

        now = time.time()
        
        active = set()
        verified = set()
        for iface in self.interfaces:
            iface.active = iface.radio_sm.is_active.get()
            if iface.active:
                active.add(iface)
            if iface.ping_monitor.is_verified.get():
                verified.add(iface)
        inactive_verified = verified - active

        # Only keep one active interface.
        if active:
            self.best_active = max(active, key = iface_score)
        else:
            self.best_active = None
        if len(active) > 1:
            for iface in active:
                if iface != self.best_active:
                    iface.radio_sm.activate_request.set(False)
                    print >> radio_manager_decisions, "XXX Disactivating %s because %s is active and better."%(iface.iface, self.best_active.iface)

        # Activate a verified interface if it is better than the current
        # active interface.
        if inactive_verified:
            #print >> radio_manager_decisions, "Active interface selection."
            #for iface in verified:
            #    print >> radio_manager_decisions, iface.iface, iface_score(iface), iface in active
            best_inactive_verified = max(inactive_verified, key = iface_score)
            if not self.best_active or iface_score(best_inactive_verified) > iface_score(self.best_active) + self.activate_hysteresis:
                if not self.best_active:
                    print >> radio_manager_decisions, "XXX Activating %s because no current best active."%best_inactive_verified.iface
                else:
                    print >> radio_manager_decisions, "XXX Activating %s because it is better than %s."%(best_inactive_verified.iface, self.best_active.iface)
                best_inactive_verified.radio_sm.activate_request.set(True)

        # Keep a closer watch on the most relevant frequencies.
        #print self.scan_manager.bss_list.bsses
        #print [candidate_bsses]
        candidate_bsses = filter(self.check_bss_matches_forcing, 
                self.scan_manager.bss_list.bsses.itervalues())
        expiry_time = now - self.hot_bss_expiry_time
        candidate_bsses.sort(key = lambda bss: self.desirability(bss, expiry_time), reverse = True)
        #print [candidate_bsses]
        periods = dict((f, self.scan_manager.frequencies.scan_period_cold) 
                for f in self.scan_manager.frequencies.frequencies)
        hot_frequencies = 0
        print >> scan_periods_log, "\033[2J\033[0;0H"
        print >> scan_periods_log, "Candidate bsses:"
        for bss in candidate_bsses:
            print >> scan_periods_log, bss.ssid, mac_addr.pretty(bss.bssid), bss.frequency, self.desirability(bss, expiry_time), now - bss.last_seen()
            if hot_frequencies < self.max_hot_frequencies and periods[bss.frequency] != self.scan_period_hot:
                hot_frequencies += 1
                p = self.scan_period_hot
            elif bss.last_seen(iface) > now - self.warm_bss_expiry_time:
                p = self.scan_period_warm
            periods[bss.frequency] = min(periods[bss.frequency], p)
        print >> scan_periods_log, "Frequencies"
        #for f in self.scan_manager.frequencies.frequencies:
        freqs = [ f for f in self.scan_manager.frequencies.frequencies if check_band(f, self.forced_band) ]
        freqs.sort()
        for f in freqs:
            print >> scan_periods_log, f, periods[f], self.scan_manager.frequencies.frequencies[f].next_scan_time - now
            self.scan_manager.frequencies.set_freq_period(f, periods[f])
Example #11
0
    def _new_scan_data(self):
        print "_new_scan_data"
        #print "\033[2J"
        #print "\033[0;0H"
        now = time.time()
        if now < self.initial_inhibit_end:
            print "inhibited"
            return
        for iface in self.interfaces:
            if not self.check_iface_matches_forcing(iface):
                continue

            cur_assoc = iface.radio_sm.associated.get()
            #print "OK to try reassociating?", iface.iface, iface.radio_sm.scanning_enabled.get(), cur_assoc
            if cur_assoc and iface == self.best_active:
                continue

            if iface.radio_sm.scanning_enabled.get() and cur_assoc != radio.Associating:
                # Pick the best bss for this interface.
                candidate_bsses = filter(self.check_bss_matches_forcing, 
                        self.scan_manager.bss_list.bsses.itervalues())
                #print "Candidate bsses:", [mac_addr.pretty(bss.bssid) for bss in candidate_bsses]
                if candidate_bsses:
                    expiry_time = now - self.bss_expiry_time
                    best_bss = max(candidate_bsses, key = lambda bss: self.desirability(bss, expiry_time, iface))
                    if iface not in best_bss.by_iface or best_bss.by_iface[iface].stamp.to_sec() < expiry_time:
                        print "Best bss is expired.", mac_addr.pretty(best_bss.bssid)
                        best_bss = None
                else:
                    print "No candidate bsses."
                    best_bss = None
                if best_bss is None:
                    print "No candidate bsses or expired."
                    #print bool(candidate_bsses), [candidate_bsses]
                    #print self.scan_manager.bss_list.bsses.values()
                    continue

                best_desirability = self.desirability(best_bss, expiry_time, iface)
                print "Best bss:", mac_addr.pretty(best_bss.bssid), best_desirability

                if cur_assoc:
                    # Are we already associated to the best AP?
                    if make_id(cur_assoc) == best_bss.id:
                        print "Already associated to best bss."
                        continue

                    # Compute desirability for current association.
                    cur_id = make_id(cur_assoc)
                    if cur_id in self.scan_manager.bss_list.bsses:
                        cur_bss = self.scan_manager.bss_list.bsses[make_id(cur_assoc)]
                        cur_desirability = self.desirability(cur_bss, expiry_time, iface)
                    else:
                        cur_desirability = -1e1000
                    
                    # Is the best ap better enough than the current best?
                    if cur_desirability + self.reassociate_hysteresis > best_desirability:
                        print "Best bss not over hysteresis threshold: %s %f > %s %f"%(mac_addr.pretty(cur_assoc.bssid), cur_desirability, mac_addr.pretty(best_bss.bssid), self.desirability(best_bss))
                        continue

                # Let's associate
                print >> radio_manager_decisions, "Associating to %s (%f) on %s"%(mac_addr.pretty(best_bss.bssid), best_desirability, iface.iface),
                if cur_assoc:
                    print >> radio_manager_decisions, "from %s (%f)"%(mac_addr.pretty(cur_assoc.bssid), cur_desirability)
                else:
                    print >> radio_manager_decisions, "from unassociated"
                iface.radio_sm.associate_request.trigger(best_bss.id)
                self.iface_associations[iface] = best_bss.id
Example #12
0
    def update(self):
        """Called in the main update cycle after all the scores have been
        computed. Decides which interfaces should be activated."""

        def iface_score(iface):
            """Used to decide what to activate and disactivate."""
            return iface.prescore

        now = time.time()

        active = set()
        verified = set()
        for iface in self.interfaces:
            iface.active = iface.radio_sm.is_active.get()
            if iface.active:
                active.add(iface)
            if iface.ping_monitor.is_verified.get():
                verified.add(iface)
        inactive_verified = verified - active

        # Only keep one active interface.
        if active:
            self.best_active = max(active, key=iface_score)
        else:
            self.best_active = None
        if len(active) > 1:
            for iface in active:
                if iface != self.best_active:
                    iface.radio_sm.activate_request.set(False)
                    print >> radio_manager_decisions, "XXX Disactivating %s because %s is active and better." % (
                        iface.iface,
                        self.best_active.iface,
                    )

        # Activate a verified interface if it is better than the current
        # active interface.
        if inactive_verified:
            # print >> radio_manager_decisions, "Active interface selection."
            # for iface in verified:
            #    print >> radio_manager_decisions, iface.iface, iface_score(iface), iface in active
            best_inactive_verified = max(inactive_verified, key=iface_score)
            if (
                not self.best_active
                or iface_score(best_inactive_verified) > iface_score(self.best_active) + self.activate_hysteresis
            ):
                if not self.best_active:
                    print >> radio_manager_decisions, "XXX Activating %s because no current best active." % best_inactive_verified.iface
                else:
                    print >> radio_manager_decisions, "XXX Activating %s because it is better than %s." % (
                        best_inactive_verified.iface,
                        self.best_active.iface,
                    )
                best_inactive_verified.radio_sm.activate_request.set(True)

        # Keep a closer watch on the most relevant frequencies.
        # print self.scan_manager.bss_list.bsses
        # print [candidate_bsses]
        candidate_bsses = filter(self.check_bss_matches_forcing, self.scan_manager.bss_list.bsses.itervalues())
        expiry_time = now - self.hot_bss_expiry_time
        candidate_bsses.sort(key=lambda bss: self.desirability(bss, expiry_time), reverse=True)
        # print [candidate_bsses]
        periods = dict(
            (f, self.scan_manager.frequencies.scan_period_cold) for f in self.scan_manager.frequencies.frequencies
        )
        hot_frequencies = 0
        print >> scan_periods_log, "\033[2J\033[0;0H"
        print >> scan_periods_log, "Candidate bsses:"
        for bss in candidate_bsses:
            print >> scan_periods_log, bss.ssid, mac_addr.pretty(bss.bssid), bss.frequency, self.desirability(
                bss, expiry_time
            ), now - bss.last_seen()
            if hot_frequencies < self.max_hot_frequencies and periods[bss.frequency] != self.scan_period_hot:
                hot_frequencies += 1
                p = self.scan_period_hot
            elif bss.last_seen(iface) > now - self.warm_bss_expiry_time:
                p = self.scan_period_warm
            periods[bss.frequency] = min(periods[bss.frequency], p)
        print >> scan_periods_log, "Frequencies"
        # for f in self.scan_manager.frequencies.frequencies:
        freqs = [f for f in self.scan_manager.frequencies.frequencies if check_band(f, self.forced_band)]
        freqs.sort()
        for f in freqs:
            print >> scan_periods_log, f, periods[f], self.scan_manager.frequencies.frequencies[f].next_scan_time - now
            self.scan_manager.frequencies.set_freq_period(f, periods[f])
Example #13
0
    def _new_scan_data(self):
        print "_new_scan_data"
        # print "\033[2J"
        # print "\033[0;0H"
        now = time.time()
        if now < self.initial_inhibit_end:
            print "inhibited"
            return
        for iface in self.interfaces:
            if not self.check_iface_matches_forcing(iface):
                continue

            cur_assoc = iface.radio_sm.associated.get()
            # print "OK to try reassociating?", iface.iface, iface.radio_sm.scanning_enabled.get(), cur_assoc
            if cur_assoc and iface == self.best_active:
                continue

            if iface.radio_sm.scanning_enabled.get() and cur_assoc != radio.Associating:
                # Pick the best bss for this interface.
                candidate_bsses = filter(self.check_bss_matches_forcing, self.scan_manager.bss_list.bsses.itervalues())
                # print "Candidate bsses:", [mac_addr.pretty(bss.bssid) for bss in candidate_bsses]
                if candidate_bsses:
                    expiry_time = now - self.bss_expiry_time
                    best_bss = max(candidate_bsses, key=lambda bss: self.desirability(bss, expiry_time, iface))
                    if iface not in best_bss.by_iface or best_bss.by_iface[iface].stamp.to_sec() < expiry_time:
                        print "Best bss is expired.", mac_addr.pretty(best_bss.bssid)
                        best_bss = None
                else:
                    print "No candidate bsses."
                    best_bss = None
                if best_bss is None:
                    print "No candidate bsses or expired."
                    # print bool(candidate_bsses), [candidate_bsses]
                    # print self.scan_manager.bss_list.bsses.values()
                    continue

                best_desirability = self.desirability(best_bss, expiry_time, iface)
                print "Best bss:", mac_addr.pretty(best_bss.bssid), best_desirability

                if cur_assoc:
                    # Are we already associated to the best AP?
                    if make_id(cur_assoc) == best_bss.id:
                        print "Already associated to best bss."
                        continue

                    # Compute desirability for current association.
                    cur_id = make_id(cur_assoc)
                    if cur_id in self.scan_manager.bss_list.bsses:
                        cur_bss = self.scan_manager.bss_list.bsses[make_id(cur_assoc)]
                        cur_desirability = self.desirability(cur_bss, expiry_time, iface)
                    else:
                        cur_desirability = -1e1000

                    # Is the best ap better enough than the current best?
                    if cur_desirability + self.reassociate_hysteresis > best_desirability:
                        print "Best bss not over hysteresis threshold: %s %f > %s %f" % (
                            mac_addr.pretty(cur_assoc.bssid),
                            cur_desirability,
                            mac_addr.pretty(best_bss.bssid),
                            self.desirability(best_bss),
                        )
                        continue

                # Let's associate
                print >> radio_manager_decisions, "Associating to %s (%f) on %s" % (
                    mac_addr.pretty(best_bss.bssid),
                    best_desirability,
                    iface.iface,
                ),
                if cur_assoc:
                    print >> radio_manager_decisions, "from %s (%f)" % (
                        mac_addr.pretty(cur_assoc.bssid),
                        cur_desirability,
                    )
                else:
                    print >> radio_manager_decisions, "from unassociated"
                iface.radio_sm.associate_request.trigger(best_bss.id)
                self.iface_associations[iface] = best_bss.id