예제 #1
0
    def do_l2_learning(self, con, inport, packet):
        """
    Dado um pacote, aprenda a fonte e o peg para um switch/inport.
    :param con: Fonte do pacote.
    :param inport: Porta de entrada.
    :param packet: Pacote recebido.
    :return: Sem retorno.
    """
        """Given a packet, learn the source and peg to a switch/inport 
    """
        # learn MAC on incoming port
        srcaddr = EthAddr(packet.src)
        #if ord(srcaddr[0]) & 1:
        #  return
        if self.st[con].has_key(srcaddr.toStr()):  # change to raw?
            # we had already heard from this switch
            dst = self.st[con][srcaddr.toStr()]  # raw?
            if dst[0] != inport:
                # but from a different port
                log.info('MAC has moved from ' + str(dst) + 'to' + str(inport))
            else:
                return
        else:
            log.info('learned MAC ' + srcaddr.toStr() +
                     ' on Switch %s, Port %d' % (con.dpid, inport))

        # learn or update timestamp of entry
        self.st[con][srcaddr.toStr()] = (inport, time(), packet)  # raw?
예제 #2
0
    def forward_l2_packet(self, con, inport, packet, buf, bufid):
        """
    Tenta aprender o destino MAC instituído à um fluxo e enviar apenas fora de suas portas de entrada.
    Se não, usa inundação.
    :param con: Fonte do pacote.
    :param inport: Porta de entrada.
    :param packet: Pacote recebido.
    :param buf: Tamanho do Buffer.
    :param bufid: ID do Buffer.
    :return: Sem retorno.
    """
        """If we've learned the destination MAC set up a flow and
    send only out of its inport.  Else, flood.
    """
        dstaddr = EthAddr(packet.dst)
        #if not ord(dstaddr[0]) & 1 and  # what did this do?
        if self.st[con].has_key(dstaddr.toStr()):  # raw?
            prt = self.st[con][dstaddr.toStr()]  # raw?
            if prt[0] == inport:
                log.warning('**warning** learned port = inport')
                ofcommand.floodPacket(con, inport, packet, buf, bufid)

            else:
                # We know the outport, set up a flow
                log.info('installing flow for ' + str(packet))
                match = ofcommand.extractMatch(packet)
                actions = [ofcommand.Output(prt[0])]
                ofcommand.addFlowEntry(con, inport, match, actions, bufid)
                # Separate bufid, make addFlowEntry() only ADD the entry
                # send/wait for Barrier
                # sendBufferedPacket(bufid)
        else:
            # haven't learned destination MAC. Flood
            ofcommand.floodPacket(con, inport, packet, buf, bufid)
예제 #3
0
 def do_l2_learning(self, con, inport, packet):
   """Given a packet, learn the source and peg to a switch/inport 
   """
   # learn MAC on incoming port
   srcaddr = EthAddr(packet.src)
   #if ord(srcaddr[0]) & 1:
   #  return
   if self.st[con].has_key(srcaddr.toStr()):   # change to raw?
     # we had already heard from this switch
     dst = self.st[con][srcaddr.toStr()]            # raw?
     if dst[0] != inport:
       # but from a different port
       log.info('MAC has moved from '+str(dst)+'to'+str(inport))
     else:
       return
   else:
     log.info('learned MAC '+srcaddr.toStr()+' on Switch %s, Port %d'% (con.dpid,inport))
     
   # learn or update timestamp of entry
   self.st[con][srcaddr.toStr()] = (inport, time(), packet)           # raw?
예제 #4
0
 def forward_l2_packet(self, con, inport, packet, buf, bufid):   
   """If we've learned the destination MAC set up a flow and
   send only out of its inport.  Else, flood.
   """
   dstaddr = EthAddr(packet.dst)
   #if not ord(dstaddr[0]) & 1 and  # what did this do?
   if self.st[con].has_key(dstaddr.toStr()):   # raw?
     prt = self.st[con][dstaddr.toStr()]                          # raw?
     if  prt[0] == inport:
       log.warning('**warning** learned port = inport')
       ofcommand.floodPacket(con, inport, packet, buf, bufid)
 
     else:
       # We know the outport, set up a flow
       log.info('installing flow for ' + str(packet))
       match = ofcommand.extractMatch(packet)
       actions = [ofcommand.Output(prt[0])]
       ofcommand.addFlowEntry(con, inport, match, actions, bufid)
       # Separate bufid, make addFlowEntry() only ADD the entry
       # send/wait for Barrier
       # sendBufferedPacket(bufid)
   else:    
     # haven't learned destination MAC. Flood 
     ofcommand.floodPacket(con, inport, packet, buf, bufid)
