[英]Mininet topology is not completing the iperf command from the 2 hosts separated by 2 switches
I'm trying to complete the mininet topology exercise from this website https://github.com/mininet/openflow-tutorial/wiki/Advanced-Topology .我正在尝试从这个网站https://github.com/mininet/openflow-tutorial/wiki/Advanced-Topology完成 mininet 拓扑练习。 Basically I have to create a topology like this:
基本上我必须创建这样的拓扑:
h1-----s1---s2----h3 h1-----s1---s2----h3
(there is also another host attached to s1 called h2) (还有另一个主机连接到 s1,称为 h2)
and program a POX controller to install flows to the switches so that the pingall
and iperf
commands work.并对 POX 控制器进行编程以将流安装到交换机,以便
pingall
和iperf
命令工作。 Everything works fine except for the iperf
command which fails when it runs from h1 to h3 or from h2 to h3.除了在从 h1 到 h3 或从 h2 到 h3 运行时失败的
iperf
命令之外,一切正常。
This is the code I have, and I believe the problem has to do with communicating to the right switch what to do with packets of a type different than arp or icmp , but I've been stuck too long on this problem and have decided to ask for help here.这是我的代码,我相信问题与与正确的交换机通信有关如何处理与arp或icmp不同类型的数据包,但我在这个问题上被困了太久,并决定在这里寻求帮助。
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)
EDIT:编辑:
I solved this by flooding IP_packets directed to h3, to all ports except the in_port我通过将指向 h3 的 IP_packets 泛洪到除 in_port 之外的所有端口来解决此问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.