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?
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)
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?
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)
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)
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))
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)
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)