예제 #5
0
    def forward_l2_packet(self, con, inport, packet, buf, bufid):
        """If we've learned the destination MAC set up a flow and
    send only out of its inport.  Else, flood.
    """
        dstaddr = EthAddr(packet.dst)
        #if not ord(dstaddr[0]) & 1 and  # what did this do?
        if self.st[con].has_key(dstaddr.toStr()):  # raw?
            prt = self.st[con][dstaddr.toStr()]  # raw?
            if prt[0] == inport:
                log.warning('**warning** learned port = inport')
                ofcommand.floodPacket(con, inport, packet, buf, bufid)

            else:
                # We know the outport, set up a flow
                log.info('installing flow for ' + str(packet))
                match = ofcommand.extractMatch(packet)
                actions = [ofcommand.Output(prt[0])]
                ofcommand.addFlowEntry(con, inport, match, actions, bufid)
                # Separate bufid, make addFlowEntry() only ADD the entry
                # send/wait for Barrier
                # sendBufferedPacket(bufid)
        else:
            # haven't learned destination MAC. Flood
            ofcommand.floodPacket(con, inport, packet, buf, bufid)
예제 #6
0
    def act_like_lswitch(self, packet, packet_in):
        """
    Implement switch-like behavior.
    """

        # Learn the port for the source MAC if necessary
        srcaddr = EthAddr(packet.src)
        if not self.macStore.has_key(srcaddr.toStr()):
            self.macStore[srcaddr.toStr()] = packet_in.in_port
            log.debug("New Host detected with MAC %s on Port %s" %
                      (srcaddr.toStr(), packet_in.in_port))

        # Check if we have the destination in our store
        dstaddr = EthAddr(packet.dst)
        if self.macStore.has_key(dstaddr.toStr()):
            # Yes, it might bee a good idea to install a flowtable entry,
            # otherwise we have to ask the controller every time
            fm = of.ofp_flow_mod()
            fm.match.in_port = packet_in.in_port
            fm.match.dl_dst = dstaddr
            fm.actions.append(
                of.ofp_action_output(port=self.macStore[dstaddr.toStr()]))
            #fm.idle_timeout = 10
            #fm.hard_timeout = 30
            log.debug("Installing FlowTable entry")
            self.connection.send(fm)

            # We wont loose this package, so we forward it
            # to its destination
            self.send_packet(packet_in.buffer_id, packet_in.data,
                             self.macStore[dstaddr.toStr()], packet_in.in_port)
            log.debug("Package <" + str(packet_in.buffer_id) +
                      "> forwarded by controller over Port " +
                      str(self.macStore[dstaddr.toStr()]))

        else:
            # Flood the packet out everything but the input port.
            # We are here, because we just put the source MAC and port
            # in our store and don't no the destination Port,
            # thus the Flood is the only thing we can do.
            self.act_like_hub(packet, packet_in)
            log.debug("Package <" + str(packet_in.buffer_id) +
                      "> flooded by controller")
  def act_like_lswitch (self, packet, packet_in):
    """
    Implement switch-like behavior.
    """
 
    # Learn the port for the source MAC if necessary
    srcaddr = EthAddr(packet.src)
    if not self.macStore.has_key(srcaddr.toStr()):
      self.macStore[srcaddr.toStr()] = packet_in.in_port
      log.debug("New Host detected with MAC %s on Port %s" % (srcaddr.toStr(), packet_in.in_port))
 
    # Check if we have the destination in our store
    dstaddr = EthAddr(packet.dst)
    if self.macStore.has_key(dstaddr.toStr()):
      # Yes, it might bee a good idea to install a flowtable entry,
      # otherwise we have to ask the controller every time
      fm = of.ofp_flow_mod()
      fm.match.in_port = packet_in.in_port
      fm.match.dl_dst = dstaddr
      fm.actions.append(of.ofp_action_output(port = self.macStore[dstaddr.toStr()]))
      #fm.idle_timeout = 10
      #fm.hard_timeout = 30
      log.debug("Installing FlowTable entry")
      self.connection.send(fm)
 
      # We wont loose this package, so we forward it
      # to its destination
      self.send_packet(packet_in.buffer_id, packet_in.data, self.macStore[dstaddr.toStr()], packet_in.in_port)
      log.debug("Package <"+str(packet_in.buffer_id)+"> forwarded by controller over Port "+str(self.macStore[dstaddr.toStr()]))
 
    else:
      # Flood the packet out everything but the input port.
      # We are here, because we just put the source MAC and port
      # in our store and don't no the destination Port, 
      # thus the Flood is the only thing we can do.
      self.act_like_hub(packet, packet_in)
      log.debug("Package <"+str(packet_in.buffer_id)+"> flooded by controller")
  def _handle_PacketIn (self, event):
    global foo
    """
    Handles packet in messages from the switch.
    """
 
    packet = event.parsed # This is the parsed packet data.
    
    log.debug("here")
    #self.check_migration()
    log.debug(packet)
    log.debug(packet.__dict__)
    log.debug("there") 
    if(foo==[] or foo[0] == '\n'):
        foo = filter(None,open("/home/mininet/migrationVaribles","r").read().split(' '))
        
    log.debug("there2")
    log.debug(foo)
    log.debug("there1")
    

    srcaddr = EthAddr(packet.src)
    dstaddr = EthAddr(packet.dst)
    if countDictionary.has_key(srcaddr.toStr()):
        countDictionary[srcaddr] = countDictionary[srcaddr] + 1
    else:
        countDictionary[srcaddr] = 0
     
    if countDictionary.has_key(dstaddr.toStr()):
        countDictionary[dstaddr] = countDictionary[dstaddr] + 1
    else:
        countDictionary[dstaddr] = 0
    
    if not packet.parsed:
      log.warning("Ignoring incomplete packet")
      return
 
    packet_in = event.ofp # The actual ofp_packet_in message.
    

 
    if(foo!=[]):
        if(foo[0]!='\n'):
            log.debug("yaha aayaa ")
            if srcaddr.toStr() == foo[0]:
                log.debug("yaha 1")
                self.update(foo[1], packet, packet_in)
            elif dstaddr.toStr() == foo[0]:
                log.debug("yaha 2")

                self.update(foo[1], packet, packet_in)
            if dstaddr.toStr() == foo[0]:
                log.debug("yaha 3")

                self.update(foo[1], packet, packet_in)
            elif srcaddr.toStr() == foo[1]:
                log.debug("yaha 1")

                self.update(foo[0], packet, packet_in)

    # This line calls the function act_like_lswitch and passes
    # the parsed package and the openflow packet message to our
    # learning switch
    self.act_like_lswitch(packet, packet_in)
