def __init__ (self, gateways = [],k ="",victim ="",limitervariation= ""):
    # Mapeamento de IP para portas
    self.arpTable = {}

    # Instalacao de gateways - Tenho DPID.
    self.gateways = set(gateways)

    # Gateways e K saltos
    self.k = k
    self.victim = victim
    
    # Mapeamento
    self.G = nx.Graph()
    self.MappingHosts = {}
    self.SwitchesToApply = []
    
    self.Trigger = False
    
    # Configuracao do Rate-Limiting 
    self.Limiter = 15
    self.LimiterVariation = limitervariation
    self.oldLimiter =  self.Limiter

    # Inicializa funcao para disparar regra e habilitar filtro.
    t = Timer(15.0, self.CalculatePath)
    t.start()

    core.openflow_discovery.addListenerByName("LinkEvent", self._handle_LinkEvent)  # listen to openflow_discovery
    core.host_tracker.addListenerByName("HostEvent", self._handle_HostEvent)  # listen to host_tracker
    core.listen_to_dependencies(self)
Пример #2
0
def create_matrix ():
    log.debug("Child process called\n-------------------")
    #_forward_path
    time.sleep(5)
    t = Timer(2.0, _forward_path, recurring=True)
    #t = threading.Timer(5.0, _forward_path)
    #threads.append(t)
    #t.daemon = True
    t.start()
    time.sleep(5)
  def __init__ (self, gateways = []):
    # Mapeamento de IP para portas
    self.arpTable = {}

    # Instalacao de gateways - Tenho DPID.
    self.gateways = set(gateways)
    
    # Inicializa funcao para disparar regra e habilitar filtro.
    t = Timer(50.0, ActivateFilters)
    t.start()

    core.listen_to_dependencies(self)
Пример #4
0
def launch():
    """
    core is able to register all the pox components
    core.openflow is the pox openflow component
    _handle_ConnectionUp subscribe to core.openflow's ConnectionUp event

    each Timer instance add a non-default parameter to show Timer
    capabilities.

    """

    TIME_TO_WAKE = 2
    args = ["ciao", "mare"]
    core.callDelayed(TIME_TO_WAKE, timeout_handler, args)

    t = Timer(
            TIME_TO_WAKE,
            timeout_handler,
            args='t1')

    t2 = Timer(
            TIME_TO_WAKE,
            timeout_handler,
            absoluteTime=True,  # use False
            args='t2')

    tr = Timer(
            TIME_TO_WAKE,
            timeout_handler,
            absoluteTime=False,
            recurring=True,  # recur infinitely overtime
            args='tr')

    tw = Timer(
            TIME_TO_WAKE,
            timeout_handler,
            absoluteTime=False,
            recurring=False,
            started=False,  # not start automatically
            args='tw')
    time.sleep(TIME_TO_WAKE)
    tw.start()

    tk = Timer(
            TIME_TO_WAKE,
            timeout_handler_kill,  # handler able to cancel the timer
            absoluteTime=False,
            recurring=True,
            started=False,
            selfStoppable=False,  # timer can be cancelled by the handler
            args='tw')
Пример #5
0
def _handle_ConnectionUp (event):
  global src_dpid, dst_dpid, mytimer
  print "ConnectionUp: ", dpidToStr(event.connection.dpid)
 
  #remember the connection dpid for switch to controller (src_dpid) and switch1 to controller(dst_dpid)
  for m in event.connection.features.ports:
    if m.name == "s0-eth0":
      src_dpid = event.connection.dpid
    elif m.name == "s1-eth0":
      dst_dpid = event.connection.dpid
 
  # when the controller knows both src_dpid and dst_dpid, the probe packet is sent out every 2 seconds
  if src_dpid<>0 and dst_dpid<>0:
    mytimer=Timer(2, _timer_func, recurring=True)
    mytimer.start()
