diff --git a/Uebung1/Aufgabe1.3.mn b/Uebung1/Aufgabe1.3.mn deleted file mode 100644 index 5a47545..0000000 --- a/Uebung1/Aufgabe1.3.mn +++ /dev/null @@ -1,153 +0,0 @@ -{ - "application": { - "dpctl": "", - "ipBase": "10.0.0.0/8", - "netflow": { - "nflowAddId": "0", - "nflowTarget": "", - "nflowTimeout": "600" - }, - "openFlowVersions": { - "ovsOf10": "0", - "ovsOf11": "0", - "ovsOf12": "0", - "ovsOf13": "1" - }, - "sflow": { - "sflowHeader": "128", - "sflowPolling": "30", - "sflowSampling": "400", - "sflowTarget": "" - }, - "startCLI": "1", - "switchType": "ovs", - "terminalType": "xterm" - }, - "controllers": [ - { - "opts": { - "controllerProtocol": "tcp", - "controllerType": "remote", - "hostname": "c0", - "remoteIP": "127.0.0.1", - "remotePort": 6633 - }, - "x": "791.0", - "y": "340.0" - } - ], - "hosts": [ - { - "number": "3", - "opts": { - "defaultRoute": "10.0.3.62", - "hostname": "h3", - "ip": "10.0.3.1/26", - "nodeNum": 3, - "sched": "host" - }, - "x": "754.0", - "y": "143.0" - }, - { - "number": "4", - "opts": { - "defaultRoute": "10.0.4.2", - "hostname": "h4", - "ip": "10.0.4.1/30", - "nodeNum": 4, - "sched": "host" - }, - "x": "355.0", - "y": "444.0" - }, - { - "number": "2", - "opts": { - "defaultRoute": "10.0.2.254", - "hostname": "h2", - "ip": "10.0.2.1/24", - "nodeNum": 2, - "sched": "host" - }, - "x": "300.0", - "y": "145.0" - }, - { - "number": "1", - "opts": { - "defaultRoute": "10.0.1.14", - "hostname": "h1", - "ip": "10.0.1.1/28", - "nodeNum": 1, - "sched": "host" - }, - "x": "452.0", - "y": "66.0" - } - ], - "links": [ - { - "dest": "h4", - "opts": {}, - "src": "s2" - }, - { - "dest": "s2", - "opts": {}, - "src": "s1" - }, - { - "dest": "s1", - "opts": {}, - "src": "h2" - }, - { - "dest": "s1", - "opts": {}, - "src": "h1" - }, - { - "dest": "h3", - "opts": {}, - "src": "s1" - } - ], - "switches": [ - { - "number": "1", - "opts": { - "controllers": [ - "c0" - ], - "dpid": "1", - "hostname": "s1", - "netflow": "0", - "nodeNum": 1, - "sflow": "0", - "switchIP": "", - "switchType": "default" - }, - "x": "576.0", - "y": "181.0" - }, - { - "number": "2", - "opts": { - "controllers": [ - "c0" - ], - "dpid": "2", - "hostname": "s2", - "netflow": "0", - "nodeNum": 2, - "sflow": "0", - "switchIP": "", - "switchType": "default" - }, - "x": "357.0", - "y": "300.0" - } - ], - "version": "2" -} \ No newline at end of file diff --git a/Uebung1/controller_1_3.py b/Uebung1/controller_1_3.py index 49bbb6c..b964a47 100644 --- a/Uebung1/controller_1_3.py +++ b/Uebung1/controller_1_3.py @@ -1,3 +1,6 @@ +# Abgabe von: +# Jutta Seth, Janek Schoffit, Eva Hoegner +# Problem 1.3 (IP Router for IPv4) from ryu.base import app_manager from ryu.controller import ofp_event from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER @@ -11,10 +14,14 @@ from ryu.lib.packet import icmp from ryu.lib.packet.arp import arp from ryu.lib.packet.packet import Packet +# For IP address subnet matching +import ipaddress + + class L3Switch(app_manager.RyuApp): OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION] - IP_ADDR = ["10.0.1.14", "10.0.2.254", "10.0.2.252", "10.0.3.62", "10.0.4.2"] + IP_ADDR = ["10.0.2.254", "10.0.2.252", "10.0.1.14", "10.0.3.62", "10.0.4.2"] MAC_ADDR = ["52:00:00:00:00:01", "52:00:00:00:00:02"] def __init__(self, *args, **kwargs): @@ -40,30 +47,6 @@ class L3Switch(app_manager.RyuApp): ofproto.OFPCML_NO_BUFFER)] self.add_flow(datapath, 0, match, actions) - self.logger.info("Add new action for: ") - self.logger.info(datapath.id) - # Routing Switch 2 to 1 - if datapath.id == 2: - actions = [parser.OFPActionDecNwTtl(), #decrease TTL count - parser.OFPActionSetField(eth_src=self.MAC_ADDR[1]), # set own mac as source - parser.OFPActionSetField(eth_dst=self.MAC_ADDR[0]), # set dst switch - parser.OFPActionOutput(1)] - - match = parser.OFPMatch(ipv4_src=("10.0.4.1", "255.255.255.252"), ipv4_dst=("10.0.1.1", "255.255.255.240"), eth_type=0x0800) - #match = parser.OFPMatch(ipv4_src="10.0.4.1", ipv4_dst="10.0.1.1", eth_type=0x0800) - self.add_flow(datapath, 0, match, actions) - - # Routing Switch 1 to 2 - if datapath.id == 1: - actions = [parser.OFPActionDecNwTtl(), #decrease TTL count - parser.OFPActionSetField(eth_src=self.MAC_ADDR[0]), # set own mac as source - parser.OFPActionSetField(eth_dst=self.MAC_ADDR[1]), # set dst switch - parser.OFPActionOutput(4)] - - match = parser.OFPMatch(ipv4_dst=("10.0.4.1", "255.255.255.252"), eth_type=0x0800) - self.add_flow(datapath, 0, match, actions) - - def add_flow(self, datapath, priority, match, actions, buffer_id=None): ofproto = datapath.ofproto @@ -109,16 +92,17 @@ class L3Switch(app_manager.RyuApp): dpid = datapath.id ofproto = datapath.ofproto parser = datapath.ofproto_parser + macaddr = self.MAC_ADDR[dpid-1] arpPacket = packet.get_protocol(arp) if arpPacket.opcode == 1 : # arp request arp_dstIp = arpPacket.dst_ip - self.logger.info('received ARP Request %s => %s (port%d)'%(frame.src, frame.dst, inPort)) + self.logger.info('received ARP Request %s => %s (port%d, ip: %s)'%(frame.src, frame.dst, inPort, arp_dstIp)) if arp_dstIp in self.IP_ADDR: # this switch was requested opcode = 2 - srcMAC = self.MAC_ADDR[dpid-1] + srcMAC = macaddr srcIP = arp_dstIp dstMAC = frame.src dstIP = arpPacket.src_ip @@ -191,13 +175,14 @@ class L3Switch(app_manager.RyuApp): self.send_packet(datapath, outPort, p) def do_icmp(self, datapath, port, pkt_ethernet, pkt_ipv4, pkt_icmp): - dpid = datapath.id + self.logger.info(pkt_icmp.type) + self.logger.info(icmp.ICMP_ECHO_REQUEST) if pkt_icmp.type != icmp.ICMP_ECHO_REQUEST: return pkt = packet.Packet() pkt.add_protocol(ethernet.ethernet(ethertype=pkt_ethernet.ethertype, dst=pkt_ethernet.src, - src=self.MAC_ADDR[dpid])) + src=self.MAC_ADDR[datapath.id-1])) pkt.add_protocol(ipv4.ipv4(dst=pkt_ipv4.src, src=pkt_ipv4.dst, proto=pkt_ipv4.proto)) @@ -205,7 +190,8 @@ class L3Switch(app_manager.RyuApp): code=icmp.ICMP_ECHO_REPLY_CODE, csum=0, data=pkt_icmp.data)) - self.logger.info("do icmp: %s" %(pkt)) + self.logger.info("do icmp: %s" %(pkt,)) + self.logger.info("port: %s" %(port)) self.send_packet(datapath, port, pkt) def do_l2_switch(self, datapath, dpid, packet, frame, in_port, buffer_id=None): @@ -242,21 +228,59 @@ class L3Switch(app_manager.RyuApp): parser = datapath.ofproto_parser if ipv4_pkt.dst in self.ip_to_mac[dpid]: - # GEt mac and port of the given destination + # Get mac and port of the given destination dstMac = self.ip_to_mac[dpid][ipv4_pkt.dst] out_port = self.mac_to_port[dpid][dstMac] else: + # This flow is for the second switch if the address is in range 10.0.0.0-10.0.3.255 + # The ipaddress module assumes an IP adress as a unicode string (python 2.7 default for a string is ascii encoding) + if datapath.id == 2 and ipaddress.ip_address(unicode(ipv4_pkt.dst)) in ipaddress.ip_network(unicode("10.0.0.0/22")): + actions = [parser.OFPActionDecNwTtl(), #decrease TTL count + parser.OFPActionSetField(eth_src=self.MAC_ADDR[1]), # set own mac as source + parser.OFPActionSetField(eth_dst=self.MAC_ADDR[0]), # set dst switch + parser.OFPActionOutput(2)] + + match = parser.OFPMatch(ipv4_dst=("10.0.0.0", "255.255.252.0"), eth_dst=self.MAC_ADDR[1], eth_type=0x0800) + self.add_flow(datapath, 1, match, actions) + + data = None + if buffer_id == ofproto.OFP_NO_BUFFER: + data = packet.data + out = parser.OFPPacketOut(datapath=datapath, buffer_id=buffer_id, + in_port=in_port, actions=actions, data=data) + datapath.send_msg(out) + return + + # Add a flow for the first switch if the ipadress matches network 4. + if datapath.id == 1 and ipaddress.ip_address(unicode(ipv4_pkt.dst)) in ipaddress.ip_network(unicode("10.0.4.0/30")): + actions = [parser.OFPActionDecNwTtl(), #decrease TTL count + parser.OFPActionSetField(eth_src=self.MAC_ADDR[0]), # set own mac as source + parser.OFPActionSetField(eth_dst=self.MAC_ADDR[1]), # set dst switch + parser.OFPActionOutput(1)] + + match = parser.OFPMatch(ipv4_dst=("10.0.4.0", "255.255.255.252"), eth_dst=self.MAC_ADDR[0], eth_type=0x0800) + self.add_flow(datapath, 1, match, actions) + + data = None + if buffer_id == ofproto.OFP_NO_BUFFER: + data = packet.data + out = parser.OFPPacketOut(datapath=datapath, buffer_id=buffer_id, + in_port=in_port, actions=actions, data=data) + datapath.send_msg(out) + return + + # Send an arp request and define mac and port # so we're able to apply the following actions # on the packet. out_port = ofproto.OFPP_FLOOD dstMac = "FF:FF:FF:FF:FF:FF" - self.send_arp(datapath, 1, self.MAC_ADDR[dpid-1], ipv4_pkt.src, dstMac, ipv4_pkt.dst, out_port) + self.send_arp(datapath, 1, self.MAC_ADDR[datapath.id-1], ipv4_pkt.src, dstMac, ipv4_pkt.dst, out_port) # Actions are applied in the same order as defined in the list. # OFPActionOutput terminates the chain. So this call should be the last action. actions = [parser.OFPActionDecNwTtl(), #decrease TTL count - parser.OFPActionSetField(eth_src=self.MAC_ADDR[1]), # set own mac as source + parser.OFPActionSetField(eth_src=self.MAC_ADDR[datapath.id-1]), # set own mac as source parser.OFPActionSetField(eth_dst=dstMac), # set dst from arp request parser.OFPActionOutput(out_port)] # forward packet through out_port @@ -313,17 +337,18 @@ class L3Switch(app_manager.RyuApp): self.logger.info("packet in dpid: %s, src: %s, dest: %s, in_port: %s", dpid, src, dst, in_port) - self.logger.info(pkt) + #self.logger.info(pkt) #learn mac to port mapping if src not in self.mac_to_port[dpid]: self.mac_to_port[dpid][src] = in_port - if eth.ethertype == ether_types.ETH_TYPE_ARP: + if eth.ethertype == ether_types.ETH_TYPE_ARP and src not in self.MAC_ADDR: self.do_arp(datapath, pkt, eth, in_port) return if eth.ethertype == ether_types.ETH_TYPE_IP: ipv4_pkt = pkt.get_protocol(ipv4.ipv4) + self.logger.info("IP src: %s, dst: %s", ipv4_pkt.src, ipv4_pkt.dst) #check if packet is for this switch if ipv4_pkt.dst in self.IP_ADDR: @@ -333,11 +358,10 @@ class L3Switch(app_manager.RyuApp): else: # forward the package into a different subnet self.do_l3_switch(datapath, dpid, pkt, eth, ipv4_pkt, in_port, msg.buffer_id) - return # packet is not for this switch, so do l2 switching - if dst != self.MAC_ADDR[dpid - 1]: + if dst != self.MAC_ADDR[dpid-1]: self.do_l2_switch(datapath, dpid, pkt, eth, in_port, msg.buffer_id) return return diff --git a/Uebung1/controller_1_3_1.py b/Uebung1/controller_1_3_1.py deleted file mode 100644 index b964a47..0000000 --- a/Uebung1/controller_1_3_1.py +++ /dev/null @@ -1,367 +0,0 @@ -# Abgabe von: -# Jutta Seth, Janek Schoffit, Eva Hoegner -# Problem 1.3 (IP Router for IPv4) -from ryu.base import app_manager -from ryu.controller import ofp_event -from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER -from ryu.controller.handler import set_ev_cls -from ryu.ofproto import ofproto_v1_3 -from ryu.lib.packet import packet -from ryu.lib.packet import ethernet -from ryu.lib.packet import ether_types -from ryu.lib.packet import ipv4 -from ryu.lib.packet import icmp -from ryu.lib.packet.arp import arp -from ryu.lib.packet.packet import Packet - -# For IP address subnet matching -import ipaddress - - -class L3Switch(app_manager.RyuApp): - OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION] - - IP_ADDR = ["10.0.2.254", "10.0.2.252", "10.0.1.14", "10.0.3.62", "10.0.4.2"] - MAC_ADDR = ["52:00:00:00:00:01", "52:00:00:00:00:02"] - - def __init__(self, *args, **kwargs): - super(L3Switch, self).__init__(*args, **kwargs) - self.mac_to_port = {} - self.ip_to_mac = {} - - @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER) - def switch_features_handler(self, ev): - datapath = ev.msg.datapath - ofproto = datapath.ofproto - parser = datapath.ofproto_parser - - # install table-miss flow entry - # - # We specify NO BUFFER to max_len of the output action due to - # OVS bug. At this moment, if we specify a lesser number, e.g., - # 128, OVS will send Packet-In with invalid buffer_id and - # truncated packet data. In that case, we cannot output packets - # correctly. The bug has been fixed in OVS v2.1.0. - match = parser.OFPMatch() - actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, - ofproto.OFPCML_NO_BUFFER)] - self.add_flow(datapath, 0, match, actions) - - - def add_flow(self, datapath, priority, match, actions, buffer_id=None): - ofproto = datapath.ofproto - parser = datapath.ofproto_parser - - inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, - actions)] - if buffer_id: - mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id, - priority=priority, match=match, - instructions=inst) - else: - mod = parser.OFPFlowMod(datapath=datapath, priority=priority, - match=match, instructions=inst) - datapath.send_msg(mod) - - def send_packet(self, datapath, port, pkt, buffer_id=None): - ofproto = datapath.ofproto - parser = datapath.ofproto_parser - - pkt.serialize() - self.logger.info("packet-out %s" % (pkt,)) - data = pkt.data - - actions = [parser.OFPActionOutput(port=port)] - - if buffer_id: - out = parser.OFPPacketOut(datapath=datapath, - buffer_id=buffer_id, - in_port=ofproto.OFPP_CONTROLLER, - actions=actions, - data=data) - else: - out = parser.OFPPacketOut(datapath=datapath, - buffer_id=ofproto.OFP_NO_BUFFER, - in_port=ofproto.OFPP_CONTROLLER, - actions=actions, - data=data) - - datapath.send_msg(out) - - def do_arp(self, datapath, packet, frame, inPort): - dpid = datapath.id - ofproto = datapath.ofproto - parser = datapath.ofproto_parser - macaddr = self.MAC_ADDR[dpid-1] - - arpPacket = packet.get_protocol(arp) - if arpPacket.opcode == 1 : - # arp request - arp_dstIp = arpPacket.dst_ip - self.logger.info('received ARP Request %s => %s (port%d, ip: %s)'%(frame.src, frame.dst, inPort, arp_dstIp)) - if arp_dstIp in self.IP_ADDR: - # this switch was requested - opcode = 2 - srcMAC = macaddr - srcIP = arp_dstIp - dstMAC = frame.src - dstIP = arpPacket.src_ip - outPort = inPort - # learn mac 2 port mapping - self.mac_to_port[dpid][dstMAC] = inPort - # learn ip 2 mac mapping - self.ip_to_mac[dpid][dstIP] = dstMAC - self.logger.info("send ARP reply %s => %s (port%d)" %(srcMAC, dstMAC, outPort)) - else: - if arpPacket.dst_ip in self.ip_to_mac[dpid]: - # optimization: the switch already knows the mapping and can answer the request - opcode = 2 - srcMAC = self.ip_to_mac[dpid][arpPacket.dst_ip] - srcIP = arpPacket.dst_ip - dstMAC = frame.src - dstIP = arpPacket.src_ip - outPort = self.mac_to_port[dpid][dstMAC] - self.logger.info("optimization: answer ARP request %s => %s (port%d)" %(srcMAC, dstMAC, outPort)) - else: - # forward arp request - opcode = 1 - srcMAC = frame.src - srcIP = arpPacket.src_ip - dstMAC = frame.dst - dstIP = arpPacket.dst_ip - outPort = ofproto.OFPP_FLOOD - # learn mac 2 port mapping - self.mac_to_port[dpid][srcMAC] = inPort - # learn ip 2 mac mapping - self.ip_to_mac[dpid][srcIP] = srcMAC - self.logger.info("froward ARP request %s => %s (port%d)" %(srcMAC, dstMAC, outPort)) - elif arpPacket.opcode == 2 : - self.logger.info(arpPacket) - if arpPacket.dst_mac in self.MAC_ADDR: - # learn mac 2 port mapping - self.mac_to_port[dpid][arpPacket.src_mac] = inPort - # learn ip 2 mac mapping - self.ip_to_mac[dpid][arpPacket.src_ip] = arpPacket.src_mac - return - else: - opcode = 2 - #arp reply - # forward arp reply - srcMAC = frame.src - srcIP = arpPacket.src_ip - dstMAC = frame.dst - dstIP = arpPacket.dst_ip - outPort = self.mac_to_port[dpid][dstMAC] - # learn mac 2 port mapping - self.mac_to_port[dpid][srcMAC] = inPort - # learn ip 2 mac mapping - self.ip_to_mac[dpid][srcIP] = srcMAC - self.logger.debug('forward ARP reply %s => %s (port%d)'%(frame.src ,frame.dst, inPort)) - self.send_arp(datapath, opcode, srcMAC, srcIP, dstMAC, dstIP, outPort) - - def send_arp(self, datapath, opcode, srcMac, srcIp, dstMac, dstIp, outPort): - if opcode == 1: - targetMac = "FF:FF:FF:FF:FF:FF" - targetIp = dstIp - elif opcode == 2: - targetMac = dstMac - targetIp = dstIp - e = ethernet.ethernet(dstMac, srcMac, ether_types.ETH_TYPE_ARP) - a = arp(1, 0x0800, 6, 4, opcode, srcMac, srcIp, targetMac, targetIp) - p = Packet() - p.add_protocol(e) - p.add_protocol(a) - - self.send_packet(datapath, outPort, p) - - def do_icmp(self, datapath, port, pkt_ethernet, pkt_ipv4, pkt_icmp): - self.logger.info(pkt_icmp.type) - self.logger.info(icmp.ICMP_ECHO_REQUEST) - if pkt_icmp.type != icmp.ICMP_ECHO_REQUEST: - return - pkt = packet.Packet() - pkt.add_protocol(ethernet.ethernet(ethertype=pkt_ethernet.ethertype, - dst=pkt_ethernet.src, - src=self.MAC_ADDR[datapath.id-1])) - pkt.add_protocol(ipv4.ipv4(dst=pkt_ipv4.src, - src=pkt_ipv4.dst, - proto=pkt_ipv4.proto)) - pkt.add_protocol(icmp.icmp(type_=icmp.ICMP_ECHO_REPLY, - code=icmp.ICMP_ECHO_REPLY_CODE, - csum=0, - data=pkt_icmp.data)) - self.logger.info("do icmp: %s" %(pkt,)) - self.logger.info("port: %s" %(port)) - self.send_packet(datapath, port, pkt) - - def do_l2_switch(self, datapath, dpid, packet, frame, in_port, buffer_id=None): - ofproto = datapath.ofproto - parser = datapath.ofproto_parser - - if frame.dst in self.mac_to_port[dpid]: - out_port = self.mac_to_port[dpid][frame.dst] - else: - out_port = ofproto.OFPP_FLOOD - - actions = [parser.OFPActionOutput(out_port)] - - # install a flow to avoid packet_in next time - if out_port != ofproto.OFPP_FLOOD: - match = parser.OFPMatch(in_port=in_port, eth_dst=frame.dst) - # verify if we have a valid buffer_id, if yes avoid to send both - # flow_mod & packet_out - if buffer_id != ofproto.OFP_NO_BUFFER: - self.add_flow(datapath, 1, match, actions, buffer_id) - return - else: - self.add_flow(datapath, 1, match, actions) - data = None - if buffer_id == ofproto.OFP_NO_BUFFER: - data = packet.data - - out = parser.OFPPacketOut(datapath=datapath, buffer_id=buffer_id, - in_port=in_port, actions=actions, data=data) - datapath.send_msg(out) - - def do_l3_switch(self, datapath, dpid, packet, frame, ipv4_pkt, in_port, buffer_id=None): - ofproto = datapath.ofproto - parser = datapath.ofproto_parser - - if ipv4_pkt.dst in self.ip_to_mac[dpid]: - # Get mac and port of the given destination - dstMac = self.ip_to_mac[dpid][ipv4_pkt.dst] - out_port = self.mac_to_port[dpid][dstMac] - else: - # This flow is for the second switch if the address is in range 10.0.0.0-10.0.3.255 - # The ipaddress module assumes an IP adress as a unicode string (python 2.7 default for a string is ascii encoding) - if datapath.id == 2 and ipaddress.ip_address(unicode(ipv4_pkt.dst)) in ipaddress.ip_network(unicode("10.0.0.0/22")): - actions = [parser.OFPActionDecNwTtl(), #decrease TTL count - parser.OFPActionSetField(eth_src=self.MAC_ADDR[1]), # set own mac as source - parser.OFPActionSetField(eth_dst=self.MAC_ADDR[0]), # set dst switch - parser.OFPActionOutput(2)] - - match = parser.OFPMatch(ipv4_dst=("10.0.0.0", "255.255.252.0"), eth_dst=self.MAC_ADDR[1], eth_type=0x0800) - self.add_flow(datapath, 1, match, actions) - - data = None - if buffer_id == ofproto.OFP_NO_BUFFER: - data = packet.data - out = parser.OFPPacketOut(datapath=datapath, buffer_id=buffer_id, - in_port=in_port, actions=actions, data=data) - datapath.send_msg(out) - return - - # Add a flow for the first switch if the ipadress matches network 4. - if datapath.id == 1 and ipaddress.ip_address(unicode(ipv4_pkt.dst)) in ipaddress.ip_network(unicode("10.0.4.0/30")): - actions = [parser.OFPActionDecNwTtl(), #decrease TTL count - parser.OFPActionSetField(eth_src=self.MAC_ADDR[0]), # set own mac as source - parser.OFPActionSetField(eth_dst=self.MAC_ADDR[1]), # set dst switch - parser.OFPActionOutput(1)] - - match = parser.OFPMatch(ipv4_dst=("10.0.4.0", "255.255.255.252"), eth_dst=self.MAC_ADDR[0], eth_type=0x0800) - self.add_flow(datapath, 1, match, actions) - - data = None - if buffer_id == ofproto.OFP_NO_BUFFER: - data = packet.data - out = parser.OFPPacketOut(datapath=datapath, buffer_id=buffer_id, - in_port=in_port, actions=actions, data=data) - datapath.send_msg(out) - return - - - # Send an arp request and define mac and port - # so we're able to apply the following actions - # on the packet. - out_port = ofproto.OFPP_FLOOD - dstMac = "FF:FF:FF:FF:FF:FF" - self.send_arp(datapath, 1, self.MAC_ADDR[datapath.id-1], ipv4_pkt.src, dstMac, ipv4_pkt.dst, out_port) - - # Actions are applied in the same order as defined in the list. - # OFPActionOutput terminates the chain. So this call should be the last action. - actions = [parser.OFPActionDecNwTtl(), #decrease TTL count - parser.OFPActionSetField(eth_src=self.MAC_ADDR[datapath.id-1]), # set own mac as source - parser.OFPActionSetField(eth_dst=dstMac), # set dst from arp request - parser.OFPActionOutput(out_port)] # forward packet through out_port - - # Only install a flow if we#re in the first case (specific mac and out_port) - if ipv4_pkt.dst in self.ip_to_mac[dpid]: - # install a flow to avoid packet_in next time - match = parser.OFPMatch(in_port=in_port, ipv4_dst=ipv4_pkt.dst, eth_type=0x0800) #onlz match ipv4 packets - - # verify if we have a valid buffer_id, if yes avoid to send both - # flow_mod & packet_out - if buffer_id != ofproto.OFP_NO_BUFFER: - self.add_flow(datapath, 1, match, actions, buffer_id) - return - else: - self.add_flow(datapath, 1, match, actions) - - data = None - if buffer_id == ofproto.OFP_NO_BUFFER: - data = packet.data - - out = parser.OFPPacketOut(datapath=datapath, buffer_id=buffer_id, - in_port=in_port, actions=actions, data=data) - datapath.send_msg(out) - - - - @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) - def _packet_in_handler(self, ev): - # If you hit this you might want to increase - # the "miss_send_length" of your switch - if ev.msg.msg_len < ev.msg.total_len: - self.logger.debug("packet truncated: only %s of %s bytes", - ev.msg.msg_len, ev.msg.total_len) - - msg = ev.msg - datapath = msg.datapath - ofproto = datapath.ofproto - parser = datapath.ofproto_parser - in_port = msg.match['in_port'] - - pkt = packet.Packet(msg.data) - eth = pkt.get_protocols(ethernet.ethernet)[0] - - if eth.ethertype == ether_types.ETH_TYPE_LLDP: - # ignore lldp packet - return - - dst = eth.dst - src = eth.src - - dpid = datapath.id - self.mac_to_port.setdefault(dpid, {}) - self.ip_to_mac.setdefault(dpid, {}) - - - self.logger.info("packet in dpid: %s, src: %s, dest: %s, in_port: %s", dpid, src, dst, in_port) - #self.logger.info(pkt) - #learn mac to port mapping - if src not in self.mac_to_port[dpid]: - self.mac_to_port[dpid][src] = in_port - - if eth.ethertype == ether_types.ETH_TYPE_ARP and src not in self.MAC_ADDR: - self.do_arp(datapath, pkt, eth, in_port) - return - - if eth.ethertype == ether_types.ETH_TYPE_IP: - ipv4_pkt = pkt.get_protocol(ipv4.ipv4) - self.logger.info("IP src: %s, dst: %s", ipv4_pkt.src, ipv4_pkt.dst) - - #check if packet is for this switch - if ipv4_pkt.dst in self.IP_ADDR: - icmp_pkt = pkt.get_protocol(icmp.icmp) - if icmp_pkt: - self.do_icmp(datapath, in_port, eth, ipv4_pkt, icmp_pkt) - else: - # forward the package into a different subnet - self.do_l3_switch(datapath, dpid, pkt, eth, ipv4_pkt, in_port, msg.buffer_id) - - - # packet is not for this switch, so do l2 switching - if dst != self.MAC_ADDR[dpid-1]: - self.do_l2_switch(datapath, dpid, pkt, eth, in_port, msg.buffer_id) - return - return