예제 #9
0
    def handle_packet(self, packet, packet_in):

        global matching_flow
        srcmac = EthAddr(packet.src)
        dstmac = EthAddr(packet.dst)

        print(packet)

        arpp = packet.find('arp')
        icmpp = packet.find('icmp')
        ipp = packet.find('ipv4')
        ip6p = packet.find('ipv6')
        tcpp = packet.find('tcp')
        udpp = packet.find('udp')

        l4p = tcpp if tcpp else udpp

        # MAC-Adresse -> Port lernen
        if srcmac.toStr() not in self.mac_table:
            self.mac_table[srcmac.toStr()] = packet_in.in_port

        # ARP und ICMP blind weiterleiten
        if arpp or icmpp:
            self.send_packet(packet, dstmac.toStr(), packet_in.in_port)
            return

        # IPv6 ignorieren
        if ip6p:
            return

        # Treffer?
        match = False

        # TCP-IP-Paket
        if ipp and l4p:
            srcip = ipp.srcip
            dstip = ipp.dstip
            srcport = l4p.srcport
            dstport = l4p.dstport

            for flow in flows:
                matching_flow = flow
                srcip_matches = True if flow.src_ip is None else srcip == flow.src_ip
                dstip_matches = True if flow.dst_ip is None else dstip == flow.dst_ip
                srcport_matches = True if flow.src_port is None else srcport == flow.src_port
                dstport_matches = True if flow.dst_port is None else dstport == flow.dst_port

                # @formatter:off
                if (
                    srcip_matches and
                    dstip_matches and
                    srcport_matches and
                    dstport_matches
                ):
                    match = True
                    break
                else:
                    match = False
                # @formatter:on

        if match:
            log.info('Paket {0} passt zu {1}'.format(packet, matching_flow))
            self.send_packet(packet, dstmac.toStr(), packet_in.in_port)
        else:
            log.warning('Keine passenden Flows, Paket {0} wird verworfen'.format(packet))