Пример #6
0
def launch():
    """
    core is able to register all the pox components
    core.openflow is the pox openflow component
    _handle_ConnectionUp subscribe to core.openflow's ConnectionUp event

    each Timer instance add a non-default parameter to show Timer
    capabilities.

    """

    TIME_TO_WAKE = 2
    args = ["ciao", "mare"]
    core.callDelayed(TIME_TO_WAKE, timeout_handler, args)

    t = Timer(TIME_TO_WAKE, timeout_handler, args='t1')

    t2 = Timer(
        TIME_TO_WAKE,
        timeout_handler,
        absoluteTime=True,  # use False
        args='t2')

    tr = Timer(
        TIME_TO_WAKE,
        timeout_handler,
        absoluteTime=False,
        recurring=True,  # recur infinitely overtime
        args='tr')

    tw = Timer(
        TIME_TO_WAKE,
        timeout_handler,
        absoluteTime=False,
        recurring=False,
        started=False,  # not start automatically
        args='tw')
    time.sleep(TIME_TO_WAKE)
    tw.start()

    tk = Timer(
        TIME_TO_WAKE,
        timeout_handler_kill,  # handler able to cancel the timer
        absoluteTime=False,
        recurring=True,
        started=False,
        selfStoppable=False,  # timer can be cancelled by the handler
        args='tw')
