예제 #1
0
    def act_like_firewall_drop(self, packet, packet_in):
        """
    Implement switch-like behavior.
    1. Implementing a "simple" learning switch.
    """

        log.debug("Installing dropping flow...")
        # Maybe the log statement should have source/destination/port?

        msg = of.ofp_flow_mod()

        ## Set fields to match received packet
        # Exact match
        msg.match = of.ofp_match.from_packet(packet_in)
        msg.idle_timeout = 30
        # msg.hard_timeout = 60 # for debugging purpose
        msg.buffer_id = packet_in.buffer_id
        msg.data = packet_in
        # No action for dropped packet
        # msg.actions.append(of.ofp_action_output(port=of.OFPP_NONE))

        # Send msg to swtich
        self.connection.send(msg)

        log.debug("------------------------------")
    def act_like_firewall_drop(self, packet, packet_in):
        """
    Implement switch-like behavior.
    1. Implementing a "simple" learning switch.
    """

        log.debug("Installing dropping flow...")
        # Maybe the log statement should have source/destination/port?

        msg = of.ofp_flow_mod()

        ## Set fields to match received packet
        # Exact match
        msg.match = of.ofp_match.from_packet(packet_in)
        msg.idle_timeout = 30
        # msg.hard_timeout = 60 # for debugging purpose
        msg.buffer_id = packet_in.buffer_id
        msg.data = packet_in
        # No action for dropped packet
        # msg.actions.append(of.ofp_action_output(port=of.OFPP_NONE))

        # Send msg to swtich
        self.connection.send(msg)

        # else:
        #   log.debug(" ==> Unknowd {0} -- Flood all".format(packet.dst))
        #   # Flood the packet out everything but the input port
        #   # This part looks familiar, right?
        #   self.resend_packet(packet_in, of.OFPP_ALL)

        log.debug("------------------------------")
 def _handle_LinkEvent(self, event):
     """ Listener de NUEVO ENLACE """
     global _flood_delay
     _flood_delay = _flood_delay + FLOOD_DELAY_INCREMENT
     log.debug('NUEVO ENLACE DETECTADO _flood_delay: %d SEGUNDOS' %
               _flood_delay)
     self._adjust_adjacency()
  def act_like_firewall_drop (self, packet, packet_in):
    """
    Implement switch-like behavior.
    1. Implementing a "simple" learning switch.
    """

    log.debug("Installing dropping flow...")
    # Maybe the log statement should have source/destination/port?

    msg = of.ofp_flow_mod()

    ## Set fields to match received packet
    # Exact match
    msg.match = of.ofp_match.from_packet(packet_in)
    msg.idle_timeout = 30
    # msg.hard_timeout = 60 # for debugging purpose
    msg.buffer_id = packet_in.buffer_id
    msg.data = packet_in
    # No action for dropped packet
    # msg.actions.append(of.ofp_action_output(port=of.OFPP_NONE))

    # Send msg to swtich
    self.connection.send(msg)

    # else:
    #   log.debug(" ==> Unknowd {0} -- Flood all".format(packet.dst))
    #   # Flood the packet out everything but the input port
    #   # This part looks familiar, right?
    #   self.resend_packet(packet_in, of.OFPP_ALL)


    log.debug("------------------------------")
  def act_like_firewall_drop (self, packet, packet_in):
    """
    Implement switch-like behavior.
    1. Implementing a "simple" learning switch.
    """

    log.debug("Installing dropping flow...")
    # Maybe the log statement should have source/destination/port?

    msg = of.ofp_flow_mod()

    ## Set fields to match received packet
    # Exact match
    msg.match = of.ofp_match.from_packet(packet_in)
    msg.idle_timeout = 30
    # msg.hard_timeout = 60 # for debugging purpose
    msg.buffer_id = packet_in.buffer_id
    msg.data = packet_in
    # No action for dropped packet
    # msg.actions.append(of.ofp_action_output(port=of.OFPP_NONE))

    # Send msg to swtich
    self.connection.send(msg)

    log.debug("------------------------------")
 def _handle_ConnectionUp(self, event):
     """ Listener de NUEVO SWITCH conectado """
     global _flood_delay
     _flood_delay = _flood_delay + FLOOD_DELAY_INCREMENT
     log.debug('NUEVO SWITCH DETECTADO _flood_delay: %d SEGUNDOS' %
               _flood_delay)
     # Creo un nuevo switch
     Switch(event.connection, event.dpid)
def send_stats_requests():
  """
  Send stats request to the connecting switch
  """
  for connection in core.openflow._connections.values():
    connection.send(of.ofp_stats_request(body=of.ofp_flow_stats_request()))
    connection.send(of.ofp_stats_request(body=of.ofp_port_stats_request()))

  log.debug("Sent %i flow/port stats request(s)", len(core.openflow._connections))
예제 #8
0
def send_stats_requests():
    """
  Send stats request to the connecting switch
  """
    for connection in core.openflow._connections.values():
        connection.send(of.ofp_stats_request(body=of.ofp_flow_stats_request()))
        connection.send(of.ofp_stats_request(body=of.ofp_port_stats_request()))

    log.debug("Sent %i flow/port stats request(s)",
              len(core.openflow._connections))
 def _adjust_adjacency(self):
     """ Ajusta la ADYACENCIA entre componentes conectados """
     log.debug('AJUSTANDO ADYACENCIA')
     adj.clear()
     switch_ids.clear()
     # por cada enlace nuevo, se ajustan adj y switch_ids
     for l in core.openflow_discovery.adjacency:
         adj[l.dpid1][l.dpid2] = l
         switch_ids.add(l.dpid1)
         switch_ids.add(l.dpid2)
예제 #10
0
  def _handle_PacketIn (self, event):
  
    packet = event.parsed
    packet_in = event.ofp

    dpid = event.dpid
    log.debug("PacketIn message from Switch with dpid = {}".format(dpid))
  
    self.track_host(packet, packet_in, dpid)

    self.simple_hub(dpid , packet, packet_in) 
예제 #11
0
    def _handle_PacketIn(self, event):

        packet = event.parsed
        packet_in = event.ofp

        dpid = event.dpid
        log.debug("PacketIn message from Switch with dpid = {}".format(dpid))

        self.track_host(packet, packet_in, dpid)

        self.simple_hub(dpid, packet, packet_in)
	def insertFlow(self, packet, connection, buffer_id):
		log.debug('Installing flow on switch %d' % self.dpid)

		msg = of.ofp_flow_mod()
		msg.match.dl_type = pkt.ethernet.IP_TYPE
		msg.match.nw_src = IPAddr('10.0.0.1')
		msg.buffer_id = buffer_id
		msg.actions.append(of.ofp_action_nw_addr.set_dst(IPAddr('10.0.0.102')))
		msg.actions.append(of.ofp_action_dl_addr.set_dst(EthAddr('00:00:01:02:03:04')))
		msg.actions.append(of.ofp_action_output(port = 2))
		
		connection.send(msg.pack())