예제 #10
0
def launch_namespace(cmd,
                     guest_ip_addr_str,
                     iface_number,
                     prefix_length=24,
                     host_ip_addr_str="",
                     guest_hw_addr=None,
                     cwd=None,
                     env=None):
    '''
  Set up and launch cmd in a new network namespace.

  Returns a pair:
   (raw socket bound to host veth interface,
    Popen object for communicating with guest namespace)

  This method uses functionality that requires CAP_NET_ADMIN capabilites. This
  means that the calling method should check that the python process was
  launched as admin/superuser.

  Parameters:
    - cmd: the string to launch, in a separate namespace
    - ip_addr_str: the ip address to assign to the namespace's interace.
                   Must be a string! not a IPAddr object
    - iface_number: unique integer for the namespace and host virtual interfaces.
    - guest_hw_addr: mac address for the guest (auto generated if None)
  '''
    if system() != 'Linux':
        raise EnvironmentError(
            'network namespace functionality requires a Linux environment')

    uid = os.geteuid()
    if uid != 0:
        # user must have CAP_NET_ADMIN, which doesn't have to be su, but most often is
        raise EnvironmentError(
            "superuser privileges required to launch network namespace")

    host_device = "heth%s" % str(iface_number)
    guest_device = "geth%s" % str(iface_number)

    try:
        # Clean up previous network namespaces
        # (Delete the device if it already exists)
        with open(os.devnull, 'wb') as null:
            for dev in (host_device, guest_device):
                if subprocess.call(['ip', 'link', 'show', dev],
                                   stdout=null,
                                   stderr=null) == 0:
                    subprocess.check_call(['ip', 'link', 'del', dev])

        # create a veth pair and set the host end to be promiscuous
        add_cmd = [
            'ip', 'link', 'add', 'name', host_device, 'type', 'veth', 'peer',
            'name', guest_device
        ]
        if guest_hw_addr:
            guest_hw_addr = EthAddr(guest_hw_addr)
            add_cmd.append('address')
            add_cmd.append(guest_hw_addr.toStr())
        subprocess.check_call(add_cmd)
        guest_eth_addr = get_eth_address_for_interface(guest_device)
        log.debug("Guest ETH %s" % guest_eth_addr)
        host_eth_addr = get_eth_address_for_interface(host_device)
        log.debug("Host ETH %s" % host_eth_addr)

        subprocess.check_call(
            ['ip', 'link', 'set', host_device, 'promisc', 'on'])
        # Our end of the veth pair
        subprocess.check_call(['ip', 'link', 'set', host_device, 'up'])
        if host_ip_addr_str != "":
            # Set a host IP on the same subnet as the guest so that host sockets automatically get
            # bound to the correct virtual interface.
            subprocess.check_call([
                'ip', 'addr', 'add',
                "%s/%d" % (host_ip_addr_str, prefix_length), 'dev', host_device
            ])
    except subprocess.CalledProcessError:
        raise  # TODO raise a more informative exception

    # all else should have succeeded, so now we fork and unshare for the guest
    # TODO(cs): use popen_filtered here?
    guest = subprocess.Popen(["unshare", "-n", "--", "/bin/bash"],
                             stdin=subprocess.PIPE,
                             env=env,
                             cwd=cwd)

    # push down the guest device into the netns
    try:
        subprocess.check_call(
            ['ip', 'link', 'set', guest_device, 'netns',
             str(guest.pid)])
    except subprocess.CalledProcessError:
        raise  # TODO raise a more informative exception

    # Bring up the interface on the guest.
    guest.stdin.write("ip link set %s up\n" % guest_device)
    # Set the IP address of the virtual interface. Note that this has the nice
    # side effect that the host can open sockets to the IP address (since the
    # guest will begin responding to ARPs).
    guest.stdin.write("ip addr add %s/%d dev %s\n" %
                      (guest_ip_addr_str, prefix_length, guest_device))

    # Send the command.
    guest.stdin.write(cmd + "\n")

    return (guest, guest_eth_addr, host_device)
