Mininet 拓扑未从由 2 个交换机分隔的 2 个主机完成 iperf 命令

Mininet topology is not completing the iperf command from the 2 hosts separated by 2 switches

我正在尝试从该网站完成 mininet 拓扑练习 https://github.com/mininet/openflow-tutorial/wiki/Advanced-Topology。 基本上我必须创建这样的拓扑:

h1-----s1---s2----h3

(还有另一台主机连接到 s1,称为 h2)

并对 POX 控制器进行编程以将流程安装到交换机,以便 pingalliperf 命令起作用。 一切正常,除了 iperf 命令在从 h1 运行到 h3 或从 h2 运行到 h3 时失败。

这是我的代码,我相信问题与与正确的交换机通信有关如何处理不同于 arpicmp,但我在这个问题上纠结太久了,决定在这里寻求帮助。

from pox.core import core
import pox.openflow.libopenflow_01 as of
import pox.lib.packet as pkt #ipv4, arp..
import pox.lib.addresses as adr #EthAddr , IPAddr ..

log = core.getLogger()



class Tutorial (object):
    def __init__ (self, connection):

        # Keep track of the connection to the switch so that we can
        # send it messages!
        self.connection = connection

        # This binds our PacketIn event listener
        connection.addListeners(self)

        self.dpid_table = {'10.0.1.1': 1, '10.0.2.1': 2}
        # Use this table to keep track of which ethernet address is on
        # which switch port (keys are MACs, values are ports).
        self.ip_to_port = {'10.0.1.2':1, '10.0.1.3':2, '10.0.2.2':3}
        self.mac_to_port = {}

        self.routing_table = {
                '10.0.1.0/24': [['10.0.1.2', 's1-eth1', '10.0.1.1', 1, '00:00:00:00:00:01'],
                                ['10.0.1.3', 's1-eth2', '10.0.1.1', 2, '00:00:00:00:00:02']],

                '10.0.2.0/24': ['10.0.2.2', 's2-eth1', '10.0.2.1', 3, '00:00:00:00:00:03'],
                 }

def FlowMode(self, packet_in, out_port):
    print("Creating Flow...")

    msg = of.ofp_flow_mod()
    msg.match.in_port = packet_in.in_port
    #msg_match = of.ofp_match(dl_type = pkt.ethernet.IP_TYPE, nw_proto = pkt.ipv4.IPv4)
    msg.idle_timeout = 15
    msg.buffer_id = packet_in.buffer_id
    action = of.ofp_action_output(port = out_port)
    msg.actions.append(action)
    self.connection.send(msg)

        print("flow created")
