def _handle_IP_packet(self, datapath, in_port, dst, actions, dl_type, src, data): #add flow for IP packets ofproto = datapath.ofproto dpid = datapath.id res = struct.unpack('!I', ipv4_to_bin(dst))[0] src_res = struct.unpack('!I', ipv4_to_bin(src))[0] match = datapath.ofproto_parser.OFPMatch(dl_type=dl_type, in_port=in_port, nw_src=src_res, nw_dst=res) mod = datapath.ofproto_parser.OFPFlowMod( datapath=datapath, match=match, cookie=0, command=ofproto.OFPFC_ADD, idle_timeout=600, hard_timeout=3600, priority=ofproto.OFP_DEFAULT_PRIORITY, flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions) datapath.send_msg(mod) #print("Created IP Flow to match: (nw_src={}, nw_dst={}, in_port={}, actions={}".\ #format(src, dst, in_port, str(actions))) #This line is wrong #self.add_flow(datapath, in_port, actions, dl_type) #Pass along original packet if dst != self.ip_addr: print("Passing packet off") out = datapath.ofproto_parser.OFPPacketOut(datapath=datapath,\ buffer_id=0xffffffff, in_port=in_port,\ actions=actions, data=data) datapath.send_msg(out)
def add_ingress_mpls_rule(self, in_port, out_port_no, mpls_label, src_ip, dst_ip): switch = self.db.get_switch_for_port(in_port) ryu_switch = self.get_ryu_switch_for_dpid(switch.dpid) dp = ryu_switch.dp parser = dp.ofproto_parser eth_IP = ether.ETH_TYPE_IP eth_MPLS = ether.ETH_TYPE_MPLS match = parser.OFPMatch() match.set_dl_type(eth_IP) nw_src = struct.unpack('!I', ipv4_to_bin(src_ip))[0] match.set_ipv4_src(nw_src) nw_dst = struct.unpack('!I', ipv4_to_bin(dst_ip))[0] match.set_ipv4_dst(nw_dst) f = dp.ofproto_parser.OFPMatchField.make( dp.ofproto.OXM_OF_MPLS_LABEL, mpls_label) actions = [ parser.OFPActionPushMpls(eth_MPLS), parser.OFPActionSetField(f), parser.OFPActionOutput(out_port_no) ] self.add_flow(dp, 3, match, actions, FLOW_TABLE_ID)
def __init__( self, version=4, header_length=5, tos=0, total_length=0, identification=0, flags=0, offset=0, ttl=255, proto=0, csum=0, src=ip.ipv4_to_bin("0.0.0.0"), dst=ip.ipv4_to_bin("0.0.0.0"), option=None, ): super(ipv4, self).__init__() self.version = version self.header_length = header_length self.tos = tos self.total_length = total_length self.identification = identification self.flags = flags self.offset = offset self.ttl = ttl self.proto = proto self.csum = csum self.src = src self.dst = dst self.option = option
def installFlowN(self, n, ipSrc, ipDst, tcpSrc, tcpDst, dlSrc, dlDst): ipSrc = struct.unpack('!I', ipv4_to_bin(ipSrc))[0] ipDst = struct.unpack('!I', ipv4_to_bin(ipDst))[0] url = "http://localhost:8080/stats/flowentry/modify" route_dict = self.routesNode1toNode2[n] for switch_dpid in route_dict.keys(): inputport = int(route_dict[switch_dpid].split(",")[0]) outputport = int(route_dict[switch_dpid].split(",")[1]) datapath = self.dpset.get(switch_dpid) parser = datapath.ofproto_parser match = parser.OFPMatch(nw_src=ipSrc, dl_type=2048, nw_dst=ipDst, nw_proto=6, tp_src=int(tcpSrc), tp_dst=int(tcpDst)) actions = [parser.OFPActionOutput(outputport)] self.add_flow(datapath, 500, match, actions) match = parser.OFPMatch(nw_src=ipDst, dl_type=2048, nw_dst=ipSrc, nw_proto=6, tp_src=int(tcpDst), tp_dst=int(tcpSrc)) actions = [parser.OFPActionOutput(inputport)] self.add_flow(datapath, 500, match, actions)
def init_flows(self, datapath): ofproto = datapath.ofproto for port, ipaddr in spe_config.ports.iteritems(): self.add_arp_reply_catcher(datapath, ipaddr=ip.ipv4_to_bin(ipaddr), port=port, table_id=1) self.add_arp_request_forwarder(datapath, ipaddr=ip.ipv4_to_bin(ipaddr), port=port, table_id=1) # make a flow to send all ARP packets to table 1 match = datapath.ofproto_parser.OFPMatch() match.set_dl_type(ether.ETH_TYPE_ARP) instructions = [datapath.ofproto_parser.OFPInstructionGotoTable(1)] self.add_flow(datapath, 0, match, instructions)
def add_qos_l4_flow(self, datapath, host1, host2, protocol, priority): ofproto = datapath.ofproto parser = datapath.ofproto_parser if host1[1] == 5060 or host2[1] == 5060: return port1 = self.l3_resolve(datapath.id, host1[0]) port2 = self.l3_resolve(datapath.id, host2[0]) if port1 == None or port2 == None: return self.logger.info('[L4] flow between {}:{} and {}:{} with priority {}'.format(host1[0], host1[1], host2[0], host2[1], priority)) # priority path host1 -> host2 actions = [parser.OFPActionVlanPcp(priority), parser.OFPActionOutput(port2)] match = parser.OFPMatch(in_port = port1, dl_type = 0x800, nw_proto = protocol, nw_src = struct.unpack('!I', ipv4_to_bin(host1[0]))[0], nw_dst = struct.unpack('!I', ipv4_to_bin(host2[0]))[0], tp_src = int(host1[1]), tp_dst = int(host2[1])) mod = parser.OFPFlowMod(datapath=datapath, match=match, cookie=0, command=ofproto.OFPFC_ADD, idle_timeout=20, hard_timeout=0, priority=3000, flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions) datapath.send_msg(mod) # priority path host2 -> host1 actions = [parser.OFPActionVlanPcp(priority), parser.OFPActionOutput(port1)] match = parser.OFPMatch(in_port = port2, dl_type = 0x800, nw_proto = protocol, nw_src = struct.unpack('!I', ipv4_to_bin(host2[0]))[0], nw_dst = struct.unpack('!I', ipv4_to_bin(host1[0]))[0], tp_src = int(host2[1]), tp_dst = int(host1[1])) mod = parser.OFPFlowMod(datapath=datapath, match=match, cookie=0, command=ofproto.OFPFC_ADD, idle_timeout=20, hard_timeout=0, priority=3000, flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions) datapath.send_msg(mod)
def _modify_blacklist(self, ipaddr, mode, dl_type=0x800): res = struct.unpack('!I', ipv4_to_bin(ipaddr))[0] if mode == "add": if ipaddr in self.blacklist: return self.blacklist.append(ipaddr) elif mode == "remove": if ipaddr not in self.blacklist: return self.blacklist.remove(ipaddr) for dp in self.dpids: datapath = self.dpids[dp] ofproto = datapath.ofproto match = datapath.ofproto_parser.OFPMatch(dl_type=dl_type, nw_src=res) if mode == "add": print("Adding " + ipaddr + " to blacklist") command = ofproto.OFPFC_ADD elif mode == "remove": print("Removing " + ipaddr + " to blacklsit") command = ofproto.OFPFC_DELETE mod = datapath.ofproto_parser.OFPFlowMod(datapath=datapath, match=match,\ cookie=0,command=command, idle_timeout=0, hard_timeout=0,\ priority=ofproto.OFP_DEFAULT_PRIORITY+5,\ flags=ofproto.OFPFF_SEND_FLOW_REM, actions=None) datapath.send_msg(mod)
def __init__(self, hwtype=ARP_HW_TYPE_ETHERNET, proto=ether.ETH_TYPE_IP, hlen=6, plen=4, opcode=ARP_REQUEST, src_mac=mac.haddr_to_bin('ff:ff:ff:ff:ff:ff'), src_ip=ip.ipv4_to_bin('0.0.0.0'), dst_mac=mac.haddr_to_bin('ff:ff:ff:ff:ff:ff'), dst_ip=ip.ipv4_to_bin('0.0.0.0')): super(arp, self).__init__() self.hwtype = hwtype self.proto = proto self.hlen = hlen self.plen = plen self.opcode = opcode self.src_mac = src_mac self.src_ip = src_ip self.dst_mac = dst_mac self.dst_ip = dst_ip
def host_update_handler(self, ev): domain = ev.domain hosts = [] for host in ev.hosts: h = self.oxparser.OXPHost(ip=ipv4_to_bin(host[0]), mac=haddr_to_bin(host[1]), mask=255, state=host[2]) hosts.append(h) host_update = self.oxparser.OXPHostUpdate(domain, hosts) domain.send_msg(host_update)
def __init__(self, version=4, header_length=5, tos=0, total_length=0, identification=0, flags=0, offset=0, ttl=255, proto=0, csum=0, src=ip.ipv4_to_bin('0.0.0.0'), dst=ip.ipv4_to_bin('0.0.0.0'), option=None): super(ipv4, self).__init__() self.version = version self.header_length = header_length self.tos = tos self.total_length = total_length self.identification = identification self.flags = flags self.offset = offset self.ttl = ttl self.proto = proto self.csum = csum self.src = src self.dst = dst self.option = option
def _create_icmp_flow(self,datapath): ofproto = datapath.ofproto ofproto_parser = datapath.ofproto_parser nw_dst = struct.unpack('!I', ipv4_to_bin(self.ip_addr))[0] match = datapath.ofproto_parser.OFPMatch(dl_type=0x800, nw_dst=nw_dst) actions = [datapath.ofproto_parser.OFPActionOutput(ofproto.OFPP_CONTROLLER)] mod = datapath.ofproto_parser.OFPFlowMod( datapath=datapath, match=match, cookie=0, command=ofproto.OFPFC_ADD, idle_timeout=0, hard_timeout=0, actions=actions, priority=0xFFFF) datapath.send_msg(mod)
def host_request_handler(self, ev): domain = ev.msg.domain host_info = self.network.access_table hosts = [] for key in host_info: h = self.oxparser.OXPHost(ip=ipv4_to_bin(host_info[key][0]), mac=haddr_to_bin(host_info[key][1]), mask=255, state=OXPP_ACTIVE) hosts.append(h) host_reply = self.oxparser.OXPHostReply(domain, hosts) domain.send_msg(host_reply)
def add_l3_flow(self, datapath, host1, host2, proto): ofproto = datapath.ofproto parser = datapath.ofproto_parser port1 = self.l3_resolve(datapath.id, host1) port2 = self.l3_resolve(datapath.id, host2) if port1 == None or port2 == None: return self.logger.info('[L3] flow between {} and {}'.format(host1, host2)) # host1 -> host2 actions = [parser.OFPActionOutput(port2)] match = parser.OFPMatch(dl_type = 0x800, nw_src = struct.unpack('!I', ipv4_to_bin(host1))[0], nw_dst = struct.unpack('!I', ipv4_to_bin(host2))[0], nw_proto = proto) mod = parser.OFPFlowMod(datapath=datapath, match=match, cookie=0, command=ofproto.OFPFC_ADD, idle_timeout=20, hard_timeout=0, priority=1000, flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions) datapath.send_msg(mod) # host2 -> host1 actions = [parser.OFPActionOutput(port1)] match = parser.OFPMatch(dl_type = 0x800, nw_src = struct.unpack('!I', ipv4_to_bin(host2))[0], nw_dst = struct.unpack('!I', ipv4_to_bin(host1))[0], nw_proto = proto) mod = parser.OFPFlowMod(datapath=datapath, match=match, cookie=0, command=ofproto.OFPFC_ADD, idle_timeout=20, hard_timeout=0, priority=1000, flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions) datapath.send_msg(mod)
def test_ipv4_to_bin(self): ipv4_str = '10.28.197.1' val = 0x0a1cc501 (res,) = struct.unpack('!I', ip.ipv4_to_bin(ipv4_str)) eq_(val, res)
def test_ipv4_to_bin(self): ipv4_str = '10.28.197.1' val = 0x0a1cc501 res = ip.ipv4_to_bin(ipv4_str) eq_(val, res)
def _packet_in_handler(self, ev): msg = ev.msg datapath = msg.datapath ofproto = datapath.ofproto dst, src, _eth_type = struct.unpack_from('!6s6sH', buffer(msg.data), 0) dpid = datapath.id self.mac_to_port.setdefault(dpid, {}) match = msg.match in_port = 0 ethtype = 0 #iterate through fields - parser should handle this #packet in dpid 20015998343868 from 08:00:27:15:d4:53 to ff:ff:ff:ff:ff:ff log_port 0 phy_port 0 #Field MTInPort(header=2147483652,length=8,n_bytes=4,value=2) #Field MTEthType(header=2147486210,length=6,n_bytes=2,value=2054) #Field MTArpOp(header=2147494402,length=6,n_bytes=2,value=1) #Field MTMetadata(header=2147484680,length=12,n_bytes=8,value=18446744073709551615L) #Field MTArpSha(header=2147495942,length=10,n_bytes=6,value="\x08\x00'\x15\xd4S") #Field MTEthDst(header=2147485190,length=10,n_bytes=6,value='\xff\xff\xff\xff\xff\xff') #Field MTArpSpa(header=2147494916,length=8,n_bytes=4,value=167772161) #Field MTArpTha(header=2147496454,length=10,n_bytes=6,value='\x00\x00\x00\x00\x00\x00') # we should build a dictionary of MTXXXX class names to speed this up for o in match.fields: self.logger.info("Field %s", str(o)) if isinstance(o, ofproto_v1_2_parser.MTInPort): in_port = o.value break self.logger.info("packet in dpid %s from %s to %s log_port %s", dpid, haddr_to_str(src), haddr_to_str(dst), in_port) # parse packet pkt = packet.Packet(msg.data) eth_pkt = pkt.next() ethtype = eth_pkt.ethertype # if ARP (request) then flood and don't make a flow if ethtype == ether.ETH_TYPE_ARP: # if ARP reply then drop arp_pkt = pkt.next() if arp_pkt.opcode == 2: # check config if ip.ipv4_to_bin(spe_config.ports[in_port]) != arp_pkt.src_ip: self.logger.info("Dropping spoofed ARP from port %d IP %s (expected IP %s)", in_port, ip.ipv4_to_str(arp_pkt.src_ip), spe_config.ports[in_port]) return out_port = ofproto_v1_2.OFPP_FLOOD actions = [datapath.ofproto_parser.OFPActionOutput(out_port, 1500)] out = datapath.ofproto_parser.OFPPacketOut( datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions) datapath.send_msg(out) # do we know the mac? if src not in self.mac_to_port[dpid]: # learn the mac address to avoid FLOOD next time. self.mac_to_port[dpid][src] = in_port # set a flow to table 0 to allow packets through to table 1 match = datapath.ofproto_parser.OFPMatch() match.set_in_port(in_port) match.set_dl_src(src) match.set_dl_type(ethtype) instructions = [datapath.ofproto_parser.OFPInstructionGotoTable(2)] self.add_flow(datapath, 0, match, instructions) if dst in self.mac_to_port[dpid]: out_port = self.mac_to_port[dpid][dst] match = datapath.ofproto_parser.OFPMatch() match.set_dl_dst(dst) actions = [datapath.ofproto_parser.OFPActionOutput(out_port, 1500)] instructions = [datapath.ofproto_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] self.add_flow(datapath, 2, match, instructions, buffer_id=msg.buffer_id) else: out_port = ofproto_v1_2.OFPP_FLOOD actions = [datapath.ofproto_parser.OFPActionOutput(out_port, 1500)] out = datapath.ofproto_parser.OFPPacketOut( datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions) datapath.send_msg(out)
def test_ipv4_to_bin(self): ipv4_str = '10.28.197.1' val = 0x0a1cc501 (res, ) = struct.unpack('!I', ip.ipv4_to_bin(ipv4_str)) eq_(val, res)
def _packet_in_handler(self, ev): msg = ev.msg datapath = msg.datapath ofproto = datapath.ofproto dst, src, _eth_type = struct.unpack_from('!6s6sH', buffer(msg.data), 0) dpid = datapath.id self.mac_to_port.setdefault(dpid, {}) match = msg.match in_port = 0 ethtype = 0 #iterate through fields - parser should handle this #packet in dpid 20015998343868 from 08:00:27:15:d4:53 to ff:ff:ff:ff:ff:ff log_port 0 phy_port 0 #Field MTInPort(header=2147483652,length=8,n_bytes=4,value=2) #Field MTEthType(header=2147486210,length=6,n_bytes=2,value=2054) #Field MTArpOp(header=2147494402,length=6,n_bytes=2,value=1) #Field MTMetadata(header=2147484680,length=12,n_bytes=8,value=18446744073709551615L) #Field MTArpSha(header=2147495942,length=10,n_bytes=6,value="\x08\x00'\x15\xd4S") #Field MTEthDst(header=2147485190,length=10,n_bytes=6,value='\xff\xff\xff\xff\xff\xff') #Field MTArpSpa(header=2147494916,length=8,n_bytes=4,value=167772161) #Field MTArpTha(header=2147496454,length=10,n_bytes=6,value='\x00\x00\x00\x00\x00\x00') # we should build a dictionary of MTXXXX class names to speed this up for o in match.fields: self.logger.info("Field %s", str(o)) if isinstance(o, ofproto_v1_2_parser.MTInPort): in_port = o.value break self.logger.info("packet in dpid %s from %s to %s log_port %s", dpid, haddr_to_str(src), haddr_to_str(dst), in_port) # parse packet pkt = packet.Packet(msg.data) eth_pkt = pkt.next() ethtype = eth_pkt.ethertype # if ARP (request) then flood and don't make a flow if ethtype == ether.ETH_TYPE_ARP: # if ARP reply then drop arp_pkt = pkt.next() if arp_pkt.opcode == 2: # check config if in_port not in spe_config.ports: self.logger.info( "Port %d not configured, trying to ARP as %s", in_port, ip.ipv4_to_str(arp_pkt.src_ip)) return if ip.ipv4_to_bin(spe_config.ports[in_port]) != arp_pkt.src_ip: self.logger.info( "Dropping spoofed ARP from port %d IP %s (expected IP %s)", in_port, ip.ipv4_to_str(arp_pkt.src_ip), spe_config.ports[in_port]) return # don't flood here - we'll do it later #out_port = ofproto_v1_2.OFPP_FLOOD #actions = [datapath.ofproto_parser.OFPActionOutput(out_port, 1500)] #out = datapath.ofproto_parser.OFPPacketOut( # datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, # actions=actions) #datapath.send_msg(out) # set ethtype to IP for the next part ethtype = ether.ETH_TYPE_IP # do we know the mac? #if src not in self.mac_to_port[dpid]: # # learn the mac address to avoid FLOOD next time. # self.mac_to_port[dpid][src] = in_port # # set a flow to table 0 to allow packets through to table 1 # match = datapath.ofproto_parser.OFPMatch() # match.set_in_port(in_port) # match.set_dl_src(src) # match.set_dl_type(ethtype) # instructions = [datapath.ofproto_parser.OFPInstructionGotoTable(2)] # self.add_flow(datapath, 0, match, instructions) # # #if dst in self.mac_to_port[dpid]: # out_port = self.mac_to_port[dpid][dst] # match = datapath.ofproto_parser.OFPMatch() # match.set_dl_dst(dst) # actions = [datapath.ofproto_parser.OFPActionOutput(out_port, 1500)] # instructions = [datapath.ofproto_parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)] # self.add_flow(datapath, 2, match, instructions, buffer_id=msg.buffer_id) #else: # out_port = ofproto_v1_2.OFPP_FLOOD # actions = [datapath.ofproto_parser.OFPActionOutput(out_port, 1500)] # out = datapath.ofproto_parser.OFPPacketOut( # datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, # actions=actions) # datapath.send_msg(out) # new way of handling this # if packet got to us then we probably don't know the MAC # so add table->2 flow to first table, and out action on table 2 # learn the mac address to avoid FLOOD next time. self.mac_to_port[dpid][src] = in_port # set a flow to table 0 to allow packets through to table 1 match = datapath.ofproto_parser.OFPMatch() match.set_in_port(in_port) match.set_dl_src(src) match.set_dl_type(ethtype) instructions = [datapath.ofproto_parser.OFPInstructionGotoTable(2)] self.add_flow(datapath, 0, match, instructions) match = datapath.ofproto_parser.OFPMatch() match.set_dl_dst(src) actions = [datapath.ofproto_parser.OFPActionOutput(in_port, 1500)] instructions = [ datapath.ofproto_parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, actions) ] self.add_flow(datapath, 2, match, instructions) # then, just in case there's no out flow, we'll do that too if dst in self.mac_to_port[dpid]: out_port = self.mac_to_port[dpid][dst] match = datapath.ofproto_parser.OFPMatch() match.set_dl_dst(dst) actions = [datapath.ofproto_parser.OFPActionOutput(out_port, 1500)] instructions = [ datapath.ofproto_parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, actions) ] self.add_flow(datapath, 2, match, instructions, buffer_id=msg.buffer_id) else: out_port = ofproto_v1_2.OFPP_FLOOD actions = [datapath.ofproto_parser.OFPActionOutput(out_port, 1500)] out = datapath.ofproto_parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=actions) datapath.send_msg(out)
def ip4_format(ip): return struct.unpack('!I', ipv4_to_bin(ip))[0]