예제 #13
0
  def track_host(self, packet, packet_in, dpid):
    
    if packet.type == packet.ARP_TYPE:

      src_ip = packet.payload.protosrc      
      if src_ip not in self.hosts:
        log.debug("DISCOVERED host with ip {} at switch with dpid {}".format(src_ip, dpid))

        self.hosts[src_ip] = dpid, packet_in.in_port   
        self.dpid_dict[dpid]["hosts"].append(src_ip.toStr())
    
    return
예제 #14
0
  def _handle_PacketIn (self, event):
  
    packet = event.parsed
    packet_in = event.ofp

    dpid = event.dpid
    log.debug("PacketIn message from Switch with dpid = {}".format(dpid))
  
    self.track_host(packet, packet_in, dpid)

    # self.simple_hub(dpid , packet, packet_in) 
    # self.learning_controller(dpid, packet, packet_in) 
    self.learning_microflow_controller(dpid, packet, packet_in)
 def startup():
     #core.openflow.addListeners(self, priority=0)
     core.openflow.addListeners(self)
     core.openflow_discovery.addListeners(self)
     # Listen for flow stats
     core.openflow.addListenerByName("FlowStatsReceived",
                                     handle_flow_stats)
     # EL LISTENER DE ABAJO ES PARA UNA SOLUCION ALTERNATIVA DEL FIREWALL CON SOLICITUD DE ESTADISTICAS PERIODICAS.
     #core.openflow.addListenerByName("FlowStatsReceived", handle_udp_flow_stats)
     core.openflow.addListenerByName("FlowRemoved", handle_flow_removed)
     core.host_tracker.addListenerByName("HostEvent",
                                         handle_host_tracker_HostEvent)
     log.debug("ZgnFattreeController ESTA LISTO")
  def is_ip_blocked(self, packet):
    """
    Handle IP packet
    2. Modify the above simple learning switch to include the logic blocking IP 
    traffic between host 2 and host 3.
    """
    ip = packet.find("ipv4")
    # log.debug("  => IP:{0}".format(ip))
    if ip is not None and Tutorial.ip_block.get(ip.srcip) == ip.dstip:
      log.debug("  ==> IP is blocked from {0} to {1}".format(ip.srcip, ip.dstip))
      return True

    return False
예제 #17
0
    def insertFlow(self, packet, connection, buffer_id):
        log.debug('Installing flow on switch %d' % self.dpid)

        msg = of.ofp_flow_mod()
        msg.match.dl_type = pkt.ethernet.IP_TYPE
        msg.match.nw_src = IPAddr('10.0.0.1')
        msg.buffer_id = buffer_id
        msg.actions.append(of.ofp_action_nw_addr.set_dst(IPAddr('10.0.0.102')))
        msg.actions.append(
            of.ofp_action_dl_addr.set_dst(EthAddr('00:00:01:02:03:04')))
        msg.actions.append(of.ofp_action_output(port=2))

        connection.send(msg.pack())
예제 #18
0
    def _handle_PacketIn(self, event):

        packet = event.parsed
        packet_in = event.ofp

        dpid = event.dpid
        log.debug("PacketIn message from Switch with dpid = {}".format(dpid))

        self.track_host(packet, packet_in, dpid)

        # self.simple_hub(dpid , packet, packet_in)
        # self.learning_controller(dpid, packet, packet_in)
        self.learning_microflow_controller(dpid, packet, packet_in)
예제 #19
0
  def _handle_LinkEvent (self, event):
    
    link = event.link

    dpid_source = link.dpid1
    dpid_dest = link.dpid2
    port_source = link.port1
    port_dest = link.port2

    if event.added:
      log.debug("Link added for switches S-{}:port-{} --> S-{}:port-{}".format(dpid_source, port_source, dpid_dest, port_dest))
      self.dpid_dict[dpid_source]["links"].append(link)    
    else:
      log.debug("Link removed for switches S-{}:port-{} --> S-{}:port-{}".format(dpid_source, port_source, dpid_dest, port_dest))
예제 #20
0
    def is_ip_blocked(self, packet):
        """
    Handle IP packet
    2. Modify the above simple learning switch to include the logic blocking IP 
    traffic between host 2 and host 3.
    """
        ip = packet.find("ipv4")
        # log.debug("  => IP:{0}".format(ip))
        if ip is not None and Tutorial.ip_block.get(ip.srcip) == ip.dstip:
            log.debug("  ==> IP is blocked from {0} to {1}".format(
                ip.srcip, ip.dstip))
            return True

        return False
예제 #21
0
  def install_rule( self, connection, priority, src_port, src_mac, dst_mac, out_port, timeout, dl_type):
    log.debug("Switch-{}: Installing rule src:{} , src_port {}, dst {} -> dst_port {}".
              format( connection.dpid, src_mac, src_port, dst_mac, out_port))
    
    # TODO: Maybe do a more fine-grained match ? 
    msg = of.ofp_flow_mod()
    msg.priority = priority
    msg.match = of.ofp_match( in_port = src_port,
			      dl_src  = src_mac,
                              dl_dst  = dst_mac,
  			      dl_type = dl_type)
    msg.hard_timeout = timeout
    msg.actions.append( of.ofp_action_output( port = out_port))
    connection.send(msg)
예제 #22
0
	def reverseProxy(self, packet, buffer_id):
		log.debug('Installing flow for reverse proxy on switch %d' % self.dpid)

		# From interior to exterior.
		n = packet.find("ipv4")

		msg = of.ofp_flow_mod()
		msg.match.dl_type = pkt.ethernet.IP_TYPE;
		msg.match.nw_dst = n.dstip
		msg.buffer_id = buffer_id
		msg.actions.append(of.ofp_action_nw_addr.set_src(self.vhost.ip))
		msg.actions.append(of.ofp_action_dl_addr.set_src(self.vhost.mac))
		msg.actions.append(of.ofp_action_output(port = self.publicPort))

		self.connection.send(msg)
예제 #23
0
	def macLearning(self, packet):
		ip = None
		mac = packet.src

		if packet.find("ipv4"):
			n = packet.find("ipv4")
			ip = n.srcip
		elif packet.find("arp"):
			a = packet.find("arp")
			if a.prototype == a.PROTO_TYPE_IP:
				ip = a.protosrc

		if ip is not None and self.hosts.get(ip) is None:
			self.hosts[ip] = Host(ip, mac)
			log.debug('Learned: %s <=> %s' % (ip, mac))
예제 #24
0
    def reverseProxy(self, packet, buffer_id):
        log.debug('Installing flow for reverse proxy on switch %d' % self.dpid)

        # From interior to exterior.
        n = packet.find("ipv4")

        msg = of.ofp_flow_mod()
        msg.match.dl_type = pkt.ethernet.IP_TYPE
        msg.match.nw_dst = n.dstip
        msg.buffer_id = buffer_id
        msg.actions.append(of.ofp_action_nw_addr.set_src(self.vhost.ip))
        msg.actions.append(of.ofp_action_dl_addr.set_src(self.vhost.mac))
        msg.actions.append(of.ofp_action_output(port=self.publicPort))

        self.connection.send(msg)
