Daniel
Daniel

Reputation: 1664

How to fetch OVS Port Information with Ryu

I am currently setting up a testbed using the OpenVSwitch and the Ryu SDN Controller framework. The OVS is running on linux, and has three ports (including the internal port), as can be seen in the following output:

root@MOF:~# ovs-ofctl -O OpenFlow13 show br0
OFPT_FEATURES_REPLY (OF1.3) (xid=0x2): dpid:aaaaaaaaaaaaaa21
n_tables:254, n_buffers:256
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS
OFPST_PORT_DESC reply (OF1.3) (xid=0x3):
 6(eth1): addr:00:50:56:82:dc:83
     config:     0
     state:      0
     current:    10GB-FD COPPER
     advertised: COPPER
     supported:  1GB-FD 10GB-FD COPPER
     speed: 10000 Mbps now, 10000 Mbps max
 10(eth2): addr:00:50:56:82:29:cb
     config:     0
     state:      0
     current:    10GB-FD COPPER
     advertised: COPPER
     supported:  1GB-FD 10GB-FD COPPER
     speed: 10000 Mbps now, 10000 Mbps max
 LOCAL(br0): addr:00:50:56:82:29:cb
     config:     PORT_DOWN
     state:      LINK_DOWN
     speed: 0 Mbps now, 0 Mbps max
OFPT_GET_CONFIG_REPLY (OF1.3) (xid=0x5): frags=normal miss_send_len=0

I managed to get notified when new switches connect using the following code snippet (minimal working example):

class MscApp(app_manager.RyuApp):

    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    _CONTEXTS = {
        'dpset': dpset.DPSet,
    }

    def __init__(self, *args, **kwargs):
        super(MscApp, self).__init__(*args, **kwargs)
        self.dpset = kwargs['dpset']

        # Initiate datapath array
        self.datapaths = {
            0xAAAAAAAAAAAAAA21: {
                'name': 'Munic',
            }
        }


    @set_ev_cls(ofp_event.EventOFPDescStatsReply, MAIN_DISPATCHER)
    def desc_stats_reply_handler(self,msg): 
        ofp = msg.datapath.ofproto
        body = ev.msg.body

        self.logger.info('OFPDescStatsReply received: '
                         'mfr_desc=%d hw_desc=%s sw_desc=%s '
                         'serial_num=%s dp_desc=%s ',
                         body.mfr_desc, body.hw_desc, body.sw_desc,
                         body.serial_num, body.dp_desc)

     @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
         print 'Router %s has joined!' % self.datapaths[datapath.id]['name']

         # Get available ports
         req = parser.OFPPortDescStatsRequest(datapath, 0)
         datapath.send_msg(req)

     @set_ev_cls(event.EventLinkAdd)
     def link_add(self, ev):
        print ev.link.src, ev.link.dst
        print self._get_hwaddr(ev.link.src.dpid, ev.link.src.port_no)

When the shown switch connects, the controller correctly prints Router Munic has joined!. However, the code snippet to fetch information about the available ports does not work. Do you have an idea how to fetch the available ports in ryu? The code snippet is from this question.

Background: The OVS has two physical ports, one is connected to an "outside" network, the other one to an "inside" network. Not only do I need to know which ports are available, I also need to know which port is which. Any ideas how to solve this? Thanks in advance!

Upvotes: 2

Views: 2358

Answers (1)

Ehsan Ab
Ehsan Ab

Reputation: 679

Based on my understanding you can set the event to be received on different phases. The second argument of set_ev_cls indicates the state of the switch. If you want to ignore packet_in messages before the negotiation between Ryu and the switch finishes use MAIN_DISPATCHER. In other words, using MAIN_DISPATCHER means this function is called only after the negotiation completes.

There are 4 negotiation phases:

  • HANDSHAKE_DISPATCHER -> Sending and waiting for hello message
  • CONFIG_DISPATCHER -> Version negotiated and sent features-request message
  • MAIN_DISPATCHER -> Switch-features message received and sent set-config message
  • DEAD_DISPATCHER -> Disconnect from the peer. Or disconnecting due to some errors.

See the the Ryu API for more details.

So back to your question, a possible reason is that you are using CONFIG_DISPATCHER. Change it to MAIN_DISPATCHER and see if it works.

Also, make sure you send a OFPPortDescStatsRequest to the switch. Cause I don't think switches generate EventOFPPortDescStatsReply unless are requested. You need a function which generates a request for a switch. I fell like this is would fix your code. Here is the function: (however, i recommend to have look at this file in my github).

def send_port_desc_stats_request(self, datapath):
    ofp_parser = datapath.ofproto_parser

    req = ofp_parser.OFPPortDescStatsRequest(datapath, 0)
    datapath.send_msg(req)

Events EventOFPPortStatsReply and EventOFPPortDescStatsReply may be useful. I am using them like this.

I have a tutorial in my github, I am using several events there. The above function are defined and explained there .

Upvotes: 3

Related Questions