Skip to content

Latest commit

 

History

History
254 lines (206 loc) · 7.34 KB

File metadata and controls

254 lines (206 loc) · 7.34 KB

Code Analysis


api.py

  • create_timer
def create_timer (seconds, target, recurring = True, pass_self = False,args=(), kw={}):

作用为创建一个定时器,此时可以通过设置 seconds 来控制调用函数的时间,通过 target 来填入需要调用的函数的名字,使用该函数将返回一个实体,如果需要停止定时器对返回的实体使用.cancel()方法即可

  • Packet
class Packet (object):
  """
  作为所有包的父类,此后所有包都需要继承,
  包里面包含了源entity,目标entity,总长度和走过的实体名(下面解释)的 list,
  一般 src 为 NULL 时就自动填上当前发送的实体,dst 为空时如果路由器没有设置相关解决方案,
  可能会引起路由器错误

  """
  def __init__ (self, dst=NullAddress, src=NullAddress):

    self.src = src # 源实体(就是实体,不是实体名)注意(有name)
    self.dst = dst # 目标实体
    self.ttl = 20 # 总长度
    self.trace = [] # 走过的路径
    self.outer_color = hsv_to_rgb(rand(), rand()*.25+.1, rand()*.95+.5,.75)
    self.inner_color = [0,0,0,0]

  def __repr__ (self):
  • Entity
class Entity (object):
  """
  所有实体元件的基类(父类)比如交换机router,路由器switch,主机host等
  """

  @classmethod # 不使用self而是cls完成在调用函数后同时实例化,可以把cls当作类名使用
  def create (cls, name, *args, **kw):
    """
    创建一个实体,加入名字即可
    """
    return core.CreateEntity(name, cls, *args, **kw)

  def get_port_count (self):
    """
    返回该实体的端口数(此时是实际物理端口)
    """
    pass

  def handle_rx (self, packet, port):
    """
    当Entity实体收到一个packet时就会自动调用这个函数(core.py中有方法
    可以识别包来的端口),所以将自动调用该函数,此时packet就是表示收到的包,
    port表示包来自的端口(物理)
    """
    pass

  def set_debug (self, *args):
    """
    将所有参数转换为此实体的调试消息。
    此次实验用不到该函数
    """
    pass

  def log (self, msg, *args, **kwargs):
    """
    格式化输出所用,实体调用该函数实际为输出某些信息(和printf作用差不多相同)
    实际使用见basics中
    """
    pass

  def send (self, packet, port=None, flood=False):
    """
    发送一个包给相对应的端口,port可以是端口号,也可以是端口号列表,如果使用了
    flood选项,那么就会发送到除port端口以外的所有端口
    """
    pass

  def remove (self):
    """
    将该实体移除,本实验用不到(如果使用图形化的话可能会在取消实体的时候调用这个
    函数
    """
    pass

  def __repr__ (self):
    return "<" + self.__class__.__name__ + " " + str(self.name) + ">"
  • HostRntity
class HostEntity (Entity):
"""
与Entity实体完全相同,只是简单的继承关系
"""

basics.py

  • BasicHost
class BasicHost (HostEntity):
  """增添了ping功能的host实体类"""

  def ping (self, dst, data=None):
    """ 发送一个ping包(后面实体化)给目标 """
    self.send(Ping(dst, data=data), flood=True)

  def handle_rx (self, packet, port):
    """
    Returns Pings with a Pong.
    host接收到不同的包输出不同的反映(一般默认只有一个端口0),
    当收到包的目标entity为NULL时,简单丢弃这个包,
    当这个包的目的entity不是自己时,发出warn,
    当这个包的目的entity是自己同时是一个ping包时,输出相关信息,同时发送一个pong包给src
    当这个包的目的entity是自己同时是一个pong包时,输出相关信息
    """
    if packet.dst is NullAddress:
      # Silently drop messages not to anyone in particular
      return

    trace = ','.join((s.name for s in packet.trace))

    if packet.dst is not self:
      self.log("NOT FOR ME: %s %s" % (packet, trace), level="WARNING")
    else:
      self.log("rx: %s %s" % (packet, trace))
      if type(packet) is Ping:
        # Trace this path
        import core
        core.events.highlight_path([packet.src] + packet.trace)
        # Send a pong response
        self.send(Pong(packet), port)
  • Ping
class Ping (Packet):
  """继承自包类的ping包"""
  def __init__ (self, dst, data=None):
    Packet.__init__(self, dst=dst) # packet中src为NULL时自动填入当前发送的实体的地址
    self.data = data # 新增包中的data
    self.outer_color[3] = 1 # 调整颜色所用
    self.inner_color = [1,1,1,1] # 调整颜色所用

  def __repr__ (self):
    """
    控制直接可以print ping类
    """
    d = self.data
    if d is not None:
      d = ': ' + str(d)
    else:
      d = ''
    return "<Ping %s->%s ttl:%i%s>" % (self.src.name, self.dst.name, self.ttl, d)
  • Pong
class Pong (Packet):
  """
  继承自包类的pong包,是对ping包的回应,origianl为ping包,解析ping包中的相关信息,
  然后再将ping包的src加入到pong包的dst中
  """
  def __init__ (self, original):
    Packet.__init__(self, dst=original.src)
    self.original = original

    # 颜色设置
    self.outer_color = original.inner_color
    self.inner_color = original.outer_color

  def __repr__ (self):
    """
    控制直接可以print pong类
    """
    return "<Pong " + str(self.original) + ">"
  • DiscoveryPacket
class DiscoveryPacket (Packet):
    """
    继承自packet的discoverypacket包
    实体建立时发送该包的机制如下:
    当拓扑图连好后,实体会将包的dst设置为NULL,同时所有已经建立的实体会向自己所有已连接entity的端口发送discovery包,
    实体会自动检测端口所连接线的latency同时加入发送往该端口的discovery包的latency中
    """
    def __init__(self, src, latency):
        Packet.__init__(self, src=src)
        self.latency = latency
        self.is_link_up = (latency != None and latency != float("inf"))

    def __repr__ (self):
        return "<%s from %s->%s, %s, %s>" % (self.__class__.__name__,
                                 self.src.name if self.src else None,
                                 self.dst.name if self.dst else None,
                                 self.latency,
                                 self.is_link_up)
  • RoutingUpdate
class RoutingUpdate (Packet):
    """
    继承自packet的路由用包,用在路由器构建路由表的包
    """

    def __init__(self):
        Packet.__init__(self)# 没有dst,src打上发送的entity的地址
        self.paths = {} # path可以当作要向邻居发送的路由矢量值,也就是记录该路由器到router/host的估计值

    def add_destination(self, dest, distance):
        """
        加入新节点和估计的延迟
        """
        self.paths[dest] = distance

    def get_distance(self, dest):
        """
        获取到某个节点的估计延迟(某个router接收到该来自邻居的包是使用)
        """
        return self.paths[dest]

    def all_dests(self):
        """
        获取包中的所有节点
        """
        return self.paths.keys()

    def str_routing_table(self):
        """
        获取包中的路由矢量值
        """
        return str(self.paths)