예제 #25
0
	def forwardProxy(self, packet, buffer_id):
		log.debug('Installing flow for forward proxy on switch %d' % self.dpid)

		# From exterior to interior.
		n = packet.find("ipv4")

		msg = of.ofp_flow_mod()
		msg.match.dl_type = pkt.ethernet.IP_TYPE;
		msg.match.nw_src = n.srcip
		msg.buffer_id = buffer_id
		msg.actions.append(of.ofp_action_nw_addr.set_dst(IPAddr('10.0.0.102')))
		msg.actions.append(of.ofp_action_dl_addr.set_dst(self.hosts[IPAddr('10.0.0.102')].mac))
		msg.actions.append(of.ofp_action_output(port = self.privatePort))
		
		self.connection.send(msg)
예제 #26
0
    def macLearning(self, packet):
        ip = None
        mac = packet.src

        if packet.find("ipv4"):
            n = packet.find("ipv4")
            ip = n.srcip
        elif packet.find("arp"):
            a = packet.find("arp")
            if a.prototype == a.PROTO_TYPE_IP:
                ip = a.protosrc

        if ip is not None and self.hosts.get(ip) is None:
            self.hosts[ip] = Host(ip, mac)
            log.debug('Learned: %s <=> %s' % (ip, mac))
 def flood():
     """ Hace un flood de los paquetes UNICAMENTE por los puertos habilitados por SPT """
     msg = of.ofp_packet_out()  # se crea el mensaje de flood
     time_diff = time.time() - self.connection.connect_time
     flood_ok = time_diff >= _flood_delay
     if flood_ok:
         # Realizar flood solo despues de que venza el tiempo de prevencion de flood
         log.debug("SWITCH_%i: FLOOD %s -> %s", self.switch_id, src_mac,
                   dst_mac)
         # Hacemos flood por todos los puertos excepto los bloqueados por el SPT
         msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD))
     else:
         log.debug("ESPERANDO FLOOD DE SWITCH %s , RESTAN %d SEGUNDOS" %
                   (self.switch_id, int(_flood_delay - time_diff)))
     msg.data = packet_in
     msg.in_port = in_port
     self.connection.send(msg)
예제 #28
0
    def forwardProxy(self, packet, buffer_id):
        log.debug('Installing flow for forward proxy on switch %d' % self.dpid)

        # From exterior to interior.
        n = packet.find("ipv4")

        msg = of.ofp_flow_mod()
        msg.match.dl_type = pkt.ethernet.IP_TYPE
        msg.match.nw_src = n.srcip
        msg.buffer_id = buffer_id
        msg.actions.append(of.ofp_action_nw_addr.set_dst(IPAddr('10.0.0.102')))
        msg.actions.append(
            of.ofp_action_dl_addr.set_dst(
                self.hosts[IPAddr('10.0.0.102')].mac))
        msg.actions.append(of.ofp_action_output(port=self.privatePort))

        self.connection.send(msg)
예제 #29
0
	def _handle_ConnectionUp(self, event):	
		if event.dpid == self.DPID_L2_SWITCH_CLIENTS or \
		   event.dpid == self.DPID_L2_SWITCH_SERVERS:
			# We make the switch which is connected by the clients (servers)
			# a learning switch so that the clients (servers) can communicate
			# with each other.
			# The switch is named 's1' ('s3') in Mininet.
			LearningSwitch(event.connection, False)
			log.debug('Learning switch %d' % event.dpid)
		elif event.dpid == self.DPID_BALANCER:
			# We make the switch which is connected by the servers a load-balancer.
			# The switch is named 's2' in Mininet.
			if self.balancer is None:
				self.balancer = LoadBalancer(1, 2)
			
			self.balancer.connect(event.connection)

			log.debug('Balancer switch %d' % event.dpid)
		else:
			log.error('Unrecognized switch (dpid = %d)' % event.dpid)
예제 #30
0
    def _handle_ConnectionUp(self, event):
        if event.dpid == self.DPID_L2_SWITCH_CLIENTS or \
           event.dpid == self.DPID_L2_SWITCH_SERVERS:
            # We make the switch which is connected by the clients (servers)
            # a learning switch so that the clients (servers) can communicate
            # with each other.
            # The switch is named 's1' ('s3') in Mininet.
            LearningSwitch(event.connection, False)
            log.debug('Learning switch %d' % event.dpid)
        elif event.dpid == self.DPID_BALANCER:
            # We make the switch which is connected by the servers a load-balancer.
            # The switch is named 's2' in Mininet.
            if self.balancer is None:
                self.balancer = LoadBalancer(1, 2)

            self.balancer.connect(event.connection)

            log.debug('Balancer switch %d' % event.dpid)
        else:
            log.error('Unrecognized switch (dpid = %d)' % event.dpid)
예제 #31
0
  def  learning_microflow_controller(self, dpid, packet, packet_in):
    
    connection = self.dpid_dict[dpid]["connection"]
    self.dpid_dict[dpid]["mac_to_port"][packet.src] = packet_in.in_port

    mac_to_port = self.dpid_dict[dpid]["mac_to_port"]
    # if dst is multicast flood it and return from the method
    if packet.dst.is_multicast:
        log.debug("Switch-{}: Type: {} . host {} --> FLOOD --> host {}".
                 format( str(dpid), pkt.ETHERNET.ethernet.getNameForType(packet.type),str(packet.src), str(packet.dst) ))
        
	self.flood( connection, packet, packet_in)
 
        self.install_rule( connection, 1, packet_in.in_port, packet.src, EthAddr("ff:ff:ff:ff:ff:ff"), of.OFPP_FLOOD, 200, packet.type)

    elif packet.dst in mac_to_port:
        out_port = mac_to_port[packet.dst]

        log.debug("Switch-{}: Type: {} . host {} --> port {} --> host {}".
	          format( dpid,  pkt.ETHERNET.ethernet.getNameForType(packet.type), str(packet.src), str(out_port), str(packet.dst)))
        
        self.resend_packet( connection, packet_in, out_port)
      
        # additionally, install a rule per flow (src, src-port, dst, dst-port)
        self.install_rule( connection, 1, packet_in.in_port, packet.src, packet.dst, out_port, GLOBAL_TIMEOUT, packet.type)
              
    else:
        log.debug("Switch-{}: Type: {} . host {} --> FLOOD --> host {}".
	          format( dpid, pkt.ETHERNET.ethernet.getNameForType(packet.type),str(packet.src), str(packet.dst) ))
        
        # Destination mac of packet not in our dictionary
	# flood the packet.
        self.flood( connection, packet, packet_in) 

    return