def act_like_router (self, packet, packet_in):

    #handle ARP Requests and replies
    etherPayload = packet.payload #the stripped ethFrame, contains ipv4 or arp packet

    if packet.type == pkt.ethernet.ARP_TYPE:
        #etherPayload is an ARP packet
                src_ip = etherPayload.protosrc
                dst_ip = etherPayload.protodst
        if etherPayload.opcode == pkt.arp.REQUEST:
            print("ARP REQUEST received by controller....\n Constructing reply...")
            arp_reply = pkt.arp()
            arp_reply.hwsrc = adr.EthAddr("11:12:13:14:15:16") #fake mac in response
                    arp_reply.hwdst = etherPayload.hwsrc
            arp_reply.opcode = pkt.arp.REPLY
            arp_reply.protosrc = etherPayload.protodst
            arp_reply.protodst = etherPayload.protosrc

            #encapsulate in ethernet frame now
            ether = pkt.ethernet()
            ether.type = pkt.ethernet.ARP_TYPE
            ether.dst = packet.src
            ether.src = packet.dst
            ether.payload = arp_reply

            msg = of.ofp_packet_out()
            msg.data = ether.pack()
            action = of.ofp_action_output(port = packet_in.in_port)
            msg.actions.append(action)
            self.connection.send(msg)
            #send to switch, will have to implement flow instead

            #self.resend_packet(ether, packet_in.in_port)
            print("ARP Reply sent!")

        elif etherPayload.opcode == pkt.arp.REPLY:
                    if src_ip not in self.arp_table:
                            self.arp_table[str(src_ip)] = etherPayload.hwsrc
                            self.mac_to_port[etherPayload.hwsrc] = packet_in.in_port
                print("ARP REPLY received by controller updating tables")
                print(self.mac_to_port)
                print(self.arp_table)
            #else:
                #self.mac_to_port[etherPayload.hwsrc] = packet_in.in_port
        else:
            print("some other ARP OPCODE received")
    elif packet.type == pkt.ethernet.IP_TYPE:
        #etherPayload is an IP packet
        if etherPayload.protocol == pkt.ipv4.ICMP_PROTOCOL:
            icmp_packet = etherPayload.payload
            if icmp_packet.type == pkt.TYPE_ECHO_REQUEST:
                print("received ping request...\n creating echo_reply message")
                src_ip = etherPayload.srcip
                dst_ip = etherPayload.dstip

                k = 0
                #check if destination exist in any of the subnets
                for subnet in self.routing_table.keys():
                    if dst_ip.inNetwork(subnet): #possible mistake here maybe turn dst_ip into IPADDR obj
                        k = subnet
                        break
                if k!=0:

                    #host exists create and send echo reply
                    print('Sending reply to network  ' + str(k))

                    #create echo fields
                    ech = pkt.echo() #echo contained in pkt.icmp
                    ech.id = icmp_packet.payload.id
                    ech.seq = icmp_packet.payload.seq + 1

                    #encapsulates in icmp
                    icmp_reply = pkt.icmp()
                    icmp_reply.type = pkt.TYPE_ECHO_REPLY #code 0
                    icmp_reply.payload = ech

                    #encapsulates in ipv4
                    ip_p = pkt.ipv4()
                    ip_p.protocol = pkt.ipv4.ICMP_PROTOCOL
                    ip_p.srcip = dst_ip
                    ip_p.dstip = src_ip
                    ip_p.payload = icmp_reply

                    #encapsulates in ethernet
                    eth_p = pkt.ethernet()
                    eth_p.type = pkt.ethernet.IP_TYPE
                    eth_p.src = packet.dst
                    eth_p.dst = packet.src
                    eth_p.payload = ip_p

                    msg = of.ofp_packet_out()
                    msg.data = eth_p.pack()
                    action = of.ofp_action_output(port = packet_in.in_port)
                    print("sending reply from: " + str(dst_ip) + " to: " + str(src_ip) + " using packet_in.in_port: " + str(packet_in.in_port))
                    msg.actions.append(action)
                    self.connection.send(msg)
                    #send to switch, will have to implement flow instead
                    #self.resend_packet(eth_p, packet_in.in_port)
                    print("echo Reply sent!")


                else:
                    #host doesn't exist send dst unreachable
                    print("ICMP destination unreachable")

                    unr = pkt.unreach()
                    unr.payload = etherPayload

                    icmp_reply = pkt.icmp()
                    icmp_reply.type = pkt.TYPE_DEST_UNREACH
                    icmp_reply.payload = unr

                    ip_p = pkt.ipv4()
                    ip_p.srcip = dst_ip
                    ip_p.dstip = src_ip
                    ip_p.protocol = pkt.ipv4.ICMP_PROTOCOL
                    ip_p.payload = icmp_reply

                    eth_p = pkt.ethernet()
                    eth_p.type = pkt.ethernet.IP_TYPE
                    eth_p.dst = packet.src
                    eth_p.src = packet.dst
                    eth_p.payload = ip_p

                    msg = of.ofp_packet_out()
                    msg.data = eth_p.pack()
                    action = of.ofp_action_output(port = packet_in.in_port)
                    #print("sending reply from: " + str(dst_ip) + " to: " + str(src_ip) + " using packet_in.in_port: " + str(packet_in.in_port))
                    msg.actions.append(action)
                    self.connection.send(msg)
                    #send to switch, will have to implement flow instead
                    #self.resend_packet(eth_p, packet_in.in_port)
                    log.debug("echo Reply sent!")

        #se non e` ICMP
        else:

            print("received some ip packet...\n handling it... ")
            src_ip = etherPayload.srcip
            dst_ip = etherPayload.dstip

            k = 0
            #check if destination exist in any of the subnets
            '''
            self.routing_table = {
            '10.0.1.0/24': ['10.0.1.2', 's1-eth1', '10.0.1.1', 1, '00:00:00:00:00:02'],

            ['10.0.1.3', 's1-eth2', '10.0.1.1', 2, '00:00:00:00:00:03']
            '''
            for subnet in self.routing_table.keys():

                if dst_ip.inNetwork(subnet):
                    k = subnet
                    break

            if k!=0:

                port1 = self.ip_to_port[str(dst_ip)] #get port to communicate on that subnet
                if str(dst_ip) == '10.0.1.2':
                    #ethDest = adr.EthAddr("4e:2d:32:b9:bc:52")
                    ethDest = adr.EthAddr(self.routing_table[subnet][0][4])
                    msg = of.ofp_packet_out()
                    action = of.ofp_action_output(port = port1)
                    packet.src = packet.dst
                    packet.dst = ethDest#adr.EthAddr('11:11:11:11:11:11')#ethDest
                    msg.data = packet.pack()
                    msg.actions.append(action)
                    self.connection.send(msg)
                    print("installing flow for packets for: " + str(dst_ip))
                    self.FlowMode(packet_in, packet_in.in_port)

                elif str(dst_ip) == '10.0.1.3':
                                #ethDest = adr.EthAddr("22:02:eb:9c:27:2d")
                    ethDest = adr.EthAddr(self.routing_table[subnet][1][4])
                    msg = of.ofp_packet_out()
                    action = of.ofp_action_output(port = port1)
                    packet.src = packet.dst
                    packet.dst = ethDest#adr.EthAddr('11:11:11:11:11:11')#ethDest
                    msg.data = packet.pack()
                    msg.actions.append(action)
                    self.connection.send(msg)
                    print("installing flow for packets for: " + str(dst_ip))
                    self.FlowMode(packet_in, packet_in.in_port)
                elif str(dst_ip) == '10.0.2.2':
                    ethDest = adr.EthAddr(self.routing_table[subnet][4])

                    if packet_in.in_port == 1 and self.connection.dpid == 1:
                        outport = 3
                        msg = of.ofp_packet_out()
                        action = of.ofp_action_output(port = outport)
                        packet.src = packet.dst
                        packet.dst = ethDest
                        msg.data = packet.pack()
                        msg.actions.append(action)
                        self.connection.send(msg)
                        print("installing flow for packets for: " + str(dst_ip) + " to switch number: " + str(connection.dpid)
                                + str(etherPayload.id))
                        self.FlowMode(packet_in, packet_in.in_port)
                    elif (packet_in.in_port == 2 or packet_in.in_port == 3)  and self.connection.dpid == 1:
                        outport = 1
                        msg = of.ofp_packet_out()
                        action = of.ofp_action_output(port = outport)
                        packet.src = packet.dst
                        packet.dst = ethDest
                        msg.data = packet.pack()
                        msg.actions.append(action)
                        self.connection.send(msg)
                        print("installing flow for packets for: " + str(dst_ip) + " to switch number: " + str(self.connection.dpid)
                                + str(etherPayload.id))
                        self.FlowMode(packet_in, packet_in.in_port)
                    elif packet_in.in_port == 1 and self.connection.dpid == 2:
                        outport = 3
                        msg = of.ofp_packet_out()
                        action = of.ofp_action_output(port = outport)
                        packet.src = packet.dst
                        packet.dst = ethDest
                        msg.data = packet.pack()
                        msg.actions.append(action)
                        self.connection.send(msg)
                        print("installing flow for packets for: " + str(dst_ip) + " to switch number: " + str(self.connection.dpid)
                                + str(etherPayload.id))
                        self.FlowMode(packet_in, packet_in.in_port)
                    elif(packet_in.in_port == 2 or packet_in.in_port == 3)  and self.connection.dpid == 2:
                        outport = 1
                        msg = of.ofp_packet_out()
                        action = of.ofp_action_output(port = outport)
                        packet.src = packet.dst
                        packet.dst = ethDest
                        msg.data = packet.pack()
                        msg.actions.append(action)
                        self.connection.send(msg)
                        print("installing flow for packets for: " + str(dst_ip) + " to switch number: " + str(self.connection.dpid)
                                + str(etherPayload.id))
                        self.FlowMode(packet_in, packet_in.in_port)


                '''
                router_msg = of.ofp_flow_mod()
                router_msg.match = of.ofp_match.from_packet(packet)
                router_msg.idle_timeout = 100
                router_msg.buffer_id = packet_in.buffer_id
                action = of.ofp_action_output(port = packet_in.in_port)
                router_msg.actions.append(action)
                self.connection.send(router_msg)
                '''





    #don't forget flow mode


def _handle_PacketIn (self, event):
    """
    Handles packet in messages from the switch.
    """
    packet = event.parsed # This is the ethernet packet.
    if not packet.parsed:
        log.warning("Ignoring incomplete packet")
        return

    packet_in = event.ofp # The actual ofp_packet_in message.




    self.act_like_router(packet, packet_in)

def resend_packet(self, packet_in, out_port):
    """
    Instructs the switch to resend a packet that it had sent to us.
    "packet_in" is the ofp_packet_in object the switch had sent to the
    controller due to a table-miss.
    """
    msg = of.ofp_packet_out()
    msg.data = packet_in.pack()

    # Add an action to send to the specified port
    action = of.ofp_action_output(port=out_port)
    msg.actions.append(action)

    # Send message to switch
    self.connection.send(msg)



def launch ():
    """
    Starts the component
    """
    def start_switch (event):
        log.debug("Controlling %s" % (event.connection,))
        Tutorial(event.connection)
    core.openflow.addListenerByName("ConnectionUp", start_switch)

编辑:

我通过将 IP_packets 泛洪到 h3 到除了 in_port

之外的所有端口来解决这个问题