Пример #7
0
class MyExplorer(object):
  def __init__ (self):
    log.warning("MyExplorer Constructed.")
    core.listen_to_dependencies(self)
    # Adjacency map.  [sw1][sw2] -> port from sw1 to sw2
    self.adj = defaultdict(lambda:defaultdict(lambda:int))

    # Port map.  [sw1][sw2] -> the output port from sw1 to sw2
    self.ports = defaultdict(lambda:defaultdict(lambda:int))

    # Switches we know of.  [dpid] -> Switch
    self.switches = set()

    self.reset_hosts()
    # self.hosts: Hosts we know of. [macaddr (string)] -> Host
    # self.hadj: [h][sw] ->  the ports where switchs connect to the hosts
    # self.sd_pair: [h1][h2] -> source-destination pair id

    self.reset_path_tables()
    # self.path_id_table: Path ID -> Path table
    # self.sd_path_table: [Source][Destination] -> Path ID list

    self.reset_srcport_tables()
    # self.sd_srcport_table: [Source][Destination] -> Srcport list

    self.reset_flowdist_tables()
    # self.flow_dist_table: [sd_pair_id][path_id-1] -> Srcport distribution

    # Latency test function
    self.adj_test = []
    self.sw_test  = []
    self.sw_lat   = []
    self.lat_test_timer = []
    # Does latency test Start?
    self.lat_test = False

    # Update step
    self.update_step  = 0
    self.update_timer = []
    self.config = Configuration()

    random.seed(time.time())

  """
   Event Handlers
  """
  def _handle_core_ComponentRegistered (self, event):
    log.warning(event.name)
    if event.name == "host_tracker":
      event.component.addListenerByName("HostEvent",
        self.__handle_host_tracker_HostEvent)

  def _handle_openflow_ConnectionUp (self, event):
    dp = event.connection.dpid
    self.switches.add(dp)
    event.connection.addListenerByName("PacketIn",
        self.__handle_PacketIn)
    log.warning("Switch %s is discovered.", dpid_to_str(dp))

  def _handle_openflow_ConnectionDown (self, event):
    pass

  def _handle_openflow_discovery_LinkEvent (self, event):
    (dp1,p1),(dp2,p2) = event.link.end
    self.adj[dp1][dp2] = 1
    self.ports[dp1][dp2] = p1
    log.warning(
      "Link %s -> %s is discovered.",
      dpid_to_str(dp1),
      dpid_to_str(dp2)
    )

  def __handle_host_tracker_HostEvent (self, event):
    h = event.entry.macaddr.toStr()
    s = event.entry.dpid

    if h == "ff:ff:ff:ff:ff:ff":
      # The address for broadcasting and testing
      return

    if event.leave:
      if h in self.hosts:
        if s in self.hadj[h]:
          self.hosts.remove(h)
          del s
    else:
      # event.join, event.move, ...
      if h not in self.hosts:
        self.hosts.add(h)
      else:
        for s1 in self.hadj[h]:
          del s1
      self.hadj[h][s] = event.entry.port
      log.warning("Host %s is discovered.", h)

  def __handle_PacketIn(self, event):
    packet = event.parsed
    src = packet.src.toStr()
    dst = packet.dst.toStr()

    # Extract IP information
    ip   = packet.find('ipv4')
    udpp = packet.find('udp')
    if ip:
      # it is not a good way to define a variable, anyway
      srcip = ip.srcip
      dstip = ip.dstip
      self.srcip_table[src] = srcip
      self.dstip_table[dst] = dstip
      if udpp:
        srcport = udpp.srcport
        # Each src-dst pair has several ports
        if srcport not in self.sd_srcport_table[src][dst]:
          # New port discovered
          self.sd_srcport_table[src][dst].append(srcport)

    # Latency test packets handling
    if self.lat_test:
      if packet.type != 0x5566:
        # not test packet, drop it
        return

      src = self._MAC_to_int(src)
      dst = self._MAC_to_int(dst)

      timeinit, = struct.unpack('!I', packet.find('ethernet').payload)
      timediff = time.time()*1000 - self.system_time - timeinit

      if src in self.adj_test:
        if dst in self.adj_test[src]:
          self.adj[src][dst] = timediff
          del self.adj_test[src][dst]

      if dst in self.sw_test:
        self.sw_lat[dst] = timediff
        self.sw_test.remove(dst)

      return

    # assign path id
    pid = 0

    if src in self.hosts:
      for d in self.sd_path_table[src]:
        # FIXME: Pick one as default
        # Maybe we should apply flood function to broadcasting
        for sd_path_id in self.sd_path_table[src][d]:
          pid = sd_path_id
          # log.warning("Packet Vid = %i", pid)

      if dst in self.hosts:
        if self.config.config_set:
          if ip and udpp:
            # If the packet is an IP/UDP packet
            id_list = self.sd_path_table[src][dst]
            # last one, in case not found
            pid = self.get_pid_by_srcport(id_list, srcport)
            if pid is None:
              # Not existed port, choose the last one as default
              pid = id_list[len(id_list) - 1]
              for k in id_list:
                now_split = self.config.now_config
                real_split = self.config.real_config
                # log.warning("now %s real %s", now_split, real_split )
                if now_split[k-1] > real_split[k-1] or now_split[k-1] == 1:
                  pid = k
                  break
              # update flow_dist_table and real_config_table
              self.flow_dist_table[pid-1].append(srcport)
              self.config.compute_real_config(id_list, self.flow_dist_table)
          else:
            id_list = self.sd_path_table[src][dst]
            # last one, in case not found
            pid = id_list[len(id_list) - 1]
          
            sum_of_all = 0
            for x in id_list:
              sum_of_all += self.config.now_config[x-1]
            
            rand_num = sum_of_all * random.random()
            for x in id_list:
              rand_num -= self.config.now_config[x-1]  # Since the path ID starts from 1, which is different from the index
              if rand_num < 0:
                # path_id should start from 1
                pid = x
                break
          # log.warning("SD pair %i, pid %i", self.sd_pair[src][dst], pid) 
        else:
          # FIXME: path selection
          for sd_path_id in self.sd_path_table[src][dst]:
            # There exists a path
            pid = sd_path_id
            # log.warning("Packet Vid = %i", pid)        

      if ip and udpp:
        # FIXME: Do we need to modify the flow whenever the packet in?
        msg = of.ofp_flow_mod()
        msg.match.dl_type = 0x800
        msg.match.nw_src = IPAddr(srcip)
        msg.match.nw_dst = IPAddr(dstip)
        msg.match.nw_proto = 17
        msg.match.tp_src = srcport
        # slog.warning("Add rule for port %s", srcport)
      else:
        msg = of.ofp_packet_out(data = event.ofp)

      if pid != 0:
        # There exists a path
        path = self.path_id_table[pid]
        if len(path) > 3:
        # It is not the last sw, tag it and send into the network
          if USE_VLAN_TAG:
            msg.actions.append( of.ofp_action_vlan_vid( vlan_vid = pid ) )
          if USE_ETHERNET_SRC_TAG:
            msg.actions.append( of.ofp_action_dl_addr.set_src( EthAddr( self._int_to_MAC( pid ) ) ) )
          msg.actions.append( of.ofp_action_output( port = self.ports[path[1]][path[2]] ) )
        elif len(path) == 3:
          # last sw, forward to the host
          #msg.actions.append( of.ofp_action_output( port = of.OFPP_FLOOD ) )
          msg.actions.append( of.ofp_action_output( port = self.hadj[path[2]][path[1]] ) )

      event.connection.send(msg)

    """
      msg = of.ofp_packet_out( data = event.ofp )
      if pid != 0:
        # There exists a path
        path = self.path_id_table[pid]
        if len(path) > 3:
          # It is not the last sw, tag it and send into the network
          if USE_VLAN_TAG:
            msg.actions.append( of.ofp_action_vlan_vid( vlan_vid = pid ) )
          if USE_ETHERNET_SRC_TAG:
            msg.actions.append( of.ofp_action_dl_addr.set_src( EthAddr( self._int_to_MAC( pid ) ) ) )
          msg.actions.append( of.ofp_action_output( port = self.ports[path[1]][path[2]] ) )
        elif len(path) == 3:
          # last sw, forward to the host
          # msg.actions.append( of.ofp_action_output( port = of.OFPP_FLOOD ) )
          msg.actions.append( of.ofp_action_output( port = self.hadj[path[2]][path[1]] ) )
    """

  def _handle_openflow_FlowStatsReceived (self, event):
    log.warning("Flow stats received.")
    for x in flow_stats_to_list(event.stats):
      log.warning( x )

  def _handle_openflow_PortStatsReceived (self, event):
    log.warning("Port stats received.")
    log.warning(flow_stats_to_list(event.stats))

  """
   Tool Functions
  """
  def _clear_all_paths_for_all_switches (self):
    msg = of.ofp_flow_mod(command=of.OFPFC_DELETE)

    # iterate over all connected switches and delete all their flows
    for sw in self.switches:
      # _connections.values() before betta
      core.openflow.sendToDPID(sw, msg)
      log.warning("Clearing all flows from %s.", dpidToStr(sw))

  def _set_path_on_swtiches (self, pid, path):
    for k, sw in enumerate(path):
      msg = of.ofp_flow_mod()

      if USE_VLAN_TAG:
        msg.match.dl_vlan = pid
      if USE_ETHERNET_SRC_TAG:
        msg.match.dl_src = EthAddr( self._int_to_MAC( pid ) ) # match ethernet addr

      if k < 1:
        # First one, host
        continue
      if k > len(path)-2:
        # Last one, host
        continue

      if k == len(path) - 2:
        # sw -> host

        if USE_VLAN_TAG:
          # strip vlan tag then send to host
          msg.actions.append(
            of.ofp_action_strip_vlan()
          )
        if USE_ETHERNET_SRC_TAG:
          # add back the real src
          msg.actions.append(
            of.ofp_action_dl_addr.set_src( EthAddr(path[0]) )
          )

        msg.actions.append(
          of.ofp_action_output( port = self.hadj[path[k+1]][sw] )
        )
        core.openflow.sendToDPID(sw, msg)
        log.warning(
          "Set rule: %s -> %s via port %i",
          dpid_to_str(sw),
          path[k+1],
          self.hadj[path[k+1]][sw]
        )
      else:
        # sw -> sw
        msg.actions.append(
          of.ofp_action_output( port = self.ports[sw][path[k+1]] )
        )
        core.openflow.sendToDPID(sw, msg)
        log.warning(
          "Set rule: %s -> %s via port %i",
          dpid_to_str(sw),
          dpid_to_str(path[k+1]),
          self.ports[sw][path[k+1]]
        )

  def _int_to_MAC(self, pid):
    tmp_pid = pid
    ma=[]
    for x in range(0, 6):
      ma.append( "%X" % (tmp_pid % 256) )
      tmp_pid //= 256
    return ma[5] + ":" + ma[4] + ":" + ma[3] + ":" + ma[2] + ":" + ma[1] + ":" + ma[0]

  def _MAC_to_int(self, mac):
    return int( "0x" + mac.replace(':', ''), 16)

  def _latency_ready(self):
    # Check if it has TIMEOUT or all the link latencies have been detected
    if time.time()*1000 - self.system_time < SYSTEM_TIMEOUT:
      for x in self.adj_test:
        for y in self.adj_test[x]:
          # Not yet
          log.warning("Waiting ...")
          return
      for x in self.sw_test:
        # Not yet
        log.warning("Waiting ...")
        return

    for sw in self.sw_test:
      self.sw_lat[sw] = LATENCY_MAX
      log.warning("sw %i timeout!", sw)
    for s1 in self.adj_test:
      for s2 in self.adj_test[s1]:
        self.adj[s1][s2] = LATENCY_MAX
        log.warning("link %i -> %i timeout!", s1, s2)

    for s1 in self.adj:
      for s2 in self.adj[s1]:
        self.adj[s1][s2] -= (self.sw_lat[s1] + self.sw_lat[s2])/2

    self.lat_test_timer.cancel()
    self.lat_test = False
    log.warning("Latency test done.")

  def _update_step(self):
    if self.update_step > len(self.config.config) - 1:
      self.update_timer.cancel()
      log.warning("Updating Ends.")
      return
    self.config.change_step(self.update_step)
    self.update_timer._next = time.time() +  self.config.next_time

    # redistribute flows based on new configuration
    self.config.reset_real_config()
    self.reset_flowdist_tables()

    # Compute for each port in all source destination pair
    for src in self.sd_path_table:
      for dst in self.sd_path_table[src]:
        id_list = self.sd_path_table[src][dst]
        for srcport in self.sd_srcport_table[src][dst]:
          pid = self.get_pid_by_srcport(id_list, srcport)  # should be None
          if pid is None:
            # Not existed port, choose the last one as default
            pid = id_list[len(id_list) - 1]
            for k in id_list:
              now_split = self.config.now_config
              real_split = self.config.real_config
              if now_split[k-1] > real_split[k-1] or now_split[k-1] == 1:
                pid = k
                break
            # update flow_dist_table and real_config_table
            self.flow_dist_table[pid-1].append(srcport)
            self.config.compute_real_config(id_list, self.flow_dist_table)

          log.warning("pid %s", pid)

          srcip = self.srcip_table[src]
          dstip = self.dstip_table[dst]
          msg = of.ofp_flow_mod( command = of.OFPFC_MODIFY )
          msg.match.dl_type = 0x800
          msg.match.nw_src = IPAddr(srcip)
          msg.match.nw_dst = IPAddr(dstip)
          msg.match.nw_proto = 17
          msg.match.tp_src = srcport
          path = self.path_id_table[pid]
          if len(path) > 3:
            # It is not the last sw, tag it and send into the network
            if USE_VLAN_TAG:
              msg.actions.append( of.ofp_action_vlan_vid( vlan_vid = pid ) )
            if USE_ETHERNET_SRC_TAG:
              msg.actions.append( of.ofp_action_dl_addr.set_src( EthAddr( self._int_to_MAC( pid ) ) ) )
            msg.actions.append( of.ofp_action_output( port = self.ports[path[1]][path[2]] ) )
          elif len(path) == 3:
            # last sw, forward to the host
            # msg.actions.append( of.ofp_action_output( port = of.OFPP_FLOOD ) )
            msg.actions.append( of.ofp_action_output( port = self.hadj[path[2]][path[1]] ) )
          sw = path[1]
          core.openflow.sendToDPID(sw, msg)
          # print msg
          # log.warning("SD pair %i, pid %i", self.sd_pair[src][dst], pid)

    log.warning("Update Step %i ...", self.update_step)
    self.update_step += 1

  """
   The function starts with a small letter is for command line interface
  """
  def reset_hosts (self):
    # Hosts we know of. [macaddr] -> Host
    self.hosts = set()
    # The ports where switches connect to the hosts
    self.hadj = defaultdict(lambda:defaultdict(lambda:int))
    # self.sd_pair: [h1][h2] -> source-destination pair id
    self.sd_pair = defaultdict(lambda:defaultdict(lambda:int))

  def reset_path_tables (self):
    # Path ID -> Path table
    self.path_id_table = defaultdict(lambda:[])
    # [Source][Destination] -> Path ID list
    self.sd_path_table = defaultdict(lambda:defaultdict(lambda:[]))

  def reset_srcport_tables (self):
    # [Source][Destination] -> Srcport list
    self.sd_srcport_table = defaultdict(lambda:defaultdict(lambda:[]))
    # [Source] -> srcip
    self.srcip_table = defaultdict(lambda:[])
    # [Destination] -> dstip
    self.dstip_table = defaultdict(lambda:[])

  def reset_flowdist_tables (self):
    # [path_id-1] -> Srcports
    self.flow_dist_table = defaultdict(lambda:[])

  def get_pid_by_srcport (self, id_list, srcport):
    # Match the srcport from cadidate path_id in id_list
    for path_id in id_list:
      if srcport in self.flow_dist_table[path_id - 1]:
        return path_id
    return None

  def port_stat (self, dpid):
    core.openflow.sendToDPID(
      dpid,
      of.ofp_stats_request(body=of.ofp_port_stats_request())
    )

  def sw_stat (self, dpid):
    core.openflow.sendToDPID(
      dpid,
      of.ofp_stats_request(body=of.ofp_flow_stats_request())
    )

  def latency(self):
    # Find link latencies and write into self.adj
    log.warning("Start latency test, please wait ...")
    self.lat_test = True
    self._clear_all_paths_for_all_switches()

    self.adj_test    = copy.deepcopy(self.adj)
    self.sw_test     = copy.copy(self.switches)
    self.sw_lat      = defaultdict(lambda:int)
    # system reference
    self.system_time = time.time()*1000

    for sw in self.sw_test:
      proto = ProbeProto()
      proto.timestamp = int(time.time()*1000 - self.system_time)
      e = pkt.ethernet()
      e.type = 0x5566
      e.src = EthAddr( "ff:ff:ff:ff:ff:ff" )
      e.dst = EthAddr( self._int_to_MAC(sw) )
      e.payload = proto
      msg = of.ofp_packet_out()
      msg.data = e.pack()
      msg.actions.append( of.ofp_action_output( port = of.OFPP_CONTROLLER ) )
      core.openflow.sendToDPID(sw, msg)

    for src in self.adj_test:
      for dst in self.adj_test[src]:
        proto = ProbeProto()
        proto.timestamp = int(time.time()*1000 - self.system_time)
        e = pkt.ethernet()
        e.type = 0x5566
        e.src = EthAddr( self._int_to_MAC(src) )
        e.dst = EthAddr( self._int_to_MAC(dst) )
        e.payload = proto
        msg = of.ofp_packet_out()
        msg.data = e.pack()
        msg.actions.append( of.ofp_action_output( port = self.ports[src][dst] ) )
        core.openflow.sendToDPID(src, msg)

    self.lat_test_timer = Timer(1, self._latency_ready, started = True, recurring = True)

  def k_path (self, k):
    # Find k-shortest path based on self.adj and self.hadj
    log.warning("Find %u path",k)

    alladj = copy.deepcopy(self.adj)
    for h in self.hadj:
      for s in self.hadj[h]:
        alladj[h][s] = 1
        alladj[s][h] = 1
    G = y_gra.DiGraph(alladj)
    log.warning("Graph constructed")

    self._clear_all_paths_for_all_switches()
    self.reset_path_tables()
    self.reset_flowdist_tables()
    self.reset_srcport_tables()

    # sd_pair_id, h1, h2, path_id ...
    output_table_1 = ""
    # path_id, path_id_table[path_id]
    output_table_2 = ""
    sd_pair_id = 0
    path_id    = 1
    for h1 in self.hadj:
      for h2 in self.hadj:
        if h1 != h2:
          self.sd_pair[h1][h2] = sd_pair_id
          output_table_1 += str(sd_pair_id) + " ( " + h1 + " , " + h2 + " ) : "
          sd_pair_id += 1
          items = y_alg.ksp_yen(G,h1,h2,k)
          for path in items:
            #print "Cost:%s\t%s" % (path['cost'], "->".join(path['path']))
            self.path_id_table[path_id] = path['path']
            self.sd_path_table[h1][h2].append(path_id)
            output_table_1 += str(path_id) + " "
            output_table_2 += str(path_id) + " " + "%s" % self.path_id_table[path_id] + "\n"
            path_id += 1
          output_table_1 += "\n"

    for pid in self.path_id_table:
      self._set_path_on_swtiches (pid, self.path_id_table[pid])

    output_file = open(OUTPUT_PATH_FILENAME, "w")
    output_file.write("SD pairs:\n%s" % output_table_1)
    output_file.write("\nPath IDs:\n%s" % output_table_2)
    output_file.close()

  def update(self):
    # let the controller start update the configuration
    log.warning("Updating Starts.")
    self.update_step = 0
    self.config.read_config( INPUT_CONFIG_FILENAME )
    # Initial update
    self.update_timer = Timer(self.config.next_time, self._update_step, started = False, recurring = True)
    self._update_step()
    self.update_timer.start()