Example #1
0
    def __init__(self, *args, **kwargs):
        super(coupler, self).__init__(*args, **kwargs)
        #modules are added to the coupler as objects
        self.switch=SimpleSwitch()
        #created address for crafted packets
        self.hw_addr = 'aa:bb:cc:dd:ee:11'
        self.ip_addr = '10.0.0.25'
        ##############################################################
        #[2] Add Additional modules or object variables here or add
        #    definitions to the provided NFG_13.py file
        self.NFG = NFG()

	#######################################################################
	#[3]Insert proactive rules provided by NFG library, follow format below
	# Only offers drop and redirect options
	def get_proactive_rules(self,dp,parser,ofproto):
		pass
Example #2
0
class coupler(app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]
    def __init__(self, *args, **kwargs):
        super(coupler, self).__init__(*args, **kwargs)
        #modules are added to the coupler as objects
        self.switch=SimpleSwitch()
        #created address for crafted packets
        self.hw_addr = 'aa:bb:cc:dd:ee:11'
        self.ip_addr = '10.0.0.25'
        ##############################################################
        #[2] Add Additional modules or object variables here or add
        #    definitions to the provided NFG_13.py file
        self.NFG = NFG()

	#######################################################################
	#[3]Insert proactive rules provided by NFG library, follow format below
	# Only offers drop and redirect options
	def get_proactive_rules(self,dp,parser,ofproto):
		pass
		#fields, ops = self.NFG.simpleFW()
		#self._add_proactive_flow(dp, parser, ofproto, fields, ops)
		
    #####################################################################
    #[4] Use below handles to direct arriving packets to modules in NFG.py; 
    #    modules return match fields (fields) and operations (ops) 
    #    hashes (determined by programmer). Ensure that fields,ops
    #    are only set once in each handle (comment out default_Field_Ops).
    ######################################################################
    #fields contains the following keys:
    #  {'keys':['inport','srcport'], 'ptype':None, 'inport':pkt['inport'],
    #  'srcmac':pkt['srcmac'], 'dstmac':None, 'srcip':None, 'dstip':None,
    #  'srcport':None, 'dstport':None}
    ######################################################################
    #ops contains the following keys:
    # {'hard_t':None, 'idle_t':None, 'priority':None, 'op':'fwd',
    #  'newport':None}
    # set *_t to 0 for permanent or >0 for temporary,
    # set * 'priority' to 0 for lowest
    # 'op':{'fwd', 'drop', 'mir' (mirror), 'newport' (redirect), 'craft'}
    # 'newport': used for mirror and redirect, otherwise None
    ######################################################################
    
    def handle_eth(self,pkt):
        print "handle eth"
        fields, ops = self.NFG.default_Field_Ops(pkt)
        #print pkt['eth']
        #fields, ops = check_list(pkt)
        #fields, ops = self.NFG.Check_List(pkt)
        self._switch_mod(pkt,fields,ops)

    def handle_arp(self,pkt):
        print "handle ARP"
        print pkt
        fields, ops = self.NFG.default_Field_Ops(pkt)
        #print pkt['arp']
        self._switch_mod(pkt, fields, ops)
		
    #Apply the most restrictive fields,ops (based on priority) are applied
    #to each packet. We will use priority to select.    
    def handle_ip(self,pkt):
	#print pkt['ip']
	#fields, ops = self.NFG.default_Field_Ops(pkt)
        print "handle ip"
        #fields2,ops2 = self.NFG.Stateful_FW(pkt)
	##############################################################
        #Determine highest priority fields and ops pair, if needed
        #xfields = [fields0, fields1, fields2]
        #xops = [ops0, ops1, ops2]
        #fields,ops = self._build_FldOps(xfields,xops)
	##############################################################
        
        self._switch_mod(pkt,fields,ops)

    def handle_icmp(self,pkt):
        print "handle icmp"
        fields, ops = self.NFG.default_Field_Ops(pkt)
        #print pkt['icmp'], '\n', pkt['ip']
        #fields, ops = self.NFG.TTL_Check(pkt)
        self._switch_mod(pkt, fields, ops)

    def handle_tcp(self,pkt):
        print "handle tcp"
        #fields, ops = self.NFG.default_Field_Ops(pkt)
        #fields,ops = self.NFG.Simple_FW(pkt)
        #print pkt['tcp']
        fields, ops = self.NFG.TTL_Check(pkt)
        # users can also call modules with no return
        #self.NFG.displayTCPFields(pkt)
        self._switch_mod(pkt, fields, ops)

    def handle_udp(self,pkt):
        print "handle udp"
        fields, ops = self.NFG.default_Field_Ops(pkt)
        #fields, ops = self.NFG.TTL_Check(pkt)
        self._switch_mod(pkt, fields, ops)

    def handle_unk(self,pkt):
        print "handl unk"
        fields, ops = self.NFG.default_Field_Ops(pkt)
        self._switch_mod(pkt, fields, ops)
		
	##################################################################
	# Supporting Code
	##################################################################
    #Initialize switch to send all packets to controller (lowest priority)
    # Adds a Table-miss flow entry (see page 8 of "Ryu: Using OpenFlow 1.3"
    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
    def switch_features_handler(self, ev):
        print "Received Switch features"
        datapath = ev.msg.datapath
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        
        # install table-miss flow entry
        match = parser.OFPMatch()
        actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                          ofproto.OFPCML_NO_BUFFER)]
	self.add_flow(datapath, 0, match, actions)
	#self._get_proactive_rules(datapath,parser,ofproto)

	def _add_proactive_flow(self,dp, parser, ofproto, fields,ops):
            actions = []
            if ops['op'] == 'drop':
                out_port = ofproto.OFPPC_NO_RECV
                actions.append(parser.OFPActionOutput(out_port))
            if ops == 'redir':
                out_port = ops['newport']
                actions.append(parser.OFPActionOutput(out_port))
                
	    match = parser.OFPMatch(eth_type=fields['eth_type'], 
					ip_proto=fields['proto'], 
					ipv4_src=fields['srcip'], 
                                        ipv4_dst=fields['dstip'],
                                        tcp_dst = fields['srctcp'])
	    
	    self.add_flow(dp, ops['priority'], match, actions)
    
    ########################################################################
    # Adds flow to the switch so future packets aren't sent to the cntrl 
    
    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)    
       
    ########################################################################
    # Adds flow to the switch so future packets are not sent to the
    # controller (requires priority, idle_t, and hard_t)
    def add_timeFlow(self, dp, ops, match, actions):
        ofproto = dp.ofproto
        parser = dp.ofproto_parser
            
        inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                             actions)]
        #fix switch mod to address 'idle_t'
        mod = parser.OFPFlowMod(datapath=dp,
                            priority=ops['priority'],
                            idle_timeout=ops['idle_t'],
                            hard_timeout=ops['hard_t'],
                            match=match, instructions=inst)
        dp.send_msg(mod) 
		
    ######################################################################## 
    #This decorator calls initial_event for packet arrivals
    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def initial_event(self,ev):
        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)
        #Call <Pkt_Parse> to Build pkt object
        parsPkt = Pkt_Parse()
        pkt = parsPkt.handle_pkt(ev)
        
        # Call appropriate handler for arriving packets (add IPv6,DHCP,etc.)
        if pkt['udp'] != None:
            self.handle_udp(pkt)
        elif pkt['tcp'] != None:
            self.handle_tcp(pkt)
        elif pkt['icmp'] != None:
            self.handle_icmp(pkt)
        elif pkt['ip']!= None:
            self.handle_ip(pkt)
        elif pkt['arp']!=None:
            self.handle_arp(pkt)
        elif pkt['eth'] != None:
            self.handle_eth(pkt)
        else:
            print "Packet not identified"
            self.handle_unk(pkt)

    ############################################################    
    # Choose the field and ops having the highest priority and 
    # assert it.    
    def _build_FldOps(xfields,xops):
        priority = 0
        for x in len(xfields):
            if xfields[x]['priority'] > priority:
                fields,ops = xfields[x],xops[x]
        return fields,ops  
               
    ##############################################################        
    #Imeplement mac-learning (switch_mod13.py) for ethernet packets.  
    def _switch_mod(self, pkt, fields, ops):
        #Build match from pkt and fields
        match = self.pkt_match(fields)
		#Build actions from pkt and ops
        actions = self.pkt_action(pkt,ops,fields)                            
        priority = ops['priority']
        msg = fields['msg']                          
        parser, ofproto = fields['dp'].ofproto_parser, fields['ofproto']

        # install temporary flow to avoid future packet_in. 
        # idle_t and hard_t must be set to something. 
        if ops['idle_t'] or ops['hard_t']:
            if out_port != ofproto.OFPP_FLOOD:
                self.add_timeFlow(dp, ops, match, actions)

        # For ping and wget, data = None
        data = None
        if msg.buffer_id == ofproto.OFP_NO_BUFFER:
            data = msg.data

        out = parser.OFPPacketOut(datapath=fields['dp'],
                                  buffer_id=msg.buffer_id,
                                  in_port=fields['inport'],
                                  actions=actions, data=data)

        fields['dp'].send_msg(out)

    #############################################################
    #Use fields to build match 
    def pkt_match(self, fields):
        parser = fields['dp'].ofproto_parser
        if fields['srcip'] != None and fields['srcip'] != None:
            match = parser.OFPMatch(ipv4_src=fields['srcip'], 
										ipv4_dst = fields['dst_ip'])
        elif fields['srcip'] != None or fields['srcip'] != None:
            matchfield=fields['srcip'] if fields['srcip'] !=None else fields['dstip']
            match = parser.OFPMatch(ipv4_src=matchfield)
        elif fields['srcmac'] == None:
            match = parser.OFPMatch(in_port=fields['inport'])
        else:
            match = parser.OFPMatch(in_port=fields['inport'],
                                    eth_dst=fields['dstmac'])
        return match

    ###############################################################
    #Determine action to be taken on packet ops={'op':None, 'newport':None}
    #User can forward , drop, redirect, mirror, or craft packets. 
    def pkt_action(self,pkt,ops,fields):
        actions = []
        parser = fields['dp'].ofproto_parser
        if ops['op'] == 'fwd':
            out_port = self.switch.handle_pkt(pkt)
            actions.append(parser.OFPActionOutput(out_port))
        elif ops['op'] == 'drop':
            out_port = fields['ofproto'].OFPPC_NO_RECV
            actions.append(parser.OFPActionOutput(out_port))
        elif ops == 'redir':
            out_port = ops['newport']
            actions.append(parser.OFPActionOutput(out_port))
        elif ops['op'] == 'mir':
            out_port = self.switch.handle_pkt(pkt)
            actions.append(parser.OFPActionOutput(out_port))
            mir_port = ops['newport']
            actions.append(parser.OFPActionOutput(mir_port))
        elif ops['op'] == 'craft':
            #create and send new pkt due to craft trigger
            self._build_pkt(ops, fields) ##need to remove pkt ##########
            #Now drop the arrived packet
            out_port = fields['ofproto'].OFPPC_NO_RECV
            actions.append(parser.OFPActionOutput(out_port))
                                                
        return actions

    #More work is required here to implement active testing for NATs etc.
    # Note fields object must be completely rewritten for crafted packet
    # Probably need to make fields['ptype'] = ['arp', 'ipv4']
    def _build_pkt(self, fields):
        pkt_out = packet.Packet()
        pkt_out.add_protocol(ethernet.ethernet(ethertype=fields['ethtype'],
                                               dst=fields['dstmac'],
                                               src=fields['srcmac']))
        # Add if ARP is required                           
                            
        if 'arp' in fields['ptype']:
            pkt_out.add_protocol(arp.arp(opcode=arp.ARP_REPLY,
                                 src_mac=fields['srcmac'],
                                 src_ip=fields['srcip'],
                                 dst_mac=fields['dstmac'],
                                 dst_ip=fields['dstip']))

        if ipv4 in fields['ptype']:
            pkt_out.add_protocol(ipv4.ipv4(dst=fields['dstip'],
                                 src=fields['srcip'],
                                 proto=fields['proto']))

        if 'icmp' in fields['ptype']:
            pkt_out.add_protocol(icmp.icmp(type_=icmp.ICMP_ECHO_REPLY,
                                 code=icmp.ICMP_ECHO_REPLY_CODE,
                                 csum=0,
                                 data=fields['data']))
								 
        if 'tcp' in fields['ptype']:
            pkt_out.add_protocol(tcp.tcp(dst_port=fields['dstport'],
				bits=fields['bits'],option=fields['opt'],
                                #=str('\\x00' * 4),
                                src_port=fields['srcport']))
                             
        #pkt.add_protocol('\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\
            #\n\\x0b\\x0c\\r\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\
            #\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f')

        self._send_packet(fields['dp'], ops['newport'], pkt_out)
	
	#Receive crafted packet and send it to the switch
    def _send_packet(self, datapath, port, pkt_out):
        if port == None: print "Port not defined" 
        #This methods sends the crafted message to the switch
        ofproto = datapath.ofproto
        parser = datapath.ofproto_parser
        pkt_out.serialize()
        self.logger.info("packet-out %s" % (pkt_out,))
        data = pkt_out.data
        actions = [parser.OFPActionOutput(port=port)]
        out = parser.OFPPacketOut(datapath=datapath,
                                  buffer_id=ofproto.OFP_NO_BUFFER,
                                  in_port=ofproto.OFPP_CONTROLLER,
                                  actions=actions,
                                  data=data)
        datapath.send_msg(out)
		
    #Clean up and disconnect ports. Controller going down  
    @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
    def handl_port_stat(self, ev):
        switch=SimpleSwitch()
        switch.port_status_handler(ev)