class TeraFlowHandler(app_manager.RyuApp): OFP_VERSIONS = [ofproto_v1_2.OFP_VERSION] def __init__(self, *args, **kwargs): super(TeraFlowHandler, self).__init__(*args, **kwargs) self.mac_to_port = {} self.ryu_fl_hdlr = RyuFlowHandler() self.policy= PolicyUser('/home/ryu/tf_users.csv') self.subscriber_port=0 self.network_port=0 self.eth_list = [] @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) def _packet_in_handler(self, ev): # if this is the first pkt to the system, lets get the port info and save it if self.subscriber_port== 0: self.ryu_fl_hdlr.get_port_info() self.subscriber_port = self.ryu_fl_hdlr.get_port_no(intf_name='eth1') self.network_port = self.ryu_fl_hdlr.get_port_no(intf_name='eth2') print "sub_port and net_port is", self.subscriber_port, self.network_port msg = ev.msg datapath = msg.datapath ofproto = datapath.ofproto in_port = msg.match['in_port'] if in_port == self.subscriber_port: out_port = self.network_port elif in_port == self.network_port: out_port = self.subscriber_port else: print "the inport is invalid. Cannot happen!!!!!\n" pass #packet is received here!!! pkt = packet.Packet(msg.data) # get ethernet data for flow srcMac = pkt.protocols[0].src dstMac = pkt.protocols[0].dst ethType = pkt.protocols[0].ethertype #if we see an arp pkt, probably the arp is not installed, lets first install and return if ethType == 2054: self.ryu_fl_hdlr.pre_flow_handler() return if ethType != 2048: if not (ethType in self.eth_list): self.eth_list.append(ethType) print '\n ##### Non IP Packet : ethType is -> ', ethType print '\n ##### Non IP Packet : -> ', pkt print '\n ##### List of Non IP EthType : -> ', self.eth_list return # get ip data for flow proto = pkt.protocols[1].proto srcIp = pkt.protocols[1].src dstIp = pkt.protocols[1].dst tos = pkt.protocols[1].tos offset = pkt.protocols[1].offset if not (self.policy.isIpValidSub(srcIp)): if not (self.policy.isIpValidSub(dstIp)): pass #print "Not an allowed flow, lets install deny flow for this guy", srcIp, dstIp #matchDict = { 'eth_type':2048,'ipv4_src':srcIp } #self.ryu_fl_hdlr.get_flow_stats_obj().deny_flow_via_rest(matchDict=matchDict) #udp or tcp if (proto == 17 or proto == 6): srcPort = pkt.protocols[2].src_port dstPort = pkt.protocols[2].dst_port # icmp if (proto == 1): icmpType = pkt.protocols[2].type icmpCode = pkt.protocols[2].code #fwd_actions = [datapath.ofproto_parser.OFPActionOutput(out_port)] #rev_actions = [datapath.ofproto_parser.OFPActionOutput(in_port)] actions = [datapath.ofproto_parser.OFPActionOutput(out_port)] # install a flow to avoid packet_in next time if out_port != ofproto.OFPP_FLOOD: if ((proto == 17 or proto == 6) and (offset == 0)): self.ryu_fl_hdlr.add_flow( msg, datapath, in_port=in_port, out_port=out_port, srcMac=srcMac, dstMac=dstMac, srcIp=srcIp, dstIp=dstIp, proto=proto, tos=tos, actions=actions, srcPort=srcPort, dstPort=dstPort, offset=offset ) elif (proto == 1): self.ryu_fl_hdlr.add_flow( msg, datapath, in_port=in_port, out_port=out_port, srcMac=srcMac, dstMac=dstMac, srcIp=srcIp, dstIp=dstIp, proto=proto, tos=tos, actions=actions, icmpType=icmpType, icmpCode=icmpCode ) else: self.ryu_fl_hdlr.add_flow( msg, datapath, in_port=in_port, out_port=out_port, srcMac=srcMac, dstMac=dstMac, srcIp=srcIp, dstIp=dstIp, proto=proto, tos=tos,actions=actions, offset=offset )
class RyuFlowHandler(BaseFlowHandler): def __init__(self): super(RyuFlowHandler, self).__init__() from flow_stats import FlowStats self.flowStats = FlowStats() self.firstTimeFlg = 1 self.flowStateChange = 1 self.flow_timeout = 30 #2mins self.flow_priority = 32765 self.polling_interval = 10 self.file_path = '/home/ryu/csvfiles' self.port_info = {} self.policy= PolicyUser('/home/ryu/tf_users.csv') def get_port_info(self): self.port_info = self.flowStats.get_port_info().values()[0]; print "port info is:", self.port_info def get_port_no(self, intf_name='eth1'): port_no = 0 for port in self.port_info: if port['name'] == intf_name: return port['port_no'] return port_no def timerHandler(self): #self.add_flow_dict = {} #print 'Inside Timer Handler....' # Carry out Flow Stats. self.flowStats.stats_collector() # getting statistics for every 10 seconds. threading.Timer(self.polling_interval, self.timerHandler).start() def pre_flow_handler(self): print 'clear all the flows in the switch' self.flowStats.clear_all_flows() print 'add a static arp flow in the switch' self.flowStats.add_arp_flow() def fwd_entry(self, datapath, match, action, inport): ofproto = datapath.ofproto inst = [datapath.ofproto_parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, action)] self.install_flows(datapath, match, inst, action, inport) def rev_entry(self, datapath, match, action, inport): ofproto = datapath.ofproto inst = [datapath.ofproto_parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, action)] if match['ip_proto'] == 17: match = datapath.ofproto_parser.OFPMatch(eth_src=match['eth_dst'], eth_dst=match['eth_src'], ipv4_src=match['ipv4_dst'], ipv4_dst=match['ipv4_src'], udp_src=match['udp_dst'], udp_dst=match['udp_src'], ip_proto=match['ip_proto'], eth_type=0x800, in_port=inport ) self.install_flows(datapath, match, inst, action, inport) def get_flow_stats_obj(self): return self.flowStats def get_flow_direction(self,flow): #find sub ip and direction sub_ip = flow['srcIp'] dir = 'FWD' if not self.policy.isIpValidSub(sub_ip): sub_ip = flow['dstIp'] dir = 'REV' if not self.policy.isIpValidSub(sub_ip): #print "both ipis belongs to valid range. how did we get here!!!!", flow return -1 return dir def add_flow(self, msg, datapath, **kwargs): #if self.flowStateChange == 1: # self.pre_flow_handler() # self.flowStateChange =0 #self.add_flow_dict = {} ofproto = datapath.ofproto #self.buffer_id = ofproto.OFP_NO_BUFFER msg = msg if (kwargs['proto'] == 6): if (kwargs['offset']==0): match = datapath.ofproto_parser.OFPMatch(in_port=kwargs['in_port'], eth_dst=kwargs['dstMac'], eth_src=kwargs['srcMac'], eth_type=0x800, ipv4_src=kwargs['srcIp'], ipv4_dst=kwargs['dstIp'], ip_proto=kwargs['proto'], tcp_src=kwargs['srcPort'], tcp_dst=kwargs['dstPort']) else: match = datapath.ofproto_parser.OFPMatch(in_port=kwargs['in_port'], eth_dst=kwargs['dstMac'], eth_src=kwargs['srcMac'], eth_type=0x800, ipv4_src=kwargs['srcIp'], ipv4_dst=kwargs['dstIp'], ip_proto=kwargs['proto']) elif (kwargs['proto'] == 17): if (kwargs['offset']==0): match = datapath.ofproto_parser.OFPMatch(in_port=kwargs['in_port'], eth_dst=kwargs['dstMac'], eth_src=kwargs['srcMac'], eth_type=0x800, ipv4_src=kwargs['srcIp'], ipv4_dst=kwargs['dstIp'], ip_proto=kwargs['proto'], udp_src=kwargs['srcPort'], udp_dst=kwargs['dstPort'] ) else: match = datapath.ofproto_parser.OFPMatch(in_port=kwargs['in_port'], eth_dst=kwargs['dstMac'], eth_src=kwargs['srcMac'], eth_type=0x800, ipv4_src=kwargs['srcIp'], ipv4_dst=kwargs['dstIp'], ip_proto=kwargs['proto']) else: match = datapath.ofproto_parser.OFPMatch(in_port=kwargs['in_port'], eth_dst=kwargs['dstMac'], eth_src=kwargs['srcMac'], eth_type=0x800, ipv4_src=kwargs['srcIp'], ipv4_dst=kwargs['dstIp'], ip_proto=kwargs['proto']) #kwargs['srcPort']=kwargs['dstPort']=0 if 'offset' in kwargs.keys(): if (kwargs['offset']==0): self.fwd_key = kwargs['srcIp'] + '_' + str(kwargs['srcPort']) + '_' + kwargs['dstIp'] + '_' + str(kwargs['dstPort']) else: self.fwd_key = kwargs['srcIp'] + '_' + kwargs['dstIp'] + '_' + str(kwargs['proto']) else: self.fwd_key = kwargs['srcIp'] + '_' + kwargs['dstIp'] + '_' + str(kwargs['proto']) kwargs['byte_count'] = kwargs['packet_count'] = kwargs['delta_bytes'] = kwargs['delta_packets'] =kwargs['app_id']= 0 kwargs['create_time'] = kwargs['last_seen_time'] = time.time() self.install_flows(msg, datapath, match, kwargs['actions'], kwargs['in_port']) #self.fwd_entry(datapath, match, kwargs['fwd_actions'], kwargs['in_port']) #self.rev_entry(datapath, match, kwargs['rev_actions'], kwargs['out_port']) add_flow_dict[self.fwd_key] = kwargs #print 'Initial Flow Dict :', add_flow_dict #print '\n call timer handler....' if self.firstTimeFlg == 1: threading.Timer(self.polling_interval, self.timerHandler).start() self.firstTimeFlg =0 def delete_flow(self, flow): flow_key = self.get_flow_key(flow) del add_flow_dict[flow_key] #print '\n\n AFTER DELETe : ', add_flow_dict def get_flow_key(self,flow): if 'srcPort' in flow.keys(): flow_key = flow['srcIp'] + '_' + str(flow['srcPort']) + '_' + flow['dstIp'] + '_' + str(flow['dstPort']) else: flow_key = flow['srcIp'] + '_' + flow['dstIp'] + '_' + str(flow['proto']) return flow_key def get_flow_timeout(self): return self.flow_timeout def dump_flows_to_file(self): #print '\n\n Inside Dump flows..!!!' total_tx_bytes = total_tx_pkts = total_rx_bytes = total_rx_pkts = 0 # write the flow entries in the csv fileTime = str(time.time()) fo = open('%s/flow_%s.csv.Pending' % (self.file_path,fileTime), 'w+') fo1 = open('%s/total_traffic_%s.csv.Pending' % (self.file_path,fileTime), 'w+') fo.write('#InPort,OutPort,SrcMac,DstMac,SrcIp,DstIp,SrcPort,DstPort,Protocol,Packets,Bytes,DelPackets,DelBytes,CreateTime,LastSeen,AppID,Tos \n') for flow in add_flow_dict.values(): #print '\n\n Flow !!! :', flow if flow['delta_bytes'] == 0 : if (time.time() - flow['last_seen_time']) > self.get_flow_timeout() : #delete the flow from ofctl table and software flow table self.delete_flow(flow) else: if self.get_flow_direction(flow) == 'FWD': total_tx_bytes += flow['delta_bytes'] total_tx_pkts += flow['delta_packets'] elif self.get_flow_direction(flow) == 'REV': total_rx_bytes += flow['delta_bytes'] total_rx_pkts += flow['delta_packets'] else: pass fo.write("%u,%u,%s,%s,%s,%s,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u\n" % ( (flow['in_port']), (flow['out_port']),flow['srcMac'], flow['dstMac'],flow['srcIp'], flow['dstIp'], (flow['srcPort']), (flow['dstPort']), (flow['proto']),(flow['packet_count']), (flow['byte_count']), (flow['delta_packets']), (flow['delta_bytes']), (flow['create_time']), (flow['last_seen_time']), (flow['app_id']),(flow['tos']))) fo.close() fo1.write("%s,%u,%u,%u,%u\n" % (fileTime,total_tx_bytes,total_rx_bytes,total_tx_pkts, total_rx_pkts)) fo1.close() def update_flow_stats(self, flow): #print '\n\n\ Inside Update stats - add_flow_dict ....!!!!:', add_flow_dict try: if not flow['ethType'] == 2054: # if the flow is neither udp or tcp, for flow key, we need src/dstport which is 0 flow_key = self.get_flow_key(flow) new_flow = prev_entry = add_flow_dict[(flow_key)] new_flow['delta_bytes']= flow['byte_count'] - prev_entry['byte_count'] new_flow['delta_packets'] = flow['packet_count'] - prev_entry['packet_count'] if new_flow['delta_bytes'] != 0: new_flow['byte_count'] = flow['byte_count'] new_flow['packet_count'] = flow['packet_count'] new_flow['last_seen_time'] = time.time() add_flow_dict[flow_key] = new_flow except Exception as err: pass #print ' Error: !!!! ', err #self.flowStats.dump_flows(add_flow_dict) def install_flows(self, msg, datapath, match, action, in_port): ofproto = datapath.ofproto inst = [datapath.ofproto_parser.OFPInstructionActions( ofproto.OFPIT_APPLY_ACTIONS, action)] mod = datapath.ofproto_parser.OFPFlowMod( datapath=datapath, cookie=0, cookie_mask=0, table_id=0, command=ofproto.OFPFC_ADD, idle_timeout=self.flow_timeout, hard_timeout=0, priority=self.flow_priority, buffer_id=ofproto.OFP_NO_BUFFER, out_port=ofproto.OFPP_ANY, out_group=ofproto.OFPG_ANY, flags=0, match=match, instructions=inst) datapath.send_msg(mod) data = None if msg.buffer_id == ofproto.OFP_NO_BUFFER: data = msg.data out = datapath.ofproto_parser.OFPPacketOut( datapath=datapath, buffer_id=msg.buffer_id, in_port=in_port, actions=action, data=data) datapath.send_msg(out)