Exemplo n.º 1
0
size_t
ofl_actions_pack(struct ofl_action_header *src, struct ofp_action_header *dst, uint8_t* data,  struct ofl_exp *exp) {

    dst->type = htons(src->type);
    memset(dst->pad, 0x00, 4);

    switch (src->type) {
        case OFPAT_OUTPUT: {
            struct ofl_action_output *sa = (struct ofl_action_output *)src;
            struct ofp_action_output *da = (struct ofp_action_output *)dst;

            da->len =     htons(sizeof(struct ofp_action_output));
            da->port =    htonl(sa->port);
            da->max_len = htons(sa->max_len);
            memset(da->pad, 0x00, 6);
            return sizeof(struct ofp_action_output);
        }

        case OFPAT_COPY_TTL_OUT:
        case OFPAT_COPY_TTL_IN: {
            dst->len = htons(sizeof(struct ofp_action_header));
            return sizeof(struct ofp_action_header);
        }

        case OFPAT_SET_MPLS_TTL: {
            struct ofl_action_mpls_ttl *sa = (struct ofl_action_mpls_ttl *)src;
            struct ofp_action_mpls_ttl *da = (struct ofp_action_mpls_ttl *)dst;

            da->len =      htons(sizeof(struct ofp_action_mpls_ttl));
            da->mpls_ttl = sa->mpls_ttl;
            memset(da->pad, 0x00, 3);
            return sizeof(struct ofp_action_mpls_ttl);
        }
        case OFPAT_DEC_MPLS_TTL: {
            dst->len = htons(sizeof(struct ofp_action_header));
            return sizeof(struct ofp_action_header);
        }
        case OFPAT_PUSH_VLAN:
        case OFPAT_PUSH_MPLS:
        case OFPAT_PUSH_PBB:{
            struct ofl_action_push *sa = (struct ofl_action_push *)src;
            struct ofp_action_push *da = (struct ofp_action_push *)dst;

            da->len =       htons(sizeof(struct ofp_action_push));
            da->ethertype = htons(sa->ethertype);
            memset(da->pad, 0x00, 2);
            return sizeof(struct ofp_action_push);
        }
        case OFPAT_POP_VLAN:
        case OFPAT_POP_PBB: {
            struct ofp_action_header *da = (struct ofp_action_header *)dst;

            da->len = htons(sizeof(struct ofp_action_header));
            return sizeof (struct ofp_action_header);
        }
        case OFPAT_POP_MPLS: {
            struct ofl_action_pop_mpls *sa = (struct ofl_action_pop_mpls *)src;
            struct ofp_action_pop_mpls *da = (struct ofp_action_pop_mpls *)dst;

            da->len =       htons(sizeof(struct ofp_action_pop_mpls));
            da->ethertype = htons(sa->ethertype);
            memset(da->pad, 0x00, 2);
            return sizeof(struct ofp_action_pop_mpls);
        }
        case OFPAT_SET_QUEUE: {
            struct ofl_action_set_queue *sa = (struct ofl_action_set_queue *)src;
            struct ofp_action_set_queue *da = (struct ofp_action_set_queue *)dst;

            da->len =      htons(sizeof(struct ofp_action_set_queue));
            da->queue_id = htonl(sa->queue_id);
            return sizeof(struct ofp_action_set_queue);
        }
        case OFPAT_GROUP: {
            struct ofl_action_group *sa = (struct ofl_action_group *)src;
            struct ofp_action_group *da = (struct ofp_action_group *)dst;

            da->len =      htons(sizeof(struct ofp_action_group));
            da->group_id = htonl(sa->group_id);
            return sizeof(struct ofp_action_group);
        }
        case OFPAT_SET_NW_TTL: {
            struct ofl_action_set_nw_ttl *sa = (struct ofl_action_set_nw_ttl *)src;
            struct ofp_action_nw_ttl *da = (struct ofp_action_nw_ttl *)dst;

            da->len =    htons(sizeof(struct ofp_action_nw_ttl));
            da->nw_ttl = sa->nw_ttl;
            memset(da->pad, 0x00, 3);
            return sizeof(struct ofp_action_nw_ttl);
        }
        case OFPAT_DEC_NW_TTL: {
            dst->len = htons(sizeof(struct ofp_action_header));
            return sizeof(struct ofp_action_header);
        }
        case OFPAT_SET_FIELD: {
            struct ofl_action_set_field *sa = (struct ofl_action_set_field *) src;
            struct ofp_action_set_field *da = (struct ofp_action_set_field *) dst;
            uint32_t header;
            uint8_t padding_size;

            da->len = htons(sizeof(struct ofp_action_set_field) + ROUND_UP(OXM_LENGTH(sa->field->header),8));
            /*Put OXM header in the field*/
            header = htonl(sa->field->header);
            memcpy(&da->field, &header, 4);

/* For OFDPA2.0
 */
            if(0xFFFF == OXM_VENDOR(sa->field->header))  /* exp */
            {
                struct OFDPA_ofl_match_exp_tlv* ofdpa_exp_tlv_p = (struct OFDPA_ofl_match_exp_tlv*)sa->field;
                uint32_t experimenter_v = htonl(ofdpa_exp_tlv_p->experimenter);
                uint16_t exp_type_v = htons(ofdpa_exp_tlv_p->exp_type);
                uint8_t length = OXM_LENGTH(sa->field->header);
                uint8_t offset_len = sizeof(struct ofp_action_set_field);

                length -= sizeof(experimenter_v);
                length -= sizeof(exp_type_v);

                memcpy(data + offset_len, &experimenter_v, sizeof(experimenter_v));
                offset_len += sizeof(experimenter_v);
                memcpy(data + offset_len, &exp_type_v, sizeof(exp_type_v));
                offset_len += sizeof(exp_type_v);

                switch(length)
                {
                    case (sizeof(uint8_t)):
                        memcpy(data + offset_len, ofdpa_exp_tlv_p->exp_data_p, sizeof(uint8_t));
                        break;

                    case (sizeof(uint16_t)):
                    {
                        uint16_t value = htons(*((uint16_t*) ofdpa_exp_tlv_p->exp_data_p));
                        memcpy(data + offset_len, &value, sizeof(value));
                        break;
                    }

                    case (sizeof(uint32_t)):
                    {
                        uint32_t value = htonl(*((uint32_t*) ofdpa_exp_tlv_p->exp_data_p));
                        memcpy(data + offset_len, &value, sizeof(value));
                        break;
                    }

                    case (sizeof(uint64_t)):
                    {
                        uint64_t value = hton64(*((uint64_t*) ofdpa_exp_tlv_p->exp_data_p));
                        memcpy(data + offset_len, &value, sizeof(value));
                        break;
                    }
                }

                /*padding*/
                padding_size = ROUND_UP(OXM_LENGTH(sa->field->header),8) - OXM_LENGTH(sa->field->header);
                memset(data + (sizeof(struct ofp_action_set_field) + OXM_LENGTH(sa->field->header)), 0, padding_size);
                return ntohs((da->len));
            }
/* End of OFDPA2.0
 */

            switch (OXM_LENGTH(sa->field->header)){
                case 1:
                case 6:
                case 12:
                case 16:
                   memcpy(data + sizeof(struct ofp_action_set_field), sa->field->value,OXM_LENGTH(sa->field->header));
                break;

                case 2:{
                   uint16_t value = htons(*((uint16_t*) sa->field->value));
                   memcpy(data + (sizeof(struct ofp_action_set_field)),&value,OXM_LENGTH(sa->field->header));
                    break;
                }
                case 4:{
                    uint16_t value1,value2;
                    uint32_t value;
                    uint8_t field = OXM_FIELD(sa->field->header);
                    if( field != 11 && field != 12 && field != 22 && field != 23)
                        value = htonl(*((uint32_t*) sa->field->value));
                    else
                        value = *((uint32_t*) sa->field->value);
                    if(field == 6){
                        value1 = value >> 16;
                        value2 = value & 0xffff;
                        value = (((uint32_t)value2) << 16)+(uint32_t)value1;
                    }
		              memcpy(data + (sizeof(struct ofp_action_set_field)), &value, OXM_LENGTH(sa->field->header));
                    break;
        		}
        		case 8:{
                    uint64_t value;
                    uint8_t field = OXM_FIELD(sa->field->header);

                    if(field == 38) /* This is for tunnel_id */
                        value = hton64(*((uint64_t *) sa->field->value));
                    else
                        value = htons(*((uint64_t *) sa->field->value));
                    memcpy(data + (sizeof(struct ofp_action_set_field)),&value,OXM_LENGTH(sa->field->header));
                    break;
                }
            }
            /*padding*/
            padding_size = ROUND_UP(OXM_LENGTH(sa->field->header),8) - OXM_LENGTH(sa->field->header);
            memset(data + (sizeof(struct ofp_action_set_field) + OXM_LENGTH(sa->field->header)), 0, padding_size);
            return ntohs((da->len));

        }
        case OFPAT_EXPERIMENTER: {
            if (exp == NULL || exp->act == NULL || exp->act->pack == NULL) {
                OFL_LOG_WARN(LOG_MODULE, "Trying to pack experimenter, but no callback was given.");
                return 0;
            }
            return exp->act->pack(src, dst);
        }
        default:
            return 0;
    };
Exemplo n.º 2
0
/* Two matches strictly match if their wildcard fields are the same, and all the
 * non-wildcarded fields match on the same exact values.
 * NOTE: Handling of bitmasked fields is not specified. In this implementation
 * masked fields are checked for equality, and only unmasked bits are compared
 * in the field.
 */
bool
match_std_strict(struct ofl_match *a, struct ofl_match *b, struct ofl_exp *exp) {

    struct ofl_match_tlv *flow_mod_match;
    struct ofl_match_tlv *flow_entry_match;
    int field_len;
    uint8_t *flow_mod_val, *flow_mod_mask=0;
    uint8_t *flow_entry_val, *flow_entry_mask=0;
    uint8_t oxm_field;
    bool has_mask;
    /* Both matches all wildcarded */
    if(!a->header.length && !b->header.length )
        return true;

    /* If the matches differ in length, there is no reason to compare */
    if (a->header.length != b->header.length)
        return false;

    /* Loop through the flow_mod match fields */
    HMAP_FOR_EACH(flow_mod_match, struct ofl_match_tlv, hmap_node, &a->match_fields)
    {
        /* Check presence of match field in flow entry */
        flow_entry_match = oxm_match_lookup(flow_mod_match->header, b);
        if (!flow_entry_match) {
            return false;
        }

        /* At this point match length and has_mask are equal */
        oxm_field = OXM_FIELD(flow_mod_match->header);
        has_mask = OXM_HASMASK(flow_mod_match->header);
        flow_mod_val = flow_mod_match->value;
        flow_entry_val = flow_entry_match->value;
        switch (OXM_VENDOR(flow_mod_match->header))
        {
            case (OFPXMC_OPENFLOW_BASIC):         
                field_len =  OXM_LENGTH(flow_mod_match->header);
                if (has_mask)
                    {
                        field_len /= 2;
                        flow_mod_mask = flow_mod_val + field_len;
                        flow_entry_mask = flow_entry_val + field_len;
                    }
                break;
            case (OFPXMC_EXPERIMENTER):
                if (exp == NULL || exp->field == NULL || exp->field->match_std == NULL) {
                    VLOG_WARN(LOG_MODULE,"Received match is experimental, but no callback was given.");
                    ofl_error(OFPET_BAD_MATCH, OFPBMC_BAD_TYPE);
                }
                exp->field->match_std(flow_mod_match, flow_entry_match, &field_len, &flow_mod_val, &flow_entry_val, &flow_mod_mask, &flow_entry_mask);
                break;
            default:
                break;
        }
        
        switch (field_len) {
            case 1:
                if (has_mask) {
                    if (!strict_mask8(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask)){
                        return false;
                    }
                }
                else {
                    if (!match_8(flow_mod_val, flow_entry_val)){
                        return false;
                    }
                }
                break;
            case 2:
                if (has_mask) {
                    if (!strict_mask16(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask)){
                        return false;
                    }
                }
                else {
                    if (!match_16(flow_mod_val, flow_entry_val)){
                        return false;
                    }
                }
                break;
            case 3:
                if (has_mask) {
                    if (!strict_mask24(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask))
                        return false;
                }
                else {                    
                    if (!match_24(flow_mod_val, flow_entry_val)){
                        return false;
                    }
                }
                break;
            case 4:
                if (has_mask) {
                    /* Quick and dirty fix for IP addresses matching 
                       TODO: Matching needs a huge refactoring  */
                    if (oxm_field == OFPXMT_OFB_IPV4_SRC ||
                        oxm_field == OFPXMT_OFB_IPV4_DST ||
                        oxm_field == OFPXMT_OFB_ARP_SPA ||
                        oxm_field == OFPXMT_OFB_ARP_TPA) {
                        if (!strict_mask_ip(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask)){
                            return false;
                        }
                    }
                    if (!strict_mask32(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask)){
                        return false;
                    }
                }
                else {

                    if (!match_32(flow_mod_val, flow_entry_val)){
                        return false;
                    }
                }
                break;
            case 6:
                if (has_mask) {
                    if (!strict_mask48(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask)){
                        return false;
                    }
                }
                else {
                    if (!match_48(flow_mod_val, flow_entry_val)){
                        return false;
                    }
                }
                break;
            case 8:
                if (has_mask) {
                    if (!strict_mask64(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask)){
                        return false;
                    }
                }
                else {
                    if (!match_64(flow_mod_val, flow_entry_val)){
                        return false;
                    }
                }
                break;
            case 16:
                if (has_mask) {
                    if (!strict_mask128(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask)){
                        return false;
                    }
                }
                else {
                    if (!match_128(flow_mod_val, flow_entry_val)){
                        return false;
                    }
                }
                break;
            default:
                /* Should never happen */
                break;
        } /* switch (field_len) */

    } /* HMAP_FOR_EACH */

    /* If we get here, all match fields in flow_mod were equal to the ones in flow entry */
    /* There can't be more fields in the flow entry as the lengths are the same */
    return true;
}
Exemplo n.º 3
0
ofl_err
ofl_actions_unpack(struct ofp_action_header *src, size_t *len, struct ofl_action_header **dst, struct ofl_exp *exp) {

    if (*len < sizeof(struct ofp_action_header)) {
        OFL_LOG_WARN(LOG_MODULE, "Received action is too short (%zu).", *len);
        return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
    }

    if (*len < ntohs(src->len)) {
        OFL_LOG_WARN(LOG_MODULE, "Received action has invalid length (set to %u, but only %zu received).", ntohs(src->len), *len);
        return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
    }

    if ((ntohs(src->len) % 8) != 0) {
        OFL_LOG_WARN(LOG_MODULE, "Received action length is not a multiple of 64 bits (%u).", ntohs(src->len));
        return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
    }

    switch (ntohs(src->type)) {
        case OFPAT_OUTPUT: {
            struct ofp_action_output *sa;
            struct ofl_action_output *da;

            if (*len < sizeof(struct ofp_action_output)) {
                OFL_LOG_WARN(LOG_MODULE, "Received OUTPUT action has invalid length (%zu).", *len);
                return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
            }

            sa = (struct ofp_action_output *)src;

            if (ntohl(sa->port) == 0 ||
                (ntohl(sa->port) > OFPP_MAX && ntohl(sa->port) < OFPP_IN_PORT) ||
                ntohl(sa->port) == OFPP_ANY) {
                if (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) {
                    char *ps = ofl_port_to_string(ntohl(sa->port));
                    OFL_LOG_WARN(LOG_MODULE, "Received OUTPUT action has invalid port (%s).", ps);
                    free(ps);
                }
                return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT);
            }

            da = (struct ofl_action_output *)malloc(sizeof(struct ofl_action_output));
            da->port = ntohl(sa->port);
            da->max_len = ntohs(sa->max_len);

            *len -= sizeof(struct ofp_action_output);
            *dst = (struct ofl_action_header *)da;
            break;
        }
        case OFPAT_COPY_TTL_OUT: {
            //ofp_action_header length was already checked
            *len -= sizeof(struct ofp_action_header);
            *dst = (struct ofl_action_header *)malloc(sizeof(struct ofl_action_header));
            break;
        }

        case OFPAT_COPY_TTL_IN: {
            //ofp_action_header length was already checked
            *len -= sizeof(struct ofp_action_header);
            *dst = (struct ofl_action_header *)malloc(sizeof(struct ofl_action_header));
            break;
        }

        case OFPAT_SET_MPLS_TTL: {
            struct ofp_action_mpls_ttl *sa;
            struct ofl_action_mpls_ttl *da;

            if (*len < sizeof(struct ofp_action_mpls_ttl)) {
                OFL_LOG_WARN(LOG_MODULE, "Received SET_MPLS_TTL action has invalid length (%zu).", *len);
                return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
            }

            sa = (struct ofp_action_mpls_ttl *)src;

            da = (struct ofl_action_mpls_ttl *)malloc(sizeof(struct ofl_action_mpls_ttl));
            da->mpls_ttl = sa->mpls_ttl;

            *len -= sizeof(struct ofp_action_mpls_ttl);
            *dst = (struct ofl_action_header *)da;
            break;
        }

        case OFPAT_DEC_MPLS_TTL: {
            //ofp_action_header length was already checked
            *len -= sizeof(struct ofp_action_mpls_ttl);
            *dst = (struct ofl_action_header *)malloc(sizeof(struct ofl_action_header));
            break;
        }

        case OFPAT_PUSH_VLAN: 
        case OFPAT_PUSH_PBB:
        case OFPAT_PUSH_MPLS: {
            struct ofp_action_push *sa;
            struct ofl_action_push *da;

            if (*len < sizeof(struct ofp_action_push)) {
                OFL_LOG_WARN(LOG_MODULE, "Received PUSH_VLAN/MPLS/PBB action has invalid length (%zu).", *len);
                return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
            }

            sa = (struct ofp_action_push *)src;

            if (((ntohs(src->type) == OFPAT_PUSH_VLAN) &&
                    (ntohs(sa->ethertype) != ETH_TYPE_VLAN &&
                     ntohs(sa->ethertype) != ETH_TYPE_VLAN_PBB)) ||
                ((ntohs(src->type) == OFPAT_PUSH_MPLS) &&
                    (ntohs(sa->ethertype) != ETH_TYPE_MPLS &&
                     ntohs(sa->ethertype) != ETH_TYPE_MPLS_MCAST)) ||
                ((ntohs(src->type) == OFPAT_PUSH_PBB) &&
                    (ntohs(sa->ethertype) != ETH_TYPE_PBB))) {
                OFL_LOG_WARN(LOG_MODULE, "Received PUSH_VLAN/MPLS/PBB has invalid eth type. (%u)", ntohs(sa->ethertype));
                return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT);
            }

            da = (struct ofl_action_push *)malloc(sizeof(struct ofl_action_push));
            da->ethertype = ntohs(sa->ethertype);

            *len -= sizeof(struct ofp_action_push);
            *dst = (struct ofl_action_header *)da;
            break;
        }

        case OFPAT_POP_VLAN: 
        case OFPAT_POP_PBB: {
            //ofp_action_header length was already checked
            *len -= sizeof(struct ofp_action_header);
            *dst = (struct ofl_action_header *)malloc(sizeof(struct ofl_action_header));
            break;
        }
                
        case OFPAT_POP_MPLS: {
            struct ofp_action_pop_mpls *sa;
            struct ofl_action_pop_mpls *da;

            if (*len < sizeof(struct ofp_action_pop_mpls)) {
                OFL_LOG_WARN(LOG_MODULE, "Received POP_MPLS action has invalid length (%zu).", *len);
                return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
            }

            sa = (struct ofp_action_pop_mpls *)src;

            da = (struct ofl_action_pop_mpls *)malloc(sizeof(struct ofl_action_pop_mpls));
            da->ethertype = ntohs(sa->ethertype);

            *len -= sizeof(struct ofp_action_pop_mpls);
            *dst = (struct ofl_action_header *)da;
            break;
        }

        case OFPAT_SET_QUEUE: {
            struct ofp_action_set_queue *sa;
            struct ofl_action_set_queue *da;

            if (*len < sizeof(struct ofp_action_set_queue)) {
                OFL_LOG_WARN(LOG_MODULE, "Received SET_QUEUE action has invalid length (%zu).", *len);
                return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
            }

            sa = (struct ofp_action_set_queue *)src;

            da = (struct ofl_action_set_queue *)malloc(sizeof(struct ofl_action_set_queue));
            da->queue_id = ntohl(sa->queue_id);

            *len -= sizeof(struct ofp_action_set_queue);
            *dst = (struct ofl_action_header *)da;
            break;
        }

        case OFPAT_GROUP: {
            struct ofp_action_group *sa;
            struct ofl_action_group *da;

            if (*len < sizeof(struct ofp_action_group)) {
                OFL_LOG_WARN(LOG_MODULE, "Received GROUP action has invalid length (%zu).", *len);
                return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
            }

            sa = (struct ofp_action_group *)src;

            if (ntohl(sa->group_id) > OFPG_MAX) {
                if (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) {
                    char *gs = ofl_group_to_string(ntohl(sa->group_id));
                    OFL_LOG_WARN(LOG_MODULE, "Received GROUP action has invalid group id (%s).", gs);
                    free(gs);
                }
                return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_OUT_GROUP);
            }

            da = (struct ofl_action_group *)malloc(sizeof(struct ofl_action_group));
            da->group_id = ntohl(sa->group_id);

            *len -= sizeof(struct ofp_action_group);
            *dst = (struct ofl_action_header *)da;
            break;
        }

        case OFPAT_SET_NW_TTL: {
            struct ofp_action_nw_ttl *sa;
            struct ofl_action_set_nw_ttl *da;

            if (*len < sizeof(struct ofp_action_nw_ttl)) {
                OFL_LOG_WARN(LOG_MODULE, "Received SET_NW_TTL action has invalid length (%zu).", *len);
                return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
            }

            sa = (struct ofp_action_nw_ttl *)src;

            da = (struct ofl_action_set_nw_ttl *)malloc(sizeof(struct ofl_action_set_nw_ttl));
            da->nw_ttl = sa->nw_ttl;

            *len -= sizeof(struct ofp_action_nw_ttl);
            *dst = (struct ofl_action_header *)da;
            break;
        }

        case OFPAT_DEC_NW_TTL: {
            //ofp_action_header length was already checked
            *len -= sizeof(struct ofp_action_header);
            *dst = (struct ofl_action_header *)malloc(sizeof(struct ofl_action_header));
            break;
        }

        case OFPAT_SET_FIELD: {
            struct ofp_action_set_field *sa;
            struct ofl_action_set_field *da;
            uint8_t *value;
            
            sa = (struct ofp_action_set_field*) src;
            da = (struct ofl_action_set_field *)malloc(sizeof(struct ofl_action_set_field));
            da->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv));
            
            memcpy(&da->field->header,sa->field,4);
            da->field->header = ntohl(da->field->header);
            value = (uint8_t *) src + sizeof (struct ofp_action_set_field);
            da->field->value = malloc(OXM_LENGTH(da->field->header));
            /*TODO: need to check if other fields are valid */
            if(da->field->header == OXM_OF_IN_PORT || da->field->header == OXM_OF_IN_PHY_PORT
                                    || da->field->header == OXM_OF_METADATA
                                    || da->field->header == OXM_OF_IPV6_EXTHDR){

                return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_SET_TYPE);
            }
            switch(OXM_LENGTH(da->field->header)){
                case 1:
                case 6:
                case 16:
                    memcpy(da->field->value , value, OXM_LENGTH(da->field->header));
                    break;
                
                case 2:{
                   uint16_t v = ntohs(*((uint16_t*) value));
                   memcpy(da->field->value , &v, OXM_LENGTH(da->field->header));
                    break;
                }
                case 4:{
                    uint32_t v; 
		    uint8_t field = OXM_FIELD(da->field->header);					
		    if( field != 11 && field != 12 && field != 22 && field != 23)  
		        v = htonl(*((uint32_t*) value));
		    else v = *((uint32_t*) value);
                    memcpy(da->field->value , &v, OXM_LENGTH(da->field->header));
                    break;
                }
                case 8:{
                    uint64_t v = hton64(*((uint64_t*) value));
                    memcpy(da->field->value , &v, OXM_LENGTH(da->field->header));
                    break;
                }                
            }
     	    *len -= ROUND_UP(ntohs(src->len),8);
     	    *dst = (struct ofl_action_header *)da;
            break;
	}

        case OFPAT_EXPERIMENTER: {
            ofl_err error;

            if (*len < sizeof(struct ofp_action_experimenter_header)) {
                OFL_LOG_WARN(LOG_MODULE, "Received EXPERIMENTER action has invalid length (%zu).", *len);
                return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN);
            }

            if (exp == NULL || exp->act == NULL || exp->act->unpack == NULL) {
                OFL_LOG_WARN(LOG_MODULE, "Received EXPERIMENTER action, but no callback is given.");
                return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_EXPERIMENTER);
            }
            error = exp->act->unpack(src, len, dst);
            if (error) {
                return error;
            }
            break;
        }

        default: {
            OFL_LOG_WARN(LOG_MODULE, "Received unknown action type (%u).", ntohs(src->type));
            return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_TYPE);
        }
    }
    (*dst)->type = (enum ofp_action_type)ntohs(src->type);

    return 0;
}
Exemplo n.º 4
0
void
ofl_structs_oxm_tlv_print(FILE *stream, struct ofl_match_tlv *f)
{
	uint8_t field = OXM_FIELD(f->header);

	switch (field) {

		case OFPXMT_OFB_IN_PORT:
			fprintf(stream, "in_port=\"%d\"", *((uint32_t*) f->value));
			break;
		case OFPXMT_OFB_IN_PHY_PORT:
			fprintf(stream, "in_phy_port=\"%d\"", *((uint32_t*) f->value));
			break;
		case OFPXMT_OFB_VLAN_VID: {
			uint16_t v = *((uint16_t *) f->value);
			if (v == OFPVID_NONE)
				fprintf(stream, "vlan_vid= none");
			else if (v == OFPVID_PRESENT && OXM_HASMASK(f->header))
				fprintf(stream, "vlan_vid= any");
			else
				fprintf(stream, "vlan_vid=\"%d\"",v & VLAN_VID_MASK);
			break;
		}
		case OFPXMT_OFB_VLAN_PCP:
			fprintf(stream, "vlan_pcp=\"%d\"", *f->value & 0x7);
			break;
		case OFPXMT_OFB_ETH_TYPE:
			fprintf(stream, "eth_type=\"0x%x\"",  *((uint16_t *) f->value));
			break;
		case OFPXMT_OFB_TCP_SRC:
			fprintf(stream, "tcp_src=\"%d\"", *((uint16_t*) f->value));
			break;
		case OFPXMT_OFB_TCP_DST:
			fprintf(stream, "tcp_dst=\"%d\"", *((uint16_t*) f->value));
			break;
		case OFPXMT_OFB_UDP_SRC:
			fprintf(stream, "udp_src=\"%d\"", *((uint16_t*) f->value));
			break;
		case OFPXMT_OFB_UDP_DST:
			fprintf(stream, "udp_dst=\"%d\"", *((uint16_t*) f->value));
			break;
		case OFPXMT_OFB_SCTP_SRC:
			fprintf(stream, "sctp_src=\"%d\"", *((uint16_t*) f->value));
			break;
		case OFPXMT_OFB_SCTP_DST:
			fprintf(stream, "sctp_dst=\"%d\"", *((uint16_t*) f->value));
			break;
		case OFPXMT_OFB_ETH_SRC:
			fprintf(stream, "eth_src=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value));
			if (OXM_HASMASK(f->header)) {
				fprintf(stream, ", eth_src_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6));
			}
			break;
		case OFPXMT_OFB_ETH_DST:
			fprintf(stream, "eth_dst=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value));
			if (OXM_HASMASK(f->header)) {
				fprintf(stream, ", eth_dst_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6));
			}
			break;
		case OFPXMT_OFB_IPV4_DST:
			fprintf(stream, "ipv4_dst=\""IP_FMT"\"", IP_ARGS(f->value));
			if (OXM_HASMASK(f->header)) {
				fprintf(stream, ", ipv4_dst_mask=\""IP_FMT"\"", IP_ARGS(f->value + 4));
			}
			break;
		case OFPXMT_OFB_IPV4_SRC:
			fprintf(stream, "ipv4_src=\""IP_FMT"\"", IP_ARGS(f->value));
			if (OXM_HASMASK(f->header)) {
				fprintf(stream, ", ipv4_src_mask=\""IP_FMT"\"", IP_ARGS(f->value + 4));
			}
			break;
		case OFPXMT_OFB_IP_PROTO:
			fprintf(stream, "ip_proto=\"%d\"", *f->value);
			break;
		case OFPXMT_OFB_IP_DSCP:
			fprintf(stream, "ip_dscp=\"%d\"", *f->value & 0x3f);
			break;
		case OFPXMT_OFB_IP_ECN:
			fprintf(stream, "ip_ecn=\"%d\"", *f->value & 0x3);
			break;
		case OFPXMT_OFB_ICMPV4_TYPE:
			fprintf(stream, "icmpv4_type= \"%d\"", *f->value);
			break;
		case OFPXMT_OFB_ICMPV4_CODE:
			fprintf(stream, "icmpv4_code=\"%d\"", *f->value);
			break;
		case OFPXMT_OFB_ARP_SHA:
			fprintf(stream, "arp_sha=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value));
			if (OXM_HASMASK(f->header)) {
				fprintf(stream, ", arp_sha_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6));
			}
			break;
		case OFPXMT_OFB_ARP_THA:
			fprintf(stream, "arp_tha=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value));
			if (OXM_HASMASK(f->header)) {
				fprintf(stream, ", arp_tha_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6));
			}
			break;
		case OFPXMT_OFB_ARP_SPA:
			fprintf(stream, "arp_spa=\""IP_FMT"\"", IP_ARGS(f->value));
			if (OXM_HASMASK(f->header)) {
				fprintf(stream, ", arp_sha_mask=\""IP_FMT"\"", IP_ARGS(f->value + 4));
			}
			break;
		case OFPXMT_OFB_ARP_TPA:
			fprintf(stream, "arp_tpa=\""IP_FMT"\"", IP_ARGS(f->value));
			if (OXM_HASMASK(f->header)) {
				fprintf(stream, ", arp_tpa_mask=\""IP_FMT"\"", IP_ARGS(f->value + 4));
			}
			break;
		case OFPXMT_OFB_ARP_OP:
			fprintf(stream, "arp_op=\"0x%x\"", *((uint16_t*) f->value));
			break;
		case OFPXMT_OFB_IPV6_SRC: {
			char addr_str[INET6_ADDRSTRLEN];
			inet_ntop(AF_INET6, f->value, addr_str, INET6_ADDRSTRLEN);
			fprintf(stream, "nw_src_ipv6=\"%s\"", addr_str);
			if (OXM_HASMASK(f->header)) {
				inet_ntop(AF_INET6, f->value + 16, addr_str, INET6_ADDRSTRLEN);
				fprintf(stream, ", nw_src_ipv6_mask=\"%s\"", addr_str);
			}
			break;
		}
		case OFPXMT_OFB_IPV6_DST: {
			char addr_str[INET6_ADDRSTRLEN];
			inet_ntop(AF_INET6, f->value, addr_str, INET6_ADDRSTRLEN);
			fprintf(stream, "nw_dst_ipv6=\"%s\"", addr_str);
			if (OXM_HASMASK(f->header)) {
				inet_ntop(AF_INET6, f->value + 16, addr_str, INET6_ADDRSTRLEN);
				fprintf(stream, ", nw_dst_ipv6_mask=\"%s\"", addr_str);
			}
			break;
		}
		case OFPXMT_OFB_IPV6_ND_TARGET: {
			char addr_str[INET6_ADDRSTRLEN];
			inet_ntop(AF_INET6, f->value, addr_str, INET6_ADDRSTRLEN);
			fprintf(stream, "ipv6_nd_target=\"%s\"", addr_str);
			break;
		}
		case OFPXMT_OFB_IPV6_ND_SLL:
			fprintf(stream, "ipv6_nd_sll=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value));
			break;
		case OFPXMT_OFB_IPV6_ND_TLL:
			fprintf(stream, "ipv6_nd_tll=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value));
			break;
		case OFPXMT_OFB_IPV6_FLABEL:
			fprintf(stream, "ipv6_flow_label=\"%d\"", *((uint32_t*) f->value) & 0x000fffff);
			if (OXM_HASMASK(f->header)) {
				fprintf(stream, ", ipv6_flow_label_mask=\"%d\"", *((uint32_t*) (f->value+4)));
			}
			break;
		case OFPXMT_OFB_ICMPV6_TYPE:
			fprintf(stream, "icmpv6_type=\"%d\"", *f->value);
			break;
		case OFPXMT_OFB_ICMPV6_CODE:
			fprintf(stream, "icmpv6_code=\"%d\"", *f->value);
			break;
		case OFPXMT_OFB_MPLS_LABEL:
			fprintf(stream, "mpls_label=\"%d\"",((uint32_t) *f->value) & 0x000fffff);
			break;
		case OFPXMT_OFB_MPLS_TC:
			fprintf(stream, "mpls_tc=\"%d\"", *f->value & 0x3);
			break;
		case OFPXMT_OFB_MPLS_BOS:
			fprintf(stream, "mpls_bos=\"%d\"", *f->value & 0xfe);
			break;
		case OFPXMT_OFB_METADATA:
			fprintf(stream, "metadata=\"0x%llx\"", *((uint64_t*) f->value));
			if (OXM_HASMASK(f->header)) {
				fprintf(stream, ", metadata_mask=\"0x%llx\"", *((uint64_t*)(f->value+8)));
			}
			break;
		case OFPXMT_OFB_PBB_ISID   :
			fprintf(stream, "pbb_isid=\"%d\"", *((uint32_t*) f->value));
			if (OXM_HASMASK(f->header)) {
				fprintf(stream, ", pbb_isid_mask=\"%d\"", *((uint32_t*)(f->value+4)));
			}
			break;
		case OFPXMT_OFB_TUNNEL_ID:
			fprintf(stream, "tunnel_id=\"%lld\"", *((uint64_t*) f->value));
			if (OXM_HASMASK(f->header)) {
				fprintf(stream, ", tunnel_id_mask=\"%lld\"", *((uint64_t*)(f->value+8)));
			}
			break;
		case OFPXMT_OFB_IPV6_EXTHDR:
			fprintf(stream, "ext_hdr=\"");
			ofl_ipv6_ext_hdr_print(stream, *((uint16_t*) f->value));
			fprintf(stream, "\"");
			if (OXM_HASMASK(f->header)) {
				fprintf(stream, ", ext_hdr_mask=\"0x%x\"", *((uint16_t*)(f->value+4)));
			}
			break;
		default:
			fprintf(stream, "unknown type %d", field);
	}
}
Exemplo n.º 5
0
size_t
ofl_actions_pack(struct ofl_action_header *src, struct ofp_action_header *dst, uint8_t* data,  struct ofl_exp *exp) {

    dst->type = htons(src->type);
    memset(dst->pad, 0x00, 4);

    switch (src->type) {
        case OFPAT_OUTPUT: {
            struct ofl_action_output *sa = (struct ofl_action_output *)src;
            struct ofp_action_output *da = (struct ofp_action_output *)dst;

            da->len =     htons(sizeof(struct ofp_action_output));
            da->port =    htonl(sa->port);
            da->max_len = htons(sa->max_len);
            memset(da->pad, 0x00, 6);
            return sizeof(struct ofp_action_output);
        }
      
        case OFPAT_COPY_TTL_OUT:
        case OFPAT_COPY_TTL_IN: {
            dst->len = htons(sizeof(struct ofp_action_header));
            return sizeof(struct ofp_action_header);
        }
      
        case OFPAT_SET_MPLS_TTL: {
            struct ofl_action_mpls_ttl *sa = (struct ofl_action_mpls_ttl *)src;
            struct ofp_action_mpls_ttl *da = (struct ofp_action_mpls_ttl *)dst;

            da->len =      htons(sizeof(struct ofp_action_mpls_ttl));
            da->mpls_ttl = sa->mpls_ttl;
            memset(da->pad, 0x00, 3);
            return sizeof(struct ofp_action_mpls_ttl);
        }
        case OFPAT_DEC_MPLS_TTL: {
            dst->len = htons(sizeof(struct ofp_action_header));
            return sizeof(struct ofp_action_header);
        }
        case OFPAT_PUSH_VLAN:
        case OFPAT_PUSH_MPLS: 
        case OFPAT_PUSH_PBB:{
            struct ofl_action_push *sa = (struct ofl_action_push *)src;
            struct ofp_action_push *da = (struct ofp_action_push *)dst;

            da->len =       htons(sizeof(struct ofp_action_push));
            da->ethertype = htons(sa->ethertype);
            memset(da->pad, 0x00, 2);
            return sizeof(struct ofp_action_push);
        }
        case OFPAT_POP_VLAN: 
        case OFPAT_POP_PBB: {
            struct ofp_action_header *da = (struct ofp_action_header *)dst;

            da->len = htons(sizeof(struct ofp_action_header));
            return sizeof (struct ofp_action_header);
        }
        case OFPAT_POP_MPLS: {
            struct ofl_action_pop_mpls *sa = (struct ofl_action_pop_mpls *)src;
            struct ofp_action_pop_mpls *da = (struct ofp_action_pop_mpls *)dst;

            da->len =       htons(sizeof(struct ofp_action_pop_mpls));
            da->ethertype = htons(sa->ethertype);
            memset(da->pad, 0x00, 2);
            return sizeof(struct ofp_action_pop_mpls);
        }
        case OFPAT_SET_QUEUE: {
            struct ofl_action_set_queue *sa = (struct ofl_action_set_queue *)src;
            struct ofp_action_set_queue *da = (struct ofp_action_set_queue *)dst;

            da->len =      htons(sizeof(struct ofp_action_set_queue));
            da->queue_id = htonl(sa->queue_id);
            return sizeof(struct ofp_action_set_queue);
        }
        case OFPAT_GROUP: {
            struct ofl_action_group *sa = (struct ofl_action_group *)src;
            struct ofp_action_group *da = (struct ofp_action_group *)dst;

            da->len =      htons(sizeof(struct ofp_action_group));
            da->group_id = htonl(sa->group_id);
            return sizeof(struct ofp_action_group);
        }
        case OFPAT_SET_NW_TTL: {
            struct ofl_action_set_nw_ttl *sa = (struct ofl_action_set_nw_ttl *)src;
            struct ofp_action_nw_ttl *da = (struct ofp_action_nw_ttl *)dst;

            da->len =    htons(sizeof(struct ofp_action_nw_ttl));
            da->nw_ttl = sa->nw_ttl;
            memset(da->pad, 0x00, 3);
            return sizeof(struct ofp_action_nw_ttl);
        }
        case OFPAT_DEC_NW_TTL: {
            dst->len = htons(sizeof(struct ofp_action_header));
            return sizeof(struct ofp_action_header);
        }
        case OFPAT_SET_FIELD: {
            struct ofl_action_set_field *sa = (struct ofl_action_set_field *) src;
            struct ofp_action_set_field *da = (struct ofp_action_set_field *) dst;
            uint32_t header;
            uint8_t padding_size;
                        
            da->len = htons(sizeof(struct ofp_action_set_field) + ROUND_UP(OXM_LENGTH(sa->field->header),8));
            /*Put OXM header in the field*/
            header = htonl(sa->field->header);
            memcpy(&da->field, &header, 4);
            switch (OXM_LENGTH(sa->field->header)){
                case 1:
                case 6:
                case 16:
                    memcpy(data + (sizeof(struct ofp_action_set_field)), sa->field->value, OXM_LENGTH(sa->field->header));
                    break;
                
                case 2:{
                   uint16_t value = htons(*((uint16_t*) sa->field->value));
                   memcpy(data + (sizeof(struct ofp_action_set_field)),&value,OXM_LENGTH(sa->field->header));
                    break;
                }
                case 4:{
                    uint32_t value; 
					uint8_t field = OXM_FIELD(sa->field->header);					
					if( field != 11 && field != 12 && field != 22 && field != 23) 
						value = htonl(*((uint32_t*) sa->field->value));
					else  
						value = *((uint32_t*) sa->field->value);                   
					memcpy(data + (sizeof(struct ofp_action_set_field)), &value, OXM_LENGTH(sa->field->header));
                    break;
                }
                case 8:{
                    uint64_t value = htons(*((uint64_t*) sa->field->value));
                    memcpy(data + (sizeof(struct ofp_action_set_field)),&value,OXM_LENGTH(sa->field->header));
                    break;
                }
            }
            /*padding*/
            padding_size = ROUND_UP(OXM_LENGTH(sa->field->header),8) - OXM_LENGTH(sa->field->header);
            memset(data + (sizeof(struct ofp_action_set_field) + OXM_LENGTH(sa->field->header)), 0, padding_size);            
            return ntohs((da->len));
        
        }
        case OFPAT_EXPERIMENTER: {
            if (exp == NULL || exp->act == NULL || exp->act->pack == NULL) {
                OFL_LOG_WARN(LOG_MODULE, "Trying to pack experimenter, but no callback was given.");
                return 0;
            }
            return exp->act->pack(src, dst);
        }
        default:
            return 0;
    };
}
void 
print_oxm_tlv(FILE *stream, struct ofl_match_tlv *f, size_t *size){
                uint8_t field = OXM_FIELD(f->header);

                if (field == OFPXMT_OFB_IN_PORT){
                    fprintf(stream, "in_port=\"%d\"",*((uint32_t*) f->value));
                    *size -= 8;   
                    if (*size > 4)                                  
                        fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_IN_PHY_PORT){
                            fprintf(stream, "in_phy_port=\"%d\"",*((uint32_t*) f->value));
                            *size -= 8;   
                            if (*size > 4)                                  
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_VLAN_VID){
                			uint16_t *v = (uint16_t *) f->value;
                			if (*v == OFPVID_NONE)
                                fprintf(stream, "vlan_vid= none");
                            else if (*v == OFPVID_PRESENT && OXM_HASMASK(f->header))
                                fprintf(stream, "vlan_vid= any");
                            else
                            	fprintf(stream, "vlan_vid=\"%d\"",*v & VLAN_VID_MASK);
                            *size -= 6;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_VLAN_PCP){
                            fprintf(stream, "vlan_pcp=\"%d\"", *f->value & 0x7);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                } 
                else if (field == OFPXMT_OFB_ETH_TYPE){
                            uint16_t *v = (uint16_t *) f->value;
                            fprintf(stream, "eth_type=");
                            fprintf(stream,"\"0x%x\"",  *v);
                            *size -= 6; 
                            if (*size > 4)                                
                                fprintf(stream, ", ");                            
                }
                else if (field == OFPXMT_OFB_TCP_SRC){
                            fprintf(stream, "tcp_src=\"%d\"",*((uint16_t*) f->value));
                            *size -= 6;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_TCP_DST){
                            fprintf(stream, "tcp_dst=\"%d\"",*((uint16_t*) f->value));
                            *size -= 6;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_UDP_SRC){
                            fprintf(stream, "udp_src=\"%d\"",*((uint16_t*) f->value));
                            *size -= 6;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_UDP_DST){
                            fprintf(stream, "udp_dst=\"%d\"",*((uint16_t*) f->value));
                            *size -= 6;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_SCTP_SRC){
                            fprintf(stream, "sctp_src=\"%d\"",*((uint16_t*) f->value));
                            *size -= 6;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_SCTP_DST){
                            fprintf(stream, "sctp_dst=\"%d\"",*((uint16_t*) f->value));
                            *size -= 6;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }                  
                else if (field == OFPXMT_OFB_ETH_SRC){
                            fprintf(stream, "eth_src=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value));
                            *size -= 10;                                
                            if (OXM_HASMASK(f->header)){
                                *size -= 6;
                                fprintf(stream, ", eth_src_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6));
                            }
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_ETH_DST){
                            fprintf(stream, "eth_dst=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value));
                            *size -= 10;                                
                            if (OXM_HASMASK(f->header)){
                                *size -= 6;
                                fprintf(stream, ", eth_dst_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6));
                            }
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_IPV4_DST){
                            fprintf(stream, "ipv4_dst=\""IP_FMT"\"",IP_ARGS(f->value));
                            *size -= 8;
                            if (OXM_HASMASK(f->header)){
                                *size -= 4;
                                fprintf(stream, ", ipv4_dst_mask=\""IP_FMT"\"",IP_ARGS(f->value + 4));
                            }                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }                                                 
                else if (field == OFPXMT_OFB_IPV4_SRC){
                            fprintf(stream, "ipv4_src=\""IP_FMT"\"",IP_ARGS(f->value));
                            *size -= 8;                                
                            if (OXM_HASMASK(f->header)){
                                *size -= 4;
                                fprintf(stream, ", ipv4_src_mask=\""IP_FMT"\"",IP_ARGS(f->value + 4));
                            }
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_IP_PROTO){
                            fprintf(stream, "ip_proto=\"%d\"", *f->value);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                } 
                else if (field == OFPXMT_OFB_IP_DSCP){
                            fprintf(stream, "ip_dscp=\"%d\"", *f->value & 0x3f);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                } 
                else if (field == OFPXMT_OFB_IP_ECN){
                            fprintf(stream, "ip_ecn=\"%d\"", *f->value & 0x3);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                } 
                else if (field == OFPXMT_OFB_ICMPV4_TYPE){
                            fprintf(stream, "icmpv4_type= \"%d\"", *f->value);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                } 
                else if (field == OFPXMT_OFB_ICMPV4_CODE){
                            fprintf(stream, "icmpv4_code=\"%d\"", *f->value);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }   
                else if (field == OFPXMT_OFB_ARP_SHA){
                            fprintf(stream, "arp_sha=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value));
                            *size -= 10;                                
                            if (OXM_HASMASK(f->header)){
                                *size -= 6;
                                fprintf(stream, ", arp_sha_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6));
                            }
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_ARP_THA){
                            fprintf(stream, "arp_tha=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value));
                            *size -= 10;

                            if (OXM_HASMASK(f->header)){
                                *size -= 6;
                                fprintf(stream, ", arp_tha_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6));
                            }
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }                      
                else if (field == OFPXMT_OFB_ARP_SPA){
                            fprintf(stream, "arp_spa=\""IP_FMT"\"",IP_ARGS(f->value));
                            *size -= 8;                                
                            if (OXM_HASMASK(f->header)){
                                *size -= 4;
                                fprintf(stream, ", arp_sha_mask=\""IP_FMT"\"",IP_ARGS(f->value + 4));
                            }           
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                } 
                else if (field == OFPXMT_OFB_ARP_TPA){
                            fprintf(stream, "arp_tpa=\""IP_FMT"\"",IP_ARGS(f->value));
                            *size -= 8;                                
                            if (OXM_HASMASK(f->header)){
                                *size -= 4;
                                fprintf(stream, ", arp_tpa_mask=\""IP_FMT"\"",IP_ARGS(f->value + 4));
                            }
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                } 
                else if (field == OFPXMT_OFB_ARP_OP){
                            uint16_t *v = (uint16_t *) f->value;
                            fprintf(stream, "arp_op=\"0x");
                            fprintf(stream,"%x\"",  *v);
                            *size -= 6;                            
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_IPV6_SRC){
                        char addr_str[INET6_ADDRSTRLEN]; 
                        inet_ntop(AF_INET6, f->value, addr_str, INET6_ADDRSTRLEN);
                        *size -= 20;
                        fprintf(stream, "nw_src_ipv6=\"%s\"", addr_str);
                        if (OXM_HASMASK(f->header)){
                                *size -= 16;
                                inet_ntop(AF_INET6, f->value + 16, addr_str, INET6_ADDRSTRLEN);
                                fprintf(stream, ", nw_src_ipv6_mask=\"%s\"", addr_str);
                        }
                        if (*size > 4)                                
                                fprintf(stream, ", ");        
                }
                else if (field == OFPXMT_OFB_IPV6_DST){
                        char addr_str[INET6_ADDRSTRLEN]; 
                        inet_ntop(AF_INET6, f->value, addr_str, INET6_ADDRSTRLEN);
                        *size -= 20;
                        fprintf(stream, "nw_dst_ipv6=\"%s\"", addr_str);
                        if (OXM_HASMASK(f->header)){
                                *size -= 16;
                                inet_ntop(AF_INET6, f->value + 16, addr_str, INET6_ADDRSTRLEN);
                                fprintf(stream, ", nw_dst_ipv6_mask=\"%s\"", addr_str);
                        }
                        if (*size > 4)                                
                                fprintf(stream, ", ");        
                }
                else if (field == OFPXMT_OFB_IPV6_ND_TARGET){
                        char addr_str[INET6_ADDRSTRLEN]; 
                        inet_ntop(AF_INET6, f->value, addr_str, INET6_ADDRSTRLEN);
                        *size -= 20;
                        fprintf(stream, "ipv6_nd_target=\"%s\"", addr_str);
                        if (*size > 4)                                
                                fprintf(stream, ", ");        
                }  
                 else if (field == OFPXMT_OFB_IPV6_ND_SLL){
                            fprintf(stream, "ipv6_nd_sll=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value));
                            *size -= 10;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_IPV6_ND_TLL){
                            fprintf(stream, "ipv6_nd_tll=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value));
                            *size -= 10;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_IPV6_FLABEL){
                            uint32_t mask = 0x000fffff;
                            *size -= 8;
                            fprintf(stream, "ipv6_flow_label=\"%d\"",*((uint32_t*) f->value) & mask );                              
                            if (OXM_HASMASK(f->header)){
                                uint8_t *flabel_mask = (uint8_t*) f->value + 4;
                                *size -= 4;
                                fprintf(stream, ", ipv6_flow_label_mask=\"%d\"",*((uint32_t*)flabel_mask)); 
                            }                         
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_ICMPV6_TYPE){
                            fprintf(stream, "icmpv6_type=\"%d\"", *f->value);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                } 
                else if (field == OFPXMT_OFB_ICMPV6_CODE){
                            fprintf(stream, "icmpv6_code=\"%d\"", *f->value);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_MPLS_LABEL){
                            uint32_t mask = 0xfffff;
                            fprintf(stream, "mpls_label=\"%d\"",((uint32_t) *f->value) & mask );
                            *size -= 8;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_MPLS_TC){
                            fprintf(stream, "mpls_tc=\"%d\"", *f->value & 0x3);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_MPLS_BOS){
                            fprintf(stream, "mpls_bos=\"%d\"", *f->value & 0xfe);
                            *size -= 5;                                
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }                  
                else if (field == OFPXMT_OFB_METADATA){
                            fprintf(stream, "metadata=\"%lld\"", *((uint64_t*) f->value));
                            *size -= 12;
                            if (OXM_HASMASK(f->header)){
                                fprintf(stream, ", metadata_mask=\"%lld\"", *((uint64_t*) f->value+ 8 ));
                                *size -= 8;
                            }                            
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_PBB_ISID   ){
                            fprintf(stream, "pbb_isid=\"%d\"",*((uint32_t*) f->value));
                            *size -= 8;
                            if (OXM_HASMASK(f->header)){
                                fprintf(stream, ", pbb_isid_mask=\"%d\"", *((uint32_t*) f->value +4));
                                *size -= 4;
                            }                            
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }
                else if (field == OFPXMT_OFB_TUNNEL_ID){
                            fprintf(stream, "tunnel_id=\"%lld\"", *((uint64_t*) f->value));
                            *size -= 12;
                            if (OXM_HASMASK(f->header)){
                                fprintf(stream, ", tunnel_id_mask=\"%lld\"", *((uint64_t*) f->value+ 8 ));
                                *size -= 8;
                            }                            
                            if (*size > 4)
                                fprintf(stream, ", ");                                                           
                }
                else if (field == OFPXMT_OFB_IPV6_EXTHDR){
                            fprintf(stream, "ext_hdr=\\");
                            ofl_ipv6_ext_hdr_print(stream, *((uint16_t*) f->value) );
                            *size -= 6;                                
                            if (OXM_HASMASK(f->header)){
                                *size -= 2;
                                fprintf(stream, ", ext_hdr_mask=\"0x%x\"",*((uint16_t*) f->value + 4));
                            }           
                            if (*size > 4)                                
                                fprintf(stream, ", ");
                }                 
                                
}