interface.py
Go to the documentation of this file.
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


multi_interface_roam
Author(s): Blaise Gassend
autogenerated on Thu Jan 2 2014 11:26:15