예제 #11
0
def launch_namespace(cmd, guest_ip_addr_str, iface_number, prefix_length=24,
                     host_ip_addr_str="", guest_hw_addr=None, cwd=None,
                     env=None):
  '''
  Set up and launch cmd in a new network namespace.

  Returns a pair:
   (raw socket bound to host veth interface,
    Popen object for communicating with guest namespace)

  This method uses functionality that requires CAP_NET_ADMIN capabilites. This
  means that the calling method should check that the python process was
  launched as admin/superuser.

  Parameters:
    - cmd: the string to launch, in a separate namespace
    - ip_addr_str: the ip address to assign to the namespace's interace.
                   Must be a string! not a IPAddr object
    - iface_number: unique integer for the namespace and host virtual interfaces.
    - guest_hw_addr: mac address for the guest (auto generated if None)
  '''
  if system() != 'Linux':
    raise EnvironmentError('network namespace functionality requires a Linux environment')

  uid = os.geteuid()
  if uid != 0:
    # user must have CAP_NET_ADMIN, which doesn't have to be su, but most often is
    raise EnvironmentError("superuser privileges required to launch network namespace")

  host_device = "heth%s" % str(iface_number)
  guest_device = "geth%s" % str(iface_number)

  try:
    # Clean up previous network namespaces
    # (Delete the device if it already exists)
    with open(os.devnull, 'wb') as null:
      for dev in (host_device, guest_device):
        if subprocess.call(['ip', 'link', 'show', dev], stdout=null, stderr=null) == 0:
          subprocess.check_call(['ip', 'link', 'del', dev])

    # create a veth pair and set the host end to be promiscuous
    add_cmd = ['ip','link','add','name',host_device,'type','veth','peer',
               'name',guest_device]
    if guest_hw_addr:
      guest_hw_addr = EthAddr(guest_hw_addr)
      add_cmd.append('address')
      add_cmd.append(guest_hw_addr.toStr())
    subprocess.check_call(add_cmd)
    guest_eth_addr = get_eth_address_for_interface(guest_device)
    log.debug("Guest ETH %s" % guest_eth_addr)
    host_eth_addr = get_eth_address_for_interface(host_device)
    log.debug("Host ETH %s" % host_eth_addr)

    subprocess.check_call(['ip','link','set',host_device,'promisc','on'])
    # Our end of the veth pair
    subprocess.check_call(['ip','link','set',host_device,'up'])
    if host_ip_addr_str != "":
      # Set a host IP on the same subnet as the guest so that host sockets automatically get
      # bound to the correct virtual interface.
      subprocess.check_call(['ip', 'addr', 'add', "%s/%d" % (host_ip_addr_str, prefix_length), 'dev', host_device])
  except subprocess.CalledProcessError:
    raise # TODO raise a more informative exception


  # all else should have succeeded, so now we fork and unshare for the guest
  # TODO(cs): use popen_filtered here?
  guest = subprocess.Popen(["unshare", "-n", "--", "/bin/bash"],
                           stdin=subprocess.PIPE, env=env, cwd=cwd)

  # push down the guest device into the netns
  try:
    subprocess.check_call(['ip', 'link', 'set', guest_device, 'netns', str(guest.pid)])
  except subprocess.CalledProcessError:
    raise # TODO raise a more informative exception

  # Bring up the interface on the guest.
  guest.stdin.write("ip link set %s up\n" % guest_device)
  # Set the IP address of the virtual interface. Note that this has the nice
  # side effect that the host can open sockets to the IP address (since the
  # guest will begin responding to ARPs).
  guest.stdin.write("ip addr add %s/%d dev %s\n" % (guest_ip_addr_str, prefix_length, guest_device))

  # Send the command.
  guest.stdin.write(cmd + "\n")

  return (guest, guest_eth_addr, host_device)