예제 #32
0
  def learning_controller(self, dpid, packet, packet_in):
          
    connection = self.dpid_dict[dpid]["connection"]
    self.dpid_dict[dpid]["mac_to_port"][packet.src] = packet_in.in_port
 
    mac_to_port = self.dpid_dict[dpid]["mac_to_port"]

    # if dst is multicast flood it and return from the method
    if packet.dst.is_multicast:
       log.debug("Switch-{}: Type: {} . host {} --> FLOOD --> host {}".
                 format( str(dpid), pkt.ETHERNET.ethernet.getNameForType(packet.type),str(packet.src), str(packet.dst) ))
       
       self.flood(connection, packet, packet_in)

    elif packet.dst in mac_to_port:
        out_port = mac_to_port[packet.dst]

        log.debug("Switch-{}: Type: {} . host {} --> port {} --> host {}".
	          format( str(dpid),  pkt.ETHERNET.ethernet.getNameForType(packet.type), str(packet.src), str(out_port), str(packet.dst)))
        
        # send packet to specific port
        self.resend_packet(connection, packet_in, out_port)
    else:
        log.debug("Switch-{}: Type: {} . host {} --> FLOOD --> host {}".
	          format( str(dpid), pkt.ETHERNET.ethernet.getNameForType(packet.type),str(packet.src), str(packet.dst) ))

        self.flood_packet(connection, packet, packet_in)

    return
def handle_flow_removed(event):
    """ Listener que maneja eliminaciones de flujos en switches. Escucha eventos tipo FlowRemoved """
    switch_id = event.connection.dpid
    match = event.ofp.match
    packet_count = event.ofp.packet_count

    if is_udp(match):
        dst_ip = match.get_nw_dst(
        )  # Tupla IP , bits_mascara. Ejemplo: (IPAddr('10.0.0.2'), 32)
        log.info(
            'SWITCH_%s: FLUJO REMOVIDO DE TIPO UDP CON DESTINO IP %s . packet_count: %s',
            switch_id, str(dst_ip[0]), packet_count)
        if packet_count > UDP_FIREWALL_THRESHOLD:
            # Si la cantidad de paquetes UDP supera el THRESHOLD establecido -> instalo un blackhole firewall
            blackhole_udp_packets(switch_id, FIREWALL_DURATION, dst_ip)
        else:
            # Si la cantidad de paquetes UDP para un destino baja luego de un tiempo, entonces se lo quita del blacklist de destinos bloqueados
            str_dst_ip = str(dst_ip[0])
            switch = switches[switch_id]
            switch.remove_firewall_ip(str_dst_ip)

    elif is_icmp(match):
        log.debug('SWITCH_%s: FLUJO REMOVIDO DE TIPO ICMP . packet_count: %s',
                  switch_id, packet_count)
    elif is_tcp(match):
        dst_ip = match.get_nw_dst(
        )  # Tupla IP , bits_mascara. Ejemplo: (IPAddr('10.0.0.2'), 32)
        log.debug(
            'SWITCH_%s: FLUJO REMOVIDO DE TIPO TCP CON DESTINO IP %s . packet_count: %s',
            switch_id, dst_ip, packet_count)
    else:
        log.debug('SWITCH_%s: FLUJO REMOVIDO packet_count: %s', switch_id,
                  packet_count)
예제 #34
0
    def _handle_LinkEvent(self, event):

        link = event.link

        dpid_source = link.dpid1
        dpid_dest = link.dpid2
        port_source = link.port1
        port_dest = link.port2

        if event.added:
            log.info(
                "Link added for switches S-{}:port-{} --> S-{}:port-{}".format(
                    dpid_source, port_source, dpid_dest, port_dest))
            self.dpid_dict[dpid_source]["links"].append(link)

            # Update our graph with new nodes/edges
            self.graph.add_edge(dpid_source,
                                dpid_dest,
                                ports={
                                    dpid_source: port_source,
                                    dpid_dest: port_dest
                                })
            log.debug("Graph Edges")
            log.debug(self.graph.edges())

        else:
            log.debug(
                "Link removed for switches S-{}:port-{} --> S-{}:port-{}".
                format(dpid_source, port_source, dpid_dest, port_dest))
예제 #35
0
def setup_logging(test_mode=False, log_file=None, log_folder=None, **kwargs):
    """
  Launch and set parameters for logging.

  :param test_mode: use test mode logging (default: False)
  :type test_mode: bool
  :param log_file: log file path
  :type log_file: str
  :return: None
  """
    global LOG_FOLDER
    if log_folder is not None:
        LOG_FOLDER = log_folder
    if not os.path.exists(LOG_FOLDER):
        os.makedirs(LOG_FOLDER)
    if log_file is None:
        log_file = os.path.join(LOG_FOLDER, "escape.log")
    # Enable logging in specific logging level
    level.launch(**kwargs)
    # Launch colorful logging
    color.launch()
    if test_mode:
        # Define logger for test mode
        pox.log.launch(format=TEST_LOGGER_FORMAT)
        log.debug("Setup Logger - formatter: %s, level: %s" %
                  (pox.log.launch.__module__,
                   logging.getLevelName(log.getEffectiveLevel())))
        # Set default log_file to log in file in test mode
    else:
        # Define default logger
        pox.log.launch(format=DEFAULT_LOGGER_FORMAT)
        log.debug("Setup logger - formatter: %s, level: %s" %
                  (setup_logging.__module__,
                   logging.getLevelName(log.getEffectiveLevel())))
    if log_file:
        # Define additional logger for logging to file
        pox.log.launch(format=FILE_LOGGER_FORMAT, file=log_file + ',w')
        log.debug("Setup Logger - formatter: %s, level: %s, file: %s" %
                  (pox.log.launch.__module__,
                   logging.getLevelName(log.getEffectiveLevel()), log_file))
 def handle_unknown():
     """ Maneja un paquete de tipo desconocido """
     log.debug('PAQUETE DESCONOCIDO DETECTADO DE TIPO %s::%s',
               eth_getNameForType, pkt_type_name)
     # TODO : VER QUE ES MEJOR , SI MANEJAR LOS PAQUETES DESCONOCIDOS O SI DROPEARLOS
     drop(30)
  def act_like_switch (self, packet, packet_in, dpid):
    """
    Implement switch-like behavior.
    1. Implementing a "simple" learning switch.
    """

    p = packet
    if p.find('ipv4'):
      log.debug(" => SWITCH[{2}]: Rcv {0} , packet_in: {1}".format(packet, packet_in, dpid))
      log.debug(" ==> Pkt Data:{0}".format(packet.dump()))
      while p:
        if isinstance(p, basestring):
          log.debug( "[%s bytes]={%s}" % (len(p),p) )
          break
        log.debug("[%s]=%s" % (p.__class__.__name__, p))
        p = p.next

    # Learn the port for the source MAC
    # log.debug(" ==> MAC: {0}->{1}".format(packet.src, packet.dst))
    self.mac_to_port[str(packet.src)] = packet_in.in_port

    is_halted = False 
    # log.debug(" ==> MAC2PORT: {0}".format(self.mac_to_port))
    port_out = self.mac_to_port.get(str(packet.dst))
    if port_out:
      is_authenticated = True
      if packet.find("ipv4"):
        # Authenticate a packet
        is_authenticated = self.authenticate(packet)
        log.debug("==> ipv4: packet auth={0}".format(is_authenticated))

      if is_authenticated:
        log.debug("Installing flow...")

        msg = of.ofp_flow_mod()

        # Exact match
        msg.match = of.ofp_match.from_packet(packet_in)
        msg.idle_timeout = 60
        msg.hard_timeout = 30 # for debugging purpose
        msg.buffer_id = packet_in.buffer_id
        msg.data = packet_in
        msg.actions.append(of.ofp_action_output(port=port_out))

        # log.debug(" ==> Msg: {0}".format(msg))
        # Send msg to swtich
        self.connection.send(msg)
      else:
        log.debug("==> Packet is not authenticated! Drop the packet")
        is_halted = True

    else:
      log.debug(" ==> Unknowd {0} -- Flood all".format(packet.dst))
      # Flood the packet out everything but the input port
      self.resend_packet(packet_in, of.OFPP_ALL)

    log.debug("------------------------------")
    return is_halted
