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

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to