$search
00001 #! /usr/bin/env python 00002 00003 import interface_upper 00004 import ping_tester 00005 import dhcp 00006 from dhcp_apply_config import DhcpAddressSetter, DhcpRouteSetter, DhcpSourceRuleSetter 00007 import config 00008 from netlink_monitor import netlink_monitor, IFSTATE 00009 import radio_sm 00010 import traceback 00011 import pythonwifi.iwlibs 00012 import mac_addr 00013 import socket 00014 import state_publisher 00015 import ipaddr 00016 00017 class Interface: 00018 def __init__(self, iface, tableid, cfgname): 00019 self.iface = iface 00020 self.cfgname = cfgname 00021 self.prettyname = config.get_interface_parameter(self.cfgname, 'name', self.cfgname) 00022 self.active = True 00023 self.priority = config.get_interface_parameter(self.cfgname, 'priority', 0) 00024 src_rule_setter = DhcpSourceRuleSetter(iface, tableid, tableid) 00025 self.tableid = str(tableid) 00026 base_station = config.get_parameter('base_station') 00027 ping_port = config.get_parameter('ping_port') 00028 self.ping_tester = ping_tester.PingTester(iface, 20, (base_station, ping_port), src_rule_setter.state_pub) 00029 00030 def update(self, interval): 00031 self.diags = [] 00032 self.status = netlink_monitor.get_status_publisher(self.iface).get() 00033 00034 self._update_specialized() 00035 00036 (bins, latency1, latency2) = self.ping_tester.update(interval) 00037 self.ping_latency = latency2 00038 self.ping_loss = 100 - 100 * bins[0] 00039 if self.status < IFSTATE.ADDR: 00040 self.goodness = self.status - IFSTATE.ADDR 00041 self.reliability = self.status - IFSTATE.ADDR 00042 else: 00043 self.goodness = 100 * bins[0] - latency2 # Goodness is how many packets made it through then average latency. 00044 00045 if self.status < IFSTATE.LINK_ADDR: 00046 self.bssid = "NoLink" 00047 00048 class DhcpInterface(Interface): 00049 def __init__(self, iface, tableid): 00050 Interface.__init__(self, iface, tableid, iface) 00051 self.interface_upper = interface_upper.InterfaceUpper(iface) 00052 self.dhcpdata = dhcp.dhcp_client(iface) 00053 DhcpAddressSetter(iface, self.dhcpdata.binding_publisher) 00054 DhcpRouteSetter(iface, tableid, self.dhcpdata.binding_publisher) 00055 00056 # FIXME RPFilter somewhere. 00057 # Flush ip rule on interface up somewhere. 00058 00059 class WiredInterface(DhcpInterface): 00060 def __init__(self, iface, tableid): 00061 DhcpInterface.__init__(self, iface, tableid) 00062 00063 def _update_specialized(self): 00064 self.reliability = 100 00065 self.bssid = "Wired" 00066 00067 class WirelessInterface(DhcpInterface): 00068 def __init__(self, iface, tableid): 00069 DhcpInterface.__init__(self, iface, tableid) 00070 self.wifi = pythonwifi.iwlibs.Wireless(iface) 00071 self.iwinfo = pythonwifi.iwlibs.WirelessInfo(iface) 00072 self.radio_sm = radio_sm.radio_sm(iface) 00073 self.ping_monitor = ping_tester.PingMonitor(self) 00074 self.had_exception_last_time = False 00075 00076 def _update_specialized(self): 00077 has_link = self.status > IFSTATE.LINK_ADDR 00078 had_exception_this_time = False 00079 try: 00080 self.essid = self.wifi.getEssid() 00081 self.diags.append(('ESSID', self.essid)) 00082 except Exception, e: 00083 if has_link: 00084 had_exception_this_time = True 00085 if self.had_exception_last_time: 00086 traceback.print_exc(10) 00087 print 00088 self.diags.append(('ESSID', 'Error collecting data.')) 00089 self.essid = "###ERROR-COLLECTING-DATA###" 00090 00091 try: 00092 self.bssid = mac_addr.pretty(self.wifi.getAPaddr()) 00093 self.diags.append(('BSSID', self.bssid)) 00094 except Exception, e: 00095 if has_link: 00096 had_exception_this_time = True 00097 if self.had_exception_last_time: 00098 traceback.print_exc(10) 00099 print 00100 self.bssid = "00:00:00:00:00:00" 00101 self.diags.append(('BSSID', 'Error collecting data.')) 00102 00103 try: 00104 self.wifi_txpower = 10**(self.wifi.wireless_info.getTXPower().value/10.) 00105 self.diags.append(('TX Power (mW)', self.wifi_txpower)) 00106 self.wifi_txpower = "%.1f mW"%self.wifi_txpower 00107 except Exception, e: 00108 if str(e).find("Operation not supported") == -1 and has_link: 00109 had_exception_this_time = True 00110 if self.had_exception_last_time: 00111 traceback.print_exc(10) 00112 print 00113 self.diags.append(('TX Power (mW)', 'Error collecting data.')) 00114 self.wifi_txpower = "unknown" 00115 00116 try: 00117 self.wifi_frequency = self.wifi.wireless_info.getFrequency().getFrequency() 00118 self.diags.append(('Frequency (Gz)', "%.4f"%(self.wifi_frequency/1e9))) 00119 except Exception, e: 00120 if has_link: 00121 had_exception_this_time = True 00122 if self.had_exception_last_time: 00123 traceback.print_exc(10) 00124 print 00125 self.wifi_frequency = 0 00126 self.diags.append(('Frequency', 'Error collecting data.')) 00127 00128 got_stats = False 00129 if has_link: 00130 try: 00131 stat, qual, discard, missed_beacon = self.wifi.getStatistics() 00132 max_quality = self.wifi.getQualityMax().quality 00133 quality = qual.quality * 100 / max_quality 00134 self.diags.append(('Quality', quality)) 00135 self.diags.append(('Signal (dB)', qual.siglevel)) 00136 self.diags.append(('Noise (dB)', qual.nlevel)) 00137 self.diags.append(('SNR (dB)', qual.siglevel - qual.nlevel)) 00138 self.wifi_signal = qual.siglevel 00139 self.wifi_noise = qual.nlevel 00140 self.wifi_quality = quality 00141 self.reliability = quality 00142 got_stats = True 00143 except Exception, e: 00144 print "Error getting wireless stats on interface %s: %s"%(self.iface, str(e)) 00145 00146 if not got_stats: 00147 #print self.prettyname, "could not collect wireless data", e 00148 print 00149 self.reliability = 0 00150 self.wifi_quality = -1 00151 self.wifi_noise = 10000 00152 self.wifi_signal = -10000 00153 for s in [ 'Quality', 'Signal', 'Noise' ]: 00154 if has_link: 00155 self.diags.append((s, 'Error collecting data.')) 00156 else: 00157 self.diags.append((s, 'Unknown')) 00158 00159 self.wifi_rate = None 00160 if has_link: 00161 try: 00162 self.wifi_rate = self.wifi.wireless_info.getBitrate().value 00163 except: 00164 pass 00165 if self.wifi_rate is None: 00166 try: 00167 self.wifi_rate = self.iwinfo.getBitrate().value 00168 except: 00169 pass 00170 if self.wifi_rate is not None: 00171 self.diags.append(('TX Rate (Mbps)', self.wifi_rate / 1e6)) 00172 self.wifi_rate = self.wifi._formatBitrate(self.wifi_rate) 00173 else: 00174 if has_link: 00175 print "Unable to determine TX rate on interface", self.iface 00176 self.diags.append(('TX Rate (Mbps)', 'Error collecting data.')) 00177 else: 00178 self.diags.append(('TX Rate (Mbps)', 'Unknown')) 00179 self.wifi_rate = "Unknown" 00180 00181 self.had_exception_last_time = had_exception_this_time 00182 00183 class StaticRouteInterface(Interface): 00184 def __init__(self, route, tableid): 00185 gateway, iface = route.split('@') 00186 Interface.__init__(self, iface, tableid, route) 00187 self.gateway = socket.gethostbyname(gateway) 00188 self._fake_binding = state_publisher.StatePublisher(None) 00189 netlink_monitor.get_state_publisher(iface, IFSTATE.ADDR).subscribe(self._publish_binding) 00190 DhcpRouteSetter(iface, tableid, self._fake_binding) 00191 00192 def _publish_binding(self, old_state, new_state): 00193 if new_state: 00194 ip, netbits = new_state 00195 net = ipaddr.IPv4Network("%s/%s"%(ip, netbits)) 00196 self._binding = { "ip" : ip, "gateway" : self.gateway, "network_slashed" : "%s/%s"%(net.network, net.prefixlen) } 00197 self._fake_binding.set(self._binding) 00198 else: 00199 self._fake_binding.set(None) 00200 00201 def _update_specialized(self): 00202 self.reliability = 100 00203 self.bssid = "Wired" 00204 00205 00206 class NoType(Exception): 00207 pass 00208 00209 class UnknownType(Exception): 00210 pass 00211 00212 def construct(iface, tableid): 00213 try: 00214 type = config.get_interface_parameter(iface, 'type') 00215 if type == "wired": 00216 return WiredInterface(iface, tableid) 00217 if type == "wireless": 00218 return WirelessInterface(iface, tableid) 00219 if type == "static": 00220 return StaticRouteInterface(iface, tableid) 00221 raise UnknownType(type) 00222 except config.NoDefault: 00223 raise NoType() 00224 00225 00226 if __name__ == "__main__": 00227 try: 00228 DhcpInterface('eth1', 50) 00229 except: 00230 import traceback 00231 traceback.print_exc() 00232 import twisted.internet.reactor as reactor 00233 reactor.run() 00234 import threading 00235 import time 00236 while True: 00237 time.sleep(0.1) 00238 threads = threading.enumerate() 00239 non_daemon = sum(0 if t.daemon else 1 for t in threads) 00240 if non_daemon == 1: 00241 break 00242 print 00243 print "Remaining threads:", non_daemon, len(threads) 00244 for t in threads: 00245 print ("daemon: " if t.daemon else "regular:"), t.name