예제 #38
0
    def act_like_switch(self, packet, packet_in, dpid):
        """
    Implement switch-like behavior.
    1. Implementing a "simple" learning switch.
    """

        p = packet
        if p.find('ipv4'):
            log.debug(" => SWITCH[{2}]: Rcv {0} , packet_in: {1}".format(
                packet, packet_in, dpid))
            log.debug(" ==> Pkt Data:{0}".format(packet.dump()))
            while p:
                if isinstance(p, basestring):
                    log.debug("[%s bytes]={%s}" % (len(p), p))
                    break
                log.debug("[%s]=%s" % (p.__class__.__name__, p))
                p = p.next

        # Learn the port for the source MAC
        # log.debug(" ==> MAC: {0}->{1}".format(packet.src, packet.dst))
        self.mac_to_port[str(packet.src)] = packet_in.in_port

        is_halted = False
        # log.debug(" ==> MAC2PORT: {0}".format(self.mac_to_port))
        port_out = self.mac_to_port.get(str(packet.dst))
        if port_out:
            is_authenticated = True
            if packet.find("ipv4"):
                # Authenticate a packet
                is_authenticated = self.authenticate(packet)
                log.debug("==> ipv4: packet auth={0}".format(is_authenticated))

            if is_authenticated:
                log.debug("Installing flow...")

                msg = of.ofp_flow_mod()

                # Exact match
                msg.match = of.ofp_match.from_packet(packet_in)
                msg.idle_timeout = 60
                msg.hard_timeout = 30  # for debugging purpose
                msg.buffer_id = packet_in.buffer_id
                msg.data = packet_in
                msg.actions.append(of.ofp_action_output(port=port_out))

                # log.debug(" ==> Msg: {0}".format(msg))
                # Send msg to swtich
                self.connection.send(msg)
            else:
                log.debug("==> Packet is not authenticated! Drop the packet")
                is_halted = True

        else:
            log.debug(" ==> Unknowd {0} -- Flood all".format(packet.dst))
            # Flood the packet out everything but the input port
            self.resend_packet(packet_in, of.OFPP_ALL)

        log.debug("------------------------------")
        return is_halted
예제 #39
0
  def policy_controller(self, dpid, packet, packet_in):
  
    connection = self.dpid_dict[dpid]["connection"]
    mac_to_port = self.dpid_dict[dpid]["mac_to_port"]

    # if protocol is IP then implement policies 
    # for all other traffic etc. ARP implement l2 switch
    if packet.type == packet.IP_TYPE: 
   
      ip_packet = packet.payload
      src_ip = ip_packet.srcip
      dst_ip = ip_packet.dstip  
      
      hosts = self.dpid_dict[dpid]["hosts"]
      links = self.dpid_dict[dpid]["links"]

      log.debug("Received IP packet from {} to {}, implementing policy!".format(src_ip, dst_ip))
     
      # implementing H1 H4 s3, H2 H4 s3 
      if (H1 == src_ip.toStr() or H2 == src_ip.toStr()) and H4 == dst_ip:

        log.debug("Implement policy from {} to {}. Should pass from upper switch".format(src_ip, dst_ip)) 
        
        # Can only infer switch identity only for hosts connected to us :(
        # if we are S1 install rule to send to S3 (switch with no hosts)
        if H1 in hosts or H2 in hosts:
 	  log.debug("In S1!")
            
          # should pass from S3, find link which dpid has no hosts :) 
          for link in links:
            next_dpid = link.dpid2
            own_port  = link.port1
            # check if link dictionary is empty for this dpid, if yes it is the right switch (S3)
            if not self.dpid_dict[next_dpid]["hosts"]:
              break

          log.debug("Installing flow at S1 for S3!")           
          self.install_ip_policy( connection, dpid, 1, packet_in.in_port, src_ip, dst_ip, own_port, GLOBAL_TIMEOUT)
	  self.resend_packet( connection, packet_in, own_port)

        # if we are S2 install rule to send directly to H4  
        elif H3 in hosts or H4 in hosts:
          log.debug("In S2!")
          
          # retrieve host data from hosts dictionary  
          dpid, own_port = self.hosts[dst_ip]

          log.debug("Installing rule and forwarding data to host!") 
          self.install_ip_policy( connection, dpid, 1, packet_in.in_port, src_ip, dst_ip, own_port, GLOBAL_TIMEOUT)
	  self.resend_packet( connection, packet_in, own_port)

        # if we are S3 install rule to send to S2 (switch with hosts H3,H4)
        else:
          log.debug("In S3!")

          for link in links:
            next_dpid = link.dpid2
            own_port  = link.port1
            # check if link dictionary is empty for this dpid, if yes it is the right switch (S3)
            if H3 in self.dpid_dict[next_dpid]["hosts"] or H4 in self.dpid_dict[next_dpid]["hosts"]:
              break

          log.debug("Installing flow for host!")           
          self.install_ip_policy( connection, dpid, 1, packet_in.in_port, src_ip, dst_ip, own_port, GLOBAL_TIMEOUT)
	  self.resend_packet( connection, packet_in, own_port)
           
      else:
        if H1 in hosts or H2 in hosts:
          log.debug("In S1")
        elif H3 in hosts or H4 in hosts:
          log.debug("In S2")
        else:
          log.debug("In S3") 

        # if dst_ip is connected to switch forward to host and install rule
        if dst_ip.toStr() in hosts: 
           dpid, own_port = self.hosts[dst_ip]
           
           log.debug("Installing rule and forwarding data to host!") 
           self.install_ip_policy( connection, dpid, 1, packet_in.in_port, src_ip, dst_ip, own_port, GLOBAL_TIMEOUT)
 	   self.resend_packet( connection, packet_in, own_port)
	else:
          
          # find dpid which host is connected to, from links to us
          for link in links:
            next_dpid = link.dpid2
            own_port  = link.port1
           
            # check in dpid connected to us if dst_ip is conencted to it, if yes install rule and forward
            if dst_ip.toStr() in self.dpid_dict[next_dpid]["hosts"]:
              break
 
          log.debug("Installing flow for host!")           
          self.install_ip_policy( connection, dpid, 1, packet_in.in_port, src_ip, dst_ip, own_port, GLOBAL_TIMEOUT)
	  self.resend_packet( connection, packet_in, own_port)
    else:
      self.learning_microflow_controller(dpid, packet, packet_in)
  def act_like_switch (self, packet, packet_in, dpid):
    """
    Implement switch-like behavior.
    """

    # log.debug(" => SWITCH[{2}]: Rcv {0} , packet_in: {1}".format(packet, packet_in, dplog.debug(" => SWITCH[{2}]: Rcv {0} , packet_in: {1}".format(packet, packet_in, dpid))
    log.debug(" => SWITCH[{2}]: Rcv {0}".format(packet, packet_in, dpid))

    # p = packet
    # if p.find('ipv4'):
    #   while p:
    #     if isinstance(p, basestring):
    #       log.debug( "[%s bytes]={%s}" % (len(p),p) )
    #       break
    #     log.debug("[%s]=%s" % (p.__class__.__name__, p))
    #     p = p.next

      # packet_in.data += "Lock is here"
      # # log.debug(" ==> Pkt Data:{0}".format(packet.dump()))
      # log.debug("  ++> Raw: {0}".format(packet.raw))
      # log.debug("  ==> PacketIn Date:{0}".format(packet_in.data[53:]))


    # Learn the port for the source MAC
    # log.debug(" ==> MAC: {0}->{1}".format(packet.src, packet.dst))
    self.mac_to_port[str(packet.src)] = packet_in.in_port

    # log.debug(" ==> MAC2PORT: {0}".format(self.mac_to_port))
    port_out = self.mac_to_port.get(str(packet.dst))
    if port_out:
      # Send packet out the associated port
      # self.resend_packet(packet_in, self.mac_to_port.get(str(packet.dst)))

      msg = None
      # If the packcet is ipv4, modify a raw packet to append encrypted data.
      # Otherwise, install a rule.

      # It is assumed that raw packet given from the switch is only first 128
      # bytes as a default POX setting.
      if packet.find("ipv4"):
        msg = of.ofp_packet_out(in_port=of.OFPP_NONE)
        mod_raw = packet.raw
        mod_raw += "auth=true"
        msg.data = mod_raw
        msg.actions.append(of.ofp_action_output(port=port_out))
        log.debug("==> IPv4: Added encrypted data to the packet.")
      else:
        msg = of.ofp_flow_mod()

        ## Set fields to match received packet
        # Exact match
        msg.match = of.ofp_match.from_packet(packet_in)
        msg.idle_timeout = 60
        msg.hard_timeout = 30 # for debugging purpose
        msg.buffer_id = packet_in.buffer_id
        msg.data = packet_in
        msg.actions.append(of.ofp_action_output(port=port_out))
        log.debug("==> Not IPv4: Send OF Mod")

      # Send msg to swtich
      self.connection.send(msg)

    else:
      log.debug(" ==> Unknowd {0} -- Flood all".format(packet.dst))
      # Flood the packet out everything but the input port
      self.resend_packet(packet_in, of.OFPP_ALL)


    log.debug("------------------------------")
 def start_switch (event):
   log.debug("Controlling %s" % (event.connection,))
   Tutorial(event.connection)
    def _handle_PacketIn(self, event):
        packet_in = event.ofp  # objeto EVENTO de tipo PACKET_IN.
        packet = event.parsed

        src_mac = packet.src  # MAC origen del paquete
        dst_mac = packet.dst  # MAC destino del paquete
        in_port = packet_in.in_port  # puerto de switch por donde ingreso el paquete

        # guardo la asociacion mac_origen -> puerto_entrada
        log.debug('SWITCH_%s: Asociando MAC %s a puerto de entrada %s',
                  self.switch_id, src_mac, in_port)
        self.mac_to_port[src_mac] = in_port

        eth_getNameForType = pkt.ETHERNET.ethernet.getNameForType(packet.type)
        # Parseo tempranamente los tipos de datos conocidos
        pkt_is_ipv6 = eth_getNameForType == 'IPV6'
        icmp_pkt = packet.find('icmp')
        tcp_pkt = packet.find('tcp')
        udp_pkt = packet.find('udp')
        pkt_is_arp = packet.type == packet.ARP_TYPE
        ip_pkt = packet.find('ipv4')

        # Obtengo el nombre 'imprimible' del paquete
        pkt_type_name = eth_getNameForType
        if icmp_pkt: pkt_type_name = 'ICMP'
        if tcp_pkt: pkt_type_name = 'TCP'
        if udp_pkt: pkt_type_name = 'UDP'
        if pkt_is_arp: pkt_type_name = 'ARP'

        def build_flow_key():
            """ Crea la clave de un flujo a partir de campos disponibles del paquete procesado """
            flow_key = pkt_type_name + '#'
            if ip_pkt: flow_key += str(ip_pkt.srcip) + 'to' + str(ip_pkt.dstip)
            if tcp_pkt:
                flow_key += ':' + str(tcp_pkt.dstport) + "-" + str(tcp_pkt.ACK)
            # TODO ... PARA UDP SE DEBEN CONSTRUIR FLUJOS DISTINTOS PARA LA IDA Y LA VUELTA... CONSIDERAR USAR LA MAC
            if udp_pkt: flow_key += ':' + str(udp_pkt.dstport)
            if icmp_pkt: flow_key += '-' + str(icmp_pkt.type)
            log.info("SWITCH_%s: flow_key = %s", self.switch_id, flow_key)
            return flow_key

        def install_flow(out_port, duration=FLOW_INSTALL_DURATION):
            """ Instala un flujo en el switch del tipo MAC_ORIGEN@PUERTO_ENTRADA -> MAC_DESTINO@PUERTO_SALIDA """
            if not pkt_is_arp:
                log.info(
                    "SWITCH_%s: Instale un flujo de %s@PUERTO_%i hacia %s@PUERTO_%i de tipo %s"
                    % (self.switch_id, src_mac, in_port, dst_mac, out_port,
                       pkt_type_name))
            msg = of.ofp_flow_mod()
            msg.match = of.ofp_match.from_packet(packet, in_port)
            msg.idle_timeout = duration
            msg.hard_timeout = duration
            msg.actions.append(of.ofp_action_output(port=out_port))
            msg.data = packet_in
            # OFPFF_SEND_FLOW_REM indica al switch que debe notificar al controlador cuando un flujo haya sido dado de baja. Ver funcion handle_flow_removed
            # OFPFF_CHECK_OVERLAP pide al switch que verifique overlap de reglas de flujo
            msg.flags = of.OFPFF_SEND_FLOW_REM + of.OFPFF_CHECK_OVERLAP
            self.connection.send(msg)

        def drop(duration=None):
            """
      Dropea el paquete y opcionalmente instala un flujo en el switch para que siga dropeando paquetes de este tipo.
      NOTA: PODRIA USARSE PARA EL FIREWALL
      """
            if duration is not None:
                if not isinstance(duration, tuple):
                    duration = (duration, duration)
                msg = of.ofp_flow_mod()
                msg.match = of.ofp_match.from_packet(packet)
                msg.idle_timeout = duration[0]
                msg.hard_timeout = duration[1]
                msg.buffer_id = packet_in.buffer_id
                msg.actions.append(of.ofp_action_output(
                    port=of.OFPP_NONE))  # Enviar el paquete a la NADA
                self.connection.send(msg)
            elif packet_in.buffer_id is not None:
                msg = of.ofp_packet_out()
                msg.buffer_id = packet_in.buffer_id
                msg.in_port = in_port
                msg.actions.append(of.ofp_action_output(
                    port=of.OFPP_NONE))  # Enviar el paquete a la NADA
                self.connection.send(msg)

        def flood():
            """ Hace un flood de los paquetes UNICAMENTE por los puertos habilitados por SPT """
            msg = of.ofp_packet_out()  # se crea el mensaje de flood
            time_diff = time.time() - self.connection.connect_time
            flood_ok = time_diff >= _flood_delay
            if flood_ok:
                # Realizar flood solo despues de que venza el tiempo de prevencion de flood
                log.debug("SWITCH_%i: FLOOD %s -> %s", self.switch_id, src_mac,
                          dst_mac)
                # Hacemos flood por todos los puertos excepto los bloqueados por el SPT
                msg.actions.append(of.ofp_action_output(port=of.OFPP_FLOOD))
            else:
                log.debug("ESPERANDO FLOOD DE SWITCH %s , RESTAN %d SEGUNDOS" %
                          (self.switch_id, int(_flood_delay - time_diff)))
            msg.data = packet_in
            msg.in_port = in_port
            self.connection.send(msg)

        def handle_all():
            """ Maneja los paquetes de forma generica """
            # TODO : MODIFICAR ESTE COMPORTAMIENTO PARA SOPORTAR ECMP
            # NOTA : dado que instalar un flujo demora tiempo, handle_all se esta llamando multiples veces...
            # si el puerto de salida se encuentra en la tabla de MACs entonces instalo un flujo en el switch
            if dst_mac in self.mac_to_port:
                out_port = self.mac_to_port[dst_mac]
                install_flow(out_port)
            else:
                flood()

        def handle_dhcp():
            """ Maneja paquetes DHCP ... Pensar si acaso deberian dropearse... """
            dstip = ip_pkt.dstip
            log.debug('MANEJANDO PAQUETE DHCP HACIA IP %s' % str(dstip))
            handle_all()

        def install_path_flow(out_port, duration=FLOW_INSTALL_DURATION):
            """ Instala un flujo selectivo a partir de un path """
            log.info(
                "SWITCH_%s: Instalando flujo a partir de path %s@PUERTO_%i -> %s@PUERTO_%i de tipo %s"
                % (self.switch_id, src_mac, in_port, dst_mac, out_port,
                   pkt_type_name))
            msg = of.ofp_flow_mod()

            if udp_pkt:
                udp_dst_port = udp_pkt.dstport
                msg.match = of.ofp_match(dl_type=IP_dl_type,
                                         nw_proto=UDP_nw_proto,
                                         tp_dst=udp_dst_port)
            elif tcp_pkt:
                tcp_dst_port = tcp_pkt.dstport
                msg.match = of.ofp_match(dl_type=IP_dl_type,
                                         nw_proto=TCP_nw_proto,
                                         tp_dst=tcp_dst_port)
            else:
                msg.match = of.ofp_match(dl_type=IP_dl_type,
                                         nw_proto=ICMP_nw_proto)
            str_dst_ip = ip_pkt.dstip
            msg.match.set_nw_dst(str_dst_ip, 32)

            msg.idle_timeout = duration
            msg.hard_timeout = duration
            msg.actions.append(of.ofp_action_output(port=out_port))
            msg.data = packet_in
            # OFPFF_SEND_FLOW_REM indica al switch que debe notificar al controlador cuando un flujo haya sido dado de baja. Ver funcion handle_flow_removed
            # OFPFF_CHECK_OVERLAP pide al switch que verifique overlap de reglas de flujo
            msg.flags = of.OFPFF_SEND_FLOW_REM + of.OFPFF_CHECK_OVERLAP
            self.connection.send(msg)

        def handle_ip_complex():
            """ Maneja paquetes tipo ip """
            dst_mac_str = str(dst_mac)  # obtengo el string de mac destino
            log.info("SWITCH_%s: Mac destino es %s", self.switch_id,
                     dst_mac_str)

            # si el host destino es desconocido, entonces me falta conocer a mas hosts y manejo el paquete como un switch bobo
            if dst_mac_str not in hosts: return handle_all()

            host_switch_port = get_host_switch_port(dst_mac_str,
                                                    self.switch_id)
            # si la mac destino es de un host y este switch esta directamente conectado al mismo, entonces instalo un flujo inmediatamente
            if host_switch_port is not None:
                log.info(
                    'SWITCH_%s: La Mac destino %s corresponde a un host conectado a MI puerto %d!',
                    self.switch_id, dst_mac_str, host_switch_port)
                return install_flow(host_switch_port)

            # TODOOOOOOOOOO : VERIFICAR SI ACASO SE DEBE USAR install_flow EN VEZ DE install_path_flow

            # verifico si ya existe un path asignado a este flujo
            flow_key = build_flow_key()
            if flow_key in current_paths:
                path = current_paths[flow_key]
                log.info('SWITCH_%s: el path %s esta asignado al flow_key %s',
                         self.switch_id, str(path), flow_key)
                # instalo un flujo para forwardear el paquete
                switch_switch_link = get_switch_switch_link(
                    self.switch_id, path)
                if switch_switch_link is not None:
                    out_port = switch_switch_link.port1
                    log.info(
                        "SWITCH_%s: El paquete debe salir por mi puerto %d",
                        self.switch_id, out_port)
                    return install_flow(out_port)
                    #return install_path_flow(out_port)
                else:
                    log.warn(
                        'SWITCH_%s: encontre un path... pero yo no tengo enlace ALGO ESTA MAL',
                        self.switch_id)
                    return handle_all()

            # si llegue a este punto es porque no hay un path asignado al camino indicado... probablemente este switch es de borde
            # debo solicitar un camino libre y asignarlo
            host = get_host_by_mac(dst_mac)
            if host is not None:
                end_switch_id = host[
                    'switch_id']  # obtengo el id del switch al cual esta conectado el host destino
                # busco o bien un camino libre o cualquier camino en caso de no existir ninguno libre
                log.info("SWITCH_%s: Busco un path hacia switch %s",
                         self.switch_id, end_switch_id)
                path = find_non_taken_path(self.switch_id, end_switch_id)
                if path is None:
                    path = find_any_path(self.switch_id, end_switch_id)
                path_str = str(path)
                log.info(
                    "SWITCH_%s: Voy a usar el path %s y se lo asigno al flujo %s",
                    self.switch_id, path_str, flow_key)
                # guardo la asociacion entre la clave del flujo y el path encontrado
                current_paths[flow_key] = path
                # marco al path encontrado como TOMADO
                taken_paths.add(path_str)
                # incremento la cantidad de veces que el camino esta siendo usado
                current_paths_load[path_str] += 1
                # instalo un flujo para forwardear el paquete
                switch_switch_link = get_switch_switch_link(
                    self.switch_id, path)
                if switch_switch_link is not None:
                    out_port = switch_switch_link.port1
                    install_flow(out_port)

                    #return install_path_flow(out_port)
                    def remove_taken_path():
                        log.info("SWITCH_%s: ELIMINANDO PATH %s DE FLUJO %s",
                                 self.switch_id, path_str, flow_key)
                        if path_str in taken_paths:
                            taken_paths.remove(path_str)
                        if flow_key in current_paths:
                            current_paths.pop(flow_key)
                        current_paths_load[path_str] -= 1

                    # despues de un tiempo elimino el path de flujo instalado
                    Timer(FLOW_INSTALL_DURATION, remove_taken_path)
                    return True

                else:
                    log.warn(
                        'SWITCH_%s: encontre un path... pero yo no tengo enlace ALGO ESTA MAL',
                        self.switch_id)
                    return handle_all()

            # condicion fallback ... manejo el paquete como puedo
            handle_all()

        def handle_ip():
            if HANDLE_IP_COMPLEX: return handle_ip_complex()
            else: return handle_all()

        def handle_udp():
            """ Maneja paquetes UDP. Si detecta que un destino esta bloqueado por un firewall, descarta el paquete """
            dstip = ip_pkt.dstip
            str_dst_ip = str(dstip)
            if str_dst_ip in self.firewall_ips:
                log.info(
                    'SWITCH_%s PAQUETES CON DESTINO %s SIGUEN BLOQUEADOS... REALIZANDO DROP',
                    self.switch_id, str_dst_ip)
                drop()
                return
            dstport = udp_pkt.dstport
            if dstport == DHCP_PORT: return handle_dhcp()
            handle_ip()

        def handle_unknown():
            """ Maneja un paquete de tipo desconocido """
            log.debug('PAQUETE DESCONOCIDO DETECTADO DE TIPO %s::%s',
                      eth_getNameForType, pkt_type_name)
            # TODO : VER QUE ES MEJOR , SI MANEJAR LOS PAQUETES DESCONOCIDOS O SI DROPEARLOS
            drop(30)
            #handle_all()

        # LOS PAQUETES DESCONOCIDOS SON DROPEADOS. POR AHORA IGNORAMOS LOS PAQUETES IPV6
        # DADO QUE ESTAMOS USANDO host_tracker, DEBEMOS MANEJAR LOS PAQUETES ARP (NO DROPEAR)
        unknown_pkt = pkt_is_ipv6 or (icmp_pkt is None and tcp_pkt is None
                                      and udp_pkt is None and not pkt_is_arp)
        if unknown_pkt: return handle_unknown()

        # los paquetes ARP los despacho inmediatamente sin crear ni reservar flujos
        if pkt_is_arp: return handle_all()

        log.debug(
            'SWITCH_%s@PORT_%d LLEGO PAQUETE TIPO %s::%s MAC_ORIGEN: %s MAC_DESTINO: %s'
            % (self.switch_id, in_port, eth_getNameForType, pkt_type_name,
               src_mac, dst_mac))

        # por alguna razon bizarra... esta linea rompe
        # si la mac es ff:ff:ff:ff:ff:ff entonces hago un flood
        #if dst_mac.is_multicast: flood()

        # si el mac origen es igual al mac destino entonces dropeo
        if src_mac == dst_mac:
            log.info("SWITCH_%s: MAC ORIGEN ES IGUAL A MAC DESTINO!",
                     self.switch_id)
            drop()

        if udp_pkt: return handle_udp()

        if ip_pkt: return handle_ip()

        handle_all()
 def handle_dhcp():
     """ Maneja paquetes DHCP ... Pensar si acaso deberian dropearse... """
     dstip = ip_pkt.dstip
     log.debug('MANEJANDO PAQUETE DHCP HACIA IP %s' % str(dstip))
     handle_all()
예제 #44
0
    def policy_controller(self, dpid, packet, packet_in):

        connection = self.dpid_dict[dpid]["connection"]
        mac_to_port = self.dpid_dict[dpid]["mac_to_port"]

        # if protocol is IP then implement policies
        # for all other traffic etc. ARP implement l2 switch
        if packet.type == packet.IP_TYPE:

            ip_packet = packet.payload
            src_ip = ip_packet.srcip
            dst_ip = ip_packet.dstip

            hosts = self.dpid_dict[dpid]["hosts"]
            links = self.dpid_dict[dpid]["links"]

            # This will be the path of switches that will be chosen
            chosen_path = []

            src_switch, src_port = self.hosts[src_ip]
            dst_switch, dst_port = self.hosts[dst_ip]

            # Check to see if we have to apply policy
            if (src_ip.toStr(), dst_ip.toStr()) in self.policies:
                policy_dpid = self.policies[src_ip.toStr(), dst_ip.toStr()]
                log.debug(
                    "Have to implement policy from {} to {} through switch {}".
                    format(src_ip.toStr(), dst_ip.toStr(), policy_dpid))

                # Get all simple paths between the switches connected to the hosts
                simple_paths = nx.all_simple_paths(self.graph, src_switch,
                                                   dst_switch)
                for simple_path in simple_paths:
                    if policy_dpid in simple_path:
                        chosen_path = simple_path
                        break

                if chosen_path == []:
                    log.info(
                        "Could not satisfy policy. Choosing shortest path!")
                    chosen_path = nx.shortest_path(self.graph, src_switch,
                                                   dst_switch)
            else:
                log.debug("Have to use shortest path!")
                chosen_path = nx.shortest_path(self.graph, src_switch,
                                               dst_switch)

            log.debug("Will use path:")
            log.debug(chosen_path)

            chosen_edges = [(chosen_path[i], chosen_path[i + 1])
                            for i in xrange(0,
                                            len(chosen_path) - 1)]

            edge_path = []
            switch_order = chosen_path
            for edge in chosen_edges:
                port1 = self.graph[edge[0]][edge[1]]['ports'][edge[0]]
                port2 = self.graph[edge[0]][edge[1]]['ports'][edge[1]]
                edge_path.append((port1, port2))

            edge_path.insert(0, (1, src_port))
            edge_path.append((dst_port, 1))

            # Install IP rules for all the switches in the path
            for i in xrange(0, len(edge_path) - 1):
                switch_dpid = switch_order[i]
                switch_connection = self.dpid_dict[switch_dpid]["connection"]
                src_port, dst_port = (edge_path[i][1], edge_path[i + 1][0])
                log.debug(
                    "Installing policy on switch {}. {} -> {} with ports {} -> {}"
                    .format(switch_dpid, src_ip, dst_ip, src_port, dst_port))
                self.install_ip_policy(switch_connection, switch_dpid, 1000,
                                       src_port, src_ip, dst_ip, dst_port,
                                       1000)

            self.resend_packet(connection, packet_in, edge_path[1][0])
        else:
            # Packet is not IP
            self.learning_microflow_controller(dpid, packet, packet_in)