static void print_oxm_match(FILE *stream, struct ofl_match *m){
        struct ofl_match_tlv   *f;
        size_t size = m->header.length;
        fprintf(stream, "oxm{");
        if (size) {
            /*TODO: Create a mapping of header values and names to avoid so many comparisons */ 
            HMAP_FOR_EACH(f, struct ofl_match_tlv, hmap_node, &m->match_fields){                             
                print_oxm_tlv(stream, f, &size);
            }
        }    
        else fprintf(stream, "all match");
void
ofl_action_print(FILE *stream, struct ofl_action_header *act, struct ofl_exp *exp) {

    ofl_action_type_print(stream, act->type);

    switch (act->type) {
        case OFPAT_OUTPUT: {
            struct ofl_action_output *a = (struct ofl_action_output *)act;

            fprintf(stream, ",{\"port\":");
            ofl_port_print(stream, a->port);
            if (a->port == OFPP_CONTROLLER) {
                fprintf(stream, ", \"mlen\":%u}", a->max_len);
            } else {
                fprintf(stream, "}");
            }
            break;
        }
        case OFPAT_SET_FIELD:{
            size_t size;
            struct ofl_action_set_field *a = (struct ofl_action_set_field *)act;
            fprintf(stream, ",{");
            size = 4 + OXM_LENGTH(a->field->header);
            print_oxm_tlv(stream, a->field, &size);
            fprintf(stream, "}");
            break;
        }
        case OFPAT_COPY_TTL_OUT:
        case OFPAT_COPY_TTL_IN: {
            break;
        }
        case OFPAT_SET_MPLS_TTL: {
            struct ofl_action_mpls_ttl *a = (struct ofl_action_mpls_ttl *)act;

            fprintf(stream, ",{\"ttl\":%u}", a->mpls_ttl);
            break;
        }
        case OFPAT_DEC_MPLS_TTL: {
            break;
        }
        case OFPAT_PUSH_VLAN:
        case OFPAT_PUSH_MPLS:
        case OFPAT_PUSH_PBB:{
            struct ofl_action_push *a = (struct ofl_action_push *)act;

            fprintf(stream, ",{\"eth\":\"0x%04"PRIx16"\"}", a->ethertype);
            break;
        }
        case OFPAT_POP_VLAN:
        case OFPAT_POP_PBB: {
            break;
        }
        case OFPAT_POP_MPLS: {
            struct ofl_action_pop_mpls *a = (struct ofl_action_pop_mpls *)act;

            fprintf(stream, ",{\"eth\":\"0x%04"PRIx16"\"}", a->ethertype);
            break;
        }
        case OFPAT_SET_QUEUE: {
            struct ofl_action_set_queue *a = (struct ofl_action_set_queue *)act;

            fprintf(stream, ",{\"q\":");
            ofl_queue_print(stream, a->queue_id);
            fprintf(stream, "}");
            break;
        }
        case OFPAT_GROUP: {
            struct ofl_action_group *a = (struct ofl_action_group *)act;

            fprintf(stream, ",{\"id\":");
            ofl_group_print(stream, a->group_id);
            fprintf(stream, "}");

            break;
        }
        case OFPAT_SET_NW_TTL: {
            struct ofl_action_set_nw_ttl *a = (struct ofl_action_set_nw_ttl *)act;

            fprintf(stream, ",{\"ttl\":%u}", a->nw_ttl);
            break;
        }
        case OFPAT_DEC_NW_TTL: {
            break;
        }
        case OFPAT_EXPERIMENTER: {
            if (exp == NULL || exp->act == NULL || exp->act->to_string == NULL) {
                struct ofl_action_experimenter *a = (struct ofl_action_experimenter *)act;

                fprintf(stream, ",{\"id\":\"0x%"PRIx32"\"}", a->experimenter_id);
            } else {
                char *c = exp->act->to_string(act);
                fprintf(stream, "%s", c);
                free (c);
            }
            break;
        }
    }
}