[ovs-dev] New custom Message - unknown OpenFlow message

Adam Paul Rzyska adam.rzyska at smail.inf.h-brs.de
Mon Mar 27 19:08:32 UTC 2017


Hello,

in the last weeks I tried to exchange custom openflow messages (type  
experimenter) between a controller (ONOS) and a switch (Open vSwitch).  
The controller sends a really simple of-msg:

struct my_custom_struct : of_nicira_header {
      uint8_t version;
      uint8_t type == 4;
      uint16_t length;
      uint32_t xid;
      uint32_t experimenter == 0x00002320;
      uint32_t subtype == 0x0080;
  };

In wireshark and OVS it is possible to see, that the switch receives  
my custom messages. I've added ofpraw and oftype in ofp-msgs.h. My  
request_method have been added to ofproto.c and also into the switch  
case. It works fine with a simple VLOG_INFO() output. Every time the  
switch receive my custom message a VLOG_INFO-message pops up into the  
logging file of OVS. But as soon as I'm trying to implement a  
reply/replies a error occurs, which crash's the vswichd (demon). This  
results in disconnecting the switch from the controller.

Error message: 2017-02-05T12:09:02Z|00225|ofp_msgs|WARN|unknown  
OpenFlow message (version 4, type 19, stat 0, vendor 0x2320, subtype 80)

I know exactly where it happens, but I don't know why... It starts  
with ofpmp_init() in my method.

My method:

static enum ofperr
my_custom_method(struct ofconn *ofconn, const struct ofp_header *request)
{
     struct ofproto *ofproto = ofconn_get_ofproto(ofconn);
     struct ovs_list replies;

     VLOG_INFO("Stat Request type: %i", request->type);

     ofpmp_init(&replies, request);

     VLOG_INFO("After OFPMP INIT");
	return 0;
}

 From there on to the file ofp-msgs.c:

void
ofpmp_init(struct ovs_list *replies, const struct ofp_header *request)
{

     struct ofpbuf *msg;

     list_init(replies);

     msg = ofpraw_alloc_stats_reply(request, 1000);
     list_push_back(replies, &msg->list_node);
}

Next one would be ofpraw_alloc_stats_reply:

struct ofpbuf *
ofpraw_alloc_stats_reply(const struct ofp_header *request,
                          size_t extra_tailroom)
{
     enum ofpraw request_raw;
     enum ofpraw reply_raw;
     enum ofperr error;

     error = ofpraw_decode_partial(&request_raw, request,
                                   ntohs(request->length));
     ovs_assert(!error);

     reply_raw = ofpraw_stats_request_to_reply(request_raw, request->version);
     ovs_assert(reply_raw);

     return ofpraw_alloc_reply(reply_raw, request, extra_tailroom);
}

Just two more ofpraw_stats_request_to_reply:
enum ofpraw
ofpraw_stats_request_to_reply(enum ofpraw raw, uint8_t version)
{
     const struct raw_info *info = raw_info_get(raw);
     const struct raw_instance *instance = raw_instance_get(info, version);
     enum ofpraw reply_raw;
     struct ofphdrs hdrs;
     enum ofperr error;

     hdrs = instance->hdrs;

     switch ((enum ofp_version)hdrs.version) {
     case OFP10_VERSION:
         ovs_assert(hdrs.type == OFPT10_STATS_REQUEST);
         hdrs.type = OFPT10_STATS_REPLY;
         break;
     case OFP11_VERSION:
     case OFP12_VERSION:
     case OFP13_VERSION:
     case OFP14_VERSION:
     case OFP15_VERSION:
         ovs_assert(hdrs.type == OFPT11_STATS_REQUEST);
         hdrs.type = OFPT11_STATS_REPLY;
         break;
     default:
         OVS_NOT_REACHED();
     }

     error = ofpraw_from_ofphdrs(&reply_raw, &hdrs);
     ovs_assert(!error);

     return reply_raw;
}

The last one would be ofpraw_from_ofphdrs:

static enum ofperr
ofpraw_from_ofphdrs(enum ofpraw *raw, const struct ofphdrs *hdrs)
{
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);

     struct raw_instance *raw_hdrs;
     uint32_t hash;

     ofpmsgs_init();

     hash = ofphdrs_hash(hdrs);
     HMAP_FOR_EACH_WITH_HASH (raw_hdrs, hmap_node, hash, &raw_instance_map) {
         if (ofphdrs_equal(hdrs, &raw_hdrs->hdrs)) {
             *raw = raw_hdrs->raw;
             return 0;
         }
     }

     if (!VLOG_DROP_WARN(&rl)) {
         struct ds s;

         ds_init(&s);
         ds_put_format(&s, "version %"PRIu8", type %"PRIu8,
                       hdrs->version, hdrs->type);
         if (ofphdrs_is_stat(hdrs)) {
             ds_put_format(&s, ", stat %"PRIu16, hdrs->stat);
         }
         if (hdrs->vendor) {
             ds_put_format(&s, ", vendor 0x%"PRIx32", subtype %"PRIu32,
                           hdrs->vendor, hdrs->subtype);
         }
         VLOG_WARN("unknown OpenFlow message (%s)", ds_cstr(&s));
         ds_destroy(&s);
     }

     return (hdrs->vendor ? OFPERR_OFPBRC_BAD_SUBTYPE
             : ofphdrs_is_stat(hdrs) ? OFPERR_OFPBRC_BAD_STAT
             : OFPERR_OFPBRC_BAD_TYPE);
}

I couldn't understand why my custom message would fail, but every  
other messages which use ofpmp_init would work smoothly. Did I forget  
any file, where I should add my subtype/custom message? Do you need  
any more information?

Any hint would be appreciated.

Best regards,
-- 
Adam Paul Rzyska



More information about the dev mailing list