[ovs-dev] Adding NoviFlow experimenters to OVS.

yann bourdeau yann.bourdeau at noviflow.com
Wed Oct 11 17:51:27 UTC 2017

Hi Ben,

> Le 11 oct. 2017 à 13:09, Ben Pfaff <blp at ovn.org> a écrit :
> On Wed, Oct 11, 2017 at 12:35:05PM -0400, yann bourdeau wrote:
>> Hi Ben,
>> 	I was able to add successfully an experimenter flow to OVS(It is missing the matching on the packet). I have two questions:
>> 1- Is it normal that the experimenter OXM is not shown on dump-flows (I think it is normal from what I have understood from the code)?
>> root at yannb-virtual-machine:/home/yannb/src/ovs# ovs-ofctl13 dump-flows br0
>> cookie=0xa, duration=89.874s, table=2, n_packets=0, n_bytes=0, send_flow_rem priority=2 actions=drop
> Did you add anything to the code to display it?  Fields are not
> displayed automatically, it requires new code.
Not I did not add anything on the display side. I’ll do it later on

>> 2- The experimenter OXM field I need to implements are of variable length (both payload and mask to match on the payload of the packet). Can I create a new type that is variable length? Can I base my code on tunnnelMD type?
>> Here is the structure if you are interested:
>> struct oxm_fields {
>> uint16_t oxm_class; /* Match class OFPXMC_EXPERIMENTER 0xffff */
>> uint oxm_field:7; /* Match field within the class NOVI_OXM_UDP_PAYLOAD 0b0000001 */
>> uint oxm_hasmask:1; /* Set if OXM includes a bitmask in payload (wildcard match tables only) */
>> uint8_t oxm_length; /* Length of OXM payload */
>> uint32_t experimenter; /* NoviFlow experimenter ID 0xff000002 */
>> uint8_t payload[1-32] /* 1-32 payload bytes to be matched on*/
>> uint8_t mask [0-32] /* Optional mask present if oxm_hasmask bit is set in the header */
>> };
> tunnelMD is probably the best model since it's the only variable-length
> field we have.  I'd start with the code there.

I was successful to add the flow with my new type.

However, I needed to comment some code in the following function because my OXM is not mapped.

from nx-match.c:

static enum ofperr
nx_pull_header__(struct ofpbuf *b, bool allow_cookie,
                 const struct vl_mff_map *vl_mff_map, uint64_t *header,
                 const struct mf_field **field)
    if (b->size < 4) {
        goto bad_len;

    *header = ((uint64_t) ntohl(get_unaligned_be32(b->data))) << 32;
    if (is_experimenter_oxm(*header)) {
        if (b->size < 8) {
            goto bad_len;
        *header = ntohll(get_unaligned_be64(b->data));
    if (nxm_length(*header) < nxm_experimenter_len(*header)) {
        VLOG_WARN_RL(&rl, "OXM header "NXM_HEADER_FMT" has invalid length %d "
                     "(minimum is %d)",
                     NXM_HEADER_ARGS(*header), nxm_length(*header),
        goto error;
    ofpbuf_pull(b, nxm_header_len(*header));

    if (field) {
        *field = mf_from_oxm_header(*header, vl_mff_map);
        if (!*field && !(allow_cookie && is_cookie_pseudoheader(*header))) {
            VLOG_DBG_RL(&rl, "OXM header "NXM_HEADER_FMT" is unknown",
            return OFPERR_OFPBMC_BAD_FIELD;
        } /*else if (mf_vl_mff_invalid(*field, vl_mff_map)) {

    return 0;

    VLOG_DBG_RL(&rl, "encountered partial (%"PRIu32"-byte) OXM entry",
    *header = 0;
    if (field) {
        *field = NULL;

Is it mandatory to have the field mapped for a variable length? What does the concept of mapped means?


More information about the dev mailing list