2016-07-05 2 views
0

J'ai créé un réseau simple dans l'environnement mininet avec la commande suivante:ryu (NRS) contrôleur de la circulation à partir de (par exemple) hôte 1

$ sudo mn --topo single,3 --mac --controller remote --switch ovsk 

Je veux utiliser RYU CONTROLLER pour calculer le trafic de la bande passante sur le port spécial du commutateur. Je pense à utiliser un événement OFPEVENTPacketIn pour le paquet entrant, mais je n'ai aucune idée du port de paquet de paquet à venir.

Mon code:

from operator import attrgetter 
from ryu.app import simple_switch_13 
from ryu.controller import ofp_event 
from ryu.controller.handler import MAIN_DISPATCHER, DEAD_DISPATCHER 
from ryu.controller.handler import set_ev_cls 
from ryu.lib import hub 

class SimpleMonitor(simple_switch_13.SimpleSwitch13): 

    def __init__(self, *args, **kwargs): 
     super(SimpleMonitor, self).__init__(*args, **kwargs) 
     self.datapaths = {} 
     self.monitor_thread = hub.spawn(self._monitor) 

    @set_ev_cls(ofp_event.EventOFPStateChange, 
       [MAIN_DISPATCHER, DEAD_DISPATCHER]) 
    def _state_change_handler1(self, ev): 
     datapath = ev.datapath 
     if ev.state == MAIN_DISPATCHER: 
      if not datapath.id in self.datapaths: 
       self.logger.debug('register datapath: %016x', datapath.id) 
       self.datapaths[datapath.id] = datapath 
     elif ev.state == DEAD_DISPATCHER: 
      if datapath.id in self.datapaths: 
       self.logger.debug('unregister datapath: %016x', datapath.id) 
       del self.datapaths[datapath.id] 

    def _monitor(self): 
     while True: 
      for dp in self.datapaths.values(): 
       self._request_stats(dp) 
      hub.sleep(10) 

    def _request_stats(self, datapath): 
     self.logger.debug('send stats request: %016x', datapath.id) 
     ofproto = datapath.ofproto 
     parser = datapath.ofproto_parser 

     req = parser.OFPFlowStatsRequest(datapath) 
     datapath.send_msg(req) 

     req = parser.OFPPortStatsRequest(datapath, 0, ofproto.OFPP_ANY) 
     datapath.send_msg(req) 

    @set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER) 
    def _flow_stats_reply_handler(self, ev): 
     body = ev.msg.body 

     self.logger.info('datapath   ' 

         'in-port eth-dst   ' 
         'out-port packets bytes') 
     self.logger.info('---------------- ' 
         '-------- ----------------- ' 
         '-------- -------- --------') 

     for stat in sorted([flow for flow in body if flow.priority == 1], 
          key=lambda flow: (flow.match['in_port'], 
              flow.match['eth_dst'])): 
#   self.logger.info('%016x %8x %17s %8x %8d %8d', 
       if stat.match['in_port']==1: 
        self.logger.info('%x %x %s %x %d %d', 
          ev.msg.datapath.id, 
          stat.match['in_port'], stat.match['eth_dst'], 
          stat.instructions[0].actions[0].port, 
          stat.packet_count, stat.byte_count) 

     #for stat in [1234]#sorted([flow for flow in body if flow.priority == 1], 
         # key=lambda flow: (flow.match['in_port'], 
           #   flow.match['eth_dst'])): 
#   self.logger.info('%016x %8x %17s %8x %8d %8d', 
       # if stat.match['in_port']==1: 
        # self.logger.info('%x %x %s %x %d %d', 
        #   ev.msg.datapath.id, 
        #   stat.match['in_port'], stat.match['eth_dst'], 
        #   stat.instructions[0].actions[0].port, 
        #   stat.packet_count, stat.byte_count) 

    @set_ev_cls(ofp_event.EventOFPPortStatsReply, MAIN_DISPATCHER) 
    def _port_stats_reply_handler(self, ev): 
     body = ev.msg.body 

     self.logger.info('datapath   port  ' 
         'rx-pkts rx-bytes rx-error ' 
         'tx-pkts tx-bytes tx-error') 
     self.logger.info('---------------- -------- ' 
         '-------- -------- -------- ' 
         '-------- -------- --------') 
     for stat in sorted(body, key=attrgetter('port_no')): 
      if stat.port_no==1: 

       self.logger.info('%016x %8x %8d %8d %8d %8d %8d %8d', 
          ev.msg.datapath.id, stat.port_no, 
          stat.rx_packets, stat.rx_bytes, stat.rx_errors, 
          stat.tx_packets, stat.tx_bytes, stat.tx_errors) 

S'il vous plaît aidez-moi à modifier ce code pour répondre à ma question. Merci.

Répondre

1

Vous devez ajouter deux méthodes dans votre contrôleur: 1) une méthode qui demande des statistiques 2) une méthode qui capture les réponses des commutateurs.

La méthode pour répondre à des statistiques est la suivante:

def send_flow_stats_request(self, datapath): 
    ofp = datapath.ofproto 
    ofp_parser = datapath.ofproto_parser 
cookie = cookie_mask = 0 
match = ofp_parser.OFPMatch(in_port=1) 
req = ofp_parser.OFPFlowStatsRequest(datapath, 0, 
            ofp.OFPTT_ALL, 
            ofp.OFPP_ANY, ofp.OFPG_ANY, 
            cookie, cookie_mask, 
            match) 
datapath.send_msg(req) 

La méthode de capture des réponses est celle-ci:

@set_ev_cls(ofp_event.EventOFPFlowStatsReply, MAIN_DISPATCHER) 
def flow_stats_reply_handler(self, ev): 
    flows = [] 
    for stat in ev.msg.body: 
     flows.append('table_id=%s ' 
        'duration_sec=%d duration_nsec=%d ' 
        'priority=%d ' 
        'idle_timeout=%d hard_timeout=%d flags=0x%04x ' 
        'cookie=%d packet_count=%d byte_count=%d ' 
        'match=%s instructions=%s' % 
        (stat.table_id, 
         stat.duration_sec, stat.duration_nsec, 
         stat.priority, 
         stat.idle_timeout, stat.hard_timeout, stat.flags, 
         stat.cookie, stat.packet_count, stat.byte_count, 
         stat.match, stat.instructions)) 
    self.logger.debug('FlowStats: %s', flows) 

Une fois que vous capturez les statistiques, vous pouvez calculer l'utilisation de la bande passante.

Cependant, vous avez également d'autres types de demandes que vous pouvez effectuer, donc je vous suggère de lire le document de seigle.

http://ryu.readthedocs.io/en/latest/