Skip to content

Handling the New Message in the Switch Side

Eder Leão Fernandes edited this page Sep 13, 2018 · 3 revisions

So you finally have your amazing message to query the maximum number of queues supported by a port.
(Don't you? You should check it out first)

But where and how to handle that received OFPT_MAX_QUEUE_REQUEST and how to send the OFPT_MAX_QUEUE_REPLY?

This guide will show you the minimal and necessary steps to have a new functionality operating in the switch.


Implementing the Message Handler

There is not an specific place to implement the function to handle the message. Most of the functions are implemented on udadapath/dp_control.c, but the functions that handles flow and table modification are implemented at pipeline.h or group modifications handled in the file group_table.h. It usually comes to which kind of element is related to the message.

For our example, the handler will be implemented as an static function in udadapath/dp_control.c.

There is not a requirement for the arguments of a function to handle a message, but in general they take three struct arguments:

struct datapath: It is the struct of the datapath that receives the message that will be handled.
struct ofl_msg_header: The message received from the controller.
struct sender: The sender identifies the remote connection that sent the message. It is used for cases in which a reply is required.

The reason is that the function handle_control_msg, where the functions are called, take the same argument.

The declaration of our handler function is as follows:

static ofl_err
handle_control_max_queue_request(struct datapath *dp, struct ofl_msg_header *msg, const struct sender *sender);

The implementation should be straight forward as the only action the function needs to do is to send a reply message with the maximum number of queues. First, build the message using struct , you previously defined in the first part of this tutorial

If you do not remember, or do not want to check the first step, here is how the struct looks like.

struct ofp_max_queues_reply{
    struct ofp_header header;
    uint16_t max_queues;
    uint8_t pad[6];
}

Now you can use initialize the struct. Because the packing function will fill most of the OpenFlow header and padding, the only fields you need to fill are the header type and max_queues value. The type is, as previously defined, OFPT_MAX_QUEUE_REPLY max_queues and the value belongs to the datapath struct.

struct ofp_max_queues_reply reply =
            {{.type = OFPT_MAX_QUEUES_REPLY},
             .max_queues  = dp->max_queues
             };

Next, send the reply and free the received request.

dp_send_message(dp, (struct ofl_msg_header *)&reply, sender);
ofl_msg_free(msg, dp->exp);

The whole function will like this:

static ofl_err
handle_control_max_queue_request(struct datapath *dp, struct ofl_msg_header *msg, const struct sender *sender)
{
    struct ofp_max_queues_reply reply =
            {{.type = OFPT_MAX_QUEUES_REPLY},
             .max_queues  = dp->max_queues
             };

    dp_send_message(dp, (struct ofl_msg_header *)&reply, sender);
    ofl_msg_free(msg, dp->exp);
}

Using the handler

Find the function that dispatches control messages to the appropriate handler.
This function is on udadapath/dp_control.c. The declaration is as follows:

ofl_err handle_control_msg(struct datapath *dp, struct ofl_msg_header *msg, const struct sender *sender)

As one might expect, a long switch handles all type of supported OpenFlow messages.

switch (msg->type) {
   case OFPT_HELLO: {
            ofl_msg_free(msg, dp->exp);
            return 0;
        }
        case OFPT_ERROR: {
            return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE);
        }
   /* And so on */
}

You just need to add OFPT_MAX_QUEUE_REQUEST and use the function handle_control_max_queue_request.

    case OFPT_MAX_QUEUE_REQUEST: {
            return handle_control_max_queue_request(dp, msg, sender);
      }

You also may want to handle the possible case of the switch receiving a OFPT_MAX_QUEUE_REPLY. Since the switch should not handle that message, an error is generated.

    case OFPT_MAX_QUEUE_REPLY: {
            return ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_